@blakesteve/roster 5.1.0 → 5.2.1

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.
Files changed (47) hide show
  1. package/README.md +57 -3
  2. package/dist/components/atoms/Combobox/Combobox.cjs +1 -1
  3. package/dist/components/atoms/Combobox/Combobox.js +63 -62
  4. package/dist/components/atoms/Input/Input.cjs +1 -1
  5. package/dist/components/atoms/Input/Input.js +41 -39
  6. package/dist/components/atoms/MultiSelect/MultiSelect.cjs +1 -1
  7. package/dist/components/atoms/MultiSelect/MultiSelect.js +69 -68
  8. package/dist/components/atoms/Select/Select.cjs +1 -1
  9. package/dist/components/atoms/Select/Select.js +52 -51
  10. package/dist/components/atoms/Spinner/Spinner.cjs +1 -1
  11. package/dist/components/atoms/Spinner/Spinner.d.ts +6 -1
  12. package/dist/components/atoms/Spinner/Spinner.js +9 -8
  13. package/dist/components/atoms/Textarea/Textarea.cjs +1 -1
  14. package/dist/components/atoms/Textarea/Textarea.js +36 -34
  15. package/dist/components/molecules/Carousel/Carousel.cjs +1 -0
  16. package/dist/components/molecules/Carousel/Carousel.d.ts +146 -0
  17. package/dist/components/molecules/Carousel/Carousel.js +363 -0
  18. package/dist/components/molecules/Carousel/carousel-layout.cjs +1 -0
  19. package/dist/components/molecules/Carousel/carousel-layout.d.ts +23 -0
  20. package/dist/components/molecules/Carousel/carousel-layout.js +22 -0
  21. package/dist/components/molecules/Carousel/carousel-math.cjs +1 -0
  22. package/dist/components/molecules/Carousel/carousel-math.d.ts +60 -0
  23. package/dist/components/molecules/Carousel/carousel-math.js +58 -0
  24. package/dist/components/molecules/CheckboxGroup/CheckboxGroup.cjs +1 -1
  25. package/dist/components/molecules/CheckboxGroup/CheckboxGroup.d.ts +5 -3
  26. package/dist/components/molecules/CheckboxGroup/CheckboxGroup.js +61 -59
  27. package/dist/components/molecules/EmptyState/EmptyState.cjs +1 -1
  28. package/dist/components/molecules/EmptyState/EmptyState.d.ts +7 -1
  29. package/dist/components/molecules/EmptyState/EmptyState.js +18 -14
  30. package/dist/components/molecules/RadioGroup/RadioGroup.cjs +1 -1
  31. package/dist/components/molecules/RadioGroup/RadioGroup.d.ts +4 -3
  32. package/dist/components/molecules/RadioGroup/RadioGroup.js +48 -47
  33. package/dist/components/organisms/Sheet/Sheet.cjs +1 -1
  34. package/dist/components/organisms/Sheet/Sheet.d.ts +8 -5
  35. package/dist/components/organisms/Sheet/Sheet.js +122 -121
  36. package/dist/components/organisms/Sheet/sheet-title.cjs +1 -0
  37. package/dist/components/organisms/Sheet/sheet-title.d.ts +10 -0
  38. package/dist/components/organisms/Sheet/sheet-title.js +17 -0
  39. package/dist/index.d.ts +1 -0
  40. package/dist/internal/field-invalid.cjs +1 -0
  41. package/dist/internal/field-invalid.d.ts +37 -0
  42. package/dist/internal/field-invalid.js +13 -0
  43. package/dist/meta.json +3 -3
  44. package/dist/roster.cjs +1 -1
  45. package/dist/roster.css +1 -1
  46. package/dist/roster.js +55 -53
  47. package/package.json +1 -1
@@ -1,26 +1,27 @@
1
1
  "use client";
2
- import { jsxs as p, jsx as r } from "react/jsx-runtime";
3
- import u from "react";
4
- import { Description as N } from "../../../node_modules/@headlessui/react/dist/components/description/description.js";
5
- import { Field as b } from "../../../node_modules/@headlessui/react/dist/components/field/field.js";
6
- import { Label as y } from "../../../node_modules/@headlessui/react/dist/components/label/label.js";
7
- import { Textarea as h } from "../../../node_modules/@headlessui/react/dist/components/textarea/textarea.js";
8
- import { cn as e } from "../../../lib/utils.js";
2
+ import { jsxs as N, jsx as e } from "react/jsx-runtime";
3
+ import b from "react";
4
+ import { Description as h } from "../../../node_modules/@headlessui/react/dist/components/description/description.js";
5
+ import { Field as v } from "../../../node_modules/@headlessui/react/dist/components/field/field.js";
6
+ import { Label as w } from "../../../node_modules/@headlessui/react/dist/components/label/label.js";
7
+ import { Textarea as y } from "../../../node_modules/@headlessui/react/dist/components/textarea/textarea.js";
8
+ import { cn as s } from "../../../lib/utils.js";
9
9
  import { textareaVariants as k } from "./textarea-variants.js";
