@telus-uds/components-web 2.32.0 → 2.32.2

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 CHANGED
@@ -1,12 +1,31 @@
1
1
  # Change Log - @telus-uds/components-web
2
2
 
3
- This log was last generated on Tue, 12 Mar 2024 22:22:38 GMT and should not be manually modified.
3
+ This log was last generated on Wed, 27 Mar 2024 21:09:55 GMT and should not be manually modified.
4
4
 
5
5
  <!-- Start content -->
6
6
 
7
+ ## 2.32.2
8
+
9
+ Wed, 27 Mar 2024 21:09:55 GMT
10
+
11
+ ### Patches
12
+
13
+ - validation added to the datepicker input and input cleaned after the content is deleted (35577399+JoshHC@users.noreply.github.com)
14
+ - Bump @telus-uds/components-base to v1.81.0
15
+
16
+ ## 2.32.1
17
+
18
+ Tue, 19 Mar 2024 18:39:50 GMT
19
+
20
+ ### Patches
21
+
22
+ - `Autocomplete`: Overlay does not render next to `TextInput` (shahzaibkhalidmalik@outlook.com)
23
+ - `NavigationBar`: overlay may render on top of toggle button in smaller viewports (shahzaibkhalidmalik@outlook.com)
24
+ - Bump @telus-uds/components-base to v1.80.1
25
+
7
26
  ## 2.32.0
8
27
 
9
- Tue, 12 Mar 2024 22:22:38 GMT
28
+ Tue, 12 Mar 2024 22:26:51 GMT
10
29
 
11
30
  ### Minor changes
12
31
 
@@ -11,7 +11,7 @@ var _componentsBase = require("@telus-uds/components-base");
11
11
  var _utils = require("../utils");
12
12
  var _jsxRuntime = require("react/jsx-runtime");
