@telus-uds/components-base 0.0.2-prerelease.4 → 0.0.2-prerelease.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.
Files changed (96) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/__fixtures__/testTheme.js +83 -11
  3. package/__tests__/Divider/Divider.test.jsx +26 -5
  4. package/__tests__/Feedback/Feedback.test.jsx +42 -0
  5. package/__tests__/Spacer/Spacer.test.jsx +63 -0
  6. package/__tests__/StackView/StackView.test.jsx +242 -0
  7. package/__tests__/StackView/StackWrap.test.jsx +47 -0
  8. package/__tests__/StackView/getStackedContent.test.jsx +295 -0
  9. package/__tests__/TextInput/TextInput.test.jsx +146 -0
  10. package/__tests__/utils/useUniqueId.test.js +31 -0
  11. package/lib/Box/Box.js +7 -2
  12. package/lib/Button/ButtonBase.js +6 -16
  13. package/lib/Button/ButtonGroup.js +13 -22
  14. package/lib/Divider/Divider.js +40 -2
  15. package/lib/Feedback/Feedback.js +110 -0
  16. package/lib/Feedback/index.js +2 -0
  17. package/lib/Icon/Icon.js +1 -1
  18. package/lib/InputLabel/InputLabel.js +86 -0
  19. package/lib/InputLabel/LabelContent.native.js +8 -0
  20. package/lib/InputLabel/LabelContent.web.js +17 -0
  21. package/lib/InputLabel/index.js +2 -0
  22. package/lib/Link/LinkBase.js +9 -3
  23. package/lib/Spacer/Spacer.js +98 -0
  24. package/lib/Spacer/index.js +2 -0
  25. package/lib/StackView/StackView.js +105 -0
  26. package/lib/StackView/StackWrap.js +32 -0
  27. package/lib/StackView/StackWrap.native.js +3 -0
  28. package/lib/StackView/StackWrapBox.js +85 -0
  29. package/lib/StackView/StackWrapGap.js +45 -0
  30. package/lib/StackView/common.js +30 -0
  31. package/lib/StackView/getStackedContent.js +111 -0
  32. package/lib/StackView/index.js +5 -0
  33. package/lib/TextInput/TextInput.js +337 -0
  34. package/lib/TextInput/index.js +2 -0
  35. package/lib/Typography/Typography.js +0 -4
  36. package/lib/index.js +6 -1
  37. package/lib/utils/input.js +3 -1
  38. package/lib/utils/propTypes.js +9 -1
  39. package/lib/utils/useUniqueId.js +12 -0
  40. package/package.json +2 -2
  41. package/release-context.json +4 -4
  42. package/src/Box/Box.jsx +4 -2
  43. package/src/Button/ButtonBase.jsx +6 -18
  44. package/src/Button/ButtonGroup.jsx +13 -17
  45. package/src/Divider/Divider.jsx +38 -3
  46. package/src/Feedback/Feedback.jsx +99 -0
  47. package/src/Feedback/index.js +3 -0
  48. package/src/Icon/Icon.jsx +2 -1
  49. package/src/InputLabel/InputLabel.jsx +99 -0
  50. package/src/InputLabel/LabelContent.native.jsx +6 -0
  51. package/src/InputLabel/LabelContent.web.jsx +13 -0
  52. package/src/InputLabel/index.js +3 -0
  53. package/src/Link/LinkBase.jsx +9 -3
  54. package/src/Spacer/Spacer.jsx +91 -0
  55. package/src/Spacer/index.js +3 -0
  56. package/src/StackView/StackView.jsx +103 -0
  57. package/src/StackView/StackWrap.jsx +33 -0
  58. package/src/StackView/StackWrap.native.jsx +4 -0
  59. package/src/StackView/StackWrapBox.jsx +82 -0
  60. package/src/StackView/StackWrapGap.jsx +39 -0
  61. package/src/StackView/common.jsx +28 -0
  62. package/src/StackView/getStackedContent.jsx +106 -0
  63. package/src/StackView/index.js +6 -0
  64. package/src/TextInput/TextInput.jsx +325 -0
  65. package/src/TextInput/index.js +3 -0
  66. package/src/Typography/Typography.jsx +0 -4
  67. package/src/index.js +6 -1
  68. package/src/utils/input.js +2 -1
  69. package/src/utils/propTypes.js +9 -0
  70. package/src/utils/useUniqueId.js +14 -0
  71. package/stories/A11yText/A11yText.stories.jsx +11 -5
  72. package/stories/ActivityIndicator/ActivityIndicator.stories.jsx +11 -2
  73. package/stories/Box/Box.stories.jsx +29 -2
  74. package/stories/Button/Button.stories.jsx +17 -21
  75. package/stories/Button/ButtonGroup.stories.jsx +2 -1
  76. package/stories/Button/ButtonLink.stories.jsx +6 -4
  77. package/stories/Card/Card.stories.jsx +13 -1
  78. package/stories/Divider/Divider.stories.jsx +26 -2
  79. package/stories/ExpandCollapse/ExpandCollapse.stories.jsx +74 -79
  80. package/stories/Feedback/Feedback.stories.jsx +97 -0
  81. package/stories/FlexGrid/01 FlexGrid.stories.jsx +20 -7
  82. package/stories/Icon/Icon.stories.jsx +11 -3
  83. package/stories/InputLabel/InputLabel.stories.jsx +37 -0
  84. package/stories/Link/ChevronLink.stories.jsx +20 -4
  85. package/stories/Link/Link.stories.jsx +24 -2
  86. package/stories/Link/TextButton.stories.jsx +24 -2
  87. package/stories/Pagination/Pagination.stories.jsx +28 -14
  88. package/stories/SideNav/SideNav.stories.jsx +17 -2
  89. package/stories/Spacer/Spacer.stories.jsx +33 -0
  90. package/stories/StackView/StackView.stories.jsx +65 -0
  91. package/stories/StackView/StackWrap.stories.jsx +52 -0
  92. package/stories/TextInput/TextInput.stories.jsx +103 -0
  93. package/stories/ToggleSwitch/ToggleSwitch.stories.jsx +16 -3
  94. package/stories/Typography/Typography.stories.jsx +12 -3
  95. package/stories/platform-supports.web.jsx +1 -1
  96. package/stories/supports.jsx +109 -13
