@salt-ds/embla-carousel 0.0.0-snapshot-20250627090641

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/CHANGELOG.md +161 -0
  2. package/README.md +3 -0
  3. package/css/salt-embla-carousel.css +155 -0
  4. package/dist-cjs/Carousel.css.js +6 -0
  5. package/dist-cjs/Carousel.css.js.map +1 -0
  6. package/dist-cjs/Carousel.js +53 -0
  7. package/dist-cjs/Carousel.js.map +1 -0
  8. package/dist-cjs/CarouselAnnouncementPlugin.js +55 -0
  9. package/dist-cjs/CarouselAnnouncementPlugin.js.map +1 -0
  10. package/dist-cjs/CarouselAutoplayIndicator.css.js +6 -0
  11. package/dist-cjs/CarouselAutoplayIndicator.css.js.map +1 -0
  12. package/dist-cjs/CarouselAutoplayIndicator.js +82 -0
  13. package/dist-cjs/CarouselAutoplayIndicator.js.map +1 -0
  14. package/dist-cjs/CarouselAutoplayIndicatorSVG.js +54 -0
  15. package/dist-cjs/CarouselAutoplayIndicatorSVG.js.map +1 -0
  16. package/dist-cjs/CarouselCard.css.js +6 -0
  17. package/dist-cjs/CarouselCard.css.js.map +1 -0
  18. package/dist-cjs/CarouselCard.js +50 -0
  19. package/dist-cjs/CarouselCard.js.map +1 -0
  20. package/dist-cjs/CarouselContext.js +22 -0
  21. package/dist-cjs/CarouselContext.js.map +1 -0
  22. package/dist-cjs/CarouselNextButton.js +35 -0
  23. package/dist-cjs/CarouselNextButton.js.map +1 -0
  24. package/dist-cjs/CarouselPreviousButton.js +35 -0
  25. package/dist-cjs/CarouselPreviousButton.js.map +1 -0
  26. package/dist-cjs/CarouselProgressLabel.css.js +6 -0
  27. package/dist-cjs/CarouselProgressLabel.css.js.map +1 -0
  28. package/dist-cjs/CarouselProgressLabel.js +65 -0
  29. package/dist-cjs/CarouselProgressLabel.js.map +1 -0
  30. package/dist-cjs/CarouselSlides.css.js +6 -0
  31. package/dist-cjs/CarouselSlides.css.js.map +1 -0
  32. package/dist-cjs/CarouselSlides.js +55 -0
  33. package/dist-cjs/CarouselSlides.js.map +1 -0
  34. package/dist-cjs/CarouselTab.css.js +6 -0
  35. package/dist-cjs/CarouselTab.css.js.map +1 -0
  36. package/dist-cjs/CarouselTab.js +71 -0
  37. package/dist-cjs/CarouselTab.js.map +1 -0
  38. package/dist-cjs/CarouselTabList.css.js +6 -0
  39. package/dist-cjs/CarouselTabList.css.js.map +1 -0
  40. package/dist-cjs/CarouselTabList.js +94 -0
  41. package/dist-cjs/CarouselTabList.js.map +1 -0
  42. package/dist-cjs/index.js +31 -0
  43. package/dist-cjs/index.js.map +1 -0
  44. package/dist-cjs/usePrevNextButtons.js +41 -0
  45. package/dist-cjs/usePrevNextButtons.js.map +1 -0
  46. package/dist-es/Carousel.css.js +4 -0
  47. package/dist-es/Carousel.css.js.map +1 -0
  48. package/dist-es/Carousel.js +51 -0
  49. package/dist-es/Carousel.js.map +1 -0
  50. package/dist-es/CarouselAnnouncementPlugin.js +52 -0
  51. package/dist-es/CarouselAnnouncementPlugin.js.map +1 -0
  52. package/dist-es/CarouselAutoplayIndicator.css.js +4 -0
  53. package/dist-es/CarouselAutoplayIndicator.css.js.map +1 -0
  54. package/dist-es/CarouselAutoplayIndicator.js +80 -0
  55. package/dist-es/CarouselAutoplayIndicator.js.map +1 -0
  56. package/dist-es/CarouselAutoplayIndicatorSVG.js +52 -0
  57. package/dist-es/CarouselAutoplayIndicatorSVG.js.map +1 -0
  58. package/dist-es/CarouselCard.css.js +4 -0
  59. package/dist-es/CarouselCard.css.js.map +1 -0
  60. package/dist-es/CarouselCard.js +48 -0
  61. package/dist-es/CarouselCard.js.map +1 -0
  62. package/dist-es/CarouselContext.js +19 -0
  63. package/dist-es/CarouselContext.js.map +1 -0
  64. package/dist-es/CarouselNextButton.js +33 -0
  65. package/dist-es/CarouselNextButton.js.map +1 -0
  66. package/dist-es/CarouselPreviousButton.js +33 -0
  67. package/dist-es/CarouselPreviousButton.js.map +1 -0
  68. package/dist-es/CarouselProgressLabel.css.js +4 -0
  69. package/dist-es/CarouselProgressLabel.css.js.map +1 -0
  70. package/dist-es/CarouselProgressLabel.js +63 -0
  71. package/dist-es/CarouselProgressLabel.js.map +1 -0
  72. package/dist-es/CarouselSlides.css.js +4 -0
  73. package/dist-es/CarouselSlides.css.js.map +1 -0
  74. package/dist-es/CarouselSlides.js +53 -0
  75. package/dist-es/CarouselSlides.js.map +1 -0
  76. package/dist-es/CarouselTab.css.js +4 -0
  77. package/dist-es/CarouselTab.css.js.map +1 -0
  78. package/dist-es/CarouselTab.js +68 -0
  79. package/dist-es/CarouselTab.js.map +1 -0
  80. package/dist-es/CarouselTabList.css.js +4 -0
  81. package/dist-es/CarouselTabList.css.js.map +1 -0
  82. package/dist-es/CarouselTabList.js +92 -0
  83. package/dist-es/CarouselTabList.js.map +1 -0
  84. package/dist-es/index.js +12 -0
  85. package/dist-es/index.js.map +1 -0
  86. package/dist-es/usePrevNextButtons.js +39 -0
  87. package/dist-es/usePrevNextButtons.js.map +1 -0
  88. package/dist-types/Carousel.d.ts +27 -0
  89. package/dist-types/CarouselAnnouncementPlugin.d.ts +34 -0
  90. package/dist-types/CarouselAutoplayIndicator.d.ts +16 -0
  91. package/dist-types/CarouselAutoplayIndicatorSVG.d.ts +24 -0
  92. package/dist-types/CarouselCard.d.ts +33 -0
  93. package/dist-types/CarouselContext.d.ts +20 -0
  94. package/dist-types/CarouselNextButton.d.ts +7 -0
  95. package/dist-types/CarouselPreviousButton.d.ts +7 -0
  96. package/dist-types/CarouselProgressLabel.d.ts +7 -0
  97. package/dist-types/CarouselSlides.d.ts +7 -0
  98. package/dist-types/CarouselTab.d.ts +34 -0
  99. package/dist-types/CarouselTabList.d.ts +12 -0
  100. package/dist-types/index.d.ts +11 -0
  101. package/dist-types/usePrevNextButtons.d.ts +20 -0
  102. package/package.json +54 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,161 @@
