@telus-uds/components-web 1.6.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,12 +1,34 @@
1
1
  # Change Log - @telus-uds/components-web
2
2
 
3
- This log was last generated on Wed, 19 Apr 2023 11:24:21 GMT and should not be manually modified.
3
+ This log was last generated on Thu, 20 Apr 2023 19:05:54 GMT and should not be manually modified.
4
4
 
5
5
  <!-- Start content -->
6
6
 
7
+ ## 1.7.0
8
+
9
+ Thu, 20 Apr 2023 19:05:54 GMT
10
+
11
+ ### Minor changes
12
+
13
+ - web modal to accept children (srikanthkhari@gmail.com)
14
+ - Added Spinner (wlsdud194@hotmail.com)
15
+ - update snapshots (kyle.king2@telus.com)
16
+ - Bump @telus-uds/components-base to v1.36.0
17
+ - Bump @telus-uds/system-theme-tokens to v2.21.0
18
+
19
+ ## 1.6.1
20
+
21
+ Wed, 19 Apr 2023 18:49:51 GMT
22
+
23
+ ### Patches
24
+
25
+ - Update default token to Preview Card (carlos.jeronimo@telus.com)
26
+ - Bump @telus-uds/components-base to v1.35.0
27
+ - Bump @telus-uds/system-theme-tokens to v2.20.0
28
+
7
29
  ## 1.6.0
8
30
 
9
- Wed, 19 Apr 2023 11:24:21 GMT
31
+ Wed, 19 Apr 2023 11:32:31 GMT
10
32
 
11
33
  ### Minor changes
12
34
 
@@ -19,6 +19,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
19
19
 