@@ -0,0 +1,45 @@
1
+ import React from 'react';
2
+ import { View } from 'react-native';
3
+ import StackWrapBox from './StackWrapBox';
4
+ import { a11yProps, useSpacingScale } from '../utils';
5
+ import { useThemeTokens } from '../ThemeProvider';
6
+ import getStackedContent from './getStackedContent';
7
+ import { staticStyles, selectFlexStyles } from './common';
8
+ /**
9
+ * The primary implementation of StackWrap.
10
+ *
11
+ * This is not intended to be used directly. It will automatically be used instead of StackWrap if:
12
+ *
13
+ * - On web, and,
14
+ * - On a browser that supports CSS `gap` (most browser versions from 2020 onwards), and,
15
+ * - The `space` between items is the same as the `gap` between wrapped rows (this is the
16
+ * default if `gap` prop is undefined)
17
+ */
18
+
19
+ const StackWrapGap = ({
20
+ space = 1,
21
+ tokens,
22
+ variant,
23
+ direction = 'row',
24
+ children,
25
+ ...rest
26
+ }) => {
27
+ const themeTokens = useThemeTokens('StackView', tokens, variant);
28
+ const flexStyles = selectFlexStyles(themeTokens);
29
+ const a11y = a11yProps.select({ ...rest
30
+ });
31
+ const size = useSpacingScale(space);
32
+ const gapStyle = {
33
+ gap: size
34
+ };
35
+ const content = getStackedContent(children, {
36
+ direction,
37
+ space: 0
38
+ });
39
+ return /*#__PURE__*/React.createElement(View, Object.assign({}, a11y, {
40
+ style: [flexStyles, staticStyles.wrap, staticStyles[direction], gapStyle]
41
+ }), content);
42
+ };
43
+
44
+ StackWrapGap.propTypes = StackWrapBox.propTypes;
45
+ export default StackWrapGap;
@@ -0,0 +1,30 @@
1
+ import { StyleSheet } from 'react-native';
2
+ export const selectFlexStyles = ({
3
+ alignItems,
4
+ justifyContent,
5
+ flexGrow
6
+ }) => ({
7
+ alignItems,
8
+ justifyContent,
9
+ flexGrow
10
+ });
11
+ export const staticStyles = StyleSheet.create({
12
+ wrap: {
13
+ flexShrink: 1,
14
+ flexWrap: 'wrap'
15
+ },
16
+ row: {
17
+ flexDirection: 'row'
18
+ },
19
+ 'row-reverse': {
20
+ flexDirection: 'row-reverse'
21
+ },
22
+ column: {
23
+ // This is the React Native View default, but also it's very fundamental to the behaviour,
24
+ // so make it explicit and allow it to be tested for.
25
+ flexDirection: 'column'
26
+ },
27
+ 'column-reverse': {
28
+ flexDirection: 'column-reverse'
29
+ }
30
+ });
@@ -0,0 +1,111 @@
1
+ import React, { Children, Fragment } from 'react';
2
+ import Box from '../Box';
3
+ import Divider from '../Divider';
4
+ import Spacer from '../Spacer';
5
+ /**
6
+ * @typedef {import('react').ReactChildren} ReactChildren
7
+ * @typedef {import('react').ReactElement} ReactElement
8
+ * @typedef {import('../utils/propTypes.js').SpacingValue} SpacingValue
9
+ */
10
+
11
+ /**
12
+ * Takes valid React Children and inserts a specified amount of space between each valid (not nullish) top
13
+ * level element, according to the provided `options`.
14
+ *
15
+ * Returns an array of the original elements plus inserted spacing elements.
16
+ * This array of elements is keyed and may be used as a component's `children` without mapping.
17
+ *
18
+ * @param {ReactChildren} children
19
+ * @param {object} [options] -
20
+ * - `space`: amount of space to insert using the theme spacing scale (see `useSpacingScale`)
21
+ * - `direction`: if 'row' or 'row-reverse', applies space horizontally, if 'column' or 'column-reverse', applies space vertically
22
+ * - `box`: if truthy, wraps each valid child in a Box component; if an object, passes it to Box as props
23
+ * - `divider`: if truthy, inserts Divider components; if an object, passes it to Divider as props
24
+ * @param {SpacingValue} [options.space]
25
+ * @param {boolean | object} [options.divider]
26
+ * @param {"row" | "column" | "row-reverse" | "column-reverse"} [options.direction]
27
+ * @returns {ReactElement[]}
28
+ */
29
+
30
+ const getStackedContent = (children, {
31
+ divider,
32
+ space,
33
+ direction = 'column',
34
+ box
35
+ }) => {
36
+ const boxProps = box && typeof box === 'object' ? box : {
37
+ space
38
+ };
39
+ const dividerProps = divider && typeof divider === 'object' ? divider : {}; // Avoid surprises if children contains comments, nulls, or is a variable wrapped as a fragment
40
+
41
+ const validChildren = Children.toArray(unpackFragment(children)).filter(Boolean);
42
+ const content = validChildren.reduce((newChildren, child, index) => {
43
+ const boxID = `Stack-Box-${index}`;
44
+ const item = box ?
45
+ /*#__PURE__*/
46
+ // If wrapped in Box, that Box needs a key.
47
+ // If possible, use an existing content key; use an index-based key only if necessary.
48
+ React.createElement(Box, Object.assign({}, boxProps, {
49
+ key: child.key || boxID,
50
+ testID: boxID
51
+ }), child) : child;
52
+ if (!index || !space && !divider) return [...newChildren, item];
53
+ const testID = `Stack-${divider ? 'Divider' : 'Spacer'}-${index}`;
54
+ const commonProps = {
55
+ testID,
56
+ key: testID,
57
+ space
58
+ };
59
+ const separator = divider ? /*#__PURE__*/React.createElement(Divider, Object.assign({
60
+ vertical: direction.startsWith('row')
61
+ }, dividerProps, commonProps)) : /*#__PURE__*/React.createElement(Spacer, Object.assign({
62
+ direction: direction.startsWith('row') ? 'row' : 'column'
63
+ }, commonProps));
64
+ return [...newChildren, separator, item];
65
+ }, []);
66
+ return content;
67
+ };
68
+ /**
69
+ * Unpacks top-level fragments, so that common compositional patterns such as the following examples
70
+ * can be iterated as flat siblings (as if they were `<Child1 /><Child2 /><Child3 />`):
71
+ *
72
+ * - Setting `children` as a property wrapped in a fragment:
73
+ *
74
+ * ```jsx
75
+ * args.children = <><Child1 /><Child2 /><Child3 /></>
76
+ * ```
77
+ *
78
+ * - Defining `children` as a variable wrapped in a fragment:
79
+ *
80
+ * ```jsx
81
+ * const content = <><Child1 /><Child2 /><Child3 /></>
82
+ * if (someCondition) return <SomeWrapper>{content}</SomeWrapper>
83
+ * ```
84
+ *
85
+ * - Using fragments at the top level of a JSX block for conditional rendering:
86
+ *
87
+ * ```jsx
88
+ * <Child1 />
89
+ * {someCondition && (
90
+ * <>
91
+ * <Child2 />
92
+ * <Child3 />
93
+ * </>
94
+ * )}
95
+ * ```
96
+ *
97
+ * @param {ReactChildren} child
98
+ * @returns {ReactChildren}
99
+ */
100
+
101
+
102
+ const unpackFragment = child => {
103
+ // If this level is a set of top-level siblings rather than one child, check each in turn
104
+ if (Children.count(child) > 1) return Children.map(child, unpackFragment); // When a fragment is found, unpack its children to the top level and check them
105
+
106
+ if (child?.type === Fragment) return unpackFragment(child.props?.children); // Stop unpacking as soon as any non-fragment child is found
107
+
108
+ return child;
109
+ };
110
+
111
+ export default getStackedContent;
@@ -0,0 +1,5 @@
1
+ import StackView from './StackView';
2
+ import StackWrap from './StackWrap';
3
+ export default StackView;
4
+ export { StackWrap };
5
+ export { default as getStackedContent } from './getStackedContent';
@@ -0,0 +1,337 @@
1
+ import React, { useState } from 'react';
2
+ import { View, TextInput as NativeTextInput, Platform, StyleSheet } from 'react-native';
3
+ import PropTypes from 'prop-types';
4
+ import { useThemeTokens, applyTextStyles } from '../ThemeProvider';
5
+ import { getTokensPropType, useInputValue, variantProp } from '../utils';
6
+ import InputLabel from '../InputLabel';
7
+ import Feedback from '../Feedback';
8
+ import Box from '../Box';
9
+ import useUniqueId from '../utils/useUniqueId';
10
+
11
+ const selectInputStyles = ({
12
+ backgroundColor,
13
+ color,
14
+ borderWidth,
15
+ borderColor,
16
+ borderRadius,
17
+ paddingTop,
18
+ paddingBottom,
19
+ paddingLeft,
20
+ paddingRight = 0,
21
+ fontName,
22
+ fontSize,
23
+ fontWeight,
24
+ lineHeight,
25
+ icon,
26
+ iconSize = 0
27
+ }, inactive) => {
28
+ // Subtract border width from padding so overall input width/height doesn't
29
+ // jump around if the border width changes (avoiding NaN and negative padding)
30
+ const offsetBorder = value => typeof value === 'number' && typeof borderWidth === 'number' ? Math.max(0, value - borderWidth) : value;
31
+
32
+ const textStyles = applyTextStyles({
33
+ fontName,
34
+ fontSize,
35
+ lineHeight,
36
+ fontWeight
37
+ });
38
+ const webStyles = Platform.select({
39
+ web: {
40
+ outline: 'none',
41
+ cursor: inactive ? 'not-allowed' : undefined
42
+ }
43
+ });
44
+ const paddingWithIcon = iconSize + paddingRight;
45
+ return {
46
+ backgroundColor,
47
+ color,
48
+ borderWidth,
49
+ borderColor,
50
+ borderRadius,
51
+ paddingLeft: offsetBorder(paddingLeft),
52
+ paddingRight: icon ? offsetBorder(paddingWithIcon) : offsetBorder(paddingRight),
53
+ paddingTop: offsetBorder(paddingTop),
54
+ paddingBottom: offsetBorder(paddingBottom),
55
+ ...textStyles,
56
+ ...webStyles
57
+ };
58
+ };
59
+
60
+ const selectOuterBorderStyles = ({
61
+ outerBackgroundColor,
62
+ outerBorderWidth = 0,
63
+ outerBorderColor,
64
+ outerBorderRadius = 0
65
+ }) => {
66
+ // Use negative margins so that the outer border doesn't expand the input's bounding box
67
+ const margin = -1 * outerBorderWidth; // Account for the border width since we style it as an outline
68
+
69
+ const borderRadius = outerBorderRadius + outerBorderWidth;
70
+ return {
71
+ background: outerBackgroundColor,
72
+ borderWidth: outerBorderWidth,
73
+ borderColor: outerBorderColor,
74
+ borderRadius,
75
+ marginTop: margin,
76
+ marginBottom: margin,
77
+ marginLeft: margin,
78
+ marginRight: margin
79
+ };
80
+ };
81
+
82
+ const selectIconTokens = ({
83
+ iconSize,
84
+ iconColor
85
+ }) => ({
86
+ size: iconSize,
87
+ color: iconColor
88
+ });
89
+
90
+ const joinDefined = array => array.filter(item => item !== undefined).join(' ');
91
+ /**
92
+ * A basic text input component. Use in forms or individually to receive user's input.
93
+ * Due to React Native's implementation of `TextInput` it's not possible to access the current value by passing a ref.
94
+ *
95
+ * ## Controlled component
96
+ * If it is required that the state of the `TextInput` be controlled by the application or other external methods,
97
+ * `value` and `onChange` props must be passed to the `TextInput`.
98
+ * If the `TextInput` value should not be changed by user input, a `readOnly` prop must be provided.
99
+ *
100
+ * ## Uncontrolled component
101
+ * If it is not necessary to control the `TextInput` state, you can create one without a value prop.
102
+ * In this case its value can be accessed within the `onChange` callback.
103
+ *
104
+ * NOTE: In order to support more advanced usages all additional props will be passed down to the React Native's
105
+ * `TextInput` component. See <a href="https://reactnative.dev/docs/textinput" target="_blank">React Native documentation</a> for
106
+ * supported props and <a href="https://reactnative.dev/docs/textinput" target="_blank">React Native Web documentation</a> for
107
+ * their implementation on the web.
108
+ */
109
+
110
+
111
+ function TextInput({
112
+ value,
113
+ initialValue,
114
+ label,
115
+ hint,
116
+ hintPosition = 'inline',
117
+ feedback,
118
+ tooltip,
119
+ validation,
120
+ inactive,
121
+ readOnly,
122
+ onChange,
123
+ onChangeText,
124
+ onFocus,
125
+ onBlur,
126
+ onMouseOver,
127
+ onMouseOut,
128
+ tokens,
129
+ variant = {},
130
+ ...remainingProps
131
+ }) {
132
+ const inputId = useUniqueId('text-input');
133
+ const hintId = useUniqueId('text-input-hint');
134
+ const feedbackId = useUniqueId('text-input-feedback');
135
+ const [isFocused, setIsFocused] = useState(false);
136
+
137
+ const handleFocus = event => {
138
+ setIsFocused(true);
139
+ if (typeof onFocus === 'function') onFocus(event);
140
+ };
141
+
142
+ const handleBlur = event => {
143
+ setIsFocused(false);
144
+ if (typeof onBlur === 'function') onBlur(event);
145
+ };
146
+
147
+ const [isHovered, setIsHovered] = useState(false);
148
+
149
+ const handleMouseOver = event => {
150
+ setIsHovered(true);
151
+ if (typeof onMouseOver === 'function') onMouseOver(event);
152
+ };
153
+
154
+ const handleMouseOut = event => {
155
+ setIsHovered(false);
156
+ if (typeof onMouseOut === 'function') onMouseOut(event);
157
+ };
158
+
159
+ const {
160
+ currentValue,
161
+ setValue,
162
+ isControlled
163
+ } = useInputValue({
164
+ value,
165
+ initialValue,
166
+ onChange,
167
+ readOnly
168
+ });
169
+
170
+ const handleChangeText = text => {
171
+ setValue(text);
172
+ if (typeof onChangeText === 'function') onChangeText(text);
173
+ };
174
+
175
+ const states = {
176
+ focus: isFocused,
177
+ hover: isHovered,
178
+ inactive
179
+ };
180
+ const themeTokens = useThemeTokens('TextInput', tokens, { ...variant,
181
+ validation
182
+ }, states);
183
+ const {
184
+ icon: IconComponent
185
+ } = themeTokens;
186
+ const hasValidationError = validation === 'error';
187
+ const inputProps = { ...remainingProps,
188
+ editable: !inactive,
189
+ onFocus: handleFocus,
190
+ onBlur: handleBlur,
191
+ onMouseOver: handleMouseOver,
192
+ onMouseOut: handleMouseOut,
193
+ onChangeText: handleChangeText,
194
+ accessibilityLabel: label,
195
+ accessibilityHint: joinDefined([!hasValidationError && feedback, hint]),
196
+ // native only -> replaced with describedBy on web
197
+ accessibilityDescribedBy: joinDefined([!hasValidationError && feedback && feedbackId, // feedback receives a11yRole=alert, so there's no need to include it here
198
+ hint && hintId]),
199
+ // introduced in RNW 0.15.0
200
+ accessibilityInvalid: hasValidationError,
201
+ // introduced in RNW 0.15.0
202
+ nativeID: inputId,
203
+ defaultValue: initialValue,
204
+ // currentValue is being updated even if the input is not controlled, passing it down to the
205
+ // Input could lead to changing its state from uncontrolled to controlled
206
+ value: isControlled ? currentValue : undefined
207
+ }; // TODO: use Stack instead of the Boxes
208
+
209
+ const feedbackVariant = {};
210
+
211
+ if (hasValidationError) {
212
+ feedbackVariant.state = 'error';
213
+ } else if (validation === 'success') {
214
+ feedbackVariant.state = 'success';
215
+ }
216
+
217
+ return /*#__PURE__*/React.createElement(View, null, label && /*#__PURE__*/React.createElement(Box, {
218
+ bottom: 1
219
+ }, /*#__PURE__*/React.createElement(InputLabel, {
220
+ label: label,
221
+ hint: hint,
222
+ hintPosition: hintPosition,
223
+ hintId: hintId,
224
+ tooltip: tooltip,
225
+ forId: inputId
226
+ })), /*#__PURE__*/React.createElement(View, {
227
+ style: selectOuterBorderStyles(themeTokens)
228
+ }, /*#__PURE__*/React.createElement(NativeTextInput, Object.assign({
229
+ style: selectInputStyles(themeTokens, inactive)
230
+ }, inputProps)), IconComponent && /*#__PURE__*/React.createElement(View, {
231
+ pointerEvents: "none" // avoid hijacking input press events
232
+ ,
233
+ style: [staticStyles.iconContainer, selectIconContainerStyles(themeTokens)]
234
+ }, /*#__PURE__*/React.createElement(IconComponent, {
235
+ tokens: selectIconTokens(themeTokens)
236
+ }))), feedback && /*#__PURE__*/React.createElement(Box, {
237
+ top: 1
238
+ }, /*#__PURE__*/React.createElement(Feedback, {
239
+ title: feedback,
240
+ variant: feedbackVariant,
241
+ accessibilityRole: hasValidationError ? 'alert' : undefined
242
+ })));
243
+ }
244
+
245
+ const selectIconContainerStyles = ({
246
+ paddingRight
247
+ }) => ({
248
+ paddingRight
249
+ });
250
+
251
+ TextInput.propTypes = {
252
+ /**
253
+ * The input label.
254
+ */
255
+ label: PropTypes.string,
256
+
257
+ /**
258
+ * If the `TextInput's` state is to be controlled by a parent component, use this prop
259
+ * together with the `onChange` to pass down and update the lifted state.
260
+ */
261
+ value: PropTypes.string,
262
+
263
+ /**
264
+ * Use this to set the initial value of an uncontrolled `TextInput`.
265
+ * Updating `initialValue` will **not** update the actual value.
266
+ */
267
+ initialValue: PropTypes.string,
268
+
269
+ /**
270
+ * A short description of the expected input.
271
+ */
272
+ hint: PropTypes.string,
273
+
274
+ /**
275
+ * Position of the hint relative to label.
276
+ */
277
+ hintPosition: PropTypes.oneOf(['inline', 'below']),
278
+
279
+ /**
280
+ * A detailed description of validation error/success or additional instructions.
281
+ * Visual variant is determined based on the `validation` prop.
282
+ */
283
+ feedback: PropTypes.string,
284
+
285
+ /**
286
+ * Content of an optional `Tooltip`. If set, a tooltip button will be shown next to the label.
287
+ */
288
+ tooltip: PropTypes.string,
289
+
290
+ /**
291
+ * Use to visually mark an input as valid or invalid.
292
+ */
293
+ validation: PropTypes.oneOf(['error', 'success']),
294
+
295
+ /**
296
+ * Disables all user interactions with the input.
297
+ */
298
+ inactive: PropTypes.bool,
299
+
300
+ /**
301
+ * Makes it impossible to change the input's value.
302
+ */
303
+ readOnly: PropTypes.bool,
304
+
305
+ /**
306
+ * Use to react upon input's value changes. Required when the `value` prop is set.
307
+ * Will receive the input's value as an argument.
308
+ */
309
+ onChange: PropTypes.func,
310
+
311
+ /** @ignore */
312
+ onChangeText: PropTypes.func,
313
+
314
+ /** @ignore */
315
+ onFocus: PropTypes.func,
316
+
317
+ /** @ignore */
318
+ onBlur: PropTypes.func,
319
+
320
+ /** @ignore */
321
+ onMouseOver: PropTypes.func,
322
+
323
+ /** @ignore */
324
+ onMouseOut: PropTypes.func,
325
+ tokens: getTokensPropType('TextInput'),
326
+ variant: variantProp.propType
327
+ };
328
+ export default TextInput;
329
+ const staticStyles = StyleSheet.create({
330
+ iconContainer: {
331
+ position: 'absolute',
332
+ right: 0,
333
+ top: 0,
334
+ bottom: 0,
335
+ justifyContent: 'center'
336
+ }
337
+ });
@@ -0,0 +1,2 @@
1
+ import TextInput from './TextInput';
2
+ export default TextInput;
@@ -36,8 +36,6 @@ const selectTextStyles = ({
36
36
  color,
37
37
  lineHeight,
38
38
  fontName,
39
- marginTop,
40
- marginBottom,
41
39
  textAlign,
42
40
  textTransform
43
41
  }) => applyTextStyles({
@@ -46,8 +44,6 @@ const selectTextStyles = ({
46
44
  color,
47
45
  lineHeight,
48
46
  fontName,
49
- marginTop,
50
- marginBottom,
51
47
  textAlign,
52
48
  textTransform
53
49
  }); // General-purpose flexible theme-neutral base component for text
package/lib/index.js CHANGED
@@ -4,16 +4,21 @@ export * from './Button';
4
4
  export { default as Card } from './Card';
5
5
  export { default as Divider } from './Divider';
6
6
  export { default as ExpandCollapse, Accordion } from './ExpandCollapse';
7
+ export { default as Feedback } from './Feedback';
7
8
  export { default as FlexGrid } from './FlexGrid';
8
9
  export { default as Icon } from './Icon';
9
10
  export * from './Icon';
10
11
  export * from './Link';
11
12
  export { default as Pagination } from './Pagination';
12
13
  export { default as SideNav } from './SideNav';
14
+ export { default as Spacer } from './Spacer';
15
+ export { default as StackView } from './StackView';
16
+ export * from './StackView';
17
+ export { default as TextInput } from './TextInput';
13
18
  export { default as ToggleSwitch } from './ToggleSwitch';
14
19
  export { default as Typography } from './Typography';
15
20
  export { default as A11yInfoProvider, useA11yInfo } from './A11yInfoProvider';
16
21
  export { default as BaseProvider } from './BaseProvider';
17
22
  export { default as ViewportProvider, useViewport } from './ViewportProvider';
18
- export { default as ThemeProvider, useTheme, useSetTheme } from './ThemeProvider';
23
+ export { default as ThemeProvider, useTheme, useSetTheme, useThemeTokens } from './ThemeProvider';
19
24
  export * from './utils';
@@ -60,6 +60,7 @@ Consumers of this hook must be one of:
60
60
  * currentValue: any
61
61
  * setValue: (value: any) => void
62
62
  * resetValue: () => void
63
+ * isControlled: bool
63
64
  * }}