10
- const w = u.forwardRef(
10
+ import { isFieldInvalid as j, withoutInvalidProps as F } from "../../../internal/field-invalid.js";
11
+ const I = b.forwardRef(
11
12
  ({
12
13
  className: m,
13
- label: s,
14
- helperText: a,
14
+ label: a,
15
+ helperText: o,
15
16
  errorMessage: t,
16
- variant: i,
17
- error: l,
18
- resize: c,
19
- disabled: d,
20
- textareaClassName: n,
21
- ...x
17
+ variant: l,
18
+ error: n,
19
+ resize: d,
20
+ disabled: c,
21
+ textareaClassName: x,
22
+ ...i
22
23
  }, f) => {
23
- const o = !!t || l;
24
+ const r = !!t || n, p = j(r, i), u = F(i);
24
25
  return (
25
26
  /* No `space-y-*` here, for the reason documented on Input: Headless UI's
26
27
  Field always renders a trailing hidden element, and Tailwind v4
@@ -30,37 +31,38 @@ const w = u.forwardRef(
30
31
  the label and description instead. Select is immune to the same trap
31
32
  only because it spaces with `gap`, and the hidden element is
32
33
  `display: none` so it is not a flex item. */
33
- /* @__PURE__ */ p(b, { className: e("rst:w-full", m), children: [
34
- s && /* `--roster-control-text`, matching Input's label — see the comment
34
+ /* @__PURE__ */ N(v, { className: s("rst:w-full", m), children: [
35
+ a && /* `--roster-control-text`, matching Input's label — see the comment
35
36
  there for why not `text-inherit`. */
36
- /* @__PURE__ */ r(y, { className: "rst:block rst:text-sm rst:font-medium rst:leading-none rst:text-[var(--roster-control-text)] rst:peer-disabled:cursor-not-allowed rst:peer-disabled:opacity-70 rst:text-left rst:mb-1.5", children: s }),
37
- /* @__PURE__ */ r(
38
- h,
37
+ /* @__PURE__ */ e(w, { className: "rst:block rst:text-sm rst:font-medium rst:leading-none rst:text-[var(--roster-control-text)] rst:peer-disabled:cursor-not-allowed rst:peer-disabled:opacity-70 rst:text-left rst:mb-1.5", children: a }),
38
+ /* @__PURE__ */ e(
39
+ y,
39
40
  {
40
41
  ref: f,
41
- disabled: d,
42
- className: e(
43
- k({ variant: i, resize: c, error: o }),
44
- n
42
+ disabled: c,
43
+ className: s(
44
+ k({ variant: l, resize: d, error: r }),
45
+ x
45
46
  ),
46
- ...x
47
+ ...u,
48
+ invalid: p
47
49
  }
48
50
  ),
49
- (a || t) && /* @__PURE__ */ r(
50
- N,
51
+ (o || t) && /* @__PURE__ */ e(
52
+ h,
51
53
  {
52
- className: e(
54
+ className: s(
53
55
  "rst:text-xs rst:text-left rst:mt-1.5",
54
- o ? "rst:text-error-600 rst:dark:text-error-400 rst:font-medium" : "rst:text-gray-500 rst:dark:text-gray-400"
56
+ r ? "rst:text-error-600 rst:dark:text-error-400 rst:font-medium" : "rst:text-gray-500 rst:dark:text-gray-400"
55
57
  ),
56
- children: t || a
58
+ children: t || o
57
59
  }
58
60
  )
59
61
  ] })
60
62
  );
61
63
  }
62
64
  );
63
- w.displayName = "Textarea";
65
+ I.displayName = "Textarea";
64
66
  export {
65
- w as Textarea
67
+ I as Textarea
66
68
  };
@@ -0,0 +1 @@
1
+ "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l=require("react/jsx-runtime"),Fe=require("react"),qe=require("../../atoms/Button/Button.cjs"),T=require("../../../lib/utils.cjs"),$e=require("../../../internal/motion.cjs"),u=require("./carousel-math.cjs"),U=require("./carousel-layout.cjs");function Be(a){const i=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(a){for(const d in a)if(d!=="default"){const b=Object.getOwnPropertyDescriptor(a,d);Object.defineProperty(i,d,b.get?b:{enumerable:!0,get:()=>a[d]})}}return i.default=a,Object.freeze(i)}const n=Be(Fe),ze=a=>Math.min(3e3,500+a*.35),He='a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"]), [contenteditable]:not([contenteditable="false"])',V=a=>typeof a=="number"?`${a}px`:a;function ne(a){const i=parseFloat(a);return Number.isFinite(i)?i:0}const Ue="rst:hidden rst:[@media(any-hover:hover)]:inline-flex",Ve="rst:hidden rst:[@media(any-hover:hover)]:flex";function se({direction:a}){return l.jsx("svg",{"aria-hidden":"true",focusable:"false",viewBox:"0 0 20 20",className:"rst:h-5 rst:w-5",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:l.jsx("path",{d:a==="prev"?"M12.5 4.5 7 10l5.5 5.5":"M7.5 4.5 13 10l-5.5 5.5"})})}const oe={overflowing:null,canScrollPrev:!1,canScrollNext:!1,index:0},We=n.forwardRef(function({"aria-label":i,"aria-labelledby":d,children:b,itemWidth:I,perView:k,gap:W=12,gutter:X=16,bleed:le=!1,snap:L="start",snapStrictness:ce="mandatory",oneAtATime:ae=!1,arrows:j="hover",arrowPlacement:M="controls",renderArrows:P,prevLabel:ie,nextLabel:ue,prevIcon:de,nextIcon:fe,arrowButtonProps:ge,fade:ve=!1,scrollbar:pe=!1,showPosition:G=!1,onIndexChange:J,onScrollStateChange:K,itemClassName:me,listClassName:xe,className:be,style:he,...Se},ye){const v=n.useRef(null),Q=`${n.useId()}-list`,Y=n.Children.toArray(b),E=Y.length,[o,we]=n.useState(oe),Z=n.useRef(oe),[Ne,Te]=n.useState(""),[Ie,Pe]=n.useState(!1),O=n.useRef({onIndexChange:J,onScrollStateChange:K});n.useEffect(()=>{O.current={onIndexChange:J,onScrollStateChange:K}});const f=n.useCallback(()=>{const e=v.current;if(!e)return null;const t=e.getBoundingClientRect(),r=getComputedStyle(e),s=t.left+e.clientLeft-e.scrollLeft;return{items:Array.from(e.children).map(g=>{const x=g.getBoundingClientRect();return{start:x.left-s,end:x.right-s}}),scrollLeft:e.scrollLeft,clientWidth:e.clientWidth,scrollWidth:e.scrollWidth,paddingStart:ne(r.scrollPaddingInlineStart||r.scrollPaddingLeft),paddingEnd:ne(r.scrollPaddingInlineEnd||r.scrollPaddingRight),align:L}},[L]),h=n.useCallback(()=>{const e=f();if(!e)return;const t={overflowing:u.overflows(e),canScrollPrev:u.canScrollPrev(e),canScrollNext:u.canScrollNext(e),index:e.items.length?u.currentIndex(e):0},r=Z.current;r.overflowing===t.overflowing&&r.canScrollPrev===t.canScrollPrev&&r.canScrollNext===t.canScrollNext&&r.index===t.index||(Z.current=t,we(t),r.index!==t.index&&O.current.onIndexChange?.(t.index),(r.canScrollPrev!==t.canScrollPrev||r.canScrollNext!==t.canScrollNext)&&O.current.onScrollStateChange?.({canScrollPrev:t.canScrollPrev,canScrollNext:t.canScrollNext}))},[f]),Ee=JSON.stringify([W,X,I,k]);n.useLayoutEffect(()=>{const e=v.current;if(!e)return;h();let t=0;const r=()=>{t||(t=requestAnimationFrame(()=>{t=0,h()}))};e.addEventListener("scroll",r,{passive:!0});const s=typeof ResizeObserver>"u"?null:new ResizeObserver(()=>h()),c=()=>{s?.observe(e),Array.from(e.children).forEach(x=>s?.observe(x))};c();const g=typeof MutationObserver>"u"?null:new MutationObserver(()=>{c(),h()});return g?.observe(e,{childList:!0}),()=>{e.removeEventListener("scroll",r),s?.disconnect(),g?.disconnect(),t&&cancelAnimationFrame(t)}},[h,E,Ee]),n.useLayoutEffect(()=>{const e=v.current;if(e&&(Pe(!e.querySelector(He)),d)){const t=d.split(/\s+/).map(r=>document.getElementById(r)?.textContent?.trim()??"").filter(Boolean).join(" ");Te(t)}},[b,d]);const S=n.useRef(null),p=n.useCallback(()=>{const e=v.current,t=S.current;t&&(S.current=null,window.clearTimeout(t.timer),e?.removeEventListener("scrollend",t.done),e&&(e.style.scrollSnapType="",delete e.dataset.settling))},[]),m=n.useCallback((e,t)=>{const r=v.current;if(!r)return;if(p(),t!=="smooth"||$e.prefersReducedMotion()||Math.abs(r.scrollLeft-e)<1){r.style.scrollSnapType="none",r.scrollTo({left:e,behavior:"instant"}),r.style.scrollSnapType="";return}r.style.scrollSnapType="none",r.dataset.settling="";const c=()=>p();S.current={timer:window.setTimeout(c,ze(Math.abs(r.scrollLeft-e))),done:c,target:e},r.addEventListener("scrollend",c,{once:!0}),r.scrollTo({left:e,behavior:"smooth"})},[p]),C=n.useCallback(e=>{const t=f();if(!t)return;const r=S.current?{...t,scrollLeft:S.current.target}:t;m(u.pageTarget(r,e),"smooth")},[f,m]);n.useImperativeHandle(ye,()=>({scrollToIndex:(e,t)=>{const r=f();if(!r||!r.items.length)return;const s=Math.min(Math.max(0,Math.round(e)),r.items.length-1);m(u.snapPosition(r,s),t?.behavior??"smooth")},scrollPrev:()=>C(-1),scrollNext:()=>C(1)}),[f,C,m]),n.useEffect(()=>p,[p]);const D=n.useRef(null),_=n.useRef(null),A=n.useRef(null);n.useLayoutEffect(()=>{const e=A.current;if(!e)return;const t=e==="prev"?D.current:_.current,r=e==="prev"?_.current:D.current,s=e==="prev"?!o.canScrollPrev:!o.canScrollNext,c=document.activeElement;s&&(c!==t&&c!==document.body&&c!==null||r&&!r.disabled&&r.focus())},[o.canScrollPrev,o.canScrollNext]);const y=n.useRef(null),w=n.useRef(!1),Ce=e=>{e.pointerType!=="mouse"||e.button!==0||o.overflowing&&(p(),w.current=!1,y.current={pointerId:e.pointerId,x0:e.clientX,scroll0:e.currentTarget.scrollLeft,dragging:!1})},Re=e=>{const t=y.current;if(!t||e.pointerId!==t.pointerId)return;const r=e.currentTarget,s=e.clientX-t.x0;if(!t.dragging){if(Math.abs(s)<=u.CAROUSEL_DRAG_THRESHOLD)return;t.dragging=!0,r.dataset.dragging="",r.style.scrollSnapType="none",window.getSelection?.()?.removeAllRanges();try{r.setPointerCapture(e.pointerId)}catch{}}r.scrollLeft=t.scroll0-s},F=e=>{const t=y.current;if(!t||e.pointerId!==t.pointerId||(y.current=null,!t.dragging))return;const r=e.currentTarget;delete r.dataset.dragging,w.current=e.type==="pointerup",window.setTimeout(()=>{w.current=!1},0);const s=f();s?m(u.snapPosition(s,u.nearestIndex(s)),"smooth"):r.style.scrollSnapType=""},ke=e=>{!w.current||e.detail===0||(w.current=!1,e.preventDefault(),e.stopPropagation())},Le=e=>{o.overflowing&&e.preventDefault()},je=e=>{const t=e.currentTarget,r=e.target;if(r===t||y.current?.dragging)return;let s=!1;try{s=r.matches(":focus-visible")}catch{s=!1}if(!s)return;const c=r.closest("[data-carousel-item]");if(!c||c.parentElement!==t)return;const g=f();if(!g)return;const x=Array.prototype.indexOf.call(t.children,c);m(u.snapPosition(g,x),"instant")},[Me,Oe]=n.useState(0);n.useEffect(()=>{const e=window.setTimeout(()=>Oe(o.index),150);return()=>window.clearTimeout(e)},[o.index]);const ee=i??Ne,te=e=>ee?`${e} ${ee}`:e,q=j!=="none"&&o.overflowing!==!1,De=j==="hover"?Ue:"rst:inline-flex",re=e=>{const t=e==="prev",{className:r,...s}=ge??{};return l.jsx(qe.Button,{type:"button",variant:"outline",colorScheme:"neutral",size:"icon",...s,"aria-label":t?ie??te("Previous"):ue??te("Next"),"aria-controls":Q,disabled:t?!o.canScrollPrev:!o.canScrollNext,onClick:()=>C(t?-1:1),ref:t?D:_,onFocus:()=>{A.current=e},onBlur:c=>{c.relatedTarget&&(A.current=null)},"data-carousel-arrow":e,className:T.cn("rst:size-11 rst:shrink-0 rst:rounded-full",M==="overlay"&&!P&&"rst:bg-[var(--roster-popover-bg)] rst:elevation-raised rst:hover:bg-[var(--roster-popover-bg)] rst:disabled:invisible",De,r),children:t?de??l.jsx(se,{direction:"prev"}):fe??l.jsx(se,{direction:"next"})})},R=q?re("prev"):null,$=q?re("next"):null,N=G&&E?l.jsxs("p",{"aria-live":"polite",className:"rst:font-ui rst:m-0 rst:text-sm rst:tabular-nums rst:opacity-75","data-carousel-position":"",children:[Me+1," of ",E]}):null;let B=null;P?B=P({prev:R,next:$,position:N}):M==="controls"&&(R||N)&&(B=l.jsxs("div",{className:T.cn("rst:mb-2 rst:items-center rst:justify-end rst:gap-2",!N&&j==="hover"?Ve:"rst:flex"),"data-carousel-controls":"",children:[N&&l.jsx("div",{className:"rst:mr-auto",children:N}),R,$]}));const z=ve&&o.overflowing&&(o.canScrollPrev||o.canScrollNext)?`linear-gradient(to right, ${o.canScrollPrev?"transparent, black 48px":"black"}, ${o.canScrollNext?"black calc(100% - 48px), transparent":"black"})`:void 0,H=I===void 0&&k!==void 0,_e={"--rst-cv-gap":V(W),"--rst-cv-gutter":V(X),...H?U.perViewVars(k):{},...z?{maskImage:z,WebkitMaskImage:z}:{}},Ae=I!==void 0?{width:V(I)}:H?{width:U.FLUID_ITEM_WIDTH}:void 0;return l.jsxs("div",{className:T.cn("rst:min-w-0",be),style:he,...Se,children:[B,l.jsxs("div",{className:"rst:relative",children:[l.jsx("ul",{ref:v,id:Q,role:"list","aria-label":i,"aria-labelledby":i?void 0:d,tabIndex:Ie&&o.overflowing?0:void 0,"data-overflowing":o.overflowing?"":void 0,onPointerDown:Ce,onPointerMove:Re,onPointerUp:F,onPointerCancel:F,onLostPointerCapture:F,onClickCapture:ke,onDragStart:Le,onFocus:je,style:_e,className:T.cn("rst:m-0 rst:flex rst:list-none rst:overflow-x-auto rst:overflow-y-hidden","rst:gap-(--rst-cv-gap) rst:px-(--rst-cv-gutter) rst:py-1 rst:scroll-px-(--rst-cv-gutter)","rst:overscroll-x-contain",ce==="mandatory"?"rst:snap-x rst:snap-mandatory":"rst:snap-x rst:snap-proximity",le&&"rst:-mx-(--rst-cv-gutter)",!pe&&"rst:[scrollbar-width:none] rst:[&::-webkit-scrollbar]:hidden",H&&U.FLUID_CLASSES,"rst:data-overflowing:cursor-grab rst:data-dragging:cursor-grabbing rst:data-dragging:select-none","rst:focus-visible:outline-hidden rst:focus-visible:ring-2 rst:focus-visible:ring-ring rst:focus-visible:ring-inset",xe),children:Y.map((e,t)=>l.jsx("li",{"data-carousel-item":"","aria-label":G?`${t+1} of ${E}`:void 0,style:Ae,className:T.cn("rst:shrink-0",L==="start"?"rst:snap-start":"rst:snap-center",ae&&"rst:snap-always",me),children:e},n.isValidElement(e)&&e.key!=null?e.key:t))}),!P&&M==="overlay"&&q&&l.jsxs(l.Fragment,{children:[l.jsx("div",{className:"rst:pointer-events-none rst:absolute rst:inset-y-0 rst:start-1 rst:flex rst:items-center",children:l.jsx("div",{className:"rst:pointer-events-auto",children:R})}),l.jsx("div",{className:"rst:pointer-events-none rst:absolute rst:inset-y-0 rst:end-1 rst:flex rst:items-center",children:l.jsx("div",{className:"rst:pointer-events-auto",children:$})})]})]})]})});exports.Carousel=We;
@@ -0,0 +1,146 @@
1
+ import { ButtonProps } from '../../atoms/Button/Button';
2
+ import * as React from "react";
3
+ /** Items per view at each width, from Roster's breakpoints up. */
4
+ export interface CarouselPerView {
5
+ base: number;
6
+ sm?: number;
7
+ md?: number;
8
+ lg?: number;
9
+ xl?: number;
10
+ }
11
+ export interface CarouselHandle {
12
+ /** Snaps item `i` into place. Instant under reduced motion, whatever is asked. */
13
+ scrollToIndex: (index: number, options?: {
14
+ behavior?: ScrollBehavior;
15
+ }) => void;
16
+ /** What the previous arrow does: back one page. */
17
+ scrollPrev: () => void;
18
+ /** What the next arrow does: on one page. */
19
+ scrollNext: () => void;
20
+ }
21
+ export interface CarouselArrowsRender {
22
+ /** The previous arrow, or `null` while the row fits and there is nothing to page. */
23
+ prev: React.ReactNode;
24
+ next: React.ReactNode;
25
+ /** The "2 of 5" readout when `showPosition` is on, otherwise `null`. */
26
+ position: React.ReactNode;
27
+ }
28
+ export interface CarouselProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "children" | "aria-label" | "aria-labelledby"> {
29
+ /** The row's name. One of this or `aria-labelledby` is required. */
30
+ "aria-label"?: string;
31
+ /** The id of the heading that names the row. */
32
+ "aria-labelledby"?: string;
33
+ /** One child per item. Each is wrapped in the list item the row snaps to. */
34
+ children: React.ReactNode;
35
+ /**
36
+ * Fixed mode: every item is this wide (a number is px). The row overflows
37
+ * once the items and gaps outgrow the box, and the next item peeks from then
38
+ * on.
39
+ */
40
+ itemWidth?: number | string;
41
+ /**
42
+ * Fluid mode: how many items are in view at each width, and the component
43
+ * sizes them. A fraction is the peek: `1.3` is one item and a third of the
44
+ * next. Ignored when `itemWidth` is set.
45
+ */
46
+ perView?: number | CarouselPerView;
47
+ /** Space between items. A number is px. */
48
+ gap?: number | string;
49
+ /**
50
+ * The inline padding at each end, and the scroll padding a snapped item
51
+ * lines up with. Match the page's own gutter so a snapped item sits under
52
+ * the text above it. A number is px.
53
+ */
54
+ gutter?: number | string;
55
+ /**
56
+ * Pulls the row out by one gutter on each side, so it runs to the edges of
57
+ * its container while the first item still lines up with the text.
58
+ */
59
+ bleed?: boolean;
60
+ /** Where an item settles. */
61
+ snap?: "start" | "center";
62
+ /** `mandatory` always settles on an item; `proximity` only near one. */
63
+ snapStrictness?: "mandatory" | "proximity";
64
+ /** One item per swipe, for a gallery of one per view (`scroll-snap-stop: always`). */
65
+ oneAtATime?: boolean;
66
+ /**
67
+ * When the arrows show. `hover`, the default, is wherever a pointer can
68
+ * hover: a touch-only screen swipes instead, and gets no arrows to aim at.
69
+ */
70
+ arrows?: "hover" | "always" | "none";
71
+ /**
72
+ * `controls`, the default, puts the arrows on a line of their own above the
73
+ * row, where they never cover an item or the peek and never fight a drag.
74
+ * `overlay` floats them over the row's two ends and takes no space.
75
+ * `renderArrows` overrides both.
76
+ */
77
+ arrowPlacement?: "controls" | "overlay";
78
+ /**
79
+ * Put the arrows (and the position readout) anywhere: a heading line beside
80
+ * a "See all" link, say. What it returns replaces the default controls line,
81
+ * so a heading rendered here sits above the row as before.
82
+ */
83
+ renderArrows?: (parts: CarouselArrowsRender) => React.ReactNode;
84
+ /** The previous arrow's accessible name. Defaults to "Previous" and the row's label. */
85
+ prevLabel?: string;
86
+ /** The next arrow's accessible name. Defaults to "Next" and the row's label. */
87
+ nextLabel?: string;
88
+ /** Replaces the previous arrow's chevron. */
89
+ prevIcon?: React.ReactNode;
90
+ /** Replaces the next arrow's chevron. */
91
+ nextIcon?: React.ReactNode;
92
+ /** Passed to both arrow buttons, over the defaults. */
93
+ arrowButtonProps?: Omit<ButtonProps, "onClick" | "disabled" | "children" | "aria-label">;
94
+ /**
95
+ * Fades the edge on a side with more to see. Never at an end, so the last
96
+ * item is never faded.
97
+ */
98
+ fade?: boolean;
99
+ /** Shows the native scrollbar. Hidden by default; the arrows and the mouse drag stand in for it. */
100
+ scrollbar?: boolean;
101
+ /**
102
+ * Shows "2 of 5", for a gallery of one item per view. It is also each item's
103
+ * name, and a change is announced politely.
104
+ */
105
+ showPosition?: boolean;
106
+ /** The first item wholly in view, whenever it changes. */
107
+ onIndexChange?: (index: number) => void;
108
+ /** Whether the row can move each way, whenever that changes. */
109
+ onScrollStateChange?: (state: {
110
+ canScrollPrev: boolean;
111
+ canScrollNext: boolean;
112
+ }) => void;
113
+ /** Classes for each list item. */
114
+ itemClassName?: string;
115
+ /** Classes for the scrolling list. `className` is the outer wrapper. */
116
+ listClassName?: string;
117
+ }
118
+ /**
119
+ * A sideways row of items: a row of cards, a selection strip, a gallery of one
120
+ * per view.
121
+ *
122
+ * Native first. The row is a real scroll container with CSS scroll snap, so
123
+ * touch, trackpad, Shift with the wheel and focus all scroll it without
124
+ * script, and every item is in the server render: no clones, no
125
+ * virtualization, no loop, and nothing moves on its own.
126
+ *
127
+ * Script adds what a mouse is missing. Pressing and dragging moves the row one
128
+ * to one and settles it on the nearest item; a drag past 6px drops the one
129
+ * click that ends it and nothing else. Previous and next arrows page by as
130
+ * many items as are wholly in view, measured each time, and are `disabled`,
131
+ * out of the tab order, at an end. A vertical wheel over the row scrolls the
132
+ * page, and sideways overscroll is contained so a swipe at an end can't go
133
+ * back a page.
134
+ *
135
+ * Keyboard focus moving onto an item snaps that item into place at once. If
136
+ * no item can take focus, the list itself is the tab stop, so a keyboard can
137
+ * still scroll it.
138
+ *
139
+ * Under reduced motion every programmatic scroll is instant: the arrows, the
140
+ * settle after a drag, and `scrollToIndex`.
141
+ *
142
+ * Renders a `ul` named by `aria-label` or `aria-labelledby`, one `li` per
143
+ * child. There is no carousel role and no slide role: nothing rotates.
144
+ */
145
+ declare const Carousel: React.ForwardRefExoticComponent<CarouselProps & React.RefAttributes<CarouselHandle>>;
146
+ export { Carousel };
@@ -0,0 +1,363 @@
1
+ "use client";
2
+ import { jsxs as y, jsx as c, Fragment as $t } from "react/jsx-runtime";
3
+ import * as n from "react";
4
+ import { Button as Bt } from "../../atoms/Button/Button.js";
5
+ import { cn as w } from "../../../lib/utils.js";
6
+ import { prefersReducedMotion as Ht } from "../../../internal/motion.js";
7
+ import { currentIndex as jt, canScrollNext as zt, canScrollPrev as Ut, overflows as Vt, pageTarget as Wt, snapPosition as U, nearestIndex as qt, CAROUSEL_DRAG_THRESHOLD as Xt } from "./carousel-math.js";
8
+ import { perViewVars as Gt, FLUID_ITEM_WIDTH as Jt, FLUID_CLASSES as Kt } from "./carousel-layout.js";
9
+ const Qt = (a) => Math.min(3e3, 500 + a * 0.35), Yt = 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"]), [contenteditable]:not([contenteditable="false"])', V = (a) => typeof a == "number" ? `${a}px` : a;
10
+ function nt(a) {
11
+ const d = parseFloat(a);
12
+ return Number.isFinite(d) ? d : 0;
13
+ }
14
+ const Zt = "rst:hidden rst:[@media(any-hover:hover)]:inline-flex", te = "rst:hidden rst:[@media(any-hover:hover)]:flex";
15
+ function st({ direction: a }) {
16
+ return /* @__PURE__ */ c(
17
+ "svg",
18
+ {
19
+ "aria-hidden": "true",
20
+ focusable: "false",
21
+ viewBox: "0 0 20 20",
22
+ className: "rst:h-5 rst:w-5",
23
+ fill: "none",
24
+ stroke: "currentColor",
25
+ strokeWidth: "2",
26
+ strokeLinecap: "round",
27
+ strokeLinejoin: "round",
28
+ children: /* @__PURE__ */ c("path", { d: a === "prev" ? "M12.5 4.5 7 10l5.5 5.5" : "M7.5 4.5 13 10l-5.5 5.5" })
29
+ }
30
+ );
31
+ }
32
+ const ot = {
33
+ overflowing: null,
34
+ canScrollPrev: !1,
35
+ canScrollNext: !1,
36
+ index: 0
37
+ }, ce = n.forwardRef(function({
38
+ "aria-label": d,
39
+ "aria-labelledby": N,
40
+ children: W,
41
+ itemWidth: I,
42
+ perView: R,
43
+ gap: q = 12,
44
+ gutter: X = 16,
45
+ bleed: lt = !1,
46
+ snap: L = "start",
47
+ snapStrictness: ct = "mandatory",
48
+ oneAtATime: at = !1,
49
+ arrows: P = "hover",
50
+ arrowPlacement: M = "controls",
51
+ renderArrows: T,
52
+ prevLabel: it,
53
+ nextLabel: ut,
54
+ prevIcon: dt,
55
+ nextIcon: ft,
56
+ arrowButtonProps: gt,
57
+ fade: vt = !1,
58
+ scrollbar: pt = !1,
59
+ showPosition: G = !1,
60
+ onIndexChange: J,
61
+ onScrollStateChange: K,
62
+ itemClassName: mt,
63
+ listClassName: bt,
64
+ className: xt,
65
+ style: ht,
66
+ ...St
67
+ }, yt) {
68
+ const f = n.useRef(null), Q = `${n.useId()}-list`, Y = n.Children.toArray(W), E = Y.length, [o, wt] = n.useState(ot), Z = n.useRef(ot), [Nt, It] = n.useState(""), [Tt, Et] = n.useState(!1), D = n.useRef({ onIndexChange: J, onScrollStateChange: K });
69
+ n.useEffect(() => {
70
+ D.current = { onIndexChange: J, onScrollStateChange: K };
71
+ });
72
+ const i = n.useCallback(() => {
73
+ const t = f.current;
74
+ if (!t) return null;
75
+ const e = t.getBoundingClientRect(), r = getComputedStyle(t), s = e.left + t.clientLeft - t.scrollLeft;
76
+ return {
77
+ items: Array.from(t.children).map((u) => {
78
+ const p = u.getBoundingClientRect();
79
+ return { start: p.left - s, end: p.right - s };
80
+ }),
81
+ scrollLeft: t.scrollLeft,
82
+ clientWidth: t.clientWidth,
83
+ scrollWidth: t.scrollWidth,
84
+ paddingStart: nt(r.scrollPaddingInlineStart || r.scrollPaddingLeft),
85
+ paddingEnd: nt(r.scrollPaddingInlineEnd || r.scrollPaddingRight),
86
+ align: L
87
+ };
88
+ }, [L]), m = n.useCallback(() => {
89
+ const t = i();
90
+ if (!t) return;
91
+ const e = {
92
+ overflowing: Vt(t),
93
+ canScrollPrev: Ut(t),
94
+ canScrollNext: zt(t),
95
+ index: t.items.length ? jt(t) : 0
96
+ }, r = Z.current;
97
+ r.overflowing === e.overflowing && r.canScrollPrev === e.canScrollPrev && r.canScrollNext === e.canScrollNext && r.index === e.index || (Z.current = e, wt(e), r.index !== e.index && D.current.onIndexChange?.(e.index), (r.canScrollPrev !== e.canScrollPrev || r.canScrollNext !== e.canScrollNext) && D.current.onScrollStateChange?.({
98
+ canScrollPrev: e.canScrollPrev,
99
+ canScrollNext: e.canScrollNext
100
+ }));
101
+ }, [i]), Ct = JSON.stringify([q, X, I, R]);
102
+ n.useLayoutEffect(() => {
103
+ const t = f.current;
104
+ if (!t) return;
105
+ m();
106
+ let e = 0;
107
+ const r = () => {
108
+ e || (e = requestAnimationFrame(() => {
109
+ e = 0, m();
110
+ }));
111
+ };
112
+ t.addEventListener("scroll", r, { passive: !0 });
113
+ const s = typeof ResizeObserver > "u" ? null : new ResizeObserver(() => m()), l = () => {
114
+ s?.observe(t), Array.from(t.children).forEach((p) => s?.observe(p));
115
+ };
116
+ l();
117
+ const u = typeof MutationObserver > "u" ? null : new MutationObserver(() => {
118
+ l(), m();
119
+ });
120
+ return u?.observe(t, { childList: !0 }), () => {
121
+ t.removeEventListener("scroll", r), s?.disconnect(), u?.disconnect(), e && cancelAnimationFrame(e);
122
+ };
123
+ }, [m, E, Ct]), n.useLayoutEffect(() => {
124
+ const t = f.current;
125
+ if (t && (Et(!t.querySelector(Yt)), N)) {
126
+ const e = N.split(/\s+/).map((r) => document.getElementById(r)?.textContent?.trim() ?? "").filter(Boolean).join(" ");
127
+ It(e);
128
+ }
129
+ }, [W, N]);
130
+ const b = n.useRef(null), g = n.useCallback(() => {
131
+ const t = f.current, e = b.current;
132
+ e && (b.current = null, window.clearTimeout(e.timer), t?.removeEventListener("scrollend", e.done), t && (t.style.scrollSnapType = "", delete t.dataset.settling));
133
+ }, []), v = n.useCallback(
134
+ (t, e) => {
135
+ const r = f.current;
136
+ if (!r) return;
137
+ if (g(), e !== "smooth" || Ht() || Math.abs(r.scrollLeft - t) < 1) {
138
+ r.style.scrollSnapType = "none", r.scrollTo({ left: t, behavior: "instant" }), r.style.scrollSnapType = "";
139
+ return;
140
+ }
141
+ r.style.scrollSnapType = "none", r.dataset.settling = "";
142
+ const l = () => g();
143
+ b.current = {
144
+ timer: window.setTimeout(l, Qt(Math.abs(r.scrollLeft - t))),
145
+ done: l,
146
+ target: t
147
+ }, r.addEventListener("scrollend", l, { once: !0 }), r.scrollTo({ left: t, behavior: "smooth" });
148
+ },
149
+ [g]
150
+ ), C = n.useCallback(
151
+ (t) => {
152
+ const e = i();
153
+ if (!e) return;
154
+ const r = b.current ? { ...e, scrollLeft: b.current.target } : e;
155
+ v(Wt(r, t), "smooth");
156
+ },
157
+ [i, v]
158
+ );
159
+ n.useImperativeHandle(
160
+ yt,
161
+ () => ({
162
+ scrollToIndex: (t, e) => {
163
+ const r = i();
164
+ if (!r || !r.items.length) return;
165
+ const s = Math.min(Math.max(0, Math.round(t)), r.items.length - 1);
166
+ v(U(r, s), e?.behavior ?? "smooth");
167
+ },
168
+ scrollPrev: () => C(-1),
169
+ scrollNext: () => C(1)
170
+ }),
171
+ [i, C, v]
172
+ ), n.useEffect(() => g, [g]);
173
+ const O = n.useRef(null), A = n.useRef(null), F = n.useRef(null);
174
+ n.useLayoutEffect(() => {
175
+ const t = F.current;
176
+ if (!t) return;
177
+ const e = t === "prev" ? O.current : A.current, r = t === "prev" ? A.current : O.current, s = t === "prev" ? !o.canScrollPrev : !o.canScrollNext, l = document.activeElement;
178
+ s && (l !== e && l !== document.body && l !== null || r && !r.disabled && r.focus());
179
+ }, [o.canScrollPrev, o.canScrollNext]);
180
+ const x = n.useRef(null), h = n.useRef(!1), kt = (t) => {
181
+ t.pointerType !== "mouse" || t.button !== 0 || o.overflowing && (g(), h.current = !1, x.current = {
182
+ pointerId: t.pointerId,
183
+ x0: t.clientX,
184
+ scroll0: t.currentTarget.scrollLeft,
185
+ dragging: !1
186
+ });
187
+ }, Rt = (t) => {
188
+ const e = x.current;
189
+ if (!e || t.pointerId !== e.pointerId) return;
190
+ const r = t.currentTarget, s = t.clientX - e.x0;
191
+ if (!e.dragging) {
192
+ if (Math.abs(s) <= Xt) return;
193
+ e.dragging = !0, r.dataset.dragging = "", r.style.scrollSnapType = "none", window.getSelection?.()?.removeAllRanges();
194
+ try {
195
+ r.setPointerCapture(t.pointerId);
196
+ } catch {
197
+ }
198
+ }
199
+ r.scrollLeft = e.scroll0 - s;
200
+ }, _ = (t) => {
201
+ const e = x.current;
202
+ if (!e || t.pointerId !== e.pointerId || (x.current = null, !e.dragging)) return;
203
+ const r = t.currentTarget;
204
+ delete r.dataset.dragging, h.current = t.type === "pointerup", window.setTimeout(() => {
205
+ h.current = !1;
206
+ }, 0);
207
+ const s = i();
208
+ s ? v(U(s, qt(s)), "smooth") : r.style.scrollSnapType = "";
209
+ }, Lt = (t) => {
210
+ !h.current || t.detail === 0 || (h.current = !1, t.preventDefault(), t.stopPropagation());
211
+ }, Pt = (t) => {
212
+ o.overflowing && t.preventDefault();
213
+ }, Mt = (t) => {
214
+ const e = t.currentTarget, r = t.target;
215
+ if (r === e || x.current?.dragging) return;
216
+ let s = !1;
217
+ try {
218
+ s = r.matches(":focus-visible");
219
+ } catch {
220
+ s = !1;
221
+ }
222
+ if (!s) return;
223
+ const l = r.closest("[data-carousel-item]");
224
+ if (!l || l.parentElement !== e) return;
225
+ const u = i();
226
+ if (!u) return;
227
+ const p = Array.prototype.indexOf.call(e.children, l);
228
+ v(U(u, p), "instant");
229
+ }, [Dt, Ot] = n.useState(0);
230
+ n.useEffect(() => {
231
+ const t = window.setTimeout(() => Ot(o.index), 150);
232
+ return () => window.clearTimeout(t);
233
+ }, [o.index]);
234
+ const tt = d ?? Nt, et = (t) => tt ? `${t} ${tt}` : t, $ = P !== "none" && o.overflowing !== !1, At = P === "hover" ? Zt : "rst:inline-flex", rt = (t) => {
235
+ const e = t === "prev", { className: r, ...s } = gt ?? {};
236
+ return /* @__PURE__ */ c(
237
+ Bt,
238
+ {
239
+ type: "button",
240
+ variant: "outline",
241
+ colorScheme: "neutral",
242
+ size: "icon",
243
+ ...s,
244
+ "aria-label": e ? it ?? et("Previous") : ut ?? et("Next"),
245
+ "aria-controls": Q,
246
+ disabled: e ? !o.canScrollPrev : !o.canScrollNext,
247
+ onClick: () => C(e ? -1 : 1),
248
+ ref: e ? O : A,
249
+ onFocus: () => {
250
+ F.current = t;
251
+ },
252
+ onBlur: (l) => {
253
+ l.relatedTarget && (F.current = null);
254
+ },
255
+ "data-carousel-arrow": t,
256
+ className: w(
257
+ /* 44px, the target size, whatever the Button's own icon size is. */
258
+ "rst:size-11 rst:shrink-0 rst:rounded-full",
259
+ /* Over the row, a disabled arrow would sit on top of the first or
260
+ last item for nothing, so it hides. Hidden is also out of the tab
261
+ order and the accessibility tree, as disabled already was. */
262
+ M === "overlay" && !T && "rst:bg-[var(--roster-popover-bg)] rst:elevation-raised rst:hover:bg-[var(--roster-popover-bg)] rst:disabled:invisible",
263
+ At,
264
+ r
265
+ ),
266
+ children: e ? dt ?? /* @__PURE__ */ c(st, { direction: "prev" }) : ft ?? /* @__PURE__ */ c(st, { direction: "next" })
267
+ }
268
+ );
269
+ }, k = $ ? rt("prev") : null, B = $ ? rt("next") : null, S = G && E ? (
270
+ /* `font-ui` here and not on the root: the readout is the only text the
271
+ carousel owns. The items are the host's content, and not Roster's to
272
+ restyle. */
273
+ /* @__PURE__ */ y("p", { "aria-live": "polite", className: "rst:font-ui rst:m-0 rst:text-sm rst:tabular-nums rst:opacity-75", "data-carousel-position": "", children: [
274
+ Dt + 1,
275
+ " of ",
276
+ E
277
+ ] })
278
+ ) : null;
279
+ let H = null;
280
+ T ? H = T({ prev: k, next: B, position: S }) : M === "controls" && (k || S) && (H = /* @__PURE__ */ y(
281
+ "div",
282
+ {
283
+ className: w(
284
+ "rst:mb-2 rst:items-center rst:justify-end rst:gap-2",
285
+ /* A line with only arrows in it takes no room where they can't show. */
286
+ !S && P === "hover" ? te : "rst:flex"
287
+ ),
288
+ "data-carousel-controls": "",
289
+ children: [
290
+ S && /* @__PURE__ */ c("div", { className: "rst:mr-auto", children: S }),
291
+ k,
292
+ B
293
+ ]
294
+ }
295
+ ));
296
+ const j = vt && o.overflowing && (o.canScrollPrev || o.canScrollNext) ? `linear-gradient(to right, ${o.canScrollPrev ? "transparent, black 48px" : "black"}, ${o.canScrollNext ? "black calc(100% - 48px), transparent" : "black"})` : void 0, z = I === void 0 && R !== void 0, Ft = {
297
+ "--rst-cv-gap": V(q),
298
+ "--rst-cv-gutter": V(X),
299
+ ...z ? Gt(R) : {},
300
+ ...j ? { maskImage: j, WebkitMaskImage: j } : {}
301
+ }, _t = I !== void 0 ? { width: V(I) } : z ? { width: Jt } : void 0;
302
+ return /* @__PURE__ */ y("div", { className: w("rst:min-w-0", xt), style: ht, ...St, children: [
303
+ H,
304
+ /* @__PURE__ */ y("div", { className: "rst:relative", children: [
305
+ /* @__PURE__ */ c(
306
+ "ul",
307
+ {
308
+ ref: f,
309
+ id: Q,
310
+ role: "list",
311
+ "aria-label": d,
312
+ "aria-labelledby": d ? void 0 : N,
313
+ tabIndex: Tt && o.overflowing ? 0 : void 0,
314
+ "data-overflowing": o.overflowing ? "" : void 0,
315
+ onPointerDown: kt,
316
+ onPointerMove: Rt,
317
+ onPointerUp: _,
318
+ onPointerCancel: _,
319
+ onLostPointerCapture: _,
320
+ onClickCapture: Lt,
321
+ onDragStart: Pt,
322
+ onFocus: Mt,
323
+ style: Ft,
324
+ className: w(
325
+ "rst:m-0 rst:flex rst:list-none rst:overflow-x-auto rst:overflow-y-hidden",
326
+ "rst:gap-(--rst-cv-gap) rst:px-(--rst-cv-gutter) rst:py-1 rst:scroll-px-(--rst-cv-gutter)",
327
+ "rst:overscroll-x-contain",
328
+ ct === "mandatory" ? "rst:snap-x rst:snap-mandatory" : "rst:snap-x rst:snap-proximity",
329
+ lt && "rst:-mx-(--rst-cv-gutter)",
330
+ !pt && "rst:[scrollbar-width:none] rst:[&::-webkit-scrollbar]:hidden",
331
+ z && Kt,
332
+ "rst:data-overflowing:cursor-grab rst:data-dragging:cursor-grabbing rst:data-dragging:select-none",
333
+ "rst:focus-visible:outline-hidden rst:focus-visible:ring-2 rst:focus-visible:ring-ring rst:focus-visible:ring-inset",
334
+ bt
335
+ ),
336
+ children: Y.map((t, e) => /* @__PURE__ */ c(
337
+ "li",
338
+ {
339
+ "data-carousel-item": "",
340
+ "aria-label": G ? `${e + 1} of ${E}` : void 0,
341
+ style: _t,
342
+ className: w(
343
+ "rst:shrink-0",
344
+ L === "start" ? "rst:snap-start" : "rst:snap-center",
345
+ at && "rst:snap-always",
346
+ mt
347
+ ),
348
+ children: t
349
+ },
350
+ n.isValidElement(t) && t.key != null ? t.key : e
351
+ ))
352
+ }
353
+ ),
354
+ !T && M === "overlay" && $ && /* @__PURE__ */ y($t, { children: [
355
+ /* @__PURE__ */ c("div", { className: "rst:pointer-events-none rst:absolute rst:inset-y-0 rst:start-1 rst:flex rst:items-center", children: /* @__PURE__ */ c("div", { className: "rst:pointer-events-auto", children: k }) }),
356
+ /* @__PURE__ */ c("div", { className: "rst:pointer-events-none rst:absolute rst:inset-y-0 rst:end-1 rst:flex rst:items-center", children: /* @__PURE__ */ c("div", { className: "rst:pointer-events-auto", children: B }) })
357
+ ] })
358
+ ] })
359
+ ] });
360
+ });
361
+ export {
362
+ ce as Carousel
363
+ };
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=["base","sm","md","lg","xl"];function o(t){const r=Math.ceil(t)-1;return`calc((100% + ${Number.isInteger(t)?0:1} * var(--rst-cv-gutter) - ${r} * var(--rst-cv-gap)) / ${t})`}function n(t){const r=typeof t=="number"?{base:t}:t,s={};let c;for(const v of a){const e=r[v];e!==void 0&&e>0&&(c=e),c!==void 0&&(s[`--rst-cv-w-${v}`]=o(c))}return s}const i="var(--rst-cv-w)",l="rst:[--rst-cv-w:var(--rst-cv-w-base)] rst:sm:[--rst-cv-w:var(--rst-cv-w-sm)] rst:md:[--rst-cv-w:var(--rst-cv-w-md)] rst:lg:[--rst-cv-w:var(--rst-cv-w-lg)] rst:xl:[--rst-cv-w:var(--rst-cv-w-xl)]";exports.BREAKPOINTS=a;exports.FLUID_CLASSES=l;exports.FLUID_ITEM_WIDTH=i;exports.fluidItemWidth=o;exports.perViewVars=n;
@@ -0,0 +1,23 @@
1
+ import { CarouselPerView } from './Carousel';
2
+ /**
3
+ * Fluid mode's sizing. The items-per-view table becomes one item width per
4
+ * breakpoint, set as custom properties on the list, and five short classes
5
+ * pick the one for the current width. The server render is already the right
6
+ * size, and nothing measures before it paints.
7
+ *
8
+ * Every breakpoint is filled in, carrying the one below it up, so the CSS
9
+ * needs no fallback chain, and a row nested in another fluid row never
10
+ * inherits the outer row's widths. Kept small on purpose: Roster's stylesheet
11
+ * ships to every consumer, carousel or not.
12
+ */
13
+ export declare const BREAKPOINTS: readonly ["base", "sm", "md", "lg", "xl"];
14
+ /**
15
+ * One item's width for `n` items per view. A fraction is the peek, and the
16
+ * peek runs into the trailing gutter, out to the edge. A whole number of items
17
+ * fits between the gutters instead, so a one-per-view gallery sits centered.
18
+ * `100%` is the list's content box, resolved where the width is used.
19
+ */
20
+ export declare function fluidItemWidth(n: number): string;
21
+ export declare function perViewVars(perView: number | CarouselPerView): Record<string, string>;
22
+ export declare const FLUID_ITEM_WIDTH = "var(--rst-cv-w)";
23
+ export declare const FLUID_CLASSES = "rst:[--rst-cv-w:var(--rst-cv-w-base)] rst:sm:[--rst-cv-w:var(--rst-cv-w-sm)] rst:md:[--rst-cv-w:var(--rst-cv-w-md)] rst:lg:[--rst-cv-w:var(--rst-cv-w-lg)] rst:xl:[--rst-cv-w:var(--rst-cv-w-xl)]";