@salt-ds/lab 1.0.0-alpha.65 → 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 (53) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/css/salt-lab.css +111 -16
  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 -2
  23. package/dist-cjs/index.js.map +1 -1
  24. package/dist-es/carousel/Carousel.css.js +1 -1
  25. package/dist-es/carousel/Carousel.js +32 -89
  26. package/dist-es/carousel/Carousel.js.map +1 -1
  27. package/dist-es/carousel/CarouselContext.js +58 -0
  28. package/dist-es/carousel/CarouselContext.js.map +1 -0
  29. package/dist-es/carousel/CarouselControls.css.js +4 -0
  30. package/dist-es/carousel/CarouselControls.css.js.map +1 -0
  31. package/dist-es/carousel/CarouselControls.js +120 -0
  32. package/dist-es/carousel/CarouselControls.js.map +1 -0
  33. package/dist-es/carousel/CarouselReducer.js +75 -0
  34. package/dist-es/carousel/CarouselReducer.js.map +1 -0
  35. package/dist-es/carousel/CarouselSlide.css.js +4 -0
  36. package/dist-es/carousel/CarouselSlide.css.js.map +1 -0
  37. package/dist-es/carousel/CarouselSlide.js +96 -46
  38. package/dist-es/carousel/CarouselSlide.js.map +1 -1
  39. package/dist-es/carousel/CarouselSlider.css.js +4 -0
  40. package/dist-es/carousel/CarouselSlider.css.js.map +1 -0
  41. package/dist-es/carousel/CarouselSlider.js +91 -0
  42. package/dist-es/carousel/CarouselSlider.js.map +1 -0
  43. package/dist-es/index.js +3 -1
  44. package/dist-es/index.js.map +1 -1
  45. package/dist-types/carousel/Carousel.d.ts +10 -23
  46. package/dist-types/carousel/CarouselContext.d.ts +11 -0
  47. package/dist-types/carousel/CarouselControls.d.ts +26 -0
  48. package/dist-types/carousel/CarouselReducer.d.ts +30 -0
  49. package/dist-types/carousel/CarouselSlide.d.ts +31 -8
  50. package/dist-types/carousel/CarouselSlider.d.ts +13 -0
  51. package/dist-types/carousel/index.d.ts +2 -0
  52. package/dist-types/utils/index.d.ts +1 -1
  53. package/package.json +2 -2
@@ -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":"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"}
@@ -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":";;;;"}
@@ -1,56 +1,106 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
- import { makePrefixer } from '@salt-ds/core';
3
- import { forwardRef, useRef } from 'react';
2
+ import { makePrefixer, useIdMemo, useId, useForkRef } from '@salt-ds/core';
3
+ import { useComponentCssInjection } from '@salt-ds/styles';
4
+ import { useWindow } from '@salt-ds/window';
4
5
  import { clsx } from 'clsx';
6
+ import { forwardRef, useContext, useRef, useEffect } from 'react';
7
+ import { CarouselDispatchContext, CarouselStateContext } from './CarouselContext.js';
8
+ import css_248z from './CarouselSlide.css.js';
5
9
 
6
10
  const withBaseName = makePrefixer("saltCarouselSlide");
