src/components/molecules/Carousel/index.tsx   A
last analyzed

Complexity

Total Complexity 3
Complexity/F 0

Size

Lines of Code 144
Function Count 0

Duplication

Duplicated Lines 0
Ratio 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 3
eloc 93
mnd 3
bc 3
fnc 0
dl 0
loc 144
ccs 36
cts 36
cp 1
rs 10
bpm 0
cpm 0
noi 0
c 0
b 0
f 0
1 1
import "./styles.css";
2
3 1
import React from "react";
4 1
import classNames from "classnames";
5
6
import { CarouselComponent, CarouselProps } from "./types";
7
8 1
import { ICONS } from "../Rater/icons";
9
10 1
import { buildBoxComponent } from "../../../utils";
11
12 1
import Button from "../../atoms/Button";
13
14
/**
15
 * A compact carousel, to show any component (or image) into a slide, with dots and arrow button to go next/previous
16
 *
17
 * @since 2.0.0
18
 *
19
 * @param {(string | JSX.Element | Element)[]} elements carousel elements
20
 * @param {string} className `common modular-ui prop` - custom className (to better customize it)
21
 * @param {boolean} unstyled `common modular-ui prop` - Style/unstyle component (to better customize it)
22
 * @param {string} id `common modular-ui prop` - `data-id` parameter (for testing purpose, to easily find the component into the DOM)
23
 * @param {boolean} dark `common modular-ui prop` - Enable/disable dark mode
24
 * @param {boolean} hide `common modular-ui prop` - Hide/show component
25
 * @param {boolean} shadow `common modular-ui prop` - Enable/disable shadow behind component (to better customize it)
26
 *
27
 * @example <caption>Example Carousel usage</caption>
28
 * import { render } from "react-dom";
29
 * import { Carousel } from '@cianciarusocataldo/modular-ui';
30
 *
31
 * render(<Carousel elements={[<div>Element 0</div>,<div>Element 1</div>]} value={1} />, document.getElementById("root"));
32
 *
33
 * @see https://cianciarusocataldo.github.io/modular-ui/components/molecules/Carousel
34
 *
35
 * @author Cataldo Cianciaruso <https://github.com/CianciarusoCataldo>
36
 *
37
 * @copyright 2022 Cataldo Cianciaruso
38
 */
39 1
const Carousel: CarouselComponent = ({
40 13
  elements: actualElements,
41 13
  label,
42 13
  onChange,
43 13
  value,
44 13
  ...commonProps
45
}) => {
46
  const arrowIcon = (
47 13
    <svg viewBox="0 0 250 250" width="2em" height="2em">
48
      <path d="M186.1 70.6c2.5-3.1 1.6-4.3-2-2.6L65.2 122c-3.6 1.6-3.6 4.3 0 6l118.9 54c3.6 1.6 4.5.5 2-2.6l-39.8-48.2c-2.5-3.1-2.5-8.1-.1-11.2l39.9-49.4z" />
49
    </svg>
50
  );
51
52 13
  const [activeClassName, setActiveClassname] = React.useState("");
53 13
  const [hoveredDot, setHoveredDot] = React.useState<number | null>(null);
54
55 13
  return buildBoxComponent<number>({
56
    callBack: (item, setItem) => {
57 13
      let dots = [];
58 13
      let elementsArray = [];
59 13
      const elements = actualElements || [];
60 13
      const updateItem = (newItem: number) => {
61 5
        onChange && onChange(newItem);
62 5
        setItem(newItem);
63
      };
64
65 13
      if (elements && elements.length > 0) {
66 12
        elements.forEach((element, index) => {
67 36
          elementsArray.push(
68
            <div
69
              key={`carousel_element_${index}`}
70
              className={classNames("element", {
71
                "component-hidden": index !== item,
72
                [activeClassName]: index === item,
73
              })}
74
            >
75
              {element}
76
            </div>
77
          );
78
79 36
          dots.push(
80
            <Button
81
              className="dot"
82
              unstyled
83
              id={`dot_${index}`}
84
              key={`dot_${index}`}
85 1
              onMouseEnter={() => setHoveredDot(index)}
86 1
              onMouseLeave={() => setHoveredDot(null)}
87
              onClick={() => {
88 3
                setActiveClassname(index > item ? "from-right" : "from-left");
89 3
                updateItem(index);
90
              }}
91
            >
92
              {index === item || (hoveredDot != null && index === hoveredDot)
93
                ? ICONS.circle.FULL
94
                : ICONS.circle.EMPTY}
95
            </Button>
96
          );
97
        });
98
      }
99 13
      return {
100
        name: "modular-carousel",
101
        Component: [
102
          <div className="elements" key="modular_carousel_elements">
103
            <Button
104
              dark={commonProps.dark}
105
              id="left_arrow"
106
              className="arrow prev"
107
              unstyled
108
              disabled={item === 0}
109
              onClick={() => {
110 1
                setActiveClassname("from-left");
111 1
                updateItem(item - 1);
112
              }}
113
            >
114
              {arrowIcon}
115
            </Button>
116
            {elementsArray}
117
            <Button
118
              dark={commonProps.dark}
119
              unstyled
120
              className="arrow next"
121
              id="right_arrow"
122
              disabled={item === elements.length - 1}
123
              onClick={() => {
124 1
                setActiveClassname("from-right");
125 1
                updateItem(item + 1);
126
              }}
127
            >
128
              {arrowIcon}
129
            </Button>
130
          </div>,
131
          <div key="modular_carousel_dots">
132
            <div className="dots">{dots}</div>
133
          </div>,
134
        ],
135
        commonProps,
136
      };
137
    },
138
    label,
139
    defaultValue: 0,
140
  });
141
};
142
143
export default Carousel;
144