@dnanpm/styleguide 3.12.0 → 3.12.2
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.
- package/build/cjs/components/Breadcrumb/Breadcrumb.d.ts +42 -0
- package/build/cjs/components/Breadcrumb/Breadcrumb.js +90 -0
- package/build/cjs/components/Carousel/Carousel.d.ts +11 -14
- package/build/cjs/components/Carousel/Carousel.js +52 -40
- package/build/cjs/components/DateTimePicker/DateTimePicker.js +4 -0
- package/build/cjs/components/Hero/Hero.d.ts +0 -6
- package/build/cjs/components/Hero/Hero.js +3 -3
- package/build/cjs/components/NotificationBadge/NotificationBadge.js +4 -0
- package/build/cjs/components/PriorityNavigation/PriorityNavigation.js +4 -0
- package/build/cjs/components/Skeleton/Skeleton.d.ts +63 -0
- package/build/cjs/components/Skeleton/Skeleton.js +73 -0
- package/build/cjs/components/Tooltip/Tooltip.js +1 -1
- package/build/cjs/components/index.d.ts +2 -0
- package/build/cjs/index.js +4 -0
- package/build/cjs/themes/globalStyles.js +1 -0
- package/build/cjs/themes/theme.d.ts +9 -2
- package/build/cjs/themes/themeComponents/breakpoints.d.ts +9 -4
- package/build/cjs/utils/styledUtils.d.ts +22 -1
- package/build/cjs/utils/styledUtils.js +26 -6
- package/build/es/components/Breadcrumb/Breadcrumb.d.ts +42 -0
- package/build/es/components/Breadcrumb/Breadcrumb.js +82 -0
- package/build/es/components/Carousel/Carousel.d.ts +11 -14
- package/build/es/components/Carousel/Carousel.js +52 -40
- package/build/es/components/DateTimePicker/DateTimePicker.js +4 -0
- package/build/es/components/Hero/Hero.d.ts +0 -6
- package/build/es/components/Hero/Hero.js +3 -3
- package/build/es/components/NotificationBadge/NotificationBadge.js +4 -0
- package/build/es/components/PriorityNavigation/PriorityNavigation.js +4 -0
- package/build/es/components/Skeleton/Skeleton.d.ts +63 -0
- package/build/es/components/Skeleton/Skeleton.js +65 -0
- package/build/es/components/Tooltip/Tooltip.js +1 -1
- package/build/es/components/index.d.ts +2 -0
- package/build/es/index.js +2 -0
- package/build/es/themes/globalStyles.js +1 -0
- package/build/es/themes/theme.d.ts +9 -2
- package/build/es/themes/themeComponents/breakpoints.d.ts +9 -4
- package/build/es/utils/styledUtils.d.ts +22 -1
- package/build/es/utils/styledUtils.js +26 -6
- package/package.json +14 -10
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { css } from '../themes/styled';
|
|
1
2
|
export declare const getMultipliedSize: (base: {
|
|
2
3
|
value: number;
|
|
3
4
|
unit: string;
|
|
@@ -6,4 +7,24 @@ export declare const getDividedSize: (base: {
|
|
|
6
7
|
value: number;
|
|
7
8
|
unit: string;
|
|
8
9
|
}, divide: number) => string;
|
|
9
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Media query helpers for responsive design.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* const StyledDiv = styled.div`
|
|
16
|
+
* font-size: 1rem;
|
|
17
|
+
* ${media.md`font-size: 1.2rem;`}
|
|
18
|
+
* ${media.lg`font-size: 1.5rem;`}
|
|
19
|
+
* `;
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* Available breakpoints:
|
|
23
|
+
* - `xs`: 480px
|
|
24
|
+
* - `sm`: 576px
|
|
25
|
+
* - `md`: 768px
|
|
26
|
+
* - `lg`: 992px
|
|
27
|
+
* - `xl`: 1200px
|
|
28
|
+
* - `xxl`: 1440px
|
|
29
|
+
*/
|
|
30
|
+
export declare const media: Record<"xxl" | "xl" | "lg" | "md" | "sm" | "xs", (l: TemplateStringsArray, ...p: (string | number)[]) => ReturnType<typeof css>>;
|
|
@@ -5,12 +5,32 @@ var breakpoints = require('../themes/themeComponents/breakpoints.js');
|
|
|
5
5
|
|
|
6
6
|
const getMultipliedSize = (base, multiply) => `${multiply * base.value}${base.unit}`;
|
|
7
7
|
const getDividedSize = (base, divide) => `${base.value / divide}${base.unit}`;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Media query helpers for responsive design.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* const StyledDiv = styled.div`
|
|
14
|
+
* font-size: 1rem;
|
|
15
|
+
* ${media.md`font-size: 1.2rem;`}
|
|
16
|
+
* ${media.lg`font-size: 1.5rem;`}
|
|
17
|
+
* `;
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* Available breakpoints:
|
|
21
|
+
* - `xs`: 480px
|
|
22
|
+
* - `sm`: 576px
|
|
23
|
+
* - `md`: 768px
|
|
24
|
+
* - `lg`: 992px
|
|
25
|
+
* - `xl`: 1200px
|
|
26
|
+
* - `xxl`: 1440px
|
|
27
|
+
*/
|
|
28
|
+
const media = Object.keys(breakpoints.default).reduce((acc, key) => {
|
|
29
|
+
acc[key] = (literals, ...placeholders) => styledComponents.css `
|
|
30
|
+
@media (min-width: ${breakpoints.default[key]}px) {
|
|
31
|
+
${styledComponents.css(literals, ...placeholders)}
|
|
32
|
+
}
|
|
33
|
+
`;
|
|
14
34
|
return acc;
|
|
15
35
|
}, {});
|
|
16
36
|
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { ComponentType } from 'react';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
export interface BreadcrumbItem {
|
|
4
|
+
/**
|
|
5
|
+
* Display text for the breadcrumb item
|
|
6
|
+
*/
|
|
7
|
+
label: string;
|
|
8
|
+
/**
|
|
9
|
+
* URL/path for the breadcrumb item. If not provided, item will be rendered as text only
|
|
10
|
+
*/
|
|
11
|
+
href?: string;
|
|
12
|
+
}
|
|
13
|
+
interface Props {
|
|
14
|
+
/**
|
|
15
|
+
* Array of breadcrumb items to display
|
|
16
|
+
*/
|
|
17
|
+
items?: BreadcrumbItem[];
|
|
18
|
+
/**
|
|
19
|
+
* Custom link component to use instead of default anchor element
|
|
20
|
+
* Useful for router integration (e.g., Next.js Link, React Router Link)
|
|
21
|
+
*/
|
|
22
|
+
linkComponent?: ComponentType<any>;
|
|
23
|
+
/**
|
|
24
|
+
* Props to pass to the link component
|
|
25
|
+
*/
|
|
26
|
+
linkProps?: Record<string, unknown>;
|
|
27
|
+
/**
|
|
28
|
+
* Screen reader label describing the breadcrumb navigation
|
|
29
|
+
*/
|
|
30
|
+
ariaLabel?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Allows to pass testid string for testing purposes
|
|
33
|
+
*/
|
|
34
|
+
'data-testid'?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Allows to pass a custom className
|
|
37
|
+
*/
|
|
38
|
+
className?: string;
|
|
39
|
+
}
|
|
40
|
+
declare const Breadcrumb: ({ "data-testid": dataTestId, ariaLabel, className, items, linkComponent: LinkComponent, linkProps, }: Props) => React.JSX.Element | null;
|
|
41
|
+
/** @component */
|
|
42
|
+
export default Breadcrumb;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
import { ChevronRight } from '@dnanpm/icons';
|
|
3
|
+
import { styled } from 'styled-components';
|
|
4
|
+
import theme from '../../themes/theme.js';
|
|
5
|
+
import { getMultipliedSize } from '../../utils/styledUtils.js';
|
|
6
|
+
|
|
7
|
+
const BreadcrumbNav = styled.nav `
|
|
8
|
+
font-size: ${theme.fontSize.s};
|
|
9
|
+
font-weight: ${theme.fontWeight.medium};
|
|
10
|
+
`;
|
|
11
|
+
const BreadcrumbList = styled.ol `
|
|
12
|
+
display: flex;
|
|
13
|
+
align-items: center;
|
|
14
|
+
flex-wrap: nowrap;
|
|
15
|
+
list-style: none;
|
|
16
|
+
margin: ${getMultipliedSize(theme.base.baseHeight, 2)} 0;
|
|
17
|
+
padding: 0;
|
|
18
|
+
gap: ${getMultipliedSize(theme.base.baseHeight, 0.5)};
|
|
19
|
+
overflow: visible;
|
|
20
|
+
container: breadcrumb / inline-size;
|
|
21
|
+
|
|
22
|
+
/* Responsive behavior: show only last 2 items when container < 600px */
|
|
23
|
+
@container (max-width: 599px) {
|
|
24
|
+
li:not(:nth-last-child(-n + 2)) {
|
|
25
|
+
display: none;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
`;
|
|
29
|
+
const BreadcrumbListItem = styled.li `
|
|
30
|
+
display: flex;
|
|
31
|
+
align-items: center;
|
|
32
|
+
gap: ${getMultipliedSize(theme.base.baseHeight, 0.5)};
|
|
33
|
+
|
|
34
|
+
&:last-child {
|
|
35
|
+
min-width: 0;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
a {
|
|
39
|
+
&:focus-visible {
|
|
40
|
+
outline: none;
|
|
41
|
+
border-radius: ${theme.radius.s};
|
|
42
|
+
box-shadow:
|
|
43
|
+
0px 0px 0px 2px ${theme.color.focus.light},
|
|
44
|
+
0px 0px 0px 4px ${theme.color.focus.dark};
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
span {
|
|
49
|
+
flex: 1 1 0%;
|
|
50
|
+
white-space: nowrap;
|
|
51
|
+
overflow: hidden;
|
|
52
|
+
text-overflow: ellipsis;
|
|
53
|
+
}
|
|
54
|
+
`;
|
|
55
|
+
const Breadcrumb = ({ 'data-testid': dataTestId, ariaLabel, className, items, linkComponent: LinkComponent, linkProps = {}, }) => {
|
|
56
|
+
if (!items || items.length === 0) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
const renderItem = (item, index) => {
|
|
60
|
+
const isLastItem = index === items.length - 1;
|
|
61
|
+
if (isLastItem || !item.href) {
|
|
62
|
+
return React__default.createElement("span", { "aria-current": isLastItem ? 'page' : undefined }, item.label);
|
|
63
|
+
}
|
|
64
|
+
if (LinkComponent) {
|
|
65
|
+
return (React__default.createElement(LinkComponent, Object.assign({ href: item.href, itemProp: "item", itemScope: true, itemType: "https://schema.org/WebPage" }, linkProps),
|
|
66
|
+
React__default.createElement("span", { itemProp: "name" }, item.label)));
|
|
67
|
+
}
|
|
68
|
+
return (React__default.createElement("a", { href: item.href, itemProp: "item", itemScope: true, itemType: "https://schema.org/WebPage" },
|
|
69
|
+
React__default.createElement("span", { itemProp: "name" }, item.label)));
|
|
70
|
+
};
|
|
71
|
+
return (React__default.createElement(BreadcrumbNav, { "aria-label": ariaLabel, className: className, "data-testid": dataTestId },
|
|
72
|
+
React__default.createElement(BreadcrumbList, { itemScope: true, itemType: "https://schema.org/BreadcrumbList" }, items.map((item, index) => {
|
|
73
|
+
var _a;
|
|
74
|
+
const isLastItem = index === items.length - 1;
|
|
75
|
+
return (React__default.createElement(BreadcrumbListItem, { itemProp: "itemListElement", itemScope: true, itemType: "https://schema.org/ListItem", key: `breadcrumb-${item.label}-${(_a = item.href) !== null && _a !== void 0 ? _a : 'nolink'}` },
|
|
76
|
+
renderItem(item, index),
|
|
77
|
+
React__default.createElement("meta", { itemProp: "position", content: (index + 1).toString() }),
|
|
78
|
+
!isLastItem && (React__default.createElement(ChevronRight, { color: theme.color.background.pink.default, size: "0.9rem" }))));
|
|
79
|
+
}))));
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
export { Breadcrumb as default };
|
|
@@ -1,11 +1,5 @@
|
|
|
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
|
-
}
|
|
9
3
|
interface Props {
|
|
10
4
|
/**
|
|
11
5
|
* Unique ID for the component
|
|
@@ -50,10 +44,12 @@ interface Props {
|
|
|
50
44
|
*/
|
|
51
45
|
className?: string;
|
|
52
46
|
/**
|
|
53
|
-
* Allows
|
|
54
|
-
*
|
|
47
|
+
* Allows for responsive behavior in the carousel.
|
|
48
|
+
* Shows as many items as possible; each item requires a defined width.
|
|
49
|
+
* This overrides the `visibleItems` prop.
|
|
50
|
+
* @default false
|
|
55
51
|
*/
|
|
56
|
-
responsive?:
|
|
52
|
+
responsive?: boolean;
|
|
57
53
|
/**
|
|
58
54
|
* Allows to pass a screen reader label for the pagination item next to the current slide number
|
|
59
55
|
*/
|
|
@@ -73,12 +69,13 @@ interface Props {
|
|
|
73
69
|
*/
|
|
74
70
|
swipeStep?: number;
|
|
75
71
|
}
|
|
76
|
-
declare const SlideItem: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>,
|
|
77
|
-
$visibleItems?: Props["visibleItems"];
|
|
78
|
-
}> & {
|
|
79
|
-
$itemWidthCorrection: number;
|
|
72
|
+
declare const SlideItem: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
|
|
80
73
|
$isSwiping: boolean;
|
|
81
|
-
|
|
74
|
+
$responsive: boolean;
|
|
75
|
+
$gap: number;
|
|
76
|
+
} & Partial<Required<{
|
|
77
|
+
$visibleItems: Props["visibleItems"];
|
|
78
|
+
}>>>> & string;
|
|
82
79
|
/** @visibleName Carousel */
|
|
83
80
|
declare const Carousel: ({ "data-testid": dataTestId, ...props }: Props) => React.JSX.Element;
|
|
84
81
|
/** @component */
|
|
@@ -33,7 +33,6 @@ const SlidesWrapper = styled.div `
|
|
|
33
33
|
display: flex;
|
|
34
34
|
width: 100%;
|
|
35
35
|
height: 100%;
|
|
36
|
-
gap: ${({ $gap }) => $gap}rem;
|
|
37
36
|
transition-property: transform;
|
|
38
37
|
transform: translate3d(0px, 0, 0);
|
|
39
38
|
transition-duration: 0ms;
|
|
@@ -44,9 +43,14 @@ const SlideItem = styled.div `
|
|
|
44
43
|
display: block;
|
|
45
44
|
position: relative;
|
|
46
45
|
flex-shrink: 0;
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
)
|
|
46
|
+
padding-right: ${({ $gap }) => $gap}rem;
|
|
47
|
+
|
|
48
|
+
${({ $responsive, $visibleItems }) => !$responsive && $visibleItems
|
|
49
|
+
? `flex-basis: calc(100% / ${$visibleItems});`
|
|
50
|
+
: `
|
|
51
|
+
flex-basis: auto;
|
|
52
|
+
width: max-content;
|
|
53
|
+
`}
|
|
50
54
|
|
|
51
55
|
a {
|
|
52
56
|
pointer-events: ${({ $isSwiping }) => ($isSwiping ? 'none' : 'auto')};
|
|
@@ -138,53 +142,51 @@ const Counter = styled.span `
|
|
|
138
142
|
`;
|
|
139
143
|
/** @visibleName Carousel */
|
|
140
144
|
const Carousel = (_a) => {
|
|
141
|
-
var _b;
|
|
145
|
+
var _b, _c;
|
|
142
146
|
var { 'data-testid': dataTestId } = _a, props = __rest(_a, ['data-testid']);
|
|
143
147
|
const slidesWrapperRef = useRef(null);
|
|
144
148
|
const scrollbarRef = useRef(null);
|
|
145
149
|
const knobRef = useRef(null);
|
|
146
|
-
const
|
|
150
|
+
const firstItemRef = useRef(null);
|
|
151
|
+
const { isMobile, width: windowWidth } = useWindowSize(theme.breakpoints.md);
|
|
147
152
|
const [currentIndex, setCurrentIndex] = useState(0);
|
|
148
153
|
const [isSwiping, setIsSwiping] = useState(false);
|
|
149
|
-
const [
|
|
154
|
+
const [autoVisibleItems, setAutoVisibleItems] = useState(null);
|
|
150
155
|
useEffect(() => {
|
|
151
|
-
|
|
152
|
-
const
|
|
153
|
-
const
|
|
154
|
-
if (
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
156
|
+
if (props.responsive) {
|
|
157
|
+
const container = slidesWrapperRef.current;
|
|
158
|
+
const firstItem = firstItemRef.current;
|
|
159
|
+
if (container && firstItem) {
|
|
160
|
+
Array.from(container.children).forEach(itemElement => {
|
|
161
|
+
const item = itemElement;
|
|
162
|
+
item.style.flexBasis = '';
|
|
163
|
+
item.style.width = '';
|
|
164
|
+
});
|
|
165
|
+
const containerWidth = container.offsetWidth;
|
|
166
|
+
const itemWidth = firstItem.offsetWidth;
|
|
167
|
+
if (itemWidth > 0) {
|
|
168
|
+
const realVisibleItems = containerWidth / itemWidth;
|
|
169
|
+
setAutoVisibleItems(Math.max(1, realVisibleItems));
|
|
170
|
+
}
|
|
160
171
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
const timeoutId = setTimeout(() => {
|
|
167
|
-
setCalculatedItems(calculateVisibleItems());
|
|
168
|
-
}, 100);
|
|
169
|
-
return () => clearTimeout(timeoutId);
|
|
170
|
-
}, [width, isMobile, props.responsive, props.visibleItems, props.children]);
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
setAutoVisibleItems(null);
|
|
175
|
+
}
|
|
176
|
+
}, [props.responsive, windowWidth, props.children]);
|
|
171
177
|
const getStep = (step, visibleItems) => {
|
|
172
178
|
if (step > visibleItems) {
|
|
173
179
|
return Math.floor(visibleItems);
|
|
174
180
|
}
|
|
175
181
|
return Math.floor(step);
|
|
176
182
|
};
|
|
177
|
-
const visibleItems = props.visibleItems
|
|
183
|
+
const visibleItems = (_b = autoVisibleItems !== null && autoVisibleItems !== void 0 ? autoVisibleItems : props.visibleItems) !== null && _b !== void 0 ? _b : (isMobile ? 1.2 : 1);
|
|
178
184
|
const slidesWrapperGapSizePx = 20;
|
|
179
185
|
const slidesCount = Children.count(props.children);
|
|
180
186
|
const slideScreensCount = Math.max(1, slidesCount - Math.floor(visibleItems) + 1);
|
|
181
|
-
const step = getStep((
|
|
187
|
+
const step = getStep((_c = props.swipeStep) !== null && _c !== void 0 ? _c : 1, visibleItems);
|
|
182
188
|
const currentStepIndex = Math.ceil(currentIndex / step);
|
|
183
189
|
const totalSwipeSteps = Math.ceil(slideScreensCount / step + ((slideScreensCount - 1) % step !== 0 ? 1 : 0));
|
|
184
|
-
const itemWidthCorrectionRatio = (slidesWrapperGapSizePx * visibleItems) % Math.floor(visibleItems) === 0
|
|
185
|
-
? (visibleItems - 1) / visibleItems
|
|
186
|
-
: Math.floor(visibleItems) / visibleItems;
|
|
187
|
-
const itemWidthCorrection = itemWidthCorrectionRatio * slidesWrapperGapSizePx;
|
|
188
190
|
const data = useMemo(() => ({
|
|
189
191
|
startX: 0,
|
|
190
192
|
startTime: 0,
|
|
@@ -320,12 +322,10 @@ const Carousel = (_a) => {
|
|
|
320
322
|
useEffect(() => {
|
|
321
323
|
if (slidesWrapperRef.current && scrollbarRef.current) {
|
|
322
324
|
const isRest = Children.count(props.children) - (currentIndex + visibleItems) < 0;
|
|
323
|
-
data.itemWidth =
|
|
324
|
-
slidesWrapperRef.current.offsetWidth / visibleItems - itemWidthCorrection;
|
|
325
|
+
data.itemWidth = slidesWrapperRef.current.offsetWidth / visibleItems;
|
|
325
326
|
data.scrollWidth = slidesWrapperRef.current.scrollWidth;
|
|
326
327
|
data.lastItemX =
|
|
327
|
-
|
|
328
|
-
(Children.count(props.children) - visibleItems) -
|
|
328
|
+
data.itemWidth * (Children.count(props.children) - visibleItems) -
|
|
329
329
|
(isRest ? slidesWrapperGapSizePx * (Math.ceil(visibleItems) - visibleItems) : 0);
|
|
330
330
|
data.scrollbarToSlidesRatio =
|
|
331
331
|
data.lastItemX /
|
|
@@ -334,14 +334,26 @@ const Carousel = (_a) => {
|
|
|
334
334
|
let slidesTransform = 0;
|
|
335
335
|
if (Children.count(props.children) >= visibleItems) {
|
|
336
336
|
slidesTransform =
|
|
337
|
-
data.itemWidth * currentIndex
|
|
338
|
-
slidesWrapperGapSizePx * currentIndex -
|
|
337
|
+
data.itemWidth * currentIndex -
|
|
339
338
|
(isRest ? data.itemWidth * (visibleItems % 1) + slidesWrapperGapSizePx : 0);
|
|
340
339
|
}
|
|
341
340
|
setElementTransform(slidesWrapperRef, -slidesTransform);
|
|
342
341
|
setElementTransform(knobRef, slidesTransform / data.scrollbarToSlidesRatio);
|
|
343
342
|
}
|
|
344
|
-
}, [currentIndex, data,
|
|
343
|
+
}, [currentIndex, data, props.children, slideScreensCount, visibleItems]);
|
|
344
|
+
useEffect(() => {
|
|
345
|
+
var _a;
|
|
346
|
+
if (props.responsive && autoVisibleItems) {
|
|
347
|
+
const items = (_a = slidesWrapperRef.current) === null || _a === void 0 ? void 0 : _a.children;
|
|
348
|
+
if (items) {
|
|
349
|
+
Array.from(items).forEach(itemElement => {
|
|
350
|
+
const item = itemElement;
|
|
351
|
+
item.style.flexBasis = `calc(100% / ${autoVisibleItems})`;
|
|
352
|
+
item.style.width = '';
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}, [autoVisibleItems, props.responsive]);
|
|
345
357
|
return (React__default.createElement(CarouselWrapper, { id: props.id, className: props.className, "data-testid": dataTestId },
|
|
346
358
|
React__default.createElement(Header, { "data-testid": dataTestId && `${dataTestId}-header` },
|
|
347
359
|
props.title && React__default.createElement(Title, null, props.title),
|
|
@@ -353,7 +365,7 @@ const Carousel = (_a) => {
|
|
|
353
365
|
React__default.createElement(ButtonArrow, { direction: "left", "aria-label": props.previousAriaLabel, onClick: handleNavigationButtonPreviousClick, disabled: currentIndex <= 0, type: "button" }),
|
|
354
366
|
React__default.createElement(ButtonArrow, { direction: "right", "aria-label": props.nextAriaLabel, onClick: handleNavigationButtonNextClick, disabled: currentIndex + visibleItems >= Children.count(props.children), type: "button" }))),
|
|
355
367
|
React__default.createElement(Content, { "data-testid": dataTestId && `${dataTestId}-content` },
|
|
356
|
-
React__default.createElement(SlidesWrapper, { ref: slidesWrapperRef, onPointerDown: handleSlidesPointerDown
|
|
368
|
+
React__default.createElement(SlidesWrapper, { ref: slidesWrapperRef, onPointerDown: handleSlidesPointerDown }, Children.map(props.children, (child, index) => (React__default.createElement(SlideItem, { ref: index === 0 ? firstItemRef : undefined, "$visibleItems": visibleItems, "$isSwiping": isSwiping, onPointerDown: handlePointerDown, "$responsive": Boolean(props.responsive), "$gap": slidesWrapperGapSizePx / 16 }, child))))),
|
|
357
369
|
React__default.createElement(Footer, { "data-testid": dataTestId && `${dataTestId}-footer` },
|
|
358
370
|
React__default.createElement(Pagination, null, [...Array(totalSwipeSteps).keys()].map((value, index) => (React__default.createElement(PaginationItem, { key: value, "aria-label": props.paginationAriaLabel &&
|
|
359
371
|
`${props.paginationAriaLabel} ${index + 1}`, "aria-current": Math.ceil(currentIndex / step) === index, "$isActive": Math.ceil(currentIndex / step) === index, onClick: handlePaginationItemClick, type: "button" })))),
|
|
@@ -251,6 +251,10 @@ const CurrentMonth = styled.div `
|
|
|
251
251
|
line-height: ${theme.lineHeight.default};
|
|
252
252
|
font-weight: ${theme.fontWeight.bold};
|
|
253
253
|
`;
|
|
254
|
+
/**
|
|
255
|
+
* TODO: Replace the VisuallyHiddenStatus styled component with the global class name.
|
|
256
|
+
* Ticket: https://jira.dna.fi/browse/STYLE-916
|
|
257
|
+
*/
|
|
254
258
|
const VisuallyHiddenStatus = styled.div `
|
|
255
259
|
position: absolute;
|
|
256
260
|
left: -9999px;
|
|
@@ -34,12 +34,6 @@ interface HeroProps {
|
|
|
34
34
|
* Background color when no image is provided
|
|
35
35
|
*/
|
|
36
36
|
backgroundColor?: string;
|
|
37
|
-
/**
|
|
38
|
-
* Enable gradient overlay on background
|
|
39
|
-
*
|
|
40
|
-
* @default false
|
|
41
|
-
*/
|
|
42
|
-
hasGradient?: boolean;
|
|
43
37
|
/**
|
|
44
38
|
* Logo image component for logo-style heroes
|
|
45
39
|
*/
|
|
@@ -27,9 +27,9 @@ const HeroImage = styled.div `
|
|
|
27
27
|
height: ${HERO_CONSTANTS.mobileHeight}px;
|
|
28
28
|
background-color: ${({ $backgroundColor }) => $backgroundColor || 'transparent'};
|
|
29
29
|
|
|
30
|
-
${({ $
|
|
30
|
+
${({ $backgroundColor }) => $backgroundColor &&
|
|
31
31
|
`
|
|
32
|
-
linear-gradient(180deg, ${theme.color.background.plum.default}${theme.color.transparency.T0} 0%, ${theme.color.background.plum.default}${theme.color.transparency.T30}
|
|
32
|
+
background-image: linear-gradient(180deg, ${theme.color.background.plum.default}${theme.color.transparency.T0} 0%, ${theme.color.background.plum.default}${theme.color.transparency.T30} 100%);
|
|
33
33
|
background-size: 100% 33.33%;
|
|
34
34
|
background-repeat: no-repeat;
|
|
35
35
|
background-position: bottom;
|
|
@@ -176,7 +176,7 @@ const Hero = (_a) => {
|
|
|
176
176
|
var { variant = 'default', headingLevel = 'h1', Image = 'img', LogoImage = 'img', 'data-testid': dataTestId } = _a, props = __rest(_a, ["variant", "headingLevel", "Image", "LogoImage", 'data-testid']);
|
|
177
177
|
const HeadingTag = headingLevel;
|
|
178
178
|
return (React__default.createElement(HeroContainer, { "$variant": variant, className: props.className, "data-testid": dataTestId },
|
|
179
|
-
React__default.createElement(HeroImage, { "$
|
|
179
|
+
React__default.createElement(HeroImage, { "$backgroundColor": props.backgroundColor },
|
|
180
180
|
props.logoImageProps && (React__default.createElement(LogoImageWrap, null,
|
|
181
181
|
React__default.createElement(LogoImageContainer, null, renderImage(LogoImage, props.logoImageProps)))),
|
|
182
182
|
!props.logoImageProps && props.imageProps && renderImage(Image, props.imageProps)),
|
|
@@ -18,6 +18,10 @@ const NotificationBadgeElement = styled.div `
|
|
|
18
18
|
background-color: ${theme.color.notification.error};
|
|
19
19
|
border-radius: ${theme.radius.circle};
|
|
20
20
|
`;
|
|
21
|
+
/**
|
|
22
|
+
* TODO: Replace the VisuallyHidden styled component with the global class name.
|
|
23
|
+
* Ticket: https://jira.dna.fi/browse/STYLE-916
|
|
24
|
+
*/
|
|
21
25
|
const VisuallyHidden = styled.span `
|
|
22
26
|
position: absolute;
|
|
23
27
|
width: 1px;
|
|
@@ -131,6 +131,10 @@ const DropdownList = styled(CoreULStyles) `
|
|
|
131
131
|
|
|
132
132
|
${getElevationShadow({ elevation: 'low' })}
|
|
133
133
|
`;
|
|
134
|
+
/**
|
|
135
|
+
* TODO: Replace the VisuallyHidden styled component with the global class name.
|
|
136
|
+
* Ticket: https://jira.dna.fi/browse/STYLE-916
|
|
137
|
+
*/
|
|
134
138
|
const VisuallyHidden = styled.span `
|
|
135
139
|
position: absolute;
|
|
136
140
|
width: 1px;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type ThemeInterface } from '../../themes/theme';
|
|
3
|
+
interface Props {
|
|
4
|
+
/**
|
|
5
|
+
* Unique ID for the skeleton
|
|
6
|
+
*/
|
|
7
|
+
id?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Background color of the skeleton
|
|
10
|
+
*
|
|
11
|
+
* @param {string} sand Uses theme.color.background.sand.E01
|
|
12
|
+
* @param {string} white Uses white background (#FFFFFF)
|
|
13
|
+
*
|
|
14
|
+
* @default 'sand'
|
|
15
|
+
*/
|
|
16
|
+
backgroundColor?: 'sand' | 'white';
|
|
17
|
+
/**
|
|
18
|
+
* Opacity level of the skeleton
|
|
19
|
+
*
|
|
20
|
+
* @param {number} 100 100% opacity
|
|
21
|
+
* @param {number} 50 50% opacity
|
|
22
|
+
* @param {number} 25 25% opacity
|
|
23
|
+
*
|
|
24
|
+
* @default 100
|
|
25
|
+
*/
|
|
26
|
+
opacity?: 100 | 50 | 25;
|
|
27
|
+
/**
|
|
28
|
+
* Allows to pass in custom radius value from theme
|
|
29
|
+
*/
|
|
30
|
+
borderRadius?: keyof ThemeInterface['radius'];
|
|
31
|
+
/**
|
|
32
|
+
* Width of the skeleton
|
|
33
|
+
*
|
|
34
|
+
* @default '100%'
|
|
35
|
+
*/
|
|
36
|
+
width?: string;
|
|
37
|
+
/**
|
|
38
|
+
* Height of the skeleton
|
|
39
|
+
*
|
|
40
|
+
* @default '6.25rem'
|
|
41
|
+
*/
|
|
42
|
+
height?: string;
|
|
43
|
+
/**
|
|
44
|
+
* Allows to pass testid string for testing purposes
|
|
45
|
+
*/
|
|
46
|
+
'data-testid'?: string;
|
|
47
|
+
/**
|
|
48
|
+
* Allows to pass a custom className
|
|
49
|
+
*/
|
|
50
|
+
className?: string;
|
|
51
|
+
/**
|
|
52
|
+
* If used inside a carousel, pass the slide index (starting from 1)
|
|
53
|
+
*/
|
|
54
|
+
carouselIndex?: number;
|
|
55
|
+
/**
|
|
56
|
+
* Screen reader label describing the use of the skeleton,
|
|
57
|
+
* e.g., "Loading content" or "Loading image."
|
|
58
|
+
*/
|
|
59
|
+
ariaLabel?: string;
|
|
60
|
+
}
|
|
61
|
+
declare const Skeleton: ({ backgroundColor, opacity, width, height, borderRadius, "data-testid": dataTestId, ...props }: Props) => React.JSX.Element;
|
|
62
|
+
/** @component */
|
|
63
|
+
export default Skeleton;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { __rest } from 'tslib';
|
|
2
|
+
import React__default from 'react';
|
|
3
|
+
import { keyframes, styled } from 'styled-components';
|
|
4
|
+
import theme from '../../themes/theme.js';
|
|
5
|
+
|
|
6
|
+
const shimmer = keyframes `
|
|
7
|
+
100% {
|
|
8
|
+
transform: translateX(100%);
|
|
9
|
+
}
|
|
10
|
+
`;
|
|
11
|
+
const sandRgba = '248, 244, 241';
|
|
12
|
+
const whiteRgba = '255, 255, 255';
|
|
13
|
+
const getAnimationDelay = (carouselIndex) => {
|
|
14
|
+
switch (carouselIndex) {
|
|
15
|
+
case 1:
|
|
16
|
+
return '0s';
|
|
17
|
+
case 2:
|
|
18
|
+
return '0.6s';
|
|
19
|
+
case 3:
|
|
20
|
+
return '1.2s';
|
|
21
|
+
case 4:
|
|
22
|
+
return '1.9s';
|
|
23
|
+
case 5:
|
|
24
|
+
return '2.5s';
|
|
25
|
+
default:
|
|
26
|
+
return '0s';
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
const getBackgroundColor = (backgroundColor) => `linear-gradient(90deg,rgba(${backgroundColor}, 0) 0%,rgba(${backgroundColor}, 0.8) 50%,rgba(${backgroundColor}, 0) 100%)`;
|
|
30
|
+
const SkeletonWrapper = styled.div `
|
|
31
|
+
position: relative;
|
|
32
|
+
overflow: hidden;
|
|
33
|
+
background-color: ${({ $backgroundColor }) => $backgroundColor === 'sand'
|
|
34
|
+
? theme.color.background.sand.E01
|
|
35
|
+
: theme.color.background.white.default};
|
|
36
|
+
opacity: ${({ $opacity }) => ($opacity ? $opacity / 100 : 1)};
|
|
37
|
+
width: ${({ $width }) => $width};
|
|
38
|
+
height: ${({ $height }) => $height};
|
|
39
|
+
border-radius: ${({ $borderRadius }) => theme.radius[$borderRadius || 's']};
|
|
40
|
+
|
|
41
|
+
&::after {
|
|
42
|
+
position: absolute;
|
|
43
|
+
inset: 0;
|
|
44
|
+
transform: translateX(-100%);
|
|
45
|
+
background: ${({ $backgroundColor }) => getBackgroundColor($backgroundColor === 'sand' ? whiteRgba : sandRgba)};
|
|
46
|
+
|
|
47
|
+
animation: ${shimmer} 1.5s infinite;
|
|
48
|
+
content: '';
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@media (min-width: 600px) {
|
|
52
|
+
&::after {
|
|
53
|
+
animation: ${shimmer} 2.5s infinite;
|
|
54
|
+
animation-delay: ${({ $carouselIndex }) => getAnimationDelay($carouselIndex)};
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
`;
|
|
58
|
+
const Skeleton = (_a) => {
|
|
59
|
+
var { backgroundColor = 'sand', opacity = 100, width = '25rem', height = '6.25rem', borderRadius = 's', 'data-testid': dataTestId } = _a, props = __rest(_a, ["backgroundColor", "opacity", "width", "height", "borderRadius", 'data-testid']);
|
|
60
|
+
return (React__default.createElement(React__default.Fragment, null,
|
|
61
|
+
props.ariaLabel && (React__default.createElement("span", { id: props.id, "aria-label": props.ariaLabel, role: "status", "aria-atomic": "true", className: "visually-hidden" })),
|
|
62
|
+
React__default.createElement(SkeletonWrapper, { className: props.className, "data-testid": dataTestId, "aria-hidden": "true", tabIndex: -1, "$backgroundColor": backgroundColor, "$opacity": opacity, "$width": width, "$height": height, "$carouselIndex": props.carouselIndex, "$borderRadius": borderRadius })));
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export { Skeleton as default };
|
|
@@ -56,7 +56,7 @@ const StyledReactTooltip = styled(Tooltip$1) `
|
|
|
56
56
|
|
|
57
57
|
border: 1px solid ${theme.color.line.L02};
|
|
58
58
|
padding: ${getMultipliedSize(theme.base.baseWidth, 1.5)};
|
|
59
|
-
text-align:
|
|
59
|
+
text-align: left;
|
|
60
60
|
font-size: ${theme.fontSize.default};
|
|
61
61
|
line-height: ${theme.lineHeight.default};
|
|
62
62
|
width: max-content;
|
|
@@ -2,6 +2,7 @@ export { default as Accordion } from './Accordion/Accordion';
|
|
|
2
2
|
export { default as AccordionItem } from './AccordionItem/AccordionItem';
|
|
3
3
|
export { default as AmountSelector } from './AmountSelector/AmountSelector';
|
|
4
4
|
export { default as Box } from './Box/Box';
|
|
5
|
+
export { default as Breadcrumb } from './Breadcrumb/Breadcrumb';
|
|
5
6
|
export { default as Button } from './Button/Button';
|
|
6
7
|
export { default as ButtonArrow } from './ButtonArrow/ButtonArrow';
|
|
7
8
|
export { default as ButtonCard } from './ButtonCard/ButtonCard';
|
|
@@ -46,6 +47,7 @@ export { default as ReadMore } from './ReadMore/ReadMore';
|
|
|
46
47
|
export { default as Search } from './Search/Search';
|
|
47
48
|
export { default as SecondaryNavigation } from './SecondaryNavigation/SecondaryNavigation';
|
|
48
49
|
export { default as Selectbox } from './Selectbox/Selectbox';
|
|
50
|
+
export { default as Skeleton } from './Skeleton/Skeleton';
|
|
49
51
|
export { default as Switch } from './Switch/Switch';
|
|
50
52
|
export { default as Tab } from './Tab/Tab';
|
|
51
53
|
export { default as Tabs } from './Tabs/Tabs';
|
package/build/es/index.js
CHANGED
|
@@ -2,6 +2,7 @@ export { default as Accordion } from './components/Accordion/Accordion.js';
|
|
|
2
2
|
export { default as AccordionItem } from './components/AccordionItem/AccordionItem.js';
|
|
3
3
|
export { default as AmountSelector } from './components/AmountSelector/AmountSelector.js';
|
|
4
4
|
export { default as Box } from './components/Box/Box.js';
|
|
5
|
+
export { default as Breadcrumb } from './components/Breadcrumb/Breadcrumb.js';
|
|
5
6
|
export { default as Button } from './components/Button/Button.js';
|
|
6
7
|
export { default as ButtonArrow } from './components/ButtonArrow/ButtonArrow.js';
|
|
7
8
|
export { default as ButtonCard } from './components/ButtonCard/ButtonCard.js';
|
|
@@ -154,6 +155,7 @@ export { default as ReadMore } from './components/ReadMore/ReadMore.js';
|
|
|
154
155
|
export { default as Search } from './components/Search/Search.js';
|
|
155
156
|
export { default as SecondaryNavigation } from './components/SecondaryNavigation/SecondaryNavigation.js';
|
|
156
157
|
export { default as Selectbox } from './components/Selectbox/Selectbox.js';
|
|
158
|
+
export { default as Skeleton } from './components/Skeleton/Skeleton.js';
|
|
157
159
|
export { default as Switch } from './components/Switch/Switch.js';
|
|
158
160
|
export { default as Tab } from './components/Tab/Tab.js';
|
|
159
161
|
export { default as Tabs } from './components/Tabs/Tabs.js';
|