@telus-uds/components-web 3.1.0 → 3.2.0
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/CHANGELOG.md +16 -2
- package/lib/NavigationBar/NavigationBar.js +69 -15
- package/lib/QuantitySelector/QuantitySelector.js +1 -1
- package/lib/ResponsiveImage/ResponsiveImage.js +7 -1
- package/lib/utils/index.js +2 -1
- package/lib/utils/scrollToAnchor.js +19 -0
- package/package.json +2 -2
- package/src/NavigationBar/NavigationBar.jsx +53 -12
- package/src/QuantitySelector/QuantitySelector.jsx +1 -1
- package/src/ResponsiveImage/ResponsiveImage.jsx +10 -3
- package/src/utils/index.js +3 -1
- package/src/utils/scrollToAnchor.js +18 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,12 +1,26 @@
|
|
|
1
1
|
# Change Log - @telus-uds/components-web
|
|
2
2
|
|
|
3
|
-
<!-- This log was last generated on
|
|
3
|
+
<!-- This log was last generated on Fri, 06 Dec 2024 02:03:26 GMT and should not be manually modified. -->
|
|
4
4
|
|
|
5
5
|
<!-- Start content -->
|
|
6
6
|
|
|
7
|
+
## 3.2.0
|
|
8
|
+
|
|
9
|
+
Fri, 06 Dec 2024 02:03:26 GMT
|
|
10
|
+
|
|
11
|
+
### Minor changes
|
|
12
|
+
|
|
13
|
+
- `NavigationBar`: enable hash navigation (guillermo.peitzner@telus.com)
|
|
14
|
+
- `ChevronLink`, `Search` & `ResponsiveImage`: new `dataSet` prop added to the components to allow the capability to pass data (35577399+JoshHC@users.noreply.github.com)
|
|
15
|
+
- Bump @telus-uds/components-base to v2.2.0
|
|
16
|
+
|
|
17
|
+
### Patches
|
|
18
|
+
|
|
19
|
+
- `QuantitySelector`: render hint when no label is provided (guillermo.peitzner@telus.com)
|
|
20
|
+
|
|
7
21
|
## 3.1.0
|
|
8
22
|
|
|
9
|
-
Mon, 02 Dec 2024 20:
|
|
23
|
+
Mon, 02 Dec 2024 20:29:26 GMT
|
|
10
24
|
|
|
11
25
|
### Minor changes
|
|
12
26
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
var _withLinkRouter$propT, _withLinkRouter$propT2, _withLinkRouter$propT3, _withLinkRouter$propT4;
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import PropTypes from 'prop-types';
|
|
4
|
-
import { selectSystemProps, StackView, Typography, useResponsiveProp, withLinkRouter } from '@telus-uds/components-base';
|
|
4
|
+
import { selectSystemProps, StackView, Typography, useHash, useInputValue, useResponsiveProp, withLinkRouter } from '@telus-uds/components-base';
|
|
5
5
|
import styled from 'styled-components';
|
|
6
|
-
import { htmlAttrs } from '../utils';
|
|
6
|
+
import { htmlAttrs, scrollToAnchor } from '../utils';
|
|
7
7
|
import NavigationItem from './NavigationItem';
|
|
8
8
|
import NavigationSubMenu from './NavigationSubMenu';
|
|
9
9
|
import collapseItems from './collapseItems';
|
|
@@ -33,18 +33,56 @@ const NavigationBar = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
33
33
|
heading,
|
|
34
34
|
headingLevel = 'h1',
|
|
35
35
|
items,
|
|
36
|
-
onChange
|
|
36
|
+
onChange,
|
|
37
37
|
selectedId,
|
|
38
|
+
value,
|
|
38
39
|
LinkRouter,
|
|
39
40
|
linkRouterProps,
|
|
40
41
|
...rest
|
|
41
42
|
} = _ref;
|
|
43
|
+
const {
|
|
44
|
+
currentValue,
|
|
45
|
+
setValue
|
|
46
|
+
} = useInputValue({
|
|
47
|
+
value,
|
|
48
|
+
initialValue: selectedId,
|
|
49
|
+
onChange
|
|
50
|
+
});
|
|
51
|
+
useHash((hash, event) => {
|
|
52
|
+
let hashItem = hash && items.find(_ref2 => {
|
|
53
|
+
let {
|
|
54
|
+
href
|
|
55
|
+
} = _ref2;
|
|
56
|
+
return hash === href;
|
|
57
|
+
});
|
|
58
|
+
if (!hashItem) {
|
|
59
|
+
const parentItem = items.find(_ref3 => {
|
|
60
|
+
let {
|
|
61
|
+
items: parentItems
|
|
62
|
+
} = _ref3;
|
|
63
|
+
return parentItems === null || parentItems === void 0 ? void 0 : parentItems.some(_ref4 => {
|
|
64
|
+
let {
|
|
65
|
+
href
|
|
66
|
+
} = _ref4;
|
|
67
|
+
return hash === href;
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
hashItem = parentItem === null || parentItem === void 0 ? void 0 : parentItem.items.find(_ref5 => {
|
|
71
|
+
let {
|
|
72
|
+
href
|
|
73
|
+
} = _ref5;
|
|
74
|
+
return hash === href;
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
const hashId = hashItem && (hashItem.id || hashItem.label);
|
|
78
|
+
if (hashId) setValue(hashId, event);
|
|
79
|
+
}, [items, setValue]);
|
|
42
80
|
const direction = useResponsiveProp({
|
|
43
81
|
xs: 'column',
|
|
44
82
|
sm: 'row'
|
|
45
83
|
});
|
|
46
84
|
const itemsForViewport = useResponsiveProp({
|
|
47
|
-
xs: collapseItems(items,
|
|
85
|
+
xs: collapseItems(items, currentValue),
|
|
48
86
|
lg: items
|
|
49
87
|
});
|
|
50
88
|
const openOverlayRef = React.useRef(null);
|
|
@@ -118,7 +156,7 @@ const NavigationBar = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
118
156
|
heading: headingLevel,
|
|
119
157
|
children: heading
|
|
120
158
|
})
|
|
121
|
-
}), itemsForViewport === null || itemsForViewport === void 0 ? void 0 : itemsForViewport.map((
|
|
159
|
+
}), itemsForViewport === null || itemsForViewport === void 0 ? void 0 : itemsForViewport.map((_ref6, index) => {
|
|
122
160
|
let {
|
|
123
161
|
href,
|
|
124
162
|
label,
|
|
@@ -129,38 +167,50 @@ const NavigationBar = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
129
167
|
linkRouterProps: itemLinkRouterProps,
|
|
130
168
|
items: nestedItems,
|
|
131
169
|
...itemRest
|
|
132
|
-
} =
|
|
170
|
+
} = _ref6;
|
|
133
171
|
const itemId = id ?? label;
|
|
134
172
|
const handleClick = event => {
|
|
135
173
|
if (nestedItems) {
|
|
136
174
|
setOpenSubMenuId(openSubMenuId !== itemId ? itemId : null);
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
if (href !== null && href !== void 0 && href.startsWith('#')) {
|
|
178
|
+
scrollToAnchor(href, event, () => setValue(itemId, event));
|
|
179
|
+
} else {
|
|
180
|
+
setValue(itemId, event);
|
|
137
181
|
}
|
|
138
182
|
onClick === null || onClick === void 0 || onClick(event);
|
|
139
|
-
onChange === null || onChange === void 0 || onChange(itemId, event);
|
|
140
183
|
};
|
|
141
184
|
const ItemComponent = nestedItems ? NavigationSubMenu : NavigationItem;
|
|
142
185
|
const isOpen = itemId === openSubMenuId;
|
|
186
|
+
const scrollableNestedItems = (nestedItems === null || nestedItems === void 0 ? void 0 : nestedItems.map(item => ({
|
|
187
|
+
...item,
|
|
188
|
+
onPress: event => {
|
|
189
|
+
const nestedItemId = item.id ?? item.label;
|
|
190
|
+
scrollToAnchor(item.href, event, () => setValue(nestedItemId, event));
|
|
191
|
+
}
|
|
192
|
+
}))) ?? nestedItems;
|
|
143
193
|
return /*#__PURE__*/_jsx(ItemComponent, {
|
|
144
194
|
ref: itemRef,
|
|
145
195
|
href: href,
|
|
146
196
|
onClick: handleClick
|
|
147
197
|
// TODO: refactor to pass selected ID via context
|
|
148
198
|
,
|
|
149
|
-
selectedId:
|
|
199
|
+
selectedId: currentValue,
|
|
150
200
|
index: index,
|
|
151
201
|
LinkRouter: ItemLinkRouter,
|
|
152
202
|
linkRouterProps: {
|
|
153
203
|
...linkRouterProps,
|
|
154
204
|
...itemLinkRouterProps
|
|
155
205
|
},
|
|
156
|
-
items:
|
|
157
|
-
selected: itemId ===
|
|
206
|
+
items: scrollableNestedItems,
|
|
207
|
+
selected: itemId === currentValue,
|
|
158
208
|
itemsContainerRef: itemsRef,
|
|
159
209
|
...itemRest,
|
|
160
|
-
...(
|
|
210
|
+
...(scrollableNestedItems && {
|
|
161
211
|
isOpen
|
|
162
212
|
}),
|
|
163
|
-
...(
|
|
213
|
+
...(scrollableNestedItems && isOpen && {
|
|
164
214
|
openOverlayRef
|
|
165
215
|
}),
|
|
166
216
|
children: label
|
|
@@ -177,7 +227,7 @@ NavigationBar.propTypes = {
|
|
|
177
227
|
*
|
|
178
228
|
* Each `item` object must contain:
|
|
179
229
|
* - `heading` - user-facing text in the tab link
|
|
180
|
-
* - `href` - the URL of the page linked to.
|
|
230
|
+
* - `href` - the URL of the page linked to.
|
|
181
231
|
* - `id` - a stable, unique identifier of the page within the set. Not written into the HTML.
|
|
182
232
|
*/
|
|
183
233
|
items: PropTypes.arrayOf(PropTypes.shape({
|
|
@@ -208,13 +258,17 @@ NavigationBar.propTypes = {
|
|
|
208
258
|
*/
|
|
209
259
|
headingLevel: PropTypes.oneOf(['h1', 'h2', 'h3', 'h4', 'h5', 'h6']),
|
|
210
260
|
/**
|
|
211
|
-
*
|
|
261
|
+
* Initial selected item ID
|
|
212
262
|
*/
|
|
213
|
-
selectedId: PropTypes.string
|
|
263
|
+
selectedId: PropTypes.string,
|
|
214
264
|
/**
|
|
215
265
|
* Optional function to be called on pressing a link
|
|
216
266
|
*/
|
|
217
267
|
onChange: PropTypes.func,
|
|
268
|
+
/**
|
|
269
|
+
* Controlled value for selected item ID
|
|
270
|
+
*/
|
|
271
|
+
value: PropTypes.string,
|
|
218
272
|
/**
|
|
219
273
|
* Accesibility role for stackview
|
|
220
274
|
*/
|
|
@@ -78,7 +78,7 @@ const QuantitySelector = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
78
78
|
setError(getCopy('errors').invalidCharacters);
|
|
79
79
|
}
|
|
80
80
|
};
|
|
81
|
-
const renderLabel = () => label ? /*#__PURE__*/_jsx(InputLabel, {
|
|
81
|
+
const renderLabel = () => label || hint ? /*#__PURE__*/_jsx(InputLabel, {
|
|
82
82
|
forId: id,
|
|
83
83
|
label: label,
|
|
84
84
|
hint: hint,
|
|
@@ -25,11 +25,13 @@ const ResponsiveImage = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
25
25
|
fallbackSrc,
|
|
26
26
|
alt,
|
|
27
27
|
loading = 'eager',
|
|
28
|
+
dataSet,
|
|
28
29
|
...rest
|
|
29
30
|
} = _ref;
|
|
30
31
|
return /*#__PURE__*/_jsxs("picture", {
|
|
31
32
|
...selectProps(rest),
|
|
32
33
|
ref: ref,
|
|
34
|
+
...dataSet,
|
|
33
35
|
children: [/*#__PURE__*/_jsx("source", {
|
|
34
36
|
srcSet: xlSrc,
|
|
35
37
|
media: `(min-width: ${viewports.map.get(viewports.xl)}px)`
|
|
@@ -89,6 +91,10 @@ ResponsiveImage.propTypes = {
|
|
|
89
91
|
* @default 'eager'
|
|
90
92
|
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#attr-loading
|
|
91
93
|
*/
|
|
92
|
-
loading: PropTypes.oneOf(['eager', 'lazy'])
|
|
94
|
+
loading: PropTypes.oneOf(['eager', 'lazy']),
|
|
95
|
+
/**
|
|
96
|
+
* The dataSet prop allows to pass data-* attributes element to the component.
|
|
97
|
+
*/
|
|
98
|
+
dataSet: PropTypes.object
|
|
93
99
|
};
|
|
94
100
|
export default ResponsiveImage;
|
package/lib/utils/index.js
CHANGED
|
@@ -7,4 +7,5 @@ import ssrStyles from './ssr';
|
|
|
7
7
|
import isElementFocusable from './isElementFocusable';
|
|
8
8
|
import renderStructuredContent from './renderStructuredContent';
|
|
9
9
|
import useOverlaidPosition from './useOverlaidPosition';
|
|
10
|
-
|
|
10
|
+
import scrollToAnchor from './scrollToAnchor';
|
|
11
|
+
export { deprecate, htmlAttrs, contentfulProps, transformGradient, useTypographyTheme, warn, media, renderStructuredContent, ssrStyles, isElementFocusable, useOverlaidPosition, scrollToAnchor };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scrolls smoothly to the anchor element specified by the href.
|
|
3
|
+
*
|
|
4
|
+
* @param {string} href - The href attribute value, expected to be an anchor link starting with '#'.
|
|
5
|
+
* @param {Event} event - The event object associated with the click or navigation action.
|
|
6
|
+
* @param {Function} onAfterScroll - A callback function to be executed after the scroll action is completed.
|
|
7
|
+
*/
|
|
8
|
+
const scrollToAnchor = (href, event, onAfterScroll) => {
|
|
9
|
+
if (href !== null && href !== void 0 && href.startsWith('#')) {
|
|
10
|
+
event.preventDefault();
|
|
11
|
+
const target = document.getElementById(href.slice(1));
|
|
12
|
+
target === null || target === void 0 || target.scrollIntoView({
|
|
13
|
+
behavior: 'smooth'
|
|
14
|
+
});
|
|
15
|
+
window.location.hash = href;
|
|
16
|
+
onAfterScroll(event);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
export default scrollToAnchor;
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
],
|
|
7
7
|
"dependencies": {
|
|
8
8
|
"@gorhom/portal": "^1.0.14",
|
|
9
|
-
"@telus-uds/components-base": "^2.
|
|
9
|
+
"@telus-uds/components-base": "^2.2.0",
|
|
10
10
|
"@telus-uds/system-constants": "^2.0.0",
|
|
11
11
|
"fscreen": "^1.2.0",
|
|
12
12
|
"lodash.omit": "^4.5.0",
|
|
@@ -81,5 +81,5 @@
|
|
|
81
81
|
"skip": true
|
|
82
82
|
},
|
|
83
83
|
"types": "types/index.d.ts",
|
|
84
|
-
"version": "3.
|
|
84
|
+
"version": "3.2.0"
|
|
85
85
|
}
|
|
@@ -4,11 +4,13 @@ import {
|
|
|
4
4
|
selectSystemProps,
|
|
5
5
|
StackView,
|
|
6
6
|
Typography,
|
|
7
|
+
useHash,
|
|
8
|
+
useInputValue,
|
|
7
9
|
useResponsiveProp,
|
|
8
10
|
withLinkRouter
|
|
9
11
|
} from '@telus-uds/components-base'
|
|
10
12
|
import styled from 'styled-components'
|
|
11
|
-
import { htmlAttrs } from '../utils'
|
|
13
|
+
import { htmlAttrs, scrollToAnchor } from '../utils'
|
|
12
14
|
import NavigationItem from './NavigationItem'
|
|
13
15
|
import NavigationSubMenu from './NavigationSubMenu'
|
|
14
16
|
import collapseItems from './collapseItems'
|
|
@@ -34,16 +36,37 @@ const NavigationBar = React.forwardRef(
|
|
|
34
36
|
heading,
|
|
35
37
|
headingLevel = 'h1',
|
|
36
38
|
items,
|
|
37
|
-
onChange
|
|
39
|
+
onChange,
|
|
38
40
|
selectedId,
|
|
41
|
+
value,
|
|
39
42
|
LinkRouter,
|
|
40
43
|
linkRouterProps,
|
|
41
44
|
...rest
|
|
42
45
|
},
|
|
43
46
|
ref
|
|
44
47
|
) => {
|
|
48
|
+
const { currentValue, setValue } = useInputValue({ value, initialValue: selectedId, onChange })
|
|
49
|
+
|
|
50
|
+
useHash(
|
|
51
|
+
(hash, event) => {
|
|
52
|
+
let hashItem = hash && items.find(({ href }) => hash === href)
|
|
53
|
+
if (!hashItem) {
|
|
54
|
+
const parentItem = items.find(({ items: parentItems }) =>
|
|
55
|
+
parentItems?.some(({ href }) => hash === href)
|
|
56
|
+
)
|
|
57
|
+
hashItem = parentItem?.items.find(({ href }) => hash === href)
|
|
58
|
+
}
|
|
59
|
+
const hashId = hashItem && (hashItem.id || hashItem.label)
|
|
60
|
+
if (hashId) setValue(hashId, event)
|
|
61
|
+
},
|
|
62
|
+
[items, setValue]
|
|
63
|
+
)
|
|
64
|
+
|
|
45
65
|
const direction = useResponsiveProp({ xs: 'column', sm: 'row' })
|
|
46
|
-
const itemsForViewport = useResponsiveProp({
|
|
66
|
+
const itemsForViewport = useResponsiveProp({
|
|
67
|
+
xs: collapseItems(items, currentValue),
|
|
68
|
+
lg: items
|
|
69
|
+
})
|
|
47
70
|
const openOverlayRef = React.useRef(null)
|
|
48
71
|
const [openSubMenuId, setOpenSubMenuId] = React.useState(null)
|
|
49
72
|
const handleSubMenuClose = (event) => {
|
|
@@ -161,14 +184,28 @@ const NavigationBar = React.forwardRef(
|
|
|
161
184
|
const handleClick = (event) => {
|
|
162
185
|
if (nestedItems) {
|
|
163
186
|
setOpenSubMenuId(openSubMenuId !== itemId ? itemId : null)
|
|
187
|
+
return
|
|
188
|
+
}
|
|
189
|
+
if (href?.startsWith('#')) {
|
|
190
|
+
scrollToAnchor(href, event, () => setValue(itemId, event))
|
|
191
|
+
} else {
|
|
192
|
+
setValue(itemId, event)
|
|
164
193
|
}
|
|
165
194
|
onClick?.(event)
|
|
166
|
-
onChange?.(itemId, event)
|
|
167
195
|
}
|
|
168
196
|
|
|
169
197
|
const ItemComponent = nestedItems ? NavigationSubMenu : NavigationItem
|
|
170
198
|
const isOpen = itemId === openSubMenuId
|
|
171
199
|
|
|
200
|
+
const scrollableNestedItems =
|
|
201
|
+
nestedItems?.map((item) => ({
|
|
202
|
+
...item,
|
|
203
|
+
onPress: (event) => {
|
|
204
|
+
const nestedItemId = item.id ?? item.label
|
|
205
|
+
scrollToAnchor(item.href, event, () => setValue(nestedItemId, event))
|
|
206
|
+
}
|
|
207
|
+
})) ?? nestedItems
|
|
208
|
+
|
|
172
209
|
return (
|
|
173
210
|
<ItemComponent
|
|
174
211
|
ref={itemRef}
|
|
@@ -176,16 +213,16 @@ const NavigationBar = React.forwardRef(
|
|
|
176
213
|
href={href}
|
|
177
214
|
onClick={handleClick}
|
|
178
215
|
// TODO: refactor to pass selected ID via context
|
|
179
|
-
selectedId={
|
|
216
|
+
selectedId={currentValue}
|
|
180
217
|
index={index}
|
|
181
218
|
LinkRouter={ItemLinkRouter}
|
|
182
219
|
linkRouterProps={{ ...linkRouterProps, ...itemLinkRouterProps }}
|
|
183
|
-
items={
|
|
184
|
-
selected={itemId ===
|
|
220
|
+
items={scrollableNestedItems}
|
|
221
|
+
selected={itemId === currentValue}
|
|
185
222
|
itemsContainerRef={itemsRef}
|
|
186
223
|
{...itemRest}
|
|
187
|
-
{...(
|
|
188
|
-
{...(
|
|
224
|
+
{...(scrollableNestedItems && { isOpen })}
|
|
225
|
+
{...(scrollableNestedItems && isOpen && { openOverlayRef })}
|
|
189
226
|
>
|
|
190
227
|
{label}
|
|
191
228
|
</ItemComponent>
|
|
@@ -207,7 +244,7 @@ NavigationBar.propTypes = {
|
|
|
207
244
|
*
|
|
208
245
|
* Each `item` object must contain:
|
|
209
246
|
* - `heading` - user-facing text in the tab link
|
|
210
|
-
* - `href` - the URL of the page linked to.
|
|
247
|
+
* - `href` - the URL of the page linked to.
|
|
211
248
|
* - `id` - a stable, unique identifier of the page within the set. Not written into the HTML.
|
|
212
249
|
*/
|
|
213
250
|
items: PropTypes.arrayOf(
|
|
@@ -242,13 +279,17 @@ NavigationBar.propTypes = {
|
|
|
242
279
|
*/
|
|
243
280
|
headingLevel: PropTypes.oneOf(['h1', 'h2', 'h3', 'h4', 'h5', 'h6']),
|
|
244
281
|
/**
|
|
245
|
-
*
|
|
282
|
+
* Initial selected item ID
|
|
246
283
|
*/
|
|
247
|
-
selectedId: PropTypes.string
|
|
284
|
+
selectedId: PropTypes.string,
|
|
248
285
|
/**
|
|
249
286
|
* Optional function to be called on pressing a link
|
|
250
287
|
*/
|
|
251
288
|
onChange: PropTypes.func,
|
|
289
|
+
/**
|
|
290
|
+
* Controlled value for selected item ID
|
|
291
|
+
*/
|
|
292
|
+
value: PropTypes.string,
|
|
252
293
|
/**
|
|
253
294
|
* Accesibility role for stackview
|
|
254
295
|
*/
|
|
@@ -14,9 +14,12 @@ const staticStyles = {
|
|
|
14
14
|
* Provide different image sources for different screen sizes.
|
|
15
15
|
*/
|
|
16
16
|
const ResponsiveImage = React.forwardRef(
|
|
17
|
-
(
|
|
17
|
+
(
|
|
18
|
+
{ xsSrc, smSrc, mdSrc, lgSrc, xlSrc, fallbackSrc, alt, loading = 'eager', dataSet, ...rest },
|
|
19
|
+
ref
|
|
20
|
+
) => {
|
|
18
21
|
return (
|
|
19
|
-
<picture {...selectProps(rest)} ref={ref}>
|
|
22
|
+
<picture {...selectProps(rest)} ref={ref} {...dataSet}>
|
|
20
23
|
<source srcSet={xlSrc} media={`(min-width: ${viewports.map.get(viewports.xl)}px)`} />
|
|
21
24
|
<source srcSet={lgSrc} media={`(min-width: ${viewports.map.get(viewports.lg)}px)`} />
|
|
22
25
|
<source srcSet={mdSrc} media={`(min-width: ${viewports.map.get(viewports.md)}px)`} />
|
|
@@ -65,7 +68,11 @@ ResponsiveImage.propTypes = {
|
|
|
65
68
|
* @default 'eager'
|
|
66
69
|
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#attr-loading
|
|
67
70
|
*/
|
|
68
|
-
loading: PropTypes.oneOf(['eager', 'lazy'])
|
|
71
|
+
loading: PropTypes.oneOf(['eager', 'lazy']),
|
|
72
|
+
/**
|
|
73
|
+
* The dataSet prop allows to pass data-* attributes element to the component.
|
|
74
|
+
*/
|
|
75
|
+
dataSet: PropTypes.object
|
|
69
76
|
}
|
|
70
77
|
|
|
71
78
|
export default ResponsiveImage
|
package/src/utils/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import ssrStyles from './ssr'
|
|
|
7
7
|
import isElementFocusable from './isElementFocusable'
|
|
8
8
|
import renderStructuredContent from './renderStructuredContent'
|
|
9
9
|
import useOverlaidPosition from './useOverlaidPosition'
|
|
10
|
+
import scrollToAnchor from './scrollToAnchor'
|
|
10
11
|
|
|
11
12
|
export {
|
|
12
13
|
deprecate,
|
|
@@ -19,5 +20,6 @@ export {
|
|
|
19
20
|
renderStructuredContent,
|
|
20
21
|
ssrStyles,
|
|
21
22
|
isElementFocusable,
|
|
22
|
-
useOverlaidPosition
|
|
23
|
+
useOverlaidPosition,
|
|
24
|
+
scrollToAnchor
|
|
23
25
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scrolls smoothly to the anchor element specified by the href.
|
|
3
|
+
*
|
|
4
|
+
* @param {string} href - The href attribute value, expected to be an anchor link starting with '#'.
|
|
5
|
+
* @param {Event} event - The event object associated with the click or navigation action.
|
|
6
|
+
* @param {Function} onAfterScroll - A callback function to be executed after the scroll action is completed.
|
|
7
|
+
*/
|
|
8
|
+
const scrollToAnchor = (href, event, onAfterScroll) => {
|
|
9
|
+
if (href?.startsWith('#')) {
|
|
10
|
+
event.preventDefault()
|
|
11
|
+
const target = document.getElementById(href.slice(1))
|
|
12
|
+
target?.scrollIntoView({ behavior: 'smooth' })
|
|
13
|
+
window.location.hash = href
|
|
14
|
+
onAfterScroll(event)
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export default scrollToAnchor
|