@telus-uds/components-base 1.18.1 → 1.19.1
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 +22 -2
- package/component-docs.json +111 -16
- package/jest.config-android.js +17 -0
- package/jest.config-ios.js +18 -0
- package/jest.config-web.js +31 -0
- package/lib/ActivityIndicator/Spinner.js +7 -7
- package/lib/ActivityIndicator/Spinner.native.js +2 -2
- package/lib/BaseProvider/HydrationContext.js +1 -1
- package/lib/BaseProvider/TamaguiProvider.js +30 -0
- package/lib/Button/ButtonBase.js +8 -4
- package/lib/Button/ButtonDropdown.js +207 -0
- package/lib/Button/ButtonGroup.js +1 -1
- package/lib/Carousel/Carousel.js +31 -5
- package/lib/Carousel/CarouselContext.js +1 -1
- package/lib/Carousel/CarouselFirstFocus/CarouselFirstFocus.js +1 -1
- package/lib/Carousel/CarouselTabs/CarouselTabsPanel.js +1 -10
- package/lib/Carousel/CarouselThumbnail.js +2 -2
- package/lib/Checkbox/Checkbox.js +1 -1
- package/lib/Checkbox/CheckboxGroup.js +2 -2
- package/lib/Divider/Divider.js +2 -2
- package/lib/FlexGrid/Col/Col.js +1 -1
- package/lib/Icon/Icon.js +1 -1
- package/lib/MultiSelectFilter/ModalOverlay.js +136 -0
- package/lib/MultiSelectFilter/MultiSelectFilter.js +314 -0
- package/lib/MultiSelectFilter/dictionary.js +19 -0
- package/lib/MultiSelectFilter/index.js +13 -0
- package/lib/Pagination/PageButton.js +2 -2
- package/lib/Pagination/Pagination.js +3 -5
- package/lib/Pagination/SideButton.js +6 -4
- package/lib/Pagination/usePagination.js +2 -2
- package/lib/Progress/ProgressBar.js +3 -3
- package/lib/Progress/ProgressBarBackground.js +3 -3
- package/lib/QuickLinksFeature/QuickLinksFeature.js +91 -0
- package/lib/QuickLinksFeature/QuickLinksFeatureItem.js +157 -0
- package/lib/QuickLinksFeature/index.js +16 -0
- package/lib/Radio/Radio.js +2 -2
- package/lib/Radio/RadioGroup.js +2 -2
- package/lib/RadioCard/RadioCard.js +1 -1
- package/lib/RadioCard/RadioCardGroup.js +2 -2
- package/lib/Responsive/Responsive.js +58 -0
- package/lib/Responsive/index.js +13 -0
- package/lib/Search/Search.js +30 -63
- package/lib/Select/constants.js +15 -0
- package/lib/SideNav/SideNav.js +2 -2
- package/lib/Skeleton/Skeleton.js +1 -1
- package/lib/Skeleton/skeletonWebAnimation.js +1 -1
- package/lib/StackView/StackWrap.js +1 -3
- package/lib/StackView/getStackedContent.js +2 -2
- package/lib/Tabs/Tabs.js +2 -4
- package/lib/Tags/Tags.js +11 -5
- package/lib/TextInput/TextInputBase.js +53 -19
- package/lib/TextInput/dictionary.js +19 -0
- package/lib/ThemeProvider/utils/styles.js +3 -3
- package/lib/ThemeProvider/utils/theme-tokens.js +9 -7
- package/lib/Timeline/Timeline.js +1 -1
- package/lib/ToggleSwitch/ToggleSwitch.js +1 -1
- package/lib/ToggleSwitch/ToggleSwitchGroup.js +1 -1
- package/lib/Tooltip/Backdrop.js +10 -2
- package/lib/Tooltip/Tooltip.native.js +357 -0
- package/lib/Tooltip/shared.js +39 -0
- package/lib/Validator/Validator.js +271 -0
- package/lib/Validator/index.js +13 -0
- package/lib/index.js +9 -0
- package/lib/utils/BaseView/BaseView.js +64 -0
- package/lib/utils/BaseView/BaseView.native.js +16 -0
- package/lib/utils/BaseView/index.js +13 -0
- package/lib/utils/animation/useVerticalExpandAnimation.js +1 -1
- package/lib/utils/children.js +2 -2
- package/lib/utils/floating-ui/index.js +43 -0
- package/lib/utils/floating-ui/index.native.js +43 -0
- package/lib/utils/input.js +12 -6
- package/lib/utils/props/componentPropType.js +3 -3
- package/lib/utils/props/selectSystemProps.js +2 -2
- package/lib/utils/props/tokens.js +2 -2
- package/lib/utils/useOverlaidPosition.js +243 -0
- package/lib/utils/useSpacingScale.js +1 -3
- package/lib/utils/useUniqueId.js +1 -1
- package/lib-module/ActivityIndicator/Spinner.js +7 -7
- package/lib-module/ActivityIndicator/Spinner.native.js +2 -2
- package/lib-module/BaseProvider/HydrationContext.js +1 -1
- package/lib-module/BaseProvider/TamaguiProvider.js +22 -0
- package/lib-module/Button/ButtonBase.js +8 -4
- package/lib-module/Button/ButtonDropdown.js +181 -0
- package/lib-module/Button/ButtonGroup.js +1 -1
- package/lib-module/Carousel/Carousel.js +31 -5
- package/lib-module/Carousel/CarouselContext.js +1 -1
- package/lib-module/Carousel/CarouselFirstFocus/CarouselFirstFocus.js +1 -1
- package/lib-module/Carousel/CarouselTabs/CarouselTabsPanel.js +1 -10
- package/lib-module/Carousel/CarouselThumbnail.js +2 -2
- package/lib-module/Checkbox/Checkbox.js +1 -1
- package/lib-module/Checkbox/CheckboxGroup.js +2 -2
- package/lib-module/Divider/Divider.js +2 -2
- package/lib-module/FlexGrid/Col/Col.js +1 -1
- package/lib-module/Icon/Icon.js +1 -1
- package/lib-module/MultiSelectFilter/ModalOverlay.js +112 -0
- package/lib-module/MultiSelectFilter/MultiSelectFilter.js +286 -0
- package/lib-module/MultiSelectFilter/dictionary.js +12 -0
- package/lib-module/MultiSelectFilter/index.js +2 -0
- package/lib-module/Pagination/PageButton.js +2 -2
- package/lib-module/Pagination/Pagination.js +3 -5
- package/lib-module/Pagination/SideButton.js +6 -4
- package/lib-module/Pagination/usePagination.js +2 -2
- package/lib-module/Progress/ProgressBar.js +3 -3
- package/lib-module/Progress/ProgressBarBackground.js +3 -3
- package/lib-module/QuickLinksFeature/QuickLinksFeature.js +69 -0
- package/lib-module/QuickLinksFeature/QuickLinksFeatureItem.js +130 -0
- package/lib-module/QuickLinksFeature/index.js +4 -0
- package/lib-module/Radio/Radio.js +2 -2
- package/lib-module/Radio/RadioGroup.js +2 -2
- package/lib-module/RadioCard/RadioCard.js +1 -1
- package/lib-module/RadioCard/RadioCardGroup.js +2 -2
- package/lib-module/Responsive/Responsive.js +45 -0
- package/lib-module/Responsive/index.js +2 -0
- package/lib-module/Search/Search.js +30 -61
- package/lib-module/Select/constants.js +5 -0
- package/lib-module/SideNav/SideNav.js +2 -2
- package/lib-module/Skeleton/Skeleton.js +1 -1
- package/lib-module/Skeleton/skeletonWebAnimation.js +1 -1
- package/lib-module/StackView/StackWrap.js +1 -3
- package/lib-module/StackView/getStackedContent.js +2 -2
- package/lib-module/Tabs/Tabs.js +2 -4
- package/lib-module/Tags/Tags.js +11 -5
- package/lib-module/TextInput/TextInputBase.js +52 -19
- package/lib-module/TextInput/dictionary.js +12 -0
- package/lib-module/ThemeProvider/utils/styles.js +3 -3
- package/lib-module/ThemeProvider/utils/theme-tokens.js +9 -7
- package/lib-module/Timeline/Timeline.js +1 -1
- package/lib-module/ToggleSwitch/ToggleSwitch.js +1 -1
- package/lib-module/ToggleSwitch/ToggleSwitchGroup.js +1 -1
- package/lib-module/Tooltip/Backdrop.js +10 -2
- package/lib-module/Tooltip/Tooltip.native.js +326 -0
- package/lib-module/Tooltip/shared.js +27 -0
- package/lib-module/Validator/Validator.js +245 -0
- package/lib-module/Validator/index.js +2 -0
- package/lib-module/index.js +1 -0
- package/lib-module/utils/BaseView/BaseView.js +43 -0
- package/lib-module/utils/BaseView/BaseView.native.js +6 -0
- package/lib-module/utils/BaseView/index.js +2 -0
- package/lib-module/utils/animation/useVerticalExpandAnimation.js +1 -1
- package/lib-module/utils/children.js +2 -2
- package/lib-module/utils/floating-ui/index.js +1 -0
- package/lib-module/utils/floating-ui/index.native.js +1 -0
- package/lib-module/utils/input.js +12 -6
- package/lib-module/utils/props/componentPropType.js +3 -3
- package/lib-module/utils/props/selectSystemProps.js +2 -2
- package/lib-module/utils/props/tokens.js +2 -2
- package/lib-module/utils/useOverlaidPosition.js +232 -0
- package/lib-module/utils/useSpacingScale.js +1 -3
- package/lib-module/utils/useUniqueId.js +1 -1
- package/package.json +7 -4
- package/src/Button/ButtonBase.jsx +4 -2
- package/src/Carousel/Carousel.jsx +42 -10
- package/src/Carousel/CarouselTabs/CarouselTabsPanel.jsx +0 -10
- package/src/Pagination/SideButton.jsx +5 -5
- package/src/Responsive/Responsive.jsx +33 -0
- package/src/Responsive/index.js +3 -0
- package/src/Search/Search.jsx +17 -32
- package/src/Tags/Tags.jsx +46 -33
- package/src/TextInput/TextInputBase.jsx +46 -16
- package/src/index.js +1 -0
|
@@ -136,7 +136,7 @@ const ToggleSwitch = /*#__PURE__*/forwardRef((_ref7, ref) => {
|
|
|
136
136
|
const getButtonTokens = buttonState => selectButtonTokens(getTokens(buttonState));
|
|
137
137
|
|
|
138
138
|
const uniqueId = useUniqueId('toggleSwitch');
|
|
139
|
-
const inputId = id
|
|
139
|
+
const inputId = id ?? uniqueId;
|
|
140
140
|
return /*#__PURE__*/_jsxs(StackView, {
|
|
141
141
|
space: 2,
|
|
142
142
|
direction: "row",
|
|
@@ -63,7 +63,7 @@ const ToggleSwitchGroup = /*#__PURE__*/forwardRef((_ref, ref) => {
|
|
|
63
63
|
const uniqueFields = ['id', 'label'];
|
|
64
64
|
|
|
65
65
|
if (!containUniqueFields(items, uniqueFields)) {
|
|
66
|
-
throw new Error(
|
|
66
|
+
throw new Error(`ToggleSwitchGroup items must have unique ${uniqueFields.join(', ')}`);
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
const toggleSwitches = items.map((_ref2, index) => {
|
|
@@ -8,7 +8,15 @@ function createPortalNode(nodeId) {
|
|
|
8
8
|
// this way the backdrop stays in place when scrolling the window - that's why we need to
|
|
9
9
|
// position it at the scroll position when rendering
|
|
10
10
|
|
|
11
|
-
node.style.cssText =
|
|
11
|
+
node.style.cssText = `
|
|
12
|
+
position: absolute;
|
|
13
|
+
top: ${window.scrollY}px;
|
|
14
|
+
left: ${window.scrollX}px;
|
|
15
|
+
right: 0;
|
|
16
|
+
bottom: 0;
|
|
17
|
+
z-index: 9999;
|
|
18
|
+
pointer-events: none;
|
|
19
|
+
`;
|
|
12
20
|
document.body.appendChild(node);
|
|
13
21
|
return node;
|
|
14
22
|
}
|
|
@@ -29,7 +37,7 @@ function Backdrop(_ref) {
|
|
|
29
37
|
} = _ref;
|
|
30
38
|
const [portalNode, setPortalNode] = useState();
|
|
31
39
|
useEffect(() => {
|
|
32
|
-
const nodeId =
|
|
40
|
+
const nodeId = `tooltip-backdrop-${Date.now()}`;
|
|
33
41
|
const node = createPortalNode(nodeId);
|
|
34
42
|
setPortalNode(node);
|
|
35
43
|
return () => {
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
import React, { forwardRef, useEffect, useRef, useState } from 'react';
|
|
2
|
+
import Dimensions from "react-native-web/dist/exports/Dimensions";
|
|
3
|
+
import Platform from "react-native-web/dist/exports/Platform";
|
|
4
|
+
import Pressable from "react-native-web/dist/exports/Pressable";
|
|
5
|
+
import StyleSheet from "react-native-web/dist/exports/StyleSheet";
|
|
6
|
+
import Text from "react-native-web/dist/exports/Text";
|
|
7
|
+
import View from "react-native-web/dist/exports/View";
|
|
8
|
+
import propTypes from './shared';
|
|
9
|
+
import { applyShadowToken, applyTextStyles, useThemeTokens } from '../ThemeProvider';
|
|
10
|
+
import { a11yProps, selectSystemProps, selectTokens, viewProps } from '../utils';
|
|
11
|
+
import Backdrop from './Backdrop';
|
|
12
|
+
import getTooltipPosition from './getTooltipPosition';
|
|
13
|
+
import TooltipButton from '../TooltipButton';
|
|
14
|
+
import useCopy from '../utils/useCopy';
|
|
15
|
+
import dictionary from './dictionary';
|
|
16
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
17
|
+
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
18
|
+
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
|
|
19
|
+
|
|
20
|
+
const selectTooltipStyles = _ref => {
|
|
21
|
+
let {
|
|
22
|
+
backgroundColor,
|
|
23
|
+
paddingTop,
|
|
24
|
+
paddingBottom,
|
|
25
|
+
paddingLeft,
|
|
26
|
+
paddingRight,
|
|
27
|
+
borderRadius
|
|
28
|
+
} = _ref;
|
|
29
|
+
return {
|
|
30
|
+
backgroundColor,
|
|
31
|
+
paddingTop,
|
|
32
|
+
paddingBottom,
|
|
33
|
+
paddingLeft,
|
|
34
|
+
paddingRight,
|
|
35
|
+
borderRadius
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const selectTooltipShadowStyles = _ref2 => {
|
|
40
|
+
let {
|
|
41
|
+
shadow,
|
|
42
|
+
borderRadius
|
|
43
|
+
} = _ref2;
|
|
44
|
+
return {
|
|
45
|
+
borderRadius,
|
|
46
|
+
...applyShadowToken(shadow)
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const selectTooltipPositionStyles = _ref3 => {
|
|
51
|
+
let {
|
|
52
|
+
top,
|
|
53
|
+
left,
|
|
54
|
+
width
|
|
55
|
+
} = _ref3;
|
|
56
|
+
return {
|
|
57
|
+
top,
|
|
58
|
+
left,
|
|
59
|
+
width
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const selectArrowStyles = (_ref4, _ref5) => {
|
|
64
|
+
let {
|
|
65
|
+
backgroundColor,
|
|
66
|
+
arrowWidth,
|
|
67
|
+
arrowBorderRadius,
|
|
68
|
+
shadow
|
|
69
|
+
} = _ref4;
|
|
70
|
+
let {
|
|
71
|
+
position,
|
|
72
|
+
width: tooltipWidth,
|
|
73
|
+
height: tooltipHeight
|
|
74
|
+
} = _ref5;
|
|
75
|
+
// the arrow width is actually a diagonal of the rectangle that we'll use as a tip
|
|
76
|
+
const rectangleSide = Math.sqrt(arrowWidth * arrowWidth / 2); // position the arrow at the side and center of the tooltip - this happens before rotation
|
|
77
|
+
// so we use the rectangle size as basis
|
|
78
|
+
|
|
79
|
+
const verticalOffset = -1 * rectangleSide / 2;
|
|
80
|
+
const horizontalOffset = rectangleSide / 2; // percentage-based absolute positioning doesn't act well on native, so we have to
|
|
81
|
+
// calculate the pixel values
|
|
82
|
+
|
|
83
|
+
const directionalStyles = {
|
|
84
|
+
above: {
|
|
85
|
+
bottom: verticalOffset,
|
|
86
|
+
left: tooltipWidth / 2 - horizontalOffset,
|
|
87
|
+
transform: [{
|
|
88
|
+
rotateZ: '45deg'
|
|
89
|
+
}]
|
|
90
|
+
},
|
|
91
|
+
below: {
|
|
92
|
+
top: verticalOffset,
|
|
93
|
+
left: tooltipWidth / 2 - horizontalOffset,
|
|
94
|
+
transform: [{
|
|
95
|
+
rotateZ: '-135deg'
|
|
96
|
+
}]
|
|
97
|
+
},
|
|
98
|
+
left: {
|
|
99
|
+
right: verticalOffset,
|
|
100
|
+
top: tooltipHeight / 2 - horizontalOffset,
|
|
101
|
+
transform: [{
|
|
102
|
+
rotateZ: '-45deg'
|
|
103
|
+
}]
|
|
104
|
+
},
|
|
105
|
+
right: {
|
|
106
|
+
left: verticalOffset,
|
|
107
|
+
top: tooltipHeight / 2 - horizontalOffset,
|
|
108
|
+
transform: [{
|
|
109
|
+
rotateZ: '135deg'
|
|
110
|
+
}]
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
return {
|
|
114
|
+
backgroundColor,
|
|
115
|
+
width: rectangleSide,
|
|
116
|
+
height: rectangleSide,
|
|
117
|
+
borderBottomRightRadius: arrowBorderRadius,
|
|
118
|
+
// this corner will be the arrow tip after rotation
|
|
119
|
+
...applyShadowToken(shadow),
|
|
120
|
+
...directionalStyles[position]
|
|
121
|
+
};
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const selectTextStyles = tokens => applyTextStyles(selectTokens('Typography', tokens));
|
|
125
|
+
|
|
126
|
+
const defaultControl = (pressableState, variant) => /*#__PURE__*/_jsx(TooltipButton, {
|
|
127
|
+
pressableState: pressableState,
|
|
128
|
+
variant: variant
|
|
129
|
+
});
|
|
130
|
+
/**
|
|
131
|
+
* Tooltip provides a descriptive and detailed explanation or instructions. It can be used next to an input label
|
|
132
|
+
* to help a user fill it in, or as a standalone component.
|
|
133
|
+
*
|
|
134
|
+
* By default the TooltipButton component will be used as a control for triggering the tooltip, but you may attach
|
|
135
|
+
* a tooltip to any other component. A render function can be used to adjust the control's styling on state changes (hover, focus, etc.).
|
|
136
|
+
*
|
|
137
|
+
* ### Positioning
|
|
138
|
+
* By default a Tooltip will be automatically positioned in a way that ensures it fits within the viewport.
|
|
139
|
+
* You may suggest a position with a prop - it will be used, unless the tooltip would end up outside the viewport.
|
|
140
|
+
*
|
|
141
|
+
* ### Usage criteria
|
|
142
|
+
* - You may use one when the information is useful only to a small percentage of users (ie. tech savvy people wouldn't need this info).
|
|
143
|
+
* - Tooltips may also be useful when vertical space is an issue.
|
|
144
|
+
*/
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
const Tooltip = /*#__PURE__*/forwardRef((_ref6, ref) => {
|
|
148
|
+
let {
|
|
149
|
+
children,
|
|
150
|
+
content,
|
|
151
|
+
position = 'auto',
|
|
152
|
+
copy = 'en',
|
|
153
|
+
tokens,
|
|
154
|
+
variant,
|
|
155
|
+
...rest
|
|
156
|
+
} = _ref6;
|
|
157
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
158
|
+
const controlRef = useRef();
|
|
159
|
+
const [controlLayout, setControlLayout] = useState(null);
|
|
160
|
+
const [tooltipDimensions, setTooltipDimensions] = useState(null);
|
|
161
|
+
const [windowDimensions, setWindowDimensions] = useState(Dimensions.get('window'));
|
|
162
|
+
const [tooltipPosition, setTooltipPosition] = useState(null);
|
|
163
|
+
const getCopy = useCopy({
|
|
164
|
+
dictionary,
|
|
165
|
+
copy
|
|
166
|
+
});
|
|
167
|
+
const themeTokens = useThemeTokens('Tooltip', tokens, variant);
|
|
168
|
+
const {
|
|
169
|
+
arrowWidth,
|
|
170
|
+
arrowOffset
|
|
171
|
+
} = themeTokens;
|
|
172
|
+
useEffect(() => {
|
|
173
|
+
const subscription = Dimensions.addEventListener('change', _ref7 => {
|
|
174
|
+
let {
|
|
175
|
+
window
|
|
176
|
+
} = _ref7;
|
|
177
|
+
setWindowDimensions(window);
|
|
178
|
+
});
|
|
179
|
+
return () => subscription === null || subscription === void 0 ? void 0 : subscription.remove();
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
const toggleIsOpen = () => setIsOpen(!isOpen);
|
|
183
|
+
|
|
184
|
+
const close = () => setIsOpen(false);
|
|
185
|
+
|
|
186
|
+
const getPressableState = _ref8 => {
|
|
187
|
+
let {
|
|
188
|
+
pressed,
|
|
189
|
+
hovered,
|
|
190
|
+
focused
|
|
191
|
+
} = _ref8;
|
|
192
|
+
return {
|
|
193
|
+
pressed,
|
|
194
|
+
hover: hovered,
|
|
195
|
+
focus: focused
|
|
196
|
+
};
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
const onTooltipLayout = _ref9 => {
|
|
200
|
+
let {
|
|
201
|
+
nativeEvent: {
|
|
202
|
+
layout: {
|
|
203
|
+
width,
|
|
204
|
+
height
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
} = _ref9;
|
|
208
|
+
|
|
209
|
+
if (tooltipDimensions === null || tooltipDimensions.width !== width || tooltipDimensions.height !== height) {
|
|
210
|
+
setTooltipDimensions({
|
|
211
|
+
width: Platform.select({
|
|
212
|
+
web: width + 0.3,
|
|
213
|
+
// avoids often unnecessary line breaks due to subpixel rendering of fonts
|
|
214
|
+
native: width
|
|
215
|
+
}),
|
|
216
|
+
height
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
useEffect(() => {
|
|
222
|
+
if (isOpen) {
|
|
223
|
+
controlRef.current.measureInWindow((x, y, width, height) => {
|
|
224
|
+
setControlLayout({
|
|
225
|
+
x,
|
|
226
|
+
y,
|
|
227
|
+
width,
|
|
228
|
+
height
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
} else {
|
|
232
|
+
setControlLayout(null);
|
|
233
|
+
setTooltipDimensions(null);
|
|
234
|
+
setTooltipPosition(null);
|
|
235
|
+
}
|
|
236
|
+
}, [isOpen]);
|
|
237
|
+
useEffect(() => {
|
|
238
|
+
setIsOpen(false);
|
|
239
|
+
}, [windowDimensions]);
|
|
240
|
+
useEffect(() => {
|
|
241
|
+
if (tooltipPosition !== null && !(tooltipPosition !== null && tooltipPosition !== void 0 && tooltipPosition.isNormalized) || !isOpen || controlLayout === null || tooltipDimensions == null) {
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const updatedPosition = getTooltipPosition(position, {
|
|
246
|
+
controlLayout,
|
|
247
|
+
tooltipDimensions,
|
|
248
|
+
windowDimensions,
|
|
249
|
+
arrowWidth,
|
|
250
|
+
arrowOffset
|
|
251
|
+
}); // avoid ending up in an infinite normalization loop
|
|
252
|
+
|
|
253
|
+
if (tooltipPosition !== null && tooltipPosition !== void 0 && tooltipPosition.isNormalized && updatedPosition.isNormalized) {
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
setTooltipPosition(updatedPosition);
|
|
258
|
+
}, [isOpen, position, tooltipDimensions, controlLayout, windowDimensions, arrowWidth, arrowOffset, tooltipPosition]);
|
|
259
|
+
const control = children !== undefined ? children : defaultControl;
|
|
260
|
+
const pressableStyles = control === defaultControl ? Platform.select({
|
|
261
|
+
web: {
|
|
262
|
+
outline: 'none'
|
|
263
|
+
}
|
|
264
|
+
}) : undefined;
|
|
265
|
+
const pressableHitSlop = control === defaultControl ? {
|
|
266
|
+
top: 10,
|
|
267
|
+
bottom: 10,
|
|
268
|
+
left: 10,
|
|
269
|
+
right: 10
|
|
270
|
+
} : undefined;
|
|
271
|
+
return /*#__PURE__*/_jsxs(View, {
|
|
272
|
+
style: staticStyles.container,
|
|
273
|
+
...selectProps(rest),
|
|
274
|
+
children: [/*#__PURE__*/_jsx(Pressable, {
|
|
275
|
+
onPress: toggleIsOpen,
|
|
276
|
+
ref: controlRef,
|
|
277
|
+
onBlur: close,
|
|
278
|
+
style: pressableStyles,
|
|
279
|
+
hitSlop: pressableHitSlop,
|
|
280
|
+
accessibilityLabel: getCopy('a11yText'),
|
|
281
|
+
accessibilityRole: "button",
|
|
282
|
+
children: typeof control === 'function' ? pressableState => control(getPressableState(pressableState), variant) : control
|
|
283
|
+
}), isOpen && /*#__PURE__*/_jsx(Backdrop, {
|
|
284
|
+
onPress: close,
|
|
285
|
+
children: /*#__PURE__*/_jsxs(View, {
|
|
286
|
+
ref: ref,
|
|
287
|
+
style: [staticStyles.tooltip, selectTooltipShadowStyles(themeTokens), // applied separately so that it doesn't cover the arrow
|
|
288
|
+
tooltipPosition && selectTooltipPositionStyles(tooltipPosition), (tooltipPosition === null || (tooltipPosition === null || tooltipPosition === void 0 ? void 0 : tooltipPosition.isNormalized)) && staticStyles.tooltipHidden // visually hide the tooltip until we have a final measurement
|
|
289
|
+
],
|
|
290
|
+
onLayout: onTooltipLayout,
|
|
291
|
+
accessibilityRole: "alert",
|
|
292
|
+
children: [/*#__PURE__*/_jsx(View, {
|
|
293
|
+
style: [staticStyles.arrow, tooltipPosition && selectArrowStyles(themeTokens, tooltipPosition)]
|
|
294
|
+
}), /*#__PURE__*/_jsx(View, {
|
|
295
|
+
style: selectTooltipStyles(themeTokens),
|
|
296
|
+
children: /*#__PURE__*/_jsx(Text, {
|
|
297
|
+
style: selectTextStyles(themeTokens),
|
|
298
|
+
children: content
|
|
299
|
+
})
|
|
300
|
+
})]
|
|
301
|
+
})
|
|
302
|
+
})]
|
|
303
|
+
});
|
|
304
|
+
});
|
|
305
|
+
Tooltip.displayName = 'NativeTooltip';
|
|
306
|
+
Tooltip.propTypes = { ...selectedSystemPropTypes,
|
|
307
|
+
...propTypes
|
|
308
|
+
};
|
|
309
|
+
export default Tooltip;
|
|
310
|
+
const staticStyles = StyleSheet.create({
|
|
311
|
+
container: {
|
|
312
|
+
alignItems: 'flex-start'
|
|
313
|
+
},
|
|
314
|
+
tooltip: {
|
|
315
|
+
position: 'absolute',
|
|
316
|
+
maxWidth: 240,
|
|
317
|
+
top: 0,
|
|
318
|
+
left: 0
|
|
319
|
+
},
|
|
320
|
+
tooltipHidden: {
|
|
321
|
+
opacity: 0
|
|
322
|
+
},
|
|
323
|
+
arrow: {
|
|
324
|
+
position: 'absolute'
|
|
325
|
+
}
|
|
326
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import PropTypes from 'prop-types';
|
|
2
|
+
import { getTokensPropType, variantProp } from '../utils';
|
|
3
|
+
const propTypes = {
|
|
4
|
+
/**
|
|
5
|
+
* Used to render the control (i.e. tooltip trigger). If a render function is used it will receive the
|
|
6
|
+
* pressable state and tooltip variant as an argument.
|
|
7
|
+
*/
|
|
8
|
+
children: PropTypes.oneOfType([PropTypes.func, PropTypes.node]),
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The message. Can be raw text or text components.
|
|
12
|
+
*/
|
|
13
|
+
content: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Select English or French copy for the accessible label.
|
|
17
|
+
*/
|
|
18
|
+
copy: PropTypes.oneOf(['en', 'fr']),
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Use to place the tooltip in a specific location (only if it fits within viewport).
|
|
22
|
+
*/
|
|
23
|
+
position: PropTypes.oneOf(['auto', 'above', 'right', 'below', 'left']),
|
|
24
|
+
tokens: getTokensPropType('Tooltip'),
|
|
25
|
+
variant: variantProp.propType
|
|
26
|
+
};
|
|
27
|
+
export default propTypes;
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import React, { forwardRef, createRef, useRef, useMemo, useEffect, useState } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import View from "react-native-web/dist/exports/View";
|
|
4
|
+
import StyleSheet from "react-native-web/dist/exports/StyleSheet";
|
|
5
|
+
import Platform from "react-native-web/dist/exports/Platform";
|
|
6
|
+
import { inputSupportsProps, selectSystemProps } from '../utils';
|
|
7
|
+
import { TextInput } from '../TextInput';
|
|
8
|
+
import StackView from '../StackView';
|
|
9
|
+
import InputSupports from '../InputSupports';
|
|
10
|
+
import { useThemeTokens } from '../ThemeProvider';
|
|
11
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
12
|
+
const [selectProps, selectedSystemPropTypes] = selectSystemProps([inputSupportsProps]);
|
|
13
|
+
|
|
14
|
+
const selectCodeTextInputTokens = _ref => {
|
|
15
|
+
let {
|
|
16
|
+
outerBorderColor,
|
|
17
|
+
outerBackgroundColor
|
|
18
|
+
} = _ref;
|
|
19
|
+
return {
|
|
20
|
+
outerBorderColor,
|
|
21
|
+
outerBackgroundColor,
|
|
22
|
+
icon: null
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const Validator = /*#__PURE__*/forwardRef((_ref2, ref) => {
|
|
27
|
+
let {
|
|
28
|
+
value = '',
|
|
29
|
+
inactive,
|
|
30
|
+
onChange,
|
|
31
|
+
tokens = {},
|
|
32
|
+
variant = {},
|
|
33
|
+
...rest
|
|
34
|
+
} = _ref2;
|
|
35
|
+
const defaultRef = useRef();
|
|
36
|
+
const codeRef = ref ?? defaultRef;
|
|
37
|
+
const {
|
|
38
|
+
supportsProps
|
|
39
|
+
} = selectProps(rest);
|
|
40
|
+
const strValidation = supportsProps.validation;
|
|
41
|
+
const [individualCodes, setIndividualCodes] = useState({});
|
|
42
|
+
const [text, setText] = useState(value);
|
|
43
|
+
const validatorsLength = 6;
|
|
44
|
+
const prefix = 'code';
|
|
45
|
+
const sufixValidation = 'Validation';
|
|
46
|
+
const [isHover, setIsHover] = useState(false);
|
|
47
|
+
|
|
48
|
+
const handleMouseOver = () => {
|
|
49
|
+
setIsHover(true);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const handleMouseOut = () => {
|
|
53
|
+
setIsHover(false);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const themeTokens = useThemeTokens('TextInput', tokens, variant, {
|
|
57
|
+
hover: isHover
|
|
58
|
+
});
|
|
59
|
+
const [codeReferences, singleCodes] = useMemo(() => {
|
|
60
|
+
const codes = [];
|
|
61
|
+
const valueCodes = {};
|
|
62
|
+
|
|
63
|
+
for (let i = 0; validatorsLength && i < validatorsLength; i += 1) {
|
|
64
|
+
codes[prefix + i] = /*#__PURE__*/createRef();
|
|
65
|
+
valueCodes[prefix + i] = '';
|
|
66
|
+
valueCodes[prefix + i + sufixValidation] = '';
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return [codes, valueCodes];
|
|
70
|
+
}, []);
|
|
71
|
+
|
|
72
|
+
const handleSingleCodes = (codeId, val, validation) => {
|
|
73
|
+
singleCodes[codeId] = val;
|
|
74
|
+
singleCodes[codeId + sufixValidation] = validation;
|
|
75
|
+
/* eslint-disable no-unused-expressions */
|
|
76
|
+
|
|
77
|
+
setIndividualCodes({ ...individualCodes,
|
|
78
|
+
[codeId]: val
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const handleChangeCode = () => {
|
|
83
|
+
let code = '';
|
|
84
|
+
|
|
85
|
+
for (let i = 0; i < validatorsLength; i += 1) code += singleCodes[prefix + i];
|
|
86
|
+
|
|
87
|
+
if (typeof onChange === 'function') onChange(code, singleCodes);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const handleChangeCodeValues = (event, codeId, nextIndex) => {
|
|
91
|
+
var _codeReferences$codeI, _event$nativeEvent, _event$target, _codeElement$value, _codeElement$value2;
|
|
92
|
+
|
|
93
|
+
const codeElement = (_codeReferences$codeI = codeReferences[codeId]) === null || _codeReferences$codeI === void 0 ? void 0 : _codeReferences$codeI.current;
|
|
94
|
+
const val = ((_event$nativeEvent = event.nativeEvent) === null || _event$nativeEvent === void 0 ? void 0 : _event$nativeEvent.value) || ((_event$target = event.target) === null || _event$target === void 0 ? void 0 : _event$target.value);
|
|
95
|
+
|
|
96
|
+
if (Number(val).toString() === 'NaN') {
|
|
97
|
+
codeElement.value = singleCodes[codeId] ?? '';
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if ((codeElement === null || codeElement === void 0 ? void 0 : (_codeElement$value = codeElement.value) === null || _codeElement$value === void 0 ? void 0 : _codeElement$value.length) > 1) {
|
|
102
|
+
const oldValue = singleCodes[codeId];
|
|
103
|
+
const newValue = codeElement.value.replace(oldValue, '');
|
|
104
|
+
codeElement.value = newValue;
|
|
105
|
+
handleSingleCodes(codeId, codeElement.value, 'success');
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
handleSingleCodes(codeId, (codeElement === null || codeElement === void 0 ? void 0 : codeElement.value) ?? singleCodes[codeId], 'success');
|
|
109
|
+
handleChangeCode();
|
|
110
|
+
|
|
111
|
+
if (nextIndex === validatorsLength) {
|
|
112
|
+
codeElement.blur();
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if ((codeElement === null || codeElement === void 0 ? void 0 : (_codeElement$value2 = codeElement.value) === null || _codeElement$value2 === void 0 ? void 0 : _codeElement$value2.length) > 0) codeReferences[prefix + nextIndex].current.focus();
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const handleKeyPress = (event, currentIndex, previousIndex) => {
|
|
120
|
+
if (!(event.keyCode === 8 || event.code === 'Backspace')) return;
|
|
121
|
+
|
|
122
|
+
if (currentIndex > 0) {
|
|
123
|
+
codeReferences[prefix + currentIndex].current.value = '';
|
|
124
|
+
codeReferences[prefix + previousIndex].current.focus();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
handleSingleCodes(prefix + currentIndex, '', '');
|
|
128
|
+
handleChangeCode();
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
const getCodeComponents = () => {
|
|
132
|
+
const components = [];
|
|
133
|
+
|
|
134
|
+
for (let i = 0; validatorsLength && i < validatorsLength; i += 1) {
|
|
135
|
+
const codeId = prefix + i;
|
|
136
|
+
const codeInputProps = {
|
|
137
|
+
nativeID: codeId,
|
|
138
|
+
keyboardType: 'numeric',
|
|
139
|
+
ref: codeReferences[codeId] ?? null,
|
|
140
|
+
validation: strValidation || singleCodes[codeId + sufixValidation],
|
|
141
|
+
tokens: selectCodeTextInputTokens(themeTokens),
|
|
142
|
+
onFocus: () => {
|
|
143
|
+
var _codeReferences$codeI2, _codeReferences$codeI3;
|
|
144
|
+
|
|
145
|
+
return ((_codeReferences$codeI2 = codeReferences[codeId]) === null || _codeReferences$codeI2 === void 0 ? void 0 : (_codeReferences$codeI3 = _codeReferences$codeI2.current) === null || _codeReferences$codeI3 === void 0 ? void 0 : _codeReferences$codeI3.select()) ?? null;
|
|
146
|
+
},
|
|
147
|
+
onKeyPress: event => handleKeyPress(event, i, i - 1),
|
|
148
|
+
onMouseOver: handleMouseOver,
|
|
149
|
+
onMouseOut: handleMouseOut,
|
|
150
|
+
inactive
|
|
151
|
+
};
|
|
152
|
+
codeInputProps.validation || delete codeInputProps.validation;
|
|
153
|
+
components.push( /*#__PURE__*/_jsx(View, {
|
|
154
|
+
style: staticStyles.codeInputWidth,
|
|
155
|
+
children: /*#__PURE__*/_jsx(TextInput, { ...codeInputProps
|
|
156
|
+
})
|
|
157
|
+
}, codeId));
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return components;
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
useEffect(() => {
|
|
164
|
+
/* eslint-disable no-unused-expressions */
|
|
165
|
+
if (Number(value).toString() !== 'NaN') setText(value);
|
|
166
|
+
}, [value]);
|
|
167
|
+
/* eslint-disable react-hooks/exhaustive-deps */
|
|
168
|
+
|
|
169
|
+
useEffect(() => {
|
|
170
|
+
for (let i = 0; i < validatorsLength; i += 1) {
|
|
171
|
+
codeReferences[prefix + i].current.value = text[i] ?? '';
|
|
172
|
+
handleSingleCodes(prefix + i, text[i] ?? '', text[i] ? 'success' : '');
|
|
173
|
+
}
|
|
174
|
+
}, [text]);
|
|
175
|
+
/* eslint-disable react-hooks/exhaustive-deps */
|
|
176
|
+
|
|
177
|
+
useEffect(() => {
|
|
178
|
+
const handlePasteCode = event => {
|
|
179
|
+
setText('');
|
|
180
|
+
const clipBoardText = event.clipboardData.getData('text');
|
|
181
|
+
if (Number(clipBoardText).toString() !== 'NaN') setText(clipBoardText);
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
const handleCopy = event => {
|
|
185
|
+
let clipBoardText = '';
|
|
186
|
+
|
|
187
|
+
for (let i = 0; i < validatorsLength; i += 1) singleCodes[prefix + i] && (clipBoardText += singleCodes[prefix + i]);
|
|
188
|
+
|
|
189
|
+
event.clipboardData.setData('text/plain', clipBoardText);
|
|
190
|
+
event.preventDefault();
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
if (Platform.OS === 'web') {
|
|
194
|
+
for (let i = 0; i < validatorsLength; i += 1) {
|
|
195
|
+
codeReferences[prefix + i].current.addEventListener('paste', handlePasteCode);
|
|
196
|
+
codeReferences[prefix + i].current.addEventListener('copy', handleCopy);
|
|
197
|
+
codeReferences[prefix + i].current.addEventListener('input', event => handleChangeCodeValues(event, prefix + i, i + 1));
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return () => {
|
|
202
|
+
if (Platform.oldValue === 'web') {
|
|
203
|
+
for (let i = 0; i < validatorsLength; i += 1) {
|
|
204
|
+
var _codeReferences, _codeReferences$curre, _codeReferences2, _codeReferences2$curr, _codeReferences3, _codeReferences3$curr;
|
|
205
|
+
|
|
206
|
+
(_codeReferences = codeReferences[prefix + i]) === null || _codeReferences === void 0 ? void 0 : (_codeReferences$curre = _codeReferences.current) === null || _codeReferences$curre === void 0 ? void 0 : _codeReferences$curre.removeEventListener('paste', handlePasteCode);
|
|
207
|
+
(_codeReferences2 = codeReferences[prefix + i]) === null || _codeReferences2 === void 0 ? void 0 : (_codeReferences2$curr = _codeReferences2.current) === null || _codeReferences2$curr === void 0 ? void 0 : _codeReferences2$curr.removeEventListener('copy', handleCopy);
|
|
208
|
+
(_codeReferences3 = codeReferences[prefix + i]) === null || _codeReferences3 === void 0 ? void 0 : (_codeReferences3$curr = _codeReferences3.current) === null || _codeReferences3$curr === void 0 ? void 0 : _codeReferences3$curr.removeEventListener('input', event => handleChangeCodeValues(event, prefix + i, i + 1));
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
}, []);
|
|
213
|
+
return /*#__PURE__*/_jsx(InputSupports, { ...supportsProps,
|
|
214
|
+
children: /*#__PURE__*/_jsx(StackView, {
|
|
215
|
+
space: 2,
|
|
216
|
+
direction: "row",
|
|
217
|
+
ref: codeRef,
|
|
218
|
+
children: getCodeComponents()
|
|
219
|
+
})
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
Validator.displayName = 'Validator';
|
|
223
|
+
Validator.propTypes = { ...selectedSystemPropTypes,
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* The value is a 6-digit code, may be only numeric characters, non numeric character aren't renderize
|
|
227
|
+
*/
|
|
228
|
+
value: PropTypes.string,
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* If true, the component is inactive and non editable.
|
|
232
|
+
*/
|
|
233
|
+
inactive: PropTypes.bool,
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Use to react upon input's value changes. Required when the `value` prop is set. Will receive the input's value as an argument.
|
|
237
|
+
*/
|
|
238
|
+
onChange: PropTypes.func
|
|
239
|
+
};
|
|
240
|
+
export default Validator;
|
|
241
|
+
const staticStyles = StyleSheet.create({
|
|
242
|
+
codeInputWidth: {
|
|
243
|
+
width: 43
|
|
244
|
+
}
|
|
245
|
+
});
|
package/lib-module/index.js
CHANGED
|
@@ -29,6 +29,7 @@ export { default as Radio } from './Radio';
|
|
|
29
29
|
export * from './Radio';
|
|
30
30
|
export { default as RadioCard } from './RadioCard';
|
|
31
31
|
export * from './RadioCard';
|
|
32
|
+
export { default as Responsive } from './Responsive';
|
|
32
33
|
export { default as Search } from './Search';
|
|
33
34
|
export { default as Select } from './Select';
|
|
34
35
|
export { default as SideNav } from './SideNav';
|