@salt-ds/lab 1.0.0-alpha.64 → 1.0.0-alpha.66

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 (105) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/css/salt-lab.css +111 -269
  3. package/dist-cjs/carousel/Carousel.css.js +1 -1
  4. package/dist-cjs/carousel/Carousel.js +30 -87
  5. package/dist-cjs/carousel/Carousel.js.map +1 -1
  6. package/dist-cjs/carousel/CarouselContext.js +62 -0
  7. package/dist-cjs/carousel/CarouselContext.js.map +1 -0
  8. package/dist-cjs/carousel/CarouselControls.css.js +6 -0
  9. package/dist-cjs/carousel/CarouselControls.css.js.map +1 -0
  10. package/dist-cjs/carousel/CarouselControls.js +122 -0
  11. package/dist-cjs/carousel/CarouselControls.js.map +1 -0
  12. package/dist-cjs/carousel/CarouselReducer.js +77 -0
  13. package/dist-cjs/carousel/CarouselReducer.js.map +1 -0
  14. package/dist-cjs/carousel/CarouselSlide.css.js +6 -0
  15. package/dist-cjs/carousel/CarouselSlide.css.js.map +1 -0
  16. package/dist-cjs/carousel/CarouselSlide.js +95 -45
  17. package/dist-cjs/carousel/CarouselSlide.js.map +1 -1
  18. package/dist-cjs/carousel/CarouselSlider.css.js +6 -0
  19. package/dist-cjs/carousel/CarouselSlider.css.js.map +1 -0
  20. package/dist-cjs/carousel/CarouselSlider.js +93 -0
  21. package/dist-cjs/carousel/CarouselSlider.js.map +1 -0
  22. package/dist-cjs/index.js +6 -6
  23. package/dist-es/carousel/Carousel.css.js +1 -1
  24. package/dist-es/carousel/Carousel.js +32 -89
  25. package/dist-es/carousel/Carousel.js.map +1 -1
  26. package/dist-es/carousel/CarouselContext.js +58 -0
  27. package/dist-es/carousel/CarouselContext.js.map +1 -0
  28. package/dist-es/carousel/CarouselControls.css.js +4 -0
  29. package/dist-es/carousel/CarouselControls.css.js.map +1 -0
  30. package/dist-es/carousel/CarouselControls.js +120 -0
  31. package/dist-es/carousel/CarouselControls.js.map +1 -0
  32. package/dist-es/carousel/CarouselReducer.js +75 -0
  33. package/dist-es/carousel/CarouselReducer.js.map +1 -0
  34. package/dist-es/carousel/CarouselSlide.css.js +4 -0
  35. package/dist-es/carousel/CarouselSlide.css.js.map +1 -0
  36. package/dist-es/carousel/CarouselSlide.js +96 -46
  37. package/dist-es/carousel/CarouselSlide.js.map +1 -1
  38. package/dist-es/carousel/CarouselSlider.css.js +4 -0
  39. package/dist-es/carousel/CarouselSlider.css.js.map +1 -0
  40. package/dist-es/carousel/CarouselSlider.js +91 -0
  41. package/dist-es/carousel/CarouselSlider.js.map +1 -0
  42. package/dist-es/index.js +3 -3
  43. package/dist-types/carousel/Carousel.d.ts +10 -23
  44. package/dist-types/carousel/CarouselContext.d.ts +11 -0
  45. package/dist-types/carousel/CarouselControls.d.ts +26 -0
  46. package/dist-types/carousel/CarouselReducer.d.ts +30 -0
  47. package/dist-types/carousel/CarouselSlide.d.ts +31 -8
  48. package/dist-types/carousel/CarouselSlider.d.ts +13 -0
  49. package/dist-types/carousel/index.d.ts +2 -0
  50. package/dist-types/index.d.ts +0 -1
  51. package/dist-types/utils/index.d.ts +1 -1
  52. package/package.json +2 -2
  53. package/dist-cjs/slider/RangeSlider.js +0 -182
  54. package/dist-cjs/slider/RangeSlider.js.map +0 -1
  55. package/dist-cjs/slider/Slider.js +0 -145
  56. package/dist-cjs/slider/Slider.js.map +0 -1
  57. package/dist-cjs/slider/internal/SliderThumb.css.js +0 -6
  58. package/dist-cjs/slider/internal/SliderThumb.css.js.map +0 -1
  59. package/dist-cjs/slider/internal/SliderThumb.js +0 -141
  60. package/dist-cjs/slider/internal/SliderThumb.js.map +0 -1
  61. package/dist-cjs/slider/internal/SliderTooltip.css.js +0 -6
  62. package/dist-cjs/slider/internal/SliderTooltip.css.js.map +0 -1
  63. package/dist-cjs/slider/internal/SliderTooltip.js +0 -58
  64. package/dist-cjs/slider/internal/SliderTooltip.js.map +0 -1
  65. package/dist-cjs/slider/internal/SliderTrack.css.js +0 -6
  66. package/dist-cjs/slider/internal/SliderTrack.css.js.map +0 -1
  67. package/dist-cjs/slider/internal/SliderTrack.js +0 -168
  68. package/dist-cjs/slider/internal/SliderTrack.js.map +0 -1
  69. package/dist-cjs/slider/internal/useRangeSliderThumb.js +0 -233
  70. package/dist-cjs/slider/internal/useRangeSliderThumb.js.map +0 -1
  71. package/dist-cjs/slider/internal/useSliderThumb.js +0 -162
  72. package/dist-cjs/slider/internal/useSliderThumb.js.map +0 -1
  73. package/dist-cjs/slider/internal/utils.js +0 -113
  74. package/dist-cjs/slider/internal/utils.js.map +0 -1
  75. package/dist-es/slider/RangeSlider.js +0 -180
  76. package/dist-es/slider/RangeSlider.js.map +0 -1
  77. package/dist-es/slider/Slider.js +0 -143
  78. package/dist-es/slider/Slider.js.map +0 -1
  79. package/dist-es/slider/internal/SliderThumb.css.js +0 -4
  80. package/dist-es/slider/internal/SliderThumb.css.js.map +0 -1
  81. package/dist-es/slider/internal/SliderThumb.js +0 -139
  82. package/dist-es/slider/internal/SliderThumb.js.map +0 -1
  83. package/dist-es/slider/internal/SliderTooltip.css.js +0 -4
  84. package/dist-es/slider/internal/SliderTooltip.css.js.map +0 -1
  85. package/dist-es/slider/internal/SliderTooltip.js +0 -56
  86. package/dist-es/slider/internal/SliderTooltip.js.map +0 -1
  87. package/dist-es/slider/internal/SliderTrack.css.js +0 -4
  88. package/dist-es/slider/internal/SliderTrack.css.js.map +0 -1
  89. package/dist-es/slider/internal/SliderTrack.js +0 -166
  90. package/dist-es/slider/internal/SliderTrack.js.map +0 -1
  91. package/dist-es/slider/internal/useRangeSliderThumb.js +0 -231
  92. package/dist-es/slider/internal/useRangeSliderThumb.js.map +0 -1
  93. package/dist-es/slider/internal/useSliderThumb.js +0 -160
  94. package/dist-es/slider/internal/useSliderThumb.js.map +0 -1
  95. package/dist-es/slider/internal/utils.js +0 -105
  96. package/dist-es/slider/internal/utils.js.map +0 -1
  97. package/dist-types/slider/RangeSlider.d.ts +0 -99
  98. package/dist-types/slider/Slider.d.ts +0 -100
  99. package/dist-types/slider/index.d.ts +0 -2
  100. package/dist-types/slider/internal/SliderThumb.d.ts +0 -28
  101. package/dist-types/slider/internal/SliderTooltip.d.ts +0 -6
  102. package/dist-types/slider/internal/SliderTrack.d.ts +0 -24
  103. package/dist-types/slider/internal/useRangeSliderThumb.d.ts +0 -30
  104. package/dist-types/slider/internal/useSliderThumb.d.ts +0 -28
  105. package/dist-types/slider/internal/utils.d.ts +0 -20
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CarouselSlider.js","sources":["../src/carousel/CarouselSlider.tsx"],"sourcesContent":["import { makePrefixer, useForkRef } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport {\n type HTMLAttributes,\n type KeyboardEvent,\n type ReactElement,\n type SyntheticEvent,\n type UIEvent,\n forwardRef,\n useContext,\n useLayoutEffect,\n useRef,\n} from \"react\";\nimport {\n CarouselDispatchContext,\n CarouselStateContext,\n} from \"./CarouselContext\";\nimport type { CarouselSlideProps } from \"./CarouselSlide\";\nimport carouselSliderCss from \"./CarouselSlider.css\";\n\nexport interface CarouselSliderProps extends HTMLAttributes<HTMLDivElement> {\n /**\n * Collection of slides to render\n */\n children: Array<ReactElement<CarouselSlideProps>>;\n /**\n * Callback fired when the selected slide change.\n **/\n onSelectionChange?: (\n event: SyntheticEvent<HTMLDivElement>,\n index: number,\n ) => void;\n}\n\nconst withBaseName = makePrefixer(\"saltCarouselSlider\");\n\nexport const CarouselSlider = forwardRef<HTMLDivElement, CarouselSliderProps>(\n function CarouselSlider(\n { children, onKeyDown, onScroll, onSelectionChange, ...rest },\n propRef,\n ) {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-carousel-slider\",\n css: carouselSliderCss,\n window: targetWindow,\n });\n const containerRef = useRef<HTMLDivElement>(null);\n const hasRun = useRef(false);\n const { slides, activeSlideIndex, focusedSlideIndex, visibleSlides } =\n useContext(CarouselStateContext);\n const dispatch = useContext(CarouselDispatchContext);\n const slideIds = [...slides.keys()];\n\n const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n if (event.repeat) return;\n switch (event.key) {\n case \"ArrowLeft\": {\n const prevIndex =\n focusedSlideIndex && focusedSlideIndex > activeSlideIndex\n ? focusedSlideIndex - 1\n : activeSlideIndex - 1;\n const prevId = slideIds[prevIndex] || null;\n\n if (!prevId) break;\n dispatch({ type: \"scroll\", payload: prevId });\n onSelectionChange?.(event, prevIndex);\n slides.get(prevId)?.element.focus();\n\n break;\n }\n case \"ArrowRight\": {\n const nextIndex = activeSlideIndex + 1;\n const nextId = slideIds[nextIndex] || null;\n\n if (!nextId) break;\n\n dispatch({ type: \"scroll\", payload: nextId });\n onSelectionChange?.(event, nextIndex);\n\n slides.get(nextId)?.element.focus();\n\n break;\n }\n }\n onKeyDown?.(event);\n };\n\n const handleScroll = (event: UIEvent<HTMLDivElement>) => {\n const container = containerRef?.current;\n if (!container) return;\n const scrollLeft = container.scrollLeft;\n const slideWidth = container.offsetWidth / visibleSlides;\n const newIndex = Math.round(scrollLeft / slideWidth) || 0;\n\n if (newIndex !== activeSlideIndex) {\n dispatch({ type: \"move\", payload: slideIds[newIndex] });\n onSelectionChange?.(event, newIndex);\n }\n onScroll?.(event);\n };\n\n useLayoutEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n const scrollBehavior = hasRun.current ? \"smooth\" : \"instant\";\n const slideWidth = container.offsetWidth / visibleSlides;\n\n requestAnimationFrame(() => {\n container.scrollTo({\n left: focusedSlideIndex * slideWidth,\n // @ts-ignore ScrollBehavior typescript definition missing instant\n behavior: scrollBehavior,\n });\n });\n\n hasRun.current = true;\n }, [focusedSlideIndex, visibleSlides]);\n\n const ref = useForkRef(propRef, containerRef);\n return (\n <div\n ref={ref}\n className={withBaseName()}\n tabIndex={-1}\n onKeyDown={handleKeyDown}\n onScroll={handleScroll}\n {...rest}\n >\n {children}\n </div>\n );\n },\n);\n"],"names":["makePrefixer","forwardRef","CarouselSlider","useWindow","useComponentCssInjection","carouselSliderCss","useRef","useContext","CarouselStateContext","CarouselDispatchContext","useLayoutEffect","useForkRef","jsx"],"mappings":"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"}
package/dist-cjs/index.js CHANGED
@@ -16,9 +16,9 @@ var isPlainObject = require('./utils/isPlainObject.js');
16
16
  var partition = require('./utils/partition.js');
