@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.
Files changed (160) hide show
  1. package/CHANGELOG.md +22 -2
  2. package/component-docs.json +111 -16
  3. package/jest.config-android.js +17 -0
  4. package/jest.config-ios.js +18 -0
  5. package/jest.config-web.js +31 -0
  6. package/lib/ActivityIndicator/Spinner.js +7 -7
  7. package/lib/ActivityIndicator/Spinner.native.js +2 -2
  8. package/lib/BaseProvider/HydrationContext.js +1 -1
  9. package/lib/BaseProvider/TamaguiProvider.js +30 -0
  10. package/lib/Button/ButtonBase.js +8 -4
  11. package/lib/Button/ButtonDropdown.js +207 -0
  12. package/lib/Button/ButtonGroup.js +1 -1
  13. package/lib/Carousel/Carousel.js +31 -5
  14. package/lib/Carousel/CarouselContext.js +1 -1
  15. package/lib/Carousel/CarouselFirstFocus/CarouselFirstFocus.js +1 -1
  16. package/lib/Carousel/CarouselTabs/CarouselTabsPanel.js +1 -10
  17. package/lib/Carousel/CarouselThumbnail.js +2 -2
  18. package/lib/Checkbox/Checkbox.js +1 -1
  19. package/lib/Checkbox/CheckboxGroup.js +2 -2
  20. package/lib/Divider/Divider.js +2 -2
  21. package/lib/FlexGrid/Col/Col.js +1 -1
  22. package/lib/Icon/Icon.js +1 -1
  23. package/lib/MultiSelectFilter/ModalOverlay.js +136 -0
  24. package/lib/MultiSelectFilter/MultiSelectFilter.js +314 -0
  25. package/lib/MultiSelectFilter/dictionary.js +19 -0
  26. package/lib/MultiSelectFilter/index.js +13 -0
  27. package/lib/Pagination/PageButton.js +2 -2
  28. package/lib/Pagination/Pagination.js +3 -5
  29. package/lib/Pagination/SideButton.js +6 -4
  30. package/lib/Pagination/usePagination.js +2 -2
  31. package/lib/Progress/ProgressBar.js +3 -3
  32. package/lib/Progress/ProgressBarBackground.js +3 -3
  33. package/lib/QuickLinksFeature/QuickLinksFeature.js +91 -0
  34. package/lib/QuickLinksFeature/QuickLinksFeatureItem.js +157 -0
  35. package/lib/QuickLinksFeature/index.js +16 -0
  36. package/lib/Radio/Radio.js +2 -2
  37. package/lib/Radio/RadioGroup.js +2 -2
  38. package/lib/RadioCard/RadioCard.js +1 -1
  39. package/lib/RadioCard/RadioCardGroup.js +2 -2
  40. package/lib/Responsive/Responsive.js +58 -0
  41. package/lib/Responsive/index.js +13 -0
  42. package/lib/Search/Search.js +30 -63
  43. package/lib/Select/constants.js +15 -0
  44. package/lib/SideNav/SideNav.js +2 -2
  45. package/lib/Skeleton/Skeleton.js +1 -1
  46. package/lib/Skeleton/skeletonWebAnimation.js +1 -1
  47. package/lib/StackView/StackWrap.js +1 -3
  48. package/lib/StackView/getStackedContent.js +2 -2
  49. package/lib/Tabs/Tabs.js +2 -4
  50. package/lib/Tags/Tags.js +11 -5
  51. package/lib/TextInput/TextInputBase.js +53 -19
  52. package/lib/TextInput/dictionary.js +19 -0
  53. package/lib/ThemeProvider/utils/styles.js +3 -3
  54. package/lib/ThemeProvider/utils/theme-tokens.js +9 -7
  55. package/lib/Timeline/Timeline.js +1 -1
  56. package/lib/ToggleSwitch/ToggleSwitch.js +1 -1
  57. package/lib/ToggleSwitch/ToggleSwitchGroup.js +1 -1
  58. package/lib/Tooltip/Backdrop.js +10 -2
  59. package/lib/Tooltip/Tooltip.native.js +357 -0
  60. package/lib/Tooltip/shared.js +39 -0
  61. package/lib/Validator/Validator.js +271 -0
  62. package/lib/Validator/index.js +13 -0
  63. package/lib/index.js +9 -0
  64. package/lib/utils/BaseView/BaseView.js +64 -0
  65. package/lib/utils/BaseView/BaseView.native.js +16 -0
  66. package/lib/utils/BaseView/index.js +13 -0
  67. package/lib/utils/animation/useVerticalExpandAnimation.js +1 -1
  68. package/lib/utils/children.js +2 -2
  69. package/lib/utils/floating-ui/index.js +43 -0
  70. package/lib/utils/floating-ui/index.native.js +43 -0
  71. package/lib/utils/input.js +12 -6
  72. package/lib/utils/props/componentPropType.js +3 -3
  73. package/lib/utils/props/selectSystemProps.js +2 -2
  74. package/lib/utils/props/tokens.js +2 -2
  75. package/lib/utils/useOverlaidPosition.js +243 -0
  76. package/lib/utils/useSpacingScale.js +1 -3
  77. package/lib/utils/useUniqueId.js +1 -1
  78. package/lib-module/ActivityIndicator/Spinner.js +7 -7
  79. package/lib-module/ActivityIndicator/Spinner.native.js +2 -2
  80. package/lib-module/BaseProvider/HydrationContext.js +1 -1
  81. package/lib-module/BaseProvider/TamaguiProvider.js +22 -0
  82. package/lib-module/Button/ButtonBase.js +8 -4
  83. package/lib-module/Button/ButtonDropdown.js +181 -0
  84. package/lib-module/Button/ButtonGroup.js +1 -1
  85. package/lib-module/Carousel/Carousel.js +31 -5
  86. package/lib-module/Carousel/CarouselContext.js +1 -1
  87. package/lib-module/Carousel/CarouselFirstFocus/CarouselFirstFocus.js +1 -1
  88. package/lib-module/Carousel/CarouselTabs/CarouselTabsPanel.js +1 -10
  89. package/lib-module/Carousel/CarouselThumbnail.js +2 -2
  90. package/lib-module/Checkbox/Checkbox.js +1 -1
  91. package/lib-module/Checkbox/CheckboxGroup.js +2 -2
  92. package/lib-module/Divider/Divider.js +2 -2
  93. package/lib-module/FlexGrid/Col/Col.js +1 -1
  94. package/lib-module/Icon/Icon.js +1 -1
  95. package/lib-module/MultiSelectFilter/ModalOverlay.js +112 -0
  96. package/lib-module/MultiSelectFilter/MultiSelectFilter.js +286 -0
  97. package/lib-module/MultiSelectFilter/dictionary.js +12 -0
  98. package/lib-module/MultiSelectFilter/index.js +2 -0
  99. package/lib-module/Pagination/PageButton.js +2 -2
  100. package/lib-module/Pagination/Pagination.js +3 -5
  101. package/lib-module/Pagination/SideButton.js +6 -4
  102. package/lib-module/Pagination/usePagination.js +2 -2
  103. package/lib-module/Progress/ProgressBar.js +3 -3
  104. package/lib-module/Progress/ProgressBarBackground.js +3 -3
  105. package/lib-module/QuickLinksFeature/QuickLinksFeature.js +69 -0
  106. package/lib-module/QuickLinksFeature/QuickLinksFeatureItem.js +130 -0
  107. package/lib-module/QuickLinksFeature/index.js +4 -0
  108. package/lib-module/Radio/Radio.js +2 -2
  109. package/lib-module/Radio/RadioGroup.js +2 -2
  110. package/lib-module/RadioCard/RadioCard.js +1 -1
  111. package/lib-module/RadioCard/RadioCardGroup.js +2 -2
  112. package/lib-module/Responsive/Responsive.js +45 -0
  113. package/lib-module/Responsive/index.js +2 -0
  114. package/lib-module/Search/Search.js +30 -61
  115. package/lib-module/Select/constants.js +5 -0
  116. package/lib-module/SideNav/SideNav.js +2 -2
  117. package/lib-module/Skeleton/Skeleton.js +1 -1
  118. package/lib-module/Skeleton/skeletonWebAnimation.js +1 -1
  119. package/lib-module/StackView/StackWrap.js +1 -3
  120. package/lib-module/StackView/getStackedContent.js +2 -2
  121. package/lib-module/Tabs/Tabs.js +2 -4
  122. package/lib-module/Tags/Tags.js +11 -5
  123. package/lib-module/TextInput/TextInputBase.js +52 -19
  124. package/lib-module/TextInput/dictionary.js +12 -0
  125. package/lib-module/ThemeProvider/utils/styles.js +3 -3
  126. package/lib-module/ThemeProvider/utils/theme-tokens.js +9 -7
  127. package/lib-module/Timeline/Timeline.js +1 -1
  128. package/lib-module/ToggleSwitch/ToggleSwitch.js +1 -1
  129. package/lib-module/ToggleSwitch/ToggleSwitchGroup.js +1 -1
  130. package/lib-module/Tooltip/Backdrop.js +10 -2
  131. package/lib-module/Tooltip/Tooltip.native.js +326 -0
  132. package/lib-module/Tooltip/shared.js +27 -0
  133. package/lib-module/Validator/Validator.js +245 -0
  134. package/lib-module/Validator/index.js +2 -0
  135. package/lib-module/index.js +1 -0
  136. package/lib-module/utils/BaseView/BaseView.js +43 -0
  137. package/lib-module/utils/BaseView/BaseView.native.js +6 -0
  138. package/lib-module/utils/BaseView/index.js +2 -0
  139. package/lib-module/utils/animation/useVerticalExpandAnimation.js +1 -1
  140. package/lib-module/utils/children.js +2 -2
  141. package/lib-module/utils/floating-ui/index.js +1 -0
  142. package/lib-module/utils/floating-ui/index.native.js +1 -0
  143. package/lib-module/utils/input.js +12 -6
  144. package/lib-module/utils/props/componentPropType.js +3 -3
  145. package/lib-module/utils/props/selectSystemProps.js +2 -2
  146. package/lib-module/utils/props/tokens.js +2 -2
  147. package/lib-module/utils/useOverlaidPosition.js +232 -0
  148. package/lib-module/utils/useSpacingScale.js +1 -3
  149. package/lib-module/utils/useUniqueId.js +1 -1
  150. package/package.json +7 -4
  151. package/src/Button/ButtonBase.jsx +4 -2
  152. package/src/Carousel/Carousel.jsx +42 -10
  153. package/src/Carousel/CarouselTabs/CarouselTabsPanel.jsx +0 -10
  154. package/src/Pagination/SideButton.jsx +5 -5
  155. package/src/Responsive/Responsive.jsx +33 -0
  156. package/src/Responsive/index.js +3 -0
  157. package/src/Search/Search.jsx +17 -32
  158. package/src/Tags/Tags.jsx +46 -33
  159. package/src/TextInput/TextInputBase.jsx +46 -16
  160. 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 !== null && id !== void 0 ? id : uniqueId;
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("ToggleSwitchGroup items must have unique ".concat(uniqueFields.join(', ')));
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 = "\n position: absolute; \n top: ".concat(window.scrollY, "px;\n left: ").concat(window.scrollX, "px; \n right: 0; \n bottom: 0; \n z-index: 9999; \n pointer-events: none;\n ");
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 = "tooltip-backdrop-".concat(Date.now());
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
+ });
@@ -0,0 +1,2 @@
1
+ import Validator from './Validator';
2
+ export default Validator;
@@ -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';