1
+ # @salt-ds/embla-carousel
2
+
3
+ ## 0.0.0-snapshot-20250627090641
4
+
5
+ ### Patch Changes
6
+
7
+ - e8d4fd7: ### Summary
8
+
9
+ The `Carousel` component has been moved from the Lab package to its own package, `@salt-ds/embla-carousel`.
10
+ Initially released as a pre-release in Lab, the Carousel was not fully featured. We have now pivoted to treating Carousel as a pattern using embla, that can compose Salt components as its slides.
11
+
12
+ [embla](https://www.embla-carousel.com) is a headless open-source carousel library offering a comprehensive set of features and an extensible API.
13
+
14
+ ### Migration Guide
15
+
16
+ To allow consumers to manage their own version of `embla`, it is defined as a peer dependency.
17
+
18
+ To migrate from the current Lab version of `Carousel`:
19
+
20
+ 1. Define `embla-carousel-react` in your package.json.
21
+
22
+ ```diff
23
+ "dependencies": {
24
+ + "embla-carousel-react": "^8.6.0",
25
+ }
26
+ ```
27
+
28
+ 2. update your imports.
29
+
30
+ ```diff
31
+ import {
32
+ Carousel,
33
+ - CarouselControls,
34
+ + CarouselNextButton,
35
+ + CarouselPreviousButton,
36
+ + CarouselProgressLabel,
37
+ - CarouselSlide,
38
+ + CarouselCard,
39
+ - CarouselSlider,
40
+ + CarouselSlides
41
+ -} from "@salt-ds/lab";
42
+ +} from "@salt-ds/embla-carousel";
43
+ ```
44
+
45
+ ### Key Changes
46
+
47
+ - `CarouselControls` has been broken into `CarouselPreviousButton`, `CarouselNextButton`, and `CarouselProgressLabel` for composability.
48
+ - `CarouselSlide` has been renamed to `CarouselCard`. While `CarouselCard` is a predefined slide, you can also create custom slides.
49
+ - `CarouselSlider` has been renamed to `CarouselSlides`.
50
+
51
+ Example Update:
52
+
53
+ ```diff
54
+ const slideId = useId();
55
+
56
+ - <Carousel controlsPlacement="bottom">
57
+ + <Carousel>
58
+ - <CarouselControls />
59
+ + <CarouselPreviousButton />
60
+ + <CarouselNextButton />
61
+ + <CarouselProgressLabel />
62
+ - <CarouselSlider>
63
+ + <CarouselSlides>
64
+ {
65
+ slides.map((slide, index) => (
66
+ - <CarouselSlide
67
+ + <CarouselCard
68
+ key={`${slideId}-${index}`}
69
+ + id={`${slideId}-${index}`}
70
+ appearance={appearance}
71
+ header={<H3>{slide.title}</H3>}
72
+ media={
73
+ <img
74
+ className="carousel-image-placeholder"
75
+ alt="stock content to show carousel slide"
76
+ src={slide.image}
77
+ />}
78
+ actions={withActions && <Link href="#">{slide.link}</Link>}
79
+ >
80
+ <Text>{slide.content}</Text>
81
+ </CarouselCard>
82
+ ))
83
+ }
84
+ - </CarouselSlider>
85
+ + </CarouselSlides>
86
+ </Carousel>
87
+ ```
88
+
89
+ ### Additional Configuration/Control of Carousel
90
+
91
+ The Carousel can be configured using the Embla API.
92
+
93
+ To configure embla, pass `emblaOptions` or `emblaPlugins` to the Carousel.
94
+
95
+ To control the behavior of the Carousel through the embla API, obtain a reference to the embla API through the `setApiRef` prop.
96
+
97
+ ```
98
+ const [emblaApi, setEmblaApi] = useState<CarouselEmblaApiType | null>(null);
99
+
100
+ const slideId = useId();
101
+ const { matchedBreakpoints } = useBreakpoint();
102
+ const isMobile = matchedBreakpoints.indexOf("sm") === -1;
103
+
104
+ useEffect(() => {
105
+ if (!emblaApi) {
106
+ return;
107
+ }
108
+
109
+ const logSnappedSlide = () => {
110
+ const snappedSlideIndex = emblaApi.selectedScrollSnap();
111
+ console.log(
112
+ `Slide ${snappedSlideIndex !== undefined ? snappedSlideIndex + 1 : undefined} is snapped into view.`,
113
+ );
114
+ };
115
+
116
+ emblaApi.on("select", logSnappedSlide);
117
+
118
+ // Cleanup listener on component unmount
119
+ return () => {
120
+ emblaApi.off("select", logSnappedSlide);
121
+ };
122
+ }, [emblaApi]);
123
+
124
+ return (
125
+ <Carousel
126
+ aria-label="Account overview"
127
+ getEmblaApi={setEmblaApi}
128
+ >
129
+ <CarouselSlides>
130
+ {slides.map((index) => (
131
+ <div
132
+ aria-label={`Example slide ${index + 1}`}
133
+ aria-roledescription="slide"
134
+ key={`${slideId}-${slide.title.replace(/ /g, "-")}-${index}`}
135
+ id={`${slideId}-${slide.title.replace(/ /g, "-")}-${index}`}
136
+ >
137
+ {index + 1}
138
+ </div>
139
+ ))}
140
+ </CarouselSlides>
141
+ </Carousel>
142
+ );
143
+ ```
144
+
145
+ Due to the challenges of making an accessible carousel, please read the documentation to understand the responsibilities that come with usage.
146
+
147
+ `Carousel` remains in a pre-release state for this release and subject to feedback will be promoted to stable in a forthcoming release.
148
+
149
+ ### Additional components
150
+
151
+ - `CarouselTabList`: A tablist for navigating between slides.
152
+ - `CarouselTab`: A tab button used by `CarouselTabList`.
153
+ - `CarouselAutoplayIndicator`: An animated countdown indicator for autoplay functionality.
154
+ - `CarouselAnnouncementPlugin`: A plugin for announcing slide changes to assistive technologies.
155
+
156
+ - Updated dependencies [62975de]
157
+ - Updated dependencies [73ccf6b]
158
+ - Updated dependencies [95dd874]
159
+ - Updated dependencies [c93c943]
160
+ - Updated dependencies [104d776]
161
+ - @salt-ds/core@0.0.0-snapshot-20250627090641
package/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # Carousel pattern
2
+
3
+ Based on [embla](https://www.embla-carousel.com/)
@@ -0,0 +1,155 @@
1
+ /* src/Carousel.css */
2
+ .saltCarousel {
3
+ --saltCarousel-slide-height: 310px;
4
+ --saltCarousel-slide-spacing: var(--salt-spacing-100);
5
+ --saltCarousel-slide-size: 100%;
6
+ display: flex;
7
+ flex-direction: column;
8
+ gap: var(--salt-spacing-100);
9
+ margin: auto;
10
+ }
11
+
12
+ /* src/CarouselAutoplayIndicator.css */
13
+ .saltCarouselAutoplayIndicator {
14
+ --salt-carousel-svg-circumference: 0;
15
+ display: flex;
16
+ align-self: center;
17
+ }
18
+ .saltCarouselAutoplayIndicatorSVG {
19
+ transform: rotate(-90deg);
20
+ }
21
+ .saltCarouselAutoplayIndicatorSVG-track {
22
+ fill: none;
23
+ stroke: var(--salt-accent-foreground);
24
+ }
25
+ .saltCarouselAutoplayIndicatorSVG-bar {
26
+ fill: none;
27
+ stroke: var(--salt-accent-background);
28
+ stroke-dasharray: var(--salt-carousel-svg-circumference);
29
+ stroke-dashoffset: var(--salt-carousel-svg-circumference);
30
+ animation: indicatorAnimation 0.5s linear;
31
+ animation-play-state: paused;
32
+ }
33
+ @keyframes indicatorAnimation {
34
+ from {
35
+ stroke-dashoffset: var(--salt-carousel-svg-circumference);
36
+ }
37
+ to {
38
+ stroke-dashoffset: 0;
39
+ }
40
+ }
41
+
42
+ /* src/CarouselCard.css */
43
+ .saltCarouselCard {
44
+ display: flex;
45
+ transform: translate3d(0, 0, 0);
46
+ flex: 0 0 var(--saltCarousel-slide-size);
47
+ min-width: 0;
48
+ padding-left: var(--saltCarousel-slide-spacing);
49
+ box-sizing: border-box;
50
+ }
51
+ .saltCarouselCard-content {
52
+ display: flex;
53
+ user-select: none;
54
+ overflow: hidden;
55
+ flex-direction: column;
56
+ gap: var(--salt-spacing-200);
57
+ flex-grow: 1;
58
+ }
59
+ .saltCarouselCard-body {
60
+ display: flex;
61
+ overflow: hidden;
62
+ flex-direction: column;
63
+ gap: var(--salt-spacing-200);
64
+ flex-grow: 1;
65
+ padding: 0 var(--salt-spacing-200) var(--salt-spacing-200) var(--salt-spacing-200);
66
+ }
67
+ .saltCarouselCard-content h2,
68
+ .saltCarouselCard-content h3 {
69
+ margin: 0;
70
+ }
71
+ .saltCarouselCard[data-visibility=off-screen] a {
72
+ visibility: hidden;
73
+ }
74
+ .saltCarouselCard-bordered {
75
+ background: var(--salt-container-primary-background);
76
+ border: var(--salt-size-border) var(--salt-container-borderStyle) var(--salt-container-primary-borderColor);
77
+ border-radius: var(--salt-palette-corner, 0);
78
+ }
79
+
80
+ /* src/CarouselProgressLabel.css */
81
+ .saltCarouselTabList.saltText {
82
+ font-weight: var(--salt-palette-text-body-fontWeight-strong);
83
+ }
84
+
85
+ /* src/CarouselSlides.css */
86
+ .saltCarouselSlides {
87
+ overflow: hidden;
88
+ }
89
+ .saltCarouselSlides-container {
90
+ display: flex;
91
+ touch-action: pan-y pinch-zoom;
92
+ margin-left: calc(var(--saltCarousel-slide-spacing) * -1);
93
+ }
94
+
95
+ /* src/CarouselTab.css */
96
+ .saltCarouselTab {
97
+ position: relative;
98
+ width: var(--salt-size-selectable);
99
+ height: var(--salt-size-selectable);
100
+ border: none;
101
+ box-shadow: inset 0 0 0 var(--salt-size-border) var(--salt-selectable-borderColor);
102
+ -webkit-tap-highlight-color: var(--salt-selectable-borderColor-hover);
103
+ -webkit-appearance: none;
104
+ appearance: none;
105
+ background-color: transparent;
106
+ touch-action: manipulation;
107
+ display: inline-flex;
108
+ text-decoration: none;
109
+ cursor: pointer;
110
+ padding: 0;
111
+ margin: 0;
112
+ align-items: center;
113
+ justify-content: center;
114
+ border-radius: var(--salt-palette-corner-strongest);
115
+ transition: box-shadow var(--salt-duration-perceptible) ease-in-out;
116
+ }
117
+ .saltCarouselTab:after {
118
+ content: "";
119
+ position: absolute;
120
+ width: var(--salt-size-selectable);
121
+ height: var(--salt-size-selectable);
122
+ border-radius: 50%;
123
+ background-color: transparent;
124
+ top: 50%;
125
+ left: 50%;
126
+ transform: translate(-50%, -50%);
127
+ }
128
+ .saltCarouselTab:focus-visible {
129
+ outline-style: var(--salt-focused-outlineStyle);
130
+ outline-width: var(--salt-focused-outlineWidth);
131
+ outline-color: var(--salt-focused-outlineColor);
132
+ outline-offset: var(--salt-focused-outlineOffset);
133
+ background: var(--salt-selectable-background-hover);
134
+ border-color: var(--salt-selectable-borderColor-hover);
135
+ }
136
+ .saltCarouselTab-selected {
137
+ box-shadow: inset 0 0 0 var(--salt-size-selectable) var(--salt-selectable-borderColor-selected);
138
+ }
139
+
140
+ /* src/CarouselTabList.css */
141
+ .saltCarouselTabList {
142
+ display: flex;
143
+ flex-wrap: wrap;
144
+ justify-content: flex-end;
145
+ align-items: center;
146
+ gap: var(--salt-spacing-200);
147
+ }
148
+ .saltCarouselTabList:focus-visible {
149
+ outline-style: var(--salt-focused-outlineStyle);
150
+ outline-width: var(--salt-focused-outlineWidth);
151
+ outline-offset: var(--salt-focused-outlineOffset);
152
+ outline-color: var(--salt-focused-outlineColor);
153
+ }
154
+
155
+ /* src/cd851d81-d6a7-4108-95c8-d10689f569ce.css */
@@ -0,0 +1,6 @@
1
+ 'use strict';
2
+
3
+ var css_248z = ".saltCarousel {\n --saltCarousel-slide-height: 310px;\n --saltCarousel-slide-spacing: var(--salt-spacing-100);\n --saltCarousel-slide-size: 100%;\n display: flex;\n flex-direction: column;\n gap: var(--salt-spacing-100);\n margin: auto;\n}\n";
4
+
5
+ module.exports = css_248z;
6
+ //# sourceMappingURL=Carousel.css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Carousel.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
@@ -0,0 +1,53 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var core = require('@salt-ds/core');
5
+ var styles = require('@salt-ds/styles');
6
+ var window = require('@salt-ds/window');
7
+ var clsx = require('clsx');
8
+ var useEmblaCarousel = require('embla-carousel-react');
9
+ var react = require('react');
10
+ var Carousel$1 = require('./Carousel.css.js');
11
+ var CarouselContext = require('./CarouselContext.js');
12
+
13
+ const withBaseName = core.makePrefixer("saltCarousel");
14
+ const Carousel = react.forwardRef(
15
+ function Carousel2({
16
+ children,
17
+ className,
18
+ emblaOptions = {},
19
+ emblaPlugins = [],
20
+ getEmblaApi,
21
+ ...rest
22
+ }, ref) {
23
+ const targetWindow = window.useWindow();
24
+ styles.useComponentCssInjection({
25
+ testId: "salt-carousel",
26
+ css: Carousel$1,
27
+ window: targetWindow
28
+ });
29
+ const [emblaRef, emblaApi] = useEmblaCarousel(emblaOptions, [
30
+ ...emblaPlugins
31
+ ]);
32
+ react.useEffect(() => {
33
+ if (emblaApi) {
34
+ getEmblaApi == null ? void 0 : getEmblaApi(emblaApi);
35
+ }
36
+ return void 0;
37
+ }, [emblaApi]);
38
+ return /* @__PURE__ */ jsxRuntime.jsx(CarouselContext.CarouselContext.Provider, { value: { emblaApi, emblaRef }, children: /* @__PURE__ */ jsxRuntime.jsx(
39
+ "section",
40
+ {
41
+ "aria-roledescription": "carousel",
42
+ role: "region",
43
+ className: clsx.clsx(withBaseName(), className),
44
+ ref,
45
+ ...rest,
46
+ children
47
+ }
48
+ ) });
49
+ }
50
+ );
51
+
52
+ exports.Carousel = Carousel;
53
+ //# sourceMappingURL=Carousel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Carousel.js","sources":["../src/Carousel.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 useEmblaCarousel, {\n type UseEmblaCarouselType,\n} from \"embla-carousel-react\";\nimport { type ComponentPropsWithoutRef, forwardRef, useEffect } from \"react\";\nimport carouselCss from \"./Carousel.css\";\nimport { CarouselContext } from \"./CarouselContext\";\n\nconst withBaseName = makePrefixer(\"saltCarousel\");\n\nexport type CarouselEmblaRefType = UseEmblaCarouselType[0];\nexport type CarouselEmblaApiType = UseEmblaCarouselType[1];\n\ntype UseCarouselParameters = Parameters<typeof useEmblaCarousel>;\nexport type CarouselOptions = UseCarouselParameters[0];\nexport type CarouselPlugin = UseCarouselParameters[1];\n\n/**\n * Props for the Carousel component.\n * Pass a ref to the carousel to get it to return a reference to the embla API\n */\nexport interface CarouselProps extends ComponentPropsWithoutRef<\"section\"> {\n /**\n * Options to configure the Embla Carousel.\n * These options are passed directly to the Embla Carousel instance.\n */\n emblaOptions?: CarouselOptions;\n\n /**\n * Plugins to enhance the functionality of the Embla Carousel.\n * These options are passed directly to the Embla Carousel instance.\n */\n emblaPlugins?: CarouselPlugin;\n /** Get embla API as ref, use this to manage the state of the Carousel */\n getEmblaApi?: (embla: CarouselEmblaApiType) => void;\n}\n\nexport const Carousel = forwardRef<HTMLElement, CarouselProps>(\n function Carousel(\n {\n children,\n className,\n emblaOptions = {},\n emblaPlugins = [],\n getEmblaApi,\n ...rest\n },\n ref,\n ) {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-carousel\",\n css: carouselCss,\n window: targetWindow,\n });\n\n const [emblaRef, emblaApi] = useEmblaCarousel(emblaOptions, [\n ...emblaPlugins,\n ]);\n\n useEffect(() => {\n if (emblaApi) {\n getEmblaApi?.(emblaApi);\n }\n return undefined;\n }, [emblaApi]);\n\n return (\n <CarouselContext.Provider value={{ emblaApi, emblaRef }}>\n <section\n aria-roledescription=\"carousel\"\n role=\"region\"\n className={clsx(withBaseName(), className)}\n ref={ref}\n {...rest}\n >\n {children}\n </section>\n </CarouselContext.Provider>\n );\n },\n);\n"],"names":["makePrefixer","forwardRef","Carousel","useWindow","useComponentCssInjection","carouselCss","useEffect","jsx","CarouselContext","clsx"],"mappings":";;;;;;;;;;;;AAWA,MAAM,YAAA,GAAeA,kBAAa,cAAc,CAAA;AA6BzC,MAAM,QAAW,GAAAC,gBAAA;AAAA,EACtB,SAASC,SACP,CAAA;AAAA,IACE,QAAA;AAAA,IACA,SAAA;AAAA,IACA,eAAe,EAAC;AAAA,IAChB,eAAe,EAAC;AAAA,IAChB,WAAA;AAAA,IACA,GAAG;AAAA,KAEL,GACA,EAAA;AACA,IAAA,MAAM,eAAeC,gBAAU,EAAA;AAC/B,IAAyBC,+BAAA,CAAA;AAAA,MACvB,MAAQ,EAAA,eAAA;AAAA,MACR,GAAK,EAAAC,UAAA;AAAA,MACL,MAAQ,EAAA;AAAA,KACT,CAAA;AAED,IAAA,MAAM,CAAC,QAAA,EAAU,QAAQ,CAAA,GAAI,iBAAiB,YAAc,EAAA;AAAA,MAC1D,GAAG;AAAA,KACJ,CAAA;AAED,IAAAC,eAAA,CAAU,MAAM;AACd,MAAA,IAAI,QAAU,EAAA;AACZ,QAAc,WAAA,IAAA,IAAA,GAAA,MAAA,GAAA,WAAA,CAAA,QAAA,CAAA;AAAA;AAEhB,MAAO,OAAA,MAAA;AAAA,KACT,EAAG,CAAC,QAAQ,CAAC,CAAA;AAEb,IACE,uBAAAC,cAAA,CAACC,gCAAgB,QAAhB,EAAA,EAAyB,OAAO,EAAE,QAAA,EAAU,UAC3C,EAAA,QAAA,kBAAAD,cAAA;AAAA,MAAC,SAAA;AAAA,MAAA;AAAA,QACC,sBAAqB,EAAA,UAAA;AAAA,QACrB,IAAK,EAAA,QAAA;AAAA,QACL,SAAW,EAAAE,SAAA,CAAK,YAAa,EAAA,EAAG,SAAS,CAAA;AAAA,QACzC,GAAA;AAAA,QACC,GAAG,IAAA;AAAA,QAEH;AAAA;AAAA,KAEL,EAAA,CAAA;AAAA;AAGN;;;;"}
@@ -0,0 +1,55 @@
1
+ 'use strict';
2
+
3
+ var core = require('@salt-ds/core');
4
+ var react = require('react');
5
+
6
+ const getSlideLabel = (slideElement, slideIndex, slideCount) => {
7
+ let description = slideElement == null ? void 0 : slideElement.getAttribute("aria-label");
8
+ if (!description) {
9
+ const labelledById = slideElement == null ? void 0 : slideElement.getAttribute("aria-labelledby");
10
+ if (labelledById) {
11
+ const labelledByElement = document.getElementById(labelledById);
12
+ description = (labelledByElement == null ? void 0 : labelledByElement.textContent) || "No description available";
13
+ } else {
14
+ description = "No description available";
15
+ }
16
+ }
17
+ return `slide ${slideIndex + 1} of ${slideCount}. ${description}`;
18
+ };
19
+ function CarouselAnnouncement(userOptions = {}) {
20
+ let emblaApi;
21
+ const { announce } = core.useAriaAnnouncer();
22
+ const handleSettle = react.useCallback(
23
+ (emblaApi2) => {
24
+ var _a;
25
+ const slideCount = (emblaApi2 == null ? void 0 : emblaApi2.slideNodes().length) ?? 0;
26
+ const slideIndexInView = ((_a = emblaApi2 == null ? void 0 : emblaApi2.slidesInView()) == null ? void 0 : _a[0]) ?? 0;
27
+ const slideElement = emblaApi2 == null ? void 0 : emblaApi2.slideNodes()[slideIndexInView];
28
+ const slideLabel = getSlideLabel(
29
+ slideElement,
30
+ slideIndexInView,
31
+ slideCount
32
+ );
33
+ announce(slideLabel);
34
+ },
35
+ [announce]
36
+ );
37
+ function init(emblaApiInstance) {
38
+ emblaApi = emblaApiInstance;
39
+ emblaApi.on("settle", handleSettle);
40
+ }
41
+ function destroy() {
42
+ emblaApi.off("settle", handleSettle);
43
+ }
44
+ const self = {
45
+ name: "announcement",
46
+ options: userOptions,
47
+ init,
48
+ destroy
49
+ };
50
+ return self;
51
+ }
52
+
53
+ exports.CarouselAnnouncement = CarouselAnnouncement;
54
+ exports.getSlideLabel = getSlideLabel;
55
+ //# sourceMappingURL=CarouselAnnouncementPlugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CarouselAnnouncementPlugin.js","sources":["../src/CarouselAnnouncementPlugin.ts"],"sourcesContent":["import { useAriaAnnouncer } from \"@salt-ds/core\";\nimport type {\n CreateOptionsType,\n CreatePluginType,\n EmblaCarouselType,\n} from \"embla-carousel\";\nimport { useCallback } from \"react\";\n\ndeclare module \"embla-carousel\" {\n interface EmblaPluginsType {\n announcement: CarouselAnnouncementType;\n }\n}\n\n/**\n * Type definition for the parameters of the getSlideLabel function.\n */\nexport type GetSlideLabelProps = (\n /**\n * The HTML element representing the slide.\n */\n slideElement: HTMLElement,\n\n /**\n * The index of the slide within the carousel.\n */\n slideIndex: number,\n\n /**\n * The total number of slides in the carousel.\n */\n slideCount: number,\n) => string;\n\n/**\n * Generates a label for a carousel slide based on ARIA attributes.\n *\n * @param props - The properties required to generate the slide description.\n * @returns A string description of the slide, including its position and ARIA label or text content.\n */\nexport const getSlideLabel: GetSlideLabelProps = (\n slideElement,\n slideIndex,\n slideCount,\n): string => {\n let description = slideElement?.getAttribute(\"aria-label\");\n if (!description) {\n const labelledById = slideElement?.getAttribute(\"aria-labelledby\");\n if (labelledById) {\n const labelledByElement = document.getElementById(labelledById);\n description =\n labelledByElement?.textContent || \"No description available\";\n } else {\n description = \"No description available\";\n }\n }\n return `slide ${slideIndex + 1} of ${slideCount}. ${description}`;\n};\n\n// biome-ignore lint/complexity/noBannedTypes: Replicated from embla docs/code\ntype OptionsType = CreateOptionsType<{}>;\n// biome-ignore lint/complexity/noBannedTypes: Replicated from embla docs/code\nexport type CarouselAnnouncementType = CreatePluginType<{}, OptionsType>;\n\nexport type CarouselAnnouncementOptionsType =\n CarouselAnnouncementType[\"options\"];\n\nexport function CarouselAnnouncement(\n userOptions: CarouselAnnouncementOptionsType = {},\n): CarouselAnnouncementType {\n let emblaApi: EmblaCarouselType;\n\n const { announce } = useAriaAnnouncer();\n\n const handleSettle = useCallback(\n (emblaApi: EmblaCarouselType) => {\n const slideCount = emblaApi?.slideNodes().length ?? 0;\n const slideIndexInView = emblaApi?.slidesInView()?.[0] ?? 0;\n const slideElement = emblaApi?.slideNodes()[slideIndexInView];\n\n const slideLabel = getSlideLabel(\n slideElement,\n slideIndexInView,\n slideCount,\n );\n announce(slideLabel);\n },\n [announce],\n );\n\n function init(emblaApiInstance: EmblaCarouselType): void {\n emblaApi = emblaApiInstance;\n emblaApi.on(\"settle\", handleSettle);\n }\n\n function destroy(): void {\n emblaApi.off(\"settle\", handleSettle);\n }\n\n const self: CarouselAnnouncementType = {\n name: \"announcement\",\n options: userOptions,\n init,\n destroy,\n };\n return self;\n}\n"],"names":["useAriaAnnouncer","useCallback","emblaApi"],"mappings":";;;;;AAwCO,MAAM,aAAoC,GAAA,CAC/C,YACA,EAAA,UAAA,EACA,UACW,KAAA;AACX,EAAI,IAAA,WAAA,GAAc,6CAAc,YAAa,CAAA,YAAA,CAAA;AAC7C,EAAA,IAAI,CAAC,WAAa,EAAA;AAChB,IAAM,MAAA,YAAA,GAAe,6CAAc,YAAa,CAAA,iBAAA,CAAA;AAChD,IAAA,IAAI,YAAc,EAAA;AAChB,MAAM,MAAA,iBAAA,GAAoB,QAAS,CAAA,cAAA,CAAe,YAAY,CAAA;AAC9D,MAAA,WAAA,GAAA,CACE,uDAAmB,WAAe,KAAA,0BAAA;AAAA,KAC/B,MAAA;AACL,MAAc,WAAA,GAAA,0BAAA;AAAA;AAChB;AAEF,EAAA,OAAO,SAAS,UAAa,GAAA,CAAC,CAAO,IAAA,EAAA,UAAU,KAAK,WAAW,CAAA,CAAA;AACjE;AAUgB,SAAA,oBAAA,CACd,WAA+C,GAAA,EACrB,EAAA;AAC1B,EAAI,IAAA,QAAA;AAEJ,EAAM,MAAA,EAAE,QAAS,EAAA,GAAIA,qBAAiB,EAAA;AAEtC,EAAA,MAAM,YAAe,GAAAC,iBAAA;AAAA,IACnB,CAACC,SAAgC,KAAA;AA3ErC,MAAA,IAAA,EAAA;AA4EM,MAAA,MAAM,UAAaA,GAAAA,CAAAA,SAAAA,IAAA,IAAAA,GAAAA,MAAAA,GAAAA,SAAAA,CAAU,aAAa,MAAU,KAAA,CAAA;AACpD,MAAA,MAAM,qBAAmB,EAAAA,GAAAA,SAAAA,IAAA,gBAAAA,SAAU,CAAA,YAAA,EAAA,KAAV,mBAA2B,CAAM,CAAA,KAAA,CAAA;AAC1D,MAAA,MAAM,YAAeA,GAAAA,SAAAA,IAAA,IAAAA,GAAAA,MAAAA,GAAAA,SAAAA,CAAU,UAAa,EAAA,CAAA,gBAAA,CAAA;AAE5C,MAAA,MAAM,UAAa,GAAA,aAAA;AAAA,QACjB,YAAA;AAAA,QACA,gBAAA;AAAA,QACA;AAAA,OACF;AACA,MAAA,QAAA,CAAS,UAAU,CAAA;AAAA,KACrB;AAAA,IACA,CAAC,QAAQ;AAAA,GACX;AAEA,EAAA,SAAS,KAAK,gBAA2C,EAAA;AACvD,IAAW,QAAA,GAAA,gBAAA;AACX,IAAS,QAAA,CAAA,EAAA,CAAG,UAAU,YAAY,CAAA;AAAA;AAGpC,EAAA,SAAS,OAAgB,GAAA;AACvB,IAAS,QAAA,CAAA,GAAA,CAAI,UAAU,YAAY,CAAA;AAAA;AAGrC,EAAA,MAAM,IAAiC,GAAA;AAAA,IACrC,IAAM,EAAA,cAAA;AAAA,IACN,OAAS,EAAA,WAAA;AAAA,IACT,IAAA;AAAA,IACA;AAAA,GACF;AACA,EAAO,OAAA,IAAA;AACT;;;;;"}
@@ -0,0 +1,6 @@
1
+ 'use strict';
2
+
3
+ var css_248z = ".saltCarouselAutoplayIndicator {\n --salt-carousel-svg-circumference: 0;\n display: flex;\n align-self: center;\n}\n\n.saltCarouselAutoplayIndicatorSVG {\n transform: rotate(-90deg);\n}\n\n.saltCarouselAutoplayIndicatorSVG-track {\n fill: none;\n stroke: var(--salt-accent-foreground);\n}\n\n.saltCarouselAutoplayIndicatorSVG-bar {\n fill: none;\n stroke: var(--salt-accent-background);\n stroke-dasharray: var(--salt-carousel-svg-circumference);\n stroke-dashoffset: var(--salt-carousel-svg-circumference);\n animation: indicatorAnimation 0.5s linear;\n animation-play-state: paused;\n}\n\n@keyframes indicatorAnimation {\n from {\n stroke-dashoffset: var(--salt-carousel-svg-circumference);\n }\n to {\n stroke-dashoffset: 0;\n }\n}\n";
4
+
5
+ module.exports = css_248z;
6
+ //# sourceMappingURL=CarouselAutoplayIndicator.css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CarouselAutoplayIndicator.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
@@ -0,0 +1,82 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var core = require('@salt-ds/core');
5
+ var styles = require('@salt-ds/styles');
6
+ var window = require('@salt-ds/window');
7
+ var clsx = require('classnames');
8
+ var react = require('react');
9
+ var CarouselAutoplayIndicator$1 = require('./CarouselAutoplayIndicator.css.js');
10
+ var CarouselAutoplayIndicatorSVG = require('./CarouselAutoplayIndicatorSVG.js');
11
+
12
+ const withBaseName = core.makePrefixer("saltCarouselAutoplayIndicator");
13
+ const sizeAndStrokeWidthMapping = {
14
+ high: { size: 10, strokeWidth: 2 },
15
+ medium: { size: 12, strokeWidth: 2 },
16
+ low: { size: 14, strokeWidth: 2 },
17
+ touch: { size: 16, strokeWidth: 2 }
18
+ };
19
+ const CarouselAutoplayIndicator = react.forwardRef(({ className, duration, slideIndex, isPlaying, children, ...props }, ref) => {
20
+ const targetWindow = window.useWindow();
21
+ styles.useComponentCssInjection({
22
+ testId: "salt-carousel-autoplay-indicator",
23
+ css: CarouselAutoplayIndicator$1,
24
+ window: targetWindow
25
+ });
26
+ const barRef = react.useRef(null);
27
+ const animationFrameId = react.useRef(null);
28
+ const density = core.useDensity();
29
+ const { size, strokeWidth } = sizeAndStrokeWidthMapping[density];
30
+ const radius = (size - strokeWidth) / 2;
31
+ const circumference = 2 * Math.PI * radius;
32
+ react.useEffect(() => {
33
+ if (barRef.current) {
34
+ animationFrameId.current = requestAnimationFrame(() => {
35
+ if (!barRef.current) {
36
+ return;
37
+ }
38
+ barRef.current.style.animation = "none";
39
+ barRef.current.style.strokeDashoffset = `${circumference}`;
40
+ animationFrameId.current = requestAnimationFrame(() => {
41
+ if (!barRef.current) {
42
+ return;
43
+ }
44
+ barRef.current.style.animation = `indicatorAnimation ${duration}ms linear`;
45
+ barRef.current.style.animationPlayState = isPlaying ? "running" : "paused";
46
+ });
47
+ });
48
+ }
49
+ return () => {
50
+ if (animationFrameId.current !== null) {
51
+ cancelAnimationFrame(animationFrameId.current);
52
+ animationFrameId.current = null;
53
+ }
54
+ };
55
+ }, [circumference, duration, slideIndex, isPlaying]);
56
+ return /* @__PURE__ */ jsxRuntime.jsx(
57
+ "div",
58
+ {
59
+ ref,
60
+ style: {
61
+ width: size,
62
+ height: size,
63
+ // @ts-ignore
64
+ "--salt-carousel-svg-circumference": circumference
65
+ },
66
+ className: clsx(withBaseName(), className),
67
+ ...props,
68
+ children: /* @__PURE__ */ jsxRuntime.jsx(
69
+ CarouselAutoplayIndicatorSVG.CarouselAutoplayIndicatorSVG,
70
+ {
71
+ size,
72
+ strokeWidth,
73
+ barRef,
74
+ radius
75
+ }
76
+ )
77
+ }
78
+ );
79
+ });
80
+
81
+ exports.CarouselAutoplayIndicator = CarouselAutoplayIndicator;
82
+ //# sourceMappingURL=CarouselAutoplayIndicator.js.map
@@ -0,0 +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>(({ className, duration, slideIndex, isPlaying, children, ...props }, ref) => {\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>(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 = 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]);\n\n return (\n <div\n ref={ref}\n style={{\n width: size,\n height: size,\n // @ts-ignore\n \"--salt-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"],"names":["makePrefixer","forwardRef","useWindow","useComponentCssInjection","carouselAutoplayIndicator","useRef","useDensity","useEffect","jsx","CarouselAutoplayIndicatorSVG"],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var core = require('@salt-ds/core');
5
+ var clsx = require('classnames');
6
+ var react = require('react');
7
+
8
+ const withBaseName = core.makePrefixer("saltCarouselAutoplayIndicatorSVG");
9
+ const CarouselAutoplayIndicatorSVG = react.forwardRef(
10
+ ({
11
+ barRef,
12
+ className,
13
+ radius,
14
+ size,
15
+ strokeWidth
16
+ }, ref) => {
17
+ return /* @__PURE__ */ jsxRuntime.jsxs(
18
+ "svg",
19
+ {
20
+ className: clsx(withBaseName(), className),
21
+ width: size,
22
+ height: size,
23
+ "aria-hidden": true,
24
+ ref,
25
+ children: [
26
+ /* @__PURE__ */ jsxRuntime.jsx(
27
+ "circle",
28
+ {
29
+ className: withBaseName("track"),
30
+ cx: size / 2,
31
+ cy: size / 2,
32
+ r: radius,
33
+ strokeWidth
34
+ }
35
+ ),
36
+ /* @__PURE__ */ jsxRuntime.jsx(
37
+ "circle",
38
+ {
39
+ ref: barRef,
40
+ className: withBaseName("bar"),
41
+ cx: size / 2,
42
+ cy: size / 2,
43
+ r: radius,
44
+ strokeWidth
45
+ }
46
+ )
47
+ ]
48
+ }
49
+ );
50
+ }
51
+ );
52
+
53
+ exports.CarouselAutoplayIndicatorSVG = CarouselAutoplayIndicatorSVG;
54
+ //# sourceMappingURL=CarouselAutoplayIndicatorSVG.js.map
@@ -0,0 +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: React.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":["makePrefixer","forwardRef","jsxs","jsx"],"mappings":";;;;;;;AAGA,MAAM,YAAA,GAAeA,kBAAa,kCAAkC,CAAA;AA0B7D,MAAM,4BAA+B,GAAAC,gBAAA;AAAA,EAI1C,CACE;AAAA,IACE,MAAA;AAAA,IACA,SAAA;AAAA,IACA,MAAA;AAAA,IACA,IAAA;AAAA,IACA;AAAA,KAEF,GACG,KAAA;AACH,IACE,uBAAAC,eAAA;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,0BAAAC,cAAA;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,0BACAA,cAAA;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;;;;"}
@@ -0,0 +1,6 @@
1
+ 'use strict';
2
+
3
+ var css_248z = ".saltCarouselCard {\n display: flex;\n transform: translate3d(0, 0, 0);\n flex: 0 0 var(--saltCarousel-slide-size);\n min-width: 0;\n padding-left: var(--saltCarousel-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-border) var(--salt-container-borderStyle) var(--salt-container-primary-borderColor);\n border-radius: var(--salt-palette-corner, 0);\n}\n";
4
+
5
+ module.exports = css_248z;
6
+ //# sourceMappingURL=CarouselCard.css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CarouselCard.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}