17
17
  var useClickOutside = require('./utils/useClickOutside.js');
18
18
  var useEventCallback = require('./utils/useEventCallback.js');
19
+ var useIsViewportLargerThanBreakpoint = require('./utils/useIsViewportLargerThanBreakpoint.js');
19
20
  var useLayoutEffectOnce = require('./utils/useLayoutEffectOnce.js');
20
21
  var useLayoutEffectSkipFirst = require('./utils/useLayoutEffectSkipFirst.js');
21
- var useIsViewportLargerThanBreakpoint = require('./utils/useIsViewportLargerThanBreakpoint.js');
22
22
  var useOverflowDetection = require('./utils/useOverflowDetection.js');
23
23
  var useSlideSelection = require('./utils/useSlideSelection.js');
24
24
  var AppHeader = require('./app-header/AppHeader.js');
@@ -35,6 +35,8 @@ var useCalendar = require('./calendar/useCalendar.js');
35
35
  var useCalendarSelection = require('./calendar/useCalendarSelection.js');
36
36
  var Carousel = require('./carousel/Carousel.js');
37
37
  var CarouselSlide = require('./carousel/CarouselSlide.js');
38
+ var CarouselSlider = require('./carousel/CarouselSlider.js');
39
+ var CarouselControls = require('./carousel/CarouselControls.js');
38
40
  var CascadingMenu = require('./cascading-menu/CascadingMenu.js');
39
41
  var ColorChooser = require('./color-chooser/ColorChooser.js');
40
42
  var Color = require('./color-chooser/Color.js');
@@ -120,8 +122,6 @@ var useWidth = require('./responsive/useWidth.js');
120
122
  var overflowUtils = require('./responsive/overflowUtils.js');
121
123
  var utils = require('./responsive/utils.js');
122
124
  var SearchInput = require('./search-input/SearchInput.js');
123
- var Slider = require('./slider/Slider.js');
124
- var RangeSlider = require('./slider/RangeSlider.js');
125
125
  var Splitter = require('./splitter/Splitter.js');
126
126
  var SplitPanel = require('./splitter/SplitPanel.js');
127
127
  var SplitHandle = require('./splitter/SplitHandle.js');
@@ -171,9 +171,9 @@ exports.isPlainObject = isPlainObject.isPlainObject;
171
171
  exports.partition = partition.partition;
172
172
  exports.useClickOutside = useClickOutside.useClickOutside;
173
173
  exports.useEventCallback = useEventCallback.useEventCallback;
174
+ exports.useIsViewportLargerThanBreakpoint = useIsViewportLargerThanBreakpoint.useIsViewportLargerThanBreakpoint;
174
175
  exports.useLayoutEffectOnce = useLayoutEffectOnce.useLayoutEffectOnce;
175
176
  exports.useLayoutEffectSkipFirst = useLayoutEffectSkipFirst.useLayoutEffectSkipFirst;
176
- exports.useIsViewportLargerThanBreakpoint = useIsViewportLargerThanBreakpoint.useIsViewportLargerThanBreakpoint;
177
177
  exports.useOverflowDetection = useOverflowDetection.useOverflowDetection;
178
178
  exports.useSlideSelection = useSlideSelection.useSlideSelection;
179
179
  exports.AppHeader = AppHeader.AppHeader;
@@ -195,6 +195,8 @@ exports.useCalendarSelection = useCalendarSelection.useCalendarSelection;
195
195
  exports.useCalendarSelectionDay = useCalendarSelection.useCalendarSelectionDay;
196
196
  exports.Carousel = Carousel.Carousel;
197
197
  exports.CarouselSlide = CarouselSlide.CarouselSlide;
198
+ exports.CarouselSlider = CarouselSlider.CarouselSlider;
199
+ exports.CarouselControls = CarouselControls.CarouselControls;
198
200
  exports.CascadingMenu = CascadingMenu.CascadingMenu;
199
201
  exports.ColorChooser = ColorChooser.ColorChooser;
200
202
  exports.Color = Color.Color;
@@ -322,8 +324,6 @@ exports.popNextItemByPriority = overflowUtils.popNextItemByPriority;
322
324
  exports.isResponsiveAttribute = utils.isResponsiveAttribute;
323
325
  exports.liftResponsivePropsToFormField = utils.liftResponsivePropsToFormField;
324
326
  exports.SearchInput = SearchInput.SearchInput;
325
- exports.Slider = Slider.Slider;
326
- exports.RangeSlider = RangeSlider.RangeSlider;
327
327
  exports.Splitter = Splitter.Splitter;
328
328
  exports.SplitPanel = SplitPanel.SplitPanel;
329
329
  exports.SplitHandle = SplitHandle.SplitHandle;
@@ -1,4 +1,4 @@
1
- var css_248z = ".saltGridLayout.saltCarousel {\n grid-template-columns: min-content auto min-content;\n grid-template-areas: \"prev-button slider next-button\" \"dots dots dots\";\n}\n\n.saltCarousel.saltCarousel-compact {\n grid-template-areas: \"slider slider slider\" \"prev-button dots next-button\";\n}\n\n.saltCarousel-prev-button {\n grid-area: prev-button;\n height: 100%;\n}\n\n.saltCarousel-next-button {\n grid-area: next-button;\n height: 100%;\n}\n\n.saltCarousel-slider {\n grid-area: slider;\n}\n\n.saltCarousel-dots {\n grid-area: dots;\n justify-self: center;\n}\n";
1
+ var css_248z = ".saltCarousel {\n display: grid;\n grid-row-gap: var(--salt-spacing-100);\n grid-template-areas: \"controls\" \"slider\";\n grid-template-rows: auto 1fr;\n}\n\n.saltCarousel.saltCarousel-bottom {\n grid-template-areas: \"slider\" \"controls\";\n grid-template-rows: 1fr auto;\n}\n";
2
2
 
3
3
  export { css_248z as default };
