@blakesteve/roster 5.0.1 → 5.2.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/README.md +110 -9
- package/dist/components/atoms/Chip/Chip.cjs +1 -1
- package/dist/components/atoms/Chip/Chip.js +27 -27
- package/dist/components/atoms/Disclosure/Disclosure.cjs +1 -1
- package/dist/components/atoms/Disclosure/Disclosure.js +42 -44
- package/dist/components/atoms/Input/Input.cjs +1 -1
- package/dist/components/atoms/Input/Input.js +46 -41
- package/dist/components/atoms/Spinner/Spinner.cjs +1 -1
- package/dist/components/atoms/Spinner/Spinner.d.ts +6 -1
- package/dist/components/atoms/Spinner/Spinner.js +9 -8
- package/dist/components/atoms/Stat/Stat.cjs +1 -1
- package/dist/components/atoms/Stat/Stat.d.ts +27 -2
- package/dist/components/atoms/Stat/Stat.js +38 -13
- package/dist/components/atoms/Switch/Switch.cjs +1 -1
- package/dist/components/atoms/Switch/Switch.d.ts +11 -1
- package/dist/components/atoms/Switch/Switch.js +38 -36
- package/dist/components/atoms/Switch/switch-variants.cjs +1 -1
- package/dist/components/atoms/Switch/switch-variants.js +1 -1
- package/dist/components/molecules/Carousel/Carousel.cjs +1 -0
- package/dist/components/molecules/Carousel/Carousel.d.ts +146 -0
- package/dist/components/molecules/Carousel/Carousel.js +363 -0
- package/dist/components/molecules/Carousel/carousel-layout.cjs +1 -0
- package/dist/components/molecules/Carousel/carousel-layout.d.ts +23 -0
- package/dist/components/molecules/Carousel/carousel-layout.js +22 -0
- package/dist/components/molecules/Carousel/carousel-math.cjs +1 -0
- package/dist/components/molecules/Carousel/carousel-math.d.ts +60 -0
- package/dist/components/molecules/Carousel/carousel-math.js +58 -0
- package/dist/components/molecules/EmptyState/EmptyState.cjs +1 -1
- package/dist/components/molecules/EmptyState/EmptyState.d.ts +7 -1
- package/dist/components/molecules/EmptyState/EmptyState.js +18 -14
- package/dist/components/molecules/LiquidTabs/LiquidNav.cjs +1 -0
- package/dist/components/molecules/LiquidTabs/LiquidNav.d.ts +62 -0
- package/dist/components/molecules/LiquidTabs/LiquidNav.js +78 -0
- package/dist/components/molecules/LiquidTabs/LiquidTabs.cjs +1 -0
- package/dist/components/molecules/LiquidTabs/LiquidTabs.d.ts +69 -0
- package/dist/components/molecules/LiquidTabs/LiquidTabs.js +92 -0
- package/dist/components/molecules/LiquidTabs/liquid-pill.cjs +1 -0
- package/dist/components/molecules/LiquidTabs/liquid-pill.d.ts +56 -0
- package/dist/components/molecules/LiquidTabs/liquid-pill.js +129 -0
- package/dist/components/molecules/LiquidTabs/liquid-tab-id.cjs +1 -0
- package/dist/components/molecules/LiquidTabs/liquid-tab-id.d.ts +12 -0
- package/dist/components/molecules/LiquidTabs/liquid-tab-id.js +6 -0
- package/dist/components/molecules/Toast/Toaster.cjs +1 -1
- package/dist/components/molecules/Toast/Toaster.d.ts +7 -0
- package/dist/components/molecules/Toast/Toaster.js +67 -45
- package/dist/components/organisms/Dialog/Dialog.cjs +1 -1
- package/dist/components/organisms/Dialog/Dialog.js +102 -79
- package/dist/components/organisms/Navbar/Navbar.cjs +1 -1
- package/dist/components/organisms/Navbar/Navbar.js +157 -157
- package/dist/components/organisms/Sheet/Sheet.cjs +1 -0
- package/dist/components/organisms/Sheet/Sheet.d.ts +85 -0
- package/dist/components/organisms/Sheet/Sheet.js +304 -0
- package/dist/components/organisms/Sheet/sheet-drag.cjs +1 -0
- package/dist/components/organisms/Sheet/sheet-drag.d.ts +40 -0
- package/dist/components/organisms/Sheet/sheet-drag.js +22 -0
- package/dist/components/organisms/Sheet/sheet-title.cjs +1 -0
- package/dist/components/organisms/Sheet/sheet-title.d.ts +10 -0
- package/dist/components/organisms/Sheet/sheet-title.js +17 -0
- package/dist/index.d.ts +5 -1
- package/dist/internal/motion.cjs +1 -0
- package/dist/internal/motion.d.ts +12 -0
- package/dist/internal/motion.js +21 -0
- package/dist/internal/page-inert.cjs +1 -0
- package/dist/internal/page-inert.d.ts +51 -0
- package/dist/internal/page-inert.js +36 -0
- package/dist/meta.json +3 -3
- package/dist/roster.cjs +1 -1
- package/dist/roster.css +1 -1
- package/dist/roster.js +130 -122
- package/package.json +1 -1
- package/dist/components/atoms/LiquidTabs/LiquidTabs.cjs +0 -1
- package/dist/components/atoms/LiquidTabs/LiquidTabs.d.ts +0 -39
- package/dist/components/atoms/LiquidTabs/LiquidTabs.js +0 -120
|
@@ -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)]";
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const a = ["base", "sm", "md", "lg", "xl"];
|
|
2
|
+
function n(t) {
|
|
3
|
+
const r = Math.ceil(t) - 1;
|
|
4
|
+
return `calc((100% + ${Number.isInteger(t) ? 0 : 1} * var(--rst-cv-gutter) - ${r} * var(--rst-cv-gap)) / ${t})`;
|
|
5
|
+
}
|
|
6
|
+
function o(t) {
|
|
7
|
+
const r = typeof t == "number" ? { base: t } : t, s = {};
|
|
8
|
+
let c;
|
|
9
|
+
for (const e of a) {
|
|
10
|
+
const v = r[e];
|
|
11
|
+
v !== void 0 && v > 0 && (c = v), c !== void 0 && (s[`--rst-cv-w-${e}`] = n(c));
|
|
12
|
+
}
|
|
13
|
+
return s;
|
|
14
|
+
}
|
|
15
|
+
const l = "var(--rst-cv-w)", w = "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)]";
|
|
16
|
+
export {
|
|
17
|
+
a as BREAKPOINTS,
|
|
18
|
+
w as FLUID_CLASSES,
|
|
19
|
+
l as FLUID_ITEM_WIDTH,
|
|
20
|
+
n as fluidItemWidth,
|
|
21
|
+
o as perViewVars
|
|
22
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const d=6,i=1;function a(t){return Math.max(0,t.scrollWidth-t.clientWidth)}function h(t){return a(t)>i}function S(t){return t.scrollLeft>i}function L(t){return t.scrollLeft<a(t)-i}function s(t,e){const n=t.items[e];if(!n)return 0;const r=t.align==="start"?n.start-t.paddingStart:(n.start+n.end)/2-(t.paddingStart+(t.clientWidth-t.paddingStart-t.paddingEnd)/2);return Math.min(Math.max(0,r),a(t))}function u(t){const e=t.scrollLeft-i,n=t.scrollLeft+t.clientWidth+i,r=[];return t.items.forEach((l,c)=>{l.start>=e&&l.end<=n&&r.push(c)}),r}function f(t){let e=0,n=1/0;return t.items.forEach((r,l)=>{const c=Math.abs(s(t,l)-t.scrollLeft);c<n&&(e=l,n=c)}),e}function m(t){const e=u(t);return e.length?e[0]:f(t)}function x(t,e){const n=t.items.length;if(!n)return 0;const r=u(t),l=r.length?r[0]:f(t),c=Math.max(1,r.length);let o=Math.min(n-1,Math.max(0,l+e*c));for(;o>0&&o<n-1&&Math.abs(s(t,o)-t.scrollLeft)<=i;)o+=e;return s(t,o)}exports.CAROUSEL_DRAG_THRESHOLD=d;exports.CAROUSEL_TOLERANCE=i;exports.canScrollNext=L;exports.canScrollPrev=S;exports.currentIndex=m;exports.fullyVisible=u;exports.maxScroll=a;exports.nearestIndex=f;exports.overflows=h;exports.pageTarget=x;exports.snapPosition=s;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a carousel's row is, and where it should go.
|
|
3
|
+
*
|
|
4
|
+
* Pure, and kept out of the component so paging and snapping can be tested
|
|
5
|
+
* with literal numbers. jsdom has no layout, so a test that read positions
|
|
6
|
+
* from the DOM would be testing zero; the stories measure the real thing.
|
|
7
|
+
*
|
|
8
|
+
* Every position is in the scroller's own coordinates, the space `scrollLeft`
|
|
9
|
+
* is measured in: an item's `start` is how far `scrollLeft` would have to be
|
|
10
|
+
* for the item's leading edge to sit at the scroller's leading edge.
|
|
11
|
+
*/
|
|
12
|
+
export interface CarouselItemBox {
|
|
13
|
+
start: number;
|
|
14
|
+
end: number;
|
|
15
|
+
}
|
|
16
|
+
export interface CarouselGeometry {
|
|
17
|
+
items: readonly CarouselItemBox[];
|
|
18
|
+
scrollLeft: number;
|
|
19
|
+
clientWidth: number;
|
|
20
|
+
scrollWidth: number;
|
|
21
|
+
/** `scroll-padding-inline-start`: the gutter a snapped item lines up with. */
|
|
22
|
+
paddingStart: number;
|
|
23
|
+
/** `scroll-padding-inline-end`. */
|
|
24
|
+
paddingEnd: number;
|
|
25
|
+
align: "start" | "center";
|
|
26
|
+
}
|
|
27
|
+
/** Movement past this, in px, makes a mouse press a drag, and its click is dropped. */
|
|
28
|
+
export declare const CAROUSEL_DRAG_THRESHOLD = 6;
|
|
29
|
+
/** Sub-pixel layout leaves fractions; anything closer than this is "at". */
|
|
30
|
+
export declare const CAROUSEL_TOLERANCE = 1;
|
|
31
|
+
export declare function maxScroll(g: CarouselGeometry): number;
|
|
32
|
+
/** Whether the row is wider than its box at all. */
|
|
33
|
+
export declare function overflows(g: CarouselGeometry): boolean;
|
|
34
|
+
export declare function canScrollPrev(g: CarouselGeometry): boolean;
|
|
35
|
+
export declare function canScrollNext(g: CarouselGeometry): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* The `scrollLeft` that snaps item `i` into place, clamped to what the row can
|
|
38
|
+
* reach. The last items of a row that can't align to the start land at the
|
|
39
|
+
* end, which is also where the browser's own snapping puts them.
|
|
40
|
+
*/
|
|
41
|
+
export declare function snapPosition(g: CarouselGeometry, i: number): number;
|
|
42
|
+
/** Indices of the items wholly inside the box at the current scroll. */
|
|
43
|
+
export declare function fullyVisible(g: CarouselGeometry): number[];
|
|
44
|
+
/** The item whose snap position is nearest the current scroll. */
|
|
45
|
+
export declare function nearestIndex(g: CarouselGeometry): number;
|
|
46
|
+
/**
|
|
47
|
+
* The first item wholly in view, which is what the row reports as its index.
|
|
48
|
+
* An item wider than the box is never wholly in view, so then it is the item
|
|
49
|
+
* the row is snapped nearest to.
|
|
50
|
+
*/
|
|
51
|
+
export declare function currentIndex(g: CarouselGeometry): number;
|
|
52
|
+
/**
|
|
53
|
+
* Where a previous or next arrow should take the row: a page, which is as many
|
|
54
|
+
* items as are wholly in view (at least one), landing on an item's snap point.
|
|
55
|
+
* Measured every time rather than a fixed pixel step, so it holds whatever the
|
|
56
|
+
* items' widths and however many are in view.
|
|
57
|
+
*
|
|
58
|
+
* Returns the target `scrollLeft`.
|
|
59
|
+
*/
|
|
60
|
+
export declare function pageTarget(g: CarouselGeometry, direction: 1 | -1): number;
|