@telus-uds/components-base 4.0.0-alpha.1 → 4.0.0-alpha.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.
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.ScrollItem = void 0;
7
+ var _react = _interopRequireDefault(require("react"));
8
+ var _propTypes = _interopRequireDefault(require("prop-types"));
9
+ var _Platform = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Platform"));
10
+ var _View = _interopRequireDefault(require("react-native-web/dist/cjs/exports/View"));
11
+ var _a11yProps = require("../utils/props/a11yProps");
12
+ var _selectSystemProps = require("../utils/props/selectSystemProps");
13
+ var _viewProps = require("../utils/props/viewProps");
14
+ var _semantics = require("../utils/a11y/semantics");
15
+ var _ScrollContext = require("./ScrollContext");
16
+ var _jsxRuntime = require("react/jsx-runtime");
17
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
18
+ const [selectProps, selectedSystemPropTypes] = (0, _selectSystemProps.selectSystemProps)([_a11yProps.a11yProps, _viewProps.viewProps]);
19
+ const DEFAULT_TAG = 'li';
20
+ const DATA_SCROLL_ITEM = 'scrollItem';
21
+ const INITIAL_DIMENSION = 0;
22
+ const TAB_INDEX = 0;
23
+ const selectContainerStyle = _ref => {
24
+ let {
25
+ itemWidth,
26
+ itemHeight
27
+ } = _ref;
28
+ const style = {};
29
+ if (itemWidth > INITIAL_DIMENSION) {
30
+ style.width = itemWidth;
31
+ }
32
+ if (itemHeight > INITIAL_DIMENSION) {
33
+ style.height = itemHeight;
34
+ }
35
+ return style;
36
+ };
37
+
38
+ /**
39
+ * The `ScrollItem` component wraps individual items within a `Scroll` container. Each item
40
+ * is individually focusable and reports its natural dimensions so the parent can apply uniform
41
+ * sizing across all items.
42
+ *
43
+ * ## Props
44
+ *
45
+ * - Use `children` to provide the content of the scroll item
46
+ * - Use `tag` to set the HTML tag of the outer container (defaults to `'li'`)
47
+ *
48
+ */
49
+ const ScrollItem = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
50
+ let {
51
+ children,
52
+ tag = DEFAULT_TAG,
53
+ ...rest
54
+ } = _ref2;
55
+ const {
56
+ itemWidth,
57
+ itemHeight,
58
+ onItemLayout
59
+ } = (0, _ScrollContext.useScroll)();
60
+ const handleLayout = _react.default.useCallback(_ref3 => {
61
+ let {
62
+ nativeEvent: {
63
+ layout: {
64
+ width,
65
+ height
66
+ }
67
+ }
68
+ } = _ref3;
69
+ onItemLayout?.(width, height);
70
+ }, [onItemLayout]);
71
+ const selectedProps = selectProps({
72
+ ...rest,
73
+ ...(0, _semantics.getA11yPropsFromHtmlTag)(tag, rest.accessibilityRole)
74
+ });
75
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
76
+ ref: ref,
77
+ style: selectContainerStyle({
78
+ itemWidth,
79
+ itemHeight
80
+ }),
81
+ onLayout: handleLayout,
82
+ dataSet: {
83
+ [DATA_SCROLL_ITEM]: true
84
+ },
85
+ ...(_Platform.default.OS === 'web' ? {
86
+ tabIndex: TAB_INDEX
87
+ } : {
88
+ focusable: true
89
+ }),
90
+ ...selectedProps,
91
+ children: children
92
+ });
93
+ });
94
+ ScrollItem.displayName = 'ScrollItem';
95
+ ScrollItem.propTypes = {
96
+ ...selectedSystemPropTypes,
97
+ /**
98
+ * Content of the scroll item
99
+ */
100
+ children: _propTypes.default.oneOfType([_propTypes.default.arrayOf(_propTypes.default.node), _propTypes.default.node]).isRequired,
101
+ /**
102
+ * Sets the HTML tag of the outer container. Defaults to `'li'`.
103
+ */
104
+ tag: _propTypes.default.oneOf(_semantics.layoutTags)
105
+ };
106
+ const MemoizedScrollItem = exports.ScrollItem = /*#__PURE__*/_react.default.memo(ScrollItem);
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.ScrollProgress = void 0;
7
+ var _react = _interopRequireDefault(require("react"));
8
+ var _propTypes = _interopRequireDefault(require("prop-types"));
9
+ var _View = _interopRequireDefault(require("react-native-web/dist/cjs/exports/View"));
10
+ var _pressability = require("../utils/pressability");
11
+ var _useAnimatedValue = require("../utils/animation/useAnimatedValue");
12
+ var _Progress = require("../Progress/Progress");
13
+ var _ProgressBar = require("../Progress/ProgressBar");
14
+ var _jsxRuntime = require("react/jsx-runtime");
15
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
16
+ const MAX_PERCENTAGE = 100;
17
+ const BORDER_RADIUS_DIVISOR = 2;
18
+ const staticProgressTokens = {
19
+ borderWidth: 0,
20
+ borderColor: 'transparent'
21
+ };
22
+ const staticProgressBarTokens = {
23
+ gradient: null,
24
+ outlineWidth: 0
25
+ };
26
+ const selectProgressTokens = _ref => {
27
+ let {
28
+ progressTrackHeight,
29
+ progressBarHeight,
30
+ progressTrackColor
31
+ } = _ref;
32
+ return {
33
+ height: progressTrackHeight,
34
+ barHeight: progressBarHeight,
35
+ backgroundColor: progressTrackColor,
36
+ borderRadius: progressTrackHeight / BORDER_RADIUS_DIVISOR
37
+ };
38
+ };
39
+ const selectBarTokens = _ref2 => {
40
+ let {
41
+ progressBarColor,
42
+ progressBarHeight
43
+ } = _ref2;
44
+ return {
45
+ backgroundColor: progressBarColor,
46
+ borderRadius: progressBarHeight / BORDER_RADIUS_DIVISOR
47
+ };
48
+ };
49
+ const ScrollProgress = exports.ScrollProgress = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
50
+ let {
51
+ pressableState,
52
+ getTokens,
53
+ thumbWrapperStyle,
54
+ getCopy
55
+ } = _ref3;
56
+ const state = (0, _pressability.resolvePressableState)(pressableState);
57
+ const themeTokens = getTokens(state);
58
+ const animatedBarHeight = (0, _useAnimatedValue.useAnimatedValue)(themeTokens.progressBarHeight);
59
+ const animatedTokens = {
60
+ ...themeTokens,
61
+ progressBarHeight: animatedBarHeight
62
+ };
63
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Progress.Progress, {
64
+ tokens: {
65
+ ...staticProgressTokens,
66
+ ...selectProgressTokens(animatedTokens)
67
+ },
68
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
69
+ ref: ref,
70
+ style: thumbWrapperStyle,
71
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_ProgressBar.ProgressBar, {
72
+ percentage: MAX_PERCENTAGE,
73
+ tokens: {
74
+ ...staticProgressBarTokens,
75
+ ...selectBarTokens(animatedTokens)
76
+ },
77
+ accessibilityLabel: getCopy('progressBarLabel')
78
+ })
79
+ })
80
+ });
81
+ });
82
+ ScrollProgress.displayName = 'ScrollProgress';
83
+ ScrollProgress.propTypes = {
84
+ /**
85
+ * State object from Pressable's render callback containing hovered, pressed, and focused states
86
+ */
87
+ pressableState: _propTypes.default.object.isRequired,
88
+ /**
89
+ * Theme token resolver callback from useThemeTokensCallback that accepts appearance state
90
+ */
91
+ getTokens: _propTypes.default.func.isRequired,
92
+ /**
93
+ * Style array for the thumb wrapper containing static and dynamic position styles
94
+ */
95
+ thumbWrapperStyle: _propTypes.default.oneOfType([_propTypes.default.object, _propTypes.default.array]).isRequired,
96
+ /**
97
+ * Copy resolver function from useCopy for retrieving localized strings
98
+ */
99
+ getCopy: _propTypes.default.func.isRequired
100
+ };
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.dictionary = void 0;
7
+ const dictionary = exports.dictionary = {
8
+ en: {
9
+ accessibilityLabel: 'Scrollable content',
10
+ instructionText: 'Use Tab, arrow keys, or space bar to navigate',
11
+ progressBarLabel: 'Scroll position'
12
+ },
13
+ fr: {
14
+ accessibilityLabel: 'Contenu défilable',
15
+ instructionText: "Utilisez Tab, les touches fléchées ou la barre d'espace pour naviguer",
16
+ progressBarLabel: 'Position de défilement'
17
+ }
18
+ };
package/lib/cjs/index.js CHANGED
@@ -471,6 +471,18 @@ Object.defineProperty(exports, "Responsive", {
471
471
  return _Responsive.Responsive;
472
472
  }
473
473
  });