13
13
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14
- const [, selectedSystemPropTypes] = (0, _componentsBase.selectSystemProps)([_utils.htmlAttrs]);
14
+ const [selectProps, selectedSystemPropTypes] = (0, _componentsBase.selectSystemProps)([_utils.htmlAttrs]);
15
15
  const BadgeContainer = /*#__PURE__*/_styledComponents.default.div.withConfig({
16
16
  displayName: "Badge__BadgeContainer",
17
17
  componentId: "components-web__sc-tsiuo2-0"
@@ -48,6 +48,11 @@ const BadgeContainer = /*#__PURE__*/_styledComponents.default.div.withConfig({
48
48
  ${gradient && '-webkit-text-fill-color: transparent;'}
49
49
  }`;
50
50
  });
51
+ const fontSizeMapping = {
52
+ 12: 'micro',
53
+ 14: 'small',
54
+ 16: 'h6'
55
+ };
51
56
  const Badge = _ref6 => {
52
57
  let {
53
58
  children,
@@ -61,10 +66,14 @@ const Badge = _ref6 => {
61
66
  borderColor,
62
67
  borderRadius,
63
68
  borderWidth,
69
+ color,
64
70
  paddingLeft,
65
71
  paddingRight,
66
72
  paddingTop,
67
- paddingBottom
73
+ paddingBottom,
74
+ fontName,
75
+ fontWeight,
76
+ fontSize
68
77
  } = (0, _componentsBase.useThemeTokens)('Badge', tokens, variant);
69
78
  const semanticGradient = gradient && (0, _utils.transformGradient)(gradient);
70
79
  const {
@@ -85,12 +94,20 @@ const Badge = _ref6 => {
85
94
  padding: `${paddingTop}px ${paddingRight}px ${paddingBottom}px ${paddingLeft}px`,
86
95
  radius: `${borderRadius}px`,
87
96
  background: background,
97
+ fontName: fontName,
98
+ fontWeight: fontWeight,
88
99
  gradient: semanticGradient,
89
100
  border: `${borderWidth}px solid ${borderColor}`,
90
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_componentsBase.Badge, {
91
- tokens: tokens,
92
- variant: variant,
93
- ...rest,
101
+ ...selectProps(rest),
102
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_componentsBase.Typography, {
103
+ tokens: {
104
+ fontName,
105
+ fontWeight,
106
+ color
107
+ },
108
+ variant: {
109
+ size: fontSizeMapping[fontSize]
110
+ },
94
111
  children: children
95
112
  })
96
113
  });
@@ -17,7 +17,6 @@ var _lodash = require("lodash");
17
17
  var _CalendarContainer = _interopRequireDefault(require("./CalendarContainer"));
18
18
  var _dictionary = _interopRequireDefault(require("./dictionary"));
19
19
  var _utils = require("../utils");
20
- var _WebPortal = _interopRequireDefault(require("../WebPortal"));
21
20
  var _jsxRuntime = require("react/jsx-runtime");
22
21
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
23
22
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
@@ -73,6 +72,7 @@ const PortalPositionedContainer = /*#__PURE__*/_styledComponents.default.div.wit
73
72
  return `${top}px`;
74
73
  }
75
74
  });
75
+ const validDatePattern = /^([0-2][0-9]|3[0-1])(\/)(0[1-9]|1[0-2])\2(\d{4})$/;
76
76
 
77
77
  /**
78
78
  * Use DatePicker to select a date on a calendar.
@@ -194,14 +194,34 @@ const DatePicker = /*#__PURE__*/(0, _react.forwardRef)((_ref3, ref) => {
194
194
  if (onDateChange) onDateChange(value);
195
195
  };
196
196
  const onChangeInput = value => {
197
- if ((0, _moment.default)(value.replace(/\s/g, ''), dateFormatWithoutSpaces, true).isValid()) {
198
- setInputDate((0, _moment.default)(value, dateFormat));
199
- if (onDateChange) onDateChange((0, _moment.default)(value, dateFormat));
200
- setInputText((0, _moment.default)(value, dateFormatWithoutSpaces).format(dateFormat));
197
+ if (value === '' || (0, _moment.default)(value.replace(/\s/g, ''), dateFormatWithoutSpaces, true).isValid()) {
198
+ if (value === '') {
199
+ setInputDate(undefined); // Set inputDate to undefined if input is empty
200
+ onDateChange === null || onDateChange === void 0 ? void 0 : onDateChange(undefined);
201
+ } else {
202
+ setInputDate((0, _moment.default)(value, dateFormat));
203
+ onDateChange === null || onDateChange === void 0 ? void 0 : onDateChange((0, _moment.default)(value, dateFormat));
204
+ }
205
+ setInputText(value === '' ? '' : (0, _moment.default)(value, dateFormatWithoutSpaces).format(dateFormat));
201
206
  } else {
202
207
  setInputText(value);
203
208
  }
204
209
  };
210
+ const handleOnKeyPress = event => {
211
+ if (event.key === 'Backspace' && inputText === '') {
212
+ setInputDate(undefined);
213
+ onDateChange === null || onDateChange === void 0 ? void 0 : onDateChange(undefined);
214
+ }
215
+ };
216
+ const handleValidation = inputValidation => {
217
+ if (validDatePattern.test(inputText.replace(/\s+/g, '')) === false && inputText !== '') {
218
+ return 'error';
219
+ }
220
+ if (inputValidation === 'error' || inputValidation === 'success') {
221
+ return inputValidation;
222
+ }
223
+ return inputValidation;
224
+ };
205
225
  const viewport = (0, _componentsBase.useViewport)();
206
226
  const daySize = getResponsiveDaySize(inline, viewport);
207
227
  const circleSize = getResponsiveCircleSize(inline, viewport);
@@ -322,14 +342,15 @@ const DatePicker = /*#__PURE__*/(0, _react.forwardRef)((_ref3, ref) => {
322
342
  hint: hint,
323
343
  placeholder: "DD / MM / YYYY",
324
344
  onChange: onChangeInput,
345
+ onKeyPress: handleOnKeyPress,
325
346
  tooltip: tooltip,
326
347
  hintPosition: hintPosition,
327
348
  label: label ?? ((_dictionary$copy = _dictionary.default[copy]) === null || _dictionary$copy === void 0 ? void 0 : _dictionary$copy.roleDescription),
328
349
  value: inputText,
329
- validation: validation,
350
+ validation: handleValidation(validation),
330
351
  inactive: disabled,
331
352
  ref: textInputRef,
332
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_WebPortal.default, {
353
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_componentsBase.Portal, {
333
354
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(PortalPositionedContainer, {
334
355
  top: datePickerPosition.top,
335
356
  left: datePickerPosition.left,
@@ -33,33 +33,38 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
33
33
  } = _ref;
34
34
  const focusTrapRef = (0, _react.useRef)();
35
35
  const maxWidth = 289; // Slightly over 288 of nav item to account for subpixel rounding
36
+ const defaultOffsets = {
37
+ offsets: {
38
+ vertical: 4
39
+ }
40
+ };
36
41
  const {
37
42
  align,
38
43
  offsets,
39
44
  minWidth
40
45
  } = (0, _componentsBase.useResponsiveProp)({
41
46
  xs: {
47
+ ...defaultOffsets,
42
48
  align: {
43
- top: 'top',
49
+ top: 'bottom',
44
50
  left: 'left'
45
51
  },
46
52
  minWidth: maxWidth
47
53
  },
48
54
  sm: {
55
+ ...defaultOffsets,
49
56
  align: {
50
- top: 'top',
57
+ top: 'bottom',
51
58
  right: 'right'
52
59
  },
53
60
  minWidth: maxWidth
54
61
  },
55
62
  lg: {
63
+ ...defaultOffsets,
56
64
  align: {
57
65
  top: 'bottom',
58
66
  center: 'center'
59
67
  },
60
- offsets: {
61
- vertical: 4
62
- },
63
68
  minWidth: 192
64
69
  }
65
70
  });
@@ -177,6 +177,12 @@ Object.defineProperty(exports, "Pagination", {
177
177
  return _componentsBase.Pagination;
178
178
  }
179
179
  });
180
+ Object.defineProperty(exports, "Portal", {
181
+ enumerable: true,
182
+ get: function () {
183
+ return _componentsBase.Portal;
184
+ }
185
+ });
180
186
  Object.defineProperty(exports, "QuickLinks", {
181
187
  enumerable: true,
182
188
  get: function () {
@@ -357,6 +363,12 @@ Object.defineProperty(exports, "ViewportProvider", {
357
363
  return _componentsBase.ViewportProvider;
358
364
  }
359
365
  });
366
+ Object.defineProperty(exports, "WebPortal", {
367
+ enumerable: true,
368
+ get: function () {
369
+ return _componentsBase.Portal;
370
+ }
371
+ });
360
372
  Object.defineProperty(exports, "useCarousel", {
361
373
  enumerable: true,
362
374
  get: function () {
package/lib/index.js CHANGED
@@ -42,8 +42,7 @@ var _exportNames = {
42
42
  TermsAndConditions: true,
43
43
  NavigationBar: true,
44
44
  Progress: true,
45
- SkeletonProvider: true,
46
- WebPortal: true
45
+ SkeletonProvider: true
47
46
  };
48
47
  Object.defineProperty(exports, "Badge", {
49
48
  enumerable: true,
@@ -255,12 +254,6 @@ Object.defineProperty(exports, "WaffleGrid", {
255
254
  return _WaffleGrid.default;
256
255
  }
257
256
  });
258
- Object.defineProperty(exports, "WebPortal", {
259
- enumerable: true,
260
- get: function () {
261
- return _WebPortal.default;
262
- }
263
- });
264
257
  Object.defineProperty(exports, "WebVideo", {
265
258
  enumerable: true,
266
259
  get: function () {
@@ -315,7 +308,6 @@ var _TermsAndConditions = _interopRequireDefault(require("./TermsAndConditions")
315
308
  var _NavigationBar = _interopRequireDefault(require("./NavigationBar"));
316
309
  var _Progress = _interopRequireDefault(require("./Progress"));
317
310
  var _SkeletonProvider = _interopRequireDefault(require("./SkeletonProvider"));
318
- var _WebPortal = _interopRequireDefault(require("./WebPortal"));
319
311
  var _baseExports = require("./baseExports");
320
312
  Object.keys(_baseExports).forEach(function (key) {
321
313
  if (key === "default" || key === "__esModule") return;
@@ -1,10 +1,10 @@
1
1
  import React from 'react';
2
2
  import styled from 'styled-components';
3
3
  import PropTypes from 'prop-types';
4
- import { selectSystemProps, getTokensPropType, useThemeTokens, Badge as BaseBadge } from '@telus-uds/components-base';
4
+ import { selectSystemProps, Typography, getTokensPropType, useThemeTokens } from '@telus-uds/components-base';
5
5
  import { htmlAttrs, transformGradient } from '../utils';
6
6
  import { jsx as _jsx } from "react/jsx-runtime";
7
- const [, selectedSystemPropTypes] = selectSystemProps([htmlAttrs]);
7
+ const [selectProps, selectedSystemPropTypes] = selectSystemProps([htmlAttrs]);
8
8
  const BadgeContainer = /*#__PURE__*/styled.div.withConfig({
9
9
  displayName: "Badge__BadgeContainer",
10
10
  componentId: "components-web__sc-tsiuo2-0"
@@ -41,6 +41,11 @@ const BadgeContainer = /*#__PURE__*/styled.div.withConfig({
41
41
  ${gradient && '-webkit-text-fill-color: transparent;'}
42
42
  }`;
43
43
  });
44
+ const fontSizeMapping = {
45
+ 12: 'micro',
46
+ 14: 'small',
47
+ 16: 'h6'
48
+ };
44
49
  const Badge = _ref6 => {
45
50
  let {
46
51
  children,
@@ -54,10 +59,14 @@ const Badge = _ref6 => {
54
59
  borderColor,
55
60
  borderRadius,
56
61
  borderWidth,
62
+ color,
57
63
  paddingLeft,
58
64
  paddingRight,
59
65
  paddingTop,
60
- paddingBottom
66
+ paddingBottom,
67
+ fontName,
68
+ fontWeight,
69
+ fontSize
61
70
  } = useThemeTokens('Badge', tokens, variant);
62
71
  const semanticGradient = gradient && transformGradient(gradient);
63
72
  const {
@@ -78,12 +87,20 @@ const Badge = _ref6 => {
78
87
  padding: `${paddingTop}px ${paddingRight}px ${paddingBottom}px ${paddingLeft}px`,
79
88
  radius: `${borderRadius}px`,
80
89
  background: background,
90
+ fontName: fontName,
91
+ fontWeight: fontWeight,
81
92
  gradient: semanticGradient,
82
93
  border: `${borderWidth}px solid ${borderColor}`,
83
- children: /*#__PURE__*/_jsx(BaseBadge, {
84
- tokens: tokens,
85
- variant: variant,
86
- ...rest,
94
+ ...selectProps(rest),
95
+ children: /*#__PURE__*/_jsx(Typography, {
96
+ tokens: {
97
+ fontName,
98
+ fontWeight,
99
+ color
100
+ },
101
+ variant: {
102
+ size: fontSizeMapping[fontSize]
103
+ },
87
104
  children: children
88
105
  })
89
106
  });
@@ -5,13 +5,12 @@ import momentPropTypes from 'react-moment-proptypes';
5
5
  import 'react-dates/initialize';
6
6
  import SingleDatePicker from 'react-dates/lib/components/SingleDatePicker';
7
7
  import DayPickerSingleDateController from 'react-dates/lib/components/DayPickerSingleDateController';
8
- import { IconButton, TextInput, selectSystemProps, useCopy, useViewport, useThemeTokens, applyTextStyles, getTokensPropType, useSafeLayoutEffect } from '@telus-uds/components-base';
8
+ import { IconButton, TextInput, Portal, selectSystemProps, useCopy, useViewport, useThemeTokens, applyTextStyles, getTokensPropType, useSafeLayoutEffect } from '@telus-uds/components-base';
9
9
  import moment from 'moment';
10
10
  import { isUndefined, throttle } from 'lodash';
11
11
  import CalendarContainer from './CalendarContainer';
12
12
  import dictionary from './dictionary';
13
13
  import { htmlAttrs } from '../utils';
14
- import WebPortal from '../WebPortal';
15
14
  import { jsx as _jsx } from "react/jsx-runtime";
16
15
  import { jsxs as _jsxs } from "react/jsx-runtime";
17
16
  import { Fragment as _Fragment } from "react/jsx-runtime";
@@ -66,6 +65,7 @@ const PortalPositionedContainer = /*#__PURE__*/styled.div.withConfig({
66
65
  return `${top}px`;
67
66
  }
68
67
  });
68
+ const validDatePattern = /^([0-2][0-9]|3[0-1])(\/)(0[1-9]|1[0-2])\2(\d{4})$/;
69
69
 
70
70
  /**
71
71
  * Use DatePicker to select a date on a calendar.
@@ -187,14 +187,34 @@ const DatePicker = /*#__PURE__*/forwardRef((_ref3, ref) => {
187
187
  if (onDateChange) onDateChange(value);
188
188
  };
189
189
  const onChangeInput = value => {
190
- if (moment(value.replace(/\s/g, ''), dateFormatWithoutSpaces, true).isValid()) {
191
- setInputDate(moment(value, dateFormat));
192
- if (onDateChange) onDateChange(moment(value, dateFormat));
193
- setInputText(moment(value, dateFormatWithoutSpaces).format(dateFormat));
190
+ if (value === '' || moment(value.replace(/\s/g, ''), dateFormatWithoutSpaces, true).isValid()) {
191
+ if (value === '') {
192
+ setInputDate(undefined); // Set inputDate to undefined if input is empty
193
+ onDateChange === null || onDateChange === void 0 ? void 0 : onDateChange(undefined);
194
+ } else {
195
+ setInputDate(moment(value, dateFormat));
196
+ onDateChange === null || onDateChange === void 0 ? void 0 : onDateChange(moment(value, dateFormat));
197
+ }
198
+ setInputText(value === '' ? '' : moment(value, dateFormatWithoutSpaces).format(dateFormat));
194
199
  } else {
195
200
  setInputText(value);
196
201
  }
197
202
  };
203
+ const handleOnKeyPress = event => {
204
+ if (event.key === 'Backspace' && inputText === '') {
205
+ setInputDate(undefined);
206
+ onDateChange === null || onDateChange === void 0 ? void 0 : onDateChange(undefined);
207
+ }
208
+ };
209
+ const handleValidation = inputValidation => {
210
+ if (validDatePattern.test(inputText.replace(/\s+/g, '')) === false && inputText !== '') {
211
+ return 'error';
212
+ }
213
+ if (inputValidation === 'error' || inputValidation === 'success') {
214
+ return inputValidation;
215
+ }
216
+ return inputValidation;
217
+ };
198
218
  const viewport = useViewport();
199
219
  const daySize = getResponsiveDaySize(inline, viewport);
200
220
  const circleSize = getResponsiveCircleSize(inline, viewport);
@@ -315,14 +335,15 @@ const DatePicker = /*#__PURE__*/forwardRef((_ref3, ref) => {
315
335
  hint: hint,
316
336
  placeholder: "DD / MM / YYYY",
317
337
  onChange: onChangeInput,
338
+ onKeyPress: handleOnKeyPress,
318
339
  tooltip: tooltip,
319
340
  hintPosition: hintPosition,
320
341
  label: label ?? ((_dictionary$copy = dictionary[copy]) === null || _dictionary$copy === void 0 ? void 0 : _dictionary$copy.roleDescription),
321
342
  value: inputText,
322
- validation: validation,
343
+ validation: handleValidation(validation),
323
344
  inactive: disabled,
324
345
  ref: textInputRef,
325
- children: /*#__PURE__*/_jsx(WebPortal, {
346
+ children: /*#__PURE__*/_jsx(Portal, {
326
347
  children: /*#__PURE__*/_jsx(PortalPositionedContainer, {
327
348
  top: datePickerPosition.top,
328
349
  left: datePickerPosition.left,
@@ -28,33 +28,38 @@ const NavigationSubMenu = _ref => {
28
28
  } = _ref;
29
29
  const focusTrapRef = useRef();
30
30
  const maxWidth = 289; // Slightly over 288 of nav item to account for subpixel rounding
31
+ const defaultOffsets = {
32
+ offsets: {
33
+ vertical: 4
34
+ }
35
+ };
31
36
  const {
32
37
  align,
33
38
  offsets,
34
39
  minWidth
35
40
  } = useResponsiveProp({
36
41
  xs: {
42
+ ...defaultOffsets,
37
43
  align: {
38
- top: 'top',
44
+ top: 'bottom',
39
45
  left: 'left'
40
46
  },
41
47
  minWidth: maxWidth
42
48
  },
43
49
  sm: {
50
+ ...defaultOffsets,
44
51
  align: {
45
- top: 'top',
52
+ top: 'bottom',
46
53
  right: 'right'
47
54
  },
48
55
  minWidth: maxWidth
49
56
  },
50
57
  lg: {
58
+ ...defaultOffsets,
51
59
  align: {
52
60
  top: 'bottom',
53
61
  center: 'center'
54
62
  },
55
- offsets: {
56
- vertical: 4
57
- },
58
63
  minWidth: 192
59
64
  }
60
65
  });
@@ -5,7 +5,7 @@ export {
5
5
  /**
6
6
  * Most base components should be re-exported as-is.
7
7
  */
8
- A11yText, ActivityIndicator, Autocomplete, Box, Button, BaseProvider, A11yInfoProvider, ViewportProvider, ThemeProvider, ButtonDropdown, ButtonGroup, ButtonLink, Carousel, CarouselTabs, Checkbox, CheckboxGroup, ChevronLink, ColourToggle, Divider, ExpandCollapse, Feedback, FlexGrid, Icon, InputLabel, InputSupports, Link, Listbox, Modal, MultiSelectFilter, Notification, Pagination, QuickLinks, QuickLinksFeature, Radio, RadioGroup, RadioCard, RadioCardGroup, Responsive, Search, Select, SideNav, Skeleton, SkipLink, Spacer, StackView, StackWrap, StepTracker, Tabs, Tags, TextButton, TextArea, TextInput, Timeline, ToggleSwitch, ToggleSwitchGroup, TooltipButton, Tooltip, Typography, Validator,
8
+ A11yText, ActivityIndicator, Autocomplete, Box, Button, BaseProvider, A11yInfoProvider, ViewportProvider, ThemeProvider, ButtonDropdown, ButtonGroup, ButtonLink, Carousel, CarouselTabs, Checkbox, CheckboxGroup, ChevronLink, ColourToggle, Divider, ExpandCollapse, Feedback, FlexGrid, Icon, InputLabel, InputSupports, Link, Listbox, Modal, MultiSelectFilter, Notification, Pagination, Portal, QuickLinks, QuickLinksFeature, Radio, RadioGroup, RadioCard, RadioCardGroup, Responsive, Search, Select, SideNav, Skeleton, SkipLink, Spacer, StackView, StackWrap, StepTracker, Tabs, Tags, TextButton, TextArea, TextInput, Timeline, ToggleSwitch, ToggleSwitchGroup, TooltipButton, Tooltip, Typography, Validator,
9
9
  /*
10
10
  * Most utilities exported from @telus-uds/components-base are for building systems, not apps.
11
11
  * Re-export only those utilities with a stable API and known use cases within apps / pages.
@@ -13,4 +13,7 @@ A11yText, ActivityIndicator, Autocomplete, Box, Button, BaseProvider, A11yInfoPr
13
13
  // Enable access to the viewports system for app-specific responsive layouts and features
14
14
  useResponsiveProp, useViewport,
15
15
  // TODO reenable ViewportContext once published from base // enable localised viewport overrides e.g. in tests, narrow columns, etc
16
- useCarousel, useSetTheme } from '@telus-uds/components-base';
16
+ useCarousel, useSetTheme } from '@telus-uds/components-base';
17
+
18
+ // TODO: Added `WebPortal` alias for backwards compatibility with `Portal` from `@telus-uds/components-base`. Remove in next major version.
19
+ export { Portal as WebPortal } from '@telus-uds/components-base';
@@ -36,6 +36,5 @@ export { default as TermsAndConditions } from './TermsAndConditions';
36
36
  export { default as NavigationBar } from './NavigationBar';
37
37
  export { default as Progress } from './Progress';
38
38
  export { default as SkeletonProvider } from './SkeletonProvider';
39
- export { default as WebPortal } from './WebPortal';
40
39
  export { ssrStyles } from './utils';
41
40
  export * from './baseExports';
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  ],
6
6
  "dependencies": {
7
7
  "@gorhom/portal": "^1.0.14",
8
- "@telus-uds/components-base": "1.80.0",
8
+ "@telus-uds/components-base": "1.81.0",
9
9
  "@telus-uds/system-constants": "^1.3.0",
10
10
  "fscreen": "^1.2.0",
11
11
  "lodash.omit": "^4.5.0",
@@ -83,5 +83,5 @@
83
83
  "skip": true
84
84
  },
85
85
  "types": "types/index.d.ts",
86
- "version": "2.32.0"
86
+ "version": "2.32.2"
87
87
  }
@@ -3,13 +3,13 @@ import styled from 'styled-components'
3
3
  import PropTypes from 'prop-types'
4
4
  import {
5
5
  selectSystemProps,
6
+ Typography,
6
7
  getTokensPropType,
7
- useThemeTokens,
8
- Badge as BaseBadge
8
+ useThemeTokens
9
9
  } from '@telus-uds/components-base'
10
10
  import { htmlAttrs, transformGradient } from '../utils'
11
11
 
12
- const [, selectedSystemPropTypes] = selectSystemProps([htmlAttrs])
12
+ const [selectProps, selectedSystemPropTypes] = selectSystemProps([htmlAttrs])
13
13
 
14
14
  const BadgeContainer = styled.div`
15
15
  background: ${({ background }) => background};
@@ -29,6 +29,12 @@ const BadgeContainer = styled.div`
29
29
  }`}
30
30
  `
31
31
 
32
+ const fontSizeMapping = {
33
+ 12: 'micro',
34
+ 14: 'small',
35
+ 16: 'h6'
36
+ }
37
+
32
38
  const Badge = ({ children, tokens, variant = {}, ...rest }) => {
33
39
  const {
34
40
  backgroundColor,
@@ -36,10 +42,14 @@ const Badge = ({ children, tokens, variant = {}, ...rest }) => {
36
42
  borderColor,
37
43
  borderRadius,
38
44
  borderWidth,
45
+ color,
39
46
  paddingLeft,
40
47
  paddingRight,
41
48
  paddingTop,
42
- paddingBottom
49
+ paddingBottom,
50
+ fontName,
51
+ fontWeight,
52
+ fontSize
43
53
  } = useThemeTokens('Badge', tokens, variant)
44
54
 
45
55
  const semanticGradient = gradient && transformGradient(gradient)
@@ -60,12 +70,18 @@ const Badge = ({ children, tokens, variant = {}, ...rest }) => {
60
70
  padding={`${paddingTop}px ${paddingRight}px ${paddingBottom}px ${paddingLeft}px`}
61
71
  radius={`${borderRadius}px`}
62
72
  background={background}
73
+ fontName={fontName}
74
+ fontWeight={fontWeight}
63
75
  gradient={semanticGradient}
64
76
  border={`${borderWidth}px solid ${borderColor}`}
77
+ {...selectProps(rest)}
65
78
  >
66
- <BaseBadge tokens={tokens} variant={variant} {...rest}>
79
+ <Typography
80
+ tokens={{ fontName, fontWeight, color }}
81
+ variant={{ size: fontSizeMapping[fontSize] }}
82
+ >
67
83
  {children}
68
- </BaseBadge>
84
+ </Typography>
69
85
  </BadgeContainer>
70
86
  )
71
87
  }
@@ -8,6 +8,7 @@ import DayPickerSingleDateController from 'react-dates/lib/components/DayPickerS
8
8
  import {
9
9
  IconButton,
10
10
  TextInput,
11
+ Portal,
11
12
  selectSystemProps,
12
13
  useCopy,
13
14
  useViewport,
@@ -21,7 +22,6 @@ import { isUndefined, throttle } from 'lodash'
21
22
  import CalendarContainer from './CalendarContainer'
22
23
  import dictionary from './dictionary'
23
24
  import { htmlAttrs } from '../utils'
24
- import WebPortal from '../WebPortal'
25
25
 
26
26
  const [selectProps, selectedSystemPropTypes] = selectSystemProps([htmlAttrs])
27
27
  const dateFormat = 'DD / MM / YYYY'
@@ -56,6 +56,8 @@ const PortalPositionedContainer = styled.div({
56
56
  top: ({ top }) => `${top}px`
57
57
  })
58
58
 
59
+ const validDatePattern = /^([0-2][0-9]|3[0-1])(\/)(0[1-9]|1[0-2])\2(\d{4})$/
60
+
59
61
  /**
60
62
  * Use DatePicker to select a date on a calendar.
61
63
  *
@@ -168,14 +170,42 @@ const DatePicker = forwardRef(
168
170
  if (onDateChange) onDateChange(value)
169
171
  }
170
172
  const onChangeInput = (value) => {
171
- if (moment(value.replace(/\s/g, ''), dateFormatWithoutSpaces, true).isValid()) {
172
- setInputDate(moment(value, dateFormat))
173
- if (onDateChange) onDateChange(moment(value, dateFormat))
174
- setInputText(moment(value, dateFormatWithoutSpaces).format(dateFormat))
173
+ if (
174
+ value === '' ||
175
+ moment(value.replace(/\s/g, ''), dateFormatWithoutSpaces, true).isValid()
176
+ ) {
177
+ if (value === '') {
178
+ setInputDate(undefined) // Set inputDate to undefined if input is empty
179
+ onDateChange?.(undefined)
180
+ } else {
181
+ setInputDate(moment(value, dateFormat))
182
+ onDateChange?.(moment(value, dateFormat))
183
+ }
184
+ setInputText(value === '' ? '' : moment(value, dateFormatWithoutSpaces).format(dateFormat))
175
185
  } else {
176
186
  setInputText(value)
177
187
  }
178
188
  }
189
+
190
+ const handleOnKeyPress = (event) => {
191
+ if (event.key === 'Backspace' && inputText === '') {
192
+ setInputDate(undefined)
193
+ onDateChange?.(undefined)
194
+ }
195
+ }
196
+
197
+ const handleValidation = (inputValidation) => {
198
+ if (validDatePattern.test(inputText.replace(/\s+/g, '')) === false && inputText !== '') {
199
+ return 'error'
200
+ }
201
+
202
+ if (inputValidation === 'error' || inputValidation === 'success') {
203
+ return inputValidation
204
+ }
205
+
206
+ return inputValidation
207
+ }
208
+
179
209
  const viewport = useViewport()
180
210
  const daySize = getResponsiveDaySize(inline, viewport)
181
211
  const circleSize = getResponsiveCircleSize(inline, viewport)
@@ -286,15 +316,16 @@ const DatePicker = forwardRef(
286
316
  hint={hint}
287
317
  placeholder="DD / MM / YYYY"
288
318
  onChange={onChangeInput}
319
+ onKeyPress={handleOnKeyPress}
289
320
  tooltip={tooltip}
290
321
  hintPosition={hintPosition}
291
322
  label={label ?? dictionary[copy]?.roleDescription}
292
323
  value={inputText}
293
- validation={validation}
324
+ validation={handleValidation(validation)}
294
325
  inactive={disabled}
295
326
  ref={textInputRef}
296
327
  >
297
- <WebPortal>
328
+ <Portal>
298
329
  {/* Because `SingleDatePicker` is an absolutely positioned element,
299
330
  * putting it in a `Portal` breaks view heirarchy because it doesn't
300
331
  * align with `TextInput`, but rather position itself with the nearest
@@ -359,7 +390,7 @@ const DatePicker = forwardRef(
359
390
  />
360
391
  </CalendarContainer>
361
392
  </PortalPositionedContainer>
362
- </WebPortal>
393
+ </Portal>
363
394
  </TextInput>
364
395
  </DateInputWrapper>
365
396
  )}
@@ -25,12 +25,13 @@ const NavigationSubMenu = ({
25
25
  const focusTrapRef = useRef()
26
26
 
27
27
  const maxWidth = 289 // Slightly over 288 of nav item to account for subpixel rounding
28
+ const defaultOffsets = { offsets: { vertical: 4 } }
28
29
  const { align, offsets, minWidth } = useResponsiveProp({
29
- xs: { align: { top: 'top', left: 'left' }, minWidth: maxWidth },
30
- sm: { align: { top: 'top', right: 'right' }, minWidth: maxWidth },
30
+ xs: { ...defaultOffsets, align: { top: 'bottom', left: 'left' }, minWidth: maxWidth },
31
+ sm: { ...defaultOffsets, align: { top: 'bottom', right: 'right' }, minWidth: maxWidth },
31
32
  lg: {
33
+ ...defaultOffsets,
32
34
  align: { top: 'bottom', center: 'center' },
33
- offsets: { vertical: 4 },
34
35
  minWidth: 192
35
36
  }
36
37
  })
@@ -36,6 +36,7 @@ export {
36
36
  MultiSelectFilter,
37
37
  Notification,
38
38
  Pagination,
39
+ Portal,
39
40
  QuickLinks,
40
41
  QuickLinksFeature,
41
42
  Radio,
@@ -74,3 +75,6 @@ export {
74
75
  useCarousel,
75
76
  useSetTheme
76
77
  } from '@telus-uds/components-base'
78
+
79
+ // TODO: Added `WebPortal` alias for backwards compatibility with `Portal` from `@telus-uds/components-base`. Remove in next major version.
80
+ export { Portal as WebPortal } from '@telus-uds/components-base'
package/src/index.js CHANGED
@@ -36,7 +36,6 @@ export { default as TermsAndConditions } from './TermsAndConditions'
36
36
  export { default as NavigationBar } from './NavigationBar'
37
37
  export { default as Progress } from './Progress'
38
38
  export { default as SkeletonProvider } from './SkeletonProvider'
39
- export { default as WebPortal } from './WebPortal'
40
39
 
41
40
  export { ssrStyles } from './utils'
42
41
 
@@ -1,51 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = void 0;
7
- var _react = require("react");
8
- var _reactDom = _interopRequireDefault(require("react-dom"));
9
- var _propTypes = _interopRequireDefault(require("prop-types"));
10
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
- /**
12
- * WebPortal component renders its children in a separate portal container appended to the document body.
13
- *
14
- * While `@gorhom/portal` works well for a lot of use-cases, there are some issues with it, particularly around
15
- * reading context values (see issues below). For web-only components, it is safe to replace `Portal` from `@gorhom/portal`
16
- * to `WebPortal` to solve such issues
17
- *
18
- * https://github.com/gorhom/react-native-portal/issues/34
19
- * https://github.com/gorhom/react-native-portal/issues/2
20
- * https://github.com/gorhom/react-native-portal/issues/3
21
- * https://github.com/gorhom/react-native-portal/issues/31
22
- *
23
- * @component
24
- * @param {object} props - The component props.
25
- * @param {React.ReactNode} props.children - The content to render within the portal.
26
- * @returns {React.ReactPortal} The React portal component.
27
- */
28
-
29
- const WebPortal = _ref => {
30
- let {
31
- children
32
- } = _ref;
33
- const [portalContainer, setPortalContainer] = (0, _react.useState)(null);
34
- (0, _react.useEffect)(() => {
35
- const container = document.createElement('div');
36
- document.body.appendChild(container);
37
- setPortalContainer(container);
38
- return () => {
39
- if (container && container.parentNode) {
40
- container.parentNode.removeChild(container);
41
- }
42
- };
43
- }, []);
44
- if (!portalContainer) return null;
45
- return /*#__PURE__*/_reactDom.default.createPortal(children, portalContainer);
46
- };
47
- WebPortal.propTypes = {
48
- children: _propTypes.default.node.isRequired
49
- };
50
- var _default = WebPortal;
51
- exports.default = _default;
@@ -1,10 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = void 0;
7
- var _WebPortal = _interopRequireDefault(require("./WebPortal"));
8
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
9
- var _default = _WebPortal.default;
10
- exports.default = _default;
@@ -1,44 +0,0 @@
1
- import { useState, useEffect } from 'react';
2
- import ReactDOM from 'react-dom';
3
- import PropTypes from 'prop-types';
4
-
5
- /**
6
- * WebPortal component renders its children in a separate portal container appended to the document body.
7
- *
8
- * While `@gorhom/portal` works well for a lot of use-cases, there are some issues with it, particularly around
9
- * reading context values (see issues below). For web-only components, it is safe to replace `Portal` from `@gorhom/portal`
10
- * to `WebPortal` to solve such issues
11
- *
12
- * https://github.com/gorhom/react-native-portal/issues/34
13
- * https://github.com/gorhom/react-native-portal/issues/2
14
- * https://github.com/gorhom/react-native-portal/issues/3
15
- * https://github.com/gorhom/react-native-portal/issues/31
16
- *
17
- * @component
18
- * @param {object} props - The component props.
19
- * @param {React.ReactNode} props.children - The content to render within the portal.
20
- * @returns {React.ReactPortal} The React portal component.
21
- */
22
-
23
- const WebPortal = _ref => {
24
- let {
25
- children
26
- } = _ref;
27
- const [portalContainer, setPortalContainer] = useState(null);
28
- useEffect(() => {
29
- const container = document.createElement('div');
30
- document.body.appendChild(container);
31
- setPortalContainer(container);
32
- return () => {
33
- if (container && container.parentNode) {
34
- container.parentNode.removeChild(container);
35
- }
36
- };
37
- }, []);
38
- if (!portalContainer) return null;
39
- return /*#__PURE__*/ReactDOM.createPortal(children, portalContainer);
40
- };
41
- WebPortal.propTypes = {
42
- children: PropTypes.node.isRequired
43
- };
44
- export default WebPortal;
@@ -1,2 +0,0 @@
1
- import WebPortal from './WebPortal';
2
- export default WebPortal;
@@ -1,47 +0,0 @@
1
- import { useState, useEffect } from 'react'
2
- import ReactDOM from 'react-dom'
3
- import PropTypes from 'prop-types'
4
-
5
- /**
6
- * WebPortal component renders its children in a separate portal container appended to the document body.
7
- *
8
- * While `@gorhom/portal` works well for a lot of use-cases, there are some issues with it, particularly around
9
- * reading context values (see issues below). For web-only components, it is safe to replace `Portal` from `@gorhom/portal`
10
- * to `WebPortal` to solve such issues
11
- *
12
- * https://github.com/gorhom/react-native-portal/issues/34
13
- * https://github.com/gorhom/react-native-portal/issues/2
14
- * https://github.com/gorhom/react-native-portal/issues/3
15
- * https://github.com/gorhom/react-native-portal/issues/31
16
- *
17
- * @component
18
- * @param {object} props - The component props.
19
- * @param {React.ReactNode} props.children - The content to render within the portal.
20
- * @returns {React.ReactPortal} The React portal component.
21
- */
22
-
23
- const WebPortal = ({ children }) => {
24
- const [portalContainer, setPortalContainer] = useState(null)
25
-
26
- useEffect(() => {
27
- const container = document.createElement('div')
28
- document.body.appendChild(container)
29
- setPortalContainer(container)
30
-
31
- return () => {
32
- if (container && container.parentNode) {
33
- container.parentNode.removeChild(container)
34
- }
35
- }
36
- }, [])
37
-
38
- if (!portalContainer) return null
39
-
40
- return ReactDOM.createPortal(children, portalContainer)
41
- }
42
-
43
- WebPortal.propTypes = {
44
- children: PropTypes.node.isRequired
45
- }
46
-
47
- export default WebPortal
@@ -1,3 +0,0 @@
1
- import WebPortal from './WebPortal'
2
-
3
- export default WebPortal