@deckai/deck-ui 0.0.28 → 0.0.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Carousel.cjs +1 -1
- package/dist/components/Carousel.cjs.map +1 -1
- package/dist/components/Carousel.d.cts +9 -0
- package/dist/components/Carousel.d.ts +9 -0
- package/dist/components/Carousel.js +1 -1
- package/dist/components/Carousel.js.map +1 -1
- package/dist/components/ReviewCard.cjs +6 -6
- package/dist/components/ReviewCard.cjs.map +1 -1
- package/dist/components/ReviewCard.js +6 -6
- package/dist/components/ReviewCard.js.map +1 -1
- package/dist/index.cjs +7 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +7 -7
- package/dist/index.js.map +1 -1
- package/dist/styles/styles.css +1 -1
- package/package.json +1 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
'use strict';var
|
|
1
|
+
'use strict';var T=require('@radix-ui/react-scroll-area'),p=require('react'),icons=require('@deckai/icons'),clsx=require('clsx'),tailwindMerge=require('tailwind-merge');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var T__namespace=/*#__PURE__*/_interopNamespace(T);var p__default=/*#__PURE__*/_interopDefault(p);var X=t=>{let[a,r]=p.useState(false);return p.useEffect(()=>{r(window.matchMedia(t).matches);let o=window.matchMedia(t),i=c=>{r(c.matches);};return o.addEventListener("change",i),()=>{o.removeEventListener("change",i);}},[t]),a};function k(...t){return tailwindMerge.twMerge(clsx.clsx(t))}var N={12:"h-[12px] w-[12px]",16:"h-[16px] w-[16px]",18:"h-[18px] w-[18px]",20:"h-[20px] w-[20px]",24:"h-[24px] w-[24px]",32:"h-[32px] w-[32px]",36:"h-[36px] w-[36px]",40:"h-[40px] w-[40px]",42:"h-[42px] w-[42px]",48:"h-[48px] w-[48px]",52:"h-[52px] w-[52px]",60:"h-[60px] w-[60px]",64:"h-[64px] w-[64px]",72:"h-[72px] w-[72px]",80:"h-[80px] w-[80px]"},D={sm:{12:"sm:h-[12px] sm:w-[12px]",16:"sm:h-[16px] sm:w-[16px]",18:"sm:h-[18px] sm:w-[18px]",20:"sm:h-[20px] sm:w-[20px]",24:"sm:h-[24px] sm:w-[24px]",32:"sm:h-[32px] sm:w-[32px]",36:"sm:h-[36px] sm:w-[36px]",40:"sm:h-[40px] sm:w-[40px]",42:"sm:h-[42px] sm:w-[42px]",48:"sm:h-[48px] sm:w-[48px]",52:"sm:h-[52px] sm:w-[52px]",60:"sm:h-[60px] sm:w-[60px]",64:"sm:h-[64px] sm:w-[64px]",72:"sm:h-[72px] sm:w-[72px]",80:"sm:h-[80px] sm:w-[80px]"},md:{12:"md:h-[12px] md:w-[12px]",16:"md:h-[16px] md:w-[16px]",18:"md:h-[18px] md:w-[18px]",20:"md:h-[20px] md:w-[20px]",24:"md:h-[24px] md:w-[24px]",32:"md:h-[32px] md:w-[32px]",36:"md:h-[36px] md:w-[36px]",40:"md:h-[40px] md:w-[40px]",42:"md:h-[42px] md:w-[42px]",48:"md:h-[48px] md:w-[48px]",52:"md:h-[52px] md:w-[52px]",60:"md:h-[60px] md:w-[60px]",64:"md:h-[64px] md:w-[64px]",72:"md:h-[72px] md:w-[72px]",80:"md:h-[80px] md:w-[80px]"},lg:{12:"lg:h-[12px] lg:w-[12px]",16:"lg:h-[16px] lg:w-[16px]",18:"lg:h-[18px] lg:w-[18px]",20:"lg:h-[20px] lg:w-[20px]",24:"lg:h-[24px] lg:w-[24px]",32:"lg:h-[32px] lg:w-[32px]",36:"lg:h-[36px] lg:w-[36px]",40:"lg:h-[40px] lg:w-[40px]",42:"lg:h-[42px] lg:w-[42px]",48:"lg:h-[48px] lg:w-[48px]",52:"lg:h-[52px] lg:w-[52px]",60:"lg:h-[60px] lg:w-[60px]",64:"lg:h-[64px] lg:w-[64px]",72:"lg:h-[72px] lg:w-[72px]",80:"lg:h-[80px] lg:w-[80px]"},xl:{12:"xl:h-[12px] xl:w-[12px]",16:"xl:h-[16px] xl:w-[16px]",18:"xl:h-[18px] xl:w-[18px]",20:"xl:h-[20px] xl:w-[20px]",24:"xl:h-[24px] xl:w-[24px]",32:"xl:h-[32px] xl:w-[32px]",36:"xl:h-[36px] xl:w-[36px]",40:"xl:h-[40px] xl:w-[40px]",42:"xl:h-[42px] xl:w-[42px]",48:"xl:h-[48px] xl:w-[48px]",52:"xl:h-[52px] xl:w-[52px]",60:"xl:h-[60px] xl:w-[60px]",64:"xl:h-[64px] xl:w-[64px]",72:"xl:h-[72px] xl:w-[72px]",80:"xl:h-[80px] xl:w-[80px]"},"2xl":{12:"2xl:h-[12px] 2xl:w-[12px]",16:"2xl:h-[16px] 2xl:w-[16px]",18:"2xl:h-[18px] 2xl:w-[18px]",20:"2xl:h-[20px] 2xl:w-[20px]",24:"2xl:h-[24px] 2xl:w-[24px]",32:"2xl:h-[32px] 2xl:w-[32px]",36:"2xl:h-[36px] 2xl:w-[36px]",40:"2xl:h-[40px] 2xl:w-[40px]",42:"2xl:h-[42px] 2xl:w-[42px]",48:"2xl:h-[48px] 2xl:w-[48px]",52:"2xl:h-[52px] 2xl:w-[52px]",60:"2xl:h-[60px] 2xl:w-[60px]",64:"2xl:h-[64px] 2xl:w-[64px]",72:"2xl:h-[72px] 2xl:w-[72px]",80:"2xl:h-[80px] 2xl:w-[80px]"}},E=t=>String(t),G=(t,a=24)=>{let r=[],l={};if(t===void 0){let o=E(a);o?r.push(N[o]):(l.height=`${a}px`,l.width=`${a}px`);}if(typeof t=="number"){let o=E(t);o?r.push(N[o]):(l.height=`${t}px`,l.width=`${t}px`);}if(Array.isArray(t)){let o=E(a),i=[o&&N[o]||`h-[${a}px] w-[${a}px]`];t.forEach(c=>{if(typeof c=="string"){let[n,g]=c.split(":"),y=parseInt(g,10),d=E(y);r.push(d&&D[n]?.[d]||`${n}:h-[${y}px] ${n}:w-[${y}px]`);}}),r.push(...i);}if(typeof t=="string"){let[o,i]=t.split(":"),c=parseInt(i,10),n=E(c);r.push(n&&D[o]?.[n]||`${o}:h-[${c}px] ${o}:w-[${c}px]`);}return {responsiveSizeClasses:r.join(" "),responsiveSizeStyles:l}};var Q={primary:"var(--color-primary)",secondary:"var(--color-secondary)",white:"var(--color-white)",primaryBlue:"var(--color-primary-100)",disabled:"var(--color-disabled)",danger:"var(--color-danger)",tertiary:"var(--color-tertiary-15)"},L=p__default.default.forwardRef(({name:t,size:a=24,color:r="primary",title:l,className:o,style:i={},...c},n)=>{let g=icons.IconMap[t],{responsiveSizeClasses:y,responsiveSizeStyles:d}=G(a,24);return p__default.default.createElement("div",{className:k("flex justify-center items-center",y,o),style:{"--icon-stroke":Q[r],...d,...i}},p__default.default.createElement(g,{ref:n,"aria-hidden":!l,"aria-label":l,stroke:t.includes("filled")?void 0:Q[r],...c}))});L.displayName="Icon";var _="focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-100";var P=p__default.default.forwardRef(({children:t,type:a="button",className:r,disabled:l,scaleOnPress:o=true,...i},c)=>p__default.default.createElement("button",{ref:c,type:a,disabled:l,className:k("appearance-none hover:opacity-90",_,l&&"opacity-50 cursor-not-allowed",o&&"transition-all active:scale-95",r),...i},t));P.displayName="Pressable";var Oe=p.forwardRef(({children:t,className:a="",gap:r=20,minHeight:l,showPaddles:o=true,onScrollStateChange:i},c)=>{let n=p.useRef(null),[g,y]=p.useState(false),[d,F]=p.useState(false),[M,z]=p.useState(false),[C,K]=p.useState(false),[S,V]=p.useState(null),[I,A]=p.useState(null),x=X("(max-width: 768px)"),H=p.useRef({canScrollLeft:false,canScrollRight:false}),$=p.useCallback(()=>{let e=n.current;if(!e)return;let{scrollLeft:s,scrollWidth:h,clientWidth:m}=e,f=s>0,w=Math.ceil(s+m)<h;(H.current.canScrollLeft!==f||H.current.canScrollRight!==w)&&(y(f),F(w),H.current={canScrollLeft:f,canScrollRight:w},i&&i({canScrollLeft:f,canScrollRight:w}));},[i]),J=p.useCallback(e=>{if(x)return;let h=e.currentTarget.getBoundingClientRect(),m=e.clientX-h.left,f=300,w=m<f,j=m>h.width-f;w!==M&&z(w),j!==C&&K(j);},[x,M,C]),U=p.useCallback(()=>{z(false),K(false);},[]),q=p.useCallback(e=>{V(e.touches[0].clientX),A(null);},[]),ee=p.useCallback(e=>{A(e.touches[0].clientX),!x&&S!==null&&Math.abs(S-e.touches[0].clientX)>10&&e.preventDefault();},[x,S]),te=p.useCallback(()=>{if(!S||!I)return;let e=n.current;if(!e)return;let s=S-I,h=x?30:50;if(Math.abs(s)<h)return;let m=x?e.clientWidth*.8:e.clientWidth,f=s>0?1:-1,w=e.scrollLeft+m*f;e.scrollTo({left:w,behavior:"smooth"});},[S,I,x]),oe=p.useCallback(()=>{V(null),A(null);},[]),O=p.useCallback(e=>{let s=n.current;if(!s)return;let h=Math.abs(e.deltaX)>Math.abs(e.deltaY);if(!h&&!e.shiftKey)return;e.preventDefault();let m=h?e.deltaX:e.deltaY;s.scrollBy({left:m,behavior:"smooth"});},[]);p.useEffect(()=>{let e=n.current;if(!e)return;let s=new ResizeObserver($);return s.observe(e),e.addEventListener("scroll",$,{passive:true}),e.addEventListener("wheel",O,{passive:false}),$(),()=>{s.disconnect(),e.removeEventListener("scroll",$),e.removeEventListener("wheel",O);}},[$,O]);let v=p.useCallback(e=>{let s=n.current;if(!s)return;let h=x?s.clientWidth*.8:s.clientWidth,m=s.scrollLeft+(e==="left"?-h:h);s.scrollTo({left:m,behavior:"smooth"});},[x]),se=p.useCallback(e=>{e.key==="ArrowLeft"?v("left"):e.key==="ArrowRight"&&v("right");},[v]),W=p.useMemo(()=>({canScrollLeft:g,canScrollRight:d}),[g,d]);p__default.default.useImperativeHandle(c,()=>({scroll:v,getScrollState:()=>W}),[v,W]);let re=p.useMemo(()=>({scrollbarWidth:"none",msOverflowStyle:"none",WebkitOverflowScrolling:"touch",touchAction:"pan-x",overflowX:"auto",minHeight:l,WebkitTapHighlightColor:"transparent",cursor:x?"default":"grab"}),[x,l]),le=p.useMemo(()=>({gap:`${r}px`}),[r]),ne=p.useMemo(()=>p__default.default.Children.map(t,e=>e===null?null:p__default.default.createElement("div",{className:"snap-start shrink-0"},e)),[t]),pe=p.useMemo(()=>x||!o?null:p__default.default.createElement(p__default.default.Fragment,null,g&&M&&p__default.default.createElement(P,{onClick:()=>v("left"),className:"absolute left-4 top-1/2 -translate-y-1/2 z-20 transition-opacity duration-200","aria-label":"Scroll left"},p__default.default.createElement("div",{className:"flex items-center justify-center w-10 h-10 rounded-full bg-overlay backdrop-blur-sm"},p__default.default.createElement(L,{name:"arrow-left",size:24,color:"white"}))),d&&C&&p__default.default.createElement(P,{onClick:()=>v("right"),className:"absolute right-4 top-1/2 -translate-y-1/2 z-20 transition-opacity duration-200","aria-label":"Scroll right"},p__default.default.createElement("div",{className:"flex items-center justify-center w-10 h-10 rounded-full bg-overlay backdrop-blur-sm"},p__default.default.createElement(L,{name:"arrow-right",size:24,color:"white"})))),[x,o,g,d,M,C,v]);return p__default.default.createElement("div",{className:`relative group w-full max-w-full overflow-hidden ${a}`,onKeyDown:se,onMouseMove:J,onMouseLeave:U,role:"region","aria-label":"Carousel"},p__default.default.createElement(T__namespace.Root,{className:"overflow-hidden w-full max-w-full",type:"hover"},p__default.default.createElement(T__namespace.Viewport,{ref:n,className:"w-full max-w-full overflow-x-auto snap-x snap-mandatory",style:re,onTouchStart:q,onTouchMove:ee,onTouchEnd:te,onTouchCancel:oe,"data-testid":"carousel-viewport"},p__default.default.createElement("div",{className:"inline-flex w-max",style:le},ne))),pe)});exports.Carousel=Oe;//# sourceMappingURL=Carousel.cjs.map
|
|
2
2
|
//# sourceMappingURL=Carousel.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/hooks/useMediaQuery.ts","../../src/components/Icon.tsx","../../src/utils/index.ts","../../src/utils/responsive.ts","../../src/utils/tailwind.ts","../../src/components/Pressable.tsx","../../src/components/Carousel.tsx"],"names":["useMediaQuery","query","matches","setMatches","useState","useEffect","mediaQueryList","handleChange","event","cn","inputs","twMerge","clsx","BASE_SIZES","RESPONSIVE_SIZES","getSizeKey","size","getResponsiveSize","baseSize","classes","styles","key","baseKey","responsiveClasses","breakpoint","valueStr","value","valueKey","COLOR_MAP","Icon","React","name","color","title","className","style","props","ref","IconComponent","IconMap","responsiveSizeClasses","responsiveSizeStyles","focusRingStyles","Pressable","children","type","disabled","scaleOnPress","Carousel","forwardRef","gap","minHeight","showPaddles","scrollContainerRef","useRef","showLeftPaddle","setShowLeftPaddle","showRightPaddle","setShowRightPaddle","isHoveringStart","setIsHoveringStart","isHoveringEnd","setIsHoveringEnd","touchStart","setTouchStart","touchEnd","setTouchEnd","isMobile","checkScrollPosition","useCallback","container","scrollLeft","scrollWidth","clientWidth","handleMouseMove","rect","mouseX","HOVER_THRESHOLD","handleTouchStart","handleTouchMove","handleTouchEnd","distance","itemWidth","direction","targetScroll","handleWheel","isHorizontalScroll","scrollAmount","observer","scroll","handleKeyDown","M","child"],"mappings":"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","file":"Carousel.cjs","sourcesContent":["import { useEffect, useState } from \"react\";\n\n/**\n * Custom hook that reliably checks if a media query matches in both client and server environments\n * Returns false during SSR and the actual match value after hydration\n */\nexport const useMediaQuery = (query: string): boolean => {\n // Initialize state but avoid hydration mismatch by not setting initial value from client-only API\n const [matches, setMatches] = useState<boolean>(false);\n\n // This runs only on the client after hydration\n useEffect(() => {\n // Create the matcher function\n const getMatches = (): boolean => window.matchMedia(query).matches;\n\n // Set the initial value after component mounts\n setMatches(getMatches());\n\n // Create the media query list\n const mediaQueryList = window.matchMedia(query);\n\n // Define event handler\n const handleChange = (event: MediaQueryListEvent) => {\n setMatches(event.matches);\n };\n\n // Add event listener using the appropriate method\n // Modern browsers\n mediaQueryList.addEventListener(\"change\", handleChange);\n\n // Cleanup function\n return () => {\n mediaQueryList.removeEventListener(\"change\", handleChange);\n };\n }, [query]); // Only re-run if query changes\n\n return matches;\n};\n","import type { IconName } from \"@deckai/icons\";\nimport { IconMap } from \"@deckai/icons\";\nimport type { SVGProps } from \"react\";\nimport React from \"react\";\n\nimport type { IconColors } from \"../types/tailwind\";\nimport { cn } from \"../utils\";\nimport type { ResponsiveSize } from \"../utils/responsive\";\nimport { getResponsiveSize } from \"../utils/responsive\";\n\nexport type IconProps = {\n name: IconName;\n /** @default 24 */\n size?: ResponsiveSize | ResponsiveSize[];\n /** @default primary */\n color?: IconColors;\n title?: string;\n className?: string;\n style?: React.CSSProperties;\n} & Omit<SVGProps<SVGSVGElement>, \"aria-hidden\" | \"aria-label\">;\n\n// Using CSS variables to support dark mode\nconst COLOR_MAP: Record<IconColors, string> = {\n primary: \"var(--color-primary)\",\n secondary: \"var(--color-secondary)\",\n white: \"var(--color-white)\",\n primaryBlue: \"var(--color-primary-100)\",\n disabled: \"var(--color-disabled)\",\n danger: \"var(--color-danger)\",\n tertiary: \"var(--color-tertiary-15)\"\n};\n\nexport const Icon = React.forwardRef<SVGSVGElement, IconProps>(\n (\n {\n name,\n size = 24,\n color = \"primary\",\n title,\n className,\n style = {},\n ...props\n },\n ref\n ) => {\n const IconComponent = IconMap[name];\n const { responsiveSizeClasses, responsiveSizeStyles } = getResponsiveSize(\n size,\n 24\n );\n\n return (\n <div\n className={cn(\n \"flex justify-center items-center\",\n responsiveSizeClasses,\n className\n )}\n style={{\n [\"--icon-stroke\" as string]: COLOR_MAP[color],\n ...responsiveSizeStyles,\n ...style\n }}\n >\n <IconComponent\n ref={ref}\n aria-hidden={!title}\n aria-label={title}\n stroke={name.includes(\"filled\") ? undefined : COLOR_MAP[color]}\n {...props}\n />\n </div>\n );\n }\n);\n\nIcon.displayName = \"Icon\";\n","import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n\nexport const noopFn = () => {};\n","export type Breakpoint = \"sm\" | \"md\" | \"lg\" | \"xl\" | \"2xl\";\nexport type ResponsiveSize = number | `${Breakpoint}:${number}`;\n\ntype SizeKey =\n | \"12\"\n | \"16\"\n | \"18\"\n | \"20\"\n | \"24\"\n | \"32\"\n | \"36\"\n | \"40\"\n | \"42\"\n | \"48\"\n | \"52\"\n | \"60\"\n | \"64\"\n | \"72\"\n | \"80\";\n\n// These constants help Tailwind identify the classes during compilation\nconst BASE_SIZES: Record<SizeKey, string> = {\n \"12\": \"h-[12px] w-[12px]\",\n \"16\": \"h-[16px] w-[16px]\",\n \"18\": \"h-[18px] w-[18px]\",\n \"20\": \"h-[20px] w-[20px]\",\n \"24\": \"h-[24px] w-[24px]\",\n \"32\": \"h-[32px] w-[32px]\",\n \"36\": \"h-[36px] w-[36px]\",\n \"40\": \"h-[40px] w-[40px]\",\n \"42\": \"h-[42px] w-[42px]\",\n \"48\": \"h-[48px] w-[48px]\",\n \"52\": \"h-[52px] w-[52px]\",\n \"60\": \"h-[60px] w-[60px]\",\n \"64\": \"h-[64px] w-[64px]\",\n \"72\": \"h-[72px] w-[72px]\",\n \"80\": \"h-[80px] w-[80px]\"\n};\n\nconst RESPONSIVE_SIZES: Record<Breakpoint, Record<SizeKey, string>> = {\n sm: {\n \"12\": \"sm:h-[12px] sm:w-[12px]\",\n \"16\": \"sm:h-[16px] sm:w-[16px]\",\n \"18\": \"sm:h-[18px] sm:w-[18px]\",\n \"20\": \"sm:h-[20px] sm:w-[20px]\",\n \"24\": \"sm:h-[24px] sm:w-[24px]\",\n \"32\": \"sm:h-[32px] sm:w-[32px]\",\n \"36\": \"sm:h-[36px] sm:w-[36px]\",\n \"40\": \"sm:h-[40px] sm:w-[40px]\",\n \"42\": \"sm:h-[42px] sm:w-[42px]\",\n \"48\": \"sm:h-[48px] sm:w-[48px]\",\n \"52\": \"sm:h-[52px] sm:w-[52px]\",\n \"60\": \"sm:h-[60px] sm:w-[60px]\",\n \"64\": \"sm:h-[64px] sm:w-[64px]\",\n \"72\": \"sm:h-[72px] sm:w-[72px]\",\n \"80\": \"sm:h-[80px] sm:w-[80px]\"\n },\n md: {\n \"12\": \"md:h-[12px] md:w-[12px]\",\n \"16\": \"md:h-[16px] md:w-[16px]\",\n \"18\": \"md:h-[18px] md:w-[18px]\",\n \"20\": \"md:h-[20px] md:w-[20px]\",\n \"24\": \"md:h-[24px] md:w-[24px]\",\n \"32\": \"md:h-[32px] md:w-[32px]\",\n \"36\": \"md:h-[36px] md:w-[36px]\",\n \"40\": \"md:h-[40px] md:w-[40px]\",\n \"42\": \"md:h-[42px] md:w-[42px]\",\n \"48\": \"md:h-[48px] md:w-[48px]\",\n \"52\": \"md:h-[52px] md:w-[52px]\",\n \"60\": \"md:h-[60px] md:w-[60px]\",\n \"64\": \"md:h-[64px] md:w-[64px]\",\n \"72\": \"md:h-[72px] md:w-[72px]\",\n \"80\": \"md:h-[80px] md:w-[80px]\"\n },\n lg: {\n \"12\": \"lg:h-[12px] lg:w-[12px]\",\n \"16\": \"lg:h-[16px] lg:w-[16px]\",\n \"18\": \"lg:h-[18px] lg:w-[18px]\",\n \"20\": \"lg:h-[20px] lg:w-[20px]\",\n \"24\": \"lg:h-[24px] lg:w-[24px]\",\n \"32\": \"lg:h-[32px] lg:w-[32px]\",\n \"36\": \"lg:h-[36px] lg:w-[36px]\",\n \"40\": \"lg:h-[40px] lg:w-[40px]\",\n \"42\": \"lg:h-[42px] lg:w-[42px]\",\n \"48\": \"lg:h-[48px] lg:w-[48px]\",\n \"52\": \"lg:h-[52px] lg:w-[52px]\",\n \"60\": \"lg:h-[60px] lg:w-[60px]\",\n \"64\": \"lg:h-[64px] lg:w-[64px]\",\n \"72\": \"lg:h-[72px] lg:w-[72px]\",\n \"80\": \"lg:h-[80px] lg:w-[80px]\"\n },\n xl: {\n \"12\": \"xl:h-[12px] xl:w-[12px]\",\n \"16\": \"xl:h-[16px] xl:w-[16px]\",\n \"18\": \"xl:h-[18px] xl:w-[18px]\",\n \"20\": \"xl:h-[20px] xl:w-[20px]\",\n \"24\": \"xl:h-[24px] xl:w-[24px]\",\n \"32\": \"xl:h-[32px] xl:w-[32px]\",\n \"36\": \"xl:h-[36px] xl:w-[36px]\",\n \"40\": \"xl:h-[40px] xl:w-[40px]\",\n \"42\": \"xl:h-[42px] xl:w-[42px]\",\n \"48\": \"xl:h-[48px] xl:w-[48px]\",\n \"52\": \"xl:h-[52px] xl:w-[52px]\",\n \"60\": \"xl:h-[60px] xl:w-[60px]\",\n \"64\": \"xl:h-[64px] xl:w-[64px]\",\n \"72\": \"xl:h-[72px] xl:w-[72px]\",\n \"80\": \"xl:h-[80px] xl:w-[80px]\"\n },\n \"2xl\": {\n \"12\": \"2xl:h-[12px] 2xl:w-[12px]\",\n \"16\": \"2xl:h-[16px] 2xl:w-[16px]\",\n \"18\": \"2xl:h-[18px] 2xl:w-[18px]\",\n \"20\": \"2xl:h-[20px] 2xl:w-[20px]\",\n \"24\": \"2xl:h-[24px] 2xl:w-[24px]\",\n \"32\": \"2xl:h-[32px] 2xl:w-[32px]\",\n \"36\": \"2xl:h-[36px] 2xl:w-[36px]\",\n \"40\": \"2xl:h-[40px] 2xl:w-[40px]\",\n \"42\": \"2xl:h-[42px] 2xl:w-[42px]\",\n \"48\": \"2xl:h-[48px] 2xl:w-[48px]\",\n \"52\": \"2xl:h-[52px] 2xl:w-[52px]\",\n \"60\": \"2xl:h-[60px] 2xl:w-[60px]\",\n \"64\": \"2xl:h-[64px] 2xl:w-[64px]\",\n \"72\": \"2xl:h-[72px] 2xl:w-[72px]\",\n \"80\": \"2xl:h-[80px] 2xl:w-[80px]\"\n }\n};\n\nconst getSizeKey = (size: number): SizeKey | undefined => {\n return String(size) as SizeKey;\n};\n\nexport const getResponsiveSize = (\n size: ResponsiveSize | ResponsiveSize[] | undefined,\n baseSize: number = 24\n): {\n responsiveSizeClasses: string;\n responsiveSizeStyles: Record<string, string>;\n} => {\n const classes: string[] = [];\n const styles: Record<string, string> = {};\n\n // If no size provided, use baseSize\n if (size === undefined) {\n const key = getSizeKey(baseSize);\n if (key) {\n classes.push(BASE_SIZES[key]);\n } else {\n styles.height = `${baseSize}px`;\n styles.width = `${baseSize}px`;\n }\n }\n\n // If size is a number, use that directly\n if (typeof size === \"number\") {\n const key = getSizeKey(size);\n if (key) {\n classes.push(BASE_SIZES[key]);\n } else {\n styles.height = `${size}px`;\n styles.width = `${size}px`;\n }\n }\n\n // If array of responsive sizes, generate responsive classes\n if (Array.isArray(size)) {\n const baseKey = getSizeKey(baseSize);\n const responsiveClasses = [\n (baseKey && BASE_SIZES[baseKey]) || `h-[${baseSize}px] w-[${baseSize}px]`\n ];\n\n size.forEach((s) => {\n if (typeof s === \"string\") {\n const [breakpoint, valueStr] = s.split(\":\") as [Breakpoint, string];\n const value = parseInt(valueStr, 10);\n const key = getSizeKey(value);\n classes.push(\n (key && RESPONSIVE_SIZES[breakpoint]?.[key]) ||\n `${breakpoint}:h-[${value}px] ${breakpoint}:w-[${value}px]`\n );\n }\n });\n\n classes.push(...responsiveClasses);\n }\n\n if (typeof size === \"string\") {\n const [breakpoint, valueStr] = size.split(\":\") as [Breakpoint, string];\n const value = parseInt(valueStr, 10);\n const valueKey = getSizeKey(value);\n classes.push(\n (valueKey && RESPONSIVE_SIZES[breakpoint]?.[valueKey]) ||\n `${breakpoint}:h-[${value}px] ${breakpoint}:w-[${value}px]`\n );\n }\n\n return {\n responsiveSizeClasses: classes.join(\" \"),\n responsiveSizeStyles: styles\n };\n};\n","import type { Colors, Typography } from \"../types/tailwind\";\n\n// Generate safelist patterns for all color utilities so you can use any theme color variable in your code\nexport const generateSafelist = (colors: Colors, typography: Typography) => {\n const colorNames = Object.keys(colors) as (keyof Colors)[];\n const utilities = [\"bg\", \"text\", \"border\", \"ring\", \"divide\", \"outline\"];\n const variants = [\"hover:\", \"focus:\", \"active:\", \"disabled:\"];\n const breakpoints = [\"sm\", \"md\", \"lg\", \"xl\", \"2xl\"];\n const sizes = [\"24\", \"42\", \"48\", \"64\", \"72\"]; // Add all the sizes you need\n\n const safelist: (string | { pattern: RegExp; variants: string[] })[] = [];\n\n colorNames.forEach((colorName) => {\n if (typeof colors[colorName] === \"object\") {\n // Handle nested color objects (with number keys)\n Object.keys(colors[colorName]).forEach((shade) => {\n utilities.forEach((utility) => {\n // Base utility\n safelist.push(`${utility}-${colorName}-${shade}`);\n\n // Variant utilities\n variants.forEach((variant) => {\n safelist.push(`${variant}${utility}-${colorName}-${shade}`);\n });\n });\n });\n } else {\n // Handle direct color values\n utilities.forEach((utility) => {\n safelist.push(`${utility}-${colorName}`);\n\n variants.forEach((variant) => {\n safelist.push(`${variant}${utility}-${colorName}`);\n });\n });\n }\n });\n\n // Generate typography classes\n Object.entries(typography).forEach(([family, sizes]) => {\n Object.keys(sizes).forEach((size) => {\n // Base typography classes\n safelist.push(`text-${family}-${size}`);\n\n // Add variants\n variants.forEach((variant) => {\n safelist.push(`${variant}text-${family}-${size}`);\n });\n });\n });\n\n const typographyClasses = Object.entries(typography).flatMap(\n ([category, sizes]) =>\n Object.keys(sizes).map((size) => `text-${category}-${size}`)\n );\n\n // Generate responsive variants\n const responsiveTypographyClasses = typographyClasses.flatMap((className) =>\n breakpoints.map((breakpoint) => `${breakpoint}:${className}`)\n );\n\n // Generate size classes with responsive variants\n const sizeClasses = sizes.flatMap((size) => [\n `h-[${size}px]`,\n `w-[${size}px]`,\n ...breakpoints.flatMap((bp) => [\n `${bp}:h-[${size}px]`,\n `${bp}:w-[${size}px]`\n ])\n ]);\n\n return [...typographyClasses, ...responsiveTypographyClasses, ...sizeClasses];\n};\n\nexport const focusRingStyles =\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-100\";\nexport const focusRingWithinStyles =\n \"focus-within:outline-none focus-within:ring-2 focus-within:ring-primary-100\";\nexport const focusRingStylesCoerced = \"ring-2 ring-primary-100\";\n","import type { ButtonHTMLAttributes } from \"react\";\nimport React from \"react\";\n\nimport { cn } from \"../utils\";\nimport { focusRingStyles } from \"../utils/tailwind\";\n\nexport type PressableProps = ButtonHTMLAttributes<HTMLButtonElement> & {\n /**\n * @default true\n * Scaling motion when pressed\n */\n scaleOnPress?: boolean;\n};\n\nexport const Pressable = React.forwardRef<HTMLButtonElement, PressableProps>(\n (\n {\n children,\n type = \"button\",\n className,\n disabled,\n scaleOnPress = true,\n ...props\n },\n ref\n ) => (\n <button\n ref={ref}\n type={type}\n disabled={disabled}\n className={cn(\n \"appearance-none hover:opacity-90\",\n focusRingStyles,\n disabled && \"opacity-50 cursor-not-allowed\",\n scaleOnPress && \"transition-all active:scale-95\",\n className\n )}\n {...props}\n >\n {children}\n </button>\n )\n);\n\nPressable.displayName = \"Pressable\";\n","import * as ScrollArea from \"@radix-ui/react-scroll-area\";\nimport React, {\n forwardRef,\n useCallback,\n useEffect,\n useRef,\n useState\n} from \"react\";\n\nimport { useMediaQuery } from \"../hooks/useMediaQuery\";\nimport { Icon } from \"./Icon\";\nimport { Pressable } from \"./Pressable\";\n\nexport type CarouselRef = {\n scroll: (direction: \"left\" | \"right\") => void;\n};\n\nexport type CarouselProps = {\n children: React.ReactNode;\n /** Optional className for the root element */\n className?: string;\n /** Optional gap between items in pixels */\n gap?: number;\n /** Optional minimum height for the carousel */\n minHeight?: string;\n /**\n * Optional boolean to show/hide paddles\n * @default true\n */\n showPaddles?: boolean;\n};\n\nexport const Carousel = forwardRef<CarouselRef, CarouselProps>(\n (\n { children, className = \"\", gap = 20, minHeight, showPaddles = true },\n ref\n ) => {\n const scrollContainerRef = useRef<HTMLDivElement>(null);\n const [showLeftPaddle, setShowLeftPaddle] = useState(false);\n const [showRightPaddle, setShowRightPaddle] = useState(false);\n const [isHoveringStart, setIsHoveringStart] = useState(false);\n const [isHoveringEnd, setIsHoveringEnd] = useState(false);\n const [touchStart, setTouchStart] = useState<number | null>(null);\n const [touchEnd, setTouchEnd] = useState<number | null>(null);\n const isMobile = useMediaQuery(\"(max-width: 768px)\");\n\n const checkScrollPosition = useCallback(() => {\n const container = scrollContainerRef.current;\n if (!container) return;\n\n const { scrollLeft, scrollWidth, clientWidth } = container;\n setShowLeftPaddle(scrollLeft > 0);\n setShowRightPaddle(Math.ceil(scrollLeft + clientWidth) < scrollWidth);\n }, []);\n\n const handleMouseMove = useCallback(\n (e: React.MouseEvent) => {\n if (isMobile) return;\n\n const container = e.currentTarget;\n const rect = container.getBoundingClientRect();\n const mouseX = e.clientX - rect.left;\n const HOVER_THRESHOLD = 300;\n\n setIsHoveringStart(mouseX < HOVER_THRESHOLD);\n setIsHoveringEnd(mouseX > rect.width - HOVER_THRESHOLD);\n },\n [isMobile]\n );\n\n // Touch handling\n const handleTouchStart = useCallback((e: React.TouchEvent) => {\n setTouchStart(e.touches[0].clientX);\n setTouchEnd(null);\n }, []);\n\n const handleTouchMove = useCallback((e: React.TouchEvent) => {\n setTouchEnd(e.touches[0].clientX);\n }, []);\n\n const handleTouchEnd = useCallback(() => {\n if (!touchStart || !touchEnd) return;\n\n const container = scrollContainerRef.current;\n if (!container) return;\n\n const distance = touchStart - touchEnd;\n const minSwipeDistance = 50;\n\n if (Math.abs(distance) < minSwipeDistance) {\n return;\n }\n\n const itemWidth = container.clientWidth;\n const direction = distance > 0 ? 1 : -1;\n const targetScroll = container.scrollLeft + itemWidth * direction;\n\n container.scrollTo({\n left: targetScroll,\n behavior: \"smooth\"\n });\n }, [touchStart, touchEnd]);\n\n const handleWheel = useCallback((e: WheelEvent) => {\n const container = scrollContainerRef.current;\n if (!container) return;\n\n // Check if the scroll is predominantly horizontal or if shift key is pressed\n const isHorizontalScroll = Math.abs(e.deltaX) > Math.abs(e.deltaY);\n if (!isHorizontalScroll && !e.shiftKey) return;\n\n e.preventDefault();\n\n // Determine the scroll amount based on the input type\n const scrollAmount = isHorizontalScroll ? e.deltaX : e.deltaY;\n\n // Apply smooth scrolling\n container.scrollBy({\n left: scrollAmount,\n behavior: \"smooth\"\n });\n }, []);\n\n useEffect(() => {\n const container = scrollContainerRef.current;\n if (!container) return;\n\n const observer = new ResizeObserver(checkScrollPosition);\n observer.observe(container);\n\n container.addEventListener(\"scroll\", checkScrollPosition);\n container.addEventListener(\"wheel\", handleWheel, { passive: false });\n\n return () => {\n observer.disconnect();\n container.removeEventListener(\"scroll\", checkScrollPosition);\n container.removeEventListener(\"wheel\", handleWheel);\n };\n }, [checkScrollPosition, handleWheel]);\n\n const scroll = useCallback((direction: \"left\" | \"right\") => {\n const container = scrollContainerRef.current;\n if (!container) return;\n\n const scrollAmount = container.clientWidth;\n const targetScroll =\n container.scrollLeft +\n (direction === \"left\" ? -scrollAmount : scrollAmount);\n\n container.scrollTo({\n left: targetScroll,\n behavior: \"smooth\"\n });\n }, []);\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === \"ArrowLeft\") {\n scroll(\"left\");\n } else if (e.key === \"ArrowRight\") {\n scroll(\"right\");\n }\n },\n [scroll]\n );\n\n // Expose scroll method via ref\n React.useImperativeHandle(\n ref,\n () => ({\n scroll\n }),\n [scroll]\n );\n\n return (\n <div\n className={`relative group w-full max-w-full overflow-x-hidden ${className}`}\n onKeyDown={handleKeyDown}\n onMouseMove={handleMouseMove}\n onMouseLeave={() => {\n setIsHoveringStart(false);\n setIsHoveringEnd(false);\n }}\n onTouchStart={handleTouchStart}\n onTouchMove={handleTouchMove}\n onTouchEnd={handleTouchEnd}\n role=\"region\"\n aria-label=\"Carousel\"\n >\n <ScrollArea.Root\n className=\"overflow-x-hidden w-full max-w-full\"\n type=\"hover\"\n >\n <ScrollArea.Viewport\n ref={scrollContainerRef}\n className=\"w-full max-w-full overflow-x-auto snap-x snap-mandatory\"\n style={{\n scrollbarWidth: \"none\",\n msOverflowStyle: \"none\",\n WebkitOverflowScrolling: \"touch\",\n minHeight\n }}\n >\n <div\n className=\"inline-flex w-max\"\n style={{\n gap: `${gap}px`\n }}\n >\n {React.Children.map(children, (child) =>\n child === null ? null : (\n <div className=\"snap-start shrink-0\">{child}</div>\n )\n )}\n </div>\n </ScrollArea.Viewport>\n </ScrollArea.Root>\n\n {/* Navigation Paddles - Only show on desktop */}\n {!isMobile && (\n <>\n {showLeftPaddle && showPaddles && isHoveringStart && (\n <Pressable\n onClick={() => scroll(\"left\")}\n className=\"absolute left-4 top-1/2 -translate-y-1/2 z-20 transition-opacity duration-200\"\n aria-label=\"Scroll left\"\n >\n <div className=\"flex items-center justify-center w-10 h-10 rounded-full bg-overlay backdrop-blur-sm\">\n <Icon name=\"arrow-left\" size={24} color=\"white\" />\n </div>\n </Pressable>\n )}\n\n {showRightPaddle && showPaddles && isHoveringEnd && (\n <Pressable\n onClick={() => scroll(\"right\")}\n className=\"absolute right-4 top-1/2 -translate-y-1/2 z-20 transition-opacity duration-200\"\n aria-label=\"Scroll right\"\n >\n <div className=\"flex items-center justify-center w-10 h-10 rounded-full bg-overlay backdrop-blur-sm\">\n <Icon name=\"arrow-right\" size={24} color=\"white\" />\n </div>\n </Pressable>\n )}\n </>\n )}\n </div>\n );\n }\n);\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/hooks/useMediaQuery.ts","../../src/components/Icon.tsx","../../src/utils/index.ts","../../src/utils/responsive.ts","../../src/utils/tailwind.ts","../../src/components/Pressable.tsx","../../src/components/Carousel.tsx"],"names":["useMediaQuery","query","matches","setMatches","useState","useEffect","mediaQueryList","handleChange","event","cn","inputs","twMerge","clsx","BASE_SIZES","RESPONSIVE_SIZES","getSizeKey","size","getResponsiveSize","baseSize","classes","styles","key","baseKey","responsiveClasses","s","breakpoint","valueStr","value","valueKey","COLOR_MAP","Icon","React","name","color","title","className","style","props","ref","IconComponent","IconMap","responsiveSizeClasses","responsiveSizeStyles","focusRingStyles","Pressable","children","type","disabled","scaleOnPress","Carousel","forwardRef","gap","minHeight","showPaddles","onScrollStateChange","scrollContainerRef","useRef","showLeftPaddle","setShowLeftPaddle","showRightPaddle","setShowRightPaddle","isHoveringStart","setIsHoveringStart","isHoveringEnd","setIsHoveringEnd","touchStart","setTouchStart","touchEnd","setTouchEnd","isMobile","prevScrollStateRef","checkScrollPosition","useCallback","container","scrollLeft","scrollWidth","clientWidth","canScrollLeft","canScrollRight","handleMouseMove","rect","mouseX","HOVER_THRESHOLD","newIsHoveringStart","newIsHoveringEnd","handleMouseLeave","handleTouchStart","handleTouchMove","handleTouchEnd","distance","minSwipeDistance","scrollAmount","direction","targetScroll","handleTouchCancel","handleWheel","isHorizontalScroll","observer","scroll","handleKeyDown","scrollState","useMemo","viewportStyle","gapStyle","mappedChildren","child","desktopPaddles","T"],"mappings":"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","file":"Carousel.cjs","sourcesContent":["import { useEffect, useState } from \"react\";\n\n/**\n * Custom hook that reliably checks if a media query matches in both client and server environments\n * Returns false during SSR and the actual match value after hydration\n */\nexport const useMediaQuery = (query: string): boolean => {\n // Initialize state but avoid hydration mismatch by not setting initial value from client-only API\n const [matches, setMatches] = useState<boolean>(false);\n\n // This runs only on the client after hydration\n useEffect(() => {\n // Create the matcher function\n const getMatches = (): boolean => window.matchMedia(query).matches;\n\n // Set the initial value after component mounts\n setMatches(getMatches());\n\n // Create the media query list\n const mediaQueryList = window.matchMedia(query);\n\n // Define event handler\n const handleChange = (event: MediaQueryListEvent) => {\n setMatches(event.matches);\n };\n\n // Add event listener using the appropriate method\n // Modern browsers\n mediaQueryList.addEventListener(\"change\", handleChange);\n\n // Cleanup function\n return () => {\n mediaQueryList.removeEventListener(\"change\", handleChange);\n };\n }, [query]); // Only re-run if query changes\n\n return matches;\n};\n","import type { IconName } from \"@deckai/icons\";\nimport { IconMap } from \"@deckai/icons\";\nimport type { SVGProps } from \"react\";\nimport React from \"react\";\n\nimport type { IconColors } from \"../types/tailwind\";\nimport { cn } from \"../utils\";\nimport type { ResponsiveSize } from \"../utils/responsive\";\nimport { getResponsiveSize } from \"../utils/responsive\";\n\nexport type IconProps = {\n name: IconName;\n /** @default 24 */\n size?: ResponsiveSize | ResponsiveSize[];\n /** @default primary */\n color?: IconColors;\n title?: string;\n className?: string;\n style?: React.CSSProperties;\n} & Omit<SVGProps<SVGSVGElement>, \"aria-hidden\" | \"aria-label\">;\n\n// Using CSS variables to support dark mode\nconst COLOR_MAP: Record<IconColors, string> = {\n primary: \"var(--color-primary)\",\n secondary: \"var(--color-secondary)\",\n white: \"var(--color-white)\",\n primaryBlue: \"var(--color-primary-100)\",\n disabled: \"var(--color-disabled)\",\n danger: \"var(--color-danger)\",\n tertiary: \"var(--color-tertiary-15)\"\n};\n\nexport const Icon = React.forwardRef<SVGSVGElement, IconProps>(\n (\n {\n name,\n size = 24,\n color = \"primary\",\n title,\n className,\n style = {},\n ...props\n },\n ref\n ) => {\n const IconComponent = IconMap[name];\n const { responsiveSizeClasses, responsiveSizeStyles } = getResponsiveSize(\n size,\n 24\n );\n\n return (\n <div\n className={cn(\n \"flex justify-center items-center\",\n responsiveSizeClasses,\n className\n )}\n style={{\n [\"--icon-stroke\" as string]: COLOR_MAP[color],\n ...responsiveSizeStyles,\n ...style\n }}\n >\n <IconComponent\n ref={ref}\n aria-hidden={!title}\n aria-label={title}\n stroke={name.includes(\"filled\") ? undefined : COLOR_MAP[color]}\n {...props}\n />\n </div>\n );\n }\n);\n\nIcon.displayName = \"Icon\";\n","import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n\nexport const noopFn = () => {};\n","export type Breakpoint = \"sm\" | \"md\" | \"lg\" | \"xl\" | \"2xl\";\nexport type ResponsiveSize = number | `${Breakpoint}:${number}`;\n\ntype SizeKey =\n | \"12\"\n | \"16\"\n | \"18\"\n | \"20\"\n | \"24\"\n | \"32\"\n | \"36\"\n | \"40\"\n | \"42\"\n | \"48\"\n | \"52\"\n | \"60\"\n | \"64\"\n | \"72\"\n | \"80\";\n\n// These constants help Tailwind identify the classes during compilation\nconst BASE_SIZES: Record<SizeKey, string> = {\n \"12\": \"h-[12px] w-[12px]\",\n \"16\": \"h-[16px] w-[16px]\",\n \"18\": \"h-[18px] w-[18px]\",\n \"20\": \"h-[20px] w-[20px]\",\n \"24\": \"h-[24px] w-[24px]\",\n \"32\": \"h-[32px] w-[32px]\",\n \"36\": \"h-[36px] w-[36px]\",\n \"40\": \"h-[40px] w-[40px]\",\n \"42\": \"h-[42px] w-[42px]\",\n \"48\": \"h-[48px] w-[48px]\",\n \"52\": \"h-[52px] w-[52px]\",\n \"60\": \"h-[60px] w-[60px]\",\n \"64\": \"h-[64px] w-[64px]\",\n \"72\": \"h-[72px] w-[72px]\",\n \"80\": \"h-[80px] w-[80px]\"\n};\n\nconst RESPONSIVE_SIZES: Record<Breakpoint, Record<SizeKey, string>> = {\n sm: {\n \"12\": \"sm:h-[12px] sm:w-[12px]\",\n \"16\": \"sm:h-[16px] sm:w-[16px]\",\n \"18\": \"sm:h-[18px] sm:w-[18px]\",\n \"20\": \"sm:h-[20px] sm:w-[20px]\",\n \"24\": \"sm:h-[24px] sm:w-[24px]\",\n \"32\": \"sm:h-[32px] sm:w-[32px]\",\n \"36\": \"sm:h-[36px] sm:w-[36px]\",\n \"40\": \"sm:h-[40px] sm:w-[40px]\",\n \"42\": \"sm:h-[42px] sm:w-[42px]\",\n \"48\": \"sm:h-[48px] sm:w-[48px]\",\n \"52\": \"sm:h-[52px] sm:w-[52px]\",\n \"60\": \"sm:h-[60px] sm:w-[60px]\",\n \"64\": \"sm:h-[64px] sm:w-[64px]\",\n \"72\": \"sm:h-[72px] sm:w-[72px]\",\n \"80\": \"sm:h-[80px] sm:w-[80px]\"\n },\n md: {\n \"12\": \"md:h-[12px] md:w-[12px]\",\n \"16\": \"md:h-[16px] md:w-[16px]\",\n \"18\": \"md:h-[18px] md:w-[18px]\",\n \"20\": \"md:h-[20px] md:w-[20px]\",\n \"24\": \"md:h-[24px] md:w-[24px]\",\n \"32\": \"md:h-[32px] md:w-[32px]\",\n \"36\": \"md:h-[36px] md:w-[36px]\",\n \"40\": \"md:h-[40px] md:w-[40px]\",\n \"42\": \"md:h-[42px] md:w-[42px]\",\n \"48\": \"md:h-[48px] md:w-[48px]\",\n \"52\": \"md:h-[52px] md:w-[52px]\",\n \"60\": \"md:h-[60px] md:w-[60px]\",\n \"64\": \"md:h-[64px] md:w-[64px]\",\n \"72\": \"md:h-[72px] md:w-[72px]\",\n \"80\": \"md:h-[80px] md:w-[80px]\"\n },\n lg: {\n \"12\": \"lg:h-[12px] lg:w-[12px]\",\n \"16\": \"lg:h-[16px] lg:w-[16px]\",\n \"18\": \"lg:h-[18px] lg:w-[18px]\",\n \"20\": \"lg:h-[20px] lg:w-[20px]\",\n \"24\": \"lg:h-[24px] lg:w-[24px]\",\n \"32\": \"lg:h-[32px] lg:w-[32px]\",\n \"36\": \"lg:h-[36px] lg:w-[36px]\",\n \"40\": \"lg:h-[40px] lg:w-[40px]\",\n \"42\": \"lg:h-[42px] lg:w-[42px]\",\n \"48\": \"lg:h-[48px] lg:w-[48px]\",\n \"52\": \"lg:h-[52px] lg:w-[52px]\",\n \"60\": \"lg:h-[60px] lg:w-[60px]\",\n \"64\": \"lg:h-[64px] lg:w-[64px]\",\n \"72\": \"lg:h-[72px] lg:w-[72px]\",\n \"80\": \"lg:h-[80px] lg:w-[80px]\"\n },\n xl: {\n \"12\": \"xl:h-[12px] xl:w-[12px]\",\n \"16\": \"xl:h-[16px] xl:w-[16px]\",\n \"18\": \"xl:h-[18px] xl:w-[18px]\",\n \"20\": \"xl:h-[20px] xl:w-[20px]\",\n \"24\": \"xl:h-[24px] xl:w-[24px]\",\n \"32\": \"xl:h-[32px] xl:w-[32px]\",\n \"36\": \"xl:h-[36px] xl:w-[36px]\",\n \"40\": \"xl:h-[40px] xl:w-[40px]\",\n \"42\": \"xl:h-[42px] xl:w-[42px]\",\n \"48\": \"xl:h-[48px] xl:w-[48px]\",\n \"52\": \"xl:h-[52px] xl:w-[52px]\",\n \"60\": \"xl:h-[60px] xl:w-[60px]\",\n \"64\": \"xl:h-[64px] xl:w-[64px]\",\n \"72\": \"xl:h-[72px] xl:w-[72px]\",\n \"80\": \"xl:h-[80px] xl:w-[80px]\"\n },\n \"2xl\": {\n \"12\": \"2xl:h-[12px] 2xl:w-[12px]\",\n \"16\": \"2xl:h-[16px] 2xl:w-[16px]\",\n \"18\": \"2xl:h-[18px] 2xl:w-[18px]\",\n \"20\": \"2xl:h-[20px] 2xl:w-[20px]\",\n \"24\": \"2xl:h-[24px] 2xl:w-[24px]\",\n \"32\": \"2xl:h-[32px] 2xl:w-[32px]\",\n \"36\": \"2xl:h-[36px] 2xl:w-[36px]\",\n \"40\": \"2xl:h-[40px] 2xl:w-[40px]\",\n \"42\": \"2xl:h-[42px] 2xl:w-[42px]\",\n \"48\": \"2xl:h-[48px] 2xl:w-[48px]\",\n \"52\": \"2xl:h-[52px] 2xl:w-[52px]\",\n \"60\": \"2xl:h-[60px] 2xl:w-[60px]\",\n \"64\": \"2xl:h-[64px] 2xl:w-[64px]\",\n \"72\": \"2xl:h-[72px] 2xl:w-[72px]\",\n \"80\": \"2xl:h-[80px] 2xl:w-[80px]\"\n }\n};\n\nconst getSizeKey = (size: number): SizeKey | undefined => {\n return String(size) as SizeKey;\n};\n\nexport const getResponsiveSize = (\n size: ResponsiveSize | ResponsiveSize[] | undefined,\n baseSize: number = 24\n): {\n responsiveSizeClasses: string;\n responsiveSizeStyles: Record<string, string>;\n} => {\n const classes: string[] = [];\n const styles: Record<string, string> = {};\n\n // If no size provided, use baseSize\n if (size === undefined) {\n const key = getSizeKey(baseSize);\n if (key) {\n classes.push(BASE_SIZES[key]);\n } else {\n styles.height = `${baseSize}px`;\n styles.width = `${baseSize}px`;\n }\n }\n\n // If size is a number, use that directly\n if (typeof size === \"number\") {\n const key = getSizeKey(size);\n if (key) {\n classes.push(BASE_SIZES[key]);\n } else {\n styles.height = `${size}px`;\n styles.width = `${size}px`;\n }\n }\n\n // If array of responsive sizes, generate responsive classes\n if (Array.isArray(size)) {\n const baseKey = getSizeKey(baseSize);\n const responsiveClasses = [\n (baseKey && BASE_SIZES[baseKey]) || `h-[${baseSize}px] w-[${baseSize}px]`\n ];\n\n size.forEach((s) => {\n if (typeof s === \"string\") {\n const [breakpoint, valueStr] = s.split(\":\") as [Breakpoint, string];\n const value = parseInt(valueStr, 10);\n const key = getSizeKey(value);\n classes.push(\n (key && RESPONSIVE_SIZES[breakpoint]?.[key]) ||\n `${breakpoint}:h-[${value}px] ${breakpoint}:w-[${value}px]`\n );\n }\n });\n\n classes.push(...responsiveClasses);\n }\n\n if (typeof size === \"string\") {\n const [breakpoint, valueStr] = size.split(\":\") as [Breakpoint, string];\n const value = parseInt(valueStr, 10);\n const valueKey = getSizeKey(value);\n classes.push(\n (valueKey && RESPONSIVE_SIZES[breakpoint]?.[valueKey]) ||\n `${breakpoint}:h-[${value}px] ${breakpoint}:w-[${value}px]`\n );\n }\n\n return {\n responsiveSizeClasses: classes.join(\" \"),\n responsiveSizeStyles: styles\n };\n};\n","import type { Colors, Typography } from \"../types/tailwind\";\n\n// Generate safelist patterns for all color utilities so you can use any theme color variable in your code\nexport const generateSafelist = (colors: Colors, typography: Typography) => {\n const colorNames = Object.keys(colors) as (keyof Colors)[];\n const utilities = [\"bg\", \"text\", \"border\", \"ring\", \"divide\", \"outline\"];\n const variants = [\"hover:\", \"focus:\", \"active:\", \"disabled:\"];\n const breakpoints = [\"sm\", \"md\", \"lg\", \"xl\", \"2xl\"];\n const sizes = [\"24\", \"42\", \"48\", \"64\", \"72\"]; // Add all the sizes you need\n\n const safelist: (string | { pattern: RegExp; variants: string[] })[] = [];\n\n colorNames.forEach((colorName) => {\n if (typeof colors[colorName] === \"object\") {\n // Handle nested color objects (with number keys)\n Object.keys(colors[colorName]).forEach((shade) => {\n utilities.forEach((utility) => {\n // Base utility\n safelist.push(`${utility}-${colorName}-${shade}`);\n\n // Variant utilities\n variants.forEach((variant) => {\n safelist.push(`${variant}${utility}-${colorName}-${shade}`);\n });\n });\n });\n } else {\n // Handle direct color values\n utilities.forEach((utility) => {\n safelist.push(`${utility}-${colorName}`);\n\n variants.forEach((variant) => {\n safelist.push(`${variant}${utility}-${colorName}`);\n });\n });\n }\n });\n\n // Generate typography classes\n Object.entries(typography).forEach(([family, sizes]) => {\n Object.keys(sizes).forEach((size) => {\n // Base typography classes\n safelist.push(`text-${family}-${size}`);\n\n // Add variants\n variants.forEach((variant) => {\n safelist.push(`${variant}text-${family}-${size}`);\n });\n });\n });\n\n const typographyClasses = Object.entries(typography).flatMap(\n ([category, sizes]) =>\n Object.keys(sizes).map((size) => `text-${category}-${size}`)\n );\n\n // Generate responsive variants\n const responsiveTypographyClasses = typographyClasses.flatMap((className) =>\n breakpoints.map((breakpoint) => `${breakpoint}:${className}`)\n );\n\n // Generate size classes with responsive variants\n const sizeClasses = sizes.flatMap((size) => [\n `h-[${size}px]`,\n `w-[${size}px]`,\n ...breakpoints.flatMap((bp) => [\n `${bp}:h-[${size}px]`,\n `${bp}:w-[${size}px]`\n ])\n ]);\n\n return [...typographyClasses, ...responsiveTypographyClasses, ...sizeClasses];\n};\n\nexport const focusRingStyles =\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-100\";\nexport const focusRingWithinStyles =\n \"focus-within:outline-none focus-within:ring-2 focus-within:ring-primary-100\";\nexport const focusRingStylesCoerced = \"ring-2 ring-primary-100\";\n","import type { ButtonHTMLAttributes } from \"react\";\nimport React from \"react\";\n\nimport { cn } from \"../utils\";\nimport { focusRingStyles } from \"../utils/tailwind\";\n\nexport type PressableProps = ButtonHTMLAttributes<HTMLButtonElement> & {\n /**\n * @default true\n * Scaling motion when pressed\n */\n scaleOnPress?: boolean;\n};\n\nexport const Pressable = React.forwardRef<HTMLButtonElement, PressableProps>(\n (\n {\n children,\n type = \"button\",\n className,\n disabled,\n scaleOnPress = true,\n ...props\n },\n ref\n ) => (\n <button\n ref={ref}\n type={type}\n disabled={disabled}\n className={cn(\n \"appearance-none hover:opacity-90\",\n focusRingStyles,\n disabled && \"opacity-50 cursor-not-allowed\",\n scaleOnPress && \"transition-all active:scale-95\",\n className\n )}\n {...props}\n >\n {children}\n </button>\n )\n);\n\nPressable.displayName = \"Pressable\";\n","import * as ScrollArea from \"@radix-ui/react-scroll-area\";\nimport React, {\n forwardRef,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState\n} from \"react\";\n\nimport { useMediaQuery } from \"../hooks/useMediaQuery\";\nimport { Icon } from \"./Icon\";\nimport { Pressable } from \"./Pressable\";\n\nexport type CarouselRef = {\n scroll: (direction: \"left\" | \"right\") => void;\n getScrollState: () => { canScrollLeft: boolean; canScrollRight: boolean };\n};\n\nexport type CarouselProps = {\n children: React.ReactNode;\n /** Optional className for the root element */\n className?: string;\n /** Optional gap between items in pixels */\n gap?: number;\n /** Optional minimum height for the carousel */\n minHeight?: string;\n /**\n * Optional boolean to show/hide paddles\n * @default true\n */\n showPaddles?: boolean;\n /** Optional callback when scroll state changes */\n onScrollStateChange?: (state: {\n canScrollLeft: boolean;\n canScrollRight: boolean;\n }) => void;\n};\n\nexport const Carousel = forwardRef<CarouselRef, CarouselProps>(\n (\n {\n children,\n className = \"\",\n gap = 20,\n minHeight,\n showPaddles = true,\n onScrollStateChange\n },\n ref\n ) => {\n const scrollContainerRef = useRef<HTMLDivElement>(null);\n const [showLeftPaddle, setShowLeftPaddle] = useState(false);\n const [showRightPaddle, setShowRightPaddle] = useState(false);\n const [isHoveringStart, setIsHoveringStart] = useState(false);\n const [isHoveringEnd, setIsHoveringEnd] = useState(false);\n const [touchStart, setTouchStart] = useState<number | null>(null);\n const [touchEnd, setTouchEnd] = useState<number | null>(null);\n const isMobile = useMediaQuery(\"(max-width: 768px)\");\n\n // Use a ref to store the previous scroll state to avoid unnecessary state updates\n const prevScrollStateRef = useRef<{\n canScrollLeft: boolean;\n canScrollRight: boolean;\n }>({ canScrollLeft: false, canScrollRight: false });\n\n const checkScrollPosition = useCallback(() => {\n const container = scrollContainerRef.current;\n if (!container) return;\n\n const { scrollLeft, scrollWidth, clientWidth } = container;\n const canScrollLeft = scrollLeft > 0;\n const canScrollRight = Math.ceil(scrollLeft + clientWidth) < scrollWidth;\n\n // Only update state if the values have changed\n if (\n prevScrollStateRef.current.canScrollLeft !== canScrollLeft ||\n prevScrollStateRef.current.canScrollRight !== canScrollRight\n ) {\n setShowLeftPaddle(canScrollLeft);\n setShowRightPaddle(canScrollRight);\n prevScrollStateRef.current = { canScrollLeft, canScrollRight };\n\n // Notify parent component of scroll state changes\n if (onScrollStateChange) {\n onScrollStateChange({ canScrollLeft, canScrollRight });\n }\n }\n }, [onScrollStateChange]);\n\n const handleMouseMove = useCallback(\n (e: React.MouseEvent) => {\n if (isMobile) return;\n\n const container = e.currentTarget;\n const rect = container.getBoundingClientRect();\n const mouseX = e.clientX - rect.left;\n const HOVER_THRESHOLD = 300;\n\n const newIsHoveringStart = mouseX < HOVER_THRESHOLD;\n const newIsHoveringEnd = mouseX > rect.width - HOVER_THRESHOLD;\n\n // Only update state if values have changed\n if (newIsHoveringStart !== isHoveringStart) {\n setIsHoveringStart(newIsHoveringStart);\n }\n if (newIsHoveringEnd !== isHoveringEnd) {\n setIsHoveringEnd(newIsHoveringEnd);\n }\n },\n [isMobile, isHoveringStart, isHoveringEnd]\n );\n\n // Handler for mouse leave - memoized to avoid recreating on every render\n const handleMouseLeave = useCallback(() => {\n setIsHoveringStart(false);\n setIsHoveringEnd(false);\n }, []);\n\n // Touch handling - for non-native scrolling behavior (swipe to snap)\n const handleTouchStart = useCallback((e: React.TouchEvent) => {\n setTouchStart(e.touches[0].clientX);\n setTouchEnd(null);\n }, []);\n\n const handleTouchMove = useCallback(\n (e: React.TouchEvent) => {\n setTouchEnd(e.touches[0].clientX);\n\n // Let native scrolling work on mobile - never prevent default\n // We'll use our own scrolling logic only when not on mobile\n if (\n !isMobile &&\n touchStart !== null &&\n Math.abs(touchStart - e.touches[0].clientX) > 10\n ) {\n e.preventDefault();\n }\n },\n [isMobile, touchStart]\n );\n\n const handleTouchEnd = useCallback(() => {\n if (!touchStart || !touchEnd) return;\n\n const container = scrollContainerRef.current;\n if (!container) return;\n\n const distance = touchStart - touchEnd;\n\n // Only use custom scrolling if it's a significant swipe\n // This allows for small drag movements to use native scrolling\n const minSwipeDistance = isMobile ? 30 : 50; // Reduced threshold for mobile\n\n if (Math.abs(distance) < minSwipeDistance) {\n return;\n }\n\n // Use 80% of container width for mobile for more natural feeling scrolling\n const scrollAmount = isMobile\n ? container.clientWidth * 0.8\n : container.clientWidth;\n\n const direction = distance > 0 ? 1 : -1;\n const targetScroll = container.scrollLeft + scrollAmount * direction;\n\n container.scrollTo({\n left: targetScroll,\n behavior: \"smooth\"\n });\n }, [touchStart, touchEnd, isMobile]);\n\n const handleTouchCancel = useCallback(() => {\n // Reset touch state when touch is canceled\n setTouchStart(null);\n setTouchEnd(null);\n }, []);\n\n const handleWheel = useCallback((e: WheelEvent) => {\n const container = scrollContainerRef.current;\n if (!container) return;\n\n // Check if the scroll is predominantly horizontal or if shift key is pressed\n const isHorizontalScroll = Math.abs(e.deltaX) > Math.abs(e.deltaY);\n if (!isHorizontalScroll && !e.shiftKey) return;\n\n e.preventDefault();\n\n // Determine the scroll amount based on the input type\n const scrollAmount = isHorizontalScroll ? e.deltaX : e.deltaY;\n\n // Apply smooth scrolling\n container.scrollBy({\n left: scrollAmount,\n behavior: \"smooth\"\n });\n }, []);\n\n useEffect(() => {\n const container = scrollContainerRef.current;\n if (!container) return;\n\n const observer = new ResizeObserver(checkScrollPosition);\n observer.observe(container);\n\n // Use passive listener for scroll events\n container.addEventListener(\"scroll\", checkScrollPosition, {\n passive: true\n });\n\n // Non-passive for wheel since we need to prevent default in some cases\n container.addEventListener(\"wheel\", handleWheel, { passive: false });\n\n // Initial check\n checkScrollPosition();\n\n return () => {\n observer.disconnect();\n container.removeEventListener(\"scroll\", checkScrollPosition);\n container.removeEventListener(\"wheel\", handleWheel);\n };\n }, [checkScrollPosition, handleWheel]);\n\n const scroll = useCallback(\n (direction: \"left\" | \"right\") => {\n const container = scrollContainerRef.current;\n if (!container) return;\n\n // Use 80% of container width for mobile for more natural feeling scrolling\n const scrollAmount = isMobile\n ? container.clientWidth * 0.8\n : container.clientWidth;\n\n const targetScroll =\n container.scrollLeft +\n (direction === \"left\" ? -scrollAmount : scrollAmount);\n\n container.scrollTo({\n left: targetScroll,\n behavior: \"smooth\"\n });\n },\n [isMobile]\n );\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === \"ArrowLeft\") {\n scroll(\"left\");\n } else if (e.key === \"ArrowRight\") {\n scroll(\"right\");\n }\n },\n [scroll]\n );\n\n // Memoize the scroll state to avoid recreating this object on every render\n const scrollState = useMemo(\n () => ({\n canScrollLeft: showLeftPaddle,\n canScrollRight: showRightPaddle\n }),\n [showLeftPaddle, showRightPaddle]\n );\n\n // Memoize the ref implementation\n React.useImperativeHandle(\n ref,\n () => ({\n scroll,\n getScrollState: () => scrollState\n }),\n [scroll, scrollState]\n );\n\n // Memoize the viewport style object to prevent unnecessary re-renders\n const viewportStyle = useMemo(\n () => ({\n scrollbarWidth: \"none\" as const,\n msOverflowStyle: \"none\" as const,\n WebkitOverflowScrolling: \"touch\" as const,\n touchAction: \"pan-x\" as const, // Always enable horizontal panning\n overflowX: \"auto\" as const, // Ensure this is always set\n minHeight,\n WebkitTapHighlightColor: \"transparent\" as const, // Remove tap highlight on mobile\n // Add cursor style for desktop to indicate scrollability\n cursor: isMobile ? \"default\" : \"grab\"\n }),\n [isMobile, minHeight]\n );\n\n // Memoize the gap style to prevent unnecessary re-renders\n const gapStyle = useMemo(() => ({ gap: `${gap}px` }), [gap]);\n\n // Memoize the children mapping to prevent unnecessary re-computation\n const mappedChildren = useMemo(\n () =>\n React.Children.map(children, (child) =>\n child === null ? null : (\n <div className=\"snap-start shrink-0\">{child}</div>\n )\n ),\n [children]\n );\n\n // Memoize paddle components for desktop\n const desktopPaddles = useMemo(() => {\n if (isMobile || !showPaddles) return null;\n\n return (\n <>\n {showLeftPaddle && isHoveringStart && (\n <Pressable\n onClick={() => scroll(\"left\")}\n className=\"absolute left-4 top-1/2 -translate-y-1/2 z-20 transition-opacity duration-200\"\n aria-label=\"Scroll left\"\n >\n <div className=\"flex items-center justify-center w-10 h-10 rounded-full bg-overlay backdrop-blur-sm\">\n <Icon name=\"arrow-left\" size={24} color=\"white\" />\n </div>\n </Pressable>\n )}\n\n {showRightPaddle && isHoveringEnd && (\n <Pressable\n onClick={() => scroll(\"right\")}\n className=\"absolute right-4 top-1/2 -translate-y-1/2 z-20 transition-opacity duration-200\"\n aria-label=\"Scroll right\"\n >\n <div className=\"flex items-center justify-center w-10 h-10 rounded-full bg-overlay backdrop-blur-sm\">\n <Icon name=\"arrow-right\" size={24} color=\"white\" />\n </div>\n </Pressable>\n )}\n </>\n );\n }, [\n isMobile,\n showPaddles,\n showLeftPaddle,\n showRightPaddle,\n isHoveringStart,\n isHoveringEnd,\n scroll\n ]);\n\n return (\n <div\n className={`relative group w-full max-w-full overflow-hidden ${className}`}\n onKeyDown={handleKeyDown}\n onMouseMove={handleMouseMove}\n onMouseLeave={handleMouseLeave}\n role=\"region\"\n aria-label=\"Carousel\"\n >\n <ScrollArea.Root\n className=\"overflow-hidden w-full max-w-full\"\n type=\"hover\"\n >\n <ScrollArea.Viewport\n ref={scrollContainerRef}\n className=\"w-full max-w-full overflow-x-auto snap-x snap-mandatory\"\n style={viewportStyle}\n onTouchStart={handleTouchStart}\n onTouchMove={handleTouchMove}\n onTouchEnd={handleTouchEnd}\n onTouchCancel={handleTouchCancel}\n data-testid=\"carousel-viewport\"\n >\n <div className=\"inline-flex w-max\" style={gapStyle}>\n {mappedChildren}\n </div>\n </ScrollArea.Viewport>\n </ScrollArea.Root>\n\n {/* Navigation Paddles - Only show on desktop */}\n {desktopPaddles}\n </div>\n );\n }\n);\n"]}
|
|
@@ -2,6 +2,10 @@ import React__default from 'react';
|
|
|
2
2
|
|
|
3
3
|
type CarouselRef = {
|
|
4
4
|
scroll: (direction: "left" | "right") => void;
|
|
5
|
+
getScrollState: () => {
|
|
6
|
+
canScrollLeft: boolean;
|
|
7
|
+
canScrollRight: boolean;
|
|
8
|
+
};
|
|
5
9
|
};
|
|
6
10
|
type CarouselProps = {
|
|
7
11
|
children: React__default.ReactNode;
|
|
@@ -16,6 +20,11 @@ type CarouselProps = {
|
|
|
16
20
|
* @default true
|
|
17
21
|
*/
|
|
18
22
|
showPaddles?: boolean;
|
|
23
|
+
/** Optional callback when scroll state changes */
|
|
24
|
+
onScrollStateChange?: (state: {
|
|
25
|
+
canScrollLeft: boolean;
|
|
26
|
+
canScrollRight: boolean;
|
|
27
|
+
}) => void;
|
|
19
28
|
};
|
|
20
29
|
declare const Carousel: React__default.ForwardRefExoticComponent<CarouselProps & React__default.RefAttributes<CarouselRef>>;
|
|
21
30
|
|
|
@@ -2,6 +2,10 @@ import React__default from 'react';
|
|
|
2
2
|
|
|
3
3
|
type CarouselRef = {
|
|
4
4
|
scroll: (direction: "left" | "right") => void;
|
|
5
|
+
getScrollState: () => {
|
|
6
|
+
canScrollLeft: boolean;
|
|
7
|
+
canScrollRight: boolean;
|
|
8
|
+
};
|
|
5
9
|
};
|
|
6
10
|
type CarouselProps = {
|
|
7
11
|
children: React__default.ReactNode;
|
|
@@ -16,6 +20,11 @@ type CarouselProps = {
|
|
|
16
20
|
* @default true
|
|
17
21
|
*/
|
|
18
22
|
showPaddles?: boolean;
|
|
23
|
+
/** Optional callback when scroll state changes */
|
|
24
|
+
onScrollStateChange?: (state: {
|
|
25
|
+
canScrollLeft: boolean;
|
|
26
|
+
canScrollRight: boolean;
|
|
27
|
+
}) => void;
|
|
19
28
|
};
|
|
20
29
|
declare const Carousel: React__default.ForwardRefExoticComponent<CarouselProps & React__default.RefAttributes<CarouselRef>>;
|
|
21
30
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import*as
|
|
1
|
+
import*as T from'@radix-ui/react-scroll-area';import p,{forwardRef,useRef,useState,useCallback,useEffect,useMemo}from'react';import {IconMap}from'@deckai/icons';import {clsx}from'clsx';import {twMerge}from'tailwind-merge';var X=t=>{let[a,r]=useState(false);return useEffect(()=>{r(window.matchMedia(t).matches);let o=window.matchMedia(t),i=c=>{r(c.matches);};return o.addEventListener("change",i),()=>{o.removeEventListener("change",i);}},[t]),a};function k(...t){return twMerge(clsx(t))}var N={12:"h-[12px] w-[12px]",16:"h-[16px] w-[16px]",18:"h-[18px] w-[18px]",20:"h-[20px] w-[20px]",24:"h-[24px] w-[24px]",32:"h-[32px] w-[32px]",36:"h-[36px] w-[36px]",40:"h-[40px] w-[40px]",42:"h-[42px] w-[42px]",48:"h-[48px] w-[48px]",52:"h-[52px] w-[52px]",60:"h-[60px] w-[60px]",64:"h-[64px] w-[64px]",72:"h-[72px] w-[72px]",80:"h-[80px] w-[80px]"},D={sm:{12:"sm:h-[12px] sm:w-[12px]",16:"sm:h-[16px] sm:w-[16px]",18:"sm:h-[18px] sm:w-[18px]",20:"sm:h-[20px] sm:w-[20px]",24:"sm:h-[24px] sm:w-[24px]",32:"sm:h-[32px] sm:w-[32px]",36:"sm:h-[36px] sm:w-[36px]",40:"sm:h-[40px] sm:w-[40px]",42:"sm:h-[42px] sm:w-[42px]",48:"sm:h-[48px] sm:w-[48px]",52:"sm:h-[52px] sm:w-[52px]",60:"sm:h-[60px] sm:w-[60px]",64:"sm:h-[64px] sm:w-[64px]",72:"sm:h-[72px] sm:w-[72px]",80:"sm:h-[80px] sm:w-[80px]"},md:{12:"md:h-[12px] md:w-[12px]",16:"md:h-[16px] md:w-[16px]",18:"md:h-[18px] md:w-[18px]",20:"md:h-[20px] md:w-[20px]",24:"md:h-[24px] md:w-[24px]",32:"md:h-[32px] md:w-[32px]",36:"md:h-[36px] md:w-[36px]",40:"md:h-[40px] md:w-[40px]",42:"md:h-[42px] md:w-[42px]",48:"md:h-[48px] md:w-[48px]",52:"md:h-[52px] md:w-[52px]",60:"md:h-[60px] md:w-[60px]",64:"md:h-[64px] md:w-[64px]",72:"md:h-[72px] md:w-[72px]",80:"md:h-[80px] md:w-[80px]"},lg:{12:"lg:h-[12px] lg:w-[12px]",16:"lg:h-[16px] lg:w-[16px]",18:"lg:h-[18px] lg:w-[18px]",20:"lg:h-[20px] lg:w-[20px]",24:"lg:h-[24px] lg:w-[24px]",32:"lg:h-[32px] lg:w-[32px]",36:"lg:h-[36px] lg:w-[36px]",40:"lg:h-[40px] lg:w-[40px]",42:"lg:h-[42px] lg:w-[42px]",48:"lg:h-[48px] lg:w-[48px]",52:"lg:h-[52px] lg:w-[52px]",60:"lg:h-[60px] lg:w-[60px]",64:"lg:h-[64px] lg:w-[64px]",72:"lg:h-[72px] lg:w-[72px]",80:"lg:h-[80px] lg:w-[80px]"},xl:{12:"xl:h-[12px] xl:w-[12px]",16:"xl:h-[16px] xl:w-[16px]",18:"xl:h-[18px] xl:w-[18px]",20:"xl:h-[20px] xl:w-[20px]",24:"xl:h-[24px] xl:w-[24px]",32:"xl:h-[32px] xl:w-[32px]",36:"xl:h-[36px] xl:w-[36px]",40:"xl:h-[40px] xl:w-[40px]",42:"xl:h-[42px] xl:w-[42px]",48:"xl:h-[48px] xl:w-[48px]",52:"xl:h-[52px] xl:w-[52px]",60:"xl:h-[60px] xl:w-[60px]",64:"xl:h-[64px] xl:w-[64px]",72:"xl:h-[72px] xl:w-[72px]",80:"xl:h-[80px] xl:w-[80px]"},"2xl":{12:"2xl:h-[12px] 2xl:w-[12px]",16:"2xl:h-[16px] 2xl:w-[16px]",18:"2xl:h-[18px] 2xl:w-[18px]",20:"2xl:h-[20px] 2xl:w-[20px]",24:"2xl:h-[24px] 2xl:w-[24px]",32:"2xl:h-[32px] 2xl:w-[32px]",36:"2xl:h-[36px] 2xl:w-[36px]",40:"2xl:h-[40px] 2xl:w-[40px]",42:"2xl:h-[42px] 2xl:w-[42px]",48:"2xl:h-[48px] 2xl:w-[48px]",52:"2xl:h-[52px] 2xl:w-[52px]",60:"2xl:h-[60px] 2xl:w-[60px]",64:"2xl:h-[64px] 2xl:w-[64px]",72:"2xl:h-[72px] 2xl:w-[72px]",80:"2xl:h-[80px] 2xl:w-[80px]"}},E=t=>String(t),G=(t,a=24)=>{let r=[],l={};if(t===void 0){let o=E(a);o?r.push(N[o]):(l.height=`${a}px`,l.width=`${a}px`);}if(typeof t=="number"){let o=E(t);o?r.push(N[o]):(l.height=`${t}px`,l.width=`${t}px`);}if(Array.isArray(t)){let o=E(a),i=[o&&N[o]||`h-[${a}px] w-[${a}px]`];t.forEach(c=>{if(typeof c=="string"){let[n,g]=c.split(":"),y=parseInt(g,10),d=E(y);r.push(d&&D[n]?.[d]||`${n}:h-[${y}px] ${n}:w-[${y}px]`);}}),r.push(...i);}if(typeof t=="string"){let[o,i]=t.split(":"),c=parseInt(i,10),n=E(c);r.push(n&&D[o]?.[n]||`${o}:h-[${c}px] ${o}:w-[${c}px]`);}return {responsiveSizeClasses:r.join(" "),responsiveSizeStyles:l}};var Q={primary:"var(--color-primary)",secondary:"var(--color-secondary)",white:"var(--color-white)",primaryBlue:"var(--color-primary-100)",disabled:"var(--color-disabled)",danger:"var(--color-danger)",tertiary:"var(--color-tertiary-15)"},L=p.forwardRef(({name:t,size:a=24,color:r="primary",title:l,className:o,style:i={},...c},n)=>{let g=IconMap[t],{responsiveSizeClasses:y,responsiveSizeStyles:d}=G(a,24);return p.createElement("div",{className:k("flex justify-center items-center",y,o),style:{"--icon-stroke":Q[r],...d,...i}},p.createElement(g,{ref:n,"aria-hidden":!l,"aria-label":l,stroke:t.includes("filled")?void 0:Q[r],...c}))});L.displayName="Icon";var _="focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-100";var P=p.forwardRef(({children:t,type:a="button",className:r,disabled:l,scaleOnPress:o=true,...i},c)=>p.createElement("button",{ref:c,type:a,disabled:l,className:k("appearance-none hover:opacity-90",_,l&&"opacity-50 cursor-not-allowed",o&&"transition-all active:scale-95",r),...i},t));P.displayName="Pressable";var Oe=forwardRef(({children:t,className:a="",gap:r=20,minHeight:l,showPaddles:o=true,onScrollStateChange:i},c)=>{let n=useRef(null),[g,y]=useState(false),[d,F]=useState(false),[M,z]=useState(false),[C,K]=useState(false),[S,V]=useState(null),[I,A]=useState(null),x=X("(max-width: 768px)"),H=useRef({canScrollLeft:false,canScrollRight:false}),$=useCallback(()=>{let e=n.current;if(!e)return;let{scrollLeft:s,scrollWidth:h,clientWidth:m}=e,f=s>0,w=Math.ceil(s+m)<h;(H.current.canScrollLeft!==f||H.current.canScrollRight!==w)&&(y(f),F(w),H.current={canScrollLeft:f,canScrollRight:w},i&&i({canScrollLeft:f,canScrollRight:w}));},[i]),J=useCallback(e=>{if(x)return;let h=e.currentTarget.getBoundingClientRect(),m=e.clientX-h.left,f=300,w=m<f,j=m>h.width-f;w!==M&&z(w),j!==C&&K(j);},[x,M,C]),U=useCallback(()=>{z(false),K(false);},[]),q=useCallback(e=>{V(e.touches[0].clientX),A(null);},[]),ee=useCallback(e=>{A(e.touches[0].clientX),!x&&S!==null&&Math.abs(S-e.touches[0].clientX)>10&&e.preventDefault();},[x,S]),te=useCallback(()=>{if(!S||!I)return;let e=n.current;if(!e)return;let s=S-I,h=x?30:50;if(Math.abs(s)<h)return;let m=x?e.clientWidth*.8:e.clientWidth,f=s>0?1:-1,w=e.scrollLeft+m*f;e.scrollTo({left:w,behavior:"smooth"});},[S,I,x]),oe=useCallback(()=>{V(null),A(null);},[]),O=useCallback(e=>{let s=n.current;if(!s)return;let h=Math.abs(e.deltaX)>Math.abs(e.deltaY);if(!h&&!e.shiftKey)return;e.preventDefault();let m=h?e.deltaX:e.deltaY;s.scrollBy({left:m,behavior:"smooth"});},[]);useEffect(()=>{let e=n.current;if(!e)return;let s=new ResizeObserver($);return s.observe(e),e.addEventListener("scroll",$,{passive:true}),e.addEventListener("wheel",O,{passive:false}),$(),()=>{s.disconnect(),e.removeEventListener("scroll",$),e.removeEventListener("wheel",O);}},[$,O]);let v=useCallback(e=>{let s=n.current;if(!s)return;let h=x?s.clientWidth*.8:s.clientWidth,m=s.scrollLeft+(e==="left"?-h:h);s.scrollTo({left:m,behavior:"smooth"});},[x]),se=useCallback(e=>{e.key==="ArrowLeft"?v("left"):e.key==="ArrowRight"&&v("right");},[v]),W=useMemo(()=>({canScrollLeft:g,canScrollRight:d}),[g,d]);p.useImperativeHandle(c,()=>({scroll:v,getScrollState:()=>W}),[v,W]);let re=useMemo(()=>({scrollbarWidth:"none",msOverflowStyle:"none",WebkitOverflowScrolling:"touch",touchAction:"pan-x",overflowX:"auto",minHeight:l,WebkitTapHighlightColor:"transparent",cursor:x?"default":"grab"}),[x,l]),le=useMemo(()=>({gap:`${r}px`}),[r]),ne=useMemo(()=>p.Children.map(t,e=>e===null?null:p.createElement("div",{className:"snap-start shrink-0"},e)),[t]),pe=useMemo(()=>x||!o?null:p.createElement(p.Fragment,null,g&&M&&p.createElement(P,{onClick:()=>v("left"),className:"absolute left-4 top-1/2 -translate-y-1/2 z-20 transition-opacity duration-200","aria-label":"Scroll left"},p.createElement("div",{className:"flex items-center justify-center w-10 h-10 rounded-full bg-overlay backdrop-blur-sm"},p.createElement(L,{name:"arrow-left",size:24,color:"white"}))),d&&C&&p.createElement(P,{onClick:()=>v("right"),className:"absolute right-4 top-1/2 -translate-y-1/2 z-20 transition-opacity duration-200","aria-label":"Scroll right"},p.createElement("div",{className:"flex items-center justify-center w-10 h-10 rounded-full bg-overlay backdrop-blur-sm"},p.createElement(L,{name:"arrow-right",size:24,color:"white"})))),[x,o,g,d,M,C,v]);return p.createElement("div",{className:`relative group w-full max-w-full overflow-hidden ${a}`,onKeyDown:se,onMouseMove:J,onMouseLeave:U,role:"region","aria-label":"Carousel"},p.createElement(T.Root,{className:"overflow-hidden w-full max-w-full",type:"hover"},p.createElement(T.Viewport,{ref:n,className:"w-full max-w-full overflow-x-auto snap-x snap-mandatory",style:re,onTouchStart:q,onTouchMove:ee,onTouchEnd:te,onTouchCancel:oe,"data-testid":"carousel-viewport"},p.createElement("div",{className:"inline-flex w-max",style:le},ne))),pe)});export{Oe as Carousel};//# sourceMappingURL=Carousel.js.map
|
|
2
2
|
//# sourceMappingURL=Carousel.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/hooks/useMediaQuery.ts","../../src/components/Icon.tsx","../../src/utils/index.ts","../../src/utils/responsive.ts","../../src/utils/tailwind.ts","../../src/components/Pressable.tsx","../../src/components/Carousel.tsx"],"names":["useMediaQuery","query","matches","setMatches","useState","useEffect","mediaQueryList","handleChange","event","cn","inputs","twMerge","clsx","BASE_SIZES","RESPONSIVE_SIZES","getSizeKey","size","getResponsiveSize","baseSize","classes","styles","key","baseKey","responsiveClasses","breakpoint","valueStr","value","valueKey","COLOR_MAP","Icon","React","name","color","title","className","style","props","ref","IconComponent","IconMap","responsiveSizeClasses","responsiveSizeStyles","focusRingStyles","Pressable","children","type","disabled","scaleOnPress","Carousel","forwardRef","gap","minHeight","showPaddles","scrollContainerRef","useRef","showLeftPaddle","setShowLeftPaddle","showRightPaddle","setShowRightPaddle","isHoveringStart","setIsHoveringStart","isHoveringEnd","setIsHoveringEnd","touchStart","setTouchStart","touchEnd","setTouchEnd","isMobile","checkScrollPosition","useCallback","container","scrollLeft","scrollWidth","clientWidth","handleMouseMove","rect","mouseX","HOVER_THRESHOLD","handleTouchStart","handleTouchMove","handleTouchEnd","distance","itemWidth","direction","targetScroll","handleWheel","isHorizontalScroll","scrollAmount","observer","scroll","handleKeyDown","child"],"mappings":"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","file":"Carousel.js","sourcesContent":["import { useEffect, useState } from \"react\";\n\n/**\n * Custom hook that reliably checks if a media query matches in both client and server environments\n * Returns false during SSR and the actual match value after hydration\n */\nexport const useMediaQuery = (query: string): boolean => {\n // Initialize state but avoid hydration mismatch by not setting initial value from client-only API\n const [matches, setMatches] = useState<boolean>(false);\n\n // This runs only on the client after hydration\n useEffect(() => {\n // Create the matcher function\n const getMatches = (): boolean => window.matchMedia(query).matches;\n\n // Set the initial value after component mounts\n setMatches(getMatches());\n\n // Create the media query list\n const mediaQueryList = window.matchMedia(query);\n\n // Define event handler\n const handleChange = (event: MediaQueryListEvent) => {\n setMatches(event.matches);\n };\n\n // Add event listener using the appropriate method\n // Modern browsers\n mediaQueryList.addEventListener(\"change\", handleChange);\n\n // Cleanup function\n return () => {\n mediaQueryList.removeEventListener(\"change\", handleChange);\n };\n }, [query]); // Only re-run if query changes\n\n return matches;\n};\n","import type { IconName } from \"@deckai/icons\";\nimport { IconMap } from \"@deckai/icons\";\nimport type { SVGProps } from \"react\";\nimport React from \"react\";\n\nimport type { IconColors } from \"../types/tailwind\";\nimport { cn } from \"../utils\";\nimport type { ResponsiveSize } from \"../utils/responsive\";\nimport { getResponsiveSize } from \"../utils/responsive\";\n\nexport type IconProps = {\n name: IconName;\n /** @default 24 */\n size?: ResponsiveSize | ResponsiveSize[];\n /** @default primary */\n color?: IconColors;\n title?: string;\n className?: string;\n style?: React.CSSProperties;\n} & Omit<SVGProps<SVGSVGElement>, \"aria-hidden\" | \"aria-label\">;\n\n// Using CSS variables to support dark mode\nconst COLOR_MAP: Record<IconColors, string> = {\n primary: \"var(--color-primary)\",\n secondary: \"var(--color-secondary)\",\n white: \"var(--color-white)\",\n primaryBlue: \"var(--color-primary-100)\",\n disabled: \"var(--color-disabled)\",\n danger: \"var(--color-danger)\",\n tertiary: \"var(--color-tertiary-15)\"\n};\n\nexport const Icon = React.forwardRef<SVGSVGElement, IconProps>(\n (\n {\n name,\n size = 24,\n color = \"primary\",\n title,\n className,\n style = {},\n ...props\n },\n ref\n ) => {\n const IconComponent = IconMap[name];\n const { responsiveSizeClasses, responsiveSizeStyles } = getResponsiveSize(\n size,\n 24\n );\n\n return (\n <div\n className={cn(\n \"flex justify-center items-center\",\n responsiveSizeClasses,\n className\n )}\n style={{\n [\"--icon-stroke\" as string]: COLOR_MAP[color],\n ...responsiveSizeStyles,\n ...style\n }}\n >\n <IconComponent\n ref={ref}\n aria-hidden={!title}\n aria-label={title}\n stroke={name.includes(\"filled\") ? undefined : COLOR_MAP[color]}\n {...props}\n />\n </div>\n );\n }\n);\n\nIcon.displayName = \"Icon\";\n","import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n\nexport const noopFn = () => {};\n","export type Breakpoint = \"sm\" | \"md\" | \"lg\" | \"xl\" | \"2xl\";\nexport type ResponsiveSize = number | `${Breakpoint}:${number}`;\n\ntype SizeKey =\n | \"12\"\n | \"16\"\n | \"18\"\n | \"20\"\n | \"24\"\n | \"32\"\n | \"36\"\n | \"40\"\n | \"42\"\n | \"48\"\n | \"52\"\n | \"60\"\n | \"64\"\n | \"72\"\n | \"80\";\n\n// These constants help Tailwind identify the classes during compilation\nconst BASE_SIZES: Record<SizeKey, string> = {\n \"12\": \"h-[12px] w-[12px]\",\n \"16\": \"h-[16px] w-[16px]\",\n \"18\": \"h-[18px] w-[18px]\",\n \"20\": \"h-[20px] w-[20px]\",\n \"24\": \"h-[24px] w-[24px]\",\n \"32\": \"h-[32px] w-[32px]\",\n \"36\": \"h-[36px] w-[36px]\",\n \"40\": \"h-[40px] w-[40px]\",\n \"42\": \"h-[42px] w-[42px]\",\n \"48\": \"h-[48px] w-[48px]\",\n \"52\": \"h-[52px] w-[52px]\",\n \"60\": \"h-[60px] w-[60px]\",\n \"64\": \"h-[64px] w-[64px]\",\n \"72\": \"h-[72px] w-[72px]\",\n \"80\": \"h-[80px] w-[80px]\"\n};\n\nconst RESPONSIVE_SIZES: Record<Breakpoint, Record<SizeKey, string>> = {\n sm: {\n \"12\": \"sm:h-[12px] sm:w-[12px]\",\n \"16\": \"sm:h-[16px] sm:w-[16px]\",\n \"18\": \"sm:h-[18px] sm:w-[18px]\",\n \"20\": \"sm:h-[20px] sm:w-[20px]\",\n \"24\": \"sm:h-[24px] sm:w-[24px]\",\n \"32\": \"sm:h-[32px] sm:w-[32px]\",\n \"36\": \"sm:h-[36px] sm:w-[36px]\",\n \"40\": \"sm:h-[40px] sm:w-[40px]\",\n \"42\": \"sm:h-[42px] sm:w-[42px]\",\n \"48\": \"sm:h-[48px] sm:w-[48px]\",\n \"52\": \"sm:h-[52px] sm:w-[52px]\",\n \"60\": \"sm:h-[60px] sm:w-[60px]\",\n \"64\": \"sm:h-[64px] sm:w-[64px]\",\n \"72\": \"sm:h-[72px] sm:w-[72px]\",\n \"80\": \"sm:h-[80px] sm:w-[80px]\"\n },\n md: {\n \"12\": \"md:h-[12px] md:w-[12px]\",\n \"16\": \"md:h-[16px] md:w-[16px]\",\n \"18\": \"md:h-[18px] md:w-[18px]\",\n \"20\": \"md:h-[20px] md:w-[20px]\",\n \"24\": \"md:h-[24px] md:w-[24px]\",\n \"32\": \"md:h-[32px] md:w-[32px]\",\n \"36\": \"md:h-[36px] md:w-[36px]\",\n \"40\": \"md:h-[40px] md:w-[40px]\",\n \"42\": \"md:h-[42px] md:w-[42px]\",\n \"48\": \"md:h-[48px] md:w-[48px]\",\n \"52\": \"md:h-[52px] md:w-[52px]\",\n \"60\": \"md:h-[60px] md:w-[60px]\",\n \"64\": \"md:h-[64px] md:w-[64px]\",\n \"72\": \"md:h-[72px] md:w-[72px]\",\n \"80\": \"md:h-[80px] md:w-[80px]\"\n },\n lg: {\n \"12\": \"lg:h-[12px] lg:w-[12px]\",\n \"16\": \"lg:h-[16px] lg:w-[16px]\",\n \"18\": \"lg:h-[18px] lg:w-[18px]\",\n \"20\": \"lg:h-[20px] lg:w-[20px]\",\n \"24\": \"lg:h-[24px] lg:w-[24px]\",\n \"32\": \"lg:h-[32px] lg:w-[32px]\",\n \"36\": \"lg:h-[36px] lg:w-[36px]\",\n \"40\": \"lg:h-[40px] lg:w-[40px]\",\n \"42\": \"lg:h-[42px] lg:w-[42px]\",\n \"48\": \"lg:h-[48px] lg:w-[48px]\",\n \"52\": \"lg:h-[52px] lg:w-[52px]\",\n \"60\": \"lg:h-[60px] lg:w-[60px]\",\n \"64\": \"lg:h-[64px] lg:w-[64px]\",\n \"72\": \"lg:h-[72px] lg:w-[72px]\",\n \"80\": \"lg:h-[80px] lg:w-[80px]\"\n },\n xl: {\n \"12\": \"xl:h-[12px] xl:w-[12px]\",\n \"16\": \"xl:h-[16px] xl:w-[16px]\",\n \"18\": \"xl:h-[18px] xl:w-[18px]\",\n \"20\": \"xl:h-[20px] xl:w-[20px]\",\n \"24\": \"xl:h-[24px] xl:w-[24px]\",\n \"32\": \"xl:h-[32px] xl:w-[32px]\",\n \"36\": \"xl:h-[36px] xl:w-[36px]\",\n \"40\": \"xl:h-[40px] xl:w-[40px]\",\n \"42\": \"xl:h-[42px] xl:w-[42px]\",\n \"48\": \"xl:h-[48px] xl:w-[48px]\",\n \"52\": \"xl:h-[52px] xl:w-[52px]\",\n \"60\": \"xl:h-[60px] xl:w-[60px]\",\n \"64\": \"xl:h-[64px] xl:w-[64px]\",\n \"72\": \"xl:h-[72px] xl:w-[72px]\",\n \"80\": \"xl:h-[80px] xl:w-[80px]\"\n },\n \"2xl\": {\n \"12\": \"2xl:h-[12px] 2xl:w-[12px]\",\n \"16\": \"2xl:h-[16px] 2xl:w-[16px]\",\n \"18\": \"2xl:h-[18px] 2xl:w-[18px]\",\n \"20\": \"2xl:h-[20px] 2xl:w-[20px]\",\n \"24\": \"2xl:h-[24px] 2xl:w-[24px]\",\n \"32\": \"2xl:h-[32px] 2xl:w-[32px]\",\n \"36\": \"2xl:h-[36px] 2xl:w-[36px]\",\n \"40\": \"2xl:h-[40px] 2xl:w-[40px]\",\n \"42\": \"2xl:h-[42px] 2xl:w-[42px]\",\n \"48\": \"2xl:h-[48px] 2xl:w-[48px]\",\n \"52\": \"2xl:h-[52px] 2xl:w-[52px]\",\n \"60\": \"2xl:h-[60px] 2xl:w-[60px]\",\n \"64\": \"2xl:h-[64px] 2xl:w-[64px]\",\n \"72\": \"2xl:h-[72px] 2xl:w-[72px]\",\n \"80\": \"2xl:h-[80px] 2xl:w-[80px]\"\n }\n};\n\nconst getSizeKey = (size: number): SizeKey | undefined => {\n return String(size) as SizeKey;\n};\n\nexport const getResponsiveSize = (\n size: ResponsiveSize | ResponsiveSize[] | undefined,\n baseSize: number = 24\n): {\n responsiveSizeClasses: string;\n responsiveSizeStyles: Record<string, string>;\n} => {\n const classes: string[] = [];\n const styles: Record<string, string> = {};\n\n // If no size provided, use baseSize\n if (size === undefined) {\n const key = getSizeKey(baseSize);\n if (key) {\n classes.push(BASE_SIZES[key]);\n } else {\n styles.height = `${baseSize}px`;\n styles.width = `${baseSize}px`;\n }\n }\n\n // If size is a number, use that directly\n if (typeof size === \"number\") {\n const key = getSizeKey(size);\n if (key) {\n classes.push(BASE_SIZES[key]);\n } else {\n styles.height = `${size}px`;\n styles.width = `${size}px`;\n }\n }\n\n // If array of responsive sizes, generate responsive classes\n if (Array.isArray(size)) {\n const baseKey = getSizeKey(baseSize);\n const responsiveClasses = [\n (baseKey && BASE_SIZES[baseKey]) || `h-[${baseSize}px] w-[${baseSize}px]`\n ];\n\n size.forEach((s) => {\n if (typeof s === \"string\") {\n const [breakpoint, valueStr] = s.split(\":\") as [Breakpoint, string];\n const value = parseInt(valueStr, 10);\n const key = getSizeKey(value);\n classes.push(\n (key && RESPONSIVE_SIZES[breakpoint]?.[key]) ||\n `${breakpoint}:h-[${value}px] ${breakpoint}:w-[${value}px]`\n );\n }\n });\n\n classes.push(...responsiveClasses);\n }\n\n if (typeof size === \"string\") {\n const [breakpoint, valueStr] = size.split(\":\") as [Breakpoint, string];\n const value = parseInt(valueStr, 10);\n const valueKey = getSizeKey(value);\n classes.push(\n (valueKey && RESPONSIVE_SIZES[breakpoint]?.[valueKey]) ||\n `${breakpoint}:h-[${value}px] ${breakpoint}:w-[${value}px]`\n );\n }\n\n return {\n responsiveSizeClasses: classes.join(\" \"),\n responsiveSizeStyles: styles\n };\n};\n","import type { Colors, Typography } from \"../types/tailwind\";\n\n// Generate safelist patterns for all color utilities so you can use any theme color variable in your code\nexport const generateSafelist = (colors: Colors, typography: Typography) => {\n const colorNames = Object.keys(colors) as (keyof Colors)[];\n const utilities = [\"bg\", \"text\", \"border\", \"ring\", \"divide\", \"outline\"];\n const variants = [\"hover:\", \"focus:\", \"active:\", \"disabled:\"];\n const breakpoints = [\"sm\", \"md\", \"lg\", \"xl\", \"2xl\"];\n const sizes = [\"24\", \"42\", \"48\", \"64\", \"72\"]; // Add all the sizes you need\n\n const safelist: (string | { pattern: RegExp; variants: string[] })[] = [];\n\n colorNames.forEach((colorName) => {\n if (typeof colors[colorName] === \"object\") {\n // Handle nested color objects (with number keys)\n Object.keys(colors[colorName]).forEach((shade) => {\n utilities.forEach((utility) => {\n // Base utility\n safelist.push(`${utility}-${colorName}-${shade}`);\n\n // Variant utilities\n variants.forEach((variant) => {\n safelist.push(`${variant}${utility}-${colorName}-${shade}`);\n });\n });\n });\n } else {\n // Handle direct color values\n utilities.forEach((utility) => {\n safelist.push(`${utility}-${colorName}`);\n\n variants.forEach((variant) => {\n safelist.push(`${variant}${utility}-${colorName}`);\n });\n });\n }\n });\n\n // Generate typography classes\n Object.entries(typography).forEach(([family, sizes]) => {\n Object.keys(sizes).forEach((size) => {\n // Base typography classes\n safelist.push(`text-${family}-${size}`);\n\n // Add variants\n variants.forEach((variant) => {\n safelist.push(`${variant}text-${family}-${size}`);\n });\n });\n });\n\n const typographyClasses = Object.entries(typography).flatMap(\n ([category, sizes]) =>\n Object.keys(sizes).map((size) => `text-${category}-${size}`)\n );\n\n // Generate responsive variants\n const responsiveTypographyClasses = typographyClasses.flatMap((className) =>\n breakpoints.map((breakpoint) => `${breakpoint}:${className}`)\n );\n\n // Generate size classes with responsive variants\n const sizeClasses = sizes.flatMap((size) => [\n `h-[${size}px]`,\n `w-[${size}px]`,\n ...breakpoints.flatMap((bp) => [\n `${bp}:h-[${size}px]`,\n `${bp}:w-[${size}px]`\n ])\n ]);\n\n return [...typographyClasses, ...responsiveTypographyClasses, ...sizeClasses];\n};\n\nexport const focusRingStyles =\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-100\";\nexport const focusRingWithinStyles =\n \"focus-within:outline-none focus-within:ring-2 focus-within:ring-primary-100\";\nexport const focusRingStylesCoerced = \"ring-2 ring-primary-100\";\n","import type { ButtonHTMLAttributes } from \"react\";\nimport React from \"react\";\n\nimport { cn } from \"../utils\";\nimport { focusRingStyles } from \"../utils/tailwind\";\n\nexport type PressableProps = ButtonHTMLAttributes<HTMLButtonElement> & {\n /**\n * @default true\n * Scaling motion when pressed\n */\n scaleOnPress?: boolean;\n};\n\nexport const Pressable = React.forwardRef<HTMLButtonElement, PressableProps>(\n (\n {\n children,\n type = \"button\",\n className,\n disabled,\n scaleOnPress = true,\n ...props\n },\n ref\n ) => (\n <button\n ref={ref}\n type={type}\n disabled={disabled}\n className={cn(\n \"appearance-none hover:opacity-90\",\n focusRingStyles,\n disabled && \"opacity-50 cursor-not-allowed\",\n scaleOnPress && \"transition-all active:scale-95\",\n className\n )}\n {...props}\n >\n {children}\n </button>\n )\n);\n\nPressable.displayName = \"Pressable\";\n","import * as ScrollArea from \"@radix-ui/react-scroll-area\";\nimport React, {\n forwardRef,\n useCallback,\n useEffect,\n useRef,\n useState\n} from \"react\";\n\nimport { useMediaQuery } from \"../hooks/useMediaQuery\";\nimport { Icon } from \"./Icon\";\nimport { Pressable } from \"./Pressable\";\n\nexport type CarouselRef = {\n scroll: (direction: \"left\" | \"right\") => void;\n};\n\nexport type CarouselProps = {\n children: React.ReactNode;\n /** Optional className for the root element */\n className?: string;\n /** Optional gap between items in pixels */\n gap?: number;\n /** Optional minimum height for the carousel */\n minHeight?: string;\n /**\n * Optional boolean to show/hide paddles\n * @default true\n */\n showPaddles?: boolean;\n};\n\nexport const Carousel = forwardRef<CarouselRef, CarouselProps>(\n (\n { children, className = \"\", gap = 20, minHeight, showPaddles = true },\n ref\n ) => {\n const scrollContainerRef = useRef<HTMLDivElement>(null);\n const [showLeftPaddle, setShowLeftPaddle] = useState(false);\n const [showRightPaddle, setShowRightPaddle] = useState(false);\n const [isHoveringStart, setIsHoveringStart] = useState(false);\n const [isHoveringEnd, setIsHoveringEnd] = useState(false);\n const [touchStart, setTouchStart] = useState<number | null>(null);\n const [touchEnd, setTouchEnd] = useState<number | null>(null);\n const isMobile = useMediaQuery(\"(max-width: 768px)\");\n\n const checkScrollPosition = useCallback(() => {\n const container = scrollContainerRef.current;\n if (!container) return;\n\n const { scrollLeft, scrollWidth, clientWidth } = container;\n setShowLeftPaddle(scrollLeft > 0);\n setShowRightPaddle(Math.ceil(scrollLeft + clientWidth) < scrollWidth);\n }, []);\n\n const handleMouseMove = useCallback(\n (e: React.MouseEvent) => {\n if (isMobile) return;\n\n const container = e.currentTarget;\n const rect = container.getBoundingClientRect();\n const mouseX = e.clientX - rect.left;\n const HOVER_THRESHOLD = 300;\n\n setIsHoveringStart(mouseX < HOVER_THRESHOLD);\n setIsHoveringEnd(mouseX > rect.width - HOVER_THRESHOLD);\n },\n [isMobile]\n );\n\n // Touch handling\n const handleTouchStart = useCallback((e: React.TouchEvent) => {\n setTouchStart(e.touches[0].clientX);\n setTouchEnd(null);\n }, []);\n\n const handleTouchMove = useCallback((e: React.TouchEvent) => {\n setTouchEnd(e.touches[0].clientX);\n }, []);\n\n const handleTouchEnd = useCallback(() => {\n if (!touchStart || !touchEnd) return;\n\n const container = scrollContainerRef.current;\n if (!container) return;\n\n const distance = touchStart - touchEnd;\n const minSwipeDistance = 50;\n\n if (Math.abs(distance) < minSwipeDistance) {\n return;\n }\n\n const itemWidth = container.clientWidth;\n const direction = distance > 0 ? 1 : -1;\n const targetScroll = container.scrollLeft + itemWidth * direction;\n\n container.scrollTo({\n left: targetScroll,\n behavior: \"smooth\"\n });\n }, [touchStart, touchEnd]);\n\n const handleWheel = useCallback((e: WheelEvent) => {\n const container = scrollContainerRef.current;\n if (!container) return;\n\n // Check if the scroll is predominantly horizontal or if shift key is pressed\n const isHorizontalScroll = Math.abs(e.deltaX) > Math.abs(e.deltaY);\n if (!isHorizontalScroll && !e.shiftKey) return;\n\n e.preventDefault();\n\n // Determine the scroll amount based on the input type\n const scrollAmount = isHorizontalScroll ? e.deltaX : e.deltaY;\n\n // Apply smooth scrolling\n container.scrollBy({\n left: scrollAmount,\n behavior: \"smooth\"\n });\n }, []);\n\n useEffect(() => {\n const container = scrollContainerRef.current;\n if (!container) return;\n\n const observer = new ResizeObserver(checkScrollPosition);\n observer.observe(container);\n\n container.addEventListener(\"scroll\", checkScrollPosition);\n container.addEventListener(\"wheel\", handleWheel, { passive: false });\n\n return () => {\n observer.disconnect();\n container.removeEventListener(\"scroll\", checkScrollPosition);\n container.removeEventListener(\"wheel\", handleWheel);\n };\n }, [checkScrollPosition, handleWheel]);\n\n const scroll = useCallback((direction: \"left\" | \"right\") => {\n const container = scrollContainerRef.current;\n if (!container) return;\n\n const scrollAmount = container.clientWidth;\n const targetScroll =\n container.scrollLeft +\n (direction === \"left\" ? -scrollAmount : scrollAmount);\n\n container.scrollTo({\n left: targetScroll,\n behavior: \"smooth\"\n });\n }, []);\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === \"ArrowLeft\") {\n scroll(\"left\");\n } else if (e.key === \"ArrowRight\") {\n scroll(\"right\");\n }\n },\n [scroll]\n );\n\n // Expose scroll method via ref\n React.useImperativeHandle(\n ref,\n () => ({\n scroll\n }),\n [scroll]\n );\n\n return (\n <div\n className={`relative group w-full max-w-full overflow-x-hidden ${className}`}\n onKeyDown={handleKeyDown}\n onMouseMove={handleMouseMove}\n onMouseLeave={() => {\n setIsHoveringStart(false);\n setIsHoveringEnd(false);\n }}\n onTouchStart={handleTouchStart}\n onTouchMove={handleTouchMove}\n onTouchEnd={handleTouchEnd}\n role=\"region\"\n aria-label=\"Carousel\"\n >\n <ScrollArea.Root\n className=\"overflow-x-hidden w-full max-w-full\"\n type=\"hover\"\n >\n <ScrollArea.Viewport\n ref={scrollContainerRef}\n className=\"w-full max-w-full overflow-x-auto snap-x snap-mandatory\"\n style={{\n scrollbarWidth: \"none\",\n msOverflowStyle: \"none\",\n WebkitOverflowScrolling: \"touch\",\n minHeight\n }}\n >\n <div\n className=\"inline-flex w-max\"\n style={{\n gap: `${gap}px`\n }}\n >\n {React.Children.map(children, (child) =>\n child === null ? null : (\n <div className=\"snap-start shrink-0\">{child}</div>\n )\n )}\n </div>\n </ScrollArea.Viewport>\n </ScrollArea.Root>\n\n {/* Navigation Paddles - Only show on desktop */}\n {!isMobile && (\n <>\n {showLeftPaddle && showPaddles && isHoveringStart && (\n <Pressable\n onClick={() => scroll(\"left\")}\n className=\"absolute left-4 top-1/2 -translate-y-1/2 z-20 transition-opacity duration-200\"\n aria-label=\"Scroll left\"\n >\n <div className=\"flex items-center justify-center w-10 h-10 rounded-full bg-overlay backdrop-blur-sm\">\n <Icon name=\"arrow-left\" size={24} color=\"white\" />\n </div>\n </Pressable>\n )}\n\n {showRightPaddle && showPaddles && isHoveringEnd && (\n <Pressable\n onClick={() => scroll(\"right\")}\n className=\"absolute right-4 top-1/2 -translate-y-1/2 z-20 transition-opacity duration-200\"\n aria-label=\"Scroll right\"\n >\n <div className=\"flex items-center justify-center w-10 h-10 rounded-full bg-overlay backdrop-blur-sm\">\n <Icon name=\"arrow-right\" size={24} color=\"white\" />\n </div>\n </Pressable>\n )}\n </>\n )}\n </div>\n );\n }\n);\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/hooks/useMediaQuery.ts","../../src/components/Icon.tsx","../../src/utils/index.ts","../../src/utils/responsive.ts","../../src/utils/tailwind.ts","../../src/components/Pressable.tsx","../../src/components/Carousel.tsx"],"names":["useMediaQuery","query","matches","setMatches","useState","useEffect","mediaQueryList","handleChange","event","cn","inputs","twMerge","clsx","BASE_SIZES","RESPONSIVE_SIZES","getSizeKey","size","getResponsiveSize","baseSize","classes","styles","key","baseKey","responsiveClasses","s","breakpoint","valueStr","value","valueKey","COLOR_MAP","Icon","React","name","color","title","className","style","props","ref","IconComponent","IconMap","responsiveSizeClasses","responsiveSizeStyles","focusRingStyles","Pressable","children","type","disabled","scaleOnPress","Carousel","forwardRef","gap","minHeight","showPaddles","onScrollStateChange","scrollContainerRef","useRef","showLeftPaddle","setShowLeftPaddle","showRightPaddle","setShowRightPaddle","isHoveringStart","setIsHoveringStart","isHoveringEnd","setIsHoveringEnd","touchStart","setTouchStart","touchEnd","setTouchEnd","isMobile","prevScrollStateRef","checkScrollPosition","useCallback","container","scrollLeft","scrollWidth","clientWidth","canScrollLeft","canScrollRight","handleMouseMove","rect","mouseX","HOVER_THRESHOLD","newIsHoveringStart","newIsHoveringEnd","handleMouseLeave","handleTouchStart","handleTouchMove","handleTouchEnd","distance","minSwipeDistance","scrollAmount","direction","targetScroll","handleTouchCancel","handleWheel","isHorizontalScroll","observer","scroll","handleKeyDown","scrollState","useMemo","viewportStyle","gapStyle","mappedChildren","child","desktopPaddles"],"mappings":"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","file":"Carousel.js","sourcesContent":["import { useEffect, useState } from \"react\";\n\n/**\n * Custom hook that reliably checks if a media query matches in both client and server environments\n * Returns false during SSR and the actual match value after hydration\n */\nexport const useMediaQuery = (query: string): boolean => {\n // Initialize state but avoid hydration mismatch by not setting initial value from client-only API\n const [matches, setMatches] = useState<boolean>(false);\n\n // This runs only on the client after hydration\n useEffect(() => {\n // Create the matcher function\n const getMatches = (): boolean => window.matchMedia(query).matches;\n\n // Set the initial value after component mounts\n setMatches(getMatches());\n\n // Create the media query list\n const mediaQueryList = window.matchMedia(query);\n\n // Define event handler\n const handleChange = (event: MediaQueryListEvent) => {\n setMatches(event.matches);\n };\n\n // Add event listener using the appropriate method\n // Modern browsers\n mediaQueryList.addEventListener(\"change\", handleChange);\n\n // Cleanup function\n return () => {\n mediaQueryList.removeEventListener(\"change\", handleChange);\n };\n }, [query]); // Only re-run if query changes\n\n return matches;\n};\n","import type { IconName } from \"@deckai/icons\";\nimport { IconMap } from \"@deckai/icons\";\nimport type { SVGProps } from \"react\";\nimport React from \"react\";\n\nimport type { IconColors } from \"../types/tailwind\";\nimport { cn } from \"../utils\";\nimport type { ResponsiveSize } from \"../utils/responsive\";\nimport { getResponsiveSize } from \"../utils/responsive\";\n\nexport type IconProps = {\n name: IconName;\n /** @default 24 */\n size?: ResponsiveSize | ResponsiveSize[];\n /** @default primary */\n color?: IconColors;\n title?: string;\n className?: string;\n style?: React.CSSProperties;\n} & Omit<SVGProps<SVGSVGElement>, \"aria-hidden\" | \"aria-label\">;\n\n// Using CSS variables to support dark mode\nconst COLOR_MAP: Record<IconColors, string> = {\n primary: \"var(--color-primary)\",\n secondary: \"var(--color-secondary)\",\n white: \"var(--color-white)\",\n primaryBlue: \"var(--color-primary-100)\",\n disabled: \"var(--color-disabled)\",\n danger: \"var(--color-danger)\",\n tertiary: \"var(--color-tertiary-15)\"\n};\n\nexport const Icon = React.forwardRef<SVGSVGElement, IconProps>(\n (\n {\n name,\n size = 24,\n color = \"primary\",\n title,\n className,\n style = {},\n ...props\n },\n ref\n ) => {\n const IconComponent = IconMap[name];\n const { responsiveSizeClasses, responsiveSizeStyles } = getResponsiveSize(\n size,\n 24\n );\n\n return (\n <div\n className={cn(\n \"flex justify-center items-center\",\n responsiveSizeClasses,\n className\n )}\n style={{\n [\"--icon-stroke\" as string]: COLOR_MAP[color],\n ...responsiveSizeStyles,\n ...style\n }}\n >\n <IconComponent\n ref={ref}\n aria-hidden={!title}\n aria-label={title}\n stroke={name.includes(\"filled\") ? undefined : COLOR_MAP[color]}\n {...props}\n />\n </div>\n );\n }\n);\n\nIcon.displayName = \"Icon\";\n","import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n\nexport const noopFn = () => {};\n","export type Breakpoint = \"sm\" | \"md\" | \"lg\" | \"xl\" | \"2xl\";\nexport type ResponsiveSize = number | `${Breakpoint}:${number}`;\n\ntype SizeKey =\n | \"12\"\n | \"16\"\n | \"18\"\n | \"20\"\n | \"24\"\n | \"32\"\n | \"36\"\n | \"40\"\n | \"42\"\n | \"48\"\n | \"52\"\n | \"60\"\n | \"64\"\n | \"72\"\n | \"80\";\n\n// These constants help Tailwind identify the classes during compilation\nconst BASE_SIZES: Record<SizeKey, string> = {\n \"12\": \"h-[12px] w-[12px]\",\n \"16\": \"h-[16px] w-[16px]\",\n \"18\": \"h-[18px] w-[18px]\",\n \"20\": \"h-[20px] w-[20px]\",\n \"24\": \"h-[24px] w-[24px]\",\n \"32\": \"h-[32px] w-[32px]\",\n \"36\": \"h-[36px] w-[36px]\",\n \"40\": \"h-[40px] w-[40px]\",\n \"42\": \"h-[42px] w-[42px]\",\n \"48\": \"h-[48px] w-[48px]\",\n \"52\": \"h-[52px] w-[52px]\",\n \"60\": \"h-[60px] w-[60px]\",\n \"64\": \"h-[64px] w-[64px]\",\n \"72\": \"h-[72px] w-[72px]\",\n \"80\": \"h-[80px] w-[80px]\"\n};\n\nconst RESPONSIVE_SIZES: Record<Breakpoint, Record<SizeKey, string>> = {\n sm: {\n \"12\": \"sm:h-[12px] sm:w-[12px]\",\n \"16\": \"sm:h-[16px] sm:w-[16px]\",\n \"18\": \"sm:h-[18px] sm:w-[18px]\",\n \"20\": \"sm:h-[20px] sm:w-[20px]\",\n \"24\": \"sm:h-[24px] sm:w-[24px]\",\n \"32\": \"sm:h-[32px] sm:w-[32px]\",\n \"36\": \"sm:h-[36px] sm:w-[36px]\",\n \"40\": \"sm:h-[40px] sm:w-[40px]\",\n \"42\": \"sm:h-[42px] sm:w-[42px]\",\n \"48\": \"sm:h-[48px] sm:w-[48px]\",\n \"52\": \"sm:h-[52px] sm:w-[52px]\",\n \"60\": \"sm:h-[60px] sm:w-[60px]\",\n \"64\": \"sm:h-[64px] sm:w-[64px]\",\n \"72\": \"sm:h-[72px] sm:w-[72px]\",\n \"80\": \"sm:h-[80px] sm:w-[80px]\"\n },\n md: {\n \"12\": \"md:h-[12px] md:w-[12px]\",\n \"16\": \"md:h-[16px] md:w-[16px]\",\n \"18\": \"md:h-[18px] md:w-[18px]\",\n \"20\": \"md:h-[20px] md:w-[20px]\",\n \"24\": \"md:h-[24px] md:w-[24px]\",\n \"32\": \"md:h-[32px] md:w-[32px]\",\n \"36\": \"md:h-[36px] md:w-[36px]\",\n \"40\": \"md:h-[40px] md:w-[40px]\",\n \"42\": \"md:h-[42px] md:w-[42px]\",\n \"48\": \"md:h-[48px] md:w-[48px]\",\n \"52\": \"md:h-[52px] md:w-[52px]\",\n \"60\": \"md:h-[60px] md:w-[60px]\",\n \"64\": \"md:h-[64px] md:w-[64px]\",\n \"72\": \"md:h-[72px] md:w-[72px]\",\n \"80\": \"md:h-[80px] md:w-[80px]\"\n },\n lg: {\n \"12\": \"lg:h-[12px] lg:w-[12px]\",\n \"16\": \"lg:h-[16px] lg:w-[16px]\",\n \"18\": \"lg:h-[18px] lg:w-[18px]\",\n \"20\": \"lg:h-[20px] lg:w-[20px]\",\n \"24\": \"lg:h-[24px] lg:w-[24px]\",\n \"32\": \"lg:h-[32px] lg:w-[32px]\",\n \"36\": \"lg:h-[36px] lg:w-[36px]\",\n \"40\": \"lg:h-[40px] lg:w-[40px]\",\n \"42\": \"lg:h-[42px] lg:w-[42px]\",\n \"48\": \"lg:h-[48px] lg:w-[48px]\",\n \"52\": \"lg:h-[52px] lg:w-[52px]\",\n \"60\": \"lg:h-[60px] lg:w-[60px]\",\n \"64\": \"lg:h-[64px] lg:w-[64px]\",\n \"72\": \"lg:h-[72px] lg:w-[72px]\",\n \"80\": \"lg:h-[80px] lg:w-[80px]\"\n },\n xl: {\n \"12\": \"xl:h-[12px] xl:w-[12px]\",\n \"16\": \"xl:h-[16px] xl:w-[16px]\",\n \"18\": \"xl:h-[18px] xl:w-[18px]\",\n \"20\": \"xl:h-[20px] xl:w-[20px]\",\n \"24\": \"xl:h-[24px] xl:w-[24px]\",\n \"32\": \"xl:h-[32px] xl:w-[32px]\",\n \"36\": \"xl:h-[36px] xl:w-[36px]\",\n \"40\": \"xl:h-[40px] xl:w-[40px]\",\n \"42\": \"xl:h-[42px] xl:w-[42px]\",\n \"48\": \"xl:h-[48px] xl:w-[48px]\",\n \"52\": \"xl:h-[52px] xl:w-[52px]\",\n \"60\": \"xl:h-[60px] xl:w-[60px]\",\n \"64\": \"xl:h-[64px] xl:w-[64px]\",\n \"72\": \"xl:h-[72px] xl:w-[72px]\",\n \"80\": \"xl:h-[80px] xl:w-[80px]\"\n },\n \"2xl\": {\n \"12\": \"2xl:h-[12px] 2xl:w-[12px]\",\n \"16\": \"2xl:h-[16px] 2xl:w-[16px]\",\n \"18\": \"2xl:h-[18px] 2xl:w-[18px]\",\n \"20\": \"2xl:h-[20px] 2xl:w-[20px]\",\n \"24\": \"2xl:h-[24px] 2xl:w-[24px]\",\n \"32\": \"2xl:h-[32px] 2xl:w-[32px]\",\n \"36\": \"2xl:h-[36px] 2xl:w-[36px]\",\n \"40\": \"2xl:h-[40px] 2xl:w-[40px]\",\n \"42\": \"2xl:h-[42px] 2xl:w-[42px]\",\n \"48\": \"2xl:h-[48px] 2xl:w-[48px]\",\n \"52\": \"2xl:h-[52px] 2xl:w-[52px]\",\n \"60\": \"2xl:h-[60px] 2xl:w-[60px]\",\n \"64\": \"2xl:h-[64px] 2xl:w-[64px]\",\n \"72\": \"2xl:h-[72px] 2xl:w-[72px]\",\n \"80\": \"2xl:h-[80px] 2xl:w-[80px]\"\n }\n};\n\nconst getSizeKey = (size: number): SizeKey | undefined => {\n return String(size) as SizeKey;\n};\n\nexport const getResponsiveSize = (\n size: ResponsiveSize | ResponsiveSize[] | undefined,\n baseSize: number = 24\n): {\n responsiveSizeClasses: string;\n responsiveSizeStyles: Record<string, string>;\n} => {\n const classes: string[] = [];\n const styles: Record<string, string> = {};\n\n // If no size provided, use baseSize\n if (size === undefined) {\n const key = getSizeKey(baseSize);\n if (key) {\n classes.push(BASE_SIZES[key]);\n } else {\n styles.height = `${baseSize}px`;\n styles.width = `${baseSize}px`;\n }\n }\n\n // If size is a number, use that directly\n if (typeof size === \"number\") {\n const key = getSizeKey(size);\n if (key) {\n classes.push(BASE_SIZES[key]);\n } else {\n styles.height = `${size}px`;\n styles.width = `${size}px`;\n }\n }\n\n // If array of responsive sizes, generate responsive classes\n if (Array.isArray(size)) {\n const baseKey = getSizeKey(baseSize);\n const responsiveClasses = [\n (baseKey && BASE_SIZES[baseKey]) || `h-[${baseSize}px] w-[${baseSize}px]`\n ];\n\n size.forEach((s) => {\n if (typeof s === \"string\") {\n const [breakpoint, valueStr] = s.split(\":\") as [Breakpoint, string];\n const value = parseInt(valueStr, 10);\n const key = getSizeKey(value);\n classes.push(\n (key && RESPONSIVE_SIZES[breakpoint]?.[key]) ||\n `${breakpoint}:h-[${value}px] ${breakpoint}:w-[${value}px]`\n );\n }\n });\n\n classes.push(...responsiveClasses);\n }\n\n if (typeof size === \"string\") {\n const [breakpoint, valueStr] = size.split(\":\") as [Breakpoint, string];\n const value = parseInt(valueStr, 10);\n const valueKey = getSizeKey(value);\n classes.push(\n (valueKey && RESPONSIVE_SIZES[breakpoint]?.[valueKey]) ||\n `${breakpoint}:h-[${value}px] ${breakpoint}:w-[${value}px]`\n );\n }\n\n return {\n responsiveSizeClasses: classes.join(\" \"),\n responsiveSizeStyles: styles\n };\n};\n","import type { Colors, Typography } from \"../types/tailwind\";\n\n// Generate safelist patterns for all color utilities so you can use any theme color variable in your code\nexport const generateSafelist = (colors: Colors, typography: Typography) => {\n const colorNames = Object.keys(colors) as (keyof Colors)[];\n const utilities = [\"bg\", \"text\", \"border\", \"ring\", \"divide\", \"outline\"];\n const variants = [\"hover:\", \"focus:\", \"active:\", \"disabled:\"];\n const breakpoints = [\"sm\", \"md\", \"lg\", \"xl\", \"2xl\"];\n const sizes = [\"24\", \"42\", \"48\", \"64\", \"72\"]; // Add all the sizes you need\n\n const safelist: (string | { pattern: RegExp; variants: string[] })[] = [];\n\n colorNames.forEach((colorName) => {\n if (typeof colors[colorName] === \"object\") {\n // Handle nested color objects (with number keys)\n Object.keys(colors[colorName]).forEach((shade) => {\n utilities.forEach((utility) => {\n // Base utility\n safelist.push(`${utility}-${colorName}-${shade}`);\n\n // Variant utilities\n variants.forEach((variant) => {\n safelist.push(`${variant}${utility}-${colorName}-${shade}`);\n });\n });\n });\n } else {\n // Handle direct color values\n utilities.forEach((utility) => {\n safelist.push(`${utility}-${colorName}`);\n\n variants.forEach((variant) => {\n safelist.push(`${variant}${utility}-${colorName}`);\n });\n });\n }\n });\n\n // Generate typography classes\n Object.entries(typography).forEach(([family, sizes]) => {\n Object.keys(sizes).forEach((size) => {\n // Base typography classes\n safelist.push(`text-${family}-${size}`);\n\n // Add variants\n variants.forEach((variant) => {\n safelist.push(`${variant}text-${family}-${size}`);\n });\n });\n });\n\n const typographyClasses = Object.entries(typography).flatMap(\n ([category, sizes]) =>\n Object.keys(sizes).map((size) => `text-${category}-${size}`)\n );\n\n // Generate responsive variants\n const responsiveTypographyClasses = typographyClasses.flatMap((className) =>\n breakpoints.map((breakpoint) => `${breakpoint}:${className}`)\n );\n\n // Generate size classes with responsive variants\n const sizeClasses = sizes.flatMap((size) => [\n `h-[${size}px]`,\n `w-[${size}px]`,\n ...breakpoints.flatMap((bp) => [\n `${bp}:h-[${size}px]`,\n `${bp}:w-[${size}px]`\n ])\n ]);\n\n return [...typographyClasses, ...responsiveTypographyClasses, ...sizeClasses];\n};\n\nexport const focusRingStyles =\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-100\";\nexport const focusRingWithinStyles =\n \"focus-within:outline-none focus-within:ring-2 focus-within:ring-primary-100\";\nexport const focusRingStylesCoerced = \"ring-2 ring-primary-100\";\n","import type { ButtonHTMLAttributes } from \"react\";\nimport React from \"react\";\n\nimport { cn } from \"../utils\";\nimport { focusRingStyles } from \"../utils/tailwind\";\n\nexport type PressableProps = ButtonHTMLAttributes<HTMLButtonElement> & {\n /**\n * @default true\n * Scaling motion when pressed\n */\n scaleOnPress?: boolean;\n};\n\nexport const Pressable = React.forwardRef<HTMLButtonElement, PressableProps>(\n (\n {\n children,\n type = \"button\",\n className,\n disabled,\n scaleOnPress = true,\n ...props\n },\n ref\n ) => (\n <button\n ref={ref}\n type={type}\n disabled={disabled}\n className={cn(\n \"appearance-none hover:opacity-90\",\n focusRingStyles,\n disabled && \"opacity-50 cursor-not-allowed\",\n scaleOnPress && \"transition-all active:scale-95\",\n className\n )}\n {...props}\n >\n {children}\n </button>\n )\n);\n\nPressable.displayName = \"Pressable\";\n","import * as ScrollArea from \"@radix-ui/react-scroll-area\";\nimport React, {\n forwardRef,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState\n} from \"react\";\n\nimport { useMediaQuery } from \"../hooks/useMediaQuery\";\nimport { Icon } from \"./Icon\";\nimport { Pressable } from \"./Pressable\";\n\nexport type CarouselRef = {\n scroll: (direction: \"left\" | \"right\") => void;\n getScrollState: () => { canScrollLeft: boolean; canScrollRight: boolean };\n};\n\nexport type CarouselProps = {\n children: React.ReactNode;\n /** Optional className for the root element */\n className?: string;\n /** Optional gap between items in pixels */\n gap?: number;\n /** Optional minimum height for the carousel */\n minHeight?: string;\n /**\n * Optional boolean to show/hide paddles\n * @default true\n */\n showPaddles?: boolean;\n /** Optional callback when scroll state changes */\n onScrollStateChange?: (state: {\n canScrollLeft: boolean;\n canScrollRight: boolean;\n }) => void;\n};\n\nexport const Carousel = forwardRef<CarouselRef, CarouselProps>(\n (\n {\n children,\n className = \"\",\n gap = 20,\n minHeight,\n showPaddles = true,\n onScrollStateChange\n },\n ref\n ) => {\n const scrollContainerRef = useRef<HTMLDivElement>(null);\n const [showLeftPaddle, setShowLeftPaddle] = useState(false);\n const [showRightPaddle, setShowRightPaddle] = useState(false);\n const [isHoveringStart, setIsHoveringStart] = useState(false);\n const [isHoveringEnd, setIsHoveringEnd] = useState(false);\n const [touchStart, setTouchStart] = useState<number | null>(null);\n const [touchEnd, setTouchEnd] = useState<number | null>(null);\n const isMobile = useMediaQuery(\"(max-width: 768px)\");\n\n // Use a ref to store the previous scroll state to avoid unnecessary state updates\n const prevScrollStateRef = useRef<{\n canScrollLeft: boolean;\n canScrollRight: boolean;\n }>({ canScrollLeft: false, canScrollRight: false });\n\n const checkScrollPosition = useCallback(() => {\n const container = scrollContainerRef.current;\n if (!container) return;\n\n const { scrollLeft, scrollWidth, clientWidth } = container;\n const canScrollLeft = scrollLeft > 0;\n const canScrollRight = Math.ceil(scrollLeft + clientWidth) < scrollWidth;\n\n // Only update state if the values have changed\n if (\n prevScrollStateRef.current.canScrollLeft !== canScrollLeft ||\n prevScrollStateRef.current.canScrollRight !== canScrollRight\n ) {\n setShowLeftPaddle(canScrollLeft);\n setShowRightPaddle(canScrollRight);\n prevScrollStateRef.current = { canScrollLeft, canScrollRight };\n\n // Notify parent component of scroll state changes\n if (onScrollStateChange) {\n onScrollStateChange({ canScrollLeft, canScrollRight });\n }\n }\n }, [onScrollStateChange]);\n\n const handleMouseMove = useCallback(\n (e: React.MouseEvent) => {\n if (isMobile) return;\n\n const container = e.currentTarget;\n const rect = container.getBoundingClientRect();\n const mouseX = e.clientX - rect.left;\n const HOVER_THRESHOLD = 300;\n\n const newIsHoveringStart = mouseX < HOVER_THRESHOLD;\n const newIsHoveringEnd = mouseX > rect.width - HOVER_THRESHOLD;\n\n // Only update state if values have changed\n if (newIsHoveringStart !== isHoveringStart) {\n setIsHoveringStart(newIsHoveringStart);\n }\n if (newIsHoveringEnd !== isHoveringEnd) {\n setIsHoveringEnd(newIsHoveringEnd);\n }\n },\n [isMobile, isHoveringStart, isHoveringEnd]\n );\n\n // Handler for mouse leave - memoized to avoid recreating on every render\n const handleMouseLeave = useCallback(() => {\n setIsHoveringStart(false);\n setIsHoveringEnd(false);\n }, []);\n\n // Touch handling - for non-native scrolling behavior (swipe to snap)\n const handleTouchStart = useCallback((e: React.TouchEvent) => {\n setTouchStart(e.touches[0].clientX);\n setTouchEnd(null);\n }, []);\n\n const handleTouchMove = useCallback(\n (e: React.TouchEvent) => {\n setTouchEnd(e.touches[0].clientX);\n\n // Let native scrolling work on mobile - never prevent default\n // We'll use our own scrolling logic only when not on mobile\n if (\n !isMobile &&\n touchStart !== null &&\n Math.abs(touchStart - e.touches[0].clientX) > 10\n ) {\n e.preventDefault();\n }\n },\n [isMobile, touchStart]\n );\n\n const handleTouchEnd = useCallback(() => {\n if (!touchStart || !touchEnd) return;\n\n const container = scrollContainerRef.current;\n if (!container) return;\n\n const distance = touchStart - touchEnd;\n\n // Only use custom scrolling if it's a significant swipe\n // This allows for small drag movements to use native scrolling\n const minSwipeDistance = isMobile ? 30 : 50; // Reduced threshold for mobile\n\n if (Math.abs(distance) < minSwipeDistance) {\n return;\n }\n\n // Use 80% of container width for mobile for more natural feeling scrolling\n const scrollAmount = isMobile\n ? container.clientWidth * 0.8\n : container.clientWidth;\n\n const direction = distance > 0 ? 1 : -1;\n const targetScroll = container.scrollLeft + scrollAmount * direction;\n\n container.scrollTo({\n left: targetScroll,\n behavior: \"smooth\"\n });\n }, [touchStart, touchEnd, isMobile]);\n\n const handleTouchCancel = useCallback(() => {\n // Reset touch state when touch is canceled\n setTouchStart(null);\n setTouchEnd(null);\n }, []);\n\n const handleWheel = useCallback((e: WheelEvent) => {\n const container = scrollContainerRef.current;\n if (!container) return;\n\n // Check if the scroll is predominantly horizontal or if shift key is pressed\n const isHorizontalScroll = Math.abs(e.deltaX) > Math.abs(e.deltaY);\n if (!isHorizontalScroll && !e.shiftKey) return;\n\n e.preventDefault();\n\n // Determine the scroll amount based on the input type\n const scrollAmount = isHorizontalScroll ? e.deltaX : e.deltaY;\n\n // Apply smooth scrolling\n container.scrollBy({\n left: scrollAmount,\n behavior: \"smooth\"\n });\n }, []);\n\n useEffect(() => {\n const container = scrollContainerRef.current;\n if (!container) return;\n\n const observer = new ResizeObserver(checkScrollPosition);\n observer.observe(container);\n\n // Use passive listener for scroll events\n container.addEventListener(\"scroll\", checkScrollPosition, {\n passive: true\n });\n\n // Non-passive for wheel since we need to prevent default in some cases\n container.addEventListener(\"wheel\", handleWheel, { passive: false });\n\n // Initial check\n checkScrollPosition();\n\n return () => {\n observer.disconnect();\n container.removeEventListener(\"scroll\", checkScrollPosition);\n container.removeEventListener(\"wheel\", handleWheel);\n };\n }, [checkScrollPosition, handleWheel]);\n\n const scroll = useCallback(\n (direction: \"left\" | \"right\") => {\n const container = scrollContainerRef.current;\n if (!container) return;\n\n // Use 80% of container width for mobile for more natural feeling scrolling\n const scrollAmount = isMobile\n ? container.clientWidth * 0.8\n : container.clientWidth;\n\n const targetScroll =\n container.scrollLeft +\n (direction === \"left\" ? -scrollAmount : scrollAmount);\n\n container.scrollTo({\n left: targetScroll,\n behavior: \"smooth\"\n });\n },\n [isMobile]\n );\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === \"ArrowLeft\") {\n scroll(\"left\");\n } else if (e.key === \"ArrowRight\") {\n scroll(\"right\");\n }\n },\n [scroll]\n );\n\n // Memoize the scroll state to avoid recreating this object on every render\n const scrollState = useMemo(\n () => ({\n canScrollLeft: showLeftPaddle,\n canScrollRight: showRightPaddle\n }),\n [showLeftPaddle, showRightPaddle]\n );\n\n // Memoize the ref implementation\n React.useImperativeHandle(\n ref,\n () => ({\n scroll,\n getScrollState: () => scrollState\n }),\n [scroll, scrollState]\n );\n\n // Memoize the viewport style object to prevent unnecessary re-renders\n const viewportStyle = useMemo(\n () => ({\n scrollbarWidth: \"none\" as const,\n msOverflowStyle: \"none\" as const,\n WebkitOverflowScrolling: \"touch\" as const,\n touchAction: \"pan-x\" as const, // Always enable horizontal panning\n overflowX: \"auto\" as const, // Ensure this is always set\n minHeight,\n WebkitTapHighlightColor: \"transparent\" as const, // Remove tap highlight on mobile\n // Add cursor style for desktop to indicate scrollability\n cursor: isMobile ? \"default\" : \"grab\"\n }),\n [isMobile, minHeight]\n );\n\n // Memoize the gap style to prevent unnecessary re-renders\n const gapStyle = useMemo(() => ({ gap: `${gap}px` }), [gap]);\n\n // Memoize the children mapping to prevent unnecessary re-computation\n const mappedChildren = useMemo(\n () =>\n React.Children.map(children, (child) =>\n child === null ? null : (\n <div className=\"snap-start shrink-0\">{child}</div>\n )\n ),\n [children]\n );\n\n // Memoize paddle components for desktop\n const desktopPaddles = useMemo(() => {\n if (isMobile || !showPaddles) return null;\n\n return (\n <>\n {showLeftPaddle && isHoveringStart && (\n <Pressable\n onClick={() => scroll(\"left\")}\n className=\"absolute left-4 top-1/2 -translate-y-1/2 z-20 transition-opacity duration-200\"\n aria-label=\"Scroll left\"\n >\n <div className=\"flex items-center justify-center w-10 h-10 rounded-full bg-overlay backdrop-blur-sm\">\n <Icon name=\"arrow-left\" size={24} color=\"white\" />\n </div>\n </Pressable>\n )}\n\n {showRightPaddle && isHoveringEnd && (\n <Pressable\n onClick={() => scroll(\"right\")}\n className=\"absolute right-4 top-1/2 -translate-y-1/2 z-20 transition-opacity duration-200\"\n aria-label=\"Scroll right\"\n >\n <div className=\"flex items-center justify-center w-10 h-10 rounded-full bg-overlay backdrop-blur-sm\">\n <Icon name=\"arrow-right\" size={24} color=\"white\" />\n </div>\n </Pressable>\n )}\n </>\n );\n }, [\n isMobile,\n showPaddles,\n showLeftPaddle,\n showRightPaddle,\n isHoveringStart,\n isHoveringEnd,\n scroll\n ]);\n\n return (\n <div\n className={`relative group w-full max-w-full overflow-hidden ${className}`}\n onKeyDown={handleKeyDown}\n onMouseMove={handleMouseMove}\n onMouseLeave={handleMouseLeave}\n role=\"region\"\n aria-label=\"Carousel\"\n >\n <ScrollArea.Root\n className=\"overflow-hidden w-full max-w-full\"\n type=\"hover\"\n >\n <ScrollArea.Viewport\n ref={scrollContainerRef}\n className=\"w-full max-w-full overflow-x-auto snap-x snap-mandatory\"\n style={viewportStyle}\n onTouchStart={handleTouchStart}\n onTouchMove={handleTouchMove}\n onTouchEnd={handleTouchEnd}\n onTouchCancel={handleTouchCancel}\n data-testid=\"carousel-viewport\"\n >\n <div className=\"inline-flex w-max\" style={gapStyle}>\n {mappedChildren}\n </div>\n </ScrollArea.Viewport>\n </ScrollArea.Root>\n\n {/* Navigation Paddles - Only show on desktop */}\n {desktopPaddles}\n </div>\n );\n }\n);\n"]}
|