474
+ Object.defineProperty(exports, "Scroll", {
475
+ enumerable: true,
476
+ get: function () {
477
+ return _Scroll.Scroll;
478
+ }
479
+ });
480
+ Object.defineProperty(exports, "ScrollItem", {
481
+ enumerable: true,
482
+ get: function () {
483
+ return _ScrollItem.ScrollItem;
484
+ }
485
+ });
474
486
  Object.defineProperty(exports, "Search", {
475
487
  enumerable: true,
476
488
  get: function () {
@@ -1272,6 +1284,8 @@ var _RadioGroup = require("./Radio/RadioGroup");
1272
1284
  var _RadioCard = require("./RadioCard/RadioCard");
1273
1285
  var _RadioCardGroup = require("./RadioCard/RadioCardGroup");
1274
1286
  var _Responsive = require("./Responsive/Responsive");
1287
+ var _Scroll = require("./Scroll/Scroll");
1288
+ var _ScrollItem = require("./Scroll/ScrollItem");
1275
1289
  var _Search = require("./Search/Search");
1276
1290
  var _Select = require("./Select/Select");
1277
1291
  var _SelectItem = require("./Select/SelectItem");
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.useAnimatedValue = void 0;
7
+ var _react = _interopRequireDefault(require("react"));
8
+ var _Animated = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Animated"));
9
+ var _Easing = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Easing"));
10
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
+ const ANIMATION_DURATION = 200;
12
+
13
+ /**
14
+ * Smoothly animates a numeric value to a new target using a quadratic ease-in-out
15
+ * curve. Returns the current interpolated value as a plain number so
16
+ * consumers can use it in non-Animated style props.
17
+ *
18
+ * @param {number} targetValue - The value to animate towards.
19
+ * @param {number} [duration=ANIMATION_DURATION] - Animation duration in ms.
20
+ */
21
+ const useAnimatedValue = function (targetValue) {
22
+ let duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ANIMATION_DURATION;
23
+ const [currentValue, setCurrentValue] = _react.default.useState(targetValue);
24
+ const animatedValue = _react.default.useRef(new _Animated.default.Value(targetValue)).current;
25
+ _react.default.useEffect(() => {
26
+ const id = animatedValue.addListener(_ref => {
27
+ let {
28
+ value
29
+ } = _ref;
30
+ return setCurrentValue(value);
31
+ });
32
+ return () => animatedValue.removeListener(id);
33
+ }, [animatedValue]);
34
+ _react.default.useEffect(() => {
35
+ const animation = _Animated.default.timing(animatedValue, {
36
+ toValue: targetValue,
37
+ duration,
38
+ easing: _Easing.default.inOut(_Easing.default.quad),
39
+ useNativeDriver: false
40
+ });
41
+ animation.start();
42
+ return () => animation.stop();
43
+ }, [targetValue, animatedValue, duration]);
44
+ return currentValue;
45
+ };
46
+ exports.useAnimatedValue = useAnimatedValue;
@@ -54,7 +54,8 @@ const unpackFragment = child => {
54
54
  exports.unpackFragment = unpackFragment;
55
55
  const isStringOrNumber = child => typeof child === 'string' || typeof child === 'number';
56
56
  // Wrap an A11yText with neighouring text strings so it doesn't split them into multiple <Text>s
57
- const isWrapable = child => isStringOrNumber(child) || child.type === _A11yText.A11yText || child.type?.name === 'FootnoteLink';
57
+ // Check displayName first as it is explicitly set and reliable regardless of export style (named vs default)
58
+ const isWrapable = child => isStringOrNumber(child) || child.type === _A11yText.A11yText || child.type?.__UDS_COMPONENT_NAME__ === 'FootnoteLink';
58
59
  const combineKeys = childrenArray => childrenArray.reduce((newKey, child) => `${newKey}${child.key || ''}`, '');
59
60
 
60
61
  // Group wrappable children for one `<Text>` parent, merging adjacent text nodes
@@ -15,28 +15,28 @@ import { applyTextStyles } from '../ThemeProvider/utils/styles';
15
15
  import { useThemeTokens } from '../ThemeProvider/useThemeTokens';
16
16
  import { jsx as _jsx } from "react/jsx-runtime";
17
17
  const [selectProps, selectedSystemPropTypes] = selectSystemProps([htmlAttrs, viewProps]);
18
-
19
- // The top property varies between devices due to how devices render the viewport.
18
+ const HALF_FONT_SIZE = 2;
19
+ const QUARTER_FONT_SIZE = 4;
20
+ const DEFAULT_LINE_HEIGHT = 1;
21
+ const LINE_HEIGHT_MULTIPLIER = 2;
20
22
  const selectTextStyle = _ref => {
21
23
  let {
22
24
  fontSize,
23
25
  lineHeight
24
26
  } = _ref;
25
- return {
26
- fontSize,
27
- lineHeight: lineHeight !== 1 ? lineHeight : fontSize * 2,
28
- ...Platform.select({
29
- ios: {
30
- top: -fontSize / 2
31
- },
32
- android: {
33
- top: fontSize / 4
34
- },
35
- web: {
36
- top: -fontSize / 2.8
37
- }
38
- })
39
- };
27
+ return Platform.select({
28
+ native: {
29
+ fontSize: fontSize / HALF_FONT_SIZE,
30
+ lineHeight: fontSize,
31
+ position: 'relative',
32
+ top: -(fontSize * lineHeight) / HALF_FONT_SIZE
33
+ },
34
+ web: {
35
+ fontSize,
36
+ lineHeight: lineHeight !== DEFAULT_LINE_HEIGHT ? lineHeight : fontSize * LINE_HEIGHT_MULTIPLIER,
37
+ top: -fontSize / QUARTER_FONT_SIZE
38
+ }
39
+ });
40
40
  };
41
41
  export const FootnoteLink = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
42
42
  let {
@@ -80,6 +80,7 @@ export const FootnoteLink = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
80
80
  });
81
81
  });
82
82
  FootnoteLink.displayName = 'FootnoteLink';
83
+ FootnoteLink.__UDS_COMPONENT_NAME__ = 'FootnoteLink';
83
84
  const copyShape = PropTypes.shape({
84
85
  a11yLabel: PropTypes.string.isRequired
85
86
  });
@@ -12,6 +12,8 @@ import { viewProps } from '../utils/props/viewProps';
12
12
  import { ProgressContext } from './ProgressContext';
13
13
  import { jsx as _jsx } from "react/jsx-runtime";
14
14
  const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
15
+ const BORDER_SIDES = 2;
16
+ const CENTER_DIVISOR = 2;
15
17
  const selectProgressStyles = _ref => {
16
18
  let {
17
19
  backgroundColor,
@@ -30,6 +32,21 @@ const selectProgressStyles = _ref => {
30
32
  ...applyShadowToken(shadow)
31
33
  };
32
34
  };
35
+ const selectBarWrapperStyles = _ref2 => {
36
+ let {
37
+ barHeight,
38
+ borderRadius,
39
+ borderWidth,
40
+ height
41
+ } = _ref2;
42
+ return {
43
+ height: barHeight,
44
+ width: '100%',
45
+ position: 'absolute',
46
+ top: (height - borderWidth * BORDER_SIDES - barHeight) / CENTER_DIVISOR,
47
+ borderRadius
48
+ };
49
+ };
33
50
 
34
51
  /**
35
52
  * The `Progress` is a container for displaying one or several `ProgressBar`s.
@@ -43,10 +60,11 @@ const selectProgressStyles = _ref => {
43
60
  *
44
61
  * - Use the following tokens to customize the appearance:
45
62
  * - `backgroundColor` for the background color of the progress container,
63
+ * - `barHeight` to control the height of the progress bars displayed within the container,
46
64
  * - `borderColor` to control the color of the border,
47
65
  * - `borderRadius` for the rounded corners,
48
66
  * - `borderWidth` to change the border width.
49
- * - `height` to control the height of the progress bars displayed within the progress bar container.
67
+ * - `height` to control the height of the progress bar container.
50
68
  * - `shadow` to apply a box shadow to the progress bar container.
51
69
  *
52
70
  * ## Variants
@@ -67,16 +85,23 @@ const selectProgressStyles = _ref => {
67
85
  * role.
68
86
  *
69
87
  */
70
- export const Progress = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
88
+ export const Progress = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
71
89
  let {
72
90
  children,
73
91
  tokens,
74
92
  variant,
75
93
  ...rest
76
- } = _ref2;
94
+ } = _ref3;
77
95
  const themeTokens = useThemeTokens('Progress', tokens, variant);
78
- // Default to false (vertical layout) to preserve existing behavior and avoid breaking changes
79
96
  const layers = variant?.layers ?? false;
97
+ const {
98
+ barHeight,
99
+ height
100
+ } = themeTokens;
101
+ const content = barHeight && barHeight !== height ? /*#__PURE__*/_jsx(View, {
102
+ style: selectBarWrapperStyles(themeTokens),
103
+ children: children
104
+ }) : children;
80
105
  return /*#__PURE__*/_jsx(ProgressContext.Provider, {
81
106
  value: {
82
107
  layers
@@ -85,7 +110,7 @@ export const Progress = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
85
110
  ref: ref,
86
111
  style: [staticStyles.progressContainer, selectProgressStyles(themeTokens)],
87
112
  ...selectProps(rest),
88
- children: children
113
+ children: content
89
114
  })
90
115
  });
91
116
  });