@nori-ui/core 1.7.0 → 1.8.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/chunk-BOMPFNM4.js +165 -0
- package/dist/chunk-BOMPFNM4.js.map +1 -0
- package/dist/chunk-BVLOX4A3.js +256 -0
- package/dist/chunk-BVLOX4A3.js.map +1 -0
- package/dist/chunk-VFUV6XJR.js +257 -0
- package/dist/chunk-VFUV6XJR.js.map +1 -0
- package/dist/client.cjs +650 -0
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +3 -0
- package/dist/client.d.ts +3 -0
- package/dist/client.js +14 -11
- package/dist/client.js.map +1 -1
- package/dist/components/Carousel/index.cjs +297 -0
- package/dist/components/Carousel/index.cjs.map +1 -0
- package/dist/components/Carousel/index.d.cts +67 -0
- package/dist/components/Carousel/index.d.ts +67 -0
- package/dist/components/Carousel/index.js +5 -0
- package/dist/components/Carousel/index.js.map +1 -0
- package/dist/components/HoverCard/index.cjs +894 -0
- package/dist/components/HoverCard/index.cjs.map +1 -0
- package/dist/components/HoverCard/index.d.cts +66 -0
- package/dist/components/HoverCard/index.d.ts +66 -0
- package/dist/components/HoverCard/index.js +9 -0
- package/dist/components/HoverCard/index.js.map +1 -0
- package/dist/components/InputOTP/index.cjs +580 -0
- package/dist/components/InputOTP/index.cjs.map +1 -0
- package/dist/components/InputOTP/index.d.cts +49 -0
- package/dist/components/InputOTP/index.d.ts +49 -0
- package/dist/components/InputOTP/index.js +7 -0
- package/dist/components/InputOTP/index.js.map +1 -0
- package/dist/index.cjs +650 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +14 -11
- package/package.json +1 -1
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import { cn } from './chunk-CHXHRJNZ.js';
|
|
2
|
+
import { __name } from './chunk-WCQVDF3K.js';
|
|
3
|
+
import { createContext, useContext, useState, useRef, useId, useCallback, useEffect, Children } from 'react';
|
|
4
|
+
import { jsx } from 'nativewind/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
var CarouselContext = createContext(null);
|
|
7
|
+
function useCarouselContext(caller) {
|
|
8
|
+
const ctx = useContext(CarouselContext);
|
|
9
|
+
if (!ctx) {
|
|
10
|
+
throw new Error(`<${caller}> must be rendered inside <Carousel>.`);
|
|
11
|
+
}
|
|
12
|
+
return ctx;
|
|
13
|
+
}
|
|
14
|
+
__name(useCarouselContext, "useCarouselContext");
|
|
15
|
+
var CarouselRoot = /* @__PURE__ */ __name(({
|
|
16
|
+
index: controlledIndex,
|
|
17
|
+
defaultIndex = 0,
|
|
18
|
+
onIndexChange,
|
|
19
|
+
loop = false,
|
|
20
|
+
orientation = "horizontal",
|
|
21
|
+
children,
|
|
22
|
+
className,
|
|
23
|
+
testID
|
|
24
|
+
}) => {
|
|
25
|
+
const [inner, setInner] = useState(defaultIndex);
|
|
26
|
+
const isControlled = controlledIndex !== void 0;
|
|
27
|
+
const index = isControlled ? controlledIndex : inner;
|
|
28
|
+
const [count, setCount] = useState(0);
|
|
29
|
+
const listRef = useRef(null);
|
|
30
|
+
const id = useId();
|
|
31
|
+
const setIndex = useCallback(
|
|
32
|
+
(next2) => {
|
|
33
|
+
if (!isControlled) {
|
|
34
|
+
setInner(next2);
|
|
35
|
+
}
|
|
36
|
+
onIndexChange?.(next2);
|
|
37
|
+
},
|
|
38
|
+
[isControlled, onIndexChange]
|
|
39
|
+
);
|
|
40
|
+
const scrollTo = useCallback(
|
|
41
|
+
(idx) => {
|
|
42
|
+
const list = listRef.current;
|
|
43
|
+
if (!list) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const item = list.children[idx];
|
|
47
|
+
if (!item) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
item.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "nearest" });
|
|
51
|
+
setIndex(idx);
|
|
52
|
+
},
|
|
53
|
+
[setIndex]
|
|
54
|
+
);
|
|
55
|
+
const next = useCallback(() => {
|
|
56
|
+
if (count === 0) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (index < count - 1) {
|
|
60
|
+
scrollTo(index + 1);
|
|
61
|
+
} else if (loop) {
|
|
62
|
+
scrollTo(0);
|
|
63
|
+
}
|
|
64
|
+
}, [index, count, loop, scrollTo]);
|
|
65
|
+
const prev = useCallback(() => {
|
|
66
|
+
if (count === 0) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if (index > 0) {
|
|
70
|
+
scrollTo(index - 1);
|
|
71
|
+
} else if (loop) {
|
|
72
|
+
scrollTo(count - 1);
|
|
73
|
+
}
|
|
74
|
+
}, [index, count, loop, scrollTo]);
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
const list = listRef.current;
|
|
77
|
+
if (!list) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const handleScroll = /* @__PURE__ */ __name(() => {
|
|
81
|
+
const { scrollLeft, scrollTop, offsetWidth, offsetHeight } = list;
|
|
82
|
+
const pos = orientation === "horizontal" ? scrollLeft : scrollTop;
|
|
83
|
+
const size = orientation === "horizontal" ? offsetWidth : offsetHeight;
|
|
84
|
+
if (size === 0) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const newIdx = Math.round(pos / size);
|
|
88
|
+
if (newIdx !== index) {
|
|
89
|
+
setIndex(newIdx);
|
|
90
|
+
}
|
|
91
|
+
}, "handleScroll");
|
|
92
|
+
list.addEventListener("scroll", handleScroll, { passive: true });
|
|
93
|
+
return () => list.removeEventListener("scroll", handleScroll);
|
|
94
|
+
}, [orientation, index, setIndex]);
|
|
95
|
+
return /* @__PURE__ */ jsx(
|
|
96
|
+
CarouselContext.Provider,
|
|
97
|
+
{
|
|
98
|
+
value: { index, count, loop, orientation, scrollTo, next, prev, listRef, setCount, id },
|
|
99
|
+
children: /* @__PURE__ */ jsx(
|
|
100
|
+
"section",
|
|
101
|
+
{
|
|
102
|
+
"aria-label": testID ?? "Carousel",
|
|
103
|
+
className: cn("relative overflow-hidden", className),
|
|
104
|
+
"data-testid": testID,
|
|
105
|
+
children
|
|
106
|
+
}
|
|
107
|
+
)
|
|
108
|
+
}
|
|
109
|
+
);
|
|
110
|
+
}, "CarouselRoot");
|
|
111
|
+
var CarouselContent = /* @__PURE__ */ __name(({ children, className, testID }) => {
|
|
112
|
+
const ctx = useCarouselContext("Carousel.Content");
|
|
113
|
+
const childCount = Children.count(children);
|
|
114
|
+
useEffect(() => {
|
|
115
|
+
ctx.setCount(childCount);
|
|
116
|
+
}, [childCount, ctx.setCount]);
|
|
117
|
+
const isHorizontal = ctx.orientation === "horizontal";
|
|
118
|
+
return /* @__PURE__ */ jsx(
|
|
119
|
+
"div",
|
|
120
|
+
{
|
|
121
|
+
ref: ctx.listRef,
|
|
122
|
+
"data-testid": testID,
|
|
123
|
+
className: cn(
|
|
124
|
+
"flex",
|
|
125
|
+
isHorizontal ? "flex-row overflow-x-auto overflow-y-hidden" : "flex-col overflow-y-auto overflow-x-hidden",
|
|
126
|
+
className
|
|
127
|
+
),
|
|
128
|
+
style: {
|
|
129
|
+
scrollSnapType: isHorizontal ? "x mandatory" : "y mandatory",
|
|
130
|
+
scrollBehavior: "smooth",
|
|
131
|
+
WebkitOverflowScrolling: "touch",
|
|
132
|
+
// Hide scrollbar
|
|
133
|
+
scrollbarWidth: "none",
|
|
134
|
+
msOverflowStyle: "none"
|
|
135
|
+
},
|
|
136
|
+
children
|
|
137
|
+
}
|
|
138
|
+
);
|
|
139
|
+
}, "CarouselContent");
|
|
140
|
+
var CarouselItem = /* @__PURE__ */ __name(({ children, className, testID }) => {
|
|
141
|
+
const ctx = useCarouselContext("Carousel.Item");
|
|
142
|
+
const isHorizontal = ctx.orientation === "horizontal";
|
|
143
|
+
return /* @__PURE__ */ jsx(
|
|
144
|
+
"div",
|
|
145
|
+
{
|
|
146
|
+
"data-testid": testID,
|
|
147
|
+
className: cn("shrink-0", isHorizontal ? "w-full" : "h-full", className),
|
|
148
|
+
style: {
|
|
149
|
+
scrollSnapAlign: "start",
|
|
150
|
+
minWidth: isHorizontal ? "100%" : void 0,
|
|
151
|
+
minHeight: !isHorizontal ? "100%" : void 0
|
|
152
|
+
},
|
|
153
|
+
children
|
|
154
|
+
}
|
|
155
|
+
);
|
|
156
|
+
}, "CarouselItem");
|
|
157
|
+
var CarouselPrevious = /* @__PURE__ */ __name(({ className, testID, children }) => {
|
|
158
|
+
const ctx = useCarouselContext("Carousel.Previous");
|
|
159
|
+
const disabled = !ctx.loop && ctx.index === 0;
|
|
160
|
+
return /* @__PURE__ */ jsx(
|
|
161
|
+
"button",
|
|
162
|
+
{
|
|
163
|
+
type: "button",
|
|
164
|
+
"aria-label": "Previous slide",
|
|
165
|
+
disabled,
|
|
166
|
+
"data-testid": testID,
|
|
167
|
+
onClick: ctx.prev,
|
|
168
|
+
className: cn(
|
|
169
|
+
"absolute left-2 top-1/2 z-10 flex h-8 w-8 -translate-y-1/2 items-center justify-center rounded-full bg-white/80 shadow hover:bg-white disabled:opacity-40",
|
|
170
|
+
className
|
|
171
|
+
),
|
|
172
|
+
children: children ?? /* @__PURE__ */ jsx(
|
|
173
|
+
"svg",
|
|
174
|
+
{
|
|
175
|
+
viewBox: "0 0 24 24",
|
|
176
|
+
fill: "none",
|
|
177
|
+
stroke: "currentColor",
|
|
178
|
+
strokeWidth: 2,
|
|
179
|
+
className: "h-4 w-4",
|
|
180
|
+
"aria-hidden": "true",
|
|
181
|
+
children: /* @__PURE__ */ jsx("path", { d: "M15 18l-6-6 6-6", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
182
|
+
}
|
|
183
|
+
)
|
|
184
|
+
}
|
|
185
|
+
);
|
|
186
|
+
}, "CarouselPrevious");
|
|
187
|
+
var CarouselNext = /* @__PURE__ */ __name(({ className, testID, children }) => {
|
|
188
|
+
const ctx = useCarouselContext("Carousel.Next");
|
|
189
|
+
const disabled = !ctx.loop && ctx.index >= ctx.count - 1;
|
|
190
|
+
return /* @__PURE__ */ jsx(
|
|
191
|
+
"button",
|
|
192
|
+
{
|
|
193
|
+
type: "button",
|
|
194
|
+
"aria-label": "Next slide",
|
|
195
|
+
disabled,
|
|
196
|
+
"data-testid": testID,
|
|
197
|
+
onClick: ctx.next,
|
|
198
|
+
className: cn(
|
|
199
|
+
"absolute right-2 top-1/2 z-10 flex h-8 w-8 -translate-y-1/2 items-center justify-center rounded-full bg-white/80 shadow hover:bg-white disabled:opacity-40",
|
|
200
|
+
className
|
|
201
|
+
),
|
|
202
|
+
children: children ?? /* @__PURE__ */ jsx(
|
|
203
|
+
"svg",
|
|
204
|
+
{
|
|
205
|
+
viewBox: "0 0 24 24",
|
|
206
|
+
fill: "none",
|
|
207
|
+
stroke: "currentColor",
|
|
208
|
+
strokeWidth: 2,
|
|
209
|
+
className: "h-4 w-4",
|
|
210
|
+
"aria-hidden": "true",
|
|
211
|
+
children: /* @__PURE__ */ jsx("path", { d: "M9 18l6-6-6-6", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
212
|
+
}
|
|
213
|
+
)
|
|
214
|
+
}
|
|
215
|
+
);
|
|
216
|
+
}, "CarouselNext");
|
|
217
|
+
var CarouselDots = /* @__PURE__ */ __name(({ className, testID }) => {
|
|
218
|
+
const ctx = useCarouselContext("Carousel.Dots");
|
|
219
|
+
if (ctx.count === 0) {
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
return /* @__PURE__ */ jsx(
|
|
223
|
+
"div",
|
|
224
|
+
{
|
|
225
|
+
role: "tablist",
|
|
226
|
+
"aria-label": "Slide navigation",
|
|
227
|
+
"data-testid": testID,
|
|
228
|
+
className: cn("absolute bottom-3 left-0 right-0 flex items-center justify-center gap-1.5", className),
|
|
229
|
+
children: Array.from({ length: ctx.count }, (_, i) => /* @__PURE__ */ jsx(
|
|
230
|
+
"button",
|
|
231
|
+
{
|
|
232
|
+
type: "button",
|
|
233
|
+
role: "tab",
|
|
234
|
+
"aria-selected": i === ctx.index,
|
|
235
|
+
"aria-label": `Go to slide ${i + 1}`,
|
|
236
|
+
onClick: () => ctx.scrollTo(i),
|
|
237
|
+
className: cn(
|
|
238
|
+
"h-1.5 w-1.5 rounded-full transition-all",
|
|
239
|
+
i === ctx.index ? "w-3 bg-white" : "bg-white/50 hover:bg-white/75"
|
|
240
|
+
)
|
|
241
|
+
},
|
|
242
|
+
i
|
|
243
|
+
))
|
|
244
|
+
}
|
|
245
|
+
);
|
|
246
|
+
}, "CarouselDots");
|
|
247
|
+
var Carousel = Object.assign(CarouselRoot, {
|
|
248
|
+
Content: CarouselContent,
|
|
249
|
+
Item: CarouselItem,
|
|
250
|
+
Previous: CarouselPrevious,
|
|
251
|
+
Next: CarouselNext,
|
|
252
|
+
Dots: CarouselDots
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
export { Carousel };
|
|
256
|
+
//# sourceMappingURL=chunk-VFUV6XJR.js.map
|
|
257
|
+
//# sourceMappingURL=chunk-VFUV6XJR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/Carousel/Carousel.web.tsx"],"names":["next"],"mappings":"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","file":"chunk-VFUV6XJR.js","sourcesContent":["'use client';\n\nimport {\n Children,\n createContext,\n type ReactNode,\n useCallback,\n useContext,\n useEffect,\n useId,\n useRef,\n useState,\n} from 'react';\nimport { cn } from '../../utils/cn';\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\ntype CarouselContextValue = {\n index: number;\n count: number;\n loop: boolean;\n orientation: 'horizontal' | 'vertical';\n scrollTo: (idx: number) => void;\n next: () => void;\n prev: () => void;\n listRef: React.RefObject<HTMLDivElement | null>;\n setCount: (n: number) => void;\n id: string;\n};\n\nconst CarouselContext = createContext<CarouselContextValue | null>(null);\n\nfunction useCarouselContext(caller: string): CarouselContextValue {\n const ctx = useContext(CarouselContext);\n if (!ctx) {\n throw new Error(`<${caller}> must be rendered inside <Carousel>.`);\n }\n return ctx;\n}\n\n// ---------------------------------------------------------------------------\n// Root\n// ---------------------------------------------------------------------------\n\nexport type CarouselProps = {\n /** Controlled current index. */\n index?: number;\n /** Initial index (uncontrolled). @defaultValue 0 */\n defaultIndex?: number;\n /** Fires with the new index. */\n onIndexChange?: (index: number) => void;\n /** Whether navigation wraps from last to first and vice-versa. @defaultValue false */\n loop?: boolean;\n /** Scroll axis. @defaultValue 'horizontal' */\n orientation?: 'horizontal' | 'vertical';\n children?: ReactNode;\n className?: string;\n testID?: string;\n};\n\nconst CarouselRoot = ({\n index: controlledIndex,\n defaultIndex = 0,\n onIndexChange,\n loop = false,\n orientation = 'horizontal',\n children,\n className,\n testID,\n}: CarouselProps) => {\n const [inner, setInner] = useState(defaultIndex);\n const isControlled = controlledIndex !== undefined;\n const index = isControlled ? (controlledIndex as number) : inner;\n const [count, setCount] = useState(0);\n const listRef = useRef<HTMLDivElement | null>(null);\n const id = useId();\n\n const setIndex = useCallback(\n (next: number) => {\n if (!isControlled) {\n setInner(next);\n }\n onIndexChange?.(next);\n },\n [isControlled, onIndexChange]\n );\n\n const scrollTo = useCallback(\n (idx: number) => {\n const list = listRef.current;\n if (!list) {\n return;\n }\n const item = list.children[idx] as HTMLElement | undefined;\n if (!item) {\n return;\n }\n item.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'nearest' });\n setIndex(idx);\n },\n [setIndex]\n );\n\n const next = useCallback(() => {\n if (count === 0) {\n return;\n }\n if (index < count - 1) {\n scrollTo(index + 1);\n } else if (loop) {\n scrollTo(0);\n }\n }, [index, count, loop, scrollTo]);\n\n const prev = useCallback(() => {\n if (count === 0) {\n return;\n }\n if (index > 0) {\n scrollTo(index - 1);\n } else if (loop) {\n scrollTo(count - 1);\n }\n }, [index, count, loop, scrollTo]);\n\n // Keep index in sync if external scroll happens\n useEffect(() => {\n const list = listRef.current;\n if (!list) {\n return;\n }\n const handleScroll = () => {\n const { scrollLeft, scrollTop, offsetWidth, offsetHeight } = list;\n const pos = orientation === 'horizontal' ? scrollLeft : scrollTop;\n const size = orientation === 'horizontal' ? offsetWidth : offsetHeight;\n if (size === 0) {\n return;\n }\n const newIdx = Math.round(pos / size);\n if (newIdx !== index) {\n setIndex(newIdx);\n }\n };\n list.addEventListener('scroll', handleScroll, { passive: true });\n return () => list.removeEventListener('scroll', handleScroll);\n }, [orientation, index, setIndex]);\n\n return (\n <CarouselContext.Provider\n value={{ index, count, loop, orientation, scrollTo, next, prev, listRef, setCount, id }}\n >\n <section\n aria-label={testID ?? 'Carousel'}\n className={cn('relative overflow-hidden', className)}\n data-testid={testID}\n >\n {children}\n </section>\n </CarouselContext.Provider>\n );\n};\n\n// ---------------------------------------------------------------------------\n// Content — the scroll container\n// ---------------------------------------------------------------------------\n\nexport type CarouselContentProps = {\n children?: ReactNode;\n className?: string;\n testID?: string;\n};\n\nconst CarouselContent = ({ children, className, testID }: CarouselContentProps) => {\n const ctx = useCarouselContext('Carousel.Content');\n\n // Count items\n const childCount = Children.count(children);\n useEffect(() => {\n ctx.setCount(childCount);\n }, [childCount, ctx.setCount]);\n\n const isHorizontal = ctx.orientation === 'horizontal';\n\n return (\n <div\n ref={ctx.listRef}\n data-testid={testID}\n className={cn(\n 'flex',\n isHorizontal\n ? 'flex-row overflow-x-auto overflow-y-hidden'\n : 'flex-col overflow-y-auto overflow-x-hidden',\n className\n )}\n style={{\n scrollSnapType: isHorizontal ? 'x mandatory' : 'y mandatory',\n scrollBehavior: 'smooth',\n WebkitOverflowScrolling: 'touch',\n // Hide scrollbar\n scrollbarWidth: 'none',\n msOverflowStyle: 'none',\n }}\n >\n {children}\n </div>\n );\n};\n\n// ---------------------------------------------------------------------------\n// Item\n// ---------------------------------------------------------------------------\n\nexport type CarouselItemProps = {\n children?: ReactNode;\n className?: string;\n testID?: string;\n};\n\nconst CarouselItem = ({ children, className, testID }: CarouselItemProps) => {\n const ctx = useCarouselContext('Carousel.Item');\n const isHorizontal = ctx.orientation === 'horizontal';\n return (\n <div\n data-testid={testID}\n className={cn('shrink-0', isHorizontal ? 'w-full' : 'h-full', className)}\n style={{\n scrollSnapAlign: 'start',\n minWidth: isHorizontal ? '100%' : undefined,\n minHeight: !isHorizontal ? '100%' : undefined,\n }}\n >\n {children}\n </div>\n );\n};\n\n// ---------------------------------------------------------------------------\n// Previous / Next buttons\n// ---------------------------------------------------------------------------\n\nexport type CarouselButtonProps = {\n className?: string;\n testID?: string;\n children?: ReactNode;\n};\n\nconst CarouselPrevious = ({ className, testID, children }: CarouselButtonProps) => {\n const ctx = useCarouselContext('Carousel.Previous');\n const disabled = !ctx.loop && ctx.index === 0;\n return (\n <button\n type=\"button\"\n aria-label=\"Previous slide\"\n disabled={disabled}\n data-testid={testID}\n onClick={ctx.prev}\n className={cn(\n 'absolute left-2 top-1/2 z-10 flex h-8 w-8 -translate-y-1/2 items-center justify-center rounded-full bg-white/80 shadow hover:bg-white disabled:opacity-40',\n className\n )}\n >\n {children ?? (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n className=\"h-4 w-4\"\n aria-hidden=\"true\"\n >\n <path d=\"M15 18l-6-6 6-6\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n )}\n </button>\n );\n};\n\nconst CarouselNext = ({ className, testID, children }: CarouselButtonProps) => {\n const ctx = useCarouselContext('Carousel.Next');\n const disabled = !ctx.loop && ctx.index >= ctx.count - 1;\n return (\n <button\n type=\"button\"\n aria-label=\"Next slide\"\n disabled={disabled}\n data-testid={testID}\n onClick={ctx.next}\n className={cn(\n 'absolute right-2 top-1/2 z-10 flex h-8 w-8 -translate-y-1/2 items-center justify-center rounded-full bg-white/80 shadow hover:bg-white disabled:opacity-40',\n className\n )}\n >\n {children ?? (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n className=\"h-4 w-4\"\n aria-hidden=\"true\"\n >\n <path d=\"M9 18l6-6-6-6\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n )}\n </button>\n );\n};\n\n// ---------------------------------------------------------------------------\n// Dots\n// ---------------------------------------------------------------------------\n\nexport type CarouselDotsProps = {\n className?: string;\n testID?: string;\n};\n\nconst CarouselDots = ({ className, testID }: CarouselDotsProps) => {\n const ctx = useCarouselContext('Carousel.Dots');\n if (ctx.count === 0) {\n return null;\n }\n return (\n <div\n role=\"tablist\"\n aria-label=\"Slide navigation\"\n data-testid={testID}\n className={cn('absolute bottom-3 left-0 right-0 flex items-center justify-center gap-1.5', className)}\n >\n {Array.from({ length: ctx.count }, (_, i) => (\n <button\n // biome-ignore lint/suspicious/noArrayIndexKey: dot index IS its stable identity\n key={i}\n type=\"button\"\n role=\"tab\"\n aria-selected={i === ctx.index}\n aria-label={`Go to slide ${i + 1}`}\n onClick={() => ctx.scrollTo(i)}\n className={cn(\n 'h-1.5 w-1.5 rounded-full transition-all',\n i === ctx.index ? 'w-3 bg-white' : 'bg-white/50 hover:bg-white/75'\n )}\n />\n ))}\n </div>\n );\n};\n\n// ---------------------------------------------------------------------------\n// Public compound export\n// ---------------------------------------------------------------------------\n\n/**\n * Paged horizontal (or vertical) slider with CSS scroll-snap.\n *\n * Composition:\n * - `Carousel.Content` — the scroll container\n * - `Carousel.Item` — each slide\n * - `Carousel.Previous` / `Carousel.Next` — navigation buttons\n * - `Carousel.Dots` — dot pagination indicators\n *\n * ```tsx\n * <Carousel>\n * <Carousel.Content>\n * <Carousel.Item><img src=\"a.jpg\" /></Carousel.Item>\n * <Carousel.Item><img src=\"b.jpg\" /></Carousel.Item>\n * </Carousel.Content>\n * <Carousel.Previous />\n * <Carousel.Next />\n * <Carousel.Dots />\n * </Carousel>\n * ```\n */\nexport const Carousel = Object.assign(CarouselRoot, {\n Content: CarouselContent,\n Item: CarouselItem,\n Previous: CarouselPrevious,\n Next: CarouselNext,\n Dots: CarouselDots,\n});\n"]}
|