64
65
  */
65
66
 
@@ -91,7 +92,8 @@ export const useInputValue = (props = {}, hookName = 'useInputValue') => {
91
92
  return {
92
93
  currentValue,
93
94
  setValue,
94
- resetValue
95
+ resetValue,
96
+ isControlled
95
97
  };
96
98
  };
97
99
  /**
@@ -405,4 +405,12 @@ export const componentPropType = (passedName, checkDisplayName = false) => {
405
405
  validate.isRequired = createValidate(true);
406
406
  return validate;
407
407
  };
408
- export const copyPropTypes = PropTypes.oneOf(['en', 'fr']);
408
+ export const copyPropTypes = PropTypes.oneOf(['en', 'fr']);
409
+ export const paddingProp = {
410
+ propType: PropTypes.shape({
411
+ paddingBottom: PropTypes.number,
412
+ paddingLeft: PropTypes.number,
413
+ paddingRight: PropTypes.number,
414
+ paddingTop: PropTypes.number
415
+ })
416
+ };
@@ -0,0 +1,12 @@
1
+ import { useState } from 'react';
2
+ let id = 0;
3
+
4
+ function useUniqueId(prefix = '') {
5
+ const [uniqueId] = useState(() => {
6
+ id += 1;
7
+ return `${prefix}-${id}`;
8
+ });
9
+ return uniqueId;
10
+ }
11
+
12
+ export default useUniqueId;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@telus-uds/components-base",
3
- "version": "0.0.2-prerelease.4",
3
+ "version": "0.0.2-prerelease.5",
4
4
  "description": "Base components",
5
5
  "keywords": [
6
6
  "base"
@@ -47,7 +47,7 @@
47
47
  },
48
48
  "dependencies": {
49
49
  "@telus-uds/system-constants": "^0.0.2-prerelease.1",
50
- "@telus-uds/tools-theme": "^0.0.2-prerelease.2",
50
+ "@telus-uds/tools-theme": "^0.0.2-prerelease.3",
51
51
  "lodash.merge": "^4.6.2",
52
52
  "prop-types": "^15.7.2"
53
53
  }
@@ -1,7 +1,7 @@
1
1
  {
2
- "previousReleaseTag": "@telus-uds/components-base/v0.0.2-prerelease.3",
3
- "changelog": "### [0.0.2-prerelease.4](https://github.com/telus/universal-design-system/compare/@telus-uds/components-base/v0.0.2-prerelease.3...@telus-uds/components-base/v0.0.2-prerelease.4) (2021-10-13)\n\n\n### Bug Fixes\n\n* same rnw dep specification for base as components-allium-web ([#642](https://github.com/telus/universal-design-system/issues/642)) ([d40a9a2](https://github.com/telus/universal-design-system/commit/d40a9a2eade0a6ab276f13d02758fff0a88c2ecd))\n",
4
- "releaseTag": "@telus-uds/components-base/v0.0.2-prerelease.4",
5
- "newVersion": "0.0.2-prerelease.4",
2
+ "previousReleaseTag": "@telus-uds/components-base/v0.0.2-prerelease.4",
3
+ "changelog": "### [0.0.2-prerelease.5](https://github.com/telus/universal-design-system/compare/@telus-uds/components-base/v0.0.2-prerelease.4...@telus-uds/components-base/v0.0.2-prerelease.5) (2021-10-27)\n\n\n### Features\n\n* **allium-web:** Add `ExpandCollapseMiniControl` component ([#661](https://github.com/telus/universal-design-system/issues/661)) ([227407e](https://github.com/telus/universal-design-system/commit/227407ec6a48c0a170b8e39761ba33293f13eb3c)), closes [#605](https://github.com/telus/universal-design-system/issues/605) [#605](https://github.com/telus/universal-design-system/issues/605) [#605](https://github.com/telus/universal-design-system/issues/605) [#605](https://github.com/telus/universal-design-system/issues/605) [#605](https://github.com/telus/universal-design-system/issues/605)\n* **allium:** add Allium `Card` ([#639](https://github.com/telus/universal-design-system/issues/639)) ([f88179c](https://github.com/telus/universal-design-system/commit/f88179c503dfe574bf7bac6bb36ce4726a9af338))\n* **base, allium:** add reverse directions and switch Allium card to using `StackView` ([#676](https://github.com/telus/universal-design-system/issues/676)) ([819a15f](https://github.com/telus/universal-design-system/commit/819a15f059faa47d1bc4e96c6370e9694effc003))\n* **base:** add StackView and Spacer ([#662](https://github.com/telus/universal-design-system/issues/662)) ([cc3965e](https://github.com/telus/universal-design-system/commit/cc3965e83c1ec2fa0f0dd006a03eeeeda5384940))\n* **base:** add StackWrap component ([#666](https://github.com/telus/universal-design-system/issues/666)) ([f34fb60](https://github.com/telus/universal-design-system/commit/f34fb60d0a923b1e4b3105c21b4a762b630ab309))\n* **base:** add TextInput component ([#649](https://github.com/telus/universal-design-system/issues/649)) ([245c073](https://github.com/telus/universal-design-system/commit/245c073ed3ba3a022f989d234fbf5cf972edec25))\n* **base:** add the Feedback component ([#656](https://github.com/telus/universal-design-system/issues/656)) ([5d7a5b6](https://github.com/telus/universal-design-system/commit/5d7a5b69c870ce1077adfdb230fddd1aa120b373))\n\n\n### Bug Fixes\n\n* **base:** control stretch from a row parent ([#668](https://github.com/telus/universal-design-system/issues/668)) ([fa13c37](https://github.com/telus/universal-design-system/commit/fa13c37b2bd6b4118dbeb39bc2cdf59d13d5b151))\n* **base:** fix icon link width in block container ([#645](https://github.com/telus/universal-design-system/issues/645)) ([ff60d1d](https://github.com/telus/universal-design-system/commit/ff60d1d1d0a66b7735b902098c7ca22e442265e1))\n",
4
+ "releaseTag": "@telus-uds/components-base/v0.0.2-prerelease.5",
5
+ "newVersion": "0.0.2-prerelease.5",
6
6
  "packageName": "@telus-uds/components-base"
7
7
  }