7
11
  const CarouselSlide = forwardRef(
8
- function CarouselSlide2({ ButtonBar, Media, description, title, contentAlignment }, ref) {
9
- const buttonBarRef = useRef(null);
10
- return /* @__PURE__ */ jsxs("div", { ref, children: [
11
- Media && /* @__PURE__ */ jsx("div", { className: withBaseName("mediaContainer"), children: Media }),
12
- /* @__PURE__ */ jsxs("div", { className: withBaseName("fixedContainer"), ref: buttonBarRef, children: [
13
- /* @__PURE__ */ jsxs(
14
- "div",
12
+ function CarouselSlide2({
13
+ actions,
14
+ appearance,
15
+ media,
16
+ header,
17
+ children,
18
+ "aria-labelledby": ariaLabelledBy,
19
+ style,
20
+ id: idProp,
21
+ ...rest
22
+ }, refProp) {
23
+ const targetWindow = useWindow();
24
+ useComponentCssInjection({
25
+ testId: "salt-carousel-slide",
26
+ css: css_248z,
27
+ window: targetWindow
28
+ });
29
+ const dispatch = useContext(CarouselDispatchContext);
30
+ const { slides, visibleSlides, activeSlideIndex } = useContext(CarouselStateContext);
31
+ const slideRef = useRef(null);
32
+ const headerRef = useRef(null);
33
+ const id = useIdMemo(idProp);
34
+ const announcerId = useId();
35
+ const slideCount = slides.size;
36
+ useEffect(() => {
37
+ var _a;
38
+ if (!slideRef.current) return;
39
+ dispatch({
40
+ type: "register",
41
+ payload: [
42
+ id,
15
43
  {
16
- className: clsx({
17
- [withBaseName("textContainer")]: contentAlignment === "center",
18
- [withBaseName("textContainerLeft")]: contentAlignment === "left"
19
- }),
20
- children: [
21
- title && /* @__PURE__ */ jsx(
22
- "div",
23
- {
24
- "aria-level": 1,
25
- className: withBaseName("titleContainer"),
26
- role: "heading",
27
- children: title
28
- }
29
- ),
30
- description && /* @__PURE__ */ jsx("div", { className: withBaseName("descriptionContainer"), children: description })
31
- ]
44
+ element: slideRef.current,
45
+ slideDescription: (_a = headerRef == null ? void 0 : headerRef.current) == null ? void 0 : _a.innerText
32
46
  }
33
- ),
34
- ButtonBar && /* @__PURE__ */ jsx(
35
- "div",
36
- {
37
- className: clsx({
38
- [withBaseName("buttonBarOverride")]: contentAlignment === "center",
39
- [withBaseName("buttonBarOverrideLeft")]: contentAlignment === "left"
40
- }),
41
- children: /* @__PURE__ */ jsx(
42
- ButtonBar,
43
- {
44
- className: clsx({
45
- [withBaseName("buttonBarContainer")]: contentAlignment === "center",
46
- [withBaseName("buttonBarContainerLeft")]: contentAlignment === "left"
47
- })
48
- }
49
- )
50
- }
51
- )
52
- ] })
53
- ] });
47
+ ]
48
+ });
49
+ return () => dispatch({ type: "unregister", payload: id });
50
+ }, [dispatch, id]);
51
+ const SlideStyles = {
52
+ "--carousel-slide-width": visibleSlides > 1 ? `calc((100% / ${visibleSlides}) - var(--salt-spacing-200)/${visibleSlides})` : void 0,
53
+ ...style
54
+ };
55
+ const ref = useForkRef(refProp, slideRef);
56
+ const slideIds = [...slides.keys()];
57
+ const index = slideIds.indexOf(id || slideIds[0]);
58
+ const helperText = `${index + 1} of ${slideCount}`;
59
+ const isVisible = index >= activeSlideIndex && index < activeSlideIndex + visibleSlides;
60
+ return /* @__PURE__ */ jsxs(
61
+ "div",
62
+ {
63
+ role: "group",
64
+ "aria-roledescription": "slide",
65
+ "aria-labelledby": clsx(ariaLabelledBy, announcerId),
66
+ id,
67
+ className: clsx(withBaseName(), {
68
+ [withBaseName("bordered")]: appearance === "bordered"
69
+ }),
70
+ style: SlideStyles,
71
+ tabIndex: isVisible ? 0 : -1,
72
+ hidden: !isVisible,
73
+ ...rest,
74
+ ref,
75
+ children: [
76
+ media,
77
+ children && /* @__PURE__ */ jsxs(
78
+ "div",
79
+ {
80
+ className: clsx(withBaseName("container"), {
81
+ [withBaseName("card")]: appearance === "bordered"
82
+ }),
83
+ children: [
84
+ /* @__PURE__ */ jsxs("div", { className: withBaseName("content"), children: [
85
+ isVisible && /* @__PURE__ */ jsx(
86
+ "span",
87
+ {
88
+ id: announcerId,
89
+ className: withBaseName("sr-only"),
90
+ "aria-hidden": "true",
91
+ children: helperText
92
+ }
93
+ ),
94
+ /* @__PURE__ */ jsx("div", { ref: headerRef, children: header }),
95
+ /* @__PURE__ */ jsx("div", { children })
96
+ ] }),
97
+ isVisible && actions
98
+ ]
99
+ }
100
+ )
101
+ ]
102
+ }
103
+ );
54
104
  }
55
105
  );
56
106
 
@@ -1 +1 @@
1
- {"version":3,"file":"CarouselSlide.js","sources":["../src/carousel/CarouselSlide.tsx"],"sourcesContent":["import { makePrefixer } from \"@salt-ds/core\";\nimport {\n type ElementType,\n type HTMLAttributes,\n type ReactElement,\n forwardRef,\n useRef,\n} from \"react\";\n\nimport { clsx } from \"clsx\";\n\nexport interface CarouselSlideProps extends HTMLAttributes<HTMLDivElement> {\n ButtonBar?: ElementType;\n Media: ReactElement;\n description?: string;\n title?: string;\n contentAlignment?: \"center\" | \"left\" | \"right\";\n}\n\nconst withBaseName = makePrefixer(\"saltCarouselSlide\");\n\nexport const CarouselSlide = forwardRef<HTMLDivElement, CarouselSlideProps>(\n function CarouselSlide(\n { ButtonBar, Media, description, title, contentAlignment },\n ref,\n ) {\n const buttonBarRef = useRef(null);\n\n return (\n <div ref={ref}>\n {Media && <div className={withBaseName(\"mediaContainer\")}>{Media}</div>}\n <div className={withBaseName(\"fixedContainer\")} ref={buttonBarRef}>\n <div\n className={clsx({\n [withBaseName(\"textContainer\")]: contentAlignment === \"center\",\n [withBaseName(\"textContainerLeft\")]: contentAlignment === \"left\",\n })}\n >\n {title && (\n <div\n aria-level={1}\n className={withBaseName(\"titleContainer\")}\n role=\"heading\"\n >\n {title}\n </div>\n )}\n {description && (\n <div className={withBaseName(\"descriptionContainer\")}>\n {description}\n </div>\n )}\n </div>\n {ButtonBar && (\n <div\n className={clsx({\n [withBaseName(\"buttonBarOverride\")]:\n contentAlignment === \"center\",\n [withBaseName(\"buttonBarOverrideLeft\")]:\n contentAlignment === \"left\",\n })}\n >\n <ButtonBar\n className={clsx({\n [withBaseName(\"buttonBarContainer\")]:\n contentAlignment === \"center\",\n [withBaseName(\"buttonBarContainerLeft\")]:\n contentAlignment === \"left\",\n })}\n />\n </div>\n )}\n </div>\n </div>\n );\n },\n);\n"],"names":["CarouselSlide"],"mappings":";;;;;AAmBA,MAAM,YAAA,GAAe,aAAa,mBAAmB,CAAA;AAE9C,MAAM,aAAgB,GAAA,UAAA;AAAA,EAC3B,SAASA,eACP,EAAE,SAAA,EAAW,OAAO,WAAa,EAAA,KAAA,EAAO,gBAAiB,EAAA,EACzD,GACA,EAAA;AACA,IAAM,MAAA,YAAA,GAAe,OAAO,IAAI,CAAA;AAEhC,IACE,uBAAA,IAAA,CAAC,SAAI,GACF,EAAA,QAAA,EAAA;AAAA,MAAA,KAAA,wBAAU,KAAI,EAAA,EAAA,SAAA,EAAW,YAAa,CAAA,gBAAgB,GAAI,QAAM,EAAA,KAAA,EAAA,CAAA;AAAA,2BAChE,KAAI,EAAA,EAAA,SAAA,EAAW,aAAa,gBAAgB,CAAA,EAAG,KAAK,YACnD,EAAA,QAAA,EAAA;AAAA,wBAAA,IAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,WAAW,IAAK,CAAA;AAAA,cACd,CAAC,YAAA,CAAa,eAAe,CAAC,GAAG,gBAAqB,KAAA,QAAA;AAAA,cACtD,CAAC,YAAA,CAAa,mBAAmB,CAAC,GAAG,gBAAqB,KAAA;AAAA,aAC3D,CAAA;AAAA,YAEA,QAAA,EAAA;AAAA,cACC,KAAA,oBAAA,GAAA;AAAA,gBAAC,KAAA;AAAA,gBAAA;AAAA,kBACC,YAAY,EAAA,CAAA;AAAA,kBACZ,SAAA,EAAW,aAAa,gBAAgB,CAAA;AAAA,kBACxC,IAAK,EAAA,SAAA;AAAA,kBAEJ,QAAA,EAAA;AAAA;AAAA,eACH;AAAA,cAED,+BACE,GAAA,CAAA,KAAA,EAAA,EAAI,WAAW,YAAa,CAAA,sBAAsB,GAChD,QACH,EAAA,WAAA,EAAA;AAAA;AAAA;AAAA,SAEJ;AAAA,QACC,SACC,oBAAA,GAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,WAAW,IAAK,CAAA;AAAA,cACd,CAAC,YAAA,CAAa,mBAAmB,CAAC,GAChC,gBAAqB,KAAA,QAAA;AAAA,cACvB,CAAC,YAAA,CAAa,uBAAuB,CAAC,GACpC,gBAAqB,KAAA;AAAA,aACxB,CAAA;AAAA,YAED,QAAA,kBAAA,GAAA;AAAA,cAAC,SAAA;AAAA,cAAA;AAAA,gBACC,WAAW,IAAK,CAAA;AAAA,kBACd,CAAC,YAAA,CAAa,oBAAoB,CAAC,GACjC,gBAAqB,KAAA,QAAA;AAAA,kBACvB,CAAC,YAAA,CAAa,wBAAwB,CAAC,GACrC,gBAAqB,KAAA;AAAA,iBACxB;AAAA;AAAA;AACH;AAAA;AACF,OAEJ,EAAA;AAAA,KACF,EAAA,CAAA;AAAA;AAGN;;;;"}
1
+ {"version":3,"file":"CarouselSlide.js","sources":["../src/carousel/CarouselSlide.tsx"],"sourcesContent":["import { makePrefixer, useForkRef, useId, useIdMemo } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport {\n type ComponentProps,\n type ReactNode,\n forwardRef,\n useContext,\n useEffect,\n useRef,\n} from \"react\";\nimport {\n CarouselDispatchContext,\n CarouselStateContext,\n} from \"./CarouselContext\";\nimport carouselSlideCss from \"./CarouselSlide.css\";\n\nexport type CarouselSlideId = string;\nexport type CarouselSlideElement = HTMLDivElement;\nexport type CarouselSlideMeta = {\n element: CarouselSlideElement;\n slideDescription?: string;\n};\nexport interface CarouselSlideProps extends ComponentProps<\"div\"> {\n /**\n * Actions to be displayed in the content footer.\n **/\n actions?: ReactNode;\n /**\n * Media content to be displayed inside the slide. This could include images, videos, etc., that are visually prominent.\n * It differs from children in that media is intended to be the main visual element of the slide.\n **/\n media?: ReactNode;\n /**\n * The appearance of the slide. Options are 'bordered', and 'transparent'.\n * 'transparent' is the default value.\n **/\n appearance?: \"bordered\" | \"transparent\";\n /**\n * Header content to be displayed at the top of the slide. This can be text or any other React node.\n **/\n header?: ReactNode;\n /**\n * Carousel slide id.\n */\n id?: string;\n}\n\nconst withBaseName = makePrefixer(\"saltCarouselSlide\");\n\nexport const CarouselSlide = forwardRef<HTMLDivElement, CarouselSlideProps>(\n function CarouselSlide(\n {\n actions,\n appearance,\n media,\n header,\n children,\n \"aria-labelledby\": ariaLabelledBy,\n style,\n id: idProp,\n ...rest\n },\n refProp,\n ) {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-carousel-slide\",\n css: carouselSlideCss,\n window: targetWindow,\n });\n const dispatch = useContext(CarouselDispatchContext);\n const { slides, visibleSlides, activeSlideIndex } =\n useContext(CarouselStateContext);\n\n const slideRef = useRef<HTMLDivElement>(null);\n const headerRef = useRef<HTMLDivElement>(null);\n const id = useIdMemo(idProp);\n const announcerId = useId();\n const slideCount = slides.size;\n\n useEffect(() => {\n if (!slideRef.current) return;\n\n dispatch({\n type: \"register\",\n payload: [\n id,\n {\n element: slideRef.current,\n slideDescription: headerRef?.current?.innerText,\n },\n ],\n });\n return () => dispatch({ type: \"unregister\", payload: id });\n }, [dispatch, id]);\n\n const SlideStyles = {\n \"--carousel-slide-width\":\n visibleSlides > 1\n ? `calc((100% / ${visibleSlides}) - var(--salt-spacing-200)/${visibleSlides})`\n : undefined,\n ...style,\n };\n\n const ref = useForkRef(refProp, slideRef);\n const slideIds = [...slides.keys()];\n const index = slideIds.indexOf(id || slideIds[0]);\n const helperText = `${index + 1} of ${slideCount}`;\n const isVisible =\n index >= activeSlideIndex && index < activeSlideIndex + visibleSlides;\n\n return (\n <div\n role=\"group\"\n aria-roledescription=\"slide\"\n aria-labelledby={clsx(ariaLabelledBy, announcerId)}\n id={id}\n className={clsx(withBaseName(), {\n [withBaseName(\"bordered\")]: appearance === \"bordered\",\n })}\n style={SlideStyles}\n tabIndex={isVisible ? 0 : -1}\n hidden={!isVisible}\n {...rest}\n ref={ref}\n >\n {media}\n {children && (\n <div\n className={clsx(withBaseName(\"container\"), {\n [withBaseName(\"card\")]: appearance === \"bordered\",\n })}\n >\n <div className={withBaseName(\"content\")}>\n {isVisible && (\n <span\n id={announcerId}\n className={withBaseName(\"sr-only\")}\n aria-hidden=\"true\"\n >\n {helperText}\n </span>\n )}\n <div ref={headerRef}>{header}</div>\n <div>{children}</div>\n </div>\n {isVisible && actions}\n </div>\n )}\n </div>\n );\n },\n);\n"],"names":["CarouselSlide","carouselSlideCss"],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ var css_248z = ".saltCarouselSlider {\n display: flex;\n scroll-snap-type: x mandatory;\n overflow-x: auto;\n scroll-behavior: smooth;\n width: 100%;\n gap: var(--salt-spacing-100);\n grid-area: slider;\n}\n@supports (scrollbar-width: none) {\n .saltCarouselSlider {\n scrollbar-width: none;\n }\n}\n@supports not (scrollbar-width: none) {\n .saltCarouselSlider::-webkit-scrollbar {\n display: none;\n }\n}\n";
2
+
3
+ export { css_248z as default };
4
+ //# sourceMappingURL=CarouselSlider.css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CarouselSlider.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}