4
4
  //# sourceMappingURL=Carousel.css.js.map
@@ -1,22 +1,20 @@
1
- import { jsxs, jsx } from 'react/jsx-runtime';
2
- import { forwardRef, Children, useEffect, createElement } from 'react';
3
- import { makePrefixer, useIcon, useId, GridLayout, Button, RadioButtonGroup, RadioButton } from '@salt-ds/core';
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { makePrefixer, useBreakpoint, resolveResponsiveValue, useId } from '@salt-ds/core';
4
3
  import { useComponentCssInjection } from '@salt-ds/styles';
5
4
  import { useWindow } from '@salt-ds/window';
6
5
  import { clsx } from 'clsx';
7
- import { DeckLayout } from '../deck-layout/DeckLayout.js';
8
- import { useSlideSelection } from '../utils/useSlideSelection.js';
6
+ import { forwardRef } from 'react';
9
7
  import css_248z from './Carousel.css.js';
8
+ import { CarouselProvider } from './CarouselContext.js';
10
9
 
11
10
  const withBaseName = makePrefixer("saltCarousel");
12
11
  const Carousel = forwardRef(
13
12
  function Carousel2({
14
- initialIndex,
15
- animation = "slide",
16
- carouselDescription,
13
+ defaultActiveSlideIndex = 0,
14
+ activeSlideIndex,
15
+ visibleSlides: visibleSlidesProp = 1,
17
16
  children,
18
- className,
19
- compact,
17
+ controlsPlacement = "top",
20
18
  id: idProp,
21
19
  ...rest
22
20
  }, ref) {
@@ -26,88 +24,33 @@ const Carousel = forwardRef(
26
24
  css: css_248z,
27
25
  window: targetWindow
28
26
  });
29
- const { NextIcon, PreviousIcon } = useIcon();
27
+ const { matchedBreakpoints } = useBreakpoint();
28
+ const visibleSlides = resolveResponsiveValue(
29
+ visibleSlidesProp,
30
+ matchedBreakpoints
31
+ );
30
32
  const id = useId(idProp);
31
- const slidesCount = Children.count(children);
32
- const [_, selectedSlide, handleSlideSelection] = useSlideSelection(initialIndex);
33
- const moveSlide = (direction) => {
34
- const moveLeft = selectedSlide === 0 ? slidesCount - 1 : selectedSlide - 1;
35
- const moveRight = selectedSlide === slidesCount - 1 ? 0 : selectedSlide + 1;
36
- const newSelection = direction === "left" ? moveLeft : moveRight;
37
- const newTransition = direction === "left" ? "decrease" : "increase";
38
- handleSlideSelection(newSelection, newTransition);
39
- };
40
- const handleRadioChange = ({
41
- target: { value }
42
- }) => {
43
- handleSlideSelection(Number(value));
44
- };
45
- useEffect(() => {
46
- if (process.env.NODE_ENV !== "production") {
47
- if (slidesCount < 1) {
48
- console.warn(
49
- "Carousel component requires more than one children to render. At least two elements should be provided."
50
- );
51
- }
52
- }
53
- }, [slidesCount]);
54
- return /* @__PURE__ */ jsxs(
55
- GridLayout,
33
+ return /* @__PURE__ */ jsx(
34
+ CarouselProvider,
56
35
  {
57
- "aria-label": carouselDescription,
58
- "aria-roledescription": "carousel",
36
+ defaultActiveSlideIndex,
37
+ activeSlideIndex,
38
+ visibleSlides,
59
39
  id,
60
- role: "region",
61
- ref,
62
- gap: 0,
63
- columns: 3,
64
- className: clsx(
65
- withBaseName(),
66
- compact && withBaseName("compact"),
67
- className
68
- ),
69
- ...rest,
70
- children: [
71
- /* @__PURE__ */ jsx(
72
- Button,
73
- {
74
- variant: "secondary",
75
- className: withBaseName("prev-button"),
76
- onClick: () => moveSlide("left"),
77
- children: /* @__PURE__ */ jsx(PreviousIcon, { size: 2 })
78
- }
79
- ),
80
- /* @__PURE__ */ jsx(
81
- DeckLayout,
82
- {
83
- activeIndex: selectedSlide,
84
- animation,
85
- className: withBaseName("slider"),
86
- children
87
- }
88
- ),
89
- /* @__PURE__ */ jsx(
90
- Button,
91
- {
92
- variant: "secondary",
93
- className: withBaseName("next-button"),
94
- onClick: () => moveSlide("right"),
95
- children: /* @__PURE__ */ jsx(NextIcon, { size: 2 })
96
- }
97
- ),
98
- /* @__PURE__ */ jsx("div", { className: withBaseName("dots"), children: /* @__PURE__ */ jsx(
99
- RadioButtonGroup,
100
- {
101
- "aria-label": "Carousel buttons",
102
- onChange: handleRadioChange,
103
- value: `${selectedSlide}`,
104
- direction: "horizontal",
105
- children: Array.from({ length: slidesCount }, (_2, index) => ({
106
- value: `${index}`
107
- })).map((radio) => /* @__PURE__ */ createElement(RadioButton, { ...radio, key: radio.value }))
108
- }
109
- ) })
110
- ]
40
+ children: /* @__PURE__ */ jsx(
41
+ "section",
42
+ {
43
+ role: "region",
44
+ className: clsx(withBaseName(), {
45
+ [withBaseName(controlsPlacement)]: controlsPlacement === "bottom"
46
+ }),
47
+ "aria-roledescription": "carousel",
48
+ id,
49
+ ref,
50
+ ...rest,
51
+ children
52
+ }
53
+ )
111
54
  }
112
55
  );
113
56
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Carousel.js","sources":["../src/carousel/Carousel.tsx"],"sourcesContent":["import {\n Button,\n GridLayout,\n RadioButton,\n RadioButtonGroup,\n makePrefixer,\n useIcon,\n useId,\n} from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport {\n type ChangeEventHandler,\n Children,\n type HTMLAttributes,\n type ReactElement,\n forwardRef,\n useEffect,\n} from \"react\";\nimport { DeckLayout } from \"../deck-layout\";\nimport { useSlideSelection } from \"../utils\";\nimport type { CarouselSlideProps } from \"./CarouselSlide\";\n\nimport carouselCss from \"./Carousel.css\";\n\nconst withBaseName = makePrefixer(\"saltCarousel\");\n\nexport interface CarouselProps extends HTMLAttributes<HTMLDivElement> {\n /**\n * The initial Index enables you to select the active slide in the carousel.\n * Optional, default 0.\n **/\n initialIndex?: number;\n /**\n * The animation when the slides are shown.\n * Optional. Defaults to `slide`\n **/\n animation?: \"slide\" | \"fade\";\n /**\n * If this props is passed it will set the aria-label with value to the carousel container.\n * Optional. Defaults to undefined\n */\n carouselDescription?: string;\n /**\n * Collection of slides to render\n * Component must implement CarouselSlideProps. Mandatory.\n */\n children: Array<ReactElement<CarouselSlideProps>>;\n /**\n * This prop will enable compact / reduced width mode.\n * The navigation buttons would be part of indicators\n * Optional. Defaults to false\n **/\n compact?: boolean;\n /**\n * It sets the id for the Carousel Container.\n * String. Optional\n */\n id?: string;\n}\n\nexport const Carousel = forwardRef<HTMLDivElement, CarouselProps>(\n function Carousel(\n {\n initialIndex,\n animation = \"slide\",\n carouselDescription,\n children,\n className,\n compact,\n id: idProp,\n ...rest\n },\n ref,\n ) {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-carousel\",\n css: carouselCss,\n window: targetWindow,\n });\n const { NextIcon, PreviousIcon } = useIcon();\n const id = useId(idProp);\n const slidesCount = Children.count(children);\n\n const [_, selectedSlide, handleSlideSelection] =\n useSlideSelection(initialIndex);\n\n const moveSlide = (direction: \"left\" | \"right\") => {\n const moveLeft =\n selectedSlide === 0 ? slidesCount - 1 : selectedSlide - 1;\n const moveRight =\n selectedSlide === slidesCount - 1 ? 0 : selectedSlide + 1;\n const newSelection = direction === \"left\" ? moveLeft : moveRight;\n const newTransition = direction === \"left\" ? \"decrease\" : \"increase\";\n handleSlideSelection(newSelection, newTransition);\n };\n\n const handleRadioChange: ChangeEventHandler<HTMLInputElement> = ({\n target: { value },\n }) => {\n handleSlideSelection(Number(value));\n };\n\n useEffect(() => {\n if (process.env.NODE_ENV !== \"production\") {\n if (slidesCount < 1) {\n console.warn(\n \"Carousel component requires more than one children to render. At least two elements should be provided.\",\n );\n }\n }\n }, [slidesCount]);\n\n return (\n <GridLayout\n aria-label={carouselDescription}\n aria-roledescription=\"carousel\"\n id={id}\n role=\"region\"\n ref={ref}\n gap={0}\n columns={3}\n className={clsx(\n withBaseName(),\n compact && withBaseName(\"compact\"),\n className,\n )}\n {...rest}\n >\n <Button\n variant=\"secondary\"\n className={withBaseName(\"prev-button\")}\n onClick={() => moveSlide(\"left\")}\n >\n <PreviousIcon size={2} />\n </Button>\n <DeckLayout\n activeIndex={selectedSlide}\n animation={animation}\n className={withBaseName(\"slider\")}\n >\n {children}\n </DeckLayout>\n <Button\n variant=\"secondary\"\n className={withBaseName(\"next-button\")}\n onClick={() => moveSlide(\"right\")}\n >\n <NextIcon size={2} />\n </Button>\n <div className={withBaseName(\"dots\")}>\n <RadioButtonGroup\n aria-label=\"Carousel buttons\"\n onChange={handleRadioChange}\n value={`${selectedSlide}`}\n direction={\"horizontal\"}\n >\n {Array.from({ length: slidesCount }, (_, index) => ({\n value: `${index}`,\n })).map((radio) => (\n <RadioButton {...radio} key={radio.value} />\n ))}\n </RadioButtonGroup>\n </div>\n </GridLayout>\n );\n },\n);\n"],"names":["Carousel","carouselCss","_"],"mappings":"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"}
1
+ {"version":3,"file":"Carousel.js","sources":["../src/carousel/Carousel.tsx"],"sourcesContent":["import {\n type ResponsiveProp,\n makePrefixer,\n resolveResponsiveValue,\n useBreakpoint,\n useId,\n} from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport { type HTMLAttributes, forwardRef } from \"react\";\nimport carouselCss from \"./Carousel.css\";\nimport { CarouselProvider } from \"./CarouselContext\";\n\nconst withBaseName = makePrefixer(\"saltCarousel\");\n\nexport interface CarouselProps extends HTMLAttributes<HTMLDivElement> {\n /**\n * The initial Index enables you to select the active slide in the carousel.\n * Optional, default 0.\n **/\n defaultActiveSlideIndex?: number;\n /**\n * Controlled index of active slide in the carousel.\n **/\n activeSlideIndex?: number;\n /**\n * Set the placement of the CarouselControls relative to the CarouselSlider element. Defaults to `top`.\n */\n controlsPlacement?: \"top\" | \"bottom\";\n /**\n * Number of slides visible at a time.\n * Optional, default 1.\n **/\n visibleSlides?: ResponsiveProp<number>;\n}\n\nexport const Carousel = forwardRef<HTMLDivElement, CarouselProps>(\n function Carousel(\n {\n defaultActiveSlideIndex = 0,\n activeSlideIndex,\n visibleSlides: visibleSlidesProp = 1,\n children,\n controlsPlacement = \"top\",\n id: idProp,\n ...rest\n },\n ref,\n ) {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-carousel\",\n css: carouselCss,\n window: targetWindow,\n });\n const { matchedBreakpoints } = useBreakpoint();\n\n const visibleSlides = resolveResponsiveValue(\n visibleSlidesProp,\n matchedBreakpoints,\n );\n const id = useId(idProp);\n return (\n <CarouselProvider\n defaultActiveSlideIndex={defaultActiveSlideIndex}\n activeSlideIndex={activeSlideIndex}\n visibleSlides={visibleSlides}\n id={id}\n >\n <section\n role=\"region\"\n className={clsx(withBaseName(), {\n [withBaseName(controlsPlacement)]: controlsPlacement === \"bottom\",\n })}\n aria-roledescription=\"carousel\"\n id={id}\n ref={ref}\n {...rest}\n >\n {children}\n </section>\n </CarouselProvider>\n );\n },\n);\n"],"names":["Carousel","carouselCss"],"mappings":";;;;;;;;;AAcA,MAAM,YAAA,GAAe,aAAa,cAAc,CAAA;AAuBzC,MAAM,QAAW,GAAA,UAAA;AAAA,EACtB,SAASA,SACP,CAAA;AAAA,IACE,uBAA0B,GAAA,CAAA;AAAA,IAC1B,gBAAA;AAAA,IACA,eAAe,iBAAoB,GAAA,CAAA;AAAA,IACnC,QAAA;AAAA,IACA,iBAAoB,GAAA,KAAA;AAAA,IACpB,EAAI,EAAA,MAAA;AAAA,IACJ,GAAG;AAAA,KAEL,GACA,EAAA;AACA,IAAA,MAAM,eAAe,SAAU,EAAA;AAC/B,IAAyB,wBAAA,CAAA;AAAA,MACvB,MAAQ,EAAA,eAAA;AAAA,MACR,GAAK,EAAAC,QAAA;AAAA,MACL,MAAQ,EAAA;AAAA,KACT,CAAA;AACD,IAAM,MAAA,EAAE,kBAAmB,EAAA,GAAI,aAAc,EAAA;AAE7C,IAAA,MAAM,aAAgB,GAAA,sBAAA;AAAA,MACpB,iBAAA;AAAA,MACA;AAAA,KACF;AACA,IAAM,MAAA,EAAA,GAAK,MAAM,MAAM,CAAA;AACvB,IACE,uBAAA,GAAA;AAAA,MAAC,gBAAA;AAAA,MAAA;AAAA,QACC,uBAAA;AAAA,QACA,gBAAA;AAAA,QACA,aAAA;AAAA,QACA,EAAA;AAAA,QAEA,QAAA,kBAAA,GAAA;AAAA,UAAC,SAAA;AAAA,UAAA;AAAA,YACC,IAAK,EAAA,QAAA;AAAA,YACL,SAAA,EAAW,IAAK,CAAA,YAAA,EAAgB,EAAA;AAAA,cAC9B,CAAC,YAAA,CAAa,iBAAiB,CAAC,GAAG,iBAAsB,KAAA;AAAA,aAC1D,CAAA;AAAA,YACD,sBAAqB,EAAA,UAAA;AAAA,YACrB,EAAA;AAAA,YACA,GAAA;AAAA,YACC,GAAG,IAAA;AAAA,YAEH;AAAA;AAAA;AACH;AAAA,KACF;AAAA;AAGN;;;;"}
@@ -0,0 +1,58 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { createContext, useControlled } from '@salt-ds/core';
3
+ import { useReducer, useEffect } from 'react';
4
+ import { carouselReducer } from './CarouselReducer.js';
5
+
6
+ const CarouselStateContext = createContext(
7
+ "CarouselStateContext",
8
+ {
9
+ slides: /* @__PURE__ */ new Map(),
10
+ activeSlideIndex: 0,
11
+ visibleSlides: 1,
12
+ focusedSlideIndex: 0,
13
+ carouselId: void 0
14
+ }
15
+ );
16
+ const CarouselDispatchContext = createContext(
17
+ "CarouselDispatchContext",
18
+ () => {
19
+ return;
20
+ }
21
+ );
22
+ function CarouselProvider({
23
+ children,
24
+ activeSlideIndex: activeSlideIndexProp,
25
+ defaultActiveSlideIndex = 0,
26
+ visibleSlides = 1,
27
+ id
28
+ }) {
29
+ const [activeSlideIndex, setActiveSlideIndex] = useControlled({
30
+ controlled: activeSlideIndexProp,
31
+ default: defaultActiveSlideIndex,
32
+ name: "Carousel",
33
+ state: "activeSlideIndex"
34
+ });
35
+ const [state, dispatch] = useReducer(carouselReducer, {
36
+ slides: /* @__PURE__ */ new Map(),
37
+ focusedSlideIndex: activeSlideIndex,
38
+ activeSlideIndex,
39
+ visibleSlides,
40
+ carouselId: id
41
+ });
42
+ useEffect(() => {
43
+ dispatch({
44
+ type: "updateSlideCount",
45
+ payload: visibleSlides
46
+ });
47
+ }, [visibleSlides]);
48
+ useEffect(() => {
49
+ dispatch({
50
+ type: "moveToIndex",
51
+ payload: activeSlideIndex
52
+ });
53
+ }, [activeSlideIndex]);
54
+ return /* @__PURE__ */ jsx(CarouselStateContext.Provider, { value: state, children: /* @__PURE__ */ jsx(CarouselDispatchContext.Provider, { value: dispatch, children }) });
55
+ }
56
+
57
+ export { CarouselDispatchContext, CarouselProvider, CarouselStateContext };
58
+ //# sourceMappingURL=CarouselContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CarouselContext.js","sources":["../src/carousel/CarouselContext.tsx"],"sourcesContent":["import { createContext, useControlled } from \"@salt-ds/core\";\nimport { type ReactNode, useEffect, useReducer } from \"react\";\nimport {\n type CarouselReducerDispatch,\n type CarouselReducerState,\n carouselReducer,\n} from \"./CarouselReducer\";\n\nexport const CarouselStateContext = createContext<CarouselReducerState>(\n \"CarouselStateContext\",\n {\n slides: new Map(),\n activeSlideIndex: 0,\n visibleSlides: 1,\n focusedSlideIndex: 0,\n carouselId: undefined,\n },\n);\nexport const CarouselDispatchContext = createContext<CarouselReducerDispatch>(\n \"CarouselDispatchContext\",\n () => {\n return;\n },\n);\n\nexport function CarouselProvider({\n children,\n activeSlideIndex: activeSlideIndexProp,\n defaultActiveSlideIndex = 0,\n visibleSlides = 1,\n id,\n}: {\n children: ReactNode;\n activeSlideIndex?: number;\n defaultActiveSlideIndex?: number;\n visibleSlides?: number;\n id?: string;\n}) {\n const [activeSlideIndex, setActiveSlideIndex] = useControlled({\n controlled: activeSlideIndexProp,\n default: defaultActiveSlideIndex,\n name: \"Carousel\",\n state: \"activeSlideIndex\",\n });\n const [state, dispatch] = useReducer(carouselReducer, {\n slides: new Map(),\n focusedSlideIndex: activeSlideIndex,\n activeSlideIndex,\n visibleSlides,\n carouselId: id,\n });\n\n useEffect(() => {\n dispatch({\n type: \"updateSlideCount\",\n payload: visibleSlides,\n });\n }, [visibleSlides]);\n\n useEffect(() => {\n dispatch({\n type: \"moveToIndex\",\n payload: activeSlideIndex,\n });\n }, [activeSlideIndex]);\n\n return (\n <CarouselStateContext.Provider value={state}>\n <CarouselDispatchContext.Provider value={dispatch}>\n {children}\n </CarouselDispatchContext.Provider>\n </CarouselStateContext.Provider>\n );\n}\n"],"names":[],"mappings":";;;;;AAQO,MAAM,oBAAuB,GAAA,aAAA;AAAA,EAClC,sBAAA;AAAA,EACA;AAAA,IACE,MAAA,sBAAY,GAAI,EAAA;AAAA,IAChB,gBAAkB,EAAA,CAAA;AAAA,IAClB,aAAe,EAAA,CAAA;AAAA,IACf,iBAAmB,EAAA,CAAA;AAAA,IACnB,UAAY,EAAA,KAAA;AAAA;AAEhB;AACO,MAAM,uBAA0B,GAAA,aAAA;AAAA,EACrC,yBAAA;AAAA,EACA,MAAM;AACJ,IAAA;AAAA;AAEJ;AAEO,SAAS,gBAAiB,CAAA;AAAA,EAC/B,QAAA;AAAA,EACA,gBAAkB,EAAA,oBAAA;AAAA,EAClB,uBAA0B,GAAA,CAAA;AAAA,EAC1B,aAAgB,GAAA,CAAA;AAAA,EAChB;AACF,CAMG,EAAA;AACD,EAAA,MAAM,CAAC,gBAAA,EAAkB,mBAAmB,CAAA,GAAI,aAAc,CAAA;AAAA,IAC5D,UAAY,EAAA,oBAAA;AAAA,IACZ,OAAS,EAAA,uBAAA;AAAA,IACT,IAAM,EAAA,UAAA;AAAA,IACN,KAAO,EAAA;AAAA,GACR,CAAA;AACD,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,WAAW,eAAiB,EAAA;AAAA,IACpD,MAAA,sBAAY,GAAI,EAAA;AAAA,IAChB,iBAAmB,EAAA,gBAAA;AAAA,IACnB,gBAAA;AAAA,IACA,aAAA;AAAA,IACA,UAAY,EAAA;AAAA,GACb,CAAA;AAED,EAAA,SAAA,CAAU,MAAM;AACd,IAAS,QAAA,CAAA;AAAA,MACP,IAAM,EAAA,kBAAA;AAAA,MACN,OAAS,EAAA;AAAA,KACV,CAAA;AAAA,GACH,EAAG,CAAC,aAAa,CAAC,CAAA;AAElB,EAAA,SAAA,CAAU,MAAM;AACd,IAAS,QAAA,CAAA;AAAA,MACP,IAAM,EAAA,aAAA;AAAA,MACN,OAAS,EAAA;AAAA,KACV,CAAA;AAAA,GACH,EAAG,CAAC,gBAAgB,CAAC,CAAA;AAErB,EAAA,uBACG,GAAA,CAAA,oBAAA,CAAqB,QAArB,EAAA,EAA8B,KAAO,EAAA,KAAA,EACpC,QAAC,kBAAA,GAAA,CAAA,uBAAA,CAAwB,QAAxB,EAAA,EAAiC,KAAO,EAAA,QAAA,EACtC,UACH,CACF,EAAA,CAAA;AAEJ;;;;"}
@@ -0,0 +1,4 @@
1
+ var css_248z = ".saltCarouselControls {\n display: flex;\n gap: var(--salt-spacing-100);\n align-items: center;\n grid-area: controls;\n}\n.saltCarouselControls-container {\n display: flex;\n flex-flow: wrap;\n align-items: center;\n gap: var(--salt-spacing-100);\n justify-content: space-between;\n}\n.saltCarouselControls-container:last-child {\n margin-left: auto;\n}\n.saltCarouselControls-container h2 {\n margin: 0;\n}\n\n.saltCarouselControls-sr-only {\n display: none;\n}\n.saltCarouselControls:focus-within .saltCarouselControls-sr-only {\n display: block;\n position: fixed;\n top: 0;\n left: 0;\n transform: translate(-100%, -100%);\n}\n";
2
+
3
+ export { css_248z as default };
4
+ //# sourceMappingURL=CarouselControls.css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CarouselControls.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
@@ -0,0 +1,120 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { makePrefixer, useIcon, Button, Text } from '@salt-ds/core';
3
+ import { useComponentCssInjection } from '@salt-ds/styles';
4
+ import { useWindow } from '@salt-ds/window';
5
+ import { forwardRef, useContext, useState, useRef } from 'react';
6
+ import { CarouselStateContext, CarouselDispatchContext } from './CarouselContext.js';
7
+ import css_248z from './CarouselControls.css.js';
8
+
9
+ const withBaseName = makePrefixer("saltCarouselControls");
10
+ const CarouselControls = forwardRef(function CarouselControls2({
11
+ onPrevious,
12
+ onNext,
13
+ disabled,
14
+ className,
15
+ title,
16
+ labelPlacement = "right",
17
+ ...rest
18
+ }, ref) {
19
+ var _a;
20
+ const targetWindow = useWindow();
21
+ useComponentCssInjection({
22
+ testId: "salt-carousel-controls",
23
+ css: css_248z,
24
+ window: targetWindow
25
+ });
26
+ const { slides, carouselId, activeSlideIndex, visibleSlides } = useContext(CarouselStateContext);
27
+ const dispatch = useContext(CarouselDispatchContext);
28
+ const slideCount = slides.size;
29
+ const { NextIcon, PreviousIcon } = useIcon();
30
+ const [isFocused, setIsFocused] = useState(false);
31
+ function handleFocusCapture() {
32
+ !isFocused && setIsFocused(true);
33
+ }
34
+ function handleBlurCapture() {
35
+ isFocused && setIsFocused(false);
36
+ }
37
+ const prevButtonRef = useRef(null);
38
+ const nextButtonRef = useRef(null);
39
+ const slideIds = [...slides.keys()];
40
+ const currentId = slideIds[activeSlideIndex] || null;
41
+ const prevId = slideIds[activeSlideIndex - 1] || null;
42
+ const nextId = slideIds[activeSlideIndex + 1] || null;
43
+ const isOnFirstSlide = activeSlideIndex === 0;
44
+ const isOnLastSlide = activeSlideIndex === slideCount - visibleSlides;
45
+ const isAnnouncerOn = nextButtonRef.current === document.activeElement || prevButtonRef.current === document.activeElement;
46
+ const currentSlideDescription = visibleSlides === 1 && currentId && ((_a = slides.get(currentId)) == null ? void 0 : _a.slideDescription) || void 0;
47
+ const controlsLabel = slideCount >= 1 && /* @__PURE__ */ jsx(
48
+ Text,
49
+ {
50
+ as: "span",
51
+ "aria-live": isAnnouncerOn ? "polite" : void 0,
52
+ "aria-atomic": "false",
53
+ children: /* @__PURE__ */ jsxs("strong", { children: [
54
+ `${activeSlideIndex + 1} ${visibleSlides > 1 && slideCount > 1 ? ` - ${activeSlideIndex + visibleSlides}` : ""} of
55
+ ${slideCount}`,
56
+ /* @__PURE__ */ jsx("span", { className: "saltCarouselControls-sr-only", children: currentSlideDescription })
57
+ ] })
58
+ }
59
+ );
60
+ function handlePrevClick(event) {
61
+ if (!prevId) return;
62
+ dispatch({ type: "scroll", payload: prevId });
63
+ onPrevious == null ? void 0 : onPrevious(event, slideIds.indexOf(prevId));
64
+ }
65
+ function handleNextClick(event) {
66
+ if (!nextId) return;
67
+ dispatch({ type: "scroll", payload: nextId });
68
+ onNext == null ? void 0 : onNext(event, slideIds.indexOf(nextId));
69
+ }
70
+ return /* @__PURE__ */ jsxs("div", { className: withBaseName("container"), ref, ...rest, children: [
71
+ title,
72
+ /* @__PURE__ */ jsxs(
73
+ "div",
74
+ {
75
+ className: withBaseName(),
76
+ ref,
77
+ ...rest,
78
+ onFocusCapture: handleFocusCapture,
79
+ onBlurCapture: handleBlurCapture,
80
+ children: [
81
+ (labelPlacement === "left" || title) && controlsLabel,
82
+ /* @__PURE__ */ jsx(
83
+ Button,
84
+ {
85
+ ref: prevButtonRef,
86
+ focusableWhenDisabled: true,
87
+ appearance: "bordered",
88
+ sentiment: "neutral",
89
+ className: withBaseName("prev-button"),
90
+ onClick: handlePrevClick,
91
+ disabled: isOnFirstSlide || disabled,
92
+ "aria-controls": carouselId,
93
+ "aria-label": `Previous slide${visibleSlides > 1 ? "s" : ""}`,
94
+ children: /* @__PURE__ */ jsx(PreviousIcon, { "aria-hidden": true })
95
+ }
96
+ ),
97
+ /* @__PURE__ */ jsx(
98
+ Button,
99
+ {
100
+ ref: nextButtonRef,
101
+ focusableWhenDisabled: true,
102
+ appearance: "bordered",
103
+ sentiment: "neutral",
104
+ className: withBaseName("next-button"),
105
+ onClick: handleNextClick,
106
+ disabled: isOnLastSlide || disabled,
107
+ "aria-controls": carouselId,
108
+ "aria-label": `Next slide${visibleSlides > 1 ? "s" : ""}`,
109
+ children: /* @__PURE__ */ jsx(NextIcon, { "aria-hidden": true })
110
+ }
111
+ ),
112
+ labelPlacement === "right" && !title && controlsLabel
113
+ ]
114
+ }
115
+ )
116
+ ] });
117
+ });
118
+
119
+ export { CarouselControls };
120
+ //# sourceMappingURL=CarouselControls.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CarouselControls.js","sources":["../src/carousel/CarouselControls.tsx"],"sourcesContent":["import { Button, Text, makePrefixer, useIcon } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport {\n type HTMLAttributes,\n type MouseEvent,\n type ReactNode,\n type SyntheticEvent,\n forwardRef,\n useContext,\n useRef,\n useState,\n} from \"react\";\nimport {\n CarouselDispatchContext,\n CarouselStateContext,\n} from \"./CarouselContext\";\n\nimport carouselControlsCss from \"./CarouselControls.css\";\n\nconst withBaseName = makePrefixer(\"saltCarouselControls\");\n\nexport interface CarouselControlsProps\n extends Omit<HTMLAttributes<HTMLDivElement>, \"title\"> {\n /**\n * Callback when Back button is clicked.\n */\n onPrevious?: (\n event: SyntheticEvent<HTMLButtonElement>,\n index: number,\n ) => void;\n /**\n * Callback when Next button is clicked.\n */\n onNext?: (event: SyntheticEvent<HTMLButtonElement>, index: number) => void;\n /**\n * Location of the label relative to the controls.\n *\n * Either 'left', or 'right'`.\n */\n labelPlacement?: \"left\" | \"right\";\n /**\n * If `true`, the carousel controls will be disabled.\n * **/\n disabled?: boolean;\n /**\n * The title of the carousel that accompanies the controls.\n */\n title?: ReactNode;\n}\n\nexport const CarouselControls = forwardRef<\n HTMLDivElement,\n CarouselControlsProps\n>(function CarouselControls(\n {\n onPrevious,\n onNext,\n disabled,\n className,\n title,\n labelPlacement = \"right\",\n ...rest\n },\n ref,\n) {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-carousel-controls\",\n css: carouselControlsCss,\n window: targetWindow,\n });\n const { slides, carouselId, activeSlideIndex, visibleSlides } =\n useContext(CarouselStateContext);\n const dispatch = useContext(CarouselDispatchContext);\n\n const slideCount = slides.size;\n const { NextIcon, PreviousIcon } = useIcon();\n\n const [isFocused, setIsFocused] = useState(false);\n function handleFocusCapture() {\n !isFocused && setIsFocused(true);\n }\n function handleBlurCapture() {\n isFocused && setIsFocused(false);\n }\n\n const prevButtonRef = useRef<HTMLButtonElement>(null);\n const nextButtonRef = useRef<HTMLButtonElement>(null);\n const slideIds = [...slides.keys()];\n\n const currentId = slideIds[activeSlideIndex] || null;\n const prevId = slideIds[activeSlideIndex - 1] || null;\n const nextId = slideIds[activeSlideIndex + 1] || null;\n\n const isOnFirstSlide = activeSlideIndex === 0;\n const isOnLastSlide = activeSlideIndex === slideCount - visibleSlides;\n\n const isAnnouncerOn =\n nextButtonRef.current === document.activeElement ||\n prevButtonRef.current === document.activeElement;\n\n const currentSlideDescription =\n (visibleSlides === 1 &&\n currentId &&\n slides.get(currentId)?.slideDescription) ||\n undefined;\n\n const controlsLabel = slideCount >= 1 && (\n <Text\n as=\"span\"\n aria-live={isAnnouncerOn ? \"polite\" : undefined}\n aria-atomic=\"false\"\n >\n <strong>\n {`${activeSlideIndex + 1} ${visibleSlides > 1 && slideCount > 1 ? ` - ${activeSlideIndex + visibleSlides}` : \"\"} of\n ${slideCount}`}\n\n {\n <span className=\"saltCarouselControls-sr-only\">\n {currentSlideDescription}\n </span>\n }\n </strong>\n </Text>\n );\n\n function handlePrevClick(event: MouseEvent<HTMLButtonElement>) {\n if (!prevId) return;\n dispatch({ type: \"scroll\", payload: prevId });\n onPrevious?.(event, slideIds.indexOf(prevId));\n }\n\n function handleNextClick(event: MouseEvent<HTMLButtonElement>) {\n if (!nextId) return;\n dispatch({ type: \"scroll\", payload: nextId });\n onNext?.(event, slideIds.indexOf(nextId));\n }\n\n return (\n <div className={withBaseName(\"container\")} ref={ref} {...rest}>\n {title}\n <div\n className={withBaseName()}\n ref={ref}\n {...rest}\n onFocusCapture={handleFocusCapture}\n onBlurCapture={handleBlurCapture}\n >\n {(labelPlacement === \"left\" || title) && controlsLabel}\n <Button\n ref={prevButtonRef}\n focusableWhenDisabled\n appearance=\"bordered\"\n sentiment=\"neutral\"\n className={withBaseName(\"prev-button\")}\n onClick={handlePrevClick}\n disabled={isOnFirstSlide || disabled}\n aria-controls={carouselId}\n aria-label={`Previous slide${visibleSlides > 1 ? \"s\" : \"\"}`}\n >\n <PreviousIcon aria-hidden />\n </Button>\n <Button\n ref={nextButtonRef}\n focusableWhenDisabled\n appearance=\"bordered\"\n sentiment=\"neutral\"\n className={withBaseName(\"next-button\")}\n onClick={handleNextClick}\n disabled={isOnLastSlide || disabled}\n aria-controls={carouselId}\n aria-label={`Next slide${visibleSlides > 1 ? \"s\" : \"\"}`}\n >\n <NextIcon aria-hidden />\n </Button>\n {labelPlacement === \"right\" && !title && controlsLabel}\n </div>\n </div>\n );\n});\n"],"names":["CarouselControls","carouselControlsCss"],"mappings":";;;;;;;;AAoBA,MAAM,YAAA,GAAe,aAAa,sBAAsB,CAAA;AA+B3C,MAAA,gBAAA,GAAmB,UAG9B,CAAA,SAASA,iBACT,CAAA;AAAA,EACE,UAAA;AAAA,EACA,MAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA,KAAA;AAAA,EACA,cAAiB,GAAA,OAAA;AAAA,EACjB,GAAG;AACL,CAAA,EACA,GACA,EAAA;AAjEF,EAAA,IAAA,EAAA;AAkEE,EAAA,MAAM,eAAe,SAAU,EAAA;AAC/B,EAAyB,wBAAA,CAAA;AAAA,IACvB,MAAQ,EAAA,wBAAA;AAAA,IACR,GAAK,EAAAC,QAAA;AAAA,IACL,MAAQ,EAAA;AAAA,GACT,CAAA;AACD,EAAA,MAAM,EAAE,MAAQ,EAAA,UAAA,EAAY,kBAAkB,aAAc,EAAA,GAC1D,WAAW,oBAAoB,CAAA;AACjC,EAAM,MAAA,QAAA,GAAW,WAAW,uBAAuB,CAAA;AAEnD,EAAA,MAAM,aAAa,MAAO,CAAA,IAAA;AAC1B,EAAA,MAAM,EAAE,QAAA,EAAU,YAAa,EAAA,GAAI,OAAQ,EAAA;AAE3C,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,SAAS,KAAK,CAAA;AAChD,EAAA,SAAS,kBAAqB,GAAA;AAC5B,IAAC,CAAA,SAAA,IAAa,aAAa,IAAI,CAAA;AAAA;AAEjC,EAAA,SAAS,iBAAoB,GAAA;AAC3B,IAAA,SAAA,IAAa,aAAa,KAAK,CAAA;AAAA;AAGjC,EAAM,MAAA,aAAA,GAAgB,OAA0B,IAAI,CAAA;AACpD,EAAM,MAAA,aAAA,GAAgB,OAA0B,IAAI,CAAA;AACpD,EAAA,MAAM,QAAW,GAAA,CAAC,GAAG,MAAA,CAAO,MAAM,CAAA;AAElC,EAAM,MAAA,SAAA,GAAY,QAAS,CAAA,gBAAgB,CAAK,IAAA,IAAA;AAChD,EAAA,MAAM,MAAS,GAAA,QAAA,CAAS,gBAAmB,GAAA,CAAC,CAAK,IAAA,IAAA;AACjD,EAAA,MAAM,MAAS,GAAA,QAAA,CAAS,gBAAmB,GAAA,CAAC,CAAK,IAAA,IAAA;AAEjD,EAAA,MAAM,iBAAiB,gBAAqB,KAAA,CAAA;AAC5C,EAAM,MAAA,aAAA,GAAgB,qBAAqB,UAAa,GAAA,aAAA;AAExD,EAAA,MAAM,gBACJ,aAAc,CAAA,OAAA,KAAY,SAAS,aACnC,IAAA,aAAA,CAAc,YAAY,QAAS,CAAA,aAAA;AAErC,EAAM,MAAA,uBAAA,GACH,kBAAkB,CACjB,IAAA,SAAA,KAAA,CACA,YAAO,GAAI,CAAA,SAAS,CAApB,KAAA,IAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAuB,gBACzB,CAAA,IAAA,KAAA,CAAA;AAEF,EAAM,MAAA,aAAA,GAAgB,cAAc,CAClC,oBAAA,GAAA;AAAA,IAAC,IAAA;AAAA,IAAA;AAAA,MACC,EAAG,EAAA,MAAA;AAAA,MACH,WAAA,EAAW,gBAAgB,QAAW,GAAA,KAAA,CAAA;AAAA,MACtC,aAAY,EAAA,OAAA;AAAA,MAEZ,+BAAC,QACE,EAAA,EAAA,QAAA,EAAA;AAAA,QAAG,CAAA,EAAA,gBAAA,GAAmB,CAAC,CAAA,CAAA,EAAI,aAAgB,GAAA,CAAA,IAAK,UAAa,GAAA,CAAA,GAAI,CAAM,GAAA,EAAA,gBAAA,GAAmB,aAAa,CAAA,CAAA,GAAK,EAAE,CAAA;AAAA,QAAA,EAC7G,UAAU,CAAA,CAAA;AAAA,wBAGT,GAAA,CAAA,MAAA,EAAA,EAAK,SAAU,EAAA,8BAAA,EACb,QACH,EAAA,uBAAA,EAAA;AAAA,OAEJ,EAAA;AAAA;AAAA,GACF;AAGF,EAAA,SAAS,gBAAgB,KAAsC,EAAA;AAC7D,IAAA,IAAI,CAAC,MAAQ,EAAA;AACb,IAAA,QAAA,CAAS,EAAE,IAAA,EAAM,QAAU,EAAA,OAAA,EAAS,QAAQ,CAAA;AAC5C,IAAa,UAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,UAAA,CAAA,KAAA,EAAO,QAAS,CAAA,OAAA,CAAQ,MAAM,CAAA,CAAA;AAAA;AAG7C,EAAA,SAAS,gBAAgB,KAAsC,EAAA;AAC7D,IAAA,IAAI,CAAC,MAAQ,EAAA;AACb,IAAA,QAAA,CAAS,EAAE,IAAA,EAAM,QAAU,EAAA,OAAA,EAAS,QAAQ,CAAA;AAC5C,IAAS,MAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,MAAA,CAAA,KAAA,EAAO,QAAS,CAAA,OAAA,CAAQ,MAAM,CAAA,CAAA;AAAA;AAGzC,EACE,uBAAA,IAAA,CAAC,SAAI,SAAW,EAAA,YAAA,CAAa,WAAW,CAAG,EAAA,GAAA,EAAW,GAAG,IACtD,EAAA,QAAA,EAAA;AAAA,IAAA,KAAA;AAAA,oBACD,IAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,WAAW,YAAa,EAAA;AAAA,QACxB,GAAA;AAAA,QACC,GAAG,IAAA;AAAA,QACJ,cAAgB,EAAA,kBAAA;AAAA,QAChB,aAAe,EAAA,iBAAA;AAAA,QAEb,QAAA,EAAA;AAAA,UAAA,CAAA,cAAA,KAAmB,UAAU,KAAU,KAAA,aAAA;AAAA,0BACzC,GAAA;AAAA,YAAC,MAAA;AAAA,YAAA;AAAA,cACC,GAAK,EAAA,aAAA;AAAA,cACL,qBAAqB,EAAA,IAAA;AAAA,cACrB,UAAW,EAAA,UAAA;AAAA,cACX,SAAU,EAAA,SAAA;AAAA,cACV,SAAA,EAAW,aAAa,aAAa,CAAA;AAAA,cACrC,OAAS,EAAA,eAAA;AAAA,cACT,UAAU,cAAkB,IAAA,QAAA;AAAA,cAC5B,eAAe,EAAA,UAAA;AAAA,cACf,YAAY,EAAA,CAAA,cAAA,EAAiB,aAAgB,GAAA,CAAA,GAAI,MAAM,EAAE,CAAA,CAAA;AAAA,cAEzD,QAAA,kBAAA,GAAA,CAAC,YAAa,EAAA,EAAA,aAAA,EAAW,IAAC,EAAA;AAAA;AAAA,WAC5B;AAAA,0BACA,GAAA;AAAA,YAAC,MAAA;AAAA,YAAA;AAAA,cACC,GAAK,EAAA,aAAA;AAAA,cACL,qBAAqB,EAAA,IAAA;AAAA,cACrB,UAAW,EAAA,UAAA;AAAA,cACX,SAAU,EAAA,SAAA;AAAA,cACV,SAAA,EAAW,aAAa,aAAa,CAAA;AAAA,cACrC,OAAS,EAAA,eAAA;AAAA,cACT,UAAU,aAAiB,IAAA,QAAA;AAAA,cAC3B,eAAe,EAAA,UAAA;AAAA,cACf,YAAY,EAAA,CAAA,UAAA,EAAa,aAAgB,GAAA,CAAA,GAAI,MAAM,EAAE,CAAA,CAAA;AAAA,cAErD,QAAA,kBAAA,GAAA,CAAC,QAAS,EAAA,EAAA,aAAA,EAAW,IAAC,EAAA;AAAA;AAAA,WACxB;AAAA,UACC,cAAA,KAAmB,OAAW,IAAA,CAAC,KAAS,IAAA;AAAA;AAAA;AAAA;AAC3C,GACF,EAAA,CAAA;AAEJ,CAAC;;;;"}
@@ -0,0 +1,75 @@
1
+ function carouselReducer(state, action) {
2
+ switch (action.type) {
3
+ case "register": {
4
+ const { slides } = state;
5
+ const [id, { element, slideDescription }] = action.payload;
6
+ const newSlides = new Map(slides);
7
+ newSlides.set(id, { element, slideDescription });
8
+ return {
9
+ ...state,
10
+ slides: newSlides
11
+ };
12
+ }
13
+ case "unregister": {
14
+ const { slides } = state;
15
+ const id = action.payload;
16
+ if (!slides.has(id)) {
17
+ return state;
18
+ }
19
+ const newSlides = new Map(slides);
20
+ newSlides.delete(id);
21
+ return {
22
+ ...state,
23
+ slides: newSlides
24
+ };
25
+ }
26
+ // moves the first visible item
27
+ case "move": {
28
+ const { slides } = state;
29
+ const id = action.payload;
30
+ if (!slides.has(id)) {
31
+ return state;
32
+ }
33
+ const slideIds = [...slides.keys()];
34
+ const index = slideIds.indexOf(id || slideIds[0]);
35
+ return {
36
+ ...state,
37
+ activeSlideIndex: index
38
+ };
39
+ }
40
+ case "moveToIndex": {
41
+ const { slides } = state;
42
+ const index = action.payload;
43
+ if (index === -1 || index > slides.size) {
44
+ return state;
45
+ }
46
+ return {
47
+ ...state,
48
+ focusedSlideIndex: index
49
+ };
50
+ }
51
+ case "updateSlideCount": {
52
+ const visibleSlides = action.payload;
53
+ return { ...state, visibleSlides };
54
+ }
55
+ case "scroll": {
56
+ const id = action.payload;
57
+ const { slides } = state;
58
+ const focusedSlideIndex = [...slides.keys()].indexOf(id);
59
+ if (focusedSlideIndex === -1) {
60
+ return state;
61
+ }
62
+ return {
63
+ ...state,
64
+ focusedSlideIndex
65
+ };
66
+ }
67
+ default: {
68
+ const exhaustiveCheck = action;
69
+ throw new Error(`Action of type ${exhaustiveCheck} does not exist`);
70
+ }
71
+ }
72
+ }
73
+
74
+ export { carouselReducer };
75
+ //# sourceMappingURL=CarouselReducer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CarouselReducer.js","sources":["../src/carousel/CarouselReducer.ts"],"sourcesContent":["import type { Dispatch } from \"react\";\n\nimport type { CarouselSlideId, CarouselSlideMeta } from \"./CarouselSlide\";\n\nexport interface CarouselReducerState {\n slides: Map<CarouselSlideId, CarouselSlideMeta>;\n activeSlideIndex: number;\n visibleSlides: number;\n focusedSlideIndex: number;\n carouselId?: string;\n}\nexport type CarouselReducerAction =\n | { type: \"register\"; payload: [CarouselSlideId, CarouselSlideMeta] }\n | { type: \"unregister\"; payload: CarouselSlideId }\n | { type: \"updateSlideCount\"; payload: number }\n | { type: \"move\"; payload: CarouselSlideId }\n | { type: \"moveToIndex\"; payload: number }\n | { type: \"scroll\"; payload: CarouselSlideId };\n\nexport type CarouselReducerDispatch = Dispatch<CarouselReducerAction>;\n\nexport function carouselReducer(\n state: CarouselReducerState,\n action: CarouselReducerAction,\n) {\n switch (action.type) {\n case \"register\": {\n const { slides } = state;\n const [id, { element, slideDescription }] = action.payload;\n const newSlides = new Map(slides);\n newSlides.set(id, { element, slideDescription });\n return {\n ...state,\n slides: newSlides,\n };\n }\n case \"unregister\": {\n const { slides } = state;\n const id = action.payload;\n if (!slides.has(id)) {\n return state;\n }\n const newSlides = new Map(slides);\n newSlides.delete(id);\n return {\n ...state,\n slides: newSlides,\n };\n }\n // moves the first visible item\n case \"move\": {\n const { slides } = state;\n const id = action.payload;\n if (!slides.has(id)) {\n return state;\n }\n const slideIds = [...slides.keys()];\n const index = slideIds.indexOf(id || slideIds[0]);\n return {\n ...state,\n activeSlideIndex: index,\n };\n }\n case \"moveToIndex\": {\n const { slides } = state;\n\n const index = action.payload;\n\n if (index === -1 || index > slides.size) {\n return state;\n }\n\n return {\n ...state,\n focusedSlideIndex: index,\n };\n }\n case \"updateSlideCount\": {\n const visibleSlides = action.payload;\n\n return { ...state, visibleSlides: visibleSlides };\n }\n\n case \"scroll\": {\n const id = action.payload;\n const { slides } = state;\n\n const focusedSlideIndex = [...slides.keys()].indexOf(id);\n\n if (focusedSlideIndex === -1) {\n return state;\n }\n\n return {\n ...state,\n focusedSlideIndex,\n };\n }\n default: {\n const exhaustiveCheck: never = action;\n throw new Error(`Action of type ${exhaustiveCheck} does not exist`);\n }\n }\n}\n"],"names":[],"mappings":"AAqBgB,SAAA,eAAA,CACd,OACA,MACA,EAAA;AACA,EAAA,QAAQ,OAAO,IAAM;AAAA,IACnB,KAAK,UAAY,EAAA;AACf,MAAM,MAAA,EAAE,QAAW,GAAA,KAAA;AACnB,MAAA,MAAM,CAAC,EAAI,EAAA,EAAE,SAAS,gBAAiB,EAAC,IAAI,MAAO,CAAA,OAAA;AACnD,MAAM,MAAA,SAAA,GAAY,IAAI,GAAA,CAAI,MAAM,CAAA;AAChC,MAAA,SAAA,CAAU,GAAI,CAAA,EAAA,EAAI,EAAE,OAAA,EAAS,kBAAkB,CAAA;AAC/C,MAAO,OAAA;AAAA,QACL,GAAG,KAAA;AAAA,QACH,MAAQ,EAAA;AAAA,OACV;AAAA;AACF,IACA,KAAK,YAAc,EAAA;AACjB,MAAM,MAAA,EAAE,QAAW,GAAA,KAAA;AACnB,MAAA,MAAM,KAAK,MAAO,CAAA,OAAA;AAClB,MAAA,IAAI,CAAC,MAAA,CAAO,GAAI,CAAA,EAAE,CAAG,EAAA;AACnB,QAAO,OAAA,KAAA;AAAA;AAET,MAAM,MAAA,SAAA,GAAY,IAAI,GAAA,CAAI,MAAM,CAAA;AAChC,MAAA,SAAA,CAAU,OAAO,EAAE,CAAA;AACnB,MAAO,OAAA;AAAA,QACL,GAAG,KAAA;AAAA,QACH,MAAQ,EAAA;AAAA,OACV;AAAA;AACF;AAAA,IAEA,KAAK,MAAQ,EAAA;AACX,MAAM,MAAA,EAAE,QAAW,GAAA,KAAA;AACnB,MAAA,MAAM,KAAK,MAAO,CAAA,OAAA;AAClB,MAAA,IAAI,CAAC,MAAA,CAAO,GAAI,CAAA,EAAE,CAAG,EAAA;AACnB,QAAO,OAAA,KAAA;AAAA;AAET,MAAA,MAAM,QAAW,GAAA,CAAC,GAAG,MAAA,CAAO,MAAM,CAAA;AAClC,MAAA,MAAM,QAAQ,QAAS,CAAA,OAAA,CAAQ,EAAM,IAAA,QAAA,CAAS,CAAC,CAAC,CAAA;AAChD,MAAO,OAAA;AAAA,QACL,GAAG,KAAA;AAAA,QACH,gBAAkB,EAAA;AAAA,OACpB;AAAA;AACF,IACA,KAAK,aAAe,EAAA;AAClB,MAAM,MAAA,EAAE,QAAW,GAAA,KAAA;AAEnB,MAAA,MAAM,QAAQ,MAAO,CAAA,OAAA;AAErB,MAAA,IAAI,KAAU,KAAA,CAAA,CAAA,IAAM,KAAQ,GAAA,MAAA,CAAO,IAAM,EAAA;AACvC,QAAO,OAAA,KAAA;AAAA;AAGT,MAAO,OAAA;AAAA,QACL,GAAG,KAAA;AAAA,QACH,iBAAmB,EAAA;AAAA,OACrB;AAAA;AACF,IACA,KAAK,kBAAoB,EAAA;AACvB,MAAA,MAAM,gBAAgB,MAAO,CAAA,OAAA;AAE7B,MAAO,OAAA,EAAE,GAAG,KAAA,EAAO,aAA6B,EAAA;AAAA;AAClD,IAEA,KAAK,QAAU,EAAA;AACb,MAAA,MAAM,KAAK,MAAO,CAAA,OAAA;AAClB,MAAM,MAAA,EAAE,QAAW,GAAA,KAAA;AAEnB,MAAM,MAAA,iBAAA,GAAoB,CAAC,GAAG,MAAA,CAAO,MAAM,CAAA,CAAE,QAAQ,EAAE,CAAA;AAEvD,MAAA,IAAI,sBAAsB,CAAI,CAAA,EAAA;AAC5B,QAAO,OAAA,KAAA;AAAA;AAGT,MAAO,OAAA;AAAA,QACL,GAAG,KAAA;AAAA,QACH;AAAA,OACF;AAAA;AACF,IACA,SAAS;AACP,MAAA,MAAM,eAAyB,GAAA,MAAA;AAC/B,MAAA,MAAM,IAAI,KAAA,CAAM,CAAkB,eAAA,EAAA,eAAe,CAAiB,eAAA,CAAA,CAAA;AAAA;AACpE;AAEJ;;;;"}
@@ -0,0 +1,4 @@
1
+ var css_248z = ".saltCarouselSlide {\n scroll-snap-align: start;\n display: flex;\n flex-direction: column;\n flex: 0 0 auto;\n box-sizing: border-box;\n width: var(--carousel-slide-width, 100%);\n gap: var(--salt-spacing-200);\n}\n.saltCarouselSlide:focus-visible {\n outline: var(--salt-focused-outline);\n outline-offset: calc(0px - var(--salt-focused-outlineWidth));\n}\n\n.saltCarouselSlide-actions {\n display: none;\n}\n\n.saltCarouselSlide-sr-only {\n position: fixed;\n top: 0;\n left: 0;\n transform: translate(-100%, -100%);\n}\n\n.saltCarouselSlide-actions.saltCarouselSlide-visible {\n display: flex;\n}\n.saltCarouselSlide-container {\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n gap: var(--salt-spacing-200);\n padding-left: var(--salt-spacing-25);\n padding-bottom: var(--salt-spacing-25);\n flex-grow: 1;\n}\n.saltCarouselSlide-content {\n display: flex;\n flex-direction: column;\n flex-grow: 1;\n gap: var(--salt-spacing-100);\n}\n.saltCarouselSlide-card {\n padding: var(--salt-spacing-200);\n padding-top: 0;\n}\n.saltCarouselSlide-content h2,\n.saltCarouselSlide-content h3 {\n margin: 0;\n}\n.saltCarouselSlide-bordered {\n border: var(--salt-size-border) var(--salt-container-borderStyle) var(--salt-container-primary-borderColor);\n border-radius: var(--salt-palette-corner, 0);\n overflow: hidden;\n}\n";
2
+
3
+ export { css_248z as default };
4
+ //# sourceMappingURL=CarouselSlide.css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CarouselSlide.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}