@dnanpm/styleguide 3.11.3 → 3.11.5
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/Button/Button.d.ts +8 -1
- package/build/cjs/components/Button/Button.js +2 -1
- package/build/cjs/components/DateTimePicker/DateTimePicker.js +41 -6
- package/build/cjs/components/Footer/Components/FooterComponents.js +26 -3
- package/build/cjs/components/MainHeaderNavigation/ChildComponents/LinkModifier.js +17 -3
- package/build/cjs/components/MainHeaderNavigation/MainHeaderNavigation.d.ts +2 -1
- package/build/cjs/components/MainHeaderNavigation/MainHeaderNavigation.js +3 -1
- package/build/cjs/components/MainHeaderNavigation/context/NavContext.d.ts +1 -0
- package/build/cjs/components/MainHeaderNavigation/context/NavContext.js +1 -0
- package/build/cjs/components/RadioButton/RadioButton.d.ts +2 -2
- package/build/cjs/components/RadioButton/RadioButton.js +8 -2
- package/build/cjs/components/Textarea/Textarea.js +5 -4
- package/build/es/components/Button/Button.d.ts +8 -1
- package/build/es/components/Button/Button.js +2 -1
- package/build/es/components/DateTimePicker/DateTimePicker.js +41 -6
- package/build/es/components/Footer/Components/FooterComponents.js +26 -3
- package/build/es/components/MainHeaderNavigation/ChildComponents/LinkModifier.js +17 -3
- package/build/es/components/MainHeaderNavigation/MainHeaderNavigation.d.ts +2 -1
- package/build/es/components/MainHeaderNavigation/MainHeaderNavigation.js +3 -1
- package/build/es/components/MainHeaderNavigation/context/NavContext.d.ts +1 -0
- package/build/es/components/MainHeaderNavigation/context/NavContext.js +1 -0
- package/build/es/components/RadioButton/RadioButton.d.ts +2 -2
- package/build/es/components/RadioButton/RadioButton.js +8 -2
- package/build/es/components/Textarea/Textarea.js +5 -4
- package/package.json +5 -6
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { MouseEvent, ReactNode } from 'react';
|
|
1
|
+
import type { ComponentType, MouseEvent, ReactNode } from 'react';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
type ButtonType = 'submit' | 'button' | 'reset';
|
|
4
4
|
export interface Props {
|
|
@@ -24,6 +24,13 @@ export interface Props {
|
|
|
24
24
|
* Allows to change the type of resulting HTML element from button (`<button></button>`) to anchor (`<a href="..."></a>`)
|
|
25
25
|
*/
|
|
26
26
|
href?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Allows to use a custom link component instead of anchor element when `href` is defined
|
|
29
|
+
*/
|
|
30
|
+
nextLink?: ComponentType<{
|
|
31
|
+
href: string;
|
|
32
|
+
children: ReactNode;
|
|
33
|
+
}>;
|
|
27
34
|
/**
|
|
28
35
|
* Allows to set the target attribute for the link
|
|
29
36
|
*/
|
|
@@ -125,8 +125,9 @@ const Element = styledComponents.styled.button `
|
|
|
125
125
|
`;
|
|
126
126
|
/** @visibleName Button */
|
|
127
127
|
const Button = (_a) => {
|
|
128
|
+
var _b;
|
|
128
129
|
var { type = 'submit', 'data-testid': dataTestId, 'data-no-close': dataNoClose, 'data-track-value': dataTrackValue, 'aria-label': ariaLabel } = _a, props = tslib.__rest(_a, ["type", 'data-testid', 'data-no-close', 'data-track-value', 'aria-label']);
|
|
129
|
-
return (React__default.default.createElement(Element, Object.assign({ id: props.id, as: props.href ? 'a' : undefined, type: props.href ? undefined : type, href: props.href, target: props.href ? props.target : undefined, rel: props.target === '_blank' ? 'noopener noreferrer' : undefined, onClick: props.onClick, onMouseDown: props.onMouseDown, "$small": props.small, "$darkBg": props.darkBg, "$fullWidth": props.fullWidth, "$loading": props.loading, tabIndex: props.loading ? -1 : 0, "data-loading": props.loading, className: props.className, "data-testid": dataTestId, "data-no-close": dataNoClose, "data-track-value": dataTrackValue, "aria-label": ariaLabel }, props.dataAttributes, (!props.href && {
|
|
130
|
+
return (React__default.default.createElement(Element, Object.assign({ id: props.id, as: (_b = props.nextLink) !== null && _b !== void 0 ? _b : (props.href ? 'a' : undefined), type: props.href ? undefined : type, href: props.href, target: props.href ? props.target : undefined, rel: props.target === '_blank' ? 'noopener noreferrer' : undefined, onClick: props.onClick, onMouseDown: props.onMouseDown, "$small": props.small, "$darkBg": props.darkBg, "$fullWidth": props.fullWidth, "$loading": props.loading, tabIndex: props.loading ? -1 : 0, "data-loading": props.loading, className: props.className, "data-testid": dataTestId, "data-no-close": dataNoClose, "data-track-value": dataTrackValue, "aria-label": ariaLabel }, props.dataAttributes, (!props.href && {
|
|
130
131
|
name: props.name,
|
|
131
132
|
disabled: props.disabled,
|
|
132
133
|
})), props.loading ? (React__default.default.createElement(PixelLoader.default, { color: props.darkBg ? theme.default.color.default.white : theme.default.color.default.plum, label: props.loadingLabel })) : (React__default.default.createElement("span", { "data-testid": dataTestId && `${dataTestId}-text`, "data-no-close": dataNoClose }, props.children))));
|
|
@@ -56,6 +56,15 @@ const localeData = {
|
|
|
56
56
|
'en-GB': undefined,
|
|
57
57
|
};
|
|
58
58
|
const sentenceCase = (string) => `${string[0].toUpperCase()}${string.slice(1)}`;
|
|
59
|
+
const parseFIDateString = (dateString) => {
|
|
60
|
+
const parts = dateString.split(/\D+/);
|
|
61
|
+
if (!parts || parts.length < 3) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
const [day, month, year] = parts.map(Number);
|
|
65
|
+
const date = new Date(year, month - 1, day);
|
|
66
|
+
return !Number.isNaN(date.getTime()) ? date : null;
|
|
67
|
+
};
|
|
59
68
|
// TODO: change `& .react-datepicker` value back to `1` after z-index of Footer removed
|
|
60
69
|
const Wrapper = styledComponents.styled.div `
|
|
61
70
|
position: relative;
|
|
@@ -111,10 +120,27 @@ const Wrapper = styledComponents.styled.div `
|
|
|
111
120
|
}
|
|
112
121
|
}
|
|
113
122
|
|
|
123
|
+
& .react-datepicker__sr-only {
|
|
124
|
+
position: absolute;
|
|
125
|
+
width: 1px;
|
|
126
|
+
height: 1px;
|
|
127
|
+
padding: 0;
|
|
128
|
+
overflow: hidden;
|
|
129
|
+
clip: rect(0, 0, 0, 0);
|
|
130
|
+
white-space: nowrap;
|
|
131
|
+
border: 0;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
& .react-datepicker__day-names {
|
|
135
|
+
background-color: ${theme.default.color.background.sand.E01};
|
|
136
|
+
padding: ${styledUtils.getMultipliedSize(theme.default.base.baseWidth, 0.5)} 0;
|
|
137
|
+
}
|
|
138
|
+
|
|
114
139
|
& .react-datepicker__day-names,
|
|
115
140
|
& .react-datepicker__week {
|
|
116
141
|
display: flex;
|
|
117
142
|
gap: ${styledUtils.getMultipliedSize(theme.default.base.baseWidth, 0.8)};
|
|
143
|
+
justify-content: center;
|
|
118
144
|
|
|
119
145
|
.react-datepicker__day-name,
|
|
120
146
|
.react-datepicker__day {
|
|
@@ -250,6 +276,7 @@ const DateTimePicker = (_a) => {
|
|
|
250
276
|
var _b, _c, _d;
|
|
251
277
|
var { date: startDate, locale = 'fi-FI', isDatePicker = true, isTimePicker = false, timeInterval = 30, 'data-testid': dataTestId } = _a, props = tslib.__rest(_a, ["date", "locale", "isDatePicker", "isTimePicker", "timeInterval", 'data-testid']);
|
|
252
278
|
const [showReactDatePicker, setShowReactDatePicker] = React.useState(false);
|
|
279
|
+
const [manualInputValue, setManualInputValue] = React.useState(null);
|
|
253
280
|
const isRange = props.endDate !== undefined;
|
|
254
281
|
const callOnChange = (date, event) => {
|
|
255
282
|
props.onChange(date, event);
|
|
@@ -258,6 +285,10 @@ const DateTimePicker = (_a) => {
|
|
|
258
285
|
setShowReactDatePicker(true);
|
|
259
286
|
};
|
|
260
287
|
const handleOnInputChange = (_, e) => {
|
|
288
|
+
if (props.isEditable) {
|
|
289
|
+
setManualInputValue(e.target.value);
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
261
292
|
if (props.onInputChange) {
|
|
262
293
|
props.onInputChange(e);
|
|
263
294
|
}
|
|
@@ -297,6 +328,7 @@ const DateTimePicker = (_a) => {
|
|
|
297
328
|
if (!shouldKeepOpen) {
|
|
298
329
|
setShowReactDatePicker(false);
|
|
299
330
|
}
|
|
331
|
+
setManualInputValue(null);
|
|
300
332
|
callOnChange(date, event);
|
|
301
333
|
};
|
|
302
334
|
const handleOnReactDatePickerClickOutside = () => {
|
|
@@ -313,12 +345,15 @@ const DateTimePicker = (_a) => {
|
|
|
313
345
|
.join(' - ');
|
|
314
346
|
const getDateTimePickerCustomHeader = (args) => DateTimePickerCustomHeader(Object.assign(Object.assign({}, args), { locale, ariaLabelPreviousMonth: props.ariaLabelPreviousMonth, ariaLabelNextMonth: props.ariaLabelNextMonth }));
|
|
315
347
|
return (React__default.default.createElement(Wrapper, { id: props.id, className: props.className, "data-testid": dataTestId },
|
|
316
|
-
React__default.default.createElement(Input.default, { id: `datetimepicker-input-${props.id}`, name: `datetimepicker-input-${props.id}`, label: props.label, placeholder: props.placeholder, value: formatInputValue, onFocus: handleOnInputFocus, onChange: handleOnInputChange, onKeyDown: handleOnKeyDown, onClearableButtonClick: props.isClearable ? handleClearable : undefined, className: "react-datepicker-ignore-onclickoutside", "data-testid": dataTestId && `${dataTestId}-datetimepicker-input`, disabled: props.isDisabled, required: props.isRequired, readonlyUnstyled: !props.isEditable, status: props.isInError ? 'error' : undefined, errorMessage: props.errorMessage, ariaLabel: props.ariaLabelInput, onBlur: (_val, e) => {
|
|
317
|
-
if (props.isEditable
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
348
|
+
React__default.default.createElement(Input.default, { id: `datetimepicker-input-${props.id}`, name: `datetimepicker-input-${props.id}`, label: props.label, placeholder: props.placeholder, value: manualInputValue !== null && manualInputValue !== void 0 ? manualInputValue : formatInputValue, onFocus: handleOnInputFocus, onChange: handleOnInputChange, onKeyDown: handleOnKeyDown, onClearableButtonClick: props.isClearable ? handleClearable : undefined, className: "react-datepicker-ignore-onclickoutside", "data-testid": dataTestId && `${dataTestId}-datetimepicker-input`, disabled: props.isDisabled, required: props.isRequired, readonlyUnstyled: !props.isEditable, status: props.isInError ? 'error' : undefined, errorMessage: props.errorMessage, ariaLabel: props.ariaLabelInput, onBlur: (_val, e) => {
|
|
349
|
+
if (!props.isEditable || !e.target.value) {
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
const date = locale === 'fi-FI'
|
|
353
|
+
? parseFIDateString(e.target.value)
|
|
354
|
+
: new Date(e.target.value);
|
|
355
|
+
if (date && !Number.isNaN(date.getTime())) {
|
|
356
|
+
callOnChange(date, e);
|
|
322
357
|
}
|
|
323
358
|
} }),
|
|
324
359
|
React__default.default.createElement(VisuallyHiddenStatus, { role: "status", "aria-live": "polite" }, startDate instanceof Date && !Number.isNaN(startDate.getTime())
|
|
@@ -283,14 +283,37 @@ const Categories = ({ categories }) => {
|
|
|
283
283
|
const GeneralInformation = ({ generalInformation }) => {
|
|
284
284
|
const { language } = React.useContext(FooterContext.default);
|
|
285
285
|
const currentYear = new Date().getFullYear();
|
|
286
|
-
const
|
|
286
|
+
const COOKIE_SETTINGS_URL = 'cookie-settings';
|
|
287
|
+
const OT_SDK_CLASSNAME = 'ot-sdk-show-settings';
|
|
288
|
+
// TODO after release: Remove redundant `isNewModelUsed` condition and refactor it's usages (STYLE-905)
|
|
289
|
+
const isNewModelUsed = !!generalInformation.mandatoryLinks;
|
|
287
290
|
const typeToClassMap = {
|
|
288
291
|
cookie: 'ot-sdk-show-settings',
|
|
289
292
|
};
|
|
290
|
-
const
|
|
293
|
+
const orderMap = ['privacyPolicy', 'cookieSettings', 'terms'];
|
|
294
|
+
const getOrderedLinks = () => {
|
|
295
|
+
if (isNewModelUsed && Array.isArray(generalInformation.mandatoryLinks)) {
|
|
296
|
+
return generalInformation.mandatoryLinks;
|
|
297
|
+
}
|
|
298
|
+
return orderMap.map(id => new Map(Object.entries(generalInformation)).get(id));
|
|
299
|
+
};
|
|
300
|
+
const getLinkHref = (item) => {
|
|
301
|
+
var _a;
|
|
302
|
+
if (!((_a = item.urls) === null || _a === void 0 ? void 0 : _a[language]))
|
|
303
|
+
return '#!';
|
|
304
|
+
return item.urls[language] !== COOKIE_SETTINGS_URL ? item.urls[language] : '#!';
|
|
305
|
+
};
|
|
306
|
+
const getLinkClassName = (item) => {
|
|
307
|
+
var _a;
|
|
308
|
+
if (isNewModelUsed) {
|
|
309
|
+
return ((_a = item.urls) === null || _a === void 0 ? void 0 : _a[language]) === COOKIE_SETTINGS_URL ? OT_SDK_CLASSNAME : '';
|
|
310
|
+
}
|
|
311
|
+
return item.type ? typeToClassMap[item.type] : '';
|
|
312
|
+
};
|
|
313
|
+
const orderedGeneralInformation = getOrderedLinks();
|
|
291
314
|
return (React__default.default.createElement(GeneralInformationContainer, { "data-testid": "general-information-section" },
|
|
292
315
|
orderedGeneralInformation.map((item, index) => item && (React__default.default.createElement(React.Fragment, { key: `general-information-link-${index}` },
|
|
293
|
-
React__default.default.createElement("a", { href: (item
|
|
316
|
+
React__default.default.createElement("a", { href: getLinkHref(item), className: getLinkClassName(item) }, item.titles[language]),
|
|
294
317
|
React__default.default.createElement("span", { "aria-hidden": "true" }, "|")))),
|
|
295
318
|
"DNA ",
|
|
296
319
|
currentYear));
|
|
@@ -11,6 +11,7 @@ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'defau
|
|
|
11
11
|
|
|
12
12
|
var React__default = /*#__PURE__*/_interopDefaultCompat(React);
|
|
13
13
|
|
|
14
|
+
/* eslint-disable react/jsx-props-no-spreading */
|
|
14
15
|
const isSelected = (currentUrl, linkUrl, exactMatch = false) => {
|
|
15
16
|
if (currentUrl && linkUrl) {
|
|
16
17
|
let url = linkUrl;
|
|
@@ -23,15 +24,28 @@ const isSelected = (currentUrl, linkUrl, exactMatch = false) => {
|
|
|
23
24
|
};
|
|
24
25
|
const isMenuItemLinkAbsolute = (menuItemLink) => menuItemLink.includes('http');
|
|
25
26
|
const LinkModifier = ({ menuItem, disabledTabIndex, showIcon }) => {
|
|
26
|
-
const { lang, currentUrl, nextJSLinkComponent, resetMenuEvents } = React.useContext(NavContext.default);
|
|
27
|
+
const { lang, currentUrl, nextJSLinkComponent, nextJSLinkLegacyBehavior, resetMenuEvents } = React.useContext(NavContext.default);
|
|
27
28
|
const menuItemLink = menuItem.urls[lang];
|
|
28
29
|
const isExternalLink = menuItem.target === '_blank';
|
|
29
|
-
const
|
|
30
|
+
const linkContent = (React__default.default.createElement(React__default.default.Fragment, null,
|
|
30
31
|
showIcon && (isExternalLink ? React__default.default.createElement(icons.Open, null) : React__default.default.createElement(icons.ArrowRight, null)),
|
|
31
32
|
React__default.default.createElement("span", null, menuItem.titles[lang])));
|
|
33
|
+
const MenuLinkComponent = (React__default.default.createElement(globalNavStyles.MenuLink, { "aria-current": isSelected(currentUrl, menuItemLink) ? 'page' : undefined, href: menuItemLink, id: menuItem.id, onClick: resetMenuEvents, tabIndex: disabledTabIndex ? -1 : undefined, target: isExternalLink ? '_blank' : '_self' }, linkContent));
|
|
34
|
+
const commonLinkProps = {
|
|
35
|
+
'aria-current': isSelected(currentUrl, menuItemLink) ? 'page' : undefined,
|
|
36
|
+
linkUrl: menuItemLink,
|
|
37
|
+
id: menuItem.id,
|
|
38
|
+
onClick: resetMenuEvents,
|
|
39
|
+
tabIndex: disabledTabIndex ? -1 : undefined,
|
|
40
|
+
target: isExternalLink ? '_blank' : '_self',
|
|
41
|
+
};
|
|
32
42
|
if (nextJSLinkComponent && !isMenuItemLinkAbsolute(menuItemLink)) {
|
|
33
43
|
const NextJSLinkComponent = nextJSLinkComponent;
|
|
34
|
-
|
|
44
|
+
if (nextJSLinkLegacyBehavior) {
|
|
45
|
+
return (React__default.default.createElement(NextJSLinkComponent, { linkUrl: menuItemLink },
|
|
46
|
+
React__default.default.createElement(globalNavStyles.MenuLink, Object.assign({}, commonLinkProps), linkContent)));
|
|
47
|
+
}
|
|
48
|
+
return (React__default.default.createElement(globalNavStyles.MenuLink, Object.assign({ as: NextJSLinkComponent }, commonLinkProps), linkContent));
|
|
35
49
|
}
|
|
36
50
|
return MenuLinkComponent;
|
|
37
51
|
};
|
|
@@ -42,10 +42,11 @@ export interface MainHeaderNavigationProps {
|
|
|
42
42
|
isLoggedIn?: boolean;
|
|
43
43
|
collapseSize?: number;
|
|
44
44
|
nextJSLinkComponent: ComponentType | ReactNode | boolean;
|
|
45
|
+
nextJSLinkLegacyBehavior?: boolean;
|
|
45
46
|
currentUrl?: string;
|
|
46
47
|
notificationText?: string;
|
|
47
48
|
}
|
|
48
49
|
/** @visibleName MainHeaderNavigation */
|
|
49
|
-
declare const MainHeaderNavigation: ({ backToPreviousCategoryLabel, businessMenuAriaLabel, categoryCollectionText, closeMainMenuAriaLabel, className, collapseSize, currentUrl, dnaLogoLinkAriaLabel, featuredItemsAriaLabel, isLoggedIn, items, language, languageSelector, languageSelectorText, login, loginComponent, loginText, mainMenuAriaLabel, minicart, minicartAmount, minicartAmountLabel, minicartComponent, minicartText, nextJSLinkComponent, notificationText, openMainMenuAriaLabel, search, searchComponent, searchText, showLoginTooltip, showMinicart, zIndex, ...props }: MainHeaderNavigationProps) => React.JSX.Element;
|
|
50
|
+
declare const MainHeaderNavigation: ({ backToPreviousCategoryLabel, businessMenuAriaLabel, categoryCollectionText, closeMainMenuAriaLabel, className, collapseSize, currentUrl, dnaLogoLinkAriaLabel, featuredItemsAriaLabel, isLoggedIn, items, language, languageSelector, languageSelectorText, login, loginComponent, loginText, mainMenuAriaLabel, minicart, minicartAmount, minicartAmountLabel, minicartComponent, minicartText, nextJSLinkComponent, nextJSLinkLegacyBehavior, notificationText, openMainMenuAriaLabel, search, searchComponent, searchText, showLoginTooltip, showMinicart, zIndex, ...props }: MainHeaderNavigationProps) => React.JSX.Element;
|
|
50
51
|
/** @component */
|
|
51
52
|
export default MainHeaderNavigation;
|
|
@@ -134,7 +134,7 @@ const initiateScrollToHeader = (componentRef) => {
|
|
|
134
134
|
/** @visibleName MainHeaderNavigation */
|
|
135
135
|
const MainHeaderNavigation = (_a) => {
|
|
136
136
|
var _b, _c, _d;
|
|
137
|
-
var { backToPreviousCategoryLabel = '', businessMenuAriaLabel = 'Sivustot', categoryCollectionText = 'Muut kategoriat', closeMainMenuAriaLabel, className, collapseSize = 767, currentUrl = '', dnaLogoLinkAriaLabel, featuredItemsAriaLabel = '', isLoggedIn = false, items = {}, language = 'fi', languageSelector = false, languageSelectorText = 'Vaihda kieltä', login = true, loginComponent, loginText = 'Kirjaudu', mainMenuAriaLabel = 'Päänavigaatio', minicart = true, minicartAmount = 0, minicartAmountLabel, minicartComponent = false, minicartText = 'Ostoskori', nextJSLinkComponent = false, notificationText = '', openMainMenuAriaLabel, search = true, searchComponent = false, searchText = 'Haku', showLoginTooltip = false, showMinicart = false, zIndex = 1030 } = _a, props = tslib.__rest(_a, ["backToPreviousCategoryLabel", "businessMenuAriaLabel", "categoryCollectionText", "closeMainMenuAriaLabel", "className", "collapseSize", "currentUrl", "dnaLogoLinkAriaLabel", "featuredItemsAriaLabel", "isLoggedIn", "items", "language", "languageSelector", "languageSelectorText", "login", "loginComponent", "loginText", "mainMenuAriaLabel", "minicart", "minicartAmount", "minicartAmountLabel", "minicartComponent", "minicartText", "nextJSLinkComponent", "notificationText", "openMainMenuAriaLabel", "search", "searchComponent", "searchText", "showLoginTooltip", "showMinicart", "zIndex"]);
|
|
137
|
+
var { backToPreviousCategoryLabel = '', businessMenuAriaLabel = 'Sivustot', categoryCollectionText = 'Muut kategoriat', closeMainMenuAriaLabel, className, collapseSize = 767, currentUrl = '', dnaLogoLinkAriaLabel, featuredItemsAriaLabel = '', isLoggedIn = false, items = {}, language = 'fi', languageSelector = false, languageSelectorText = 'Vaihda kieltä', login = true, loginComponent, loginText = 'Kirjaudu', mainMenuAriaLabel = 'Päänavigaatio', minicart = true, minicartAmount = 0, minicartAmountLabel, minicartComponent = false, minicartText = 'Ostoskori', nextJSLinkComponent = false, nextJSLinkLegacyBehavior = true, notificationText = '', openMainMenuAriaLabel, search = true, searchComponent = false, searchText = 'Haku', showLoginTooltip = false, showMinicart = false, zIndex = 1030 } = _a, props = tslib.__rest(_a, ["backToPreviousCategoryLabel", "businessMenuAriaLabel", "categoryCollectionText", "closeMainMenuAriaLabel", "className", "collapseSize", "currentUrl", "dnaLogoLinkAriaLabel", "featuredItemsAriaLabel", "isLoggedIn", "items", "language", "languageSelector", "languageSelectorText", "login", "loginComponent", "loginText", "mainMenuAriaLabel", "minicart", "minicartAmount", "minicartAmountLabel", "minicartComponent", "minicartText", "nextJSLinkComponent", "nextJSLinkLegacyBehavior", "notificationText", "openMainMenuAriaLabel", "search", "searchComponent", "searchText", "showLoginTooltip", "showMinicart", "zIndex"]);
|
|
138
138
|
const { isMobile } = useWindowSize.default(collapseSize);
|
|
139
139
|
const navigationEl = React.useRef(null);
|
|
140
140
|
const key = ramda.prop('id');
|
|
@@ -257,6 +257,7 @@ const MainHeaderNavigation = (_a) => {
|
|
|
257
257
|
minicartComponent,
|
|
258
258
|
navZIndex: zIndex,
|
|
259
259
|
nextJSLinkComponent,
|
|
260
|
+
nextJSLinkLegacyBehavior,
|
|
260
261
|
resetMenuEvents,
|
|
261
262
|
searchComponent,
|
|
262
263
|
setTooltipItems,
|
|
@@ -281,6 +282,7 @@ const MainHeaderNavigation = (_a) => {
|
|
|
281
282
|
menuLevel,
|
|
282
283
|
minicartComponent,
|
|
283
284
|
nextJSLinkComponent,
|
|
285
|
+
nextJSLinkLegacyBehavior,
|
|
284
286
|
searchComponent,
|
|
285
287
|
showLoginTooltip,
|
|
286
288
|
showMinicart,
|
|
@@ -20,6 +20,7 @@ export interface NavContextProps {
|
|
|
20
20
|
minicartComponent?: ComponentType | ReactNode | boolean;
|
|
21
21
|
navZIndex: number;
|
|
22
22
|
nextJSLinkComponent: ComponentType | ReactNode | boolean;
|
|
23
|
+
nextJSLinkLegacyBehavior?: boolean;
|
|
23
24
|
resetMenuEvents: () => void;
|
|
24
25
|
searchComponent?: ComponentType | ReactNode | boolean;
|
|
25
26
|
setTooltipItems: Dispatch<SetStateAction<MenuTooltipItems>>;
|
|
@@ -46,7 +46,7 @@ interface RadioButtonProps {
|
|
|
46
46
|
}
|
|
47
47
|
type RadioGroupOption = Omit<RadioButtonProps, 'checked' | 'onChange' | 'name'>;
|
|
48
48
|
type GroupVariant = 'fieldset' | 'radiogroup';
|
|
49
|
-
interface RadioButtonGroupProps extends Omit<RadioButtonProps, 'id' | 'checked' | 'disabled'> {
|
|
49
|
+
interface RadioButtonGroupProps extends Omit<RadioButtonProps, 'id' | 'checked' | 'disabled' | 'label'> {
|
|
50
50
|
/**
|
|
51
51
|
* Unique ID for the radio button group
|
|
52
52
|
*/
|
|
@@ -64,7 +64,7 @@ interface RadioButtonGroupProps extends Omit<RadioButtonProps, 'id' | 'checked'
|
|
|
64
64
|
* Label for the group
|
|
65
65
|
* Will be rendered inside a `<legend>` or a `<div>`, depending on `groupVariant`
|
|
66
66
|
*/
|
|
67
|
-
label?: string;
|
|
67
|
+
label?: string | React.ReactNode;
|
|
68
68
|
/**
|
|
69
69
|
* Helper text shown below the group label
|
|
70
70
|
*/
|
|
@@ -98,9 +98,15 @@ const StyledFieldset = styledComponents.styled.fieldset `
|
|
|
98
98
|
min-inline-size: unset;
|
|
99
99
|
`;
|
|
100
100
|
const RadioButtonGroup = ({ label, description, groupName, value, onChange, id, options, children, groupVariant, className, 'data-testid': dataTestId, }) => {
|
|
101
|
-
var _a;
|
|
102
101
|
const isFieldset = groupVariant === 'fieldset';
|
|
103
|
-
const baseId =
|
|
102
|
+
const baseId = id !== null && id !== void 0 ? id : (typeof label === 'string'
|
|
103
|
+
? label
|
|
104
|
+
.normalize('NFKD')
|
|
105
|
+
.replace(/[\u0300-\u036f]/g, '')
|
|
106
|
+
.replace(/\s+/g, '-')
|
|
107
|
+
.replace(/[^a-zA-Z0-9-_]/g, '')
|
|
108
|
+
.toLowerCase()
|
|
109
|
+
: 'radio-group');
|
|
104
110
|
const labelId = `${baseId}-label`;
|
|
105
111
|
const descriptionId = `${baseId}-description`;
|
|
106
112
|
const combinedDescribedBy = [description ? descriptionId : undefined].filter(Boolean).join(' ');
|
|
@@ -64,6 +64,7 @@ const ErrorMessage = styledComponents.styled(Message) `
|
|
|
64
64
|
const Textarea = (_a) => {
|
|
65
65
|
var { height = 3, 'data-testid': dataTestId, ariaLabel } = _a, props = tslib.__rest(_a, ["height", 'data-testid', "ariaLabel"]);
|
|
66
66
|
const inputRef = React.useRef(null);
|
|
67
|
+
const isErrorStatus = props.status === 'error';
|
|
67
68
|
const handleOnBlur = (e) => {
|
|
68
69
|
if (props.onBlur) {
|
|
69
70
|
props.onBlur(e.target.value, e);
|
|
@@ -80,14 +81,14 @@ const Textarea = (_a) => {
|
|
|
80
81
|
inputRef.current.focus();
|
|
81
82
|
}
|
|
82
83
|
};
|
|
83
|
-
const errorId =
|
|
84
|
+
const errorId = isErrorStatus && props.errorMessage ? `${props.id}-error` : undefined;
|
|
84
85
|
const commentId = props.commentMessage ? `${props.id}-comment` : undefined;
|
|
85
86
|
const describedBy = [errorId, commentId].filter(Boolean).join(' ') || undefined;
|
|
86
87
|
return (React__default.default.createElement(FieldContainer, { className: props.className },
|
|
87
|
-
props.label && (React__default.default.createElement(LabelText.default, { htmlFor: props.id, "data-testid": dataTestId && `${dataTestId}-label`, status:
|
|
88
|
-
React__default.default.createElement(StyledTextarea, { id: props.id, name: props.name, ref: inputRef, value: props.value, rows: height, placeholder: props.placeholder, tabIndex: props.tabIndex, onChange: handleChange, onBlur: handleOnBlur, onFocus: props.onFocus, onClick: onClick, onKeyDown: props.onKeyDown, onKeyPress: props.onKeyPress, required: props.required, disabled: props.disabled, "aria-label": !props.label ? ariaLabel : undefined, "aria-describedby": describedBy, "data-testid": dataTestId }),
|
|
88
|
+
props.label && (React__default.default.createElement(LabelText.default, { htmlFor: props.id, "data-testid": dataTestId && `${dataTestId}-label`, status: isErrorStatus ? 'error' : undefined, isMandatory: props.required }, props.label)),
|
|
89
|
+
React__default.default.createElement(StyledTextarea, { id: props.id, name: props.name, ref: inputRef, value: props.value, rows: height, placeholder: props.placeholder, tabIndex: props.tabIndex, onChange: handleChange, onBlur: handleOnBlur, onFocus: props.onFocus, onClick: onClick, onKeyDown: props.onKeyDown, onKeyPress: props.onKeyPress, required: props.required, disabled: props.disabled, "aria-label": !props.label ? ariaLabel : undefined, "aria-invalid": isErrorStatus, "aria-describedby": describedBy, "data-testid": dataTestId }),
|
|
89
90
|
props.commentMessage && (React__default.default.createElement(Message, { id: commentId, "data-testid": dataTestId && `${dataTestId}-comment` }, props.commentMessage)),
|
|
90
|
-
|
|
91
|
+
isErrorStatus && props.errorMessage && (React__default.default.createElement(ErrorMessage, { id: errorId, "data-testid": dataTestId && `${dataTestId}-error` }, props.errorMessage))));
|
|
91
92
|
};
|
|
92
93
|
|
|
93
94
|
exports.default = Textarea;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { MouseEvent, ReactNode } from 'react';
|
|
1
|
+
import type { ComponentType, MouseEvent, ReactNode } from 'react';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
type ButtonType = 'submit' | 'button' | 'reset';
|
|
4
4
|
export interface Props {
|
|
@@ -24,6 +24,13 @@ export interface Props {
|
|
|
24
24
|
* Allows to change the type of resulting HTML element from button (`<button></button>`) to anchor (`<a href="..."></a>`)
|
|
25
25
|
*/
|
|
26
26
|
href?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Allows to use a custom link component instead of anchor element when `href` is defined
|
|
29
|
+
*/
|
|
30
|
+
nextLink?: ComponentType<{
|
|
31
|
+
href: string;
|
|
32
|
+
children: ReactNode;
|
|
33
|
+
}>;
|
|
27
34
|
/**
|
|
28
35
|
* Allows to set the target attribute for the link
|
|
29
36
|
*/
|
|
@@ -117,8 +117,9 @@ const Element = styled.button `
|
|
|
117
117
|
`;
|
|
118
118
|
/** @visibleName Button */
|
|
119
119
|
const Button = (_a) => {
|
|
120
|
+
var _b;
|
|
120
121
|
var { type = 'submit', 'data-testid': dataTestId, 'data-no-close': dataNoClose, 'data-track-value': dataTrackValue, 'aria-label': ariaLabel } = _a, props = __rest(_a, ["type", 'data-testid', 'data-no-close', 'data-track-value', 'aria-label']);
|
|
121
|
-
return (React__default.createElement(Element, Object.assign({ id: props.id, as: props.href ? 'a' : undefined, type: props.href ? undefined : type, href: props.href, target: props.href ? props.target : undefined, rel: props.target === '_blank' ? 'noopener noreferrer' : undefined, onClick: props.onClick, onMouseDown: props.onMouseDown, "$small": props.small, "$darkBg": props.darkBg, "$fullWidth": props.fullWidth, "$loading": props.loading, tabIndex: props.loading ? -1 : 0, "data-loading": props.loading, className: props.className, "data-testid": dataTestId, "data-no-close": dataNoClose, "data-track-value": dataTrackValue, "aria-label": ariaLabel }, props.dataAttributes, (!props.href && {
|
|
122
|
+
return (React__default.createElement(Element, Object.assign({ id: props.id, as: (_b = props.nextLink) !== null && _b !== void 0 ? _b : (props.href ? 'a' : undefined), type: props.href ? undefined : type, href: props.href, target: props.href ? props.target : undefined, rel: props.target === '_blank' ? 'noopener noreferrer' : undefined, onClick: props.onClick, onMouseDown: props.onMouseDown, "$small": props.small, "$darkBg": props.darkBg, "$fullWidth": props.fullWidth, "$loading": props.loading, tabIndex: props.loading ? -1 : 0, "data-loading": props.loading, className: props.className, "data-testid": dataTestId, "data-no-close": dataNoClose, "data-track-value": dataTrackValue, "aria-label": ariaLabel }, props.dataAttributes, (!props.href && {
|
|
122
123
|
name: props.name,
|
|
123
124
|
disabled: props.disabled,
|
|
124
125
|
})), props.loading ? (React__default.createElement(PixelLoader, { color: props.darkBg ? theme.color.default.white : theme.color.default.plum, label: props.loadingLabel })) : (React__default.createElement("span", { "data-testid": dataTestId && `${dataTestId}-text`, "data-no-close": dataNoClose }, props.children))));
|
|
@@ -47,6 +47,15 @@ const localeData = {
|
|
|
47
47
|
'en-GB': undefined,
|
|
48
48
|
};
|
|
49
49
|
const sentenceCase = (string) => `${string[0].toUpperCase()}${string.slice(1)}`;
|
|
50
|
+
const parseFIDateString = (dateString) => {
|
|
51
|
+
const parts = dateString.split(/\D+/);
|
|
52
|
+
if (!parts || parts.length < 3) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
const [day, month, year] = parts.map(Number);
|
|
56
|
+
const date = new Date(year, month - 1, day);
|
|
57
|
+
return !Number.isNaN(date.getTime()) ? date : null;
|
|
58
|
+
};
|
|
50
59
|
// TODO: change `& .react-datepicker` value back to `1` after z-index of Footer removed
|
|
51
60
|
const Wrapper = styled.div `
|
|
52
61
|
position: relative;
|
|
@@ -102,10 +111,27 @@ const Wrapper = styled.div `
|
|
|
102
111
|
}
|
|
103
112
|
}
|
|
104
113
|
|
|
114
|
+
& .react-datepicker__sr-only {
|
|
115
|
+
position: absolute;
|
|
116
|
+
width: 1px;
|
|
117
|
+
height: 1px;
|
|
118
|
+
padding: 0;
|
|
119
|
+
overflow: hidden;
|
|
120
|
+
clip: rect(0, 0, 0, 0);
|
|
121
|
+
white-space: nowrap;
|
|
122
|
+
border: 0;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
& .react-datepicker__day-names {
|
|
126
|
+
background-color: ${theme.color.background.sand.E01};
|
|
127
|
+
padding: ${getMultipliedSize(theme.base.baseWidth, 0.5)} 0;
|
|
128
|
+
}
|
|
129
|
+
|
|
105
130
|
& .react-datepicker__day-names,
|
|
106
131
|
& .react-datepicker__week {
|
|
107
132
|
display: flex;
|
|
108
133
|
gap: ${getMultipliedSize(theme.base.baseWidth, 0.8)};
|
|
134
|
+
justify-content: center;
|
|
109
135
|
|
|
110
136
|
.react-datepicker__day-name,
|
|
111
137
|
.react-datepicker__day {
|
|
@@ -241,6 +267,7 @@ const DateTimePicker = (_a) => {
|
|
|
241
267
|
var _b, _c, _d;
|
|
242
268
|
var { date: startDate, locale = 'fi-FI', isDatePicker = true, isTimePicker = false, timeInterval = 30, 'data-testid': dataTestId } = _a, props = __rest(_a, ["date", "locale", "isDatePicker", "isTimePicker", "timeInterval", 'data-testid']);
|
|
243
269
|
const [showReactDatePicker, setShowReactDatePicker] = useState(false);
|
|
270
|
+
const [manualInputValue, setManualInputValue] = useState(null);
|
|
244
271
|
const isRange = props.endDate !== undefined;
|
|
245
272
|
const callOnChange = (date, event) => {
|
|
246
273
|
props.onChange(date, event);
|
|
@@ -249,6 +276,10 @@ const DateTimePicker = (_a) => {
|
|
|
249
276
|
setShowReactDatePicker(true);
|
|
250
277
|
};
|
|
251
278
|
const handleOnInputChange = (_, e) => {
|
|
279
|
+
if (props.isEditable) {
|
|
280
|
+
setManualInputValue(e.target.value);
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
252
283
|
if (props.onInputChange) {
|
|
253
284
|
props.onInputChange(e);
|
|
254
285
|
}
|
|
@@ -288,6 +319,7 @@ const DateTimePicker = (_a) => {
|
|
|
288
319
|
if (!shouldKeepOpen) {
|
|
289
320
|
setShowReactDatePicker(false);
|
|
290
321
|
}
|
|
322
|
+
setManualInputValue(null);
|
|
291
323
|
callOnChange(date, event);
|
|
292
324
|
};
|
|
293
325
|
const handleOnReactDatePickerClickOutside = () => {
|
|
@@ -304,12 +336,15 @@ const DateTimePicker = (_a) => {
|
|
|
304
336
|
.join(' - ');
|
|
305
337
|
const getDateTimePickerCustomHeader = (args) => DateTimePickerCustomHeader(Object.assign(Object.assign({}, args), { locale, ariaLabelPreviousMonth: props.ariaLabelPreviousMonth, ariaLabelNextMonth: props.ariaLabelNextMonth }));
|
|
306
338
|
return (React__default.createElement(Wrapper, { id: props.id, className: props.className, "data-testid": dataTestId },
|
|
307
|
-
React__default.createElement(Input, { id: `datetimepicker-input-${props.id}`, name: `datetimepicker-input-${props.id}`, label: props.label, placeholder: props.placeholder, value: formatInputValue, onFocus: handleOnInputFocus, onChange: handleOnInputChange, onKeyDown: handleOnKeyDown, onClearableButtonClick: props.isClearable ? handleClearable : undefined, className: "react-datepicker-ignore-onclickoutside", "data-testid": dataTestId && `${dataTestId}-datetimepicker-input`, disabled: props.isDisabled, required: props.isRequired, readonlyUnstyled: !props.isEditable, status: props.isInError ? 'error' : undefined, errorMessage: props.errorMessage, ariaLabel: props.ariaLabelInput, onBlur: (_val, e) => {
|
|
308
|
-
if (props.isEditable
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
339
|
+
React__default.createElement(Input, { id: `datetimepicker-input-${props.id}`, name: `datetimepicker-input-${props.id}`, label: props.label, placeholder: props.placeholder, value: manualInputValue !== null && manualInputValue !== void 0 ? manualInputValue : formatInputValue, onFocus: handleOnInputFocus, onChange: handleOnInputChange, onKeyDown: handleOnKeyDown, onClearableButtonClick: props.isClearable ? handleClearable : undefined, className: "react-datepicker-ignore-onclickoutside", "data-testid": dataTestId && `${dataTestId}-datetimepicker-input`, disabled: props.isDisabled, required: props.isRequired, readonlyUnstyled: !props.isEditable, status: props.isInError ? 'error' : undefined, errorMessage: props.errorMessage, ariaLabel: props.ariaLabelInput, onBlur: (_val, e) => {
|
|
340
|
+
if (!props.isEditable || !e.target.value) {
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
const date = locale === 'fi-FI'
|
|
344
|
+
? parseFIDateString(e.target.value)
|
|
345
|
+
: new Date(e.target.value);
|
|
346
|
+
if (date && !Number.isNaN(date.getTime())) {
|
|
347
|
+
callOnChange(date, e);
|
|
313
348
|
}
|
|
314
349
|
} }),
|
|
315
350
|
React__default.createElement(VisuallyHiddenStatus, { role: "status", "aria-live": "polite" }, startDate instanceof Date && !Number.isNaN(startDate.getTime())
|
|
@@ -277,14 +277,37 @@ const Categories = ({ categories }) => {
|
|
|
277
277
|
const GeneralInformation = ({ generalInformation }) => {
|
|
278
278
|
const { language } = useContext(FooterContext);
|
|
279
279
|
const currentYear = new Date().getFullYear();
|
|
280
|
-
const
|
|
280
|
+
const COOKIE_SETTINGS_URL = 'cookie-settings';
|
|
281
|
+
const OT_SDK_CLASSNAME = 'ot-sdk-show-settings';
|
|
282
|
+
// TODO after release: Remove redundant `isNewModelUsed` condition and refactor it's usages (STYLE-905)
|
|
283
|
+
const isNewModelUsed = !!generalInformation.mandatoryLinks;
|
|
281
284
|
const typeToClassMap = {
|
|
282
285
|
cookie: 'ot-sdk-show-settings',
|
|
283
286
|
};
|
|
284
|
-
const
|
|
287
|
+
const orderMap = ['privacyPolicy', 'cookieSettings', 'terms'];
|
|
288
|
+
const getOrderedLinks = () => {
|
|
289
|
+
if (isNewModelUsed && Array.isArray(generalInformation.mandatoryLinks)) {
|
|
290
|
+
return generalInformation.mandatoryLinks;
|
|
291
|
+
}
|
|
292
|
+
return orderMap.map(id => new Map(Object.entries(generalInformation)).get(id));
|
|
293
|
+
};
|
|
294
|
+
const getLinkHref = (item) => {
|
|
295
|
+
var _a;
|
|
296
|
+
if (!((_a = item.urls) === null || _a === void 0 ? void 0 : _a[language]))
|
|
297
|
+
return '#!';
|
|
298
|
+
return item.urls[language] !== COOKIE_SETTINGS_URL ? item.urls[language] : '#!';
|
|
299
|
+
};
|
|
300
|
+
const getLinkClassName = (item) => {
|
|
301
|
+
var _a;
|
|
302
|
+
if (isNewModelUsed) {
|
|
303
|
+
return ((_a = item.urls) === null || _a === void 0 ? void 0 : _a[language]) === COOKIE_SETTINGS_URL ? OT_SDK_CLASSNAME : '';
|
|
304
|
+
}
|
|
305
|
+
return item.type ? typeToClassMap[item.type] : '';
|
|
306
|
+
};
|
|
307
|
+
const orderedGeneralInformation = getOrderedLinks();
|
|
285
308
|
return (React__default.createElement(GeneralInformationContainer, { "data-testid": "general-information-section" },
|
|
286
309
|
orderedGeneralInformation.map((item, index) => item && (React__default.createElement(Fragment, { key: `general-information-link-${index}` },
|
|
287
|
-
React__default.createElement("a", { href: (item
|
|
310
|
+
React__default.createElement("a", { href: getLinkHref(item), className: getLinkClassName(item) }, item.titles[language]),
|
|
288
311
|
React__default.createElement("span", { "aria-hidden": "true" }, "|")))),
|
|
289
312
|
"DNA ",
|
|
290
313
|
currentYear));
|
|
@@ -3,6 +3,7 @@ import React__default, { useContext } from 'react';
|
|
|
3
3
|
import NavContext from '../context/NavContext.js';
|
|
4
4
|
import { MenuLink } from '../globalNavStyles.js';
|
|
5
5
|
|
|
6
|
+
/* eslint-disable react/jsx-props-no-spreading */
|
|
6
7
|
const isSelected = (currentUrl, linkUrl, exactMatch = false) => {
|
|
7
8
|
if (currentUrl && linkUrl) {
|
|
8
9
|
let url = linkUrl;
|
|
@@ -15,15 +16,28 @@ const isSelected = (currentUrl, linkUrl, exactMatch = false) => {
|
|
|
15
16
|
};
|
|
16
17
|
const isMenuItemLinkAbsolute = (menuItemLink) => menuItemLink.includes('http');
|
|
17
18
|
const LinkModifier = ({ menuItem, disabledTabIndex, showIcon }) => {
|
|
18
|
-
const { lang, currentUrl, nextJSLinkComponent, resetMenuEvents } = useContext(NavContext);
|
|
19
|
+
const { lang, currentUrl, nextJSLinkComponent, nextJSLinkLegacyBehavior, resetMenuEvents } = useContext(NavContext);
|
|
19
20
|
const menuItemLink = menuItem.urls[lang];
|
|
20
21
|
const isExternalLink = menuItem.target === '_blank';
|
|
21
|
-
const
|
|
22
|
+
const linkContent = (React__default.createElement(React__default.Fragment, null,
|
|
22
23
|
showIcon && (isExternalLink ? React__default.createElement(Open, null) : React__default.createElement(ArrowRight, null)),
|
|
23
24
|
React__default.createElement("span", null, menuItem.titles[lang])));
|
|
25
|
+
const MenuLinkComponent = (React__default.createElement(MenuLink, { "aria-current": isSelected(currentUrl, menuItemLink) ? 'page' : undefined, href: menuItemLink, id: menuItem.id, onClick: resetMenuEvents, tabIndex: disabledTabIndex ? -1 : undefined, target: isExternalLink ? '_blank' : '_self' }, linkContent));
|
|
26
|
+
const commonLinkProps = {
|
|
27
|
+
'aria-current': isSelected(currentUrl, menuItemLink) ? 'page' : undefined,
|
|
28
|
+
linkUrl: menuItemLink,
|
|
29
|
+
id: menuItem.id,
|
|
30
|
+
onClick: resetMenuEvents,
|
|
31
|
+
tabIndex: disabledTabIndex ? -1 : undefined,
|
|
32
|
+
target: isExternalLink ? '_blank' : '_self',
|
|
33
|
+
};
|
|
24
34
|
if (nextJSLinkComponent && !isMenuItemLinkAbsolute(menuItemLink)) {
|
|
25
35
|
const NextJSLinkComponent = nextJSLinkComponent;
|
|
26
|
-
|
|
36
|
+
if (nextJSLinkLegacyBehavior) {
|
|
37
|
+
return (React__default.createElement(NextJSLinkComponent, { linkUrl: menuItemLink },
|
|
38
|
+
React__default.createElement(MenuLink, Object.assign({}, commonLinkProps), linkContent)));
|
|
39
|
+
}
|
|
40
|
+
return (React__default.createElement(MenuLink, Object.assign({ as: NextJSLinkComponent }, commonLinkProps), linkContent));
|
|
27
41
|
}
|
|
28
42
|
return MenuLinkComponent;
|
|
29
43
|
};
|
|
@@ -42,10 +42,11 @@ export interface MainHeaderNavigationProps {
|
|
|
42
42
|
isLoggedIn?: boolean;
|
|
43
43
|
collapseSize?: number;
|
|
44
44
|
nextJSLinkComponent: ComponentType | ReactNode | boolean;
|
|
45
|
+
nextJSLinkLegacyBehavior?: boolean;
|
|
45
46
|
currentUrl?: string;
|
|
46
47
|
notificationText?: string;
|
|
47
48
|
}
|
|
48
49
|
/** @visibleName MainHeaderNavigation */
|
|
49
|
-
declare const MainHeaderNavigation: ({ backToPreviousCategoryLabel, businessMenuAriaLabel, categoryCollectionText, closeMainMenuAriaLabel, className, collapseSize, currentUrl, dnaLogoLinkAriaLabel, featuredItemsAriaLabel, isLoggedIn, items, language, languageSelector, languageSelectorText, login, loginComponent, loginText, mainMenuAriaLabel, minicart, minicartAmount, minicartAmountLabel, minicartComponent, minicartText, nextJSLinkComponent, notificationText, openMainMenuAriaLabel, search, searchComponent, searchText, showLoginTooltip, showMinicart, zIndex, ...props }: MainHeaderNavigationProps) => React.JSX.Element;
|
|
50
|
+
declare const MainHeaderNavigation: ({ backToPreviousCategoryLabel, businessMenuAriaLabel, categoryCollectionText, closeMainMenuAriaLabel, className, collapseSize, currentUrl, dnaLogoLinkAriaLabel, featuredItemsAriaLabel, isLoggedIn, items, language, languageSelector, languageSelectorText, login, loginComponent, loginText, mainMenuAriaLabel, minicart, minicartAmount, minicartAmountLabel, minicartComponent, minicartText, nextJSLinkComponent, nextJSLinkLegacyBehavior, notificationText, openMainMenuAriaLabel, search, searchComponent, searchText, showLoginTooltip, showMinicart, zIndex, ...props }: MainHeaderNavigationProps) => React.JSX.Element;
|
|
50
51
|
/** @component */
|
|
51
52
|
export default MainHeaderNavigation;
|
|
@@ -126,7 +126,7 @@ const initiateScrollToHeader = (componentRef) => {
|
|
|
126
126
|
/** @visibleName MainHeaderNavigation */
|
|
127
127
|
const MainHeaderNavigation = (_a) => {
|
|
128
128
|
var _b, _c, _d;
|
|
129
|
-
var { backToPreviousCategoryLabel = '', businessMenuAriaLabel = 'Sivustot', categoryCollectionText = 'Muut kategoriat', closeMainMenuAriaLabel, className, collapseSize = 767, currentUrl = '', dnaLogoLinkAriaLabel, featuredItemsAriaLabel = '', isLoggedIn = false, items = {}, language = 'fi', languageSelector = false, languageSelectorText = 'Vaihda kieltä', login = true, loginComponent, loginText = 'Kirjaudu', mainMenuAriaLabel = 'Päänavigaatio', minicart = true, minicartAmount = 0, minicartAmountLabel, minicartComponent = false, minicartText = 'Ostoskori', nextJSLinkComponent = false, notificationText = '', openMainMenuAriaLabel, search = true, searchComponent = false, searchText = 'Haku', showLoginTooltip = false, showMinicart = false, zIndex = 1030 } = _a, props = __rest(_a, ["backToPreviousCategoryLabel", "businessMenuAriaLabel", "categoryCollectionText", "closeMainMenuAriaLabel", "className", "collapseSize", "currentUrl", "dnaLogoLinkAriaLabel", "featuredItemsAriaLabel", "isLoggedIn", "items", "language", "languageSelector", "languageSelectorText", "login", "loginComponent", "loginText", "mainMenuAriaLabel", "minicart", "minicartAmount", "minicartAmountLabel", "minicartComponent", "minicartText", "nextJSLinkComponent", "notificationText", "openMainMenuAriaLabel", "search", "searchComponent", "searchText", "showLoginTooltip", "showMinicart", "zIndex"]);
|
|
129
|
+
var { backToPreviousCategoryLabel = '', businessMenuAriaLabel = 'Sivustot', categoryCollectionText = 'Muut kategoriat', closeMainMenuAriaLabel, className, collapseSize = 767, currentUrl = '', dnaLogoLinkAriaLabel, featuredItemsAriaLabel = '', isLoggedIn = false, items = {}, language = 'fi', languageSelector = false, languageSelectorText = 'Vaihda kieltä', login = true, loginComponent, loginText = 'Kirjaudu', mainMenuAriaLabel = 'Päänavigaatio', minicart = true, minicartAmount = 0, minicartAmountLabel, minicartComponent = false, minicartText = 'Ostoskori', nextJSLinkComponent = false, nextJSLinkLegacyBehavior = true, notificationText = '', openMainMenuAriaLabel, search = true, searchComponent = false, searchText = 'Haku', showLoginTooltip = false, showMinicart = false, zIndex = 1030 } = _a, props = __rest(_a, ["backToPreviousCategoryLabel", "businessMenuAriaLabel", "categoryCollectionText", "closeMainMenuAriaLabel", "className", "collapseSize", "currentUrl", "dnaLogoLinkAriaLabel", "featuredItemsAriaLabel", "isLoggedIn", "items", "language", "languageSelector", "languageSelectorText", "login", "loginComponent", "loginText", "mainMenuAriaLabel", "minicart", "minicartAmount", "minicartAmountLabel", "minicartComponent", "minicartText", "nextJSLinkComponent", "nextJSLinkLegacyBehavior", "notificationText", "openMainMenuAriaLabel", "search", "searchComponent", "searchText", "showLoginTooltip", "showMinicart", "zIndex"]);
|
|
130
130
|
const { isMobile } = useWindowSize(collapseSize);
|
|
131
131
|
const navigationEl = useRef(null);
|
|
132
132
|
const key = prop('id');
|
|
@@ -249,6 +249,7 @@ const MainHeaderNavigation = (_a) => {
|
|
|
249
249
|
minicartComponent,
|
|
250
250
|
navZIndex: zIndex,
|
|
251
251
|
nextJSLinkComponent,
|
|
252
|
+
nextJSLinkLegacyBehavior,
|
|
252
253
|
resetMenuEvents,
|
|
253
254
|
searchComponent,
|
|
254
255
|
setTooltipItems,
|
|
@@ -273,6 +274,7 @@ const MainHeaderNavigation = (_a) => {
|
|
|
273
274
|
menuLevel,
|
|
274
275
|
minicartComponent,
|
|
275
276
|
nextJSLinkComponent,
|
|
277
|
+
nextJSLinkLegacyBehavior,
|
|
276
278
|
searchComponent,
|
|
277
279
|
showLoginTooltip,
|
|
278
280
|
showMinicart,
|
|
@@ -20,6 +20,7 @@ export interface NavContextProps {
|
|
|
20
20
|
minicartComponent?: ComponentType | ReactNode | boolean;
|
|
21
21
|
navZIndex: number;
|
|
22
22
|
nextJSLinkComponent: ComponentType | ReactNode | boolean;
|
|
23
|
+
nextJSLinkLegacyBehavior?: boolean;
|
|
23
24
|
resetMenuEvents: () => void;
|
|
24
25
|
searchComponent?: ComponentType | ReactNode | boolean;
|
|
25
26
|
setTooltipItems: Dispatch<SetStateAction<MenuTooltipItems>>;
|
|
@@ -46,7 +46,7 @@ interface RadioButtonProps {
|
|
|
46
46
|
}
|
|
47
47
|
type RadioGroupOption = Omit<RadioButtonProps, 'checked' | 'onChange' | 'name'>;
|
|
48
48
|
type GroupVariant = 'fieldset' | 'radiogroup';
|
|
49
|
-
interface RadioButtonGroupProps extends Omit<RadioButtonProps, 'id' | 'checked' | 'disabled'> {
|
|
49
|
+
interface RadioButtonGroupProps extends Omit<RadioButtonProps, 'id' | 'checked' | 'disabled' | 'label'> {
|
|
50
50
|
/**
|
|
51
51
|
* Unique ID for the radio button group
|
|
52
52
|
*/
|
|
@@ -64,7 +64,7 @@ interface RadioButtonGroupProps extends Omit<RadioButtonProps, 'id' | 'checked'
|
|
|
64
64
|
* Label for the group
|
|
65
65
|
* Will be rendered inside a `<legend>` or a `<div>`, depending on `groupVariant`
|
|
66
66
|
*/
|
|
67
|
-
label?: string;
|
|
67
|
+
label?: string | React.ReactNode;
|
|
68
68
|
/**
|
|
69
69
|
* Helper text shown below the group label
|
|
70
70
|
*/
|
|
@@ -90,9 +90,15 @@ const StyledFieldset = styled.fieldset `
|
|
|
90
90
|
min-inline-size: unset;
|
|
91
91
|
`;
|
|
92
92
|
const RadioButtonGroup = ({ label, description, groupName, value, onChange, id, options, children, groupVariant, className, 'data-testid': dataTestId, }) => {
|
|
93
|
-
var _a;
|
|
94
93
|
const isFieldset = groupVariant === 'fieldset';
|
|
95
|
-
const baseId =
|
|
94
|
+
const baseId = id !== null && id !== void 0 ? id : (typeof label === 'string'
|
|
95
|
+
? label
|
|
96
|
+
.normalize('NFKD')
|
|
97
|
+
.replace(/[\u0300-\u036f]/g, '')
|
|
98
|
+
.replace(/\s+/g, '-')
|
|
99
|
+
.replace(/[^a-zA-Z0-9-_]/g, '')
|
|
100
|
+
.toLowerCase()
|
|
101
|
+
: 'radio-group');
|
|
96
102
|
const labelId = `${baseId}-label`;
|
|
97
103
|
const descriptionId = `${baseId}-description`;
|
|
98
104
|
const combinedDescribedBy = [description ? descriptionId : undefined].filter(Boolean).join(' ');
|
|
@@ -56,6 +56,7 @@ const ErrorMessage = styled(Message) `
|
|
|
56
56
|
const Textarea = (_a) => {
|
|
57
57
|
var { height = 3, 'data-testid': dataTestId, ariaLabel } = _a, props = __rest(_a, ["height", 'data-testid', "ariaLabel"]);
|
|
58
58
|
const inputRef = useRef(null);
|
|
59
|
+
const isErrorStatus = props.status === 'error';
|
|
59
60
|
const handleOnBlur = (e) => {
|
|
60
61
|
if (props.onBlur) {
|
|
61
62
|
props.onBlur(e.target.value, e);
|
|
@@ -72,14 +73,14 @@ const Textarea = (_a) => {
|
|
|
72
73
|
inputRef.current.focus();
|
|
73
74
|
}
|
|
74
75
|
};
|
|
75
|
-
const errorId =
|
|
76
|
+
const errorId = isErrorStatus && props.errorMessage ? `${props.id}-error` : undefined;
|
|
76
77
|
const commentId = props.commentMessage ? `${props.id}-comment` : undefined;
|
|
77
78
|
const describedBy = [errorId, commentId].filter(Boolean).join(' ') || undefined;
|
|
78
79
|
return (React__default.createElement(FieldContainer, { className: props.className },
|
|
79
|
-
props.label && (React__default.createElement(LabelText, { htmlFor: props.id, "data-testid": dataTestId && `${dataTestId}-label`, status:
|
|
80
|
-
React__default.createElement(StyledTextarea, { id: props.id, name: props.name, ref: inputRef, value: props.value, rows: height, placeholder: props.placeholder, tabIndex: props.tabIndex, onChange: handleChange, onBlur: handleOnBlur, onFocus: props.onFocus, onClick: onClick, onKeyDown: props.onKeyDown, onKeyPress: props.onKeyPress, required: props.required, disabled: props.disabled, "aria-label": !props.label ? ariaLabel : undefined, "aria-describedby": describedBy, "data-testid": dataTestId }),
|
|
80
|
+
props.label && (React__default.createElement(LabelText, { htmlFor: props.id, "data-testid": dataTestId && `${dataTestId}-label`, status: isErrorStatus ? 'error' : undefined, isMandatory: props.required }, props.label)),
|
|
81
|
+
React__default.createElement(StyledTextarea, { id: props.id, name: props.name, ref: inputRef, value: props.value, rows: height, placeholder: props.placeholder, tabIndex: props.tabIndex, onChange: handleChange, onBlur: handleOnBlur, onFocus: props.onFocus, onClick: onClick, onKeyDown: props.onKeyDown, onKeyPress: props.onKeyPress, required: props.required, disabled: props.disabled, "aria-label": !props.label ? ariaLabel : undefined, "aria-invalid": isErrorStatus, "aria-describedby": describedBy, "data-testid": dataTestId }),
|
|
81
82
|
props.commentMessage && (React__default.createElement(Message, { id: commentId, "data-testid": dataTestId && `${dataTestId}-comment` }, props.commentMessage)),
|
|
82
|
-
|
|
83
|
+
isErrorStatus && props.errorMessage && (React__default.createElement(ErrorMessage, { id: errorId, "data-testid": dataTestId && `${dataTestId}-error` }, props.errorMessage))));
|
|
83
84
|
};
|
|
84
85
|
|
|
85
86
|
export { Textarea as default };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dnanpm/styleguide",
|
|
3
3
|
"sideEffects": false,
|
|
4
|
-
"version": "v3.11.
|
|
4
|
+
"version": "v3.11.5",
|
|
5
5
|
"main": "build/cjs/index.js",
|
|
6
6
|
"module": "build/es/index.js",
|
|
7
7
|
"jsnext:main": "build/es/index.js",
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"clean": "rm -rf node_modules build dnanpm-styleguide*.tgz",
|
|
26
26
|
"eslint": "cross-env eslint --fix './**/*.{ts,tsx}'",
|
|
27
27
|
"eslint:check": "cross-env eslint './**/*.{ts,tsx}'",
|
|
28
|
-
"format": "cross-env prettier --ignore-path .prettierignore --write --loglevel silent '**/*.{ts,tsx,js,json}'",
|
|
29
|
-
"format:check": "cross-env prettier --ignore-path .prettierignore --check '**/*.{ts,tsx,js,json}'",
|
|
28
|
+
"format": "cross-env prettier --ignore-path .prettierignore --write --loglevel silent '**/*.{ts,tsx,js,json,md}'",
|
|
29
|
+
"format:check": "cross-env prettier --ignore-path .prettierignore --check '**/*.{ts,tsx,js,json,md}'",
|
|
30
30
|
"prepublishOnly": "npm run clean && npm ci && npm run eslint:check && npm run format:check && npm run build",
|
|
31
31
|
"styleguide": "styleguidist server",
|
|
32
32
|
"styleguide:build": "styleguidist build",
|
|
@@ -58,7 +58,6 @@
|
|
|
58
58
|
"@types/node": "^17.0.45",
|
|
59
59
|
"@types/ramda": "^0.27.36",
|
|
60
60
|
"@types/react": "^18.3.11",
|
|
61
|
-
"@types/react-datepicker": "^6.2.0",
|
|
62
61
|
"@types/react-dom": "^18.3.1",
|
|
63
62
|
"@types/react-modal": "^3.13.1",
|
|
64
63
|
"@types/resize-observer-browser": "^0.1.8",
|
|
@@ -72,7 +71,7 @@
|
|
|
72
71
|
"eslint-config-airbnb-typescript": "^17.1.0",
|
|
73
72
|
"eslint-config-prettier": "^10.1.8",
|
|
74
73
|
"eslint-plugin-import": "2.32.0",
|
|
75
|
-
"eslint-plugin-jsdoc": "^
|
|
74
|
+
"eslint-plugin-jsdoc": "^56.1.2",
|
|
76
75
|
"eslint-plugin-jsx-a11y": "^6.10.2",
|
|
77
76
|
"eslint-plugin-prefer-arrow": "^1.2.3",
|
|
78
77
|
"eslint-plugin-react": "^7.37.4",
|
|
@@ -99,7 +98,7 @@
|
|
|
99
98
|
},
|
|
100
99
|
"dependencies": {
|
|
101
100
|
"ramda": "^0.27.1",
|
|
102
|
-
"react-datepicker": "
|
|
101
|
+
"react-datepicker": "8.7.0",
|
|
103
102
|
"react-modal": "^3.16.1",
|
|
104
103
|
"react-select": "^5.8.1",
|
|
105
104
|
"react-spring": "^8.0.27",
|