20
20
  const Modal = _ref => {
21
21
  let {
22
+ children,
22
23
  isOpen,
23
24
  onClose,
24
25
  maxWidth,
@@ -40,6 +41,7 @@ const Modal = _ref => {
40
41
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_componentsBase.Modal, {
41
42
  isOpen: isOpen,
42
43
  onClose: onClose,
44
+ variant: variant,
43
45
  maxWidth: maxWidth,
44
46
  ...nonContentProps,
45
47
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_ModalContent.default, {
@@ -55,12 +57,14 @@ const Modal = _ref => {
55
57
  confirmButtonText: confirmButtonText,
56
58
  confirmButtonVariant: confirmButtonVariant,
57
59
  cancelButtonText: cancelButtonText,
58
- cancelButtonType: cancelButtonType
60
+ cancelButtonType: cancelButtonType,
61
+ children: children
59
62
  })
60
63
  });
61
64
  };
62
65
 
63
66
  Modal.propTypes = {
67
+ children: _propTypes.default.node,
64
68
  tokens: _propTypes.default.object,
65
69
  variant: _propTypes.default.object,
66
70
 
@@ -92,6 +92,7 @@ const ModalContent = _ref4 => {
92
92
  variant,
93
93
  cancelButtonText,
94
94
  cancelButtonType: CancelButton = _componentsBase.TextButton,
95
+ children,
95
96
  onCancel
96
97
  } = _ref4;
97
98
  const {
@@ -152,7 +153,7 @@ const ModalContent = _ref4 => {
152
153
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_componentsBase.Typography, {
153
154
  children: bodyText
154
155
  })
155
- }), (hasConfirmButton || hasCancelButton) && /*#__PURE__*/(0, _jsxRuntime.jsxs)(StyledFooter, { ...themeTokens,
156
+ }), children, (hasConfirmButton || hasCancelButton) && /*#__PURE__*/(0, _jsxRuntime.jsxs)(StyledFooter, { ...themeTokens,
156
157
  hasBorder: isContentOverflowing,
157
158
  viewport: viewport,
158
159
  children: [hasConfirmButton && /*#__PURE__*/(0, _jsxRuntime.jsx)(_componentsBase.Button, {
@@ -189,6 +190,7 @@ ModalContent.propTypes = {
189
190
  cancelButtonText: _propTypes.default.string,
190
191
  cancelButtonType: _propTypes.default.elementType,
191
192
  // TODO: figure out a way of passing an icon to the TextButton
193
+ children: _propTypes.default.node,
192
194
  onCancel: _propTypes.default.func
193
195
  };
194
196
  var _default = ModalContent;
@@ -60,7 +60,11 @@ const FullBleedOffsetInner = /*#__PURE__*/_styledComponents.default.div.withConf
60
60
 
61
61
  const defaultTokens = {
62
62
  minWidth: 0,
63
- shadow: null
63
+ shadow: null,
64
+ contentAlignItems: 'stretch',
65
+ contentJustifyContent: 'flex-start',
66
+ contentFlexGrow: 0,
67
+ contentFlexShrink: 0
64
68
  };
65
69
  /**
66
70
  * Showcase and guide users to another page, with a preview containing title and a footer.
@@ -0,0 +1,234 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ var _react = _interopRequireDefault(require("react"));
9
+
10
+ var _propTypes = _interopRequireDefault(require("prop-types"));
11
+
12
+ var _styledComponents = _interopRequireDefault(require("styled-components"));
13
+
14
+ var _componentsBase = require("@telus-uds/components-base");
15
+
16
+ var _SpinnerContent = _interopRequireDefault(require("./SpinnerContent"));
17
+
18
+ var _utils = require("../utils");
19
+
20
+ var _constants = require("./constants");
21
+
22
+ var _jsxRuntime = require("react/jsx-runtime");
23
+
24
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
25
+
26
+ const [selectProps, selectedSystemPropTypes] = (0, _componentsBase.selectSystemProps)([_utils.htmlAttrs]);
27
+
28
+ const SpinnerContainer = /*#__PURE__*/_styledComponents.default.div.withConfig({
29
+ displayName: "Spinner__SpinnerContainer",
30
+ componentId: "components-web__sc-116rqck-0"
31
+ })(_ref => {
32
+ let {
33
+ inline,
34
+ fullScreen
35
+ } = _ref;
36
+ return {
37
+ position: 'relative',
38
+ ...(inline && {
39
+ display: 'block',
40
+ ...(0, _utils.media)().from('md').css({
41
+ display: 'inline-block'
42
+ })
43
+ }),
44
+ ...(fullScreen && {
45
+ top: '50%',
46
+ transform: 'translateY(-50%)'
47
+ })
48
+ };
49
+ });
50
+
51
+ const ContentOverlay = /*#__PURE__*/_styledComponents.default.div.withConfig({
52
+ displayName: "Spinner__ContentOverlay",
53
+ componentId: "components-web__sc-116rqck-1"
54
+ })({
55
+ position: 'absolute',
56
+ width: '100%',
57
+ height: '100%',
58
+ zIndex: _constants.BACKDROP_Z_INDEX
59
+ });
60
+
61
+ const FullscreenOverlay = /*#__PURE__*/_styledComponents.default.div.withConfig({
62
+ displayName: "Spinner__FullscreenOverlay",
63
+ componentId: "components-web__sc-116rqck-2"
64
+ })(_ref2 => {
65
+ let {
66
+ fullScreenOverLayBackground
67
+ } = _ref2;
68
+ return {
69
+ position: 'fixed',
70
+ width: '100vw',
71
+ height: '100vh',
72
+ top: 0,
73
+ left: 0,
74
+ zIndex: _constants.BACKDROP_Z_INDEX,
75
+ backgroundColor: fullScreenOverLayBackground
76
+ };
77
+ });
78
+
79
+ const OpaqueContainer = /*#__PURE__*/_styledComponents.default.div.withConfig({
80
+ displayName: "Spinner__OpaqueContainer",
81
+ componentId: "components-web__sc-116rqck-3"
82
+ })({
83
+ opacity: _constants.BACKDROP_OPACITY
84
+ });
85
+
86
+ const recursiveMap = (children, fn) => _react.default.Children.map(children, child => {
87
+ if (! /*#__PURE__*/_react.default.isValidElement(child)) {
88
+ return child;
89
+ }
90
+
91
+ if (child.props.children) {
92
+ return fn( /*#__PURE__*/_react.default.cloneElement(child, {
93
+ children: recursiveMap(child.props.children, fn)
94
+ }));
95
+ }
96
+
97
+ return fn(child);
98
+ });
99
+ /**
100
+ * Loading indicator.
101
+ */
102
+
103
+
104
+ const Spinner = _ref3 => {
105
+ let {
106
+ children,
107
+ fullScreen = false,
108
+ inline = false,
109
+ label,
110
+ show = false,
111
+ isStatic = false,
112
+ tokens,
113
+ variant = {},
114
+ ...rest
115
+ } = _ref3;
116
+ const {
117
+ fullScreenOverLayBackground,
118
+ size,
119
+ thickness
120
+ } = (0, _componentsBase.useThemeTokens)('Spinner', tokens, variant);
121
+ const {
122
+ size: sizeVariant = 'large'
123
+ } = variant;
124
+ (0, _componentsBase.useScrollBlocking)([fullScreen, show]);
125
+
126
+ if (!show) {
127
+ return children ?? null;
128
+ } // Full screen spinner
129
+
130
+
131
+ if (fullScreen) {
132
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(FullscreenOverlay, {
133
+ fullScreenOverLayBackground: fullScreenOverLayBackground,
134
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(SpinnerContainer, {
135
+ inline: inline,
136
+ fullScreen: fullScreen,
137
+ "aria-live": "assertive",
138
+ ...selectProps(rest),
139
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_SpinnerContent.default, {
140
+ label: label,
141
+ overlay: true,
142
+ size: size,
143
+ thickness: thickness,
144
+ sizeVariant: sizeVariant,
145
+ isStatic: isStatic
146
+ })
147
+ })
148
+ });
149
+ } // Overlay spinner
150
+
151
+
152
+ if (children) {
153
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(SpinnerContainer, {
154
+ inline: inline,
155
+ "aria-live": "assertive",
156
+ ...selectProps(rest),
157
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_SpinnerContent.default, {
158
+ label: label,
159
+ overlay: true,
160
+ size: size,
161
+ thickness: thickness,
162
+ sizeVariant: sizeVariant,
163
+ isStatic: isStatic
164
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(ContentOverlay, {}), /*#__PURE__*/(0, _jsxRuntime.jsx)(OpaqueContainer, {
165
+ inert: "true",
166
+ children: recursiveMap(children, c => {
167
+ if (c) {
168
+ return /*#__PURE__*/_react.default.cloneElement(c, {
169
+ tabIndex: '-1',
170
+ 'aria-hidden': 'true'
171
+ });
172
+ }
173
+
174
+ return undefined;
175
+ })
176
+ })]
177
+ });
178
+ } // Standalone spinner
179
+
180
+
181
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(SpinnerContainer, { ...selectProps(rest),
182
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_SpinnerContent.default, {
183
+ label: label,
184
+ size: size,
185
+ thickness: thickness,
186
+ sizeVariant: sizeVariant,
187
+ isStatic: isStatic
188
+ })
189
+ });
190
+ };
191
+
192
+ Spinner.propTypes = { ...selectedSystemPropTypes,
193
+
194
+ /**
195
+ * Content to be overlaid while the spinner is active. Can be text, any HTML element,
196
+ * or any component.
197
+ */
198
+ children: _propTypes.default.node,
199
+
200
+ /**
201
+ * Enables body locking.
202
+ */
203
+ fullScreen: _propTypes.default.bool,
204
+
205
+ /**
206
+ * Set the inline prop to true if the Spinner should only cover its children; if
207
+ * the Spinner should cover the full width of its parent regardless of the size of
208
+ * its children, inline should be set to false
209
+ */
210
+ inline: _propTypes.default.bool,
211
+
212
+ /**
213
+ * Communicates a message to assistive technology while visible. This same message
214
+ * will appear underneath the spinner when its `size` is `large`.
215
+ */
216
+ label: _propTypes.default.string.isRequired,
217
+
218
+ /**
219
+ * The size of the spinner
220
+ */
221
+ // size: PropTypes.oneOf(['large', 'small']),
222
+
223
+ /**
224
+ * Whether or not to render the spinner.
225
+ */
226
+ show: _propTypes.default.bool,
227
+
228
+ /**
229
+ * If true, it should render a static spinner
230
+ */
231
+ isStatic: _propTypes.default.bool
232
+ };
233
+ var _default = Spinner;
234
+ exports.default = _default;
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ var _react = _interopRequireDefault(require("react"));
9
+
10
+ var _propTypes = _interopRequireDefault(require("prop-types"));
11
+
12
+ var _styledComponents = _interopRequireDefault(require("styled-components"));
13
+
14
+ var _componentsBase = require("@telus-uds/components-base");
15
+
16
+ var _utils = require("../utils");
17
+
18
+ var _constants = require("./constants");
19
+
20
+ var _jsxRuntime = require("react/jsx-runtime");
21
+
22
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
23
+
24
+ const [selectProps, selectedSystemPropTypes] = (0, _componentsBase.selectSystemProps)([_utils.htmlAttrs]);
25
+
26
+ const Container = /*#__PURE__*/_styledComponents.default.div.withConfig({
27
+ displayName: "SpinnerContent__Container",
28
+ componentId: "components-web__sc-1c8bd8e-0"
29
+ })(_ref => {
30
+ let {
31
+ overlay
32
+ } = _ref;
33
+ return {
34
+ display: 'inline-flex',
35
+ flexDirection: 'column',
36
+ alignItems: 'center',
37
+ ...(overlay && {
38
+ position: 'absolute',
39
+ top: '50%',
40
+ left: '50%',
41
+ transform: 'translate(-50%, -50%)',
42
+ zIndex: _constants.BACKDROP_Z_INDEX
43
+ })
44
+ };
45
+ });
46
+
47
+ const SpinnerContent = _ref2 => {
48
+ let {
49
+ label,
50
+ overlay = false,
51
+ sizeVariant,
52
+ size,
53
+ thickness,
54
+ isStatic,
55
+ ...rest
56
+ } = _ref2;
57
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(Container, {
58
+ overlay: overlay,
59
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_componentsBase.StackView, {
60
+ space: 3,
61
+ tokens: {
62
+ alignItems: 'center'
63
+ },
64
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_componentsBase.ActivityIndicator, {
65
+ label: label,
66
+ tokens: {
67
+ size,
68
+ thickness
69
+ },
70
+ isStatic: isStatic,
71
+ ...selectProps(rest)
72
+ }), sizeVariant === _constants.LARGE && /*#__PURE__*/(0, _jsxRuntime.jsx)(_componentsBase.Typography, {
73
+ children: label
74
+ })]
75
+ })
76
+ });
77
+ };
78
+
79
+ SpinnerContent.propTypes = { ...selectedSystemPropTypes,
80
+
81
+ /**
82
+ * Communicates a message to assistive technology while visible. This same message will appear underneath the spinner when its `size` is `large`.
83
+ */
84
+ label: _propTypes.default.string.isRequired,
85
+
86
+ /**
87
+ * Whether the container has to have an overlay styling.
88
+ */
89
+ overlay: _propTypes.default.bool,
90
+
91
+ /**
92
+ * Size (width and height) of the spinner.
93
+ */
94
+ size: _propTypes.default.number,
95
+
96
+ /**
97
+ * The size of the spinner
98
+ */
99
+ sizeVariant: _propTypes.default.oneOf(['large', 'small']),
100
+
101
+ /**
102
+ * If true, it should render a static spinner
103
+ */
104
+ isStatic: _propTypes.default.bool
105
+ };
106
+ var _default = SpinnerContent;
107
+ exports.default = _default;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.SMALL = exports.LARGE = exports.BACKDROP_Z_INDEX = exports.BACKDROP_OPACITY = void 0;
7
+ const BACKDROP_OPACITY = 0.06;
8
+ exports.BACKDROP_OPACITY = BACKDROP_OPACITY;
9
+ const BACKDROP_Z_INDEX = 1400;
10
+ exports.BACKDROP_Z_INDEX = BACKDROP_Z_INDEX;
11
+ const LARGE = 'large';
12
+ exports.LARGE = LARGE;
13
+ const SMALL = 'small';
14
+ exports.SMALL = SMALL;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ var _Spinner = _interopRequireDefault(require("./Spinner"));
9
+
10
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
+
12
+ var _default = _Spinner.default;
13
+ exports.default = _default;
package/lib/index.js CHANGED
@@ -22,7 +22,8 @@ var _exportNames = {
22
22
  Toast: true,
23
23
  Table: true,
24
24
  Image: true,
25
- WaffleGrid: true
25
+ WaffleGrid: true,
26
+ Spinner: true
26
27
  };
27
28
  Object.defineProperty(exports, "Badge", {
28
29
  enumerable: true,
@@ -114,6 +115,12 @@ Object.defineProperty(exports, "Span", {
114
115
  return _Span.default;
115
116
  }
116
117
  });
118
+ Object.defineProperty(exports, "Spinner", {
119
+ enumerable: true,
120
+ get: function () {
121
+ return _Spinner.default;
122
+ }
123
+ });
117
124
  Object.defineProperty(exports, "Table", {
118
125
  enumerable: true,
119
126
  get: function () {
@@ -177,6 +184,8 @@ var _Image = _interopRequireDefault(require("./Image"));
177
184
 
178
185
  var _WaffleGrid = _interopRequireDefault(require("./WaffleGrid"));
179
186
 
187
+ var _Spinner = _interopRequireDefault(require("./Spinner"));
188
+
180
189
  var _baseExports = require("./baseExports");
181
190
 
182
191
  Object.keys(_baseExports).forEach(function (key) {
@@ -6,6 +6,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
6
6
 
7
7
  const Modal = _ref => {
8
8
  let {
9
+ children,
9
10
  isOpen,
10
11
  onClose,
11
12
  maxWidth,
@@ -27,6 +28,7 @@ const Modal = _ref => {
27
28
  return /*#__PURE__*/_jsx(BaseModal, {
28
29
  isOpen: isOpen,
29
30
  onClose: onClose,
31
+ variant: variant,
30
32
  maxWidth: maxWidth,
31
33
  ...nonContentProps,
32
34
  children: /*#__PURE__*/_jsx(ModalContent, {
@@ -42,12 +44,14 @@ const Modal = _ref => {
42
44
  confirmButtonText: confirmButtonText,
43
45
  confirmButtonVariant: confirmButtonVariant,
44
46
  cancelButtonText: cancelButtonText,
45
- cancelButtonType: cancelButtonType
47
+ cancelButtonType: cancelButtonType,
48
+ children: children
46
49
  })
47
50
  });
48
51
  };
49
52
 
50
53
  Modal.propTypes = {
54
+ children: PropTypes.node,
51
55
  tokens: PropTypes.object,
52
56
  variant: PropTypes.object,
53
57
 
@@ -72,6 +72,7 @@ const ModalContent = _ref4 => {
72
72
  variant,
73
73
  cancelButtonText,
74
74
  cancelButtonType: CancelButton = TextButton,
75
+ children,
75
76
  onCancel
76
77
  } = _ref4;
77
78
  const {
@@ -132,7 +133,7 @@ const ModalContent = _ref4 => {
132
133
  children: /*#__PURE__*/_jsx(Typography, {
133
134
  children: bodyText
134
135
  })
135
- }), (hasConfirmButton || hasCancelButton) && /*#__PURE__*/_jsxs(StyledFooter, { ...themeTokens,
136
+ }), children, (hasConfirmButton || hasCancelButton) && /*#__PURE__*/_jsxs(StyledFooter, { ...themeTokens,
136
137
  hasBorder: isContentOverflowing,
137
138
  viewport: viewport,
138
139
  children: [hasConfirmButton && /*#__PURE__*/_jsx(Button, {
@@ -169,6 +170,7 @@ ModalContent.propTypes = {
169
170
  cancelButtonText: PropTypes.string,
170
171
  cancelButtonType: PropTypes.elementType,
171
172
  // TODO: figure out a way of passing an icon to the TextButton
173
+ children: PropTypes.node,
172
174
  onCancel: PropTypes.func
173
175
  };
174
176
  export default ModalContent;
@@ -39,7 +39,11 @@ const FullBleedOffsetInner = /*#__PURE__*/styled.div.withConfig({
39
39
  });
40
40
  const defaultTokens = {
41
41
  minWidth: 0,
42
- shadow: null
42
+ shadow: null,
43
+ contentAlignItems: 'stretch',
44
+ contentJustifyContent: 'flex-start',
45
+ contentFlexGrow: 0,
46
+ contentFlexShrink: 0
43
47
  };
44
48
  /**
45
49
  * Showcase and guide users to another page, with a preview containing title and a footer.
@@ -0,0 +1,213 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import styled from 'styled-components';
4
+ import { selectSystemProps, useScrollBlocking, useThemeTokens } from '@telus-uds/components-base';
5
+ import SpinnerContent from './SpinnerContent';
6
+ import { htmlAttrs, media } from '../utils';
7
+ import { BACKDROP_OPACITY, BACKDROP_Z_INDEX } from './constants';
8
+ import { jsx as _jsx } from "react/jsx-runtime";
9
+ import { jsxs as _jsxs } from "react/jsx-runtime";
10
+ const [selectProps, selectedSystemPropTypes] = selectSystemProps([htmlAttrs]);
11
+ const SpinnerContainer = /*#__PURE__*/styled.div.withConfig({
12
+ displayName: "Spinner__SpinnerContainer",
13
+ componentId: "components-web__sc-116rqck-0"
14
+ })(_ref => {
15
+ let {
16
+ inline,
17
+ fullScreen
18
+ } = _ref;
19
+ return {
20
+ position: 'relative',
21
+ ...(inline && {
22
+ display: 'block',
23
+ ...media().from('md').css({
24
+ display: 'inline-block'
25
+ })
26
+ }),
27
+ ...(fullScreen && {
28
+ top: '50%',
29
+ transform: 'translateY(-50%)'
30
+ })
31
+ };
32
+ });
33
+ const ContentOverlay = /*#__PURE__*/styled.div.withConfig({
34
+ displayName: "Spinner__ContentOverlay",
35
+ componentId: "components-web__sc-116rqck-1"
36
+ })({
37
+ position: 'absolute',
38
+ width: '100%',
39
+ height: '100%',
40
+ zIndex: BACKDROP_Z_INDEX
41
+ });
42
+ const FullscreenOverlay = /*#__PURE__*/styled.div.withConfig({
43
+ displayName: "Spinner__FullscreenOverlay",
44
+ componentId: "components-web__sc-116rqck-2"
45
+ })(_ref2 => {
46
+ let {
47
+ fullScreenOverLayBackground
48
+ } = _ref2;
49
+ return {
50
+ position: 'fixed',
51
+ width: '100vw',
52
+ height: '100vh',
53
+ top: 0,
54
+ left: 0,
55
+ zIndex: BACKDROP_Z_INDEX,
56
+ backgroundColor: fullScreenOverLayBackground
57
+ };
58
+ });
59
+ const OpaqueContainer = /*#__PURE__*/styled.div.withConfig({
60
+ displayName: "Spinner__OpaqueContainer",
61
+ componentId: "components-web__sc-116rqck-3"
62
+ })({
63
+ opacity: BACKDROP_OPACITY
64
+ });
65
+
66
+ const recursiveMap = (children, fn) => React.Children.map(children, child => {
67
+ if (! /*#__PURE__*/React.isValidElement(child)) {
68
+ return child;
69
+ }
70
+
71
+ if (child.props.children) {
72
+ return fn( /*#__PURE__*/React.cloneElement(child, {
73
+ children: recursiveMap(child.props.children, fn)
74
+ }));
75
+ }
76
+
77
+ return fn(child);
78
+ });
79
+ /**
80
+ * Loading indicator.
81
+ */
82
+
83
+
84
+ const Spinner = _ref3 => {
85
+ let {
86
+ children,
87
+ fullScreen = false,
88
+ inline = false,
89
+ label,
90
+ show = false,
91
+ isStatic = false,
92
+ tokens,
93
+ variant = {},
94
+ ...rest
95
+ } = _ref3;
96
+ const {
97
+ fullScreenOverLayBackground,
98
+ size,
99
+ thickness
100
+ } = useThemeTokens('Spinner', tokens, variant);
101
+ const {
102
+ size: sizeVariant = 'large'
103
+ } = variant;
104
+ useScrollBlocking([fullScreen, show]);
105
+
106
+ if (!show) {
107
+ return children ?? null;
108
+ } // Full screen spinner
109
+
110
+
111
+ if (fullScreen) {
112
+ return /*#__PURE__*/_jsx(FullscreenOverlay, {
113
+ fullScreenOverLayBackground: fullScreenOverLayBackground,
114
+ children: /*#__PURE__*/_jsx(SpinnerContainer, {
115
+ inline: inline,
116
+ fullScreen: fullScreen,
117
+ "aria-live": "assertive",
118
+ ...selectProps(rest),
119
+ children: /*#__PURE__*/_jsx(SpinnerContent, {
120
+ label: label,
121
+ overlay: true,
122
+ size: size,
123
+ thickness: thickness,
124
+ sizeVariant: sizeVariant,
125
+ isStatic: isStatic
126
+ })
127
+ })
128
+ });
129
+ } // Overlay spinner
130
+
131
+
132
+ if (children) {
133
+ return /*#__PURE__*/_jsxs(SpinnerContainer, {
134
+ inline: inline,
135
+ "aria-live": "assertive",
136
+ ...selectProps(rest),
137
+ children: [/*#__PURE__*/_jsx(SpinnerContent, {
138
+ label: label,
139
+ overlay: true,
140
+ size: size,
141
+ thickness: thickness,
142
+ sizeVariant: sizeVariant,
143
+ isStatic: isStatic
144
+ }), /*#__PURE__*/_jsx(ContentOverlay, {}), /*#__PURE__*/_jsx(OpaqueContainer, {
145
+ inert: "true",
146
+ children: recursiveMap(children, c => {
147
+ if (c) {
148
+ return /*#__PURE__*/React.cloneElement(c, {
149
+ tabIndex: '-1',
150
+ 'aria-hidden': 'true'
151
+ });
152
+ }
153
+
154
+ return undefined;
155
+ })
156
+ })]
157
+ });
158
+ } // Standalone spinner
159
+
160
+
161
+ return /*#__PURE__*/_jsx(SpinnerContainer, { ...selectProps(rest),
162
+ children: /*#__PURE__*/_jsx(SpinnerContent, {
163
+ label: label,
164
+ size: size,
165
+ thickness: thickness,
166
+ sizeVariant: sizeVariant,
167
+ isStatic: isStatic
168
+ })
169
+ });
170
+ };
171
+
172
+ Spinner.propTypes = { ...selectedSystemPropTypes,
173
+
174
+ /**
175
+ * Content to be overlaid while the spinner is active. Can be text, any HTML element,
176
+ * or any component.
177
+ */
178
+ children: PropTypes.node,
179
+
180
+ /**
181
+ * Enables body locking.
182
+ */
183
+ fullScreen: PropTypes.bool,
184
+
185
+ /**
186
+ * Set the inline prop to true if the Spinner should only cover its children; if
187
+ * the Spinner should cover the full width of its parent regardless of the size of
188
+ * its children, inline should be set to false
189
+ */
190
+ inline: PropTypes.bool,
191
+
192
+ /**
193
+ * Communicates a message to assistive technology while visible. This same message
194
+ * will appear underneath the spinner when its `size` is `large`.
195
+ */
196
+ label: PropTypes.string.isRequired,
197
+
198
+ /**
199
+ * The size of the spinner
200
+ */
201
+ // size: PropTypes.oneOf(['large', 'small']),
202
+
203
+ /**
204
+ * Whether or not to render the spinner.
205
+ */
206
+ show: PropTypes.bool,
207
+
208
+ /**
209
+ * If true, it should render a static spinner
210
+ */
211
+ isStatic: PropTypes.bool
212
+ };
213
+ export default Spinner;
@@ -0,0 +1,90 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import styled from 'styled-components';
4
+ import { ActivityIndicator, StackView, Typography, selectSystemProps } from '@telus-uds/components-base';
5
+ import { htmlAttrs } from '../utils';
6
+ import { BACKDROP_Z_INDEX, LARGE } from './constants';
7
+ import { jsx as _jsx } from "react/jsx-runtime";
8
+ import { jsxs as _jsxs } from "react/jsx-runtime";
9
+ const [selectProps, selectedSystemPropTypes] = selectSystemProps([htmlAttrs]);
10
+ const Container = /*#__PURE__*/styled.div.withConfig({
11
+ displayName: "SpinnerContent__Container",
12
+ componentId: "components-web__sc-1c8bd8e-0"
13
+ })(_ref => {
14
+ let {
15
+ overlay
16
+ } = _ref;
17
+ return {
18
+ display: 'inline-flex',
19
+ flexDirection: 'column',
20
+ alignItems: 'center',
21
+ ...(overlay && {
22
+ position: 'absolute',
23
+ top: '50%',
24
+ left: '50%',
25
+ transform: 'translate(-50%, -50%)',
26
+ zIndex: BACKDROP_Z_INDEX
27
+ })
28
+ };
29
+ });
30
+
31
+ const SpinnerContent = _ref2 => {
32
+ let {
33
+ label,
34
+ overlay = false,
35
+ sizeVariant,
36
+ size,
37
+ thickness,
38
+ isStatic,
39
+ ...rest
40
+ } = _ref2;
41
+ return /*#__PURE__*/_jsx(Container, {
42
+ overlay: overlay,
43
+ children: /*#__PURE__*/_jsxs(StackView, {
44
+ space: 3,
45
+ tokens: {
46
+ alignItems: 'center'
47
+ },
48
+ children: [/*#__PURE__*/_jsx(ActivityIndicator, {
49
+ label: label,
50
+ tokens: {
51
+ size,
52
+ thickness
53
+ },
54
+ isStatic: isStatic,
55
+ ...selectProps(rest)
56
+ }), sizeVariant === LARGE && /*#__PURE__*/_jsx(Typography, {
57
+ children: label
58
+ })]
59
+ })
60
+ });
61
+ };
62
+
63
+ SpinnerContent.propTypes = { ...selectedSystemPropTypes,
64
+
65
+ /**
66
+ * Communicates a message to assistive technology while visible. This same message will appear underneath the spinner when its `size` is `large`.
67
+ */
68
+ label: PropTypes.string.isRequired,
69
+
70
+ /**
71
+ * Whether the container has to have an overlay styling.
72
+ */
73
+ overlay: PropTypes.bool,
74
+
75
+ /**
76
+ * Size (width and height) of the spinner.
77
+ */
78
+ size: PropTypes.number,
79
+
80
+ /**
81
+ * The size of the spinner
82
+ */
83
+ sizeVariant: PropTypes.oneOf(['large', 'small']),
84
+
85
+ /**
86
+ * If true, it should render a static spinner
87
+ */
88
+ isStatic: PropTypes.bool
89
+ };
90
+ export default SpinnerContent;
@@ -0,0 +1,4 @@
1
+ export const BACKDROP_OPACITY = 0.06;
2
+ export const BACKDROP_Z_INDEX = 1400;
3
+ export const LARGE = 'large';
4
+ export const SMALL = 'small';
@@ -0,0 +1,2 @@
1
+ import Spinner from './Spinner';
2
+ export default Spinner;
@@ -17,4 +17,5 @@ export { default as Toast } from './Toast';
17
17
  export { default as Table } from './Table';
18
18
  export { default as Image } from './Image';
19
19
  export { default as WaffleGrid } from './WaffleGrid';
20
+ export { default as Spinner } from './Spinner';
20
21
  export * from './baseExports';
package/package.json CHANGED
@@ -5,11 +5,11 @@
5
5
  ],
6
6
  "dependencies": {
7
7
  "@gorhom/portal": "^1.0.14",
8
- "@telus-uds/components-base": "1.34.2",
8
+ "@telus-uds/components-base": "1.36.0",
9
9
  "@telus-uds/system-constants": "^1.2.0",
10
10
  "react-dates": "^21.8.0",
11
11
  "react-moment-proptypes": "^1.8.1",
12
- "@telus-uds/system-theme-tokens": "^2.19.0",
12
+ "@telus-uds/system-theme-tokens": "^2.21.0",
13
13
  "prop-types": "^15.7.2",
14
14
  "lodash.omit": "^4.5.0",
15
15
  "lodash.throttle": "^4.1.1",
@@ -59,5 +59,5 @@
59
59
  "skip": true
60
60
  },
61
61
  "types": "types/index.d.ts",
62
- "version": "1.6.0"
62
+ "version": "1.7.0"
63
63
  }
@@ -4,6 +4,7 @@ import PropTypes from 'prop-types'
4
4
  import ModalContent from './ModalContent'
5
5
 
6
6
  const Modal = ({
7
+ children,
7
8
  isOpen,
8
9
  onClose,
9
10
  maxWidth,
@@ -23,7 +24,13 @@ const Modal = ({
23
24
  ...nonContentProps
24
25
  }) => {
25
26
  return (
26
- <BaseModal isOpen={isOpen} onClose={onClose} maxWidth={maxWidth} {...nonContentProps}>
27
+ <BaseModal
28
+ isOpen={isOpen}
29
+ onClose={onClose}
30
+ variant={variant}
31
+ maxWidth={maxWidth}
32
+ {...nonContentProps}
33
+ >
27
34
  <ModalContent
28
35
  tokens={tokens}
29
36
  variant={variant}
@@ -38,12 +45,15 @@ const Modal = ({
38
45
  confirmButtonVariant={confirmButtonVariant}
39
46
  cancelButtonText={cancelButtonText}
40
47
  cancelButtonType={cancelButtonType}
41
- />
48
+ >
49
+ {children}
50
+ </ModalContent>
42
51
  </BaseModal>
43
52
  )
44
53
  }
45
54
 
46
55
  Modal.propTypes = {
56
+ children: PropTypes.node,
47
57
  tokens: PropTypes.object,
48
58
  variant: PropTypes.object,
49
59
  /**
@@ -66,6 +66,7 @@ const ModalContent = ({
66
66
  variant,
67
67
  cancelButtonText,
68
68
  cancelButtonType: CancelButton = TextButton,
69
+ children,
69
70
  onCancel
70
71
  }) => {
71
72
  const { headingColor, cancelButtonColor, ...themeTokens } = useThemeTokens(
@@ -118,6 +119,7 @@ const ModalContent = ({
118
119
  <Typography>{bodyText}</Typography>
119
120
  </Box>
120
121
  )}
122
+ {children}
121
123
  {(hasConfirmButton || hasCancelButton) && (
122
124
  <StyledFooter {...themeTokens} hasBorder={isContentOverflowing} viewport={viewport}>
123
125
  {hasConfirmButton && (
@@ -155,6 +157,7 @@ ModalContent.propTypes = {
155
157
  onConfirm: PropTypes.func,
156
158
  cancelButtonText: PropTypes.string,
157
159
  cancelButtonType: PropTypes.elementType, // TODO: figure out a way of passing an icon to the TextButton
160
+ children: PropTypes.node,
158
161
  onCancel: PropTypes.func
159
162
  }
160
163
 
@@ -44,7 +44,11 @@ const FullBleedOffsetInner = styled.div(({ borderOffset }) => ({
44
44
 
45
45
  const defaultTokens = {
46
46
  minWidth: 0,
47
- shadow: null
47
+ shadow: null,
48
+ contentAlignItems: 'stretch',
49
+ contentJustifyContent: 'flex-start',
50
+ contentFlexGrow: 0,
51
+ contentFlexShrink: 0
48
52
  }
49
53
 
50
54
  /**
@@ -0,0 +1,186 @@
1
+ import React from 'react'
2
+ import PropTypes from 'prop-types'
3
+ import styled from 'styled-components'
4
+ import { selectSystemProps, useScrollBlocking, useThemeTokens } from '@telus-uds/components-base'
5
+ import SpinnerContent from './SpinnerContent'
6
+ import { htmlAttrs, media } from '../utils'
7
+ import { BACKDROP_OPACITY, BACKDROP_Z_INDEX } from './constants'
8
+
9
+ const [selectProps, selectedSystemPropTypes] = selectSystemProps([htmlAttrs])
10
+
11
+ const SpinnerContainer = styled.div(({ inline, fullScreen }) => ({
12
+ position: 'relative',
13
+ ...(inline && {
14
+ display: 'block',
15
+ ...media().from('md').css({
16
+ display: 'inline-block'
17
+ })
18
+ }),
19
+ ...(fullScreen && { top: '50%', transform: 'translateY(-50%)' })
20
+ }))
21
+
22
+ const ContentOverlay = styled.div({
23
+ position: 'absolute',
24
+ width: '100%',
25
+ height: '100%',
26
+ zIndex: BACKDROP_Z_INDEX
27
+ })
28
+
29
+ const FullscreenOverlay = styled.div(({ fullScreenOverLayBackground }) => ({
30
+ position: 'fixed',
31
+ width: '100vw',
32
+ height: '100vh',
33
+ top: 0,
34
+ left: 0,
35
+ zIndex: BACKDROP_Z_INDEX,
36
+ backgroundColor: fullScreenOverLayBackground
37
+ }))
38
+ const OpaqueContainer = styled.div({
39
+ opacity: BACKDROP_OPACITY
40
+ })
41
+
42
+ const recursiveMap = (children, fn) =>
43
+ React.Children.map(children, (child) => {
44
+ if (!React.isValidElement(child)) {
45
+ return child
46
+ }
47
+ if (child.props.children) {
48
+ return fn(
49
+ React.cloneElement(child, {
50
+ children: recursiveMap(child.props.children, fn)
51
+ })
52
+ )
53
+ }
54
+
55
+ return fn(child)
56
+ })
57
+
58
+ /**
59
+ * Loading indicator.
60
+ */
61
+ const Spinner = ({
62
+ children,
63
+ fullScreen = false,
64
+ inline = false,
65
+ label,
66
+ show = false,
67
+ isStatic = false,
68
+ tokens,
69
+ variant = {},
70
+ ...rest
71
+ }) => {
72
+ const { fullScreenOverLayBackground, size, thickness } = useThemeTokens(
73
+ 'Spinner',
74
+ tokens,
75
+ variant
76
+ )
77
+
78
+ const { size: sizeVariant = 'large' } = variant
79
+
80
+ useScrollBlocking([fullScreen, show])
81
+
82
+ if (!show) {
83
+ return children ?? null
84
+ }
85
+
86
+ // Full screen spinner
87
+ if (fullScreen) {
88
+ return (
89
+ <FullscreenOverlay fullScreenOverLayBackground={fullScreenOverLayBackground}>
90
+ <SpinnerContainer
91
+ inline={inline}
92
+ fullScreen={fullScreen}
93
+ aria-live="assertive"
94
+ {...selectProps(rest)}
95
+ >
96
+ <SpinnerContent
97
+ label={label}
98
+ overlay={true}
99
+ size={size}
100
+ thickness={thickness}
101
+ sizeVariant={sizeVariant}
102
+ isStatic={isStatic}
103
+ />
104
+ </SpinnerContainer>
105
+ </FullscreenOverlay>
106
+ )
107
+ }
108
+
109
+ // Overlay spinner
110
+ if (children) {
111
+ return (
112
+ <SpinnerContainer inline={inline} aria-live="assertive" {...selectProps(rest)}>
113
+ <SpinnerContent
114
+ label={label}
115
+ overlay={true}
116
+ size={size}
117
+ thickness={thickness}
118
+ sizeVariant={sizeVariant}
119
+ isStatic={isStatic}
120
+ />
121
+
122
+ <ContentOverlay />
123
+
124
+ <OpaqueContainer inert="true">
125
+ {recursiveMap(children, (c) => {
126
+ if (c) {
127
+ return React.cloneElement(c, { tabIndex: '-1', 'aria-hidden': 'true' })
128
+ }
129
+ return undefined
130
+ })}
131
+ </OpaqueContainer>
132
+ </SpinnerContainer>
133
+ )
134
+ }
135
+
136
+ // Standalone spinner
137
+ return (
138
+ <SpinnerContainer {...selectProps(rest)}>
139
+ <SpinnerContent
140
+ label={label}
141
+ size={size}
142
+ thickness={thickness}
143
+ sizeVariant={sizeVariant}
144
+ isStatic={isStatic}
145
+ />
146
+ </SpinnerContainer>
147
+ )
148
+ }
149
+
150
+ Spinner.propTypes = {
151
+ ...selectedSystemPropTypes,
152
+ /**
153
+ * Content to be overlaid while the spinner is active. Can be text, any HTML element,
154
+ * or any component.
155
+ */
156
+ children: PropTypes.node,
157
+ /**
158
+ * Enables body locking.
159
+ */
160
+ fullScreen: PropTypes.bool,
161
+ /**
162
+ * Set the inline prop to true if the Spinner should only cover its children; if
163
+ * the Spinner should cover the full width of its parent regardless of the size of
164
+ * its children, inline should be set to false
165
+ */
166
+ inline: PropTypes.bool,
167
+ /**
168
+ * Communicates a message to assistive technology while visible. This same message
169
+ * will appear underneath the spinner when its `size` is `large`.
170
+ */
171
+ label: PropTypes.string.isRequired,
172
+ /**
173
+ * The size of the spinner
174
+ */
175
+ // size: PropTypes.oneOf(['large', 'small']),
176
+ /**
177
+ * Whether or not to render the spinner.
178
+ */
179
+ show: PropTypes.bool,
180
+ /**
181
+ * If true, it should render a static spinner
182
+ */
183
+ isStatic: PropTypes.bool
184
+ }
185
+
186
+ export default Spinner
@@ -0,0 +1,76 @@
1
+ import React from 'react'
2
+ import PropTypes from 'prop-types'
3
+ import styled from 'styled-components'
4
+ import {
5
+ ActivityIndicator,
6
+ StackView,
7
+ Typography,
8
+ selectSystemProps
9
+ } from '@telus-uds/components-base'
10
+ import { htmlAttrs } from '../utils'
11
+ import { BACKDROP_Z_INDEX, LARGE } from './constants'
12
+
13
+ const [selectProps, selectedSystemPropTypes] = selectSystemProps([htmlAttrs])
14
+
15
+ const Container = styled.div(({ overlay }) => ({
16
+ display: 'inline-flex',
17
+ flexDirection: 'column',
18
+ alignItems: 'center',
19
+ ...(overlay && {
20
+ position: 'absolute',
21
+ top: '50%',
22
+ left: '50%',
23
+ transform: 'translate(-50%, -50%)',
24
+ zIndex: BACKDROP_Z_INDEX
25
+ })
26
+ }))
27
+
28
+ const SpinnerContent = ({
29
+ label,
30
+ overlay = false,
31
+ sizeVariant,
32
+ size,
33
+ thickness,
34
+ isStatic,
35
+ ...rest
36
+ }) => {
37
+ return (
38
+ <Container overlay={overlay}>
39
+ <StackView space={3} tokens={{ alignItems: 'center' }}>
40
+ <ActivityIndicator
41
+ label={label}
42
+ tokens={{ size, thickness }}
43
+ isStatic={isStatic}
44
+ {...selectProps(rest)}
45
+ />
46
+ {sizeVariant === LARGE && <Typography>{label}</Typography>}
47
+ </StackView>
48
+ </Container>
49
+ )
50
+ }
51
+
52
+ SpinnerContent.propTypes = {
53
+ ...selectedSystemPropTypes,
54
+ /**
55
+ * Communicates a message to assistive technology while visible. This same message will appear underneath the spinner when its `size` is `large`.
56
+ */
57
+ label: PropTypes.string.isRequired,
58
+ /**
59
+ * Whether the container has to have an overlay styling.
60
+ */
61
+ overlay: PropTypes.bool,
62
+ /**
63
+ * Size (width and height) of the spinner.
64
+ */
65
+ size: PropTypes.number,
66
+ /**
67
+ * The size of the spinner
68
+ */
69
+ sizeVariant: PropTypes.oneOf(['large', 'small']),
70
+ /**
71
+ * If true, it should render a static spinner
72
+ */
73
+ isStatic: PropTypes.bool
74
+ }
75
+
76
+ export default SpinnerContent
@@ -0,0 +1,4 @@
1
+ export const BACKDROP_OPACITY = 0.06
2
+ export const BACKDROP_Z_INDEX = 1400
3
+ export const LARGE = 'large'
4
+ export const SMALL = 'small'
@@ -0,0 +1,3 @@
1
+ import Spinner from './Spinner'
2
+
3
+ export default Spinner
package/src/index.js CHANGED
@@ -17,5 +17,6 @@ export { default as Toast } from './Toast'
17
17
  export { default as Table } from './Table'
18
18
  export { default as Image } from './Image'
19
19
  export { default as WaffleGrid } from './WaffleGrid'
20
+ export { default as Spinner } from './Spinner'
20
21
 
21
22
  export * from './baseExports'
@@ -0,0 +1,16 @@
1
+ import type { ComponentType, ReactNode } from 'react'
2
+ import type { HTMLAttrs, Variant } from './common'
3
+
4
+ export interface SpinnerProps extends HTMLAttrs {
5
+ children?: ReactNode
6
+ variant?: Variant
7
+ fullScreen?: boolean
8
+ inline?: boolean
9
+ label: string
10
+ show?: boolean
11
+ isStatic?: boolean
12
+ }
13
+
14
+ declare const Spinner: ComponentType<SpinnerProps>
15
+
16
+ export default Spinner