@alto-avios/alto-ui 5.2.0 → 5.4.0
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/assets/BannerSectionContent.css +1 -0
- package/dist/assets/BannerSectionPlectrum.css +1 -0
- package/dist/assets/Box.css +1 -1
- package/dist/assets/BoxLink.css +1 -0
- package/dist/assets/CalloutBanner.css +1 -1
- package/dist/assets/Carousel.css +1 -1
- package/dist/assets/CarouselButton.css +1 -1
- package/dist/assets/CategoryTileGroup.css +1 -0
- package/dist/assets/Input.css +1 -1
- package/dist/assets/IntroSection.css +1 -0
- package/dist/assets/Link.css +1 -1
- package/dist/assets/ProductTile.css +1 -0
- package/dist/assets/SelectCard.css +1 -1
- package/dist/assets/margin.css +1 -0
- package/dist/components/BannerSectionContent/BannerSectionContent.d.ts +31 -0
- package/dist/components/BannerSectionContent/BannerSectionContent.js +5 -0
- package/dist/components/BannerSectionContent/BannerSectionContent.js.map +1 -0
- package/dist/components/BannerSectionContent/index.d.ts +2 -0
- package/dist/components/BannerSectionContent/index.js +2 -0
- package/dist/components/BannerSectionContent/index.js.map +1 -0
- package/dist/components/BannerSectionPlectrum/BannerSectionPlectrum.d.ts +39 -0
- package/dist/components/BannerSectionPlectrum/BannerSectionPlectrum.js +9 -0
- package/dist/components/BannerSectionPlectrum/BannerSectionPlectrum.js.map +1 -0
- package/dist/components/BannerSectionPlectrum/index.d.ts +2 -0
- package/dist/components/BannerSectionPlectrum/index.js +2 -0
- package/dist/components/BannerSectionPlectrum/index.js.map +1 -0
- package/dist/components/Box/Box.d.ts +17 -6
- package/dist/components/Box/Box.js +2 -2
- package/dist/components/Box/Box.js.map +1 -1
- package/dist/components/BoxLink/BoxLink.d.ts +59 -0
- package/dist/components/BoxLink/BoxLink.js +3 -0
- package/dist/components/BoxLink/BoxLink.js.map +1 -0
- package/dist/components/BoxLink/BoxLinkContext.d.ts +24 -0
- package/dist/components/BoxLink/BoxLinkContext.js +2 -0
- package/dist/components/BoxLink/BoxLinkContext.js.map +1 -0
- package/dist/components/BoxLink/index.d.ts +4 -0
- package/dist/components/BoxLink/index.js +2 -0
- package/dist/components/BoxLink/index.js.map +1 -0
- package/dist/components/Button/Button.d.ts +1 -1
- package/dist/components/CalloutBanner/CalloutBanner.d.ts +2 -1
- package/dist/components/CalloutBanner/CalloutBanner.js +9 -9
- package/dist/components/CalloutBanner/CalloutBanner.js.map +1 -1
- package/dist/components/Carousel/Carousel.d.ts +29 -1
- package/dist/components/Carousel/Carousel.js +8 -8
- package/dist/components/Carousel/Carousel.js.map +1 -1
- package/dist/components/Carousel/CarouselButton/CarouselButton.d.ts +6 -0
- package/dist/components/Carousel/CarouselButton/CarouselButton.js +1 -1
- package/dist/components/Carousel/CarouselButton/CarouselButton.js.map +1 -1
- package/dist/components/Carousel/CarouselControls.js +1 -1
- package/dist/components/Carousel/CarouselControls.js.map +1 -1
- package/dist/components/Carousel/index.d.ts +2 -0
- package/dist/components/Carousel/index.js +1 -1
- package/dist/components/CategoryTileGroup/CategoryTileGroup.d.ts +52 -0
- package/dist/components/CategoryTileGroup/CategoryTileGroup.js +8 -0
- package/dist/components/CategoryTileGroup/CategoryTileGroup.js.map +1 -0
- package/dist/components/CategoryTileGroup/index.d.ts +2 -0
- package/dist/components/CategoryTileGroup/index.js +2 -0
- package/dist/components/CategoryTileGroup/index.js.map +1 -0
- package/dist/components/Checkbox/Checkbox.d.ts +1 -1
- package/dist/components/Checkbox/Checkbox.js +5 -5
- package/dist/components/Checkbox/Checkbox.js.map +1 -1
- package/dist/components/CreditCardNumberField/CreditCardNumberField.d.ts +2 -1
- package/dist/components/CreditCardNumberField/CreditCardNumberField.js +4 -4
- package/dist/components/CreditCardNumberField/CreditCardNumberField.js.map +1 -1
- package/dist/components/CreditCardSecurityCodeField/CreditCardSecurityCodeField.d.ts +1 -1
- package/dist/components/CreditCardSecurityCodeField/CreditCardSecurityCodeField.js +6 -6
- package/dist/components/CreditCardSecurityCodeField/CreditCardSecurityCodeField.js.map +1 -1
- package/dist/components/DatePicker/DatePicker.d.ts +1 -1
- package/dist/components/DatePicker/DatePicker.js +3 -3
- package/dist/components/DatePicker/DatePicker.js.map +1 -1
- package/dist/components/DateRangePicker/DateRangePicker.d.ts +1 -1
- package/dist/components/DateRangePicker/DateRangePicker.js +6 -6
- package/dist/components/DateRangePicker/DateRangePicker.js.map +1 -1
- package/dist/components/FieldHeader/FieldHeader.d.ts +1 -1
- package/dist/components/FieldHeader/FieldHeader.js +2 -2
- package/dist/components/FieldHeader/FieldHeader.js.map +1 -1
- package/dist/components/Form/Form.d.ts +1 -1
- package/dist/components/Form/Form.js +1 -1
- package/dist/components/Form/Form.js.map +1 -1
- package/dist/components/Heading/Heading.js +2 -2
- package/dist/components/Heading/Heading.js.map +1 -1
- package/dist/components/IntroSection/IntroSection.d.ts +42 -0
- package/dist/components/IntroSection/IntroSection.js +4 -0
- package/dist/components/IntroSection/IntroSection.js.map +1 -0
- package/dist/components/IntroSection/index.d.ts +2 -0
- package/dist/components/IntroSection/index.js +2 -0
- package/dist/components/IntroSection/index.js.map +1 -0
- package/dist/components/Label/Label.js +1 -1
- package/dist/components/Label/Label.js.map +1 -1
- package/dist/components/Link/Link.js +2 -3
- package/dist/components/Link/Link.js.map +1 -1
- package/dist/components/Menu/Menu.d.ts +4 -4
- package/dist/components/Menu/Menu.js +1 -1
- package/dist/components/Menu/Menu.js.map +1 -1
- package/dist/components/Paragraph/Paragraph.js +1 -1
- package/dist/components/Paragraph/Paragraph.js.map +1 -1
- package/dist/components/Popover/Popover.d.ts +1 -1
- package/dist/components/Popover/Popover.js.map +1 -1
- package/dist/components/ProductTile/ProductTile.d.ts +51 -0
- package/dist/components/ProductTile/ProductTile.js +7 -0
- package/dist/components/ProductTile/ProductTile.js.map +1 -0
- package/dist/components/ProductTile/index.d.ts +2 -0
- package/dist/components/ProductTile/index.js +2 -0
- package/dist/components/ProductTile/index.js.map +1 -0
- package/dist/components/Radio/Radio.d.ts +1 -1
- package/dist/components/Radio/Radio.js +1 -1
- package/dist/components/Radio/Radio.js.map +1 -1
- package/dist/components/SearchField/SearchField.d.ts +2 -1
- package/dist/components/SearchField/SearchField.js +4 -4
- package/dist/components/SearchField/SearchField.js.map +1 -1
- package/dist/components/Section/Section.d.ts +9 -1
- package/dist/components/Section/Section.js +3 -3
- package/dist/components/Section/Section.js.map +1 -1
- package/dist/components/SelectCard/SelectCard.d.ts +18 -9
- package/dist/components/SelectCard/SelectCard.js +5 -5
- package/dist/components/SelectCard/SelectCard.js.map +1 -1
- package/dist/components/Slider/Slider.d.ts +1 -1
- package/dist/components/Slider/Slider.js +12 -12
- package/dist/components/Slider/Slider.js.map +1 -1
- package/dist/components/SubHeading/SubHeading.js +1 -1
- package/dist/components/SubHeading/SubHeading.js.map +1 -1
- package/dist/components/_base/Input/Input.js +8 -8
- package/dist/components/index.d.ts +16 -2
- package/dist/components/index.js +1 -1
- package/dist/{flex-BJOhaXnU.js → flex-BfhdHBb6.js} +2 -2
- package/dist/flex-BfhdHBb6.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/margin-CCJx_ENX.js +2 -0
- package/dist/margin-CCJx_ENX.js.map +1 -0
- package/dist/useObjectRef-DIiuqtNU.js +2 -0
- package/dist/useObjectRef-DIiuqtNU.js.map +1 -0
- package/dist/utils/flex/flex.d.ts +20 -6
- package/dist/utils/flex/flex.js +1 -1
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.js +1 -1
- package/dist/utils/layout/hooks/useFitCount.d.ts +74 -0
- package/dist/utils/layout/hooks/useFitCount.js +2 -0
- package/dist/utils/layout/hooks/useFitCount.js.map +1 -0
- package/dist/utils/margin/margin.d.ts +13 -0
- package/dist/utils/margin/margin.js +2 -0
- package/dist/utils/margin/margin.js.map +1 -0
- package/dist/utils/margin/margin.test.d.ts +1 -0
- package/dist/utils/position/position.d.ts +1 -1
- package/dist/utils/stories/DraggableContainer.js +7 -7
- package/dist/utils/stories/DraggableContainer.js.map +1 -1
- package/dist/utils/stories/IntroSectionWithCategoryTileGroup.d.ts +3 -0
- package/dist/utils/stories/IntroSectionWithCategoryTileGroup.js +5 -0
- package/dist/utils/stories/IntroSectionWithCategoryTileGroup.js.map +1 -0
- package/package.json +4 -2
- package/dist/assets/truncate.css +0 -1
- package/dist/flex-BJOhaXnU.js.map +0 -1
- package/dist/utils/truncate/truncate.d.ts +0 -6
- package/dist/utils/truncate/truncate.js +0 -2
- package/dist/utils/truncate/truncate.js.map +0 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import{jsx as e,jsxs as t}from"react/jsx-runtime";import
|
|
2
|
-
return e("div",{className:(()=>{const e=[
|
|
3
|
-
/* @__PURE__ */e(
|
|
4
|
-
return e(
|
|
5
|
-
/* @__PURE__ */t("div",{className:`${
|
|
6
|
-
/* @__PURE__ */e(
|
|
7
|
-
/* @__PURE__ */e(
|
|
8
|
-
/* @__PURE__ */e("div",{className:
|
|
1
|
+
import{jsx as e,jsxs as t}from"react/jsx-runtime";import r,{useRef as n,useState as a,useCallback as o,useEffect as i}from"react";import{c as s}from"../../index-CCUt_dAN.js";import{C as l,a as u,b as c,c as d,d as m}from"../../IconButton.module-C7YCy-MU.js";import{CarouselButton as f}from"./CarouselButton/CarouselButton.js";import{CarouselDots as h}from"./CarouselDots/CarouselDots.js";import{AutoplayControl as p}from"./AutoplayControl/AutoplayControl.js";import{focusStyleVariants as v}from"../../utils/focus/focusStyles.js";import{useFocusRing as y}from"@react-aria/focus";import{resolveResponsiveProp as g}from"../../utils/breakpoint/responsive.js";import{useBreakpoint as b}from"../../utils/breakpoint/hooks/useBreakpoint.js";import '../../assets/Carousel.css';const w={carouselWrapper:"_carouselWrapper_1uhyq_2",showPartialItems:"_showPartialItems_1uhyq_14",carousel:"_carousel_1uhyq_2",hasScrollPadding:"_hasScrollPadding_1uhyq_25",scroller:"_scroller_1uhyq_43",item:"_item_1uhyq_78",slideLeft:"_slideLeft_1uhyq_127",slideRight:"_slideRight_1uhyq_131",controls:"_controls_1uhyq_154",defaultPrevButton:"_defaultPrevButton_1uhyq_165",defaultNextButton:"_defaultNextButton_1uhyq_173",defaultDotsContainer:"_defaultDotsContainer_1uhyq_182",defaultCarouselWrapper:"_defaultCarouselWrapper_1uhyq_193",defaultAutoplayControl:"_defaultAutoplayControl_1uhyq_200",showOnHover:"_showOnHover_1uhyq_209",hidden:"_hidden_1uhyq_219",hiddenTabs:"_hiddenTabs_1uhyq_250",autoplayControlWrapper:"_autoplayControlWrapper_1uhyq_268"},_=s(w.carousel,{variants:{looping:{infinite:w.infinite,backToStart:w.native,off:void 0}}}),C=({children:s=[],"aria-label":C,"aria-describedby":x,looping:N="off",itemsPerPage:A=1,spaceBetweenItems:S=0,scrollPadding:P,iconType:q="chevron",arrowStyleVariant:L="neutral",arrowSize:M="md",hideDisabledArrow:E=!1,showArrowsOnHover:T=!1,focusStyle:D="default",dotsSize:$="md",dotsVariant:I="standard",hideDots:k=!1,autoPlay:B=!1,autoPlayInterval:W=2e3,autoPlayStyleVariant:j="neutralVibrant",autoPlayControlSize:z="md",mouseDragging:R=!0,carouselWrapperClassName:F="",prevArrowClassName:H="",nextArrowClassName:O="",autoplayControlClassName:V="",dotsContainerClassName:Y="",dotsWrapperClassName:X="",dotClassName:G="",activeDotClassName:K="",itemWrapperClassName:J="",scrollerClassName:Q="",activeItemClassName:U="",onArrowPress:Z,onDotPress:ee,onAutoplayPress:te,controlsRef:re,onNavigationStateChange:ne})=>{const ae=r.Children.toArray(s),oe=ae.length,ie=b(),se=g(A,ie)??1,le=g(S,ie)??0,ue=g(P,ie)??void 0,ce=g(M,ie)??"md",de=g(k,ie)??!1,me=Math.max(1,se),fe=Math.max(1,Math.floor(me)),he=r.useMemo(()=>{const e=Array.from({length:oe},(e,t)=>t).reduce((e,t)=>{const r=e.at(-1);return r&&r.length<fe?r.push(t):e.push([t]),e},[]);if(e.length>=2){const t=fe-e.at(-1).length;if(t>0){const r=[...e.at(-2)].splice(fe-t);e.at(-1).unshift(...r)}}return e},[oe,fe]),pe=n(null),ve=n(null),ye=n(null),ge=n(null),be=n(null),we=n([]),[_e,Ce]=a(0),[xe,Ne]=a(0),[Ae,Se]=a(!1),[Pe,qe]=a(he.length>1),[Le,Me]=a(0),[Ee,Te]=a(0),[De,$e]=a(!1),[Ie,ke]=a(!1),[Be,We]=a(!1),[je]=a(!1),[ze,Re]=a(null),Fe="infinite"===N?"infinite":"backToStart"===N?"native":"off"!==N?N:void 0,He=Le>0?Le:he.length,Oe=!de&&He>1,Ve=(e,t)=>e||t,Ye=o(()=>pe.current?.querySelector('[data-carousel-scroller="true"]'),[]),Xe=o((e,t)=>{const r=t*Math.max(1,Math.floor(me)),n=e.querySelector(`[data-item-index="${r}"]`);if(!n)return!1;const a=e.getBoundingClientRect(),o=n.getBoundingClientRect(),i=e.scrollLeft+(o.left-a.left);return e.scrollTo({left:i,behavior:"smooth"}),!0},[me]),Ge=o(e=>{if(!(e===_e||e<0||e>=He)&&pe.current){const t=pe.current.querySelector(`[data-slide-tab="true"][data-index="${e}"]`);t&&(t.click(),Ne(_e),Ce(e))}},[_e,He]),Ke=o(()=>{if(!pe.current||He<=1)return;const e=pe.current.querySelector('[data-carousel-scroller="true"]');if(!e)return;const t=Array.from(e.querySelectorAll("[data-item-index]"));if(!t.length)return;const r=e.getBoundingClientRect().left;let n=0,a=Number.POSITIVE_INFINITY;t.forEach(e=>{const t=parseInt(e.dataset.itemIndex??"",10);if(Number.isNaN(t))return;const o=Math.abs(e.getBoundingClientRect().left-r);o<a&&(a=o,n=t)});const o=Math.max(1,Math.floor(me)),i=Math.min(He-1,Math.floor(n/o));i!==_e&&(Ne(_e),Ce(i))},[_e,me,He]),Je=o(()=>{const e=Ye();if(e){const t=Math.max(0,_e-1);return Xe(e,t)||e.scrollBy({left:-e.clientWidth,behavior:"smooth"}),Ne(_e),Ce(t),void window.setTimeout(()=>{Ke()},200)}_e<=0||Ge(_e-1)},[_e,Ye,Ge,Xe,Ke]),Qe=o(()=>{const e=Ye();if(e){const t=Math.min(He-1,_e+1);return Xe(e,t)||e.scrollBy({left:e.clientWidth,behavior:"smooth"}),Ne(_e),Ce(t),void window.setTimeout(()=>{Ke()},200)}_e>=He-1||Ge(_e+1)},[_e,Ye,Ge,Xe,Ke,He]);i(()=>{const e=((e,t)=>({canGoPrev:e>0,canGoNext:e<t-1,currentPage:e,totalPages:t}))(_e,He);if(re)return re.current={prev:Je,next:Qe,goToSlide:Ge,...e},ne?.(e),()=>{re.current&&(re.current=null)};ne?.(e)},[re,_e,Qe,Je,Ge,ne,He]),i(()=>()=>{null!==ye.current&&window.clearTimeout(ye.current),null!==ge.current&&window.clearTimeout(ge.current)},[]),i(()=>{if(!pe.current||!R)return;const e=e=>{if(!De)return;const t=e.target;if(!(t instanceof Element))return;t.closest("a[href]")&&(e.preventDefault(),e.stopPropagation(),setTimeout(()=>{$e(!1)},0))},t=e=>{Re({x:e.clientX,y:e.clientY})},r=e=>{if(null===ze)return;const t=Math.abs(e.clientX-ze.x),r=Math.abs(e.clientY-ze.y);Math.sqrt(t*t+r*r)>5&&$e(!0)},n=()=>{De?setTimeout(()=>{$e(!1),Re(null)},50):Re(null)},a=pe.current;return a.addEventListener("mousedown",t,!0),a.addEventListener("mousemove",r,!0),a.addEventListener("mouseup",n,!0),a.addEventListener("click",e,!0),()=>{a.removeEventListener("mousedown",t,!0),a.removeEventListener("mousemove",r,!0),a.removeEventListener("mouseup",n,!0),a.removeEventListener("click",e,!0)}},[R,De,ze,5]),i(()=>{if(pe.current){const e=pe.current.querySelector(`.${w.scroller}`);e&&e instanceof HTMLElement&&(xe<_e?(e.classList.remove(w.slideLeft),e.classList.add(w.slideRight)):xe>_e&&(e.classList.remove(w.slideRight),e.classList.add(w.slideLeft)))}},[_e,xe]),i(()=>{const e=pe.current;if(!e)return;let t=null;const r=()=>{null===t&&(t=window.requestAnimationFrame(()=>{t=null,(()=>{const t=e.querySelectorAll('[data-slide-tab="true"]').length;Me(e=>e===t?e:t)})()}))},n=new MutationObserver(()=>{r()});return n.observe(e,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["data-slide-tab"]}),r(),()=>{null!==t&&window.cancelAnimationFrame(t),n.disconnect()}},[oe,me]),i(()=>{const e=be.current;if(!e)return;let t=null;const r=()=>{null===t&&(t=window.requestAnimationFrame(()=>{t=null,n()}))},n=()=>{const t=Math.max(0,e.scrollWidth-e.clientWidth),r=e.scrollLeft,n=t>1,a=n?r>1:_e>0,o=n?r<t-1:_e<He-1,i=we.current.length>0?we.current:Array.from(e.querySelectorAll("[data-item-index]"));0===we.current.length&&(we.current=i);const s=r+1,l=i.find(e=>e.offsetLeft+e.offsetWidth>s)?.dataset.itemIndex??"0",u=parseInt(l,10),c=Number.isNaN(u)?0:u,d=Math.max(1,Math.ceil(me)),m=c+d-1;i.forEach(e=>{const t=e.dataset.itemIndex;if("string"!=typeof t)return;const r=parseInt(t,10);if(Number.isNaN(r))return;r>=c&&r<=m?(e.removeAttribute("inert"),e.removeAttribute("aria-hidden")):(e.setAttribute("inert","true"),e.setAttribute("aria-hidden","true"))});const f=he.map(e=>e[0]).reduce((e,t,r)=>t<=c?r:e,0),h=n?f:_e;Se(e=>e===a?e:a),qe(e=>e===o?e:o),Te(e=>e===c?e:c),Ce(e=>(e!==h&&Ne(e),e===h?e:h))},a=new ResizeObserver(()=>{r()});a.observe(e);(()=>{const t=Array.from(e.querySelectorAll("[data-item-index]"));return we.current=t,t})().forEach(e=>{a.observe(e)});const o=()=>{r()};return e.addEventListener("load",o,!0),n(),e.addEventListener("scroll",n,{passive:!0}),window.addEventListener("resize",r),()=>{null!==t&&window.cancelAnimationFrame(t),a.disconnect(),e.removeEventListener("load",o,!0),e.removeEventListener("scroll",n),window.removeEventListener("resize",r),we.current=[]}},[_e,he,me,He,oe]);const Ue=T?{onMouseEnter:()=>ke(!0),onMouseLeave:()=>ke(!1),onFocus:()=>We(!0),onBlur:e=>{e.currentTarget.contains(e.relatedTarget)||We(!1)}}:{},Ze=He>1&&(!T||Ie||Be),et=(()=>{const e={};return 1!==se&&(e["--items-per-page"]=String(me)),le>0&&(e["--space-between-items"]=`${le}px`),ue&&(e["--scroll-padding"]=ue),Object.keys(e).length>0?e:void 0})(),{focusProps:tt,isFocusVisible:rt}=y(),nt=he[_e]??[];/* @__PURE__ */
|
|
2
|
+
return e("div",{className:(()=>{const e=[w.carouselWrapper];return Number.isInteger(me)||e.push(w.showPartialItems),ue&&e.push(w.hasScrollPadding),F&&F.trim()?e.push(F):e.push(w.defaultCarouselWrapper),e.join(" ")})(),ref:pe,style:et,"data-dots-size":$,...Ue,"data-arrows-visible":Ze?"true":"false","data-transitioning":je?"true":void 0,"data-scroll-padding":ue,role:"region","aria-label":(()=>{if(C)return C;return`Carousel with ${oe} items, currently showing slide ${_e+1} of ${He}${B?", autoplay enabled":""}`})(),"aria-describedby":x,"aria-roledescription":"carousel",children:/* @__PURE__ */t(l,{className:`${_({looping:N})}`,loop:Fe,ref:ve,autoplay:B,autoplayInterval:W,mouseDragging:R&&!je,onActivePageIndexChange:({index:e})=>{Ce(t=>(t!==e&&Ne(t),e))},onDragStart:e=>{$e(!0),e&&e.nativeEvent&&Re({x:e.nativeEvent.clientX,y:e.nativeEvent.clientY})},onDragEnd:()=>{null!==ye.current&&window.clearTimeout(ye.current),null!==ge.current&&window.clearTimeout(ge.current),ye.current=window.setTimeout(()=>{$e(!1),Ke()},50),ge.current=window.setTimeout(()=>{Ke()},150)},"data-dragging":De?"true":"false",itemsPerPage:me,scrollPadding:ue,"data-has-space-between":le>0?"true":void 0,"data-items-per-page":1!==se?me.toString():void 0,children:[
|
|
3
|
+
/* @__PURE__ */e(u,{className:`${w.scroller} ${v({focusStyle:D})} ${Q}`.trim(),ref:be,...tt,"data-focused":!!rt||void 0,"data-focus-visible":!!rt||void 0,"data-transitioning":je?"true":void 0,style:(()=>{const e={};if(le>=0&&(e.gap=`${le}px`),se>1&&le>0){const t=le*(me-1)/me;e.gridAutoColumns=`calc(${100/me}% - ${t}px)`}else se>1&&(e.gridAutoColumns=100/me+"%");return e})(),tabIndex:0,role:"region","aria-label":"Carousel content",onKeyDown:e=>{if("ArrowLeft"===e.key){e.preventDefault();const t=pe.current?.querySelector('[dir="prev"]');t&&!t.disabled&&t.click()}else if("ArrowRight"===e.key){e.preventDefault();const t=pe.current?.querySelector('[dir="next"]');t&&!t.disabled&&t.click()}else"Home"===e.key?(e.preventDefault(),Ge(0)):"End"===e.key&&(e.preventDefault(),Ge(He-1))},children:ae.map((t,r)=>{const n=nt.includes(r),a=[J||"",w.item,n&&U?U:""].filter(Boolean).join(" ");/* @__PURE__ */
|
|
4
|
+
return e(c,{className:a,"data-is-active":n?"true":void 0,"data-item-index":r,"aria-label":`Slide ${r+1} of ${oe}`,children:t},r)})}),
|
|
5
|
+
/* @__PURE__ */t("div",{className:`${w.controls} ${T?w.showOnHover:""}`,children:[
|
|
6
|
+
/* @__PURE__ */e(f,{dir:"prev",variant:L,size:ce,focusStyle:D,iconType:q,hideDisabledArrow:E,overrideHideDisabledArrow:Fe?void 0:!Ae,onClick:Fe?void 0:()=>Ge(Ae?Ee<=0?0:Math.max(0,Math.ceil(Ee/fe)-1):_e),onPress:()=>Z?.("prev"),className:`${Ve(H,w.defaultPrevButton)} ${Ze?"":w.hidden}`}),
|
|
7
|
+
/* @__PURE__ */e(f,{dir:"next",variant:L,size:ce,focusStyle:D,iconType:q,hideDisabledArrow:E,overrideHideDisabledArrow:Fe?void 0:!Pe,onClick:Fe?void 0:()=>Ge(Pe?Math.min(He-1,Math.floor(Ee/fe)+1):_e),onPress:()=>Z?.("next"),className:`${Ve(O,w.defaultNextButton)} ${Ze?"":w.hidden}`})]}),
|
|
8
|
+
/* @__PURE__ */e("div",{className:w.hiddenTabs,children:/* @__PURE__ */e(d,{children:t=>/* @__PURE__ */e(m,{index:t.index,"data-index":t.index,"data-slide-tab":"true",tabIndex:-1},t.index)})}),B&&/* @__PURE__ */e("div",{className:`${w.autoplayControlWrapper} ${Ve(V,w.defaultAutoplayControl)}`,children:/* @__PURE__ */e(p,{variant:j,size:z,className:"",onPress:te})}),Oe&&/* @__PURE__ */e(h,{totalItems:He,currentPage:_e,onDotClick:e=>Ge(e),onPress:ee,focusStyle:D,dotsSize:$,variant:I,className:Ve(Y,w.defaultDotsContainer),dotsWrapperClassName:X,dotClassName:G,activeDotClassName:K,isTransitioning:je})]})})};export{C as Carousel,C as default};
|
|
9
9
|
//# sourceMappingURL=Carousel.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Carousel.js","sources":["../../../src/components/Carousel/Carousel.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect } from 'react';\nimport { cva } from 'class-variance-authority';\nimport {\n Carousel as AriaCarousel,\n CarouselScroller as AriaCarouselScroller,\n CarouselItem as AriaCarouselItem,\n CarouselTabs as AriaCarouselTabs,\n CarouselTab as AriaCarouselTab,\n} from 'react-aria-carousel';\nimport styles from './Carousel.module.css';\nimport { CarouselButton } from './CarouselButton/CarouselButton';\nimport { CarouselDots } from './CarouselDots/CarouselDots';\nimport { AutoplayControl } from './AutoplayControl/AutoplayControl';\nimport { focusStyleVariants } from '../../utils/focus/focusStyles';\nimport { useFocusRing } from '@react-aria/focus';\n\nimport {\n WithResponsive,\n resolveResponsiveProp,\n} from '../../utils/breakpoint/responsive';\nimport { useBreakpoint } from '../../utils/breakpoint/hooks/useBreakpoint';\n\nconst carousel = cva(styles.carousel, {\n variants: {\n looping: {\n infinite: styles.infinite,\n backToStart: styles.native,\n off: undefined,\n },\n },\n});\n\nexport interface CarouselBaseProps {\n /**\n * Content to be displayed in the carousel\n */\n children?: React.ReactNode | React.ReactNode[];\n\n /**\n * Accessible name for the carousel\n * Describes the purpose or content of the carousel for screen readers\n * @example \"Featured products\" or \"Customer testimonials\"\n */\n 'aria-label'?: string;\n\n /**\n * ID of an element that provides additional description for the carousel\n * Can reference an element that gives more context about the carousel's content\n * @example \"carousel-description\"\n */\n 'aria-describedby'?: string;\n\n /**\n * Looping behavior\n * - 'infinite': Carousel loops continuously\n * - 'backToStart': Carousel loops back to start after reaching end\n * - 'off': Looping is disabled\n * @default 'off'\n */\n looping?: 'infinite' | 'backToStart' | 'off';\n\n /**\n * Number of items to display per page (minimum: 1)\n * Decimal values (e.g., 2.25) can be used to show partial items\n * @default 1\n * @min 1\n */\n itemsPerPage?: number;\n\n /**\n * Space between carousel items in pixels\n * @default 0\n */\n spaceBetweenItems?: number;\n\n /**\n * Amount of padding added to the scroll container to create a \"peek\" effect.\n * This shows a portion of the adjacent items.\n * Accepts any valid CSS dimension (px, rem, em, %) - e.g., \"15%\", \"20px\", \"2rem\"\n * @example \"15%\" or \"20px\" or \"2rem\"\n * @default undefined\n */\n scrollPadding?: string;\n\n /* Button and Controls Props */\n /**\n * Icon type for navigation buttons\n * @default 'chevron'\n */\n iconType?: 'chevron';\n\n /**\n * Style of carousel arrow buttons\n * @default 'neutral'\n */\n arrowStyleVariant?:\n | 'neutral'\n | 'white'\n | 'shapeFlat'\n | 'shapeElevated'\n | 'gradient';\n\n /**\n * Size of navigation buttons\n * @default 'md'\n */\n arrowSize?: 'sm' | 'md' | 'lg';\n\n /**\n * Whether to hide navigation buttons when disabled\n * Note: Navigation buttons are automatically hidden when all items fit on one page\n * @default false\n */\n hideDisabledArrow?: boolean;\n\n /**\n * Whether to show arrows only when hovering over the carousel or when it has focus\n * @default false\n */\n showArrowsOnHover?: boolean;\n\n /**\n * Focus style for interactive elements\n * @default 'default'\n */\n focusStyle?: 'default' | 'white';\n\n /* Dots/Tabs Props */\n /**\n * Size of pagination dots\n * @default 'md'\n */\n dotsSize?: 'md' | 'lg';\n\n /**\n * Visual style of pagination dots\n * @default 'standard'\n */\n dotsVariant?: 'standard' | 'transparent';\n\n /**\n * Whether to hide pagination dots\n * Note: Dots are automatically hidden when there's only one page\n * @default false\n */\n hideDots?: boolean;\n\n /* Autoplay Props */\n /**\n * Whether the autoplay is enabled\n * @default false\n */\n autoPlay?: boolean;\n\n /**\n * Interval in milliseconds between slides during autoplay\n * @default 2000\n */\n autoPlayInterval?: number;\n\n /**\n * Style variant for autoplay control button\n * @default 'neutralVibrant'\n */\n autoPlayStyleVariant?:\n | 'neutralVibrant'\n | 'neutralSubtle'\n | 'whiteVibrant'\n | 'whiteSubtle';\n\n /**\n * Size of autoplay control button\n * @default 'md'\n */\n autoPlayControlSize?: 'sm' | 'md';\n\n /**\n * Whether to enable mouse dragging for the carousel\n * @default true\n */\n mouseDragging?: boolean;\n\n /* Custom Class Names for Positioning and Styling */\n /**\n * Class name for the outermost wrapper of the carousel\n */\n carouselWrapperClassName?: string;\n\n /**\n * Class name for the previous button\n * Use this to position the previous button\n */\n prevArrowClassName?: string;\n\n /**\n * Class name for the next button\n * Use this to position the next button\n */\n nextArrowClassName?: string;\n\n /**\n * Class name for the autoplay control\n * Use this to position the autoplay button\n */\n autoplayControlClassName?: string;\n\n /**\n * Class name for the dots container\n * Use this to position the pagination dots\n */\n dotsContainerClassName?: string;\n\n /**\n * Class name for the dots wrapper\n * Use this to style the dots wrapper\n */\n dotsWrapperClassName?: string;\n\n /**\n * Class name for individual dots\n */\n dotClassName?: string;\n\n /**\n * Class name for the active dot\n */\n activeDotClassName?: string;\n\n /**\n * Class name for individual carousel item wrappers\n * Use this to style the wrapper div around each carousel item\n */\n itemWrapperClassName?: string;\n\n /**\n * Class name for the currently active/visible carousel item\n * This class is applied to the item that corresponds to the current page\n */\n activeItemClassName?: string;\n\n /**\n * Callback fired when a carousel navigation button (prev/next) is pressed\n */\n onArrowPress?: (direction: 'prev' | 'next') => void;\n\n /**\n * Callback fired when a dot is pressed\n */\n onDotPress?: (index: number) => void;\n\n /**\n * Callback fired when the autoplay button is pressed\n */\n onAutoplayPress?: (state: 'play' | 'pause') => void;\n}\n\ntype ResponsiveKeys =\n | 'itemsPerPage'\n | 'spaceBetweenItems'\n | 'scrollPadding'\n | 'showArrowsOnHover'\n | 'arrowSize'\n | 'hideDots';\n\nexport type CarouselProps = WithResponsive<CarouselBaseProps, ResponsiveKeys>;\n\nexport const Carousel = ({\n children = [],\n 'aria-label': ariaLabel,\n 'aria-describedby': ariaDescribedby,\n looping = 'off',\n itemsPerPage = 1,\n spaceBetweenItems = 0,\n scrollPadding,\n\n // Button and Controls Props\n iconType = 'chevron',\n arrowStyleVariant = 'neutral',\n arrowSize = 'md',\n hideDisabledArrow = false,\n showArrowsOnHover = false,\n focusStyle = 'default',\n\n // Dots/Tabs Props\n dotsSize = 'md',\n dotsVariant = 'standard',\n hideDots = false,\n\n // Autoplay Props\n autoPlay = false,\n autoPlayInterval = 2000,\n autoPlayStyleVariant = 'neutralVibrant',\n autoPlayControlSize = 'md',\n\n // Mouse Dragging\n mouseDragging = true,\n\n // Custom Class Names\n carouselWrapperClassName = '',\n prevArrowClassName = '',\n nextArrowClassName = '',\n autoplayControlClassName = '',\n dotsContainerClassName = '',\n dotsWrapperClassName = '',\n dotClassName = '',\n activeDotClassName = '',\n itemWrapperClassName = '',\n activeItemClassName = '',\n\n // Event Callbacks\n onArrowPress,\n onDotPress,\n onAutoplayPress,\n}: CarouselProps) => {\n // Map looping values to expected loop values for AriaCarousel\n const getLoopValue = () => {\n if (looping === 'infinite') return 'infinite';\n if (looping === 'backToStart') return 'native';\n if (looping === 'off') return undefined;\n return looping; // other values pass through\n };\n\n const items = React.Children.toArray(children);\n const totalItems = items.length;\n\n const breakpoint = useBreakpoint();\n const resolvedItemsPerPage =\n resolveResponsiveProp(itemsPerPage, breakpoint) ?? 1;\n const resolvedSpaceBetweenItems =\n resolveResponsiveProp(spaceBetweenItems, breakpoint) ?? 0;\n const resolvedScrollPadding =\n resolveResponsiveProp(scrollPadding, breakpoint) ?? undefined;\n const resolvedArrowSize =\n resolveResponsiveProp(arrowSize, breakpoint) ?? 'md';\n const resolvedHideDots = resolveResponsiveProp(hideDots, breakpoint) ?? false;\n\n // Ensure itemsPerPage is at least 1\n // We allow decimal values for showing partial items\n const safeItemsPerPage = Math.max(1, resolvedItemsPerPage);\n\n // Calculate total pages based on items per page\n const totalPages = Math.ceil(totalItems / safeItemsPerPage);\n\n // Determine if dots should be shown\n // Hide dots if:\n // 1. resolvedHideDots prop is true (responsive), OR\n // 2. There's only one page (totalPages <= 1)\n const shouldShowDots = !resolvedHideDots && totalPages > 1;\n\n const carouselRef = useRef<HTMLDivElement>(null);\n const ariaCarouselRef = useRef<HTMLDivElement>(null);\n\n const [currentPage, setCurrentPage] = useState(0);\n const [prevPage, setPrevPage] = useState(0);\n const [isDragging, setIsDragging] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n const [isFocused, setIsFocused] = useState(false);\n const [isTransitioning] = useState(false);\n\n // Add state variables for drag/link handling\n const [dragStartPosition, setDragStartPosition] = useState<{\n x: number;\n y: number;\n } | null>(null);\n const dragThreshold = 5; // Pixels of movement needed to consider as a drag\n\n // Helper function to get class names with defaults\n const getClassNameWithDefault = (\n customClassName: string,\n defaultClassName: string,\n ): string => {\n return customClassName || defaultClassName;\n };\n\n // Get CSS classes based on showing partial items\n const getCarouselWrapperClasses = () => {\n const classes = [styles.carouselWrapper];\n\n if (!Number.isInteger(safeItemsPerPage)) {\n classes.push(styles.showPartialItems);\n }\n\n if (resolvedScrollPadding) {\n classes.push(styles.hasScrollPadding);\n }\n\n // Apply default wrapper class if no custom wrapper class is provided\n if (carouselWrapperClassName && carouselWrapperClassName.trim()) {\n classes.push(carouselWrapperClassName);\n } else {\n classes.push(styles.defaultCarouselWrapper);\n }\n\n return classes.join(' ');\n };\n\n // Determine if we need to set CSS variables and return only what's needed\n const getCssVariables = () => {\n const cssVars: Record<string, string> = {};\n\n // Only set these if they differ from defaults\n if (resolvedItemsPerPage !== 1) {\n cssVars['--items-per-page'] = String(safeItemsPerPage);\n }\n\n if (resolvedSpaceBetweenItems > 0) {\n cssVars['--space-between-items'] = `${resolvedSpaceBetweenItems}px`;\n }\n\n if (resolvedScrollPadding) {\n cssVars['--scroll-padding'] = resolvedScrollPadding;\n }\n\n return Object.keys(cssVars).length > 0 ? cssVars : undefined;\n };\n\n // Helper function to determine which items are currently active/visible\n const getActiveItemIndices = () => {\n const startIndex = currentPage * Math.floor(safeItemsPerPage);\n const endIndex = Math.min(\n startIndex + Math.ceil(safeItemsPerPage),\n totalItems,\n );\n\n const activeIndices: number[] = [];\n for (let i = startIndex; i < endIndex; i++) {\n activeIndices.push(i);\n }\n\n return activeIndices;\n };\n\n const navigateToSlide = (index: number) => {\n if (index === currentPage || index < 0 || index >= totalPages) {\n return;\n }\n\n // Find and click the corresponding hidden tab\n if (carouselRef.current) {\n const targetTab = carouselRef.current.querySelector(\n `[data-slide-tab=\"true\"][data-index=\"${index}\"]`,\n ) as HTMLElement;\n\n if (targetTab) {\n targetTab.click();\n }\n }\n };\n\n // Add effect to handle link click prevention during drag\n useEffect(() => {\n if (!carouselRef.current || !mouseDragging) return;\n\n // Function to prevent click events on links during/after drag\n const preventLinkActivation = (e: MouseEvent) => {\n // If we are currently dragging, or just finished dragging, prevent link clicks\n if (isDragging) {\n e.preventDefault();\n e.stopPropagation();\n\n // Reset isDragging after the current event cycle completes\n setTimeout(() => {\n setIsDragging(false);\n }, 0);\n }\n };\n\n // Function to handle mouse down events\n const handleMouseDown = (e: MouseEvent) => {\n setDragStartPosition({ x: e.clientX, y: e.clientY });\n };\n\n // Function to handle mouse move events\n const handleMouseMove = (e: MouseEvent) => {\n if (dragStartPosition === null) return;\n\n // Calculate the distance moved\n const dx = Math.abs(e.clientX - dragStartPosition.x);\n const dy = Math.abs(e.clientY - dragStartPosition.y);\n const distance = Math.sqrt(dx * dx + dy * dy);\n\n // If the user has moved more than the threshold, consider it a drag\n if (distance > dragThreshold) {\n setIsDragging(true);\n }\n };\n\n // Function to handle mouse up events\n const handleMouseUp = () => {\n // If this wasn't a drag, don't interfere with normal clicks\n if (!isDragging) {\n setDragStartPosition(null);\n return;\n }\n\n // Add a brief delay for the click prevention to work\n setTimeout(() => {\n setIsDragging(false);\n setDragStartPosition(null);\n }, 50);\n };\n\n // Add event listeners for the carousel container\n const carouselElement = carouselRef.current;\n\n // Capture phase is important to catch events before they reach the links\n carouselElement.addEventListener('mousedown', handleMouseDown, true);\n carouselElement.addEventListener('mousemove', handleMouseMove, true);\n carouselElement.addEventListener('mouseup', handleMouseUp, true);\n\n // This is the key event listener that prevents link activation\n carouselElement.addEventListener('click', preventLinkActivation, true);\n\n return () => {\n // Clean up event listeners\n carouselElement.removeEventListener('mousedown', handleMouseDown, true);\n carouselElement.removeEventListener('mousemove', handleMouseMove, true);\n carouselElement.removeEventListener('mouseup', handleMouseUp, true);\n carouselElement.removeEventListener('click', preventLinkActivation, true);\n };\n }, [mouseDragging, isDragging, dragStartPosition, dragThreshold]);\n\n // Handle transition direction\n useEffect(() => {\n if (carouselRef.current) {\n const scroller = carouselRef.current.querySelector(`.${styles.scroller}`);\n if (scroller && scroller instanceof HTMLElement) {\n if (prevPage < currentPage) {\n scroller.classList.remove(styles.slideLeft);\n scroller.classList.add(styles.slideRight);\n } else if (prevPage > currentPage) {\n scroller.classList.remove(styles.slideRight);\n scroller.classList.add(styles.slideLeft);\n }\n }\n }\n }, [currentPage, prevPage]);\n\n // Track selected tab changes\n useEffect(() => {\n if (!carouselRef.current) return;\n\n const checkCurrentPage = () => {\n if (!carouselRef.current) return;\n\n // Find the currently selected tab\n const selectedTab = carouselRef.current.querySelector(\n '[data-slide-tab=\"true\"][aria-selected=\"true\"]',\n );\n if (selectedTab) {\n const indexStr = (selectedTab as HTMLElement).dataset.index;\n if (typeof indexStr === 'string' && indexStr.length > 0) {\n const newIndex = parseInt(indexStr, 10);\n if (\n !isNaN(newIndex) &&\n newIndex !== currentPage &&\n newIndex >= 0 &&\n newIndex < totalPages\n ) {\n setPrevPage(currentPage);\n setCurrentPage(newIndex);\n }\n }\n }\n };\n\n // Set up mutation observer to watch for aria-selected changes\n const observer = new MutationObserver((mutations) => {\n let shouldCheck = false;\n mutations.forEach((mutation) => {\n if (\n mutation.type === 'attributes' &&\n mutation.attributeName === 'aria-selected'\n ) {\n shouldCheck = true;\n }\n });\n\n if (shouldCheck) {\n // Small delay to ensure DOM is updated\n setTimeout(checkCurrentPage, 10);\n }\n });\n\n // Observe all hidden tabs\n const hiddenTabs = carouselRef.current.querySelectorAll(\n '[data-slide-tab=\"true\"]',\n );\n hiddenTabs.forEach((tab) => {\n observer.observe(tab, {\n attributes: true,\n attributeFilter: ['aria-selected'],\n });\n });\n\n // Initial check\n checkCurrentPage();\n\n // Also check periodically as backup\n const interval = setInterval(checkCurrentPage, 500);\n\n return () => {\n observer.disconnect();\n clearInterval(interval);\n };\n }, [currentPage, totalPages]);\n\n // Interaction handlers for hover and focus\n const interactionHandlers = showArrowsOnHover\n ? {\n onMouseEnter: () => setIsHovered(true),\n onMouseLeave: () => setIsHovered(false),\n onFocus: () => setIsFocused(true),\n onBlur: (e: React.FocusEvent) => {\n // Only blur if focus is moving outside the carousel\n if (!e.currentTarget.contains(e.relatedTarget as Node)) {\n setIsFocused(false);\n }\n },\n }\n : {};\n\n // Determine whether arrows should be visible\n // Hide arrows if:\n // 1. There's only one page (all items fit on screen), OR\n // 2. showArrowsOnHover is true and carousel is not hovered/focused\n const shouldShowArrows = totalPages > 1;\n const arrowsVisible =\n shouldShowArrows && (!showArrowsOnHover || isHovered || isFocused);\n\n // Get style object only if we have variables to set\n const cssVars = getCssVariables();\n\n const { focusProps, isFocusVisible } = useFocusRing();\n\n // Custom styles for grid-auto-columns calculation\n const getScrollerStyles = () => {\n const styles: React.CSSProperties = {};\n\n // ALWAYS apply gap if spaceBetweenItems is set, regardless of itemsPerPage\n if (resolvedSpaceBetweenItems >= 0) {\n styles.gap = `${resolvedSpaceBetweenItems}px`;\n }\n\n // Only calculate grid-auto-columns if we have multiple items per page AND spacing\n if (resolvedItemsPerPage > 1 && resolvedSpaceBetweenItems > 0) {\n // Advanced calculation for grid layout to account for gap spacing\n const gapSpacePerItem =\n (resolvedSpaceBetweenItems * (safeItemsPerPage - 1)) / safeItemsPerPage;\n\n styles.gridAutoColumns = `calc(${100 / safeItemsPerPage}% - ${gapSpacePerItem}px)`;\n } else if (resolvedItemsPerPage > 1) {\n // No gap, just divide width evenly\n styles.gridAutoColumns = `${100 / safeItemsPerPage}%`;\n }\n\n return styles;\n };\n\n // Get active item indices for the current page\n const activeItemIndices = getActiveItemIndices();\n\n // Handle carousel keyboard navigation\n const handleCarouselKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'ArrowLeft') {\n e.preventDefault();\n // Navigate to previous slide\n const prevButton = carouselRef.current?.querySelector(\n '[dir=\"prev\"]',\n ) as HTMLButtonElement;\n if (prevButton && !prevButton.disabled) {\n prevButton.click();\n }\n } else if (e.key === 'ArrowRight') {\n e.preventDefault();\n // Navigate to next slide\n const nextButton = carouselRef.current?.querySelector(\n '[dir=\"next\"]',\n ) as HTMLButtonElement;\n if (nextButton && !nextButton.disabled) {\n nextButton.click();\n }\n } else if (e.key === 'Home') {\n e.preventDefault();\n // Go to first slide\n navigateToSlide(0);\n } else if (e.key === 'End') {\n e.preventDefault();\n // Go to last slide\n navigateToSlide(totalPages - 1);\n }\n };\n\n // Generate a meaningful default aria-label if none provided\n const getDefaultAriaLabel = () => {\n if (ariaLabel) return ariaLabel;\n\n const currentSlideNumber = currentPage + 1;\n const autoplayStatus = autoPlay ? ', autoplay enabled' : '';\n\n return `Carousel with ${totalItems} items, currently showing slide ${currentSlideNumber} of ${totalPages}${autoplayStatus}`;\n };\n\n return (\n <div\n className={getCarouselWrapperClasses()}\n ref={carouselRef}\n style={cssVars as React.CSSProperties}\n data-dots-size={dotsSize}\n {...interactionHandlers}\n data-arrows-visible={arrowsVisible ? 'true' : 'false'}\n data-transitioning={isTransitioning ? 'true' : undefined}\n data-scroll-padding={resolvedScrollPadding}\n role=\"region\"\n aria-label={getDefaultAriaLabel()}\n aria-describedby={ariaDescribedby}\n aria-roledescription=\"carousel\"\n >\n <AriaCarousel\n className={`${carousel({ looping })}`}\n loop={getLoopValue()}\n ref={ariaCarouselRef}\n autoplay={autoPlay}\n autoplayInterval={autoPlayInterval}\n mouseDragging={mouseDragging && !isTransitioning}\n onDragStart={(e) => {\n setIsDragging(true);\n if (e && e.nativeEvent) {\n setDragStartPosition({\n x: e.nativeEvent.clientX,\n y: e.nativeEvent.clientY,\n });\n }\n }}\n onDragEnd={() => {\n // We keep isDragging true for a short time after drag ends\n // This helps ensure click events don't fire immediately after dragging\n setTimeout(() => {\n setIsDragging(false);\n }, 50);\n }}\n data-dragging={isDragging ? 'true' : 'false'}\n itemsPerPage={safeItemsPerPage}\n scrollPadding={resolvedScrollPadding}\n data-has-space-between={\n resolvedSpaceBetweenItems > 0 ? 'true' : undefined\n }\n data-items-per-page={\n resolvedItemsPerPage !== 1 ? safeItemsPerPage.toString() : undefined\n }\n >\n <AriaCarouselScroller\n className={`${styles.scroller} ${focusStyleVariants({ focusStyle })}`}\n {...focusProps}\n data-focused={isFocusVisible ? true : undefined}\n data-focus-visible={isFocusVisible ? true : undefined}\n data-transitioning={isTransitioning ? 'true' : undefined}\n style={getScrollerStyles()}\n tabIndex={0}\n role=\"region\"\n aria-label=\"Carousel content\"\n onKeyDown={handleCarouselKeyDown}\n >\n {items.map((child, index) => {\n const isActiveItem = activeItemIndices.includes(index);\n const itemClasses = [\n itemWrapperClassName || '',\n styles.item,\n isActiveItem && activeItemClassName ? activeItemClassName : '',\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <AriaCarouselItem\n key={index}\n className={itemClasses}\n data-is-active={isActiveItem ? 'true' : undefined}\n data-item-index={index}\n aria-label={`Slide ${index + 1} of ${totalItems}`}\n >\n {child}\n </AriaCarouselItem>\n );\n })}\n </AriaCarouselScroller>\n\n <div\n className={`${styles.controls} ${showArrowsOnHover ? styles.showOnHover : ''}`}\n >\n <CarouselButton\n dir=\"prev\"\n variant={arrowStyleVariant}\n size={resolvedArrowSize}\n focusStyle={focusStyle}\n iconType={iconType}\n hideDisabledArrow={hideDisabledArrow}\n onPress={() => onArrowPress?.('prev')}\n className={`${getClassNameWithDefault(prevArrowClassName, styles.defaultPrevButton)} ${!arrowsVisible ? styles.hidden : ''}`}\n />\n\n <CarouselButton\n dir=\"next\"\n variant={arrowStyleVariant}\n size={resolvedArrowSize}\n focusStyle={focusStyle}\n iconType={iconType}\n hideDisabledArrow={hideDisabledArrow}\n onPress={() => onArrowPress?.('next')}\n className={`${getClassNameWithDefault(nextArrowClassName, styles.defaultNextButton)} ${!arrowsVisible ? styles.hidden : ''}`}\n />\n </div>\n\n <div className={styles.hiddenTabs}>\n <AriaCarouselTabs>\n {(page) => (\n <AriaCarouselTab\n key={page.index}\n index={page.index}\n data-index={page.index}\n data-slide-tab=\"true\"\n tabIndex={-1}\n />\n )}\n </AriaCarouselTabs>\n </div>\n\n {autoPlay && (\n <div\n className={`${styles.autoplayControlWrapper} ${getClassNameWithDefault(autoplayControlClassName, styles.defaultAutoplayControl)}`}\n >\n <AutoplayControl\n variant={autoPlayStyleVariant}\n size={autoPlayControlSize}\n className=\"\"\n onPress={onAutoplayPress}\n />\n </div>\n )}\n\n {shouldShowDots && (\n <CarouselDots\n totalItems={totalPages}\n currentPage={currentPage}\n onDotClick={(index) => navigateToSlide(index)}\n onPress={onDotPress}\n focusStyle={focusStyle}\n dotsSize={dotsSize}\n variant={dotsVariant}\n className={getClassNameWithDefault(\n dotsContainerClassName,\n styles.defaultDotsContainer,\n )}\n dotsWrapperClassName={dotsWrapperClassName}\n dotClassName={dotClassName}\n activeDotClassName={activeDotClassName}\n isTransitioning={isTransitioning}\n />\n )}\n </AriaCarousel>\n </div>\n );\n};\n\nexport default Carousel;\n"],"names":["carousel","cva","styles","variants","looping","infinite","backToStart","native","off","Carousel","children","ariaLabel","ariaDescribedby","itemsPerPage","spaceBetweenItems","scrollPadding","iconType","arrowStyleVariant","arrowSize","hideDisabledArrow","showArrowsOnHover","focusStyle","dotsSize","dotsVariant","hideDots","autoPlay","autoPlayInterval","autoPlayStyleVariant","autoPlayControlSize","mouseDragging","carouselWrapperClassName","prevArrowClassName","nextArrowClassName","autoplayControlClassName","dotsContainerClassName","dotsWrapperClassName","dotClassName","activeDotClassName","itemWrapperClassName","activeItemClassName","onArrowPress","onDotPress","onAutoplayPress","items","React","Children","toArray","totalItems","length","breakpoint","useBreakpoint","resolvedItemsPerPage","resolveResponsiveProp","resolvedSpaceBetweenItems","resolvedScrollPadding","resolvedArrowSize","resolvedHideDots","safeItemsPerPage","Math","max","totalPages","ceil","shouldShowDots","carouselRef","useRef","ariaCarouselRef","currentPage","setCurrentPage","useState","prevPage","setPrevPage","isDragging","setIsDragging","isHovered","setIsHovered","isFocused","setIsFocused","isTransitioning","dragStartPosition","setDragStartPosition","getClassNameWithDefault","customClassName","defaultClassName","navigateToSlide","index","current","targetTab","querySelector","click","useEffect","preventLinkActivation","e","preventDefault","stopPropagation","setTimeout","handleMouseDown","x","clientX","y","clientY","handleMouseMove","dx","abs","dy","sqrt","handleMouseUp","carouselElement","addEventListener","removeEventListener","scroller","HTMLElement","classList","remove","slideLeft","add","slideRight","checkCurrentPage","selectedTab","indexStr","dataset","newIndex","parseInt","isNaN","observer","MutationObserver","mutations","shouldCheck","forEach","mutation","type","attributeName","querySelectorAll","tab","observe","attributes","attributeFilter","interval","setInterval","disconnect","clearInterval","interactionHandlers","onMouseEnter","onMouseLeave","onFocus","onBlur","currentTarget","contains","relatedTarget","arrowsVisible","cssVars","String","Object","keys","getCssVariables","focusProps","isFocusVisible","useFocusRing","activeItemIndices","startIndex","floor","endIndex","min","activeIndices","i","push","getActiveItemIndices","jsx","className","classes","carouselWrapper","Number","isInteger","showPartialItems","hasScrollPadding","trim","defaultCarouselWrapper","join","getCarouselWrapperClasses","ref","style","role","getDefaultAriaLabel","jsxs","AriaCarousel","loop","autoplay","autoplayInterval","onDragStart","nativeEvent","onDragEnd","toString","AriaCarouselScroller","focusStyleVariants","gap","gapSpacePerItem","gridAutoColumns","getScrollerStyles","tabIndex","onKeyDown","key","prevButton","disabled","nextButton","map","child","isActiveItem","includes","itemClasses","item","filter","Boolean","AriaCarouselItem","controls","showOnHover","CarouselButton","dir","variant","size","onPress","defaultPrevButton","hidden","defaultNextButton","hiddenTabs","AriaCarouselTabs","page","AriaCarouselTab","autoplayControlWrapper","defaultAutoplayControl","AutoplayControl","CarouselDots","onDotClick","defaultDotsContainer"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Carousel.js","sources":["../../../src/components/Carousel/Carousel.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect, useCallback } from 'react';\nimport { cva } from 'class-variance-authority';\nimport {\n Carousel as AriaCarousel,\n CarouselScroller as AriaCarouselScroller,\n CarouselItem as AriaCarouselItem,\n CarouselTabs as AriaCarouselTabs,\n CarouselTab as AriaCarouselTab,\n} from 'react-aria-carousel';\nimport styles from './Carousel.module.css';\nimport { CarouselButton } from './CarouselButton/CarouselButton';\nimport { CarouselDots } from './CarouselDots/CarouselDots';\nimport { AutoplayControl } from './AutoplayControl/AutoplayControl';\nimport { focusStyleVariants } from '../../utils/focus/focusStyles';\nimport { useFocusRing } from '@react-aria/focus';\n\nimport {\n WithResponsive,\n resolveResponsiveProp,\n} from '../../utils/breakpoint/responsive';\nimport { useBreakpoint } from '../../utils/breakpoint/hooks/useBreakpoint';\n\nconst carousel = cva(styles.carousel, {\n variants: {\n looping: {\n infinite: styles.infinite,\n backToStart: styles.native,\n off: undefined,\n },\n },\n});\n\nexport interface CarouselBaseProps {\n /**\n * Content to be displayed in the carousel\n */\n children?: React.ReactNode | React.ReactNode[];\n\n /**\n * Accessible name for the carousel\n * Describes the purpose or content of the carousel for screen readers\n * @example \"Featured products\" or \"Customer testimonials\"\n */\n 'aria-label'?: string;\n\n /**\n * ID of an element that provides additional description for the carousel\n * Can reference an element that gives more context about the carousel's content\n * @example \"carousel-description\"\n */\n 'aria-describedby'?: string;\n\n /**\n * Looping behavior\n * - 'infinite': Carousel loops continuously\n * - 'backToStart': Carousel loops back to start after reaching end\n * - 'off': Looping is disabled\n * @default 'off'\n */\n looping?: 'infinite' | 'backToStart' | 'off';\n\n /**\n * Number of items to display per page (minimum: 1)\n * Decimal values (e.g., 2.25) can be used to show partial items\n * @default 1\n * @min 1\n */\n itemsPerPage?: number;\n\n /**\n * Space between carousel items in pixels\n * @default 0\n */\n spaceBetweenItems?: number;\n\n /**\n * Amount of padding added to the scroll container to create a \"peek\" effect.\n * This shows a portion of the adjacent items.\n * Accepts any valid CSS dimension (px, rem, em, %) - e.g., \"15%\", \"20px\", \"2rem\"\n * @example \"15%\" or \"20px\" or \"2rem\"\n * @default undefined\n */\n scrollPadding?: string;\n\n /* Button and Controls Props */\n /**\n * Icon type for navigation buttons\n * @default 'chevron'\n */\n iconType?: 'chevron';\n\n /**\n * Style of carousel arrow buttons\n * @default 'neutral'\n */\n arrowStyleVariant?:\n | 'neutral'\n | 'white'\n | 'shapeFlat'\n | 'shapeElevated'\n | 'gradient';\n\n /**\n * Size of navigation buttons\n * @default 'md'\n */\n arrowSize?: 'sm' | 'md' | 'lg';\n\n /**\n * Whether to hide navigation buttons when disabled\n * Note: Navigation buttons are automatically hidden when all items fit on one page\n * @default false\n */\n hideDisabledArrow?: boolean;\n\n /**\n * Whether to show arrows only when hovering over the carousel or when it has focus\n * @default false\n */\n showArrowsOnHover?: boolean;\n\n /**\n * Focus style for interactive elements\n * @default 'default'\n */\n focusStyle?: 'default' | 'white';\n\n /* Dots/Tabs Props */\n /**\n * Size of pagination dots\n * @default 'md'\n */\n dotsSize?: 'md' | 'lg';\n\n /**\n * Visual style of pagination dots\n * @default 'standard'\n */\n dotsVariant?: 'standard' | 'transparent';\n\n /**\n * Whether to hide pagination dots\n * Note: Dots are automatically hidden when there's only one page\n * @default false\n */\n hideDots?: boolean;\n\n /* Autoplay Props */\n /**\n * Whether the autoplay is enabled\n * @default false\n */\n autoPlay?: boolean;\n\n /**\n * Interval in milliseconds between slides during autoplay\n * @default 2000\n */\n autoPlayInterval?: number;\n\n /**\n * Style variant for autoplay control button\n * @default 'neutralVibrant'\n */\n autoPlayStyleVariant?:\n | 'neutralVibrant'\n | 'neutralSubtle'\n | 'whiteVibrant'\n | 'whiteSubtle';\n\n /**\n * Size of autoplay control button\n * @default 'md'\n */\n autoPlayControlSize?: 'sm' | 'md';\n\n /**\n * Whether to enable mouse dragging for the carousel\n * @default true\n */\n mouseDragging?: boolean;\n\n /* Custom Class Names for Positioning and Styling */\n /**\n * Class name for the outermost wrapper of the carousel\n */\n carouselWrapperClassName?: string;\n\n /**\n * Class name for the previous button\n * Use this to position the previous button\n */\n prevArrowClassName?: string;\n\n /**\n * Class name for the next button\n * Use this to position the next button\n */\n nextArrowClassName?: string;\n\n /**\n * Class name for the autoplay control\n * Use this to position the autoplay button\n */\n autoplayControlClassName?: string;\n\n /**\n * Class name for the dots container\n * Use this to position the pagination dots\n */\n dotsContainerClassName?: string;\n\n /**\n * Class name for the dots wrapper\n * Use this to style the dots wrapper\n */\n dotsWrapperClassName?: string;\n\n /**\n * Class name for individual dots\n */\n dotClassName?: string;\n\n /**\n * Class name for the active dot\n */\n activeDotClassName?: string;\n\n /**\n * Class name for individual carousel item wrappers\n * Use this to style the wrapper div around each carousel item\n */\n itemWrapperClassName?: string;\n\n /**\n * Class name for the scroll container\n * Use this to customize the grid/scroll layout of carousel items\n */\n scrollerClassName?: string;\n\n /**\n * Class name for the currently active/visible carousel item\n * This class is applied to the item that corresponds to the current page\n */\n activeItemClassName?: string;\n\n /**\n * Callback fired when a carousel navigation button (prev/next) is pressed\n */\n onArrowPress?: (direction: 'prev' | 'next') => void;\n\n /**\n * Callback fired when a dot is pressed\n */\n onDotPress?: (index: number) => void;\n\n /**\n * Callback fired when the autoplay button is pressed\n */\n onAutoplayPress?: (state: 'play' | 'pause') => void;\n\n /**\n * Imperative controls ref for driving carousel navigation from external UI.\n */\n controlsRef?: React.MutableRefObject<CarouselControls | null>;\n\n /**\n * Callback fired when carousel navigation state changes.\n */\n onNavigationStateChange?: (state: CarouselNavigationState) => void;\n}\n\nexport interface CarouselControls {\n prev: () => void;\n next: () => void;\n goToSlide: (index: number) => void;\n canGoPrev: boolean;\n canGoNext: boolean;\n currentPage: number;\n totalPages: number;\n}\n\nexport interface CarouselNavigationState {\n canGoPrev: boolean;\n canGoNext: boolean;\n currentPage: number;\n totalPages: number;\n}\n\nconst toNavigationState = (\n currentPage: number,\n totalPages: number,\n): CarouselNavigationState => ({\n canGoPrev: currentPage > 0,\n canGoNext: currentPage < totalPages - 1,\n currentPage,\n totalPages,\n});\n\ntype ResponsiveKeys =\n | 'itemsPerPage'\n | 'spaceBetweenItems'\n | 'scrollPadding'\n | 'showArrowsOnHover'\n | 'arrowSize'\n | 'hideDots';\n\nexport type CarouselProps = WithResponsive<CarouselBaseProps, ResponsiveKeys>;\n\nexport const Carousel = ({\n children = [],\n 'aria-label': ariaLabel,\n 'aria-describedby': ariaDescribedby,\n looping = 'off',\n itemsPerPage = 1,\n spaceBetweenItems = 0,\n scrollPadding,\n\n // Button and Controls Props\n iconType = 'chevron',\n arrowStyleVariant = 'neutral',\n arrowSize = 'md',\n hideDisabledArrow = false,\n showArrowsOnHover = false,\n focusStyle = 'default',\n\n // Dots/Tabs Props\n dotsSize = 'md',\n dotsVariant = 'standard',\n hideDots = false,\n\n // Autoplay Props\n autoPlay = false,\n autoPlayInterval = 2000,\n autoPlayStyleVariant = 'neutralVibrant',\n autoPlayControlSize = 'md',\n\n // Mouse Dragging\n mouseDragging = true,\n\n // Custom Class Names\n carouselWrapperClassName = '',\n prevArrowClassName = '',\n nextArrowClassName = '',\n autoplayControlClassName = '',\n dotsContainerClassName = '',\n dotsWrapperClassName = '',\n dotClassName = '',\n activeDotClassName = '',\n itemWrapperClassName = '',\n scrollerClassName = '',\n activeItemClassName = '',\n\n // Event Callbacks\n onArrowPress,\n onDotPress,\n onAutoplayPress,\n controlsRef,\n onNavigationStateChange,\n}: CarouselProps) => {\n // Map looping values to expected loop values for AriaCarousel\n const getLoopValue = () => {\n if (looping === 'infinite') return 'infinite';\n if (looping === 'backToStart') return 'native';\n if (looping === 'off') return undefined;\n return looping; // other values pass through\n };\n\n const items = React.Children.toArray(children);\n const totalItems = items.length;\n\n const breakpoint = useBreakpoint();\n const resolvedItemsPerPage =\n resolveResponsiveProp(itemsPerPage, breakpoint) ?? 1;\n const resolvedSpaceBetweenItems =\n resolveResponsiveProp(spaceBetweenItems, breakpoint) ?? 0;\n const resolvedScrollPadding =\n resolveResponsiveProp(scrollPadding, breakpoint) ?? undefined;\n const resolvedArrowSize =\n resolveResponsiveProp(arrowSize, breakpoint) ?? 'md';\n const resolvedHideDots = resolveResponsiveProp(hideDots, breakpoint) ?? false;\n\n // Ensure itemsPerPage is at least 1\n // We allow decimal values for showing partial items\n const safeItemsPerPage = Math.max(1, resolvedItemsPerPage);\n const wholeItemsPerPage = Math.max(1, Math.floor(safeItemsPerPage));\n\n const pageItemGroups = React.useMemo(() => {\n const groups = Array.from(\n { length: totalItems },\n (_, index) => index,\n ).reduce<number[][]>((accumulator, index) => {\n const currentGroup = accumulator.at(-1);\n\n if (currentGroup && currentGroup.length < wholeItemsPerPage) {\n currentGroup.push(index);\n } else {\n accumulator.push([index]);\n }\n\n return accumulator;\n }, []);\n\n if (groups.length >= 2) {\n const deficit = wholeItemsPerPage - groups.at(-1)!.length;\n\n if (deficit > 0) {\n const fill = [...groups.at(-2)!].splice(wholeItemsPerPage - deficit);\n groups.at(-1)!.unshift(...fill);\n }\n }\n\n return groups;\n }, [totalItems, wholeItemsPerPage]);\n\n const carouselRef = useRef<HTMLDivElement>(null);\n const ariaCarouselRef = useRef<HTMLDivElement>(null);\n const dragEndResetTimeoutRef = useRef<number | null>(null);\n const dragEndSyncTimeoutRef = useRef<number | null>(null);\n const scrollerRef = useRef<HTMLDivElement>(null);\n const itemElementsRef = useRef<HTMLElement[]>([]);\n\n const [currentPage, setCurrentPage] = useState(0);\n const [prevPage, setPrevPage] = useState(0);\n const [canScrollPrev, setCanScrollPrev] = useState(false);\n const [canScrollNext, setCanScrollNext] = useState(pageItemGroups.length > 1);\n const [ariaTabsPageCount, setAriaTabsPageCount] = useState(0);\n const [firstVisibleItemIndex, setFirstVisibleItemIndex] = useState(0);\n const [isDragging, setIsDragging] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n const [isFocused, setIsFocused] = useState(false);\n const [isTransitioning] = useState(false);\n\n // Add state variables for drag/link handling\n const [dragStartPosition, setDragStartPosition] = useState<{\n x: number;\n y: number;\n } | null>(null);\n const dragThreshold = 5; // Pixels of movement needed to consider as a drag\n const loopMode = getLoopValue();\n const totalPages =\n ariaTabsPageCount > 0 ? ariaTabsPageCount : pageItemGroups.length;\n\n // Determine if dots should be shown\n // Hide dots if:\n // 1. resolvedHideDots prop is true (responsive), OR\n // 2. There's only one page (totalPages <= 1)\n const shouldShowDots = !resolvedHideDots && totalPages > 1;\n\n // Helper function to get class names with defaults\n const getClassNameWithDefault = (\n customClassName: string,\n defaultClassName: string,\n ): string => {\n return customClassName || defaultClassName;\n };\n\n // Get CSS classes based on showing partial items\n const getCarouselWrapperClasses = () => {\n const classes = [styles.carouselWrapper];\n\n if (!Number.isInteger(safeItemsPerPage)) {\n classes.push(styles.showPartialItems);\n }\n\n if (resolvedScrollPadding) {\n classes.push(styles.hasScrollPadding);\n }\n\n // Apply default wrapper class if no custom wrapper class is provided\n if (carouselWrapperClassName && carouselWrapperClassName.trim()) {\n classes.push(carouselWrapperClassName);\n } else {\n classes.push(styles.defaultCarouselWrapper);\n }\n\n return classes.join(' ');\n };\n\n // Determine if we need to set CSS variables and return only what's needed\n const getCssVariables = () => {\n const cssVars: Record<string, string> = {};\n\n // Only set these if they differ from defaults\n if (resolvedItemsPerPage !== 1) {\n cssVars['--items-per-page'] = String(safeItemsPerPage);\n }\n\n if (resolvedSpaceBetweenItems > 0) {\n cssVars['--space-between-items'] = `${resolvedSpaceBetweenItems}px`;\n }\n\n if (resolvedScrollPadding) {\n cssVars['--scroll-padding'] = resolvedScrollPadding;\n }\n\n return Object.keys(cssVars).length > 0 ? cssVars : undefined;\n };\n\n // Helper function to determine which items are currently active/visible\n const getActiveItemIndices = () => {\n return pageItemGroups[currentPage] ?? [];\n };\n\n const getScrollerElement = useCallback(() => {\n return carouselRef.current?.querySelector(\n '[data-carousel-scroller=\"true\"]',\n ) as HTMLElement | null;\n }, []);\n\n const scrollToPage = useCallback(\n (scroller: HTMLElement, pageIndex: number) => {\n const itemsPerPageWhole = Math.max(1, Math.floor(safeItemsPerPage));\n const targetItemIndex = pageIndex * itemsPerPageWhole;\n const targetItem = scroller.querySelector(\n `[data-item-index=\"${targetItemIndex}\"]`,\n ) as HTMLElement | null;\n\n if (!targetItem) {\n return false;\n }\n\n const scrollerRect = scroller.getBoundingClientRect();\n const itemRect = targetItem.getBoundingClientRect();\n const targetScrollLeft =\n scroller.scrollLeft + (itemRect.left - scrollerRect.left);\n\n scroller.scrollTo({\n left: targetScrollLeft,\n behavior: 'smooth',\n });\n\n return true;\n },\n [safeItemsPerPage],\n );\n\n const navigateToSlide = useCallback(\n (index: number) => {\n if (index === currentPage || index < 0 || index >= totalPages) {\n return;\n }\n\n // Find and click the corresponding hidden tab\n if (carouselRef.current) {\n const targetTab = carouselRef.current.querySelector(\n `[data-slide-tab=\"true\"][data-index=\"${index}\"]`,\n ) as HTMLElement;\n\n if (targetTab) {\n targetTab.click();\n setPrevPage(currentPage);\n setCurrentPage(index);\n }\n }\n },\n [currentPage, totalPages],\n );\n\n const syncCurrentPageFromVisibleItem = useCallback(() => {\n if (!carouselRef.current || totalPages <= 1) {\n return;\n }\n\n const scroller = carouselRef.current.querySelector(\n '[data-carousel-scroller=\"true\"]',\n ) as HTMLElement | null;\n\n if (!scroller) {\n return;\n }\n\n const itemElements = Array.from(\n scroller.querySelectorAll('[data-item-index]'),\n ) as HTMLElement[];\n\n if (!itemElements.length) {\n return;\n }\n\n const scrollerLeft = scroller.getBoundingClientRect().left;\n let closestItemIndex = 0;\n let closestDistance = Number.POSITIVE_INFINITY;\n\n itemElements.forEach((element) => {\n const index = parseInt(element.dataset.itemIndex ?? '', 10);\n\n if (Number.isNaN(index)) {\n return;\n }\n\n const distance = Math.abs(\n element.getBoundingClientRect().left - scrollerLeft,\n );\n\n if (distance < closestDistance) {\n closestDistance = distance;\n closestItemIndex = index;\n }\n });\n\n const itemsPerPageWhole = Math.max(1, Math.floor(safeItemsPerPage));\n const nextPage = Math.min(\n totalPages - 1,\n Math.floor(closestItemIndex / itemsPerPageWhole),\n );\n\n if (nextPage !== currentPage) {\n setPrevPage(currentPage);\n setCurrentPage(nextPage);\n }\n }, [currentPage, safeItemsPerPage, totalPages]);\n\n const navigateToPreviousSlide = useCallback(() => {\n const scroller = getScrollerElement();\n\n if (scroller) {\n const targetPage = Math.max(0, currentPage - 1);\n const didScrollToItemGroup = scrollToPage(scroller, targetPage);\n\n if (!didScrollToItemGroup) {\n scroller.scrollBy({\n left: -scroller.clientWidth,\n behavior: 'smooth',\n });\n }\n\n setPrevPage(currentPage);\n setCurrentPage(targetPage);\n\n window.setTimeout(() => {\n syncCurrentPageFromVisibleItem();\n }, 200);\n return;\n }\n\n if (currentPage <= 0) {\n return;\n }\n\n navigateToSlide(currentPage - 1);\n }, [\n currentPage,\n getScrollerElement,\n navigateToSlide,\n scrollToPage,\n syncCurrentPageFromVisibleItem,\n ]);\n\n const navigateToNextSlide = useCallback(() => {\n const scroller = getScrollerElement();\n\n if (scroller) {\n const targetPage = Math.min(totalPages - 1, currentPage + 1);\n const didScrollToItemGroup = scrollToPage(scroller, targetPage);\n\n if (!didScrollToItemGroup) {\n scroller.scrollBy({\n left: scroller.clientWidth,\n behavior: 'smooth',\n });\n }\n\n setPrevPage(currentPage);\n setCurrentPage(targetPage);\n\n window.setTimeout(() => {\n syncCurrentPageFromVisibleItem();\n }, 200);\n return;\n }\n\n if (currentPage >= totalPages - 1) {\n return;\n }\n\n navigateToSlide(currentPage + 1);\n }, [\n currentPage,\n getScrollerElement,\n navigateToSlide,\n scrollToPage,\n syncCurrentPageFromVisibleItem,\n totalPages,\n ]);\n\n useEffect(() => {\n const navigationState = toNavigationState(currentPage, totalPages);\n\n if (!controlsRef) {\n onNavigationStateChange?.(navigationState);\n return;\n }\n\n controlsRef.current = {\n prev: navigateToPreviousSlide,\n next: navigateToNextSlide,\n goToSlide: navigateToSlide,\n ...navigationState,\n };\n\n onNavigationStateChange?.(navigationState);\n\n return () => {\n if (controlsRef.current) {\n controlsRef.current = null;\n }\n };\n }, [\n controlsRef,\n currentPage,\n navigateToNextSlide,\n navigateToPreviousSlide,\n navigateToSlide,\n onNavigationStateChange,\n totalPages,\n ]);\n\n useEffect(() => {\n return () => {\n if (dragEndResetTimeoutRef.current !== null) {\n window.clearTimeout(dragEndResetTimeoutRef.current);\n }\n\n if (dragEndSyncTimeoutRef.current !== null) {\n window.clearTimeout(dragEndSyncTimeoutRef.current);\n }\n };\n }, []);\n\n // Add effect to handle link click prevention during drag\n useEffect(() => {\n if (!carouselRef.current || !mouseDragging) return;\n\n // Function to prevent link activation during/after drag\n const preventLinkActivation = (e: MouseEvent) => {\n if (!isDragging) return;\n\n const target = e.target;\n if (!(target instanceof Element)) return;\n\n const link = target.closest('a[href]');\n if (!link) return;\n\n e.preventDefault();\n e.stopPropagation();\n\n // Reset isDragging after the current event cycle completes\n setTimeout(() => {\n setIsDragging(false);\n }, 0);\n };\n\n // Function to handle mouse down events\n const handleMouseDown = (e: MouseEvent) => {\n setDragStartPosition({ x: e.clientX, y: e.clientY });\n };\n\n // Function to handle mouse move events\n const handleMouseMove = (e: MouseEvent) => {\n if (dragStartPosition === null) return;\n\n // Calculate the distance moved\n const dx = Math.abs(e.clientX - dragStartPosition.x);\n const dy = Math.abs(e.clientY - dragStartPosition.y);\n const distance = Math.sqrt(dx * dx + dy * dy);\n\n // If the user has moved more than the threshold, consider it a drag\n if (distance > dragThreshold) {\n setIsDragging(true);\n }\n };\n\n // Function to handle mouse up events\n const handleMouseUp = () => {\n // If this wasn't a drag, don't interfere with normal clicks\n if (!isDragging) {\n setDragStartPosition(null);\n return;\n }\n\n // Add a brief delay for the click prevention to work\n setTimeout(() => {\n setIsDragging(false);\n setDragStartPosition(null);\n }, 50);\n };\n\n // Add event listeners for the carousel container\n const carouselElement = carouselRef.current;\n\n // Capture phase is important to catch events before they reach the links\n carouselElement.addEventListener('mousedown', handleMouseDown, true);\n carouselElement.addEventListener('mousemove', handleMouseMove, true);\n carouselElement.addEventListener('mouseup', handleMouseUp, true);\n\n // This is the key event listener that prevents link activation\n carouselElement.addEventListener('click', preventLinkActivation, true);\n\n return () => {\n // Clean up event listeners\n carouselElement.removeEventListener('mousedown', handleMouseDown, true);\n carouselElement.removeEventListener('mousemove', handleMouseMove, true);\n carouselElement.removeEventListener('mouseup', handleMouseUp, true);\n carouselElement.removeEventListener('click', preventLinkActivation, true);\n };\n }, [mouseDragging, isDragging, dragStartPosition, dragThreshold]);\n\n // Handle transition direction\n useEffect(() => {\n if (carouselRef.current) {\n const scroller = carouselRef.current.querySelector(`.${styles.scroller}`);\n if (scroller && scroller instanceof HTMLElement) {\n if (prevPage < currentPage) {\n scroller.classList.remove(styles.slideLeft);\n scroller.classList.add(styles.slideRight);\n } else if (prevPage > currentPage) {\n scroller.classList.remove(styles.slideRight);\n scroller.classList.add(styles.slideLeft);\n }\n }\n }\n }, [currentPage, prevPage]);\n\n // Keep total page count aligned with the pages emitted by react-aria-carousel.\n useEffect(() => {\n const carouselElement = carouselRef.current;\n if (!carouselElement) return;\n\n let animationFrameId: number | null = null;\n\n const updateAriaPageCount = () => {\n const nextCount = carouselElement.querySelectorAll(\n '[data-slide-tab=\"true\"]',\n ).length;\n\n setAriaTabsPageCount((previousCount) =>\n previousCount === nextCount ? previousCount : nextCount,\n );\n };\n\n const scheduleAriaPageCountUpdate = () => {\n if (animationFrameId !== null) {\n return;\n }\n\n animationFrameId = window.requestAnimationFrame(() => {\n animationFrameId = null;\n updateAriaPageCount();\n });\n };\n\n const observer = new MutationObserver(() => {\n scheduleAriaPageCountUpdate();\n });\n\n observer.observe(carouselElement, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['data-slide-tab'],\n });\n\n scheduleAriaPageCountUpdate();\n\n return () => {\n if (animationFrameId !== null) {\n window.cancelAnimationFrame(animationFrameId);\n }\n\n observer.disconnect();\n };\n }, [totalItems, safeItemsPerPage]);\n\n // Track the actual scroll position so arrow state matches mouse dragging,\n // even when the underlying library still considers the first page active.\n useEffect(() => {\n const scroller = scrollerRef.current;\n if (!scroller) return;\n\n let animationFrameId: number | null = null;\n\n const scheduleScrollNavigationUpdate = () => {\n if (animationFrameId !== null) {\n return;\n }\n\n animationFrameId = window.requestAnimationFrame(() => {\n animationFrameId = null;\n updateScrollNavigation();\n });\n };\n\n const updateScrollNavigation = () => {\n const maxScrollLeft = Math.max(\n 0,\n scroller.scrollWidth - scroller.clientWidth,\n );\n const scrollLeft = scroller.scrollLeft;\n const epsilon = 1;\n const hasScrollableOverflow = maxScrollLeft > epsilon;\n const nextCanScrollPrev = hasScrollableOverflow\n ? scrollLeft > epsilon\n : currentPage > 0;\n const nextCanScrollNext = hasScrollableOverflow\n ? scrollLeft < maxScrollLeft - epsilon\n : currentPage < totalPages - 1;\n\n const itemElements =\n itemElementsRef.current.length > 0\n ? itemElementsRef.current\n : Array.from(\n scroller.querySelectorAll<HTMLElement>('[data-item-index]'),\n );\n\n if (itemElementsRef.current.length === 0) {\n itemElementsRef.current = itemElements;\n }\n\n const viewportStart = scrollLeft + epsilon;\n const nextFirstVisibleItemIndex =\n itemElements.find((item) => {\n const itemEnd = item.offsetLeft + item.offsetWidth;\n return itemEnd > viewportStart;\n })?.dataset.itemIndex ?? '0';\n\n const parsedFirstVisibleItemIndex = parseInt(\n nextFirstVisibleItemIndex,\n 10,\n );\n const safeFirstVisibleItemIndex = Number.isNaN(\n parsedFirstVisibleItemIndex,\n )\n ? 0\n : parsedFirstVisibleItemIndex;\n\n // Keep the currently visible item window interactive even before\n // the underlying carousel page index snaps to the next page start.\n const visibleItemCount = Math.max(1, Math.ceil(safeItemsPerPage));\n const visibleWindowEndIndex =\n safeFirstVisibleItemIndex + visibleItemCount - 1;\n\n itemElements.forEach((item) => {\n const itemIndexString = item.dataset.itemIndex;\n if (typeof itemIndexString !== 'string') return;\n\n const itemIndex = parseInt(itemIndexString, 10);\n if (Number.isNaN(itemIndex)) return;\n\n const isInVisibleWindow =\n itemIndex >= safeFirstVisibleItemIndex &&\n itemIndex <= visibleWindowEndIndex;\n\n if (isInVisibleWindow) {\n item.removeAttribute('inert');\n item.removeAttribute('aria-hidden');\n } else {\n item.setAttribute('inert', 'true');\n item.setAttribute('aria-hidden', 'true');\n }\n });\n\n const nextPageIndexFromVisibleItem = pageItemGroups\n .map((page) => page[0])\n .reduce((resolvedPageIndex, pageStartIndex, pageIndex) => {\n if (pageStartIndex <= safeFirstVisibleItemIndex) {\n return pageIndex;\n }\n\n return resolvedPageIndex;\n }, 0);\n\n const nextPageIndex = hasScrollableOverflow\n ? nextPageIndexFromVisibleItem\n : currentPage;\n\n setCanScrollPrev((previousValue) =>\n previousValue === nextCanScrollPrev ? previousValue : nextCanScrollPrev,\n );\n setCanScrollNext((previousValue) =>\n previousValue === nextCanScrollNext ? previousValue : nextCanScrollNext,\n );\n setFirstVisibleItemIndex((previousValue) => {\n const nextIndex = safeFirstVisibleItemIndex;\n return previousValue === nextIndex ? previousValue : nextIndex;\n });\n setCurrentPage((previousPage) => {\n if (previousPage !== nextPageIndex) {\n setPrevPage(previousPage);\n }\n\n return previousPage === nextPageIndex ? previousPage : nextPageIndex;\n });\n };\n\n const resizeObserver = new ResizeObserver(() => {\n scheduleScrollNavigationUpdate();\n });\n\n const refreshItemElements = () => {\n const nextItemElements = Array.from(\n scroller.querySelectorAll<HTMLElement>('[data-item-index]'),\n );\n itemElementsRef.current = nextItemElements;\n return nextItemElements;\n };\n\n resizeObserver.observe(scroller);\n\n const itemElements = refreshItemElements();\n itemElements.forEach((item) => {\n resizeObserver.observe(item);\n });\n\n const handleImageLoad = () => {\n scheduleScrollNavigationUpdate();\n };\n\n scroller.addEventListener('load', handleImageLoad, true);\n updateScrollNavigation();\n scroller.addEventListener('scroll', updateScrollNavigation, {\n passive: true,\n });\n window.addEventListener('resize', scheduleScrollNavigationUpdate);\n\n return () => {\n if (animationFrameId !== null) {\n window.cancelAnimationFrame(animationFrameId);\n }\n\n resizeObserver.disconnect();\n scroller.removeEventListener('load', handleImageLoad, true);\n scroller.removeEventListener('scroll', updateScrollNavigation);\n window.removeEventListener('resize', scheduleScrollNavigationUpdate);\n itemElementsRef.current = [];\n };\n }, [currentPage, pageItemGroups, safeItemsPerPage, totalPages, totalItems]);\n\n const handleActivePageIndexChange = ({ index }: { index: number }) => {\n setCurrentPage((previousPage) => {\n if (previousPage !== index) {\n setPrevPage(previousPage);\n }\n\n return index;\n });\n };\n\n const getPrevTargetPage = () => {\n if (!canScrollPrev) {\n return currentPage;\n }\n\n if (firstVisibleItemIndex <= 0) {\n return 0;\n }\n\n return Math.max(\n 0,\n Math.ceil(firstVisibleItemIndex / wholeItemsPerPage) - 1,\n );\n };\n\n const getNextTargetPage = () => {\n if (!canScrollNext) {\n return currentPage;\n }\n\n return Math.min(\n totalPages - 1,\n Math.floor(firstVisibleItemIndex / wholeItemsPerPage) + 1,\n );\n };\n\n // Interaction handlers for hover and focus\n const interactionHandlers = showArrowsOnHover\n ? {\n onMouseEnter: () => setIsHovered(true),\n onMouseLeave: () => setIsHovered(false),\n onFocus: () => setIsFocused(true),\n onBlur: (e: React.FocusEvent) => {\n // Only blur if focus is moving outside the carousel\n if (!e.currentTarget.contains(e.relatedTarget as Node)) {\n setIsFocused(false);\n }\n },\n }\n : {};\n\n // Determine whether arrows should be visible\n // Hide arrows if:\n // 1. There's only one page (all items fit on screen), OR\n // 2. showArrowsOnHover is true and carousel is not hovered/focused\n const shouldShowArrows = totalPages > 1;\n const arrowsVisible =\n shouldShowArrows && (!showArrowsOnHover || isHovered || isFocused);\n\n // Get style object only if we have variables to set\n const cssVars = getCssVariables();\n\n const { focusProps, isFocusVisible } = useFocusRing();\n\n // Custom styles for grid-auto-columns calculation\n const getScrollerStyles = () => {\n const styles: React.CSSProperties = {};\n\n // ALWAYS apply gap if spaceBetweenItems is set, regardless of itemsPerPage\n if (resolvedSpaceBetweenItems >= 0) {\n styles.gap = `${resolvedSpaceBetweenItems}px`;\n }\n\n // Only calculate grid-auto-columns if we have multiple items per page AND spacing\n if (resolvedItemsPerPage > 1 && resolvedSpaceBetweenItems > 0) {\n // Advanced calculation for grid layout to account for gap spacing\n const gapSpacePerItem =\n (resolvedSpaceBetweenItems * (safeItemsPerPage - 1)) / safeItemsPerPage;\n\n styles.gridAutoColumns = `calc(${100 / safeItemsPerPage}% - ${gapSpacePerItem}px)`;\n } else if (resolvedItemsPerPage > 1) {\n // No gap, just divide width evenly\n styles.gridAutoColumns = `${100 / safeItemsPerPage}%`;\n }\n\n return styles;\n };\n\n // Get active item indices for the current page\n const activeItemIndices = getActiveItemIndices();\n\n // Handle carousel keyboard navigation\n const handleCarouselKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'ArrowLeft') {\n e.preventDefault();\n // Navigate to previous slide\n const prevButton = carouselRef.current?.querySelector(\n '[dir=\"prev\"]',\n ) as HTMLButtonElement;\n if (prevButton && !prevButton.disabled) {\n prevButton.click();\n }\n } else if (e.key === 'ArrowRight') {\n e.preventDefault();\n // Navigate to next slide\n const nextButton = carouselRef.current?.querySelector(\n '[dir=\"next\"]',\n ) as HTMLButtonElement;\n if (nextButton && !nextButton.disabled) {\n nextButton.click();\n }\n } else if (e.key === 'Home') {\n e.preventDefault();\n // Go to first slide\n navigateToSlide(0);\n } else if (e.key === 'End') {\n e.preventDefault();\n // Go to last slide\n navigateToSlide(totalPages - 1);\n }\n };\n\n // Generate a meaningful default aria-label if none provided\n const getDefaultAriaLabel = () => {\n if (ariaLabel) return ariaLabel;\n\n const currentSlideNumber = currentPage + 1;\n const autoplayStatus = autoPlay ? ', autoplay enabled' : '';\n\n return `Carousel with ${totalItems} items, currently showing slide ${currentSlideNumber} of ${totalPages}${autoplayStatus}`;\n };\n\n return (\n <div\n className={getCarouselWrapperClasses()}\n ref={carouselRef}\n style={cssVars as React.CSSProperties}\n data-dots-size={dotsSize}\n {...interactionHandlers}\n data-arrows-visible={arrowsVisible ? 'true' : 'false'}\n data-transitioning={isTransitioning ? 'true' : undefined}\n data-scroll-padding={resolvedScrollPadding}\n role=\"region\"\n aria-label={getDefaultAriaLabel()}\n aria-describedby={ariaDescribedby}\n aria-roledescription=\"carousel\"\n >\n <AriaCarousel\n className={`${carousel({ looping })}`}\n loop={loopMode}\n ref={ariaCarouselRef}\n autoplay={autoPlay}\n autoplayInterval={autoPlayInterval}\n mouseDragging={mouseDragging && !isTransitioning}\n onActivePageIndexChange={handleActivePageIndexChange}\n onDragStart={(e) => {\n setIsDragging(true);\n if (e && e.nativeEvent) {\n setDragStartPosition({\n x: e.nativeEvent.clientX,\n y: e.nativeEvent.clientY,\n });\n }\n }}\n onDragEnd={() => {\n // We keep isDragging true for a short time after drag ends\n // This helps ensure click events don't fire immediately after dragging\n if (dragEndResetTimeoutRef.current !== null) {\n window.clearTimeout(dragEndResetTimeoutRef.current);\n }\n\n if (dragEndSyncTimeoutRef.current !== null) {\n window.clearTimeout(dragEndSyncTimeoutRef.current);\n }\n\n dragEndResetTimeoutRef.current = window.setTimeout(() => {\n setIsDragging(false);\n syncCurrentPageFromVisibleItem();\n }, 50);\n\n dragEndSyncTimeoutRef.current = window.setTimeout(() => {\n syncCurrentPageFromVisibleItem();\n }, 150);\n }}\n data-dragging={isDragging ? 'true' : 'false'}\n itemsPerPage={safeItemsPerPage}\n scrollPadding={resolvedScrollPadding}\n data-has-space-between={\n resolvedSpaceBetweenItems > 0 ? 'true' : undefined\n }\n data-items-per-page={\n resolvedItemsPerPage !== 1 ? safeItemsPerPage.toString() : undefined\n }\n >\n <AriaCarouselScroller\n className={`${styles.scroller} ${focusStyleVariants({ focusStyle })} ${scrollerClassName}`.trim()}\n ref={scrollerRef}\n {...focusProps}\n data-focused={isFocusVisible ? true : undefined}\n data-focus-visible={isFocusVisible ? true : undefined}\n data-transitioning={isTransitioning ? 'true' : undefined}\n style={getScrollerStyles()}\n tabIndex={0}\n role=\"region\"\n aria-label=\"Carousel content\"\n onKeyDown={handleCarouselKeyDown}\n >\n {items.map((child, index) => {\n const isActiveItem = activeItemIndices.includes(index);\n const itemClasses = [\n itemWrapperClassName || '',\n styles.item,\n isActiveItem && activeItemClassName ? activeItemClassName : '',\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <AriaCarouselItem\n key={index}\n className={itemClasses}\n data-is-active={isActiveItem ? 'true' : undefined}\n data-item-index={index}\n aria-label={`Slide ${index + 1} of ${totalItems}`}\n >\n {child}\n </AriaCarouselItem>\n );\n })}\n </AriaCarouselScroller>\n\n <div\n className={`${styles.controls} ${showArrowsOnHover ? styles.showOnHover : ''}`}\n >\n <CarouselButton\n dir=\"prev\"\n variant={arrowStyleVariant}\n size={resolvedArrowSize}\n focusStyle={focusStyle}\n iconType={iconType}\n hideDisabledArrow={hideDisabledArrow}\n overrideHideDisabledArrow={loopMode ? undefined : !canScrollPrev}\n onClick={\n loopMode ? undefined : () => navigateToSlide(getPrevTargetPage())\n }\n onPress={() => onArrowPress?.('prev')}\n className={`${getClassNameWithDefault(prevArrowClassName, styles.defaultPrevButton)} ${!arrowsVisible ? styles.hidden : ''}`}\n />\n\n <CarouselButton\n dir=\"next\"\n variant={arrowStyleVariant}\n size={resolvedArrowSize}\n focusStyle={focusStyle}\n iconType={iconType}\n hideDisabledArrow={hideDisabledArrow}\n overrideHideDisabledArrow={loopMode ? undefined : !canScrollNext}\n onClick={\n loopMode ? undefined : () => navigateToSlide(getNextTargetPage())\n }\n onPress={() => onArrowPress?.('next')}\n className={`${getClassNameWithDefault(nextArrowClassName, styles.defaultNextButton)} ${!arrowsVisible ? styles.hidden : ''}`}\n />\n </div>\n\n <div className={styles.hiddenTabs}>\n <AriaCarouselTabs>\n {(page) => (\n <AriaCarouselTab\n key={page.index}\n index={page.index}\n data-index={page.index}\n data-slide-tab=\"true\"\n tabIndex={-1}\n />\n )}\n </AriaCarouselTabs>\n </div>\n\n {autoPlay && (\n <div\n className={`${styles.autoplayControlWrapper} ${getClassNameWithDefault(autoplayControlClassName, styles.defaultAutoplayControl)}`}\n >\n <AutoplayControl\n variant={autoPlayStyleVariant}\n size={autoPlayControlSize}\n className=\"\"\n onPress={onAutoplayPress}\n />\n </div>\n )}\n\n {shouldShowDots && (\n <CarouselDots\n totalItems={totalPages}\n currentPage={currentPage}\n onDotClick={(index) => navigateToSlide(index)}\n onPress={onDotPress}\n focusStyle={focusStyle}\n dotsSize={dotsSize}\n variant={dotsVariant}\n className={getClassNameWithDefault(\n dotsContainerClassName,\n styles.defaultDotsContainer,\n )}\n dotsWrapperClassName={dotsWrapperClassName}\n dotClassName={dotClassName}\n activeDotClassName={activeDotClassName}\n isTransitioning={isTransitioning}\n />\n )}\n </AriaCarousel>\n </div>\n );\n};\n\nexport default Carousel;\n"],"names":["carousel","cva","styles","variants","looping","infinite","backToStart","native","off","Carousel","children","ariaLabel","ariaDescribedby","itemsPerPage","spaceBetweenItems","scrollPadding","iconType","arrowStyleVariant","arrowSize","hideDisabledArrow","showArrowsOnHover","focusStyle","dotsSize","dotsVariant","hideDots","autoPlay","autoPlayInterval","autoPlayStyleVariant","autoPlayControlSize","mouseDragging","carouselWrapperClassName","prevArrowClassName","nextArrowClassName","autoplayControlClassName","dotsContainerClassName","dotsWrapperClassName","dotClassName","activeDotClassName","itemWrapperClassName","scrollerClassName","activeItemClassName","onArrowPress","onDotPress","onAutoplayPress","controlsRef","onNavigationStateChange","items","React","Children","toArray","totalItems","length","breakpoint","useBreakpoint","resolvedItemsPerPage","resolveResponsiveProp","resolvedSpaceBetweenItems","resolvedScrollPadding","resolvedArrowSize","resolvedHideDots","safeItemsPerPage","Math","max","wholeItemsPerPage","floor","pageItemGroups","useMemo","groups","Array","from","_","index","reduce","accumulator","currentGroup","at","push","deficit","fill","splice","unshift","carouselRef","useRef","ariaCarouselRef","dragEndResetTimeoutRef","dragEndSyncTimeoutRef","scrollerRef","itemElementsRef","currentPage","setCurrentPage","useState","prevPage","setPrevPage","canScrollPrev","setCanScrollPrev","canScrollNext","setCanScrollNext","ariaTabsPageCount","setAriaTabsPageCount","firstVisibleItemIndex","setFirstVisibleItemIndex","isDragging","setIsDragging","isHovered","setIsHovered","isFocused","setIsFocused","isTransitioning","dragStartPosition","setDragStartPosition","loopMode","totalPages","shouldShowDots","getClassNameWithDefault","customClassName","defaultClassName","getScrollerElement","useCallback","current","querySelector","scrollToPage","scroller","pageIndex","targetItemIndex","targetItem","scrollerRect","getBoundingClientRect","itemRect","targetScrollLeft","scrollLeft","left","scrollTo","behavior","navigateToSlide","targetTab","click","syncCurrentPageFromVisibleItem","itemElements","querySelectorAll","scrollerLeft","closestItemIndex","closestDistance","Number","POSITIVE_INFINITY","forEach","element","parseInt","dataset","itemIndex","isNaN","distance","abs","itemsPerPageWhole","nextPage","min","navigateToPreviousSlide","targetPage","scrollBy","clientWidth","window","setTimeout","navigateToNextSlide","useEffect","navigationState","canGoPrev","canGoNext","toNavigationState","prev","next","goToSlide","clearTimeout","preventLinkActivation","e","target","Element","closest","preventDefault","stopPropagation","handleMouseDown","x","clientX","y","clientY","handleMouseMove","dx","dy","sqrt","handleMouseUp","carouselElement","addEventListener","removeEventListener","HTMLElement","classList","remove","slideLeft","add","slideRight","animationFrameId","scheduleAriaPageCountUpdate","requestAnimationFrame","nextCount","previousCount","updateAriaPageCount","observer","MutationObserver","observe","childList","subtree","attributes","attributeFilter","cancelAnimationFrame","disconnect","scheduleScrollNavigationUpdate","updateScrollNavigation","maxScrollLeft","scrollWidth","hasScrollableOverflow","nextCanScrollPrev","nextCanScrollNext","viewportStart","nextFirstVisibleItemIndex","find","item","offsetLeft","offsetWidth","parsedFirstVisibleItemIndex","safeFirstVisibleItemIndex","visibleItemCount","ceil","visibleWindowEndIndex","itemIndexString","removeAttribute","setAttribute","nextPageIndexFromVisibleItem","map","page","resolvedPageIndex","pageStartIndex","nextPageIndex","previousValue","previousPage","resizeObserver","ResizeObserver","nextItemElements","refreshItemElements","handleImageLoad","passive","interactionHandlers","onMouseEnter","onMouseLeave","onFocus","onBlur","currentTarget","contains","relatedTarget","arrowsVisible","cssVars","String","Object","keys","getCssVariables","focusProps","isFocusVisible","useFocusRing","activeItemIndices","jsx","className","classes","carouselWrapper","isInteger","showPartialItems","hasScrollPadding","trim","defaultCarouselWrapper","join","getCarouselWrapperClasses","ref","style","role","getDefaultAriaLabel","jsxs","AriaCarousel","loop","autoplay","autoplayInterval","onActivePageIndexChange","onDragStart","nativeEvent","onDragEnd","toString","AriaCarouselScroller","focusStyleVariants","gap","gapSpacePerItem","gridAutoColumns","getScrollerStyles","tabIndex","onKeyDown","key","prevButton","disabled","nextButton","child","isActiveItem","includes","itemClasses","filter","Boolean","AriaCarouselItem","controls","showOnHover","CarouselButton","dir","variant","size","overrideHideDisabledArrow","onClick","onPress","defaultPrevButton","hidden","defaultNextButton","hiddenTabs","AriaCarouselTabs","AriaCarouselTab","autoplayControlWrapper","defaultAutoplayControl","AutoplayControl","CarouselDots","onDotClick","defaultDotsContainer"],"mappings":"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"}
|
|
@@ -29,6 +29,12 @@ export interface CarouselButtonProps {
|
|
|
29
29
|
* @default false
|
|
30
30
|
*/
|
|
31
31
|
isDisabled?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Override the hideDisabledArrow state when itemsPerPage > 1 and looping is off
|
|
34
|
+
* eg, when itemsPerPage=3, scrolling 4/5 into view, enables the prev arrow to be enabled/made visible
|
|
35
|
+
* @private Internal use only
|
|
36
|
+
*/
|
|
37
|
+
overrideHideDisabledArrow?: boolean;
|
|
32
38
|
/**
|
|
33
39
|
* Additional CSS class name for the button container
|
|
34
40
|
*/
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{jsx as e}from"react/jsx-runtime";import{forwardRef as t,useState as r,useRef as a,useEffect as i}from"react";import{e as
|
|
1
|
+
import{jsx as e}from"react/jsx-runtime";import{forwardRef as t,useState as r,useRef as a,useEffect as i}from"react";import{e as o,i as n}from"../../../IconButton.module-C7YCy-MU.js";import{useFocusRing as s}from"@react-aria/focus";import{focusStyleVariants as d}from"../../../utils/focus/focusStyles.js";import{Icon as l}from"../../Icon/Icon.js";import '../../../assets/CarouselButton.css';const u={arrowContainer:"_arrowContainer_lk4ma_1",iconButton:"_iconButton_lk4ma_19",hideDisabledArrow:"_hideDisabledArrow_lk4ma_25",neutral:"_neutral_lk4ma_35",white:"_white_lk4ma_47",shapeFlat:"_shapeFlat_lk4ma_65",shapeElevated:"_shapeElevated_lk4ma_78",gradient:"_gradient_lk4ma_102",next:"_next_lk4ma_109",fullHeight:"_fullHeight_lk4ma_143",prev:"_prev_lk4ma_154"},c=t(function(t,c){const{dir:v,variant:m="neutral",size:f="md",focusStyle:p="default",hideDisabledArrow:h=!1,isDisabled:b=!1,overrideHideDisabledArrow:_,iconType:$="chevron",className:w="",buttonClassName:k="",onClick:y,onPress:E,standalone:g=!1}=t,{isFocusVisible:x,focusProps:C,isFocused:D}=s(),A="prev"===v?u.prev:u.next,[F,L]=r(!1),[N,B]=r(!1),[M,S]=r(!1),[H,P]=r(!1),j=a(null),I=a(null);i(()=>{var e;I.current&&(e=I.current,I.current=e,j.current=e,c&&("function"==typeof c?c(e):c.current=e))},[c]);const U=m&&u[m]||"",q="gradient"===m,z=g?b:_??M;i(()=>{if(g)return;const e=I.current;if(!e)return;S("true"===e.getAttribute("aria-disabled"));const t=new MutationObserver(t=>{t.forEach(t=>{if("attributes"===t.type&&"aria-disabled"===t.attributeName){const t="true"===e.getAttribute("aria-disabled");S(t),t&&(L(!1),B(!1),P(!1))}})});return t.observe(e,{attributes:!0,attributeFilter:["aria-disabled"]}),()=>{t.disconnect()}},[g]),i(()=>{if(!I.current)return;const e=I.current,t=t=>{if(t.target===e&&x&&(P(!0),!g)){const t=e.closest('[role="region"][aria-roledescription="carousel"], .carouselWrapper');if(t){t.querySelectorAll('[dir="prev"], [dir="next"]').forEach(t=>{t!==e&&t instanceof HTMLElement&&t.dispatchEvent(new CustomEvent("carousel:hideFocus"))})}}},r=()=>{P(!1)},a=()=>{P(!1)};return e.addEventListener("focus",t),e.addEventListener("blur",r),e.addEventListener("carousel:hideFocus",a),()=>{e.removeEventListener("focus",t),e.removeEventListener("blur",r),e.removeEventListener("carousel:hideFocus",a)}},[x,g]),i(()=>{x?D&&x&&P(!0):P(!1)},[x,D]);const K=q&&H?d({focusStyle:p}):"",O=()=>{z||(y&&y(),E&&E())},T={className:`${u.arrowContainer} ${A} ${h?u.hideDisabledArrow:""} ${U||""} ${q?u.fullHeight:""} ${K} ${w||""}`,...C,...z?{}:{onMouseEnter:()=>L(!0),onMouseLeave:()=>L(!1),onMouseDown:()=>B(!0),onMouseUp:()=>B(!1)},"data-hovered":!(z||!F)||void 0,"data-pressed":!(z||!N)||void 0,"data-disabled":!!z||void 0,"data-focused":!(z||!D)||void 0,"data-focus-visible":!!H||void 0,ref:I,tabIndex:g?h&&z?-1:0:z?-1:0,onKeyDown:e=>{g&&z||" "!==e.key&&"Enter"!==e.key||e.preventDefault()},onKeyUp:e=>{g&&z||" "!==e.key&&"Enter"!==e.key||z||(e.preventDefault(),g?O():I.current&&I.current.click())},"aria-label":`${"prev"===v?"Previous":"Next"} ${g?"item":"slide"}${z?", unavailable":""}`,"aria-disabled":g||void 0===_?void 0:!!_||void 0,role:"button"},V=/* @__PURE__ */e("div",{className:`${(()=>{let e="neutral",t="quaternary";"white"===m&&(e="white",t="secondary");const r=n.iconButton,a=n[f]||"",i=`${e}${t.charAt(0).toUpperCase()+t.slice(1)}`;return`${r} ${a} ${n[i]||""} ${!q&&H?d({focusStyle:p}):""} ${k||""}`})()} ${u.iconButton}`,"data-focused":!(z||!D||!H)||void 0,"data-focus-visible":!(z||!H)||void 0,"data-parent-hovered":!(z||!F)||void 0,"data-parent-pressed":!(z||!N)||void 0,"data-parent-disabled":g?void 0:!!z||void 0,"aria-hidden":"true",children:/* @__PURE__ */e(l,{iconName:`${$}-${"prev"===v?"left":"right"}`,color:(()=>{switch(m){case"white":return"whitePrimary";case"gradient":return"accentPrimary";default:return"whiteOnVibrant"}})(),iconSize:"sm"===f?"0.75x":"lg"===f?"2x":"md"===f?"1.25x":"1x","aria-hidden":"true"})});return g?/* @__PURE__ */e("button",{...T,onClick:O,children:V}):/* @__PURE__ */e(o,{dir:v,...T,onClick:O,children:V})});c.displayName="CarouselButton";export{c as CarouselButton,c as default};
|
|
2
2
|
//# sourceMappingURL=CarouselButton.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CarouselButton.js","sources":["../../../../src/components/Carousel/CarouselButton/CarouselButton.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect, forwardRef } from 'react';\nimport { CarouselButton as AriaCarouselButton } from 'react-aria-carousel';\nimport { useFocusRing } from '@react-aria/focus';\nimport styles from './CarouselButton.module.css';\nimport iconButtonStyles from '../../IconButton/IconButton.module.css';\nimport { focusStyleVariants } from '../../../utils/focus/focusStyles';\nimport { Icon } from '../../Icon/Icon';\n\nexport interface CarouselButtonProps {\n /**\n * Direction of the button (prev or next)\n */\n dir: 'prev' | 'next';\n\n /**\n * Button style variant\n * @default 'neutral'\n */\n variant?: 'neutral' | 'white' | 'shapeFlat' | 'shapeElevated' | 'gradient';\n\n /**\n * Button size\n * @default 'md'\n */\n size?: 'sm' | 'md' | 'lg';\n\n /**\n * Focus style\n * @default 'default'\n */\n focusStyle?: 'default' | 'white';\n\n /**\n * Whether to hide the button when disabled\n * @default false\n */\n hideDisabledArrow?: boolean;\n\n /**\n * Whether the button is disabled (for standalone use)\n * @default false\n */\n isDisabled?: boolean;\n\n /**\n * Additional CSS class name for the button container\n */\n className?: string;\n\n /**\n * Additional CSS class name for the button content\n */\n buttonClassName?: string;\n\n /**\n * Custom click handler for implementing custom navigation behavior\n */\n onClick?: () => void;\n\n /**\n * Callback fired when the button is pressed\n */\n onPress?: () => void;\n\n /**\n * Whether to use standalone mode (outside carousel context)\n * @default false\n */\n standalone?: boolean;\n\n // Internal prop to manage the icon type\n /**\n * @private\n */\n iconType?: 'chevron';\n}\n\nexport const CarouselButton = forwardRef<\n HTMLButtonElement,\n CarouselButtonProps\n>(function CarouselButton(props, forwardedRef) {\n const {\n dir,\n variant = 'neutral',\n size = 'md',\n focusStyle = 'default',\n hideDisabledArrow = false,\n isDisabled = false,\n iconType = 'chevron',\n className = '',\n buttonClassName = '',\n onClick,\n onPress,\n standalone = false,\n } = props;\n const { isFocusVisible, focusProps, isFocused } = useFocusRing();\n const directionClass = dir === 'prev' ? styles.prev : styles.next;\n const [isHovered, setIsHovered] = useState(false);\n const [isPressed, setIsPressed] = useState(false);\n const [carouselIsDisabled, setCarouselIsDisabled] = useState(false);\n const [shouldShowFocusRing, setShouldShowFocusRing] = useState(false);\n\n // Internal ref for managing the button element\n const internalButtonRef = useRef<HTMLButtonElement | null>(null);\n\n // Combine the forwarded ref with our internal ref\n const buttonRef = useRef<HTMLButtonElement | null>(null);\n\n useEffect(() => {\n // Set the ref to the same element for both internal use and forwarded ref\n const setRefs = (element: HTMLButtonElement | null) => {\n buttonRef.current = element;\n internalButtonRef.current = element;\n\n if (forwardedRef) {\n if (typeof forwardedRef === 'function') {\n forwardedRef(element);\n } else {\n forwardedRef.current = element;\n }\n }\n };\n\n if (buttonRef.current) {\n setRefs(buttonRef.current);\n }\n }, [forwardedRef]);\n\n const variantStyleClass = variant ? styles[variant] || '' : '';\n\n // Determine if this button should be full height based on gradient variant\n const shouldBeFullHeight = variant === 'gradient';\n\n // For standalone mode, use the isDisabled prop directly\n // For carousel mode, track aria-disabled attribute changes\n const effectiveIsDisabled = standalone ? isDisabled : carouselIsDisabled;\n\n // Set up the MutationObserver to track disabled state changes (carousel mode only)\n useEffect(() => {\n if (standalone) return;\n\n const element = buttonRef.current;\n if (!element) return;\n\n // Set initial disabled state\n setCarouselIsDisabled(element.getAttribute('aria-disabled') === 'true');\n\n // Use MutationObserver to track changes to aria-disabled\n const observer = new MutationObserver((mutations) => {\n mutations.forEach((mutation) => {\n if (\n mutation.type === 'attributes' &&\n mutation.attributeName === 'aria-disabled'\n ) {\n const isCurrentlyDisabled =\n element.getAttribute('aria-disabled') === 'true';\n setCarouselIsDisabled(isCurrentlyDisabled);\n\n // Reset hover and press states when disabled\n if (isCurrentlyDisabled) {\n setIsHovered(false);\n setIsPressed(false);\n setShouldShowFocusRing(false);\n }\n }\n });\n });\n\n observer.observe(element, {\n attributes: true,\n attributeFilter: ['aria-disabled'],\n });\n\n // Clean up the observer on unmount\n return () => {\n observer.disconnect();\n };\n }, [standalone]);\n\n // Handle focus coordination with proper cleanup\n useEffect(() => {\n if (!buttonRef.current) return;\n\n const element = buttonRef.current;\n\n const handleFocus = (e: FocusEvent) => {\n // Only show focus ring if this element is actually focused and focus is visible\n if (e.target === element && isFocusVisible) {\n setShouldShowFocusRing(true);\n\n // Hide focus rings on sibling buttons (carousel mode only)\n if (!standalone) {\n const carouselContainer = element.closest(\n '[role=\"region\"][aria-roledescription=\"carousel\"], .carouselWrapper',\n );\n if (carouselContainer) {\n const siblingButtons = carouselContainer.querySelectorAll(\n '[dir=\"prev\"], [dir=\"next\"]',\n );\n siblingButtons.forEach((button) => {\n if (button !== element && button instanceof HTMLElement) {\n // Dispatch a custom event to tell sibling to hide its focus ring\n button.dispatchEvent(new CustomEvent('carousel:hideFocus'));\n }\n });\n }\n }\n }\n };\n\n const handleBlur = () => {\n // Always hide focus ring when losing focus\n setShouldShowFocusRing(false);\n };\n\n const handleHideFocus = () => {\n // Hide focus ring when sibling gets focus\n setShouldShowFocusRing(false);\n };\n\n element.addEventListener('focus', handleFocus);\n element.addEventListener('blur', handleBlur);\n element.addEventListener('carousel:hideFocus', handleHideFocus);\n\n return () => {\n element.removeEventListener('focus', handleFocus);\n element.removeEventListener('blur', handleBlur);\n element.removeEventListener('carousel:hideFocus', handleHideFocus);\n };\n }, [isFocusVisible, standalone]);\n\n // Update focus ring state when isFocusVisible changes\n useEffect(() => {\n if (!isFocusVisible) {\n setShouldShowFocusRing(false);\n } else if (isFocused && isFocusVisible) {\n setShouldShowFocusRing(true);\n }\n }, [isFocusVisible, isFocused]);\n\n // Map button size to icon size:\n // - 'md' button uses '1x' icon\n // - 'sm' button uses '.75x' icon\n // - 'lg' button uses '2x' icon\n const getIconSize = () => {\n if (size === 'sm') return '0.75x';\n if (size === 'lg') return '2x';\n if (size === 'md') return '1.25x';\n return '1x'; // Default fallback\n };\n\n // Get appropriate icon color based on variant\n const getIconColor = () => {\n switch (variant) {\n case 'white':\n return 'whitePrimary';\n case 'gradient':\n return 'accentPrimary';\n default:\n return 'whiteOnVibrant';\n }\n };\n\n // Apply focus class ONLY to container for full height variants\n const containerFocusClass =\n shouldBeFullHeight && shouldShowFocusRing\n ? focusStyleVariants({ focusStyle })\n : '';\n\n // Get button class styles\n const getButtonClasses = () => {\n let styleVariant = 'neutral';\n let emphasis = 'quaternary';\n\n if (variant === 'white') {\n styleVariant = 'white';\n emphasis = 'secondary';\n }\n\n const baseClass = iconButtonStyles.iconButton;\n const sizeClass = iconButtonStyles[size] || '';\n const emphasisClassKey = `${styleVariant}${emphasis.charAt(0).toUpperCase() + emphasis.slice(1)}`;\n const emphasisClass = iconButtonStyles[emphasisClassKey] || '';\n\n // Apply focus class to inner button for non-full-height buttons\n const focusClass =\n !shouldBeFullHeight && shouldShowFocusRing\n ? focusStyleVariants({ focusStyle })\n : '';\n\n return `${baseClass} ${sizeClass} ${emphasisClass} ${focusClass} ${buttonClassName || ''}`;\n };\n\n // Only apply hover/press handlers if not disabled\n const mouseEventHandlers = effectiveIsDisabled\n ? {}\n : {\n onMouseEnter: () => setIsHovered(true),\n onMouseLeave: () => setIsHovered(false),\n onMouseDown: () => setIsPressed(true),\n onMouseUp: () => setIsPressed(false),\n };\n\n // Handle custom click events while still using the default behavior\n const handleClick = () => {\n if (!effectiveIsDisabled) {\n if (onClick) {\n onClick();\n }\n if (onPress) {\n onPress();\n }\n }\n };\n\n // Handle keyboard events for better accessibility\n const handleKeyDown = (e: React.KeyboardEvent) => {\n // In standalone mode, don't prevent default if disabled\n if (standalone && effectiveIsDisabled) {\n return;\n }\n\n // Prevent default behavior for space and enter to avoid double-triggering\n if (e.key === ' ' || e.key === 'Enter') {\n e.preventDefault();\n }\n };\n\n const handleKeyUp = (e: React.KeyboardEvent) => {\n // In standalone mode, don't handle if disabled\n if (standalone && effectiveIsDisabled) {\n return;\n }\n\n // Trigger click on key release for space and enter\n if ((e.key === ' ' || e.key === 'Enter') && !effectiveIsDisabled) {\n e.preventDefault(); // Prevent double activation from native button behavior\n\n if (standalone) {\n // In standalone mode, call handleClick directly\n handleClick();\n } else if (buttonRef.current) {\n // In carousel mode, trigger native click to let AriaCarouselButton handle navigation\n buttonRef.current.click();\n }\n }\n };\n\n // Get the appropriate tabIndex based on disabled state and hideDisabledArrow\n const getTabIndex = () => {\n // In standalone mode, always allow focus unless hideDisabledArrow is true and button is disabled\n if (standalone) {\n return hideDisabledArrow && effectiveIsDisabled ? -1 : 0;\n }\n\n // Carousel mode logic\n if (effectiveIsDisabled) {\n return -1;\n }\n return 0;\n };\n\n // Get aria-label for the button\n const getAriaLabel = () => {\n const action = dir === 'prev' ? 'Previous' : 'Next';\n const context = standalone ? 'item' : 'slide';\n const state = effectiveIsDisabled ? ', unavailable' : '';\n return `${action} ${context}${state}`;\n };\n\n // Common button props\n const commonProps = {\n className: `${styles.arrowContainer} ${directionClass} ${hideDisabledArrow ? styles.hideDisabledArrow : ''} ${variantStyleClass || ''} ${shouldBeFullHeight ? styles.fullHeight : ''} ${containerFocusClass} ${className || ''}`,\n ...focusProps,\n ...mouseEventHandlers,\n 'data-hovered': !effectiveIsDisabled && isHovered ? true : undefined,\n 'data-pressed': !effectiveIsDisabled && isPressed ? true : undefined,\n 'data-disabled': effectiveIsDisabled ? true : undefined,\n 'data-focused': !effectiveIsDisabled && isFocused ? true : undefined,\n 'data-focus-visible': shouldShowFocusRing ? true : undefined,\n ref: buttonRef,\n tabIndex: getTabIndex(),\n onKeyDown: handleKeyDown,\n onKeyUp: handleKeyUp,\n 'aria-label': getAriaLabel(),\n role: 'button',\n };\n\n // Button content\n const buttonContent = (\n <div\n className={`${getButtonClasses()} ${styles.iconButton}`}\n data-focused={\n !effectiveIsDisabled && isFocused && shouldShowFocusRing\n ? true\n : undefined\n }\n data-focus-visible={\n !effectiveIsDisabled && shouldShowFocusRing ? true : undefined\n }\n data-parent-hovered={!effectiveIsDisabled && isHovered ? true : undefined}\n data-parent-pressed={!effectiveIsDisabled && isPressed ? true : undefined}\n // For standalone mode, don't show as disabled\n data-parent-disabled={\n standalone ? undefined : effectiveIsDisabled ? true : undefined\n }\n aria-hidden=\"true\"\n >\n <Icon\n iconName={`${iconType}-${dir === 'prev' ? 'left' : 'right'}`}\n color={getIconColor()}\n iconSize={getIconSize()}\n aria-hidden=\"true\"\n />\n </div>\n );\n\n // Render standalone button or carousel button based on mode\n if (standalone) {\n return (\n <button\n {...commonProps}\n onClick={handleClick}\n // Don't set aria-disabled for standalone buttons since we want them always enabled\n >\n {buttonContent}\n </button>\n );\n }\n\n // Default carousel mode\n return (\n <AriaCarouselButton dir={dir} {...commonProps} onClick={handleClick}>\n {buttonContent}\n </AriaCarouselButton>\n );\n});\n\nCarouselButton.displayName = 'CarouselButton';\n\nexport default CarouselButton;\n"],"names":["CarouselButton","forwardRef","props","forwardedRef","dir","variant","size","focusStyle","hideDisabledArrow","isDisabled","iconType","className","buttonClassName","onClick","onPress","standalone","isFocusVisible","focusProps","isFocused","useFocusRing","directionClass","styles","prev","next","isHovered","setIsHovered","useState","isPressed","setIsPressed","carouselIsDisabled","setCarouselIsDisabled","shouldShowFocusRing","setShouldShowFocusRing","internalButtonRef","useRef","buttonRef","useEffect","element","current","variantStyleClass","shouldBeFullHeight","effectiveIsDisabled","getAttribute","observer","MutationObserver","mutations","forEach","mutation","type","attributeName","isCurrentlyDisabled","observe","attributes","attributeFilter","disconnect","handleFocus","e","target","carouselContainer","closest","querySelectorAll","button","HTMLElement","dispatchEvent","CustomEvent","handleBlur","handleHideFocus","addEventListener","removeEventListener","containerFocusClass","focusStyleVariants","handleClick","commonProps","arrowContainer","fullHeight","onMouseEnter","onMouseLeave","onMouseDown","onMouseUp","ref","tabIndex","onKeyDown","key","preventDefault","onKeyUp","click","role","buttonContent","jsx","styleVariant","emphasis","baseClass","iconButtonStyles","iconButton","sizeClass","emphasisClassKey","charAt","toUpperCase","slice","getButtonClasses","children","Icon","iconName","color","getIconColor","iconSize","AriaCarouselButton","displayName"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CarouselButton.js","sources":["../../../../src/components/Carousel/CarouselButton/CarouselButton.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect, forwardRef } from 'react';\nimport { CarouselButton as AriaCarouselButton } from 'react-aria-carousel';\nimport { useFocusRing } from '@react-aria/focus';\nimport styles from './CarouselButton.module.css';\nimport iconButtonStyles from '../../IconButton/IconButton.module.css';\nimport { focusStyleVariants } from '../../../utils/focus/focusStyles';\nimport { Icon } from '../../Icon/Icon';\n\nexport interface CarouselButtonProps {\n /**\n * Direction of the button (prev or next)\n */\n dir: 'prev' | 'next';\n\n /**\n * Button style variant\n * @default 'neutral'\n */\n variant?: 'neutral' | 'white' | 'shapeFlat' | 'shapeElevated' | 'gradient';\n\n /**\n * Button size\n * @default 'md'\n */\n size?: 'sm' | 'md' | 'lg';\n\n /**\n * Focus style\n * @default 'default'\n */\n focusStyle?: 'default' | 'white';\n\n /**\n * Whether to hide the button when disabled\n * @default false\n */\n hideDisabledArrow?: boolean;\n\n /**\n * Whether the button is disabled (for standalone use)\n * @default false\n */\n isDisabled?: boolean;\n\n /**\n * Override the hideDisabledArrow state when itemsPerPage > 1 and looping is off\n * eg, when itemsPerPage=3, scrolling 4/5 into view, enables the prev arrow to be enabled/made visible\n * @private Internal use only\n */\n overrideHideDisabledArrow?: boolean;\n\n /**\n * Additional CSS class name for the button container\n */\n className?: string;\n\n /**\n * Additional CSS class name for the button content\n */\n buttonClassName?: string;\n\n /**\n * Custom click handler for implementing custom navigation behavior\n */\n onClick?: () => void;\n\n /**\n * Callback fired when the button is pressed\n */\n onPress?: () => void;\n\n /**\n * Whether to use standalone mode (outside carousel context)\n * @default false\n */\n standalone?: boolean;\n\n // Internal prop to manage the icon type\n /**\n * @private\n */\n iconType?: 'chevron';\n}\n\nexport const CarouselButton = forwardRef<\n HTMLButtonElement,\n CarouselButtonProps\n>(function CarouselButton(props, forwardedRef) {\n const {\n dir,\n variant = 'neutral',\n size = 'md',\n focusStyle = 'default',\n hideDisabledArrow = false,\n isDisabled = false,\n overrideHideDisabledArrow,\n iconType = 'chevron',\n className = '',\n buttonClassName = '',\n onClick,\n onPress,\n standalone = false,\n } = props;\n const { isFocusVisible, focusProps, isFocused } = useFocusRing();\n const directionClass = dir === 'prev' ? styles.prev : styles.next;\n const [isHovered, setIsHovered] = useState(false);\n const [isPressed, setIsPressed] = useState(false);\n const [carouselIsDisabled, setCarouselIsDisabled] = useState(false);\n const [shouldShowFocusRing, setShouldShowFocusRing] = useState(false);\n\n // Internal ref for managing the button element\n const internalButtonRef = useRef<HTMLButtonElement | null>(null);\n\n // Combine the forwarded ref with our internal ref\n const buttonRef = useRef<HTMLButtonElement | null>(null);\n\n useEffect(() => {\n // Set the ref to the same element for both internal use and forwarded ref\n const setRefs = (element: HTMLButtonElement | null) => {\n buttonRef.current = element;\n internalButtonRef.current = element;\n\n if (forwardedRef) {\n if (typeof forwardedRef === 'function') {\n forwardedRef(element);\n } else {\n forwardedRef.current = element;\n }\n }\n };\n\n if (buttonRef.current) {\n setRefs(buttonRef.current);\n }\n }, [forwardedRef]);\n\n const variantStyleClass = variant ? styles[variant] || '' : '';\n\n // Determine if this button should be full height based on gradient variant\n const shouldBeFullHeight = variant === 'gradient';\n\n // For standalone mode, use the isDisabled prop directly\n // For carousel mode, track aria-disabled attribute changes\n const effectiveIsDisabled = standalone\n ? isDisabled\n : (overrideHideDisabledArrow ?? carouselIsDisabled);\n\n // Set up the MutationObserver to track disabled state changes (carousel mode only)\n useEffect(() => {\n if (standalone) return;\n\n const element = buttonRef.current;\n if (!element) return;\n\n // Set initial disabled state\n setCarouselIsDisabled(element.getAttribute('aria-disabled') === 'true');\n\n // Use MutationObserver to track changes to aria-disabled\n const observer = new MutationObserver((mutations) => {\n mutations.forEach((mutation) => {\n if (\n mutation.type === 'attributes' &&\n mutation.attributeName === 'aria-disabled'\n ) {\n const isCurrentlyDisabled =\n element.getAttribute('aria-disabled') === 'true';\n setCarouselIsDisabled(isCurrentlyDisabled);\n\n // Reset hover and press states when disabled\n if (isCurrentlyDisabled) {\n setIsHovered(false);\n setIsPressed(false);\n setShouldShowFocusRing(false);\n }\n }\n });\n });\n\n observer.observe(element, {\n attributes: true,\n attributeFilter: ['aria-disabled'],\n });\n\n // Clean up the observer on unmount\n return () => {\n observer.disconnect();\n };\n }, [standalone]);\n\n // Handle focus coordination with proper cleanup\n useEffect(() => {\n if (!buttonRef.current) return;\n\n const element = buttonRef.current;\n\n const handleFocus = (e: FocusEvent) => {\n // Only show focus ring if this element is actually focused and focus is visible\n if (e.target === element && isFocusVisible) {\n setShouldShowFocusRing(true);\n\n // Hide focus rings on sibling buttons (carousel mode only)\n if (!standalone) {\n const carouselContainer = element.closest(\n '[role=\"region\"][aria-roledescription=\"carousel\"], .carouselWrapper',\n );\n if (carouselContainer) {\n const siblingButtons = carouselContainer.querySelectorAll(\n '[dir=\"prev\"], [dir=\"next\"]',\n );\n siblingButtons.forEach((button) => {\n if (button !== element && button instanceof HTMLElement) {\n // Dispatch a custom event to tell sibling to hide its focus ring\n button.dispatchEvent(new CustomEvent('carousel:hideFocus'));\n }\n });\n }\n }\n }\n };\n\n const handleBlur = () => {\n // Always hide focus ring when losing focus\n setShouldShowFocusRing(false);\n };\n\n const handleHideFocus = () => {\n // Hide focus ring when sibling gets focus\n setShouldShowFocusRing(false);\n };\n\n element.addEventListener('focus', handleFocus);\n element.addEventListener('blur', handleBlur);\n element.addEventListener('carousel:hideFocus', handleHideFocus);\n\n return () => {\n element.removeEventListener('focus', handleFocus);\n element.removeEventListener('blur', handleBlur);\n element.removeEventListener('carousel:hideFocus', handleHideFocus);\n };\n }, [isFocusVisible, standalone]);\n\n // Update focus ring state when isFocusVisible changes\n useEffect(() => {\n if (!isFocusVisible) {\n setShouldShowFocusRing(false);\n } else if (isFocused && isFocusVisible) {\n setShouldShowFocusRing(true);\n }\n }, [isFocusVisible, isFocused]);\n\n // Map button size to icon size:\n // - 'md' button uses '1x' icon\n // - 'sm' button uses '.75x' icon\n // - 'lg' button uses '2x' icon\n const getIconSize = () => {\n if (size === 'sm') return '0.75x';\n if (size === 'lg') return '2x';\n if (size === 'md') return '1.25x';\n return '1x'; // Default fallback\n };\n\n // Get appropriate icon color based on variant\n const getIconColor = () => {\n switch (variant) {\n case 'white':\n return 'whitePrimary';\n case 'gradient':\n return 'accentPrimary';\n default:\n return 'whiteOnVibrant';\n }\n };\n\n // Apply focus class ONLY to container for full height variants\n const containerFocusClass =\n shouldBeFullHeight && shouldShowFocusRing\n ? focusStyleVariants({ focusStyle })\n : '';\n\n // Get button class styles\n const getButtonClasses = () => {\n let styleVariant = 'neutral';\n let emphasis = 'quaternary';\n\n if (variant === 'white') {\n styleVariant = 'white';\n emphasis = 'secondary';\n }\n\n const baseClass = iconButtonStyles.iconButton;\n const sizeClass = iconButtonStyles[size] || '';\n const emphasisClassKey = `${styleVariant}${emphasis.charAt(0).toUpperCase() + emphasis.slice(1)}`;\n const emphasisClass = iconButtonStyles[emphasisClassKey] || '';\n\n // Apply focus class to inner button for non-full-height buttons\n const focusClass =\n !shouldBeFullHeight && shouldShowFocusRing\n ? focusStyleVariants({ focusStyle })\n : '';\n\n return `${baseClass} ${sizeClass} ${emphasisClass} ${focusClass} ${buttonClassName || ''}`;\n };\n\n // Only apply hover/press handlers if not disabled\n const mouseEventHandlers = effectiveIsDisabled\n ? {}\n : {\n onMouseEnter: () => setIsHovered(true),\n onMouseLeave: () => setIsHovered(false),\n onMouseDown: () => setIsPressed(true),\n onMouseUp: () => setIsPressed(false),\n };\n\n // Handle custom click events while still using the default behavior\n const handleClick = () => {\n if (!effectiveIsDisabled) {\n if (onClick) {\n onClick();\n }\n if (onPress) {\n onPress();\n }\n }\n };\n\n // Handle keyboard events for better accessibility\n const handleKeyDown = (e: React.KeyboardEvent) => {\n // In standalone mode, don't prevent default if disabled\n if (standalone && effectiveIsDisabled) {\n return;\n }\n\n // Prevent default behavior for space and enter to avoid double-triggering\n if (e.key === ' ' || e.key === 'Enter') {\n e.preventDefault();\n }\n };\n\n const handleKeyUp = (e: React.KeyboardEvent) => {\n // In standalone mode, don't handle if disabled\n if (standalone && effectiveIsDisabled) {\n return;\n }\n\n // Trigger click on key release for space and enter\n if ((e.key === ' ' || e.key === 'Enter') && !effectiveIsDisabled) {\n e.preventDefault(); // Prevent double activation from native button behavior\n\n if (standalone) {\n // In standalone mode, call handleClick directly\n handleClick();\n } else if (buttonRef.current) {\n // In carousel mode, trigger native click to let AriaCarouselButton handle navigation\n buttonRef.current.click();\n }\n }\n };\n\n // Get the appropriate tabIndex based on disabled state and hideDisabledArrow\n const getTabIndex = () => {\n // In standalone mode, always allow focus unless hideDisabledArrow is true and button is disabled\n if (standalone) {\n return hideDisabledArrow && effectiveIsDisabled ? -1 : 0;\n }\n\n // Carousel mode logic\n if (effectiveIsDisabled) {\n return -1;\n }\n return 0;\n };\n\n // Get aria-label for the button\n const getAriaLabel = () => {\n const action = dir === 'prev' ? 'Previous' : 'Next';\n const context = standalone ? 'item' : 'slide';\n const state = effectiveIsDisabled ? ', unavailable' : '';\n return `${action} ${context}${state}`;\n };\n\n // Common button props\n const commonProps = {\n className: `${styles.arrowContainer} ${directionClass} ${hideDisabledArrow ? styles.hideDisabledArrow : ''} ${variantStyleClass || ''} ${shouldBeFullHeight ? styles.fullHeight : ''} ${containerFocusClass} ${className || ''}`,\n ...focusProps,\n ...mouseEventHandlers,\n 'data-hovered': !effectiveIsDisabled && isHovered ? true : undefined,\n 'data-pressed': !effectiveIsDisabled && isPressed ? true : undefined,\n 'data-disabled': effectiveIsDisabled ? true : undefined,\n 'data-focused': !effectiveIsDisabled && isFocused ? true : undefined,\n 'data-focus-visible': shouldShowFocusRing ? true : undefined,\n ref: buttonRef,\n tabIndex: getTabIndex(),\n onKeyDown: handleKeyDown,\n onKeyUp: handleKeyUp,\n 'aria-label': getAriaLabel(),\n 'aria-disabled':\n !standalone && overrideHideDisabledArrow !== undefined\n ? overrideHideDisabledArrow\n ? true\n : undefined\n : undefined,\n role: 'button',\n };\n\n // Button content\n const buttonContent = (\n <div\n className={`${getButtonClasses()} ${styles.iconButton}`}\n data-focused={\n !effectiveIsDisabled && isFocused && shouldShowFocusRing\n ? true\n : undefined\n }\n data-focus-visible={\n !effectiveIsDisabled && shouldShowFocusRing ? true : undefined\n }\n data-parent-hovered={!effectiveIsDisabled && isHovered ? true : undefined}\n data-parent-pressed={!effectiveIsDisabled && isPressed ? true : undefined}\n // For standalone mode, don't show as disabled\n data-parent-disabled={\n standalone ? undefined : effectiveIsDisabled ? true : undefined\n }\n aria-hidden=\"true\"\n >\n <Icon\n iconName={`${iconType}-${dir === 'prev' ? 'left' : 'right'}`}\n color={getIconColor()}\n iconSize={getIconSize()}\n aria-hidden=\"true\"\n />\n </div>\n );\n\n // Render standalone button or carousel button based on mode\n if (standalone) {\n return (\n <button\n {...commonProps}\n onClick={handleClick}\n // Don't set aria-disabled for standalone buttons since we want them always enabled\n >\n {buttonContent}\n </button>\n );\n }\n\n // Default carousel mode\n return (\n <AriaCarouselButton dir={dir} {...commonProps} onClick={handleClick}>\n {buttonContent}\n </AriaCarouselButton>\n );\n});\n\nCarouselButton.displayName = 'CarouselButton';\n\nexport default CarouselButton;\n"],"names":["CarouselButton","forwardRef","props","forwardedRef","dir","variant","size","focusStyle","hideDisabledArrow","isDisabled","overrideHideDisabledArrow","iconType","className","buttonClassName","onClick","onPress","standalone","isFocusVisible","focusProps","isFocused","useFocusRing","directionClass","styles","prev","next","isHovered","setIsHovered","useState","isPressed","setIsPressed","carouselIsDisabled","setCarouselIsDisabled","shouldShowFocusRing","setShouldShowFocusRing","internalButtonRef","useRef","buttonRef","useEffect","element","current","variantStyleClass","shouldBeFullHeight","effectiveIsDisabled","getAttribute","observer","MutationObserver","mutations","forEach","mutation","type","attributeName","isCurrentlyDisabled","observe","attributes","attributeFilter","disconnect","handleFocus","e","target","carouselContainer","closest","querySelectorAll","button","HTMLElement","dispatchEvent","CustomEvent","handleBlur","handleHideFocus","addEventListener","removeEventListener","containerFocusClass","focusStyleVariants","handleClick","commonProps","arrowContainer","fullHeight","onMouseEnter","onMouseLeave","onMouseDown","onMouseUp","ref","tabIndex","onKeyDown","key","preventDefault","onKeyUp","click","role","buttonContent","jsx","styleVariant","emphasis","baseClass","iconButtonStyles","iconButton","sizeClass","emphasisClassKey","charAt","toUpperCase","slice","getButtonClasses","children","Icon","iconName","color","getIconColor","iconSize","AriaCarouselButton","displayName"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e={"aria-label":{control:"text",description:"Accessible name for the carousel - describes the purpose or content for screen readers",table:{category:"Accessibility",type:{summary:"string"}}},"aria-describedby":{control:"text",description:"ID of element that describes the carousel",table:{category:"Accessibility",type:{summary:"string"}}},looping:{control:{type:"radio"},options:["off","infinite","backToStart"],description:'Looping behavior: "infinite" for continuous cycling, "backToStart" for jumping back to start, "off" to disable looping',defaultValue:"off",table:{category:"Core Configuration",type:{summary:'"infinite" | "backToStart" | "off"'},defaultValue:{summary:'"off"'}}},itemsPerPage:{control:{type:"number",min:1,max:10,step:.25},description:"Number of items to display per page (minimum: 1). Decimal values (e.g., 2.25) can be used to show partial items for peek effects",defaultValue:1,table:{category:"Core Configuration",type:{summary:"number | ResponsiveValue<number>"},defaultValue:{summary:"1"}}},spaceBetweenItems:{control:{type:"number",min:0,max:100},description:"Space between carousel items in pixels. Works with both scroll padding and fractional items",defaultValue:0,table:{category:"Core Configuration",type:{summary:"number | ResponsiveValue<number>"},defaultValue:{summary:"0"}}},scrollPadding:{control:"text",description:'Amount of padding to add to create a "peek" effect. Accepts any valid CSS dimension (px, rem, em, %) - e.g., "15%", "20px", "2rem"',table:{category:"Core Configuration",type:{summary:"string | ResponsiveValue<string>"},defaultValue:{summary:"undefined"}}},mouseDragging:{control:"boolean",description:"Whether to enable mouse dragging for the carousel",defaultValue:!0,table:{category:"Core Configuration",type:{summary:"boolean"},defaultValue:{summary:"true"}}},iconType:{table:{disable:!0}},arrowStyleVariant:{control:{type:"select"},options:["neutral","white","shapeFlat","shapeElevated","gradient"],description:"Style variant for navigation arrow buttons",defaultValue:"neutral",table:{category:"Button and Controls",type:{summary:'"neutral" | "white" | "shapeFlat" | "shapeElevated" | "gradient"'},defaultValue:{summary:'"neutral"'}}},arrowSize:{control:{type:"select"},options:["sm","md","lg"],description:"Size of navigation buttons",defaultValue:"md",table:{category:"Button and Controls",type:{summary:'"sm" | "md" | "lg" | ResponsiveValue<"sm" | "md" | "lg">'},defaultValue:{summary:'"md"'}}},hideDisabledArrow:{control:"boolean",description:"Whether to hide navigation buttons when they are disabled (e.g., at first/last slide when looping is off)",defaultValue:!1,table:{category:"Button and Controls",type:{summary:"boolean"},defaultValue:{summary:"false"}}},showArrowsOnHover:{control:"boolean",description:"Whether to show arrows only when hovering over the carousel or when it has focus",defaultValue:!1,table:{category:"Button and Controls",type:{summary:"boolean | ResponsiveValue<boolean>"},defaultValue:{summary:"false"}}},focusStyle:{control:{type:"radio"},options:["default","white"],description:'Focus style for interactive elements - use "white" for dark backgrounds',defaultValue:"default",table:{category:"Button and Controls",type:{summary:'"default" | "white"'},defaultValue:{summary:'"default"'}}},hideDots:{control:"boolean",description:"Whether to hide pagination dots. Can be set responsively to show/hide dots at different breakpoints",defaultValue:!1,table:{category:"Dots/Pagination",type:{summary:"boolean | ResponsiveValue<boolean>"},defaultValue:{summary:"false"}}},dotsSize:{control:{type:"radio"},options:["md","lg"],description:"Size of pagination dots when visible",defaultValue:"md",table:{category:"Dots/Pagination",type:{summary:'"md" | "lg"'},defaultValue:{summary:'"md"'}}},dotsVariant:{control:{type:"radio"},options:["standard","transparent"],description:"Visual style of pagination dots",defaultValue:"standard",table:{category:"Dots/Pagination",type:{summary:'"standard" | "transparent"'},defaultValue:{summary:'"standard"'}}},autoPlay:{control:"boolean",description:"Whether the autoplay is enabled",defaultValue:!1,table:{category:"Autoplay",type:{summary:"boolean"},defaultValue:{summary:"false"}}},autoPlayInterval:{control:{type:"number",min:1e3,max:1e4,step:500},description:"Interval in milliseconds between slides during autoplay",defaultValue:2e3,table:{category:"Autoplay",type:{summary:"number"},defaultValue:{summary:"2000"}}},autoPlayStyleVariant:{control:{type:"select"},options:["neutralVibrant","neutralSubtle","whiteVibrant","whiteSubtle"],description:"Style variant for autoplay control button",defaultValue:"neutralVibrant",table:{category:"Autoplay",type:{summary:'"neutralVibrant" | "neutralSubtle" | "whiteVibrant" | "whiteSubtle"'},defaultValue:{summary:'"neutralVibrant"'}}},autoPlayControlSize:{control:{type:"radio"},options:["sm","md"],description:"Size of autoplay control button",defaultValue:"md",table:{category:"Autoplay",type:{summary:'"sm" | "md"'},defaultValue:{summary:'"md"'}}},carouselWrapperClassName:{control:"text",description:'Custom class name for the outermost wrapper to allow custom styles - use your preferred naming convention (helper: "defaultCarouselWrapper")',table:{category:"Custom Styling & Positioning",type:{summary:"string"}}},prevArrowClassName:{control:"text",description:'Custom class name for the previous button to allow custom styles - use your preferred naming convention (helper: "defaultPrevButton")',table:{category:"Custom Styling & Positioning",type:{summary:"string"}}},nextArrowClassName:{control:"text",description:'Custom class name for the next button to allow custom styles - use your preferred naming convention (helper: "defaultNextButton")',table:{category:"Custom Styling & Positioning",type:{summary:"string"}}},autoplayControlClassName:{control:"text",description:'Custom class name for the autoplay control to allow custom styles - use your preferred naming convention (helper: "autoplayControl")',table:{category:"Custom Styling & Positioning",type:{summary:"string"}}},dotsContainerClassName:{control:"text",description:'Custom class name for the dots container to allow custom styles - use your preferred naming convention (helper: "defaultDotsContainer")',table:{category:"Custom Styling & Positioning",type:{summary:"string"}}},dotsWrapperClassName:{control:"text",description:"Custom class name for the dots wrapper to allow custom styles - use your preferred naming convention",table:{category:"Custom Styling & Positioning",type:{summary:"string"}}},dotClassName:{control:"text",description:"Custom class name for individual dots to allow custom styles - use your preferred naming convention",table:{category:"Custom Styling & Positioning",type:{summary:"string"}}},activeDotClassName:{control:"text",description:"Custom class name for the active dot to allow custom styles - use your preferred naming convention",table:{category:"Custom Styling & Positioning",type:{summary:"string"}}},itemWrapperClassName:{control:"text",description:"Custom class name for individual carousel item wrappers to allow custom styles - use your preferred naming convention",table:{category:"Custom Styling & Positioning",type:{summary:"string"}}},activeItemClassName:{control:"text",description:"Custom class name for the currently active/visible carousel item to allow custom styles - use your preferred naming convention",table:{category:"Custom Styling & Positioning",type:{summary:"string"}}},onArrowPress:{control:!1,description:'Callback fired when a navigation arrow button (prev/next) is pressed. Receives the direction ("prev" or "next") as a parameter',table:{category:"Event Callbacks",type:{summary:'(direction: "prev" | "next") => void'}}},onDotPress:{control:!1,description:"Callback fired when a pagination dot is pressed. Receives the dot index (0-based) as a parameter",table:{category:"Event Callbacks",type:{summary:"(index: number) => void"}}},onAutoplayPress:{control:!1,description:'Callback fired when the autoplay play/pause button is pressed. Receives the state ("play" or "pause") as a parameter',table:{category:"Event Callbacks",type:{summary:'(state: "play" | "pause") => void'}}},children:{control:{type:"object"},description:"Content to be displayed in the carousel",table:{category:"Content",disable:!0}}};export{e as carouselArgTypes};
|
|
1
|
+
const e={"aria-label":{control:"text",description:"Accessible name for the carousel - describes the purpose or content for screen readers",table:{category:"Accessibility",type:{summary:"string"}}},"aria-describedby":{control:"text",description:"ID of element that describes the carousel",table:{category:"Accessibility",type:{summary:"string"}}},looping:{control:{type:"radio"},options:["off","infinite","backToStart"],description:'Looping behavior: "infinite" for continuous cycling, "backToStart" for jumping back to start, "off" to disable looping',defaultValue:"off",table:{category:"Core Configuration",type:{summary:'"infinite" | "backToStart" | "off"'},defaultValue:{summary:'"off"'}}},itemsPerPage:{control:{type:"number",min:1,max:10,step:.25},description:"Number of items to display per page (minimum: 1). Decimal values (e.g., 2.25) can be used to show partial items for peek effects",defaultValue:1,table:{category:"Core Configuration",type:{summary:"number | ResponsiveValue<number>"},defaultValue:{summary:"1"}}},spaceBetweenItems:{control:{type:"number",min:0,max:100},description:"Space between carousel items in pixels. Works with both scroll padding and fractional items",defaultValue:0,table:{category:"Core Configuration",type:{summary:"number | ResponsiveValue<number>"},defaultValue:{summary:"0"}}},scrollPadding:{control:"text",description:'Amount of padding to add to create a "peek" effect. Accepts any valid CSS dimension (px, rem, em, %) - e.g., "15%", "20px", "2rem"',table:{category:"Core Configuration",type:{summary:"string | ResponsiveValue<string>"},defaultValue:{summary:"undefined"}}},mouseDragging:{control:"boolean",description:"Whether to enable mouse dragging for the carousel",defaultValue:!0,table:{category:"Core Configuration",type:{summary:"boolean"},defaultValue:{summary:"true"}}},iconType:{table:{disable:!0}},arrowStyleVariant:{control:{type:"select"},options:["neutral","white","shapeFlat","shapeElevated","gradient"],description:"Style variant for navigation arrow buttons",defaultValue:"neutral",table:{category:"Button and Controls",type:{summary:'"neutral" | "white" | "shapeFlat" | "shapeElevated" | "gradient"'},defaultValue:{summary:'"neutral"'}}},arrowSize:{control:{type:"select"},options:["sm","md","lg"],description:"Size of navigation buttons",defaultValue:"md",table:{category:"Button and Controls",type:{summary:'"sm" | "md" | "lg" | ResponsiveValue<"sm" | "md" | "lg">'},defaultValue:{summary:'"md"'}}},hideDisabledArrow:{control:"boolean",description:"Whether to hide navigation buttons when they are disabled (e.g., at first/last slide when looping is off)",defaultValue:!1,table:{category:"Button and Controls",type:{summary:"boolean"},defaultValue:{summary:"false"}}},showArrowsOnHover:{control:"boolean",description:"Whether to show arrows only when hovering over the carousel or when it has focus",defaultValue:!1,table:{category:"Button and Controls",type:{summary:"boolean | ResponsiveValue<boolean>"},defaultValue:{summary:"false"}}},focusStyle:{control:{type:"radio"},options:["default","white"],description:'Focus style for interactive elements - use "white" for dark backgrounds',defaultValue:"default",table:{category:"Button and Controls",type:{summary:'"default" | "white"'},defaultValue:{summary:'"default"'}}},hideDots:{control:"boolean",description:"Whether to hide pagination dots. Can be set responsively to show/hide dots at different breakpoints",defaultValue:!1,table:{category:"Dots/Pagination",type:{summary:"boolean | ResponsiveValue<boolean>"},defaultValue:{summary:"false"}}},dotsSize:{control:{type:"radio"},options:["md","lg"],description:"Size of pagination dots when visible",defaultValue:"md",table:{category:"Dots/Pagination",type:{summary:'"md" | "lg"'},defaultValue:{summary:'"md"'}}},dotsVariant:{control:{type:"radio"},options:["standard","transparent"],description:"Visual style of pagination dots",defaultValue:"standard",table:{category:"Dots/Pagination",type:{summary:'"standard" | "transparent"'},defaultValue:{summary:'"standard"'}}},autoPlay:{control:"boolean",description:"Whether the autoplay is enabled",defaultValue:!1,table:{category:"Autoplay",type:{summary:"boolean"},defaultValue:{summary:"false"}}},autoPlayInterval:{control:{type:"number",min:1e3,max:1e4,step:500},description:"Interval in milliseconds between slides during autoplay",defaultValue:2e3,table:{category:"Autoplay",type:{summary:"number"},defaultValue:{summary:"2000"}}},autoPlayStyleVariant:{control:{type:"select"},options:["neutralVibrant","neutralSubtle","whiteVibrant","whiteSubtle"],description:"Style variant for autoplay control button",defaultValue:"neutralVibrant",table:{category:"Autoplay",type:{summary:'"neutralVibrant" | "neutralSubtle" | "whiteVibrant" | "whiteSubtle"'},defaultValue:{summary:'"neutralVibrant"'}}},autoPlayControlSize:{control:{type:"radio"},options:["sm","md"],description:"Size of autoplay control button",defaultValue:"md",table:{category:"Autoplay",type:{summary:'"sm" | "md"'},defaultValue:{summary:'"md"'}}},carouselWrapperClassName:{control:"text",description:'Custom class name for the outermost wrapper to allow custom styles - use your preferred naming convention (helper: "defaultCarouselWrapper")',table:{category:"Custom Styling & Positioning",type:{summary:"string"}}},prevArrowClassName:{control:"text",description:'Custom class name for the previous button to allow custom styles - use your preferred naming convention (helper: "defaultPrevButton")',table:{category:"Custom Styling & Positioning",type:{summary:"string"}}},nextArrowClassName:{control:"text",description:'Custom class name for the next button to allow custom styles - use your preferred naming convention (helper: "defaultNextButton")',table:{category:"Custom Styling & Positioning",type:{summary:"string"}}},autoplayControlClassName:{control:"text",description:'Custom class name for the autoplay control to allow custom styles - use your preferred naming convention (helper: "autoplayControl")',table:{category:"Custom Styling & Positioning",type:{summary:"string"}}},dotsContainerClassName:{control:"text",description:'Custom class name for the dots container to allow custom styles - use your preferred naming convention (helper: "defaultDotsContainer")',table:{category:"Custom Styling & Positioning",type:{summary:"string"}}},dotsWrapperClassName:{control:"text",description:"Custom class name for the dots wrapper to allow custom styles - use your preferred naming convention",table:{category:"Custom Styling & Positioning",type:{summary:"string"}}},dotClassName:{control:"text",description:"Custom class name for individual dots to allow custom styles - use your preferred naming convention",table:{category:"Custom Styling & Positioning",type:{summary:"string"}}},activeDotClassName:{control:"text",description:"Custom class name for the active dot to allow custom styles - use your preferred naming convention",table:{category:"Custom Styling & Positioning",type:{summary:"string"}}},itemWrapperClassName:{control:"text",description:"Custom class name for individual carousel item wrappers to allow custom styles - use your preferred naming convention",table:{category:"Custom Styling & Positioning",type:{summary:"string"}}},scrollerClassName:{control:"text",description:"Custom class name for the carousel scroll container to allow custom grid and scrolling styles",table:{category:"Custom Styling & Positioning",type:{summary:"string"}}},activeItemClassName:{control:"text",description:"Custom class name for the currently active/visible carousel item to allow custom styles - use your preferred naming convention",table:{category:"Custom Styling & Positioning",type:{summary:"string"}}},onArrowPress:{control:!1,description:'Callback fired when a navigation arrow button (prev/next) is pressed. Receives the direction ("prev" or "next") as a parameter',table:{category:"Event Callbacks",type:{summary:'(direction: "prev" | "next") => void'}}},onDotPress:{control:!1,description:"Callback fired when a pagination dot is pressed. Receives the dot index (0-based) as a parameter",table:{category:"Event Callbacks",type:{summary:"(index: number) => void"}}},onAutoplayPress:{control:!1,description:'Callback fired when the autoplay play/pause button is pressed. Receives the state ("play" or "pause") as a parameter',table:{category:"Event Callbacks",type:{summary:'(state: "play" | "pause") => void'}}},children:{control:{type:"object"},description:"Content to be displayed in the carousel",table:{category:"Content",disable:!0}}};export{e as carouselArgTypes};
|
|
2
2
|
//# sourceMappingURL=CarouselControls.js.map
|