@dnanpm/styleguide 3.9.4 → 3.9.6

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.
@@ -1,4 +1,4 @@
1
- import type { ReactNode } from 'react';
1
+ import type { ReactNode, AriaRole } from 'react';
2
2
  import React from 'react';
3
3
  import type { ElevationLevel } from '../../types/elevation';
4
4
  interface Props {
@@ -60,6 +60,15 @@ interface Props {
60
60
  * Allows to pass a custom className
61
61
  */
62
62
  className?: string;
63
+ /**
64
+ * Screen reader label describing the purpose or topic of the box content,
65
+ * e.g., "important information" or "example."
66
+ */
67
+ ariaLabel?: string;
68
+ /**
69
+ * Allows to pass a role to the component
70
+ */
71
+ role?: AriaRole;
63
72
  }
64
73
  declare const Box: ({ elevation, "data-testid": dataTestId, ...props }: Props) => React.JSX.Element;
65
74
  /** @component */
@@ -26,7 +26,7 @@ const BoxWrapper = styled__default.default.div `
26
26
  `;
27
27
  const Box = (_a) => {
28
28
  var { elevation = 'none', 'data-testid': dataTestId } = _a, props = tslib.__rest(_a, ["elevation", 'data-testid']);
29
- return (React__default.default.createElement(BoxWrapper, { id: props.id, "$elevation": elevation, shadow: props.shadow, width: props.width, height: props.height, margin: props.margin, padding: props.padding, className: props.className, "data-testid": dataTestId }, props.children));
29
+ return (React__default.default.createElement(BoxWrapper, { id: props.id, "$elevation": elevation, shadow: props.shadow, width: props.width, height: props.height, margin: props.margin, padding: props.padding, className: props.className, "data-testid": dataTestId, role: props.role, "aria-label": props.ariaLabel }, props.children));
30
30
  };
31
31
 
32
32
  exports.default = Box;
@@ -1,5 +1,11 @@
1
1
  import type { MouseEvent, ReactNode } from 'react';
2
2
  import React from 'react';
3
+ interface Responsive {
4
+ minItems: number;
5
+ maxItems: number;
6
+ minWidth: number;
7
+ maxWidth: number;
8
+ }
3
9
  interface Props {
4
10
  /**
5
11
  * Unique ID for the component
@@ -43,6 +49,11 @@ interface Props {
43
49
  * Allows to pass a custom className
44
50
  */
45
51
  className?: string;
52
+ /**
53
+ * Allows to define responsive configuration
54
+ * If not provided, visibleItems property will be used
55
+ */
56
+ responsive?: Partial<Responsive>;
46
57
  }
47
58
  /** @visibleName Carousel */
48
59
  declare const Carousel: ({ "data-testid": dataTestId, ...props }: Props) => React.JSX.Element;
@@ -55,6 +55,10 @@ const SlideItem = styled.default.div `
55
55
  flex-basis: calc(
56
56
  ${({ visibleItems, itemWidthCorrection }) => `(100% / ${visibleItems}) - ${itemWidthCorrection}px`}
57
57
  );
58
+
59
+ a {
60
+ pointer-events: ${({ isSwiping }) => (isSwiping ? 'none' : 'auto')};
61
+ }
58
62
  `;
59
63
  const Footer = styled.default.div `
60
64
  ${styledUtils.media.md `
@@ -146,9 +150,32 @@ const Carousel = (_a) => {
146
150
  const slidesWrapperRef = React.useRef(null);
147
151
  const scrollbarRef = React.useRef(null);
148
152
  const knobRef = React.useRef(null);
149
- const { isMobile } = useWindowSize.default(theme.default.breakpoints.md);
153
+ const { isMobile, width } = useWindowSize.default(theme.default.breakpoints.md);
150
154
  const [currentIndex, setCurrentIndex] = React.useState(0);
151
- const visibleItems = props.visibleItems || (isMobile ? 1.2 : 1);
155
+ const [isSwiping, setIsSwiping] = React.useState(false);
156
+ const [calculatedItems, setCalculatedItems] = React.useState(props.visibleItems || (isMobile ? 1.2 : 1));
157
+ React.useEffect(() => {
158
+ const calculateVisibleItems = () => {
159
+ const defaultValue = props.visibleItems || (isMobile ? 1.2 : 1);
160
+ const { minItems, maxItems, minWidth, maxWidth } = props.responsive || {};
161
+ if (!width || !minItems || !maxItems || !minWidth || !maxWidth) {
162
+ return defaultValue;
163
+ }
164
+ const calculatedMaxItems = React.Children.count(props.children) === 1 ? 1 : maxItems;
165
+ if (width < minWidth) {
166
+ return minItems;
167
+ }
168
+ if (width > maxWidth) {
169
+ return calculatedMaxItems;
170
+ }
171
+ return minItems + ((width - minWidth) / (maxWidth - minWidth)) * (maxItems - minItems);
172
+ };
173
+ const timeoutId = setTimeout(() => {
174
+ setCalculatedItems(calculateVisibleItems());
175
+ }, 100);
176
+ return () => clearTimeout(timeoutId);
177
+ }, [width, isMobile, props.responsive, props.visibleItems, props.children]);
178
+ const visibleItems = props.visibleItems || calculatedItems;
152
179
  const slidesWrapperGapSizePx = 20;
153
180
  const slideScreensCount = React.Children.count(props.children) - Math.floor(visibleItems) + 1;
154
181
  const itemWidthCorrectionRatio = (slidesWrapperGapSizePx * visibleItems) % Math.floor(visibleItems) === 0
@@ -238,6 +265,7 @@ const Carousel = (_a) => {
238
265
  }
239
266
  setElementTransform(slidesWrapperRef, data.currentTransform, 0);
240
267
  setElementTransform(knobRef, data.knobCurrentTransform, 0);
268
+ setIsSwiping(true);
241
269
  };
242
270
  const handlePointerUp = (e) => {
243
271
  const endTime = Date.now();
@@ -264,6 +292,7 @@ const Carousel = (_a) => {
264
292
  }
265
293
  document.removeEventListener('pointermove', handlePointerMove);
266
294
  document.removeEventListener('pointerup', handlePointerUp);
295
+ setIsSwiping(false);
267
296
  };
268
297
  const handleSlidesPointerDown = (e) => {
269
298
  if (slidesWrapperRef.current && scrollbarRef.current && knobRef.current) {
@@ -279,6 +308,9 @@ const Carousel = (_a) => {
279
308
  const handleScrollbarPointerDown = (e) => {
280
309
  handleSlidesPointerDown(e);
281
310
  };
311
+ const handlePointerDown = (e) => {
312
+ e.preventDefault();
313
+ };
282
314
  React.useEffect(() => {
283
315
  if (slidesWrapperRef.current && scrollbarRef.current) {
284
316
  const isRest = React.Children.count(props.children) - (currentIndex + visibleItems) < 0;
@@ -315,7 +347,7 @@ const Carousel = (_a) => {
315
347
  React__default.default.createElement(ButtonArrow.default, { direction: "left", "aria-label": "Previous", onClick: handleNavigationButtonPreviousClick, disabled: currentIndex <= 0 }),
316
348
  React__default.default.createElement(ButtonArrow.default, { direction: "right", "aria-label": "Next", onClick: handleNavigationButtonNextClick, disabled: currentIndex + visibleItems >= React.Children.count(props.children) }))),
317
349
  React__default.default.createElement(Content, { "data-testid": dataTestId && `${dataTestId}-content` },
318
- React__default.default.createElement(SlidesWrapper, { ref: slidesWrapperRef, onPointerDown: handleSlidesPointerDown, gap: slidesWrapperGapSizePx / 16 }, React.Children.map(props.children, child => (React__default.default.createElement(SlideItem, { visibleItems: visibleItems, itemWidthCorrection: itemWidthCorrection }, child))))),
350
+ React__default.default.createElement(SlidesWrapper, { ref: slidesWrapperRef, onPointerDown: handleSlidesPointerDown, gap: slidesWrapperGapSizePx / 16 }, React.Children.map(props.children, child => (React__default.default.createElement(SlideItem, { visibleItems: visibleItems, itemWidthCorrection: itemWidthCorrection, isSwiping: isSwiping, onPointerDown: handlePointerDown }, child))))),
319
351
  React__default.default.createElement(Footer, { "data-testid": dataTestId && `${dataTestId}-footer` },
320
352
  React__default.default.createElement(Pagination, null, [...Array(slideScreensCount).keys()].map((value, index) => (React__default.default.createElement(PaginationItem, { key: value, "aria-label": `Move to step ${index + 1}`, "aria-current": index === currentIndex, isActive: index === currentIndex, onClick: handlePaginationItemClick })))),
321
353
  React__default.default.createElement(Scrollbar, { ref: scrollbarRef, onPointerDown: handleScrollbarPointerDown },
@@ -169,6 +169,7 @@ const socialMediaIcons = {
169
169
  instagram: icons.Instagram,
170
170
  linkedin: icons.Linkedin,
171
171
  tiktok: icons.Tiktok,
172
+ threads: icons.Threads,
172
173
  twitter: icons.X,
173
174
  youtube: icons.Youtube,
174
175
  };
@@ -220,14 +221,15 @@ const GeneralInformation = ({ generalInformation }) => {
220
221
  const SocialMediaLinks = ({ socialMedia }) => {
221
222
  const { language } = React.useContext(FooterContext.default);
222
223
  return (React__default.default.createElement(SocialMediaLinksContainer, { "data-testid": "social-media-section" }, socialMedia &&
223
- Object.keys(socialMedia || {}).map(socialMediaKey => {
224
- if (socialMediaKey === '__typename') {
225
- return null;
226
- }
224
+ Object.keys(socialMedia).map(socialMediaKey => {
225
+ var _a;
227
226
  const socialMediaName = socialMediaKey.charAt(0).toUpperCase() +
228
227
  socialMediaKey.toLowerCase().slice(1);
229
228
  const currentObject = socialMedia[socialMediaKey];
230
- const currentMediaUrl = currentObject === null || currentObject === void 0 ? void 0 : currentObject.urls[language];
229
+ const currentMediaUrl = (_a = currentObject === null || currentObject === void 0 ? void 0 : currentObject.urls) === null || _a === void 0 ? void 0 : _a[language];
230
+ if (!currentMediaUrl) {
231
+ return null;
232
+ }
231
233
  return (React__default.default.createElement("a", { href: currentMediaUrl, key: `social-media-link-${socialMediaKey}`, "aria-label": socialMediaName },
232
234
  React__default.default.createElement(Icon.default, { icon: socialMediaIcons[socialMediaKey.toLowerCase()] })));
233
235
  })));
@@ -36,7 +36,12 @@ interface Props {
36
36
  * Allows to pass testid string for testing purposes
37
37
  */
38
38
  'data-testid'?: string;
39
+ /**
40
+ * Screen reader label describing the purpose of the switch,
41
+ * e.g., "toggle between accepting or rejecting the terms and conditions"
42
+ */
43
+ ariaLabel?: string;
39
44
  }
40
- declare const Switch: ({ onChange, "data-testid": dataTestId, ...props }: Props) => React.JSX.Element;
45
+ declare const Switch: ({ onChange, "data-testid": dataTestId, ariaLabel, ...props }: Props) => React.JSX.Element;
41
46
  /** @component */
42
47
  export default Switch;
@@ -71,11 +71,18 @@ const Checkbox = styled.default.input `
71
71
  }
72
72
  :disabled + label > div {
73
73
  cursor: not-allowed;
74
- border-color: ${({ checked }) => checked && checked ? theme.default.color.default.pink : theme.default.color.line.L01}${theme.default.color.transparency.T40}};
74
+ border-color: ${({ checked }) => checked ? theme.default.color.default.pink : theme.default.color.line.L01}${theme.default.color.transparency
75
+ .T40};
75
76
  }
76
77
  :disabled + label div div {
77
78
  pointer-events: none;
78
- background-color: ${({ checked }) => checked && checked ? theme.default.color.default.pink : theme.default.color.line.L01}${theme.default.color.transparency.T40};
79
+ background-color: ${({ checked }) => checked ? theme.default.color.default.pink : theme.default.color.line.L01}${theme.default.color.transparency
80
+ .T40};
81
+ }
82
+
83
+ :focus-visible + label > div {
84
+ outline: none;
85
+ box-shadow: 0px 0px 0px 2px ${theme.default.color.focus.dark};
79
86
  }
80
87
  `;
81
88
  const LabelWrapper = styled.default(LabelText.default) `
@@ -100,14 +107,15 @@ const Rail = styled.default.div `
100
107
  `};
101
108
  `;
102
109
  const Switch = (_a) => {
103
- var { onChange, 'data-testid': dataTestId } = _a, props = tslib.__rest(_a, ["onChange", 'data-testid']);
110
+ var { onChange, 'data-testid': dataTestId, ariaLabel } = _a, props = tslib.__rest(_a, ["onChange", 'data-testid', "ariaLabel"]);
104
111
  const handleChange = () => {
105
112
  if (onChange && !props.disabled) {
106
113
  onChange(!props.isChecked);
107
114
  }
108
115
  };
116
+ const accessibleLabel = props.label ? undefined : ariaLabel || 'Toggle switch';
109
117
  return (React__namespace.createElement(Container, { className: props.className, "data-testid": dataTestId },
110
- React__namespace.createElement(Checkbox, { id: props.id, name: props.name, checked: Boolean(props.isChecked), "aria-checked": Boolean(props.isChecked), disabled: props.disabled, onChange: handleChange, role: "switch", type: "checkbox" }),
118
+ React__namespace.createElement(Checkbox, { id: props.id, name: props.name, checked: Boolean(props.isChecked), "aria-label": accessibleLabel, disabled: props.disabled, onChange: handleChange, role: "switch", type: "checkbox" }),
111
119
  React__namespace.createElement(LabelWrapper, { htmlFor: props.id },
112
120
  React__namespace.createElement(Rail, { isChecked: props.isChecked },
113
121
  React__namespace.createElement(Button, { isChecked: props.isChecked })),
@@ -27,6 +27,13 @@ const TabLabel = styled.default.li `
27
27
  border-bottom: 0 none;
28
28
  padding: 0.625rem 1.25rem;
29
29
  cursor: pointer;
30
+
31
+ &:focus {
32
+ border: 1px solid ${theme.default.color.focus.light};
33
+ box-shadow: 0px 0px 0px 2px ${theme.default.color.focus.dark};
34
+ z-index: 1;
35
+ outline: none;
36
+ }
30
37
  `;
31
38
  const TabStyle = styled.default.li `
32
39
  display: inline-block;
@@ -85,13 +92,14 @@ const Tab = (_a) => {
85
92
  props.onClick(props.label, e);
86
93
  }
87
94
  };
95
+ const isActive = props.activeTab ? props.activeTab === props.label : props.isActive;
88
96
  return type === 'box' || type === 'default' || type === 'panel' ? (React__default.default.createElement(React__default.default.Fragment, null,
89
- React__default.default.createElement(TabLabel, { role: "tab", id: props.id, "$type": type, "aria-selected": props.activeTab ? props.activeTab === props.label : props.isActive, isActive: props.activeTab ? props.activeTab === props.label : props.isActive, onClick: onClickHandler }, props.label),
97
+ React__default.default.createElement(TabLabel, { role: "tab", id: props.id, "$type": type, "aria-selected": isActive, isActive: isActive, onClick: onClickHandler, tabIndex: isActive ? 0 : -1 }, props.label),
90
98
  props.isStateless &&
91
99
  (props.children && (props.activeTab === props.label || props.isActive) ? (React__default.default.createElement(ContentContainer, { role: "tabpanel", "$type": props.tabStyle || type, as: (type === 'box' || type === 'default') && !props.tabStyle
92
100
  ? Box.default
93
101
  : undefined }, props.children)) : (React__default.default.createElement(Divider.default, { margin: "0" }))))) : (React__default.default.createElement(React__default.default.Fragment, null,
94
- React__default.default.createElement(TabStyle, { role: "tab", id: props.id, "$type": props.tabStyle || type, "aria-selected": props.activeTab ? props.activeTab === props.label : props.isActive, isActive: props.activeTab ? props.activeTab === props.label : props.isActive, onClick: onClickHandler }, props.label),
102
+ React__default.default.createElement(TabStyle, { role: "tab", id: props.id, "$type": props.tabStyle || type, "aria-selected": isActive, isActive: isActive, onClick: onClickHandler, tabIndex: isActive ? 0 : -1 }, props.label),
95
103
  props.isStateless &&
96
104
  props.children &&
97
105
  (props.activeTab === props.label || props.isActive) && (React__default.default.createElement(ContentContainer, { role: "tabpanel", "$type": props.tabStyle || type }, props.children))));
@@ -100,6 +100,18 @@ const Tabs = (_a) => {
100
100
  }
101
101
  }
102
102
  };
103
+ const onKeyDown = (e) => {
104
+ const tabElements = Array.from(e.currentTarget.querySelectorAll('[role="tab"]'));
105
+ const currentIndex = tabElements.indexOf(document.activeElement);
106
+ if (e.key === 'ArrowRight' || e.key === 'ArrowLeft') {
107
+ e.preventDefault();
108
+ const direction = e.key === 'ArrowRight' ? 1 : -1;
109
+ const nextIndex = (currentIndex + direction + tabElements.length) % tabElements.length;
110
+ const nextTab = tabElements[nextIndex];
111
+ nextTab.focus();
112
+ nextTab.click();
113
+ }
114
+ };
103
115
  if (!tabs) {
104
116
  return null;
105
117
  }
@@ -108,7 +120,7 @@ const Tabs = (_a) => {
108
120
  setActiveTab((outerActiveTab === null || outerActiveTab === void 0 ? void 0 : outerActiveTab.props.label) || tabs[0].props.label);
109
121
  }
110
122
  return (React__default.default.createElement("div", { className: props.className ? `tabs ${props.className}` : 'tabs', "data-testid": dataTestId },
111
- React__default.default.createElement(Tablist, { role: "tablist", "$type": props.tabStyle || type, isFullWidth: props.isFullWidth, isNarrowUnderlined: props.isNarrowUnderlined }, React.Children.map(props.children, tab => React.isValidElement(tab) &&
123
+ React__default.default.createElement(Tablist, { role: "tablist", "$type": props.tabStyle || type, isFullWidth: props.isFullWidth, isNarrowUnderlined: props.isNarrowUnderlined, onKeyDown: onKeyDown }, React.Children.map(props.children, tab => React.isValidElement(tab) &&
112
124
  tab.type === Tab.default && (React__default.default.createElement(Tab.default, { id: tab.props.id, key: tab.props.label, label: tab.props.label, type: props.tabStyle || type, isActive: tab.props.isActive
113
125
  ? tab.props.isActive
114
126
  : activeTab === tab.props.label, activeTab: tab.props.activeTab, onClick: onClickTabItem, className: tab.props.className, "data-testid": tab.props['data-testid'] })))),
@@ -220,19 +220,20 @@ const CheckboxAndRadioInputCore = styled.default.input `
220
220
 
221
221
  &:disabled {
222
222
  cursor: not-allowed;
223
- color: ${theme.default.color.line.L01}${theme.default.color.transparency.T30};
224
- border-color: ${theme.default.color.line.L01}${theme.default.color.transparency.T30};
225
- background-color: ${theme.default.color.background.white.default}${theme.default.color.transparency.T30};
223
+ color: ${theme.default.color.text.gray};
224
+ background-color: ${theme.default.color.line.L02};
225
+ border-color: ${theme.default.color.line.L01};
226
226
 
227
227
  & + label {
228
228
  cursor: not-allowed;
229
- color: ${theme.default.color.text.black}${theme.default.color.transparency.T30};
229
+ color: ${theme.default.color.text.gray};
230
230
  }
231
231
  }
232
232
 
233
233
  &:disabled:checked {
234
234
  color: ${theme.default.color.default.pink}${theme.default.color.transparency.T30};
235
235
  border-color: ${theme.default.color.default.pink}${theme.default.color.transparency.T30};
236
+ background-color: ${theme.default.color.background.white.default};
236
237
  }
237
238
  `;
238
239
  styled.createGlobalStyle `
@@ -1,4 +1,4 @@
1
- import type { ReactNode } from 'react';
1
+ import type { ReactNode, AriaRole } from 'react';
2
2
  import React from 'react';
3
3
  import type { ElevationLevel } from '../../types/elevation';
4
4
  interface Props {
@@ -60,6 +60,15 @@ interface Props {
60
60
  * Allows to pass a custom className
61
61
  */
62
62
  className?: string;
63
+ /**
64
+ * Screen reader label describing the purpose or topic of the box content,
65
+ * e.g., "important information" or "example."
66
+ */
67
+ ariaLabel?: string;
68
+ /**
69
+ * Allows to pass a role to the component
70
+ */
71
+ role?: AriaRole;
63
72
  }
64
73
  declare const Box: ({ elevation, "data-testid": dataTestId, ...props }: Props) => React.JSX.Element;
65
74
  /** @component */
@@ -17,7 +17,7 @@ const BoxWrapper = styled__default.div `
17
17
  `;
18
18
  const Box = (_a) => {
19
19
  var { elevation = 'none', 'data-testid': dataTestId } = _a, props = __rest(_a, ["elevation", 'data-testid']);
20
- return (React__default.createElement(BoxWrapper, { id: props.id, "$elevation": elevation, shadow: props.shadow, width: props.width, height: props.height, margin: props.margin, padding: props.padding, className: props.className, "data-testid": dataTestId }, props.children));
20
+ return (React__default.createElement(BoxWrapper, { id: props.id, "$elevation": elevation, shadow: props.shadow, width: props.width, height: props.height, margin: props.margin, padding: props.padding, className: props.className, "data-testid": dataTestId, role: props.role, "aria-label": props.ariaLabel }, props.children));
21
21
  };
22
22
 
23
23
  export { Box as default };
@@ -1,5 +1,11 @@
1
1
  import type { MouseEvent, ReactNode } from 'react';
2
2
  import React from 'react';
3
+ interface Responsive {
4
+ minItems: number;
5
+ maxItems: number;
6
+ minWidth: number;
7
+ maxWidth: number;
8
+ }
3
9
  interface Props {
4
10
  /**
5
11
  * Unique ID for the component
@@ -43,6 +49,11 @@ interface Props {
43
49
  * Allows to pass a custom className
44
50
  */
45
51
  className?: string;
52
+ /**
53
+ * Allows to define responsive configuration
54
+ * If not provided, visibleItems property will be used
55
+ */
56
+ responsive?: Partial<Responsive>;
46
57
  }
47
58
  /** @visibleName Carousel */
48
59
  declare const Carousel: ({ "data-testid": dataTestId, ...props }: Props) => React.JSX.Element;
@@ -1,6 +1,6 @@
1
1
  import { __rest } from 'tslib';
2
2
  import { ArrowRight } from '@dnanpm/icons';
3
- import React__default, { useRef, useState, Children, useMemo, useEffect } from 'react';
3
+ import React__default, { useRef, useState, useEffect, Children, useMemo } from 'react';
4
4
  import useWindowSize from '../../hooks/useWindowSize.js';
5
5
  import styled from '../../themes/styled.js';
6
6
  import theme from '../../themes/theme.js';
@@ -47,6 +47,10 @@ const SlideItem = styled.div `
47
47
  flex-basis: calc(
48
48
  ${({ visibleItems, itemWidthCorrection }) => `(100% / ${visibleItems}) - ${itemWidthCorrection}px`}
49
49
  );
50
+
51
+ a {
52
+ pointer-events: ${({ isSwiping }) => (isSwiping ? 'none' : 'auto')};
53
+ }
50
54
  `;
51
55
  const Footer = styled.div `
52
56
  ${media.md `
@@ -138,9 +142,32 @@ const Carousel = (_a) => {
138
142
  const slidesWrapperRef = useRef(null);
139
143
  const scrollbarRef = useRef(null);
140
144
  const knobRef = useRef(null);
141
- const { isMobile } = useWindowSize(theme.breakpoints.md);
145
+ const { isMobile, width } = useWindowSize(theme.breakpoints.md);
142
146
  const [currentIndex, setCurrentIndex] = useState(0);
143
- const visibleItems = props.visibleItems || (isMobile ? 1.2 : 1);
147
+ const [isSwiping, setIsSwiping] = useState(false);
148
+ const [calculatedItems, setCalculatedItems] = useState(props.visibleItems || (isMobile ? 1.2 : 1));
149
+ useEffect(() => {
150
+ const calculateVisibleItems = () => {
151
+ const defaultValue = props.visibleItems || (isMobile ? 1.2 : 1);
152
+ const { minItems, maxItems, minWidth, maxWidth } = props.responsive || {};
153
+ if (!width || !minItems || !maxItems || !minWidth || !maxWidth) {
154
+ return defaultValue;
155
+ }
156
+ const calculatedMaxItems = Children.count(props.children) === 1 ? 1 : maxItems;
157
+ if (width < minWidth) {
158
+ return minItems;
159
+ }
160
+ if (width > maxWidth) {
161
+ return calculatedMaxItems;
162
+ }
163
+ return minItems + ((width - minWidth) / (maxWidth - minWidth)) * (maxItems - minItems);
164
+ };
165
+ const timeoutId = setTimeout(() => {
166
+ setCalculatedItems(calculateVisibleItems());
167
+ }, 100);
168
+ return () => clearTimeout(timeoutId);
169
+ }, [width, isMobile, props.responsive, props.visibleItems, props.children]);
170
+ const visibleItems = props.visibleItems || calculatedItems;
144
171
  const slidesWrapperGapSizePx = 20;
145
172
  const slideScreensCount = Children.count(props.children) - Math.floor(visibleItems) + 1;
146
173
  const itemWidthCorrectionRatio = (slidesWrapperGapSizePx * visibleItems) % Math.floor(visibleItems) === 0
@@ -230,6 +257,7 @@ const Carousel = (_a) => {
230
257
  }
231
258
  setElementTransform(slidesWrapperRef, data.currentTransform, 0);
232
259
  setElementTransform(knobRef, data.knobCurrentTransform, 0);
260
+ setIsSwiping(true);
233
261
  };
234
262
  const handlePointerUp = (e) => {
235
263
  const endTime = Date.now();
@@ -256,6 +284,7 @@ const Carousel = (_a) => {
256
284
  }
257
285
  document.removeEventListener('pointermove', handlePointerMove);
258
286
  document.removeEventListener('pointerup', handlePointerUp);
287
+ setIsSwiping(false);
259
288
  };
260
289
  const handleSlidesPointerDown = (e) => {
261
290
  if (slidesWrapperRef.current && scrollbarRef.current && knobRef.current) {
@@ -271,6 +300,9 @@ const Carousel = (_a) => {
271
300
  const handleScrollbarPointerDown = (e) => {
272
301
  handleSlidesPointerDown(e);
273
302
  };
303
+ const handlePointerDown = (e) => {
304
+ e.preventDefault();
305
+ };
274
306
  useEffect(() => {
275
307
  if (slidesWrapperRef.current && scrollbarRef.current) {
276
308
  const isRest = Children.count(props.children) - (currentIndex + visibleItems) < 0;
@@ -307,7 +339,7 @@ const Carousel = (_a) => {
307
339
  React__default.createElement(ButtonArrow, { direction: "left", "aria-label": "Previous", onClick: handleNavigationButtonPreviousClick, disabled: currentIndex <= 0 }),
308
340
  React__default.createElement(ButtonArrow, { direction: "right", "aria-label": "Next", onClick: handleNavigationButtonNextClick, disabled: currentIndex + visibleItems >= Children.count(props.children) }))),
309
341
  React__default.createElement(Content, { "data-testid": dataTestId && `${dataTestId}-content` },
310
- React__default.createElement(SlidesWrapper, { ref: slidesWrapperRef, onPointerDown: handleSlidesPointerDown, gap: slidesWrapperGapSizePx / 16 }, Children.map(props.children, child => (React__default.createElement(SlideItem, { visibleItems: visibleItems, itemWidthCorrection: itemWidthCorrection }, child))))),
342
+ React__default.createElement(SlidesWrapper, { ref: slidesWrapperRef, onPointerDown: handleSlidesPointerDown, gap: slidesWrapperGapSizePx / 16 }, Children.map(props.children, child => (React__default.createElement(SlideItem, { visibleItems: visibleItems, itemWidthCorrection: itemWidthCorrection, isSwiping: isSwiping, onPointerDown: handlePointerDown }, child))))),
311
343
  React__default.createElement(Footer, { "data-testid": dataTestId && `${dataTestId}-footer` },
312
344
  React__default.createElement(Pagination, null, [...Array(slideScreensCount).keys()].map((value, index) => (React__default.createElement(PaginationItem, { key: value, "aria-label": `Move to step ${index + 1}`, "aria-current": index === currentIndex, isActive: index === currentIndex, onClick: handlePaginationItemClick })))),
313
345
  React__default.createElement(Scrollbar, { ref: scrollbarRef, onPointerDown: handleScrollbarPointerDown },
@@ -1,4 +1,4 @@
1
- import { User, Headset, Shop, ArrowRight, ChevronDown, Facebook, Instagram, Linkedin, Tiktok, X, Youtube } from '@dnanpm/icons';
1
+ import { User, Headset, Shop, ArrowRight, ChevronDown, Facebook, Instagram, Linkedin, Tiktok, Threads, X, Youtube } from '@dnanpm/icons';
2
2
  import React__default, { useContext } from 'react';
3
3
  import styled from '../../../themes/styled.js';
4
4
  import theme from '../../../themes/theme.js';
@@ -163,6 +163,7 @@ const socialMediaIcons = {
163
163
  instagram: Instagram,
164
164
  linkedin: Linkedin,
165
165
  tiktok: Tiktok,
166
+ threads: Threads,
166
167
  twitter: X,
167
168
  youtube: Youtube,
168
169
  };
@@ -214,14 +215,15 @@ const GeneralInformation = ({ generalInformation }) => {
214
215
  const SocialMediaLinks = ({ socialMedia }) => {
215
216
  const { language } = useContext(FooterContext);
216
217
  return (React__default.createElement(SocialMediaLinksContainer, { "data-testid": "social-media-section" }, socialMedia &&
217
- Object.keys(socialMedia || {}).map(socialMediaKey => {
218
- if (socialMediaKey === '__typename') {
219
- return null;
220
- }
218
+ Object.keys(socialMedia).map(socialMediaKey => {
219
+ var _a;
221
220
  const socialMediaName = socialMediaKey.charAt(0).toUpperCase() +
222
221
  socialMediaKey.toLowerCase().slice(1);
223
222
  const currentObject = socialMedia[socialMediaKey];
224
- const currentMediaUrl = currentObject === null || currentObject === void 0 ? void 0 : currentObject.urls[language];
223
+ const currentMediaUrl = (_a = currentObject === null || currentObject === void 0 ? void 0 : currentObject.urls) === null || _a === void 0 ? void 0 : _a[language];
224
+ if (!currentMediaUrl) {
225
+ return null;
226
+ }
225
227
  return (React__default.createElement("a", { href: currentMediaUrl, key: `social-media-link-${socialMediaKey}`, "aria-label": socialMediaName },
226
228
  React__default.createElement(Icon, { icon: socialMediaIcons[socialMediaKey.toLowerCase()] })));
227
229
  })));
@@ -36,7 +36,12 @@ interface Props {
36
36
  * Allows to pass testid string for testing purposes
37
37
  */
38
38
  'data-testid'?: string;
39
+ /**
40
+ * Screen reader label describing the purpose of the switch,
41
+ * e.g., "toggle between accepting or rejecting the terms and conditions"
42
+ */
43
+ ariaLabel?: string;
39
44
  }
40
- declare const Switch: ({ onChange, "data-testid": dataTestId, ...props }: Props) => React.JSX.Element;
45
+ declare const Switch: ({ onChange, "data-testid": dataTestId, ariaLabel, ...props }: Props) => React.JSX.Element;
41
46
  /** @component */
42
47
  export default Switch;
@@ -47,11 +47,18 @@ const Checkbox = styled.input `
47
47
  }
48
48
  :disabled + label > div {
49
49
  cursor: not-allowed;
50
- border-color: ${({ checked }) => checked && checked ? theme.color.default.pink : theme.color.line.L01}${theme.color.transparency.T40}};
50
+ border-color: ${({ checked }) => checked ? theme.color.default.pink : theme.color.line.L01}${theme.color.transparency
51
+ .T40};
51
52
  }
52
53
  :disabled + label div div {
53
54
  pointer-events: none;
54
- background-color: ${({ checked }) => checked && checked ? theme.color.default.pink : theme.color.line.L01}${theme.color.transparency.T40};
55
+ background-color: ${({ checked }) => checked ? theme.color.default.pink : theme.color.line.L01}${theme.color.transparency
56
+ .T40};
57
+ }
58
+
59
+ :focus-visible + label > div {
60
+ outline: none;
61
+ box-shadow: 0px 0px 0px 2px ${theme.color.focus.dark};
55
62
  }
56
63
  `;
57
64
  const LabelWrapper = styled(LabelText) `
@@ -76,14 +83,15 @@ const Rail = styled.div `
76
83
  `};
77
84
  `;
78
85
  const Switch = (_a) => {
79
- var { onChange, 'data-testid': dataTestId } = _a, props = __rest(_a, ["onChange", 'data-testid']);
86
+ var { onChange, 'data-testid': dataTestId, ariaLabel } = _a, props = __rest(_a, ["onChange", 'data-testid', "ariaLabel"]);
80
87
  const handleChange = () => {
81
88
  if (onChange && !props.disabled) {
82
89
  onChange(!props.isChecked);
83
90
  }
84
91
  };
92
+ const accessibleLabel = props.label ? undefined : ariaLabel || 'Toggle switch';
85
93
  return (React.createElement(Container, { className: props.className, "data-testid": dataTestId },
86
- React.createElement(Checkbox, { id: props.id, name: props.name, checked: Boolean(props.isChecked), "aria-checked": Boolean(props.isChecked), disabled: props.disabled, onChange: handleChange, role: "switch", type: "checkbox" }),
94
+ React.createElement(Checkbox, { id: props.id, name: props.name, checked: Boolean(props.isChecked), "aria-label": accessibleLabel, disabled: props.disabled, onChange: handleChange, role: "switch", type: "checkbox" }),
87
95
  React.createElement(LabelWrapper, { htmlFor: props.id },
88
96
  React.createElement(Rail, { isChecked: props.isChecked },
89
97
  React.createElement(Button, { isChecked: props.isChecked })),
@@ -19,6 +19,13 @@ const TabLabel = styled.li `
19
19
  border-bottom: 0 none;
20
20
  padding: 0.625rem 1.25rem;
21
21
  cursor: pointer;
22
+
23
+ &:focus {
24
+ border: 1px solid ${theme.color.focus.light};
25
+ box-shadow: 0px 0px 0px 2px ${theme.color.focus.dark};
26
+ z-index: 1;
27
+ outline: none;
28
+ }
22
29
  `;
23
30
  const TabStyle = styled.li `
24
31
  display: inline-block;
@@ -77,13 +84,14 @@ const Tab = (_a) => {
77
84
  props.onClick(props.label, e);
78
85
  }
79
86
  };
87
+ const isActive = props.activeTab ? props.activeTab === props.label : props.isActive;
80
88
  return type === 'box' || type === 'default' || type === 'panel' ? (React__default.createElement(React__default.Fragment, null,
81
- React__default.createElement(TabLabel, { role: "tab", id: props.id, "$type": type, "aria-selected": props.activeTab ? props.activeTab === props.label : props.isActive, isActive: props.activeTab ? props.activeTab === props.label : props.isActive, onClick: onClickHandler }, props.label),
89
+ React__default.createElement(TabLabel, { role: "tab", id: props.id, "$type": type, "aria-selected": isActive, isActive: isActive, onClick: onClickHandler, tabIndex: isActive ? 0 : -1 }, props.label),
82
90
  props.isStateless &&
83
91
  (props.children && (props.activeTab === props.label || props.isActive) ? (React__default.createElement(ContentContainer, { role: "tabpanel", "$type": props.tabStyle || type, as: (type === 'box' || type === 'default') && !props.tabStyle
84
92
  ? Box
85
93
  : undefined }, props.children)) : (React__default.createElement(Divider, { margin: "0" }))))) : (React__default.createElement(React__default.Fragment, null,
86
- React__default.createElement(TabStyle, { role: "tab", id: props.id, "$type": props.tabStyle || type, "aria-selected": props.activeTab ? props.activeTab === props.label : props.isActive, isActive: props.activeTab ? props.activeTab === props.label : props.isActive, onClick: onClickHandler }, props.label),
94
+ React__default.createElement(TabStyle, { role: "tab", id: props.id, "$type": props.tabStyle || type, "aria-selected": isActive, isActive: isActive, onClick: onClickHandler, tabIndex: isActive ? 0 : -1 }, props.label),
87
95
  props.isStateless &&
88
96
  props.children &&
89
97
  (props.activeTab === props.label || props.isActive) && (React__default.createElement(ContentContainer, { role: "tabpanel", "$type": props.tabStyle || type }, props.children))));
@@ -92,6 +92,18 @@ const Tabs = (_a) => {
92
92
  }
93
93
  }
94
94
  };
95
+ const onKeyDown = (e) => {
96
+ const tabElements = Array.from(e.currentTarget.querySelectorAll('[role="tab"]'));
97
+ const currentIndex = tabElements.indexOf(document.activeElement);
98
+ if (e.key === 'ArrowRight' || e.key === 'ArrowLeft') {
99
+ e.preventDefault();
100
+ const direction = e.key === 'ArrowRight' ? 1 : -1;
101
+ const nextIndex = (currentIndex + direction + tabElements.length) % tabElements.length;
102
+ const nextTab = tabElements[nextIndex];
103
+ nextTab.focus();
104
+ nextTab.click();
105
+ }
106
+ };
95
107
  if (!tabs) {
96
108
  return null;
97
109
  }
@@ -100,7 +112,7 @@ const Tabs = (_a) => {
100
112
  setActiveTab((outerActiveTab === null || outerActiveTab === void 0 ? void 0 : outerActiveTab.props.label) || tabs[0].props.label);
101
113
  }
102
114
  return (React__default.createElement("div", { className: props.className ? `tabs ${props.className}` : 'tabs', "data-testid": dataTestId },
103
- React__default.createElement(Tablist, { role: "tablist", "$type": props.tabStyle || type, isFullWidth: props.isFullWidth, isNarrowUnderlined: props.isNarrowUnderlined }, Children.map(props.children, tab => isValidElement(tab) &&
115
+ React__default.createElement(Tablist, { role: "tablist", "$type": props.tabStyle || type, isFullWidth: props.isFullWidth, isNarrowUnderlined: props.isNarrowUnderlined, onKeyDown: onKeyDown }, Children.map(props.children, tab => isValidElement(tab) &&
104
116
  tab.type === Tab && (React__default.createElement(Tab, { id: tab.props.id, key: tab.props.label, label: tab.props.label, type: props.tabStyle || type, isActive: tab.props.isActive
105
117
  ? tab.props.isActive
106
118
  : activeTab === tab.props.label, activeTab: tab.props.activeTab, onClick: onClickTabItem, className: tab.props.className, "data-testid": tab.props['data-testid'] })))),
@@ -218,19 +218,20 @@ const CheckboxAndRadioInputCore = styled.input `
218
218
 
219
219
  &:disabled {
220
220
  cursor: not-allowed;
221
- color: ${theme.color.line.L01}${theme.color.transparency.T30};
222
- border-color: ${theme.color.line.L01}${theme.color.transparency.T30};
223
- background-color: ${theme.color.background.white.default}${theme.color.transparency.T30};
221
+ color: ${theme.color.text.gray};
222
+ background-color: ${theme.color.line.L02};
223
+ border-color: ${theme.color.line.L01};
224
224
 
225
225
  & + label {
226
226
  cursor: not-allowed;
227
- color: ${theme.color.text.black}${theme.color.transparency.T30};
227
+ color: ${theme.color.text.gray};
228
228
  }
229
229
  }
230
230
 
231
231
  &:disabled:checked {
232
232
  color: ${theme.color.default.pink}${theme.color.transparency.T30};
233
233
  border-color: ${theme.color.default.pink}${theme.color.transparency.T30};
234
+ background-color: ${theme.color.background.white.default};
234
235
  }
235
236
  `;
236
237
  createGlobalStyle `
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@dnanpm/styleguide",
3
3
  "sideEffects": false,
4
- "version": "v3.9.4",
4
+ "version": "v3.9.6",
5
5
  "main": "build/cjs/index.js",
6
6
  "module": "build/es/index.js",
7
7
  "jsnext:main": "build/es/index.js",
@@ -43,8 +43,8 @@
43
43
  "@babel/core": "^7.26.0",
44
44
  "@babel/preset-env": "^7.26.0",
45
45
  "@babel/preset-react": "^7.25.9",
46
- "@babel/preset-typescript": "^7.25.7",
47
- "@dnanpm/icons": "2.0.4",
46
+ "@babel/preset-typescript": "^7.26.0",
47
+ "@dnanpm/icons": "2.0.7",
48
48
  "@rollup/plugin-commonjs": "^28.0.1",
49
49
  "@rollup/plugin-node-resolve": "^15.3.0",
50
50
  "@rollup/plugin-typescript": "^12.1.1",
@@ -73,7 +73,7 @@
73
73
  "eslint-plugin-jsdoc": "^39.9.1",
74
74
  "eslint-plugin-jsx-a11y": "^6.10.1",
75
75
  "eslint-plugin-prefer-arrow": "^1.2.3",
76
- "eslint-plugin-react": "^7.37.2",
76
+ "eslint-plugin-react": "^7.37.4",
77
77
  "eslint-plugin-react-hooks": "^4.6.2",
78
78
  "jest": "^29.7.0",
79
79
  "jest-environment-jsdom": "^29.7.0",
@@ -86,10 +86,10 @@
86
86
  "react-dom": "^18.3.1",
87
87
  "react-styleguidist": "^13.1.3",
88
88
  "rollup": "^3.29.4",
89
- "rollup-plugin-import-css": "^3.5.6",
89
+ "rollup-plugin-import-css": "^3.5.8",
90
90
  "style-loader": "^3.3.3",
91
91
  "styled-components": "^5.3.11",
92
- "ts-jest": "^29.2.5",
92
+ "ts-jest": "^29.2.6",
93
93
  "ts-node": "^10.9.2",
94
94
  "tslib": "^2.8.0",
95
95
  "typescript": "^5.1.6",