@salt-ds/embla-carousel 0.0.0-snapshot-20250627090641 → 0.1.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/CHANGELOG.md +14 -10
- package/css/salt-embla-carousel.css +14 -14
- package/dist-cjs/Carousel.css.js +1 -1
- package/dist-cjs/Carousel.js.map +1 -1
- package/dist-cjs/CarouselAnnouncementPlugin.js +9 -12
- package/dist-cjs/CarouselAnnouncementPlugin.js.map +1 -1
- package/dist-cjs/CarouselAutoplayIndicator.css.js +1 -1
- package/dist-cjs/CarouselAutoplayIndicator.js +64 -54
- package/dist-cjs/CarouselAutoplayIndicator.js.map +1 -1
- package/dist-cjs/CarouselAutoplayIndicatorSVG.js.map +1 -1
- package/dist-cjs/CarouselCard.css.js +1 -1
- package/dist-cjs/CarouselCard.js +1 -1
- package/dist-cjs/CarouselCard.js.map +1 -1
- package/dist-cjs/CarouselNextButton.js +4 -7
- package/dist-cjs/CarouselNextButton.js.map +1 -1
- package/dist-cjs/CarouselPreviousButton.js +4 -7
- package/dist-cjs/CarouselPreviousButton.js.map +1 -1
- package/dist-cjs/CarouselProgressLabel.css.js +1 -1
- package/dist-cjs/CarouselProgressLabel.js +24 -24
- package/dist-cjs/CarouselProgressLabel.js.map +1 -1
- package/dist-cjs/CarouselSlides.css.js +1 -1
- package/dist-cjs/CarouselSlides.js +33 -3
- package/dist-cjs/CarouselSlides.js.map +1 -1
- package/dist-cjs/CarouselTab.css.js +1 -1
- package/dist-cjs/CarouselTab.js +11 -15
- package/dist-cjs/CarouselTab.js.map +1 -1
- package/dist-cjs/CarouselTabList.js.map +1 -1
- package/dist-cjs/createCustomSettle.js +14 -0
- package/dist-cjs/createCustomSettle.js.map +1 -0
- package/dist-cjs/usePrevNextButtons.js +11 -13
- package/dist-cjs/usePrevNextButtons.js.map +1 -1
- package/dist-es/Carousel.css.js +1 -1
- package/dist-es/Carousel.js.map +1 -1
- package/dist-es/CarouselAnnouncementPlugin.js +9 -12
- package/dist-es/CarouselAnnouncementPlugin.js.map +1 -1
- package/dist-es/CarouselAutoplayIndicator.css.js +1 -1
- package/dist-es/CarouselAutoplayIndicator.js +64 -54
- package/dist-es/CarouselAutoplayIndicator.js.map +1 -1
- package/dist-es/CarouselAutoplayIndicatorSVG.js.map +1 -1
- package/dist-es/CarouselCard.css.js +1 -1
- package/dist-es/CarouselCard.js +1 -1
- package/dist-es/CarouselCard.js.map +1 -1
- package/dist-es/CarouselNextButton.js +5 -8
- package/dist-es/CarouselNextButton.js.map +1 -1
- package/dist-es/CarouselPreviousButton.js +5 -8
- package/dist-es/CarouselPreviousButton.js.map +1 -1
- package/dist-es/CarouselProgressLabel.css.js +1 -1
- package/dist-es/CarouselProgressLabel.js +25 -25
- package/dist-es/CarouselProgressLabel.js.map +1 -1
- package/dist-es/CarouselSlides.css.js +1 -1
- package/dist-es/CarouselSlides.js +34 -4
- package/dist-es/CarouselSlides.js.map +1 -1
- package/dist-es/CarouselTab.css.js +1 -1
- package/dist-es/CarouselTab.js +12 -16
- package/dist-es/CarouselTab.js.map +1 -1
- package/dist-es/CarouselTabList.js.map +1 -1
- package/dist-es/createCustomSettle.js +12 -0
- package/dist-es/createCustomSettle.js.map +1 -0
- package/dist-es/usePrevNextButtons.js +12 -14
- package/dist-es/usePrevNextButtons.js.map +1 -1
- package/dist-types/Carousel.d.ts +1 -1
- package/dist-types/CarouselAnnouncementPlugin.d.ts +8 -18
- package/dist-types/CarouselAutoplayIndicator.d.ts +4 -0
- package/dist-types/CarouselAutoplayIndicatorSVG.d.ts +2 -2
- package/dist-types/CarouselNextButton.d.ts +1 -1
- package/dist-types/CarouselPreviousButton.d.ts +1 -1
- package/dist-types/createCustomSettle.d.ts +4 -0
- package/package.json +2 -2
|
@@ -14,67 +14,77 @@ const sizeAndStrokeWidthMapping = {
|
|
|
14
14
|
low: { size: 14, strokeWidth: 2 },
|
|
15
15
|
touch: { size: 16, strokeWidth: 2 }
|
|
16
16
|
};
|
|
17
|
-
const CarouselAutoplayIndicator = forwardRef(
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
17
|
+
const CarouselAutoplayIndicator = forwardRef(
|
|
18
|
+
({
|
|
19
|
+
className,
|
|
20
|
+
duration,
|
|
21
|
+
slideIndex,
|
|
22
|
+
isPlaying,
|
|
23
|
+
isPaused = false,
|
|
24
|
+
children,
|
|
25
|
+
...props
|
|
26
|
+
}, ref) => {
|
|
27
|
+
const targetWindow = useWindow();
|
|
28
|
+
useComponentCssInjection({
|
|
29
|
+
testId: "salt-carousel-autoplay-indicator",
|
|
30
|
+
css: css_248z,
|
|
31
|
+
window: targetWindow
|
|
32
|
+
});
|
|
33
|
+
const barRef = useRef(null);
|
|
34
|
+
const animationFrameId = useRef(null);
|
|
35
|
+
const density = useDensity();
|
|
36
|
+
const { size, strokeWidth } = sizeAndStrokeWidthMapping[density];
|
|
37
|
+
const radius = (size - strokeWidth) / 2;
|
|
38
|
+
const circumference = 2 * Math.PI * radius;
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
if (barRef.current) {
|
|
38
41
|
animationFrameId.current = requestAnimationFrame(() => {
|
|
39
42
|
if (!barRef.current) {
|
|
40
43
|
return;
|
|
41
44
|
}
|
|
42
|
-
barRef.current.style.animation =
|
|
43
|
-
barRef.current.style.
|
|
45
|
+
barRef.current.style.animation = "none";
|
|
46
|
+
barRef.current.style.strokeDashoffset = `${circumference}`;
|
|
47
|
+
animationFrameId.current = requestAnimationFrame(() => {
|
|
48
|
+
if (!barRef.current) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
barRef.current.style.animation = `indicatorAnimation ${duration}ms linear`;
|
|
52
|
+
barRef.current.style.animationPlayState = isPaused ? "paused" : isPlaying ? "running" : "paused";
|
|
53
|
+
});
|
|
44
54
|
});
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
return () => {
|
|
48
|
-
if (animationFrameId.current !== null) {
|
|
49
|
-
cancelAnimationFrame(animationFrameId.current);
|
|
50
|
-
animationFrameId.current = null;
|
|
51
55
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
{
|
|
57
|
-
ref,
|
|
58
|
-
style: {
|
|
59
|
-
width: size,
|
|
60
|
-
height: size,
|
|
61
|
-
// @ts-ignore
|
|
62
|
-
"--salt-carousel-svg-circumference": circumference
|
|
63
|
-
},
|
|
64
|
-
className: clsx(withBaseName(), className),
|
|
65
|
-
...props,
|
|
66
|
-
children: /* @__PURE__ */ jsx(
|
|
67
|
-
CarouselAutoplayIndicatorSVG,
|
|
68
|
-
{
|
|
69
|
-
size,
|
|
70
|
-
strokeWidth,
|
|
71
|
-
barRef,
|
|
72
|
-
radius
|
|
56
|
+
return () => {
|
|
57
|
+
if (animationFrameId.current !== null) {
|
|
58
|
+
cancelAnimationFrame(animationFrameId.current);
|
|
59
|
+
animationFrameId.current = null;
|
|
73
60
|
}
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
|
|
61
|
+
};
|
|
62
|
+
}, [circumference, duration, slideIndex, isPlaying, isPaused]);
|
|
63
|
+
return /* @__PURE__ */ jsx(
|
|
64
|
+
"div",
|
|
65
|
+
{
|
|
66
|
+
ref,
|
|
67
|
+
style: {
|
|
68
|
+
width: size,
|
|
69
|
+
height: size,
|
|
70
|
+
// @ts-ignore
|
|
71
|
+
"--carousel-svg-circumference": circumference
|
|
72
|
+
},
|
|
73
|
+
className: clsx(withBaseName(), className),
|
|
74
|
+
...props,
|
|
75
|
+
children: /* @__PURE__ */ jsx(
|
|
76
|
+
CarouselAutoplayIndicatorSVG,
|
|
77
|
+
{
|
|
78
|
+
size,
|
|
79
|
+
strokeWidth,
|
|
80
|
+
barRef,
|
|
81
|
+
radius
|
|
82
|
+
}
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
);
|
|
78
88
|
|
|
79
89
|
export { CarouselAutoplayIndicator };
|
|
80
90
|
//# sourceMappingURL=CarouselAutoplayIndicator.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CarouselAutoplayIndicator.js","sources":["../src/CarouselAutoplayIndicator.tsx"],"sourcesContent":["import { makePrefixer, useDensity } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport clsx from \"classnames\";\nimport {\n type ComponentPropsWithoutRef,\n forwardRef,\n useEffect,\n useRef,\n} from \"react\";\nimport carouselAutoplayIndicator from \"./CarouselAutoplayIndicator.css\";\nimport { CarouselAutoplayIndicatorSVG } from \"./CarouselAutoplayIndicatorSVG\";\n\nexport interface CarouselAutoplayIndicatorProps\n extends ComponentPropsWithoutRef<\"div\"> {\n /**\n * Duration of each slide in milliseconds.\n */\n duration: number;\n /**\n * Index of slide currently displayed.\n */\n slideIndex: number;\n /**\n * If `true`, the indicator is animated to visualize the time until the next slide.\n */\n isPlaying: boolean;\n}\n\nconst withBaseName = makePrefixer(\"saltCarouselAutoplayIndicator\");\n\nconst sizeAndStrokeWidthMapping = {\n high: { size: 10, strokeWidth: 2 },\n medium: { size: 12, strokeWidth: 2 },\n low: { size: 14, strokeWidth: 2 },\n touch: { size: 16, strokeWidth: 2 },\n};\n\nexport const CarouselAutoplayIndicator = forwardRef<\n HTMLDivElement,\n CarouselAutoplayIndicatorProps\n>(({
|
|
1
|
+
{"version":3,"file":"CarouselAutoplayIndicator.js","sources":["../src/CarouselAutoplayIndicator.tsx"],"sourcesContent":["import { makePrefixer, useDensity } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport clsx from \"classnames\";\nimport {\n type ComponentPropsWithoutRef,\n forwardRef,\n useEffect,\n useRef,\n} from \"react\";\nimport carouselAutoplayIndicator from \"./CarouselAutoplayIndicator.css\";\nimport { CarouselAutoplayIndicatorSVG } from \"./CarouselAutoplayIndicatorSVG\";\n\nexport interface CarouselAutoplayIndicatorProps\n extends ComponentPropsWithoutRef<\"div\"> {\n /**\n * Duration of each slide in milliseconds.\n */\n duration: number;\n /**\n * Index of slide currently displayed.\n */\n slideIndex: number;\n /**\n * If `true`, the indicator is animated to visualize the time until the next slide.\n */\n isPlaying: boolean;\n /**\n * If `true`, the animation is paused.\n */\n isPaused?: boolean;\n}\n\nconst withBaseName = makePrefixer(\"saltCarouselAutoplayIndicator\");\n\nconst sizeAndStrokeWidthMapping = {\n high: { size: 10, strokeWidth: 2 },\n medium: { size: 12, strokeWidth: 2 },\n low: { size: 14, strokeWidth: 2 },\n touch: { size: 16, strokeWidth: 2 },\n};\n\nexport const CarouselAutoplayIndicator = forwardRef<\n HTMLDivElement,\n CarouselAutoplayIndicatorProps\n>(\n (\n {\n className,\n duration,\n slideIndex,\n isPlaying,\n isPaused = false,\n children,\n ...props\n },\n ref,\n ) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-carousel-autoplay-indicator\",\n css: carouselAutoplayIndicator,\n window: targetWindow,\n });\n\n const barRef = useRef<SVGCircleElement>(null);\n const animationFrameId = useRef<number | null>(null);\n\n const density = useDensity();\n const { size, strokeWidth } = sizeAndStrokeWidthMapping[density];\n const radius = (size - strokeWidth) / 2;\n const circumference = 2 * Math.PI * radius;\n\n useEffect(() => {\n if (barRef.current) {\n animationFrameId.current = requestAnimationFrame(() => {\n if (!barRef.current) {\n return;\n }\n barRef.current.style.animation = \"none\"; // Reset animation\n barRef.current.style.strokeDashoffset = `${circumference}`;\n animationFrameId.current = requestAnimationFrame(() => {\n if (!barRef.current) {\n return;\n }\n barRef.current.style.animation = `indicatorAnimation ${duration}ms linear`;\n barRef.current.style.animationPlayState = isPaused\n ? \"paused\"\n : isPlaying\n ? \"running\"\n : \"paused\";\n });\n });\n }\n\n return () => {\n if (animationFrameId.current !== null) {\n cancelAnimationFrame(animationFrameId.current);\n animationFrameId.current = null;\n }\n };\n }, [circumference, duration, slideIndex, isPlaying, isPaused]);\n\n return (\n <div\n ref={ref}\n style={{\n width: size,\n height: size,\n // @ts-ignore\n \"--carousel-svg-circumference\": circumference,\n }}\n className={clsx(withBaseName(), className)}\n {...props}\n >\n <CarouselAutoplayIndicatorSVG\n size={size}\n strokeWidth={strokeWidth}\n barRef={barRef}\n radius={radius}\n />\n </div>\n );\n },\n);\n"],"names":["carouselAutoplayIndicator"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CarouselAutoplayIndicatorSVG.js","sources":["../src/CarouselAutoplayIndicatorSVG.tsx"],"sourcesContent":["import { makePrefixer } from \"@salt-ds/core\";\nimport clsx from \"classnames\";\nimport { type SVGAttributes, forwardRef } from \"react\";\nconst withBaseName = makePrefixer(\"saltCarouselAutoplayIndicatorSVG\");\n\nexport interface CarouselAutoplayIndicatorSVGProps\n extends SVGAttributes<SVGSVGElement> {\n /**\n * Class name to apply to the SVG element.\n */\n className?: string;\n /**\n * Ref to attach to progress indicator element\n */\n barRef:
|
|
1
|
+
{"version":3,"file":"CarouselAutoplayIndicatorSVG.js","sources":["../src/CarouselAutoplayIndicatorSVG.tsx"],"sourcesContent":["import { makePrefixer } from \"@salt-ds/core\";\nimport clsx from \"classnames\";\nimport { type Ref, type SVGAttributes, forwardRef } from \"react\";\n\nconst withBaseName = makePrefixer(\"saltCarouselAutoplayIndicatorSVG\");\n\nexport interface CarouselAutoplayIndicatorSVGProps\n extends SVGAttributes<SVGSVGElement> {\n /**\n * Class name to apply to the SVG element.\n */\n className?: string;\n /**\n * Ref to attach to progress indicator element\n */\n barRef: Ref<SVGCircleElement>;\n /**\n * Size of the SVG in pixels.\n */\n size: number;\n /**\n * Stroke width of the progress indicator in pixels.\n */\n strokeWidth: number;\n /**\n * Radius of the progress indicator circle.\n */\n radius: number;\n}\n\nexport const CarouselAutoplayIndicatorSVG = forwardRef<\n SVGSVGElement,\n CarouselAutoplayIndicatorSVGProps\n>(\n (\n {\n barRef,\n className,\n radius,\n size,\n strokeWidth,\n }: CarouselAutoplayIndicatorSVGProps,\n ref,\n ) => {\n return (\n <svg\n className={clsx(withBaseName(), className)}\n width={size}\n height={size}\n aria-hidden\n ref={ref}\n >\n <circle\n className={withBaseName(\"track\")}\n cx={size / 2}\n cy={size / 2}\n r={radius}\n strokeWidth={strokeWidth}\n />\n <circle\n ref={barRef}\n className={withBaseName(\"bar\")}\n cx={size / 2}\n cy={size / 2}\n r={radius}\n strokeWidth={strokeWidth}\n />\n </svg>\n );\n },\n);\n"],"names":[],"mappings":";;;;;AAIA,MAAM,YAAA,GAAe,aAAa,kCAAkC,CAAA;AA0B7D,MAAM,4BAA+B,GAAA,UAAA;AAAA,EAI1C,CACE;AAAA,IACE,MAAA;AAAA,IACA,SAAA;AAAA,IACA,MAAA;AAAA,IACA,IAAA;AAAA,IACA;AAAA,KAEF,GACG,KAAA;AACH,IACE,uBAAA,IAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,SAAW,EAAA,IAAA,CAAK,YAAa,EAAA,EAAG,SAAS,CAAA;AAAA,QACzC,KAAO,EAAA,IAAA;AAAA,QACP,MAAQ,EAAA,IAAA;AAAA,QACR,aAAW,EAAA,IAAA;AAAA,QACX,GAAA;AAAA,QAEA,QAAA,EAAA;AAAA,0BAAA,GAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cACC,SAAA,EAAW,aAAa,OAAO,CAAA;AAAA,cAC/B,IAAI,IAAO,GAAA,CAAA;AAAA,cACX,IAAI,IAAO,GAAA,CAAA;AAAA,cACX,CAAG,EAAA,MAAA;AAAA,cACH;AAAA;AAAA,WACF;AAAA,0BACA,GAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cACC,GAAK,EAAA,MAAA;AAAA,cACL,SAAA,EAAW,aAAa,KAAK,CAAA;AAAA,cAC7B,IAAI,IAAO,GAAA,CAAA;AAAA,cACX,IAAI,IAAO,GAAA,CAAA;AAAA,cACX,CAAG,EAAA,MAAA;AAAA,cACH;AAAA;AAAA;AACF;AAAA;AAAA,KACF;AAAA;AAGN;;;;"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var css_248z = ".saltCarouselCard {\n display: flex;\n transform: translate3d(0, 0, 0);\n flex: 0 0 var(--
|
|
1
|
+
var css_248z = ".saltCarouselCard {\n display: flex;\n transform: translate3d(0, 0, 0);\n flex: 0 0 var(--carousel-slide-size);\n min-width: 0;\n padding-left: var(--carousel-slide-spacing);\n box-sizing: border-box;\n}\n\n.saltCarouselCard-content {\n display: flex;\n user-select: none;\n overflow: hidden;\n flex-direction: column;\n gap: var(--salt-spacing-200);\n flex-grow: 1;\n}\n\n.saltCarouselCard-body {\n display: flex;\n overflow: hidden;\n flex-direction: column;\n gap: var(--salt-spacing-200);\n flex-grow: 1;\n padding: 0 var(--salt-spacing-200) var(--salt-spacing-200) var(--salt-spacing-200);\n}\n\n.saltCarouselCard-content h2,\n.saltCarouselCard-content h3 {\n margin: 0;\n}\n\n.saltCarouselCard[data-visibility=\"off-screen\"] a {\n visibility: hidden;\n}\n\n.saltCarouselCard-bordered {\n background: var(--salt-container-primary-background);\n border: var(--salt-size-fixed-100) var(--salt-container-borderStyle) var(--salt-container-primary-borderColor);\n border-radius: var(--salt-palette-corner, 0);\n}\n";
|
|
2
2
|
|
|
3
3
|
export { css_248z as default };
|
|
4
4
|
//# sourceMappingURL=CarouselCard.css.js.map
|
package/dist-es/CarouselCard.js
CHANGED
|
@@ -11,7 +11,7 @@ const CarouselCard = forwardRef(
|
|
|
11
11
|
function CarouselCard2({ actions, appearance, children, className, header, media, ...rest }, ref) {
|
|
12
12
|
const targetWindow = useWindow();
|
|
13
13
|
useComponentCssInjection({
|
|
14
|
-
testId: "salt-carousel-
|
|
14
|
+
testId: "salt-carousel-card",
|
|
15
15
|
css: css_248z,
|
|
16
16
|
window: targetWindow
|
|
17
17
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CarouselCard.js","sources":["../src/CarouselCard.tsx"],"sourcesContent":["import { makePrefixer } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport { type ComponentProps, type ReactNode, forwardRef } from \"react\";\nimport saltCarouselCardCss from \"./CarouselCard.css\";\n\nconst withBaseName = makePrefixer(\"saltCarouselCard\");\n\n/**\n * Props for the CarouselCard component.\n */\nexport interface CarouselCardProps extends ComponentProps<\"div\"> {\n /**\n * Actions to be displayed in the content footer.\n * This can include buttons or any other interactive elements.\n */\n actions?: ReactNode;\n\n /**\n * Media content to be displayed inside the slide.\n * This could include images, videos, etc., that are visually prominent.\n * It differs from children in that media is intended to be the main visual element of the slide.\n */\n media?: ReactNode;\n\n /**\n * The appearance of the slide. Options are 'bordered', and 'transparent'.\n * 'transparent' is the default value.\n **/\n appearance?: \"bordered\" | \"transparent\";\n\n /**\n * Header content to be displayed at the top of the slide.\n * This can be text or any other React node.\n */\n header?: ReactNode;\n\n /**\n * Carousel slide id.\n * This can be used to uniquely identify the slide.\n */\n id?: string;\n}\n\nexport const CarouselCard = forwardRef<HTMLDivElement, CarouselCardProps>(\n function CarouselCard(\n { actions, appearance, children, className, header, media, ...rest },\n ref,\n ) {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-carousel-
|
|
1
|
+
{"version":3,"file":"CarouselCard.js","sources":["../src/CarouselCard.tsx"],"sourcesContent":["import { makePrefixer } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport { type ComponentProps, type ReactNode, forwardRef } from \"react\";\nimport saltCarouselCardCss from \"./CarouselCard.css\";\n\nconst withBaseName = makePrefixer(\"saltCarouselCard\");\n\n/**\n * Props for the CarouselCard component.\n */\nexport interface CarouselCardProps extends ComponentProps<\"div\"> {\n /**\n * Actions to be displayed in the content footer.\n * This can include buttons or any other interactive elements.\n */\n actions?: ReactNode;\n\n /**\n * Media content to be displayed inside the slide.\n * This could include images, videos, etc., that are visually prominent.\n * It differs from children in that media is intended to be the main visual element of the slide.\n */\n media?: ReactNode;\n\n /**\n * The appearance of the slide. Options are 'bordered', and 'transparent'.\n * 'transparent' is the default value.\n **/\n appearance?: \"bordered\" | \"transparent\";\n\n /**\n * Header content to be displayed at the top of the slide.\n * This can be text or any other React node.\n */\n header?: ReactNode;\n\n /**\n * Carousel slide id.\n * This can be used to uniquely identify the slide.\n */\n id?: string;\n}\n\nexport const CarouselCard = forwardRef<HTMLDivElement, CarouselCardProps>(\n function CarouselCard(\n { actions, appearance, children, className, header, media, ...rest },\n ref,\n ) {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-carousel-card\",\n css: saltCarouselCardCss,\n window: targetWindow,\n });\n\n return (\n <div\n role=\"tabpanel\"\n aria-roledescription=\"slide\"\n className={clsx(withBaseName(), className)}\n {...rest}\n ref={ref}\n >\n <div\n className={clsx(withBaseName(\"content\"), {\n [withBaseName(\"bordered\")]: appearance === \"bordered\",\n })}\n >\n {media}\n {children && (\n <div className={withBaseName(\"body\")}>\n <div>{header}</div>\n <div>{children}</div>\n {actions}\n </div>\n )}\n </div>\n </div>\n );\n },\n);\n"],"names":["CarouselCard","saltCarouselCardCss"],"mappings":";;;;;;;;AAOA,MAAM,YAAA,GAAe,aAAa,kBAAkB,CAAA;AAsC7C,MAAM,YAAe,GAAA,UAAA;AAAA,EAC1B,SAASA,aAAAA,CACP,EAAE,OAAA,EAAS,UAAY,EAAA,QAAA,EAAU,SAAW,EAAA,MAAA,EAAQ,KAAO,EAAA,GAAG,IAAK,EAAA,EACnE,GACA,EAAA;AACA,IAAA,MAAM,eAAe,SAAU,EAAA;AAC/B,IAAyB,wBAAA,CAAA;AAAA,MACvB,MAAQ,EAAA,oBAAA;AAAA,MACR,GAAK,EAAAC,QAAA;AAAA,MACL,MAAQ,EAAA;AAAA,KACT,CAAA;AAED,IACE,uBAAA,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,IAAK,EAAA,UAAA;AAAA,QACL,sBAAqB,EAAA,OAAA;AAAA,QACrB,SAAW,EAAA,IAAA,CAAK,YAAa,EAAA,EAAG,SAAS,CAAA;AAAA,QACxC,GAAG,IAAA;AAAA,QACJ,GAAA;AAAA,QAEA,QAAA,kBAAA,IAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,SAAW,EAAA,IAAA,CAAK,YAAa,CAAA,SAAS,CAAG,EAAA;AAAA,cACvC,CAAC,YAAA,CAAa,UAAU,CAAC,GAAG,UAAe,KAAA;AAAA,aAC5C,CAAA;AAAA,YAEA,QAAA,EAAA;AAAA,cAAA,KAAA;AAAA,cACA,4BACE,IAAA,CAAA,KAAA,EAAA,EAAI,SAAW,EAAA,YAAA,CAAa,MAAM,CACjC,EAAA,QAAA,EAAA;AAAA,gCAAA,GAAA,CAAC,SAAK,QAAO,EAAA,MAAA,EAAA,CAAA;AAAA,gCACb,GAAA,CAAC,SAAK,QAAS,EAAA,CAAA;AAAA,gBACd;AAAA,eACH,EAAA;AAAA;AAAA;AAAA;AAEJ;AAAA,KACF;AAAA;AAGN;;;;"}
|
|
@@ -1,18 +1,15 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
2
|
import { useIcon, Button } from '@salt-ds/core';
|
|
3
|
-
import { forwardRef
|
|
3
|
+
import { forwardRef } from 'react';
|
|
4
4
|
import { usePrevNextButtons } from './usePrevNextButtons.js';
|
|
5
5
|
|
|
6
6
|
const CarouselNextButton = forwardRef(function CarouselNextButton2({ className, onClick, ...rest }, ref) {
|
|
7
7
|
const { NextIcon } = useIcon();
|
|
8
8
|
const { nextBtnDisabled, onNextButtonClick } = usePrevNextButtons();
|
|
9
|
-
const handleClick =
|
|
10
|
-
(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
},
|
|
14
|
-
[onNextButtonClick, onClick]
|
|
15
|
-
);
|
|
9
|
+
const handleClick = (event) => {
|
|
10
|
+
onNextButtonClick();
|
|
11
|
+
onClick == null ? void 0 : onClick(event);
|
|
12
|
+
};
|
|
16
13
|
return /* @__PURE__ */ jsx(
|
|
17
14
|
Button,
|
|
18
15
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CarouselNextButton.js","sources":["../src/CarouselNextButton.tsx"],"sourcesContent":["import { Button, type ButtonProps, useIcon } from \"@salt-ds/core\";\nimport { type MouseEventHandler, forwardRef
|
|
1
|
+
{"version":3,"file":"CarouselNextButton.js","sources":["../src/CarouselNextButton.tsx"],"sourcesContent":["import { Button, type ButtonProps, useIcon } from \"@salt-ds/core\";\nimport { type MouseEventHandler, forwardRef } from \"react\";\nimport { usePrevNextButtons } from \"./usePrevNextButtons\";\n\n/**\n * Props for the CarouselNextButton component.\n */\nexport interface CarouselNextButtonProps\n extends Omit<ButtonProps, \"variant\" | \"loading\" | \"loadingAnnouncement\"> {}\n\nexport const CarouselNextButton = forwardRef<\n HTMLButtonElement,\n CarouselNextButtonProps\n>(function CarouselNextButton({ className, onClick, ...rest }, ref) {\n const { NextIcon } = useIcon();\n const { nextBtnDisabled, onNextButtonClick } = usePrevNextButtons();\n\n const handleClick: MouseEventHandler<HTMLButtonElement> = (event) => {\n onNextButtonClick();\n onClick?.(event);\n };\n\n return (\n <Button\n onClick={handleClick}\n disabled={nextBtnDisabled}\n focusableWhenDisabled\n appearance=\"bordered\"\n sentiment=\"neutral\"\n aria-label=\"Next slide\"\n ref={ref}\n {...rest}\n >\n <NextIcon aria-hidden />\n </Button>\n );\n});\n"],"names":["CarouselNextButton"],"mappings":";;;;;AAUa,MAAA,kBAAA,GAAqB,UAGhC,CAAA,SAASA,mBAAmB,CAAA,EAAE,WAAW,OAAS,EAAA,GAAG,IAAK,EAAA,EAAG,GAAK,EAAA;AAClE,EAAM,MAAA,EAAE,QAAS,EAAA,GAAI,OAAQ,EAAA;AAC7B,EAAA,MAAM,EAAE,eAAA,EAAiB,iBAAkB,EAAA,GAAI,kBAAmB,EAAA;AAElE,EAAM,MAAA,WAAA,GAAoD,CAAC,KAAU,KAAA;AACnE,IAAkB,iBAAA,EAAA;AAClB,IAAU,OAAA,IAAA,IAAA,GAAA,MAAA,GAAA,OAAA,CAAA,KAAA,CAAA;AAAA,GACZ;AAEA,EACE,uBAAA,GAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,OAAS,EAAA,WAAA;AAAA,MACT,QAAU,EAAA,eAAA;AAAA,MACV,qBAAqB,EAAA,IAAA;AAAA,MACrB,UAAW,EAAA,UAAA;AAAA,MACX,SAAU,EAAA,SAAA;AAAA,MACV,YAAW,EAAA,YAAA;AAAA,MACX,GAAA;AAAA,MACC,GAAG,IAAA;AAAA,MAEJ,QAAA,kBAAA,GAAA,CAAC,QAAS,EAAA,EAAA,aAAA,EAAW,IAAC,EAAA;AAAA;AAAA,GACxB;AAEJ,CAAC;;;;"}
|
|
@@ -1,18 +1,15 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
2
|
import { useIcon, Button } from '@salt-ds/core';
|
|
3
|
-
import { forwardRef
|
|
3
|
+
import { forwardRef } from 'react';
|
|
4
4
|
import { usePrevNextButtons } from './usePrevNextButtons.js';
|
|
5
5
|
|
|
6
6
|
const CarouselPreviousButton = forwardRef(function CarouselPreviousButton2({ className, onClick, ...rest }, ref) {
|
|
7
7
|
const { PreviousIcon } = useIcon();
|
|
8
8
|
const { prevBtnDisabled, onPrevButtonClick } = usePrevNextButtons();
|
|
9
|
-
const handleClick =
|
|
10
|
-
(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
},
|
|
14
|
-
[onPrevButtonClick, onClick]
|
|
15
|
-
);
|
|
9
|
+
const handleClick = (event) => {
|
|
10
|
+
onPrevButtonClick();
|
|
11
|
+
onClick == null ? void 0 : onClick(event);
|
|
12
|
+
};
|
|
16
13
|
return /* @__PURE__ */ jsx(
|
|
17
14
|
Button,
|
|
18
15
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CarouselPreviousButton.js","sources":["../src/CarouselPreviousButton.tsx"],"sourcesContent":["import { Button, type ButtonProps, useIcon } from \"@salt-ds/core\";\nimport { type MouseEventHandler, forwardRef
|
|
1
|
+
{"version":3,"file":"CarouselPreviousButton.js","sources":["../src/CarouselPreviousButton.tsx"],"sourcesContent":["import { Button, type ButtonProps, useIcon } from \"@salt-ds/core\";\nimport { type MouseEventHandler, forwardRef } from \"react\";\nimport { usePrevNextButtons } from \"./usePrevNextButtons\";\n\n/**\n * Props for the CarouselPreviousButton component.\n */\nexport interface CarouselPreviousButtonProps\n extends Omit<ButtonProps, \"variant\" | \"loading\" | \"loadingAnnouncement\"> {}\n\nexport const CarouselPreviousButton = forwardRef<\n HTMLButtonElement,\n CarouselPreviousButtonProps\n>(function CarouselPreviousButton({ className, onClick, ...rest }, ref) {\n const { PreviousIcon } = useIcon();\n const { prevBtnDisabled, onPrevButtonClick } = usePrevNextButtons();\n\n const handleClick: MouseEventHandler<HTMLButtonElement> = (event) => {\n onPrevButtonClick();\n onClick?.(event);\n };\n\n return (\n <Button\n onClick={handleClick}\n disabled={prevBtnDisabled}\n focusableWhenDisabled\n appearance=\"bordered\"\n sentiment=\"neutral\"\n aria-label=\"Previous slide\"\n ref={ref}\n {...rest}\n >\n <PreviousIcon aria-hidden />\n </Button>\n );\n});\n"],"names":["CarouselPreviousButton"],"mappings":";;;;;AAUa,MAAA,sBAAA,GAAyB,UAGpC,CAAA,SAASA,uBAAuB,CAAA,EAAE,WAAW,OAAS,EAAA,GAAG,IAAK,EAAA,EAAG,GAAK,EAAA;AACtE,EAAM,MAAA,EAAE,YAAa,EAAA,GAAI,OAAQ,EAAA;AACjC,EAAA,MAAM,EAAE,eAAA,EAAiB,iBAAkB,EAAA,GAAI,kBAAmB,EAAA;AAElE,EAAM,MAAA,WAAA,GAAoD,CAAC,KAAU,KAAA;AACnE,IAAkB,iBAAA,EAAA;AAClB,IAAU,OAAA,IAAA,IAAA,GAAA,MAAA,GAAA,OAAA,CAAA,KAAA,CAAA;AAAA,GACZ;AAEA,EACE,uBAAA,GAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,OAAS,EAAA,WAAA;AAAA,MACT,QAAU,EAAA,eAAA;AAAA,MACV,qBAAqB,EAAA,IAAA;AAAA,MACrB,UAAW,EAAA,UAAA;AAAA,MACX,SAAU,EAAA,SAAA;AAAA,MACV,YAAW,EAAA,gBAAA;AAAA,MACX,GAAA;AAAA,MACC,GAAG,IAAA;AAAA,MAEJ,QAAA,kBAAA,GAAA,CAAC,YAAa,EAAA,EAAA,aAAA,EAAW,IAAC,EAAA;AAAA;AAAA,GAC5B;AAEJ,CAAC;;;;"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var css_248z = ".saltCarouselTabList.saltText {\n font-weight: var(--salt-
|
|
1
|
+
var css_248z = ".saltCarouselTabList.saltText {\n font-weight: var(--salt-text-fontWeight-strong);\n}\n";
|
|
2
2
|
|
|
3
3
|
export { css_248z as default };
|
|
4
4
|
//# sourceMappingURL=CarouselProgressLabel.css.js.map
|
|
@@ -3,7 +3,7 @@ import { makePrefixer, Text } from '@salt-ds/core';
|
|
|
3
3
|
import { useComponentCssInjection } from '@salt-ds/styles';
|
|
4
4
|
import { useWindow } from '@salt-ds/window';
|
|
5
5
|
import { clsx } from 'clsx';
|
|
6
|
-
import { useState,
|
|
6
|
+
import { useState, useEffect } from 'react';
|
|
7
7
|
import { useCarouselContext } from './CarouselContext.js';
|
|
8
8
|
import css_248z from './CarouselProgressLabel.css.js';
|
|
9
9
|
|
|
@@ -23,34 +23,34 @@ function CarouselProgressLabel({
|
|
|
23
23
|
const { emblaApi } = useCarouselContext();
|
|
24
24
|
const [currentSlide, setCurrentSlide] = useState("");
|
|
25
25
|
const [totalSlides, setTotalSlides] = useState(0);
|
|
26
|
-
const handleSettle = useCallback((emblaApi2) => {
|
|
27
|
-
const slideIndexInView = (emblaApi2 == null ? void 0 : emblaApi2.selectedScrollSnap()) ?? 0;
|
|
28
|
-
const numberOfSlides = (emblaApi2 == null ? void 0 : emblaApi2.slideNodes().length) ?? 0;
|
|
29
|
-
const scrollSnaps = (emblaApi2 == null ? void 0 : emblaApi2.scrollSnapList()) ?? [];
|
|
30
|
-
const slidesPerTransition = numberOfSlides ? Math.ceil(numberOfSlides / scrollSnaps.length) : 0;
|
|
31
|
-
const startSlideNumber = Math.min(
|
|
32
|
-
slideIndexInView * slidesPerTransition + 1,
|
|
33
|
-
numberOfSlides - (slidesPerTransition - 1)
|
|
34
|
-
);
|
|
35
|
-
const endSlideNumber = Math.min(
|
|
36
|
-
startSlideNumber + slidesPerTransition - 1,
|
|
37
|
-
numberOfSlides
|
|
38
|
-
);
|
|
39
|
-
if (startSlideNumber === endSlideNumber) {
|
|
40
|
-
setCurrentSlide(startSlideNumber.toString(10));
|
|
41
|
-
} else {
|
|
42
|
-
setCurrentSlide(`${startSlideNumber}-${endSlideNumber}`);
|
|
43
|
-
}
|
|
44
|
-
setTotalSlides(numberOfSlides);
|
|
45
|
-
}, []);
|
|
46
26
|
useEffect(() => {
|
|
27
|
+
const handleSelect = (emblaApi2) => {
|
|
28
|
+
const slideIndexInView = (emblaApi2 == null ? void 0 : emblaApi2.selectedScrollSnap()) ?? 0;
|
|
29
|
+
const numberOfSlides = (emblaApi2 == null ? void 0 : emblaApi2.slideNodes().length) ?? 0;
|
|
30
|
+
const scrollSnaps = (emblaApi2 == null ? void 0 : emblaApi2.scrollSnapList()) ?? [];
|
|
31
|
+
const slidesPerTransition = numberOfSlides ? Math.ceil(numberOfSlides / scrollSnaps.length) : 0;
|
|
32
|
+
const startSlideNumber = Math.min(
|
|
33
|
+
slideIndexInView * slidesPerTransition + 1,
|
|
34
|
+
numberOfSlides - (slidesPerTransition - 1)
|
|
35
|
+
);
|
|
36
|
+
const endSlideNumber = Math.min(
|
|
37
|
+
startSlideNumber + slidesPerTransition - 1,
|
|
38
|
+
numberOfSlides
|
|
39
|
+
);
|
|
40
|
+
if (startSlideNumber === endSlideNumber) {
|
|
41
|
+
setCurrentSlide(startSlideNumber.toString(10));
|
|
42
|
+
} else {
|
|
43
|
+
setCurrentSlide(`${startSlideNumber}-${endSlideNumber}`);
|
|
44
|
+
}
|
|
45
|
+
setTotalSlides(numberOfSlides);
|
|
46
|
+
};
|
|
47
47
|
if (!emblaApi) return;
|
|
48
|
-
emblaApi.on("init",
|
|
49
|
-
|
|
48
|
+
emblaApi.on("init", handleSelect).on("reInit", handleSelect).on("select", handleSelect);
|
|
49
|
+
handleSelect(emblaApi);
|
|
50
50
|
return () => {
|
|
51
|
-
emblaApi.off("init",
|
|
51
|
+
emblaApi.off("init", handleSelect).off("reInit", handleSelect).off("select", handleSelect);
|
|
52
52
|
};
|
|
53
|
-
}, [emblaApi
|
|
53
|
+
}, [emblaApi]);
|
|
54
54
|
return /* @__PURE__ */ jsxs(Text, { className: clsx(withBaseName(), className), ...props, children: [
|
|
55
55
|
"Slide ",
|
|
56
56
|
currentSlide,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CarouselProgressLabel.js","sources":["../src/CarouselProgressLabel.tsx"],"sourcesContent":["import { Text, type TextProps, makePrefixer } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport type { EmblaCarouselType } from \"embla-carousel\";\nimport {
|
|
1
|
+
{"version":3,"file":"CarouselProgressLabel.js","sources":["../src/CarouselProgressLabel.tsx"],"sourcesContent":["import { Text, type TextProps, makePrefixer } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport type { EmblaCarouselType } from \"embla-carousel\";\nimport { useEffect, useState } from \"react\";\nimport { useCarouselContext } from \"./CarouselContext\";\nimport carouselProgressLabelCss from \"./CarouselProgressLabel.css\";\n\n/**\n * Props for the CarouselProgressLabel component.\n */\nexport interface CarouselProgressLabelProps extends TextProps<\"div\"> {}\n\nconst withBaseName = makePrefixer(\"saltCarouselTabList\");\n\nexport function CarouselProgressLabel({\n className,\n styleAs = \"label\",\n children,\n ...props\n}: CarouselProgressLabelProps) {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-carousel-progress-label\",\n css: carouselProgressLabelCss,\n window: targetWindow,\n });\n\n const { emblaApi } = useCarouselContext();\n\n const [currentSlide, setCurrentSlide] = useState(\"\");\n const [totalSlides, setTotalSlides] = useState(0);\n\n useEffect(() => {\n const handleSelect = (emblaApi: EmblaCarouselType) => {\n const slideIndexInView = emblaApi?.selectedScrollSnap() ?? 0;\n const numberOfSlides = emblaApi?.slideNodes().length ?? 0;\n const scrollSnaps = emblaApi?.scrollSnapList() ?? [];\n const slidesPerTransition = numberOfSlides\n ? Math.ceil(numberOfSlides / scrollSnaps.length)\n : 0;\n const startSlideNumber = Math.min(\n slideIndexInView * slidesPerTransition + 1,\n numberOfSlides - (slidesPerTransition - 1),\n );\n const endSlideNumber = Math.min(\n startSlideNumber + slidesPerTransition - 1,\n numberOfSlides,\n );\n\n if (startSlideNumber === endSlideNumber) {\n setCurrentSlide(startSlideNumber.toString(10));\n } else {\n setCurrentSlide(`${startSlideNumber}-${endSlideNumber}`);\n }\n setTotalSlides(numberOfSlides);\n };\n\n if (!emblaApi) return;\n emblaApi\n .on(\"init\", handleSelect)\n .on(\"reInit\", handleSelect)\n .on(\"select\", handleSelect);\n handleSelect(emblaApi);\n // Cleanup listener on component unmount\n return () => {\n emblaApi\n .off(\"init\", handleSelect)\n .off(\"reInit\", handleSelect)\n .off(\"select\", handleSelect);\n };\n }, [emblaApi]);\n\n return (\n <Text className={clsx(withBaseName(), className)} {...props}>\n Slide {currentSlide} of {totalSlides}\n </Text>\n );\n}\n"],"names":["carouselProgressLabelCss","emblaApi"],"mappings":";;;;;;;;;AAcA,MAAM,YAAA,GAAe,aAAa,qBAAqB,CAAA;AAEhD,SAAS,qBAAsB,CAAA;AAAA,EACpC,SAAA;AAAA,EACA,OAAU,GAAA,OAAA;AAAA,EACV,QAAA;AAAA,EACA,GAAG;AACL,CAA+B,EAAA;AAC7B,EAAA,MAAM,eAAe,SAAU,EAAA;AAC/B,EAAyB,wBAAA,CAAA;AAAA,IACvB,MAAQ,EAAA,8BAAA;AAAA,IACR,GAAK,EAAAA,QAAA;AAAA,IACL,MAAQ,EAAA;AAAA,GACT,CAAA;AAED,EAAM,MAAA,EAAE,QAAS,EAAA,GAAI,kBAAmB,EAAA;AAExC,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAI,SAAS,EAAE,CAAA;AACnD,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAI,SAAS,CAAC,CAAA;AAEhD,EAAA,SAAA,CAAU,MAAM;AACd,IAAM,MAAA,YAAA,GAAe,CAACC,SAAgC,KAAA;AACpD,MAAA,MAAM,gBAAmBA,GAAAA,CAAAA,SAAAA,IAAA,IAAAA,GAAAA,MAAAA,GAAAA,SAAAA,CAAU,kBAAwB,EAAA,KAAA,CAAA;AAC3D,MAAA,MAAM,cAAiBA,GAAAA,CAAAA,SAAAA,IAAA,IAAAA,GAAAA,MAAAA,GAAAA,SAAAA,CAAU,aAAa,MAAU,KAAA,CAAA;AACxD,MAAA,MAAM,WAAcA,GAAAA,CAAAA,SAAAA,IAAA,IAAAA,GAAAA,MAAAA,GAAAA,SAAAA,CAAU,qBAAoB,EAAC;AACnD,MAAA,MAAM,sBAAsB,cACxB,GAAA,IAAA,CAAK,KAAK,cAAiB,GAAA,WAAA,CAAY,MAAM,CAC7C,GAAA,CAAA;AACJ,MAAA,MAAM,mBAAmB,IAAK,CAAA,GAAA;AAAA,QAC5B,mBAAmB,mBAAsB,GAAA,CAAA;AAAA,QACzC,kBAAkB,mBAAsB,GAAA,CAAA;AAAA,OAC1C;AACA,MAAA,MAAM,iBAAiB,IAAK,CAAA,GAAA;AAAA,QAC1B,mBAAmB,mBAAsB,GAAA,CAAA;AAAA,QACzC;AAAA,OACF;AAEA,MAAA,IAAI,qBAAqB,cAAgB,EAAA;AACvC,QAAgB,eAAA,CAAA,gBAAA,CAAiB,QAAS,CAAA,EAAE,CAAC,CAAA;AAAA,OACxC,MAAA;AACL,QAAA,eAAA,CAAgB,CAAG,EAAA,gBAAgB,CAAI,CAAA,EAAA,cAAc,CAAE,CAAA,CAAA;AAAA;AAEzD,MAAA,cAAA,CAAe,cAAc,CAAA;AAAA,KAC/B;AAEA,IAAA,IAAI,CAAC,QAAU,EAAA;AACf,IACG,QAAA,CAAA,EAAA,CAAG,MAAQ,EAAA,YAAY,CACvB,CAAA,EAAA,CAAG,UAAU,YAAY,CAAA,CACzB,EAAG,CAAA,QAAA,EAAU,YAAY,CAAA;AAC5B,IAAA,YAAA,CAAa,QAAQ,CAAA;AAErB,IAAA,OAAO,MAAM;AACX,MACG,QAAA,CAAA,GAAA,CAAI,MAAQ,EAAA,YAAY,CACxB,CAAA,GAAA,CAAI,UAAU,YAAY,CAAA,CAC1B,GAAI,CAAA,QAAA,EAAU,YAAY,CAAA;AAAA,KAC/B;AAAA,GACF,EAAG,CAAC,QAAQ,CAAC,CAAA;AAEb,EACE,uBAAA,IAAA,CAAC,QAAK,SAAW,EAAA,IAAA,CAAK,cAAgB,EAAA,SAAS,CAAI,EAAA,GAAG,KAAO,EAAA,QAAA,EAAA;AAAA,IAAA,QAAA;AAAA,IACpD,YAAA;AAAA,IAAa,MAAA;AAAA,IAAK;AAAA,GAC3B,EAAA,CAAA;AAEJ;;;;"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var css_248z = ".saltCarouselSlides {\n overflow: hidden;\n}\n.saltCarouselSlides-container {\n display: flex;\n touch-action: pan-y pinch-zoom;\n margin-left: calc(var(--
|
|
1
|
+
var css_248z = ".saltCarouselSlides {\n overflow: hidden;\n}\n.saltCarouselSlides-container {\n display: flex;\n touch-action: pan-y pinch-zoom;\n margin-left: calc(var(--carousel-slide-spacing) * -1);\n}\n";
|
|
2
2
|
|
|
3
3
|
export { css_248z as default };
|
|
4
4
|
//# sourceMappingURL=CarouselSlides.css.js.map
|
|
@@ -3,13 +3,14 @@ import { makePrefixer, useForkRef } from '@salt-ds/core';
|
|
|
3
3
|
import { useComponentCssInjection } from '@salt-ds/styles';
|
|
4
4
|
import { useWindow } from '@salt-ds/window';
|
|
5
5
|
import { clsx } from 'clsx';
|
|
6
|
-
import { forwardRef } from 'react';
|
|
6
|
+
import { forwardRef, useRef, useEffect } from 'react';
|
|
7
7
|
import { useCarouselContext } from './CarouselContext.js';
|
|
8
8
|
import css_248z from './CarouselSlides.css.js';
|
|
9
|
+
import { createCustomSettle } from './createCustomSettle.js';
|
|
9
10
|
|
|
10
11
|
const withBaseName = makePrefixer("saltCarouselSlides");
|
|
11
12
|
const CarouselSlides = forwardRef(
|
|
12
|
-
function CarouselSlides2({ children, className, onKeyDown, ...rest },
|
|
13
|
+
function CarouselSlides2({ children, className, onKeyDown, ...rest }, ref) {
|
|
13
14
|
const targetWindow = useWindow();
|
|
14
15
|
useComponentCssInjection({
|
|
15
16
|
testId: "salt-carousel-slides",
|
|
@@ -17,7 +18,34 @@ const CarouselSlides = forwardRef(
|
|
|
17
18
|
window: targetWindow
|
|
18
19
|
});
|
|
19
20
|
const { emblaApi, emblaRef } = useCarouselContext();
|
|
20
|
-
const
|
|
21
|
+
const carouselRef = useForkRef(ref, emblaRef);
|
|
22
|
+
const usingArrowNavigation = useRef();
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
const handleSettle = (emblaApi2) => {
|
|
25
|
+
if (!usingArrowNavigation.current) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const slideIndexInView = (emblaApi2 == null ? void 0 : emblaApi2.selectedScrollSnap()) ?? 0;
|
|
29
|
+
const snappedSlide = emblaApi2.slideNodes()[slideIndexInView];
|
|
30
|
+
if (snappedSlide) {
|
|
31
|
+
const focusableElements = snappedSlide.querySelectorAll(
|
|
32
|
+
'a, button, input, textarea, select, [tabindex]:not([tabindex="-1"])'
|
|
33
|
+
);
|
|
34
|
+
if (focusableElements.length > 0) {
|
|
35
|
+
focusableElements[0].focus();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
usingArrowNavigation.current = false;
|
|
39
|
+
};
|
|
40
|
+
if (!emblaApi) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const scrollCallback = createCustomSettle(handleSettle);
|
|
44
|
+
emblaApi.on("scroll", scrollCallback);
|
|
45
|
+
return () => {
|
|
46
|
+
emblaApi.off("scroll", scrollCallback);
|
|
47
|
+
};
|
|
48
|
+
}, [emblaApi]);
|
|
21
49
|
const handleKeyDown = (event) => {
|
|
22
50
|
if (event.repeat) {
|
|
23
51
|
return;
|
|
@@ -26,11 +54,13 @@ const CarouselSlides = forwardRef(
|
|
|
26
54
|
case "ArrowLeft": {
|
|
27
55
|
event.preventDefault();
|
|
28
56
|
emblaApi == null ? void 0 : emblaApi.scrollPrev();
|
|
57
|
+
usingArrowNavigation.current = true;
|
|
29
58
|
break;
|
|
30
59
|
}
|
|
31
60
|
case "ArrowRight": {
|
|
32
61
|
event.preventDefault();
|
|
33
62
|
emblaApi == null ? void 0 : emblaApi.scrollNext();
|
|
63
|
+
usingArrowNavigation.current = true;
|
|
34
64
|
break;
|
|
35
65
|
}
|
|
36
66
|
}
|
|
@@ -40,7 +70,7 @@ const CarouselSlides = forwardRef(
|
|
|
40
70
|
"div",
|
|
41
71
|
{
|
|
42
72
|
onKeyDown: handleKeyDown,
|
|
43
|
-
ref,
|
|
73
|
+
ref: carouselRef,
|
|
44
74
|
className: clsx(withBaseName(), className),
|
|
45
75
|
...rest,
|
|
46
76
|
children: /* @__PURE__ */ jsx("div", { className: withBaseName("container"), children })
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CarouselSlides.js","sources":["../src/CarouselSlides.tsx"],"sourcesContent":["import { makePrefixer, useForkRef } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport {\n type ComponentPropsWithoutRef,\n type KeyboardEvent,\n
|
|
1
|
+
{"version":3,"file":"CarouselSlides.js","sources":["../src/CarouselSlides.tsx"],"sourcesContent":["import { makePrefixer, useForkRef } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport type { EmblaCarouselType } from \"embla-carousel\";\nimport {\n type ComponentPropsWithoutRef,\n type KeyboardEvent,\n forwardRef,\n useEffect,\n useRef,\n} from \"react\";\nimport { useCarouselContext } from \"./CarouselContext\";\nimport carouselSlidesCss from \"./CarouselSlides.css\";\nimport { createCustomSettle } from \"./createCustomSettle\";\n\n/**\n * Props for the CarouselSlides component.\n */\nexport interface CarouselSlidesProps extends ComponentPropsWithoutRef<\"div\"> {}\n\nconst withBaseName = makePrefixer(\"saltCarouselSlides\");\n\nexport const CarouselSlides = forwardRef<HTMLDivElement, CarouselSlidesProps>(\n function CarouselSlides({ children, className, onKeyDown, ...rest }, ref) {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-carousel-slides\",\n css: carouselSlidesCss,\n window: targetWindow,\n });\n const { emblaApi, emblaRef } = useCarouselContext();\n\n const carouselRef = useForkRef<HTMLDivElement>(ref, emblaRef);\n\n const usingArrowNavigation = useRef<boolean>();\n\n useEffect(() => {\n const handleSettle = (emblaApi: EmblaCarouselType) => {\n if (!usingArrowNavigation.current) {\n return;\n }\n const slideIndexInView = emblaApi?.selectedScrollSnap() ?? 0;\n const snappedSlide = emblaApi.slideNodes()[slideIndexInView];\n if (snappedSlide) {\n const focusableElements = snappedSlide.querySelectorAll<HTMLElement>(\n 'a, button, input, textarea, select, [tabindex]:not([tabindex=\"-1\"])',\n );\n if (focusableElements.length > 0) {\n focusableElements[0].focus();\n }\n }\n usingArrowNavigation.current = false;\n };\n\n if (!emblaApi) {\n return;\n }\n const scrollCallback = createCustomSettle(handleSettle);\n emblaApi.on(\"scroll\", scrollCallback);\n // Cleanup listener on component unmount\n return () => {\n emblaApi.off(\"scroll\", scrollCallback);\n };\n }, [emblaApi]);\n\n const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n if (event.repeat) {\n return;\n }\n switch (event.key) {\n case \"ArrowLeft\": {\n event.preventDefault();\n emblaApi?.scrollPrev();\n usingArrowNavigation.current = true;\n break;\n }\n case \"ArrowRight\": {\n event.preventDefault();\n emblaApi?.scrollNext();\n usingArrowNavigation.current = true;\n break;\n }\n }\n onKeyDown?.(event);\n };\n\n return (\n <div\n onKeyDown={handleKeyDown}\n ref={carouselRef}\n className={clsx(withBaseName(), className)}\n {...rest}\n >\n <div className={withBaseName(\"container\")}>{children}</div>\n </div>\n );\n },\n);\n"],"names":["CarouselSlides","carouselSlidesCss","emblaApi"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var css_248z = ".saltCarouselTab {\n position: relative;\n width: var(--salt-size-selectable);\n height: var(--salt-size-selectable);\n border: none;\n box-shadow: inset 0 0 0 var(--salt-size-
|
|
1
|
+
var css_248z = ".saltCarouselTab {\n position: relative;\n width: var(--salt-size-selectable);\n height: var(--salt-size-selectable);\n border: none;\n box-shadow: inset 0 0 0 var(--salt-size-fixed-100) var(--salt-selectable-borderColor);\n -webkit-tap-highlight-color: var(--salt-selectable-borderColor-hover);\n -webkit-appearance: none;\n appearance: none;\n background-color: transparent;\n touch-action: manipulation;\n display: inline-flex;\n text-decoration: none;\n cursor: pointer;\n padding: 0;\n margin: 0;\n align-items: center;\n justify-content: center;\n border-radius: var(--salt-palette-corner-strongest);\n transition: box-shadow var(--salt-duration-perceptible) ease-in-out;\n}\n\n.saltCarouselTab:after {\n content: \"\";\n position: absolute;\n width: var(--salt-size-selectable);\n height: var(--salt-size-selectable);\n border-radius: 50%;\n background-color: transparent;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n}\n\n.saltCarouselTab:focus-visible {\n outline-style: var(--salt-focused-outlineStyle);\n outline-width: var(--salt-focused-outlineWidth);\n outline-color: var(--salt-focused-outlineColor);\n outline-offset: var(--salt-focused-outlineOffset);\n background: var(--salt-selectable-background-hover);\n border-color: var(--salt-selectable-borderColor-hover);\n}\n\n.saltCarouselTab-selected {\n box-shadow: inset 0 0 0 var(--salt-size-selectable) var(--salt-selectable-borderColor-selected);\n}\n";
|
|
2
2
|
|
|
3
3
|
export { css_248z as default };
|
|
4
4
|
//# sourceMappingURL=CarouselTab.css.js.map
|
package/dist-es/CarouselTab.js
CHANGED
|
@@ -3,27 +3,23 @@ import { makePrefixer } from '@salt-ds/core';
|
|
|
3
3
|
import { useComponentCssInjection } from '@salt-ds/styles';
|
|
4
4
|
import { useWindow } from '@salt-ds/window';
|
|
5
5
|
import { clsx } from 'clsx';
|
|
6
|
-
import { forwardRef, useState,
|
|
6
|
+
import { forwardRef, useState, useEffect } from 'react';
|
|
7
7
|
import css_248z from './CarouselTab.css.js';
|
|
8
8
|
|
|
9
9
|
const withBaseName = makePrefixer("saltCarouselTab");
|
|
10
10
|
const useCarouselTab = (emblaApi) => {
|
|
11
11
|
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
12
12
|
const [scrollSnaps, setScrollSnaps] = useState([]);
|
|
13
|
-
const handleClick =
|
|
14
|
-
(index)
|
|
15
|
-
|
|
16
|
-
emblaApi.scrollTo(index);
|
|
17
|
-
},
|
|
18
|
-
[emblaApi]
|
|
19
|
-
);
|
|
20
|
-
const handleInit = useCallback((emblaApi2) => {
|
|
21
|
-
setScrollSnaps(emblaApi2.scrollSnapList());
|
|
22
|
-
}, []);
|
|
23
|
-
const handleSelect = useCallback((emblaApi2) => {
|
|
24
|
-
setSelectedIndex(emblaApi2.selectedScrollSnap());
|
|
25
|
-
}, []);
|
|
13
|
+
const handleClick = (index) => {
|
|
14
|
+
emblaApi == null ? void 0 : emblaApi.scrollTo(index);
|
|
15
|
+
};
|
|
26
16
|
useEffect(() => {
|
|
17
|
+
const handleInit = (emblaApi2) => {
|
|
18
|
+
setScrollSnaps(emblaApi2.scrollSnapList());
|
|
19
|
+
};
|
|
20
|
+
const handleSelect = (emblaApi2) => {
|
|
21
|
+
setSelectedIndex(emblaApi2.selectedScrollSnap());
|
|
22
|
+
};
|
|
27
23
|
if (!emblaApi) return;
|
|
28
24
|
handleInit(emblaApi);
|
|
29
25
|
handleSelect(emblaApi);
|
|
@@ -31,9 +27,9 @@ const useCarouselTab = (emblaApi) => {
|
|
|
31
27
|
return () => {
|
|
32
28
|
emblaApi.off("init", handleInit);
|
|
33
29
|
emblaApi.off("reInit", handleInit);
|
|
34
|
-
emblaApi.off("
|
|
30
|
+
emblaApi.off("select", handleSelect);
|
|
35
31
|
};
|
|
36
|
-
}, [emblaApi
|
|
32
|
+
}, [emblaApi]);
|
|
37
33
|
return {
|
|
38
34
|
selectedIndex,
|
|
39
35
|
scrollSnaps,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CarouselTab.js","sources":["../src/CarouselTab.tsx"],"sourcesContent":["import { makePrefixer } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport type { EmblaCarouselType } from \"embla-carousel\";\nimport {\n type ComponentPropsWithRef,\n forwardRef,\n
|
|
1
|
+
{"version":3,"file":"CarouselTab.js","sources":["../src/CarouselTab.tsx"],"sourcesContent":["import { makePrefixer } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport type { EmblaCarouselType } from \"embla-carousel\";\nimport {\n type ComponentPropsWithRef,\n forwardRef,\n useEffect,\n useState,\n} from \"react\";\nimport carouselTabCss from \"./CarouselTab.css\";\n\n/**\n * Type definition for the UseCarouselTab hook.\n * Provides state and handlers for tablist navigation in a carousel.\n */\ntype UseCarouselTabProps = {\n /**\n * The index of the currently selected slide.\n */\n selectedIndex: number;\n\n /**\n * An array of scroll snap positions for the carousel slides.\n */\n scrollSnaps: number[];\n\n /**\n * Handler function for clicking a tab button to navigate to a specific slide.\n *\n * @param index - The index of the slide to navigate to.\n */\n onClick: (index: number) => void;\n};\n\nconst withBaseName = makePrefixer(\"saltCarouselTab\");\n\nexport const useCarouselTab = (\n emblaApi: EmblaCarouselType | undefined,\n): UseCarouselTabProps => {\n const [selectedIndex, setSelectedIndex] = useState(0);\n const [scrollSnaps, setScrollSnaps] = useState<number[]>([]);\n\n const handleClick = (index: number) => {\n emblaApi?.scrollTo(index);\n };\n\n useEffect(() => {\n const handleInit = (emblaApi: EmblaCarouselType) => {\n setScrollSnaps(emblaApi.scrollSnapList());\n };\n\n const handleSelect = (emblaApi: EmblaCarouselType) => {\n setSelectedIndex(emblaApi.selectedScrollSnap());\n };\n\n if (!emblaApi) return;\n\n handleInit(emblaApi);\n handleSelect(emblaApi);\n emblaApi\n .on(\"init\", handleInit)\n .on(\"reInit\", handleInit)\n .on(\"select\", handleSelect);\n // Cleanup listener on component unmount\n return () => {\n emblaApi.off(\"init\", handleInit);\n emblaApi.off(\"reInit\", handleInit);\n emblaApi.off(\"select\", handleSelect);\n };\n }, [emblaApi]);\n\n return {\n selectedIndex,\n scrollSnaps,\n onClick: handleClick,\n };\n};\n\n/**\n * Props for the CarouselTab component.\n */\nexport interface CarouselTabProps extends ComponentPropsWithRef<\"button\"> {\n /**\n * Is the selected slide\n */\n selected?: boolean;\n}\n\nexport const CarouselTab = forwardRef<HTMLButtonElement, CarouselTabProps>(\n function CarouselTab(\n { children, className, selected = false, ...rest },\n ref,\n ) {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-carousel-tab\",\n css: carouselTabCss,\n window: targetWindow,\n });\n\n return (\n <button\n className={clsx(\n withBaseName(),\n { [withBaseName(\"selected\")]: selected },\n className,\n )}\n ref={ref}\n {...rest}\n >\n {children}\n </button>\n );\n },\n);\n"],"names":["emblaApi","CarouselTab","carouselTabCss"],"mappings":";;;;;;;;AAoCA,MAAM,YAAA,GAAe,aAAa,iBAAiB,CAAA;AAEtC,MAAA,cAAA,GAAiB,CAC5B,QACwB,KAAA;AACxB,EAAA,MAAM,CAAC,aAAA,EAAe,gBAAgB,CAAA,GAAI,SAAS,CAAC,CAAA;AACpD,EAAA,MAAM,CAAC,WAAa,EAAA,cAAc,CAAI,GAAA,QAAA,CAAmB,EAAE,CAAA;AAE3D,EAAM,MAAA,WAAA,GAAc,CAAC,KAAkB,KAAA;AACrC,IAAA,QAAA,IAAA,IAAA,GAAA,MAAA,GAAA,QAAA,CAAU,QAAS,CAAA,KAAA,CAAA;AAAA,GACrB;AAEA,EAAA,SAAA,CAAU,MAAM;AACd,IAAM,MAAA,UAAA,GAAa,CAACA,SAAgC,KAAA;AAClD,MAAeA,cAAAA,CAAAA,SAAAA,CAAS,gBAAgB,CAAA;AAAA,KAC1C;AAEA,IAAM,MAAA,YAAA,GAAe,CAACA,SAAgC,KAAA;AACpD,MAAiBA,gBAAAA,CAAAA,SAAAA,CAAS,oBAAoB,CAAA;AAAA,KAChD;AAEA,IAAA,IAAI,CAAC,QAAU,EAAA;AAEf,IAAA,UAAA,CAAW,QAAQ,CAAA;AACnB,IAAA,YAAA,CAAa,QAAQ,CAAA;AACrB,IACG,QAAA,CAAA,EAAA,CAAG,MAAQ,EAAA,UAAU,CACrB,CAAA,EAAA,CAAG,UAAU,UAAU,CAAA,CACvB,EAAG,CAAA,QAAA,EAAU,YAAY,CAAA;AAE5B,IAAA,OAAO,MAAM;AACX,MAAS,QAAA,CAAA,GAAA,CAAI,QAAQ,UAAU,CAAA;AAC/B,MAAS,QAAA,CAAA,GAAA,CAAI,UAAU,UAAU,CAAA;AACjC,MAAS,QAAA,CAAA,GAAA,CAAI,UAAU,YAAY,CAAA;AAAA,KACrC;AAAA,GACF,EAAG,CAAC,QAAQ,CAAC,CAAA;AAEb,EAAO,OAAA;AAAA,IACL,aAAA;AAAA,IACA,WAAA;AAAA,IACA,OAAS,EAAA;AAAA,GACX;AACF;AAYO,MAAM,WAAc,GAAA,UAAA;AAAA,EACzB,SAASC,YACP,CAAA,EAAE,QAAU,EAAA,SAAA,EAAW,WAAW,KAAO,EAAA,GAAG,IAAK,EAAA,EACjD,GACA,EAAA;AACA,IAAA,MAAM,eAAe,SAAU,EAAA;AAC/B,IAAyB,wBAAA,CAAA;AAAA,MACvB,MAAQ,EAAA,mBAAA;AAAA,MACR,GAAK,EAAAC,QAAA;AAAA,MACL,MAAQ,EAAA;AAAA,KACT,CAAA;AAED,IACE,uBAAA,GAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,SAAW,EAAA,IAAA;AAAA,UACT,YAAa,EAAA;AAAA,UACb,EAAE,CAAC,YAAA,CAAa,UAAU,CAAC,GAAG,QAAS,EAAA;AAAA,UACvC;AAAA,SACF;AAAA,QACA,GAAA;AAAA,QACC,GAAG,IAAA;AAAA,QAEH;AAAA;AAAA,KACH;AAAA;AAGN;;;;"}
|