@telus-uds/components-base 1.70.0 → 1.72.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 +30 -2
- package/jest.setup.js +7 -0
- package/lib/Autocomplete/Autocomplete.js +3 -13
- package/lib/Card/Card.js +68 -7
- package/lib/Card/PressableCardBase.js +2 -0
- package/lib/ColourToggle/ColourBubble.js +135 -0
- package/lib/ColourToggle/ColourToggle.js +101 -0
- package/lib/ColourToggle/index.js +10 -0
- package/lib/FlexGrid/Col/Col.js +50 -64
- package/lib/FlexGrid/FlexGrid.js +37 -40
- package/lib/FlexGrid/Row/Row.js +43 -44
- package/lib/Icon/IconText.js +9 -2
- package/lib/Link/LinkBase.js +10 -3
- package/lib/Modal/ModalContent.js +4 -6
- package/lib/OrderedList/Item.js +180 -0
- package/lib/OrderedList/ItemBase.js +48 -0
- package/lib/OrderedList/OrderedList.js +71 -0
- package/lib/OrderedList/OrderedListBase.js +47 -0
- package/lib/OrderedList/index.js +10 -0
- package/lib/index.js +16 -0
- package/lib/utils/ssr-media-query/create-stylesheet/create-stylesheet-mobile.js +56 -0
- package/lib/utils/ssr-media-query/create-stylesheet/index.android.js +10 -0
- package/lib/utils/ssr-media-query/create-stylesheet/index.ios.js +10 -0
- package/lib/utils/ssr-media-query/create-stylesheet/index.js +44 -0
- package/lib/utils/ssr-media-query/utils/inject.js +13 -0
- package/lib-module/Autocomplete/Autocomplete.js +3 -13
- package/lib-module/Card/Card.js +71 -8
- package/lib-module/Card/PressableCardBase.js +2 -0
- package/lib-module/ColourToggle/ColourBubble.js +125 -0
- package/lib-module/ColourToggle/ColourToggle.js +92 -0
- package/lib-module/ColourToggle/index.js +2 -0
- package/lib-module/FlexGrid/Col/Col.js +51 -65
- package/lib-module/FlexGrid/FlexGrid.js +38 -41
- package/lib-module/FlexGrid/Row/Row.js +44 -45
- package/lib-module/Icon/IconText.js +9 -2
- package/lib-module/Link/LinkBase.js +10 -3
- package/lib-module/Modal/ModalContent.js +4 -6
- package/lib-module/OrderedList/Item.js +171 -0
- package/lib-module/OrderedList/ItemBase.js +37 -0
- package/lib-module/OrderedList/OrderedList.js +61 -0
- package/lib-module/OrderedList/OrderedListBase.js +36 -0
- package/lib-module/OrderedList/index.js +2 -0
- package/lib-module/index.js +2 -0
- package/lib-module/utils/ssr-media-query/create-stylesheet/create-stylesheet-mobile.js +48 -0
- package/lib-module/utils/ssr-media-query/create-stylesheet/index.android.js +2 -0
- package/lib-module/utils/ssr-media-query/create-stylesheet/index.ios.js +2 -0
- package/lib-module/utils/ssr-media-query/create-stylesheet/index.js +36 -0
- package/lib-module/utils/ssr-media-query/utils/inject.js +13 -0
- package/package.json +2 -2
- package/src/Autocomplete/Autocomplete.jsx +14 -21
- package/src/Card/Card.jsx +73 -11
- package/src/Card/PressableCardBase.jsx +2 -0
- package/src/ColourToggle/ColourBubble.jsx +111 -0
- package/src/ColourToggle/ColourToggle.jsx +83 -0
- package/src/ColourToggle/index.js +3 -0
- package/src/FlexGrid/Col/Col.jsx +48 -80
- package/src/FlexGrid/FlexGrid.jsx +36 -44
- package/src/FlexGrid/Row/Row.jsx +38 -56
- package/src/Icon/IconText.jsx +11 -1
- package/src/Link/ChevronLink.jsx +1 -0
- package/src/Link/LinkBase.jsx +16 -6
- package/src/Modal/ModalContent.jsx +4 -6
- package/src/OrderedList/Item.jsx +152 -0
- package/src/OrderedList/ItemBase.jsx +31 -0
- package/src/OrderedList/OrderedList.jsx +61 -0
- package/src/OrderedList/OrderedListBase.jsx +33 -0
- package/src/OrderedList/index.js +3 -0
- package/src/index.js +2 -0
- package/src/utils/ssr-media-query/create-stylesheet/create-stylesheet-mobile.js +41 -0
- package/src/utils/ssr-media-query/create-stylesheet/index.android.js +3 -0
- package/src/utils/ssr-media-query/create-stylesheet/index.ios.js +3 -0
- package/src/utils/ssr-media-query/create-stylesheet/index.js +33 -0
- package/src/utils/ssr-media-query/utils/inject.js +13 -0
- package/types/Badge.d.ts +28 -0
- package/types/Box.d.ts +52 -0
- package/types/ChevronLink.d.ts +47 -0
- package/types/Common.d.ts +106 -0
- package/types/Divider.d.ts +19 -0
- package/types/ExpandCollapse.d.ts +65 -0
- package/types/HorizontalScrollButton.d.ts +16 -0
- package/types/Icon.d.ts +21 -0
- package/types/Link.d.ts +48 -0
- package/types/List.d.ts +48 -0
- package/types/Search.d.ts +38 -0
- package/types/Select.d.ts +57 -0
- package/types/Spacer.d.ts +5 -0
- package/types/StackView.d.ts +28 -0
- package/types/Tabs.d.ts +46 -0
- package/types/TextButton.d.ts +11 -0
- package/types/ToggleSwitch.d.ts +54 -0
- package/types/ToolTip.d.ts +40 -0
- package/types/Typography.d.ts +39 -0
- package/types/index.d.ts +62 -0
- package/lib/utils/ssr-media-query/create-stylesheet.js +0 -76
- package/lib-module/utils/ssr-media-query/create-stylesheet.js +0 -68
- package/src/utils/ssr-media-query/create-stylesheet.js +0 -61
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import React, { forwardRef, useMemo } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import { getTokensPropType, htmlAttrs, selectSystemProps, variantProp, viewProps } from '../utils';
|
|
4
|
+
import OrderedListBase from './OrderedListBase';
|
|
5
|
+
import Item from './Item';
|
|
6
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
7
|
+
const [selectProps, selectedSystemPropsTypes] = selectSystemProps([htmlAttrs, viewProps]);
|
|
8
|
+
const getChildrenWithParentVariants = (variant, children, start) => {
|
|
9
|
+
if (variant) return children.map((child, i) => {
|
|
10
|
+
var _child$props;
|
|
11
|
+
const existingChildVariants = ((_child$props = child.props) === null || _child$props === void 0 ? void 0 : _child$props.variant) ?? {};
|
|
12
|
+
return {
|
|
13
|
+
...child,
|
|
14
|
+
props: {
|
|
15
|
+
...child.props,
|
|
16
|
+
index: start + i,
|
|
17
|
+
isLastChild: i === children.length - 1,
|
|
18
|
+
variant: {
|
|
19
|
+
...existingChildVariants,
|
|
20
|
+
...variant
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
});
|
|
25
|
+
return children;
|
|
26
|
+
};
|
|
27
|
+
const OrderedList = /*#__PURE__*/forwardRef((_ref, ref) => {
|
|
28
|
+
let {
|
|
29
|
+
children,
|
|
30
|
+
start,
|
|
31
|
+
variant,
|
|
32
|
+
...rest
|
|
33
|
+
} = _ref;
|
|
34
|
+
const childrenWithParentVariants = useMemo(() => getChildrenWithParentVariants(variant, children, start), [children, variant, start]);
|
|
35
|
+
return /*#__PURE__*/_jsx(OrderedListBase, {
|
|
36
|
+
ref: ref,
|
|
37
|
+
...selectProps(rest),
|
|
38
|
+
children: childrenWithParentVariants
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
OrderedList.propTypes = {
|
|
42
|
+
...selectedSystemPropsTypes,
|
|
43
|
+
tokens: getTokensPropType('OrderedList'),
|
|
44
|
+
/**
|
|
45
|
+
* A list of ordered items wrapped in `OrderedList.Item`.
|
|
46
|
+
*/
|
|
47
|
+
children: PropTypes.node.isRequired,
|
|
48
|
+
/**
|
|
49
|
+
* The position to start the list with.
|
|
50
|
+
*/
|
|
51
|
+
start: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
|
52
|
+
variant: variantProp.propType
|
|
53
|
+
};
|
|
54
|
+
OrderedList.defaultProps = {
|
|
55
|
+
start: 1,
|
|
56
|
+
tokens: {},
|
|
57
|
+
variant: {}
|
|
58
|
+
};
|
|
59
|
+
OrderedList.displayName = 'OrderedList';
|
|
60
|
+
OrderedList.Item = Item;
|
|
61
|
+
export default OrderedList;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/* eslint-disable react-native-a11y/has-valid-accessibility-role */
|
|
2
|
+
import React, { forwardRef } from 'react';
|
|
3
|
+
import PropTypes from 'prop-types';
|
|
4
|
+
import View from "react-native-web/dist/exports/View";
|
|
5
|
+
import StyleSheet from "react-native-web/dist/exports/StyleSheet";
|
|
6
|
+
import ItemBase from './ItemBase';
|
|
7
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
8
|
+
const OrderedListBase = /*#__PURE__*/forwardRef((_ref, ref) => {
|
|
9
|
+
let {
|
|
10
|
+
children,
|
|
11
|
+
...rest
|
|
12
|
+
} = _ref;
|
|
13
|
+
return /*#__PURE__*/_jsx(View, {
|
|
14
|
+
accessibilityRole: "list",
|
|
15
|
+
ref: ref,
|
|
16
|
+
style: staticStyles.container,
|
|
17
|
+
...rest,
|
|
18
|
+
children: children
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
OrderedListBase.propTypes = {
|
|
22
|
+
/**
|
|
23
|
+
* A list of ordered items wrapped in `OrderedListBase.Item`.
|
|
24
|
+
*/
|
|
25
|
+
children: PropTypes.node.isRequired
|
|
26
|
+
};
|
|
27
|
+
OrderedListBase.displayName = 'OrderedList';
|
|
28
|
+
OrderedListBase.Item = ItemBase;
|
|
29
|
+
export default OrderedListBase;
|
|
30
|
+
const staticStyles = StyleSheet.create({
|
|
31
|
+
container: {
|
|
32
|
+
flexDirection: 'column',
|
|
33
|
+
margin: 0,
|
|
34
|
+
padding: 0
|
|
35
|
+
}
|
|
36
|
+
});
|
package/lib-module/index.js
CHANGED
|
@@ -11,6 +11,7 @@ export { default as Checkbox } from './Checkbox';
|
|
|
11
11
|
export * from './Checkbox';
|
|
12
12
|
export { default as CheckboxCard } from './CheckboxCard';
|
|
13
13
|
export { default as CheckboxCardGroup } from './CheckboxCardGroup';
|
|
14
|
+
export { default as ColourToggle } from './ColourToggle';
|
|
14
15
|
export { default as Divider } from './Divider';
|
|
15
16
|
export { default as ExpandCollapse, Accordion } from './ExpandCollapse';
|
|
16
17
|
export { default as Feedback } from './Feedback';
|
|
@@ -28,6 +29,7 @@ export { default as List, ListItem, ListBase } from './List';
|
|
|
28
29
|
export { default as Modal } from './Modal';
|
|
29
30
|
export { default as MultiSelectFilter } from './MultiSelectFilter';
|
|
30
31
|
export { default as Notification } from './Notification';
|
|
32
|
+
export { default as OrderedList } from './OrderedList';
|
|
31
33
|
export { default as Pagination } from './Pagination';
|
|
32
34
|
export { default as Progress } from './Progress';
|
|
33
35
|
export { default as QuickLinks } from './QuickLinks';
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import mediaQuery from 'css-mediaquery';
|
|
2
|
+
import Dimensions from "react-native-web/dist/exports/Dimensions";
|
|
3
|
+
import { isMediaOrPseudo, isMedia } from '../utils/common';
|
|
4
|
+
const createStyleSheet = stylesWithQuery => {
|
|
5
|
+
if (!stylesWithQuery) return {
|
|
6
|
+
ids: {},
|
|
7
|
+
styles: {},
|
|
8
|
+
fullStyles: {}
|
|
9
|
+
};
|
|
10
|
+
let cleanStyles;
|
|
11
|
+
const ids = {};
|
|
12
|
+
Object.keys(stylesWithQuery).forEach(key => {
|
|
13
|
+
if (!(stylesWithQuery !== null && stylesWithQuery !== void 0 && stylesWithQuery[key])) return;
|
|
14
|
+
const mediaQueriesAndPseudoClasses = Object.keys(stylesWithQuery[key]).filter(isMediaOrPseudo);
|
|
15
|
+
cleanStyles = JSON.parse(JSON.stringify(stylesWithQuery));
|
|
16
|
+
mediaQueriesAndPseudoClasses.forEach(str => {
|
|
17
|
+
if (isMedia(str)) {
|
|
18
|
+
const mqStr = str.replace('@media', '');
|
|
19
|
+
const {
|
|
20
|
+
width,
|
|
21
|
+
height
|
|
22
|
+
} = Dimensions.get('window');
|
|
23
|
+
const isMatchingMediaQuery = mediaQuery.match(mqStr, {
|
|
24
|
+
width,
|
|
25
|
+
height,
|
|
26
|
+
orientation: width > height ? 'landscape' : 'portrait',
|
|
27
|
+
'aspect-ratio': width / height
|
|
28
|
+
});
|
|
29
|
+
if (isMatchingMediaQuery) {
|
|
30
|
+
cleanStyles = {
|
|
31
|
+
...cleanStyles,
|
|
32
|
+
[key]: {
|
|
33
|
+
...cleanStyles[key],
|
|
34
|
+
...stylesWithQuery[key][str]
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
delete cleanStyles[key][str];
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
return {
|
|
43
|
+
ids,
|
|
44
|
+
styles: cleanStyles,
|
|
45
|
+
fullStyles: stylesWithQuery
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
export default createStyleSheet;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { addCss } from '../utils/inject';
|
|
2
|
+
import createDeclarationBlock from '../utils/create-declaration-block';
|
|
3
|
+
import hash from '../hash';
|
|
4
|
+
import { isMediaOrPseudo, deepClone, createCssRule } from '../utils/common';
|
|
5
|
+
const createStyleSheet = stylesWithQuery => {
|
|
6
|
+
if (!stylesWithQuery) return {
|
|
7
|
+
ids: {},
|
|
8
|
+
styles: {},
|
|
9
|
+
fullStyles: {}
|
|
10
|
+
};
|
|
11
|
+
let cleanStyles;
|
|
12
|
+
let ids = {};
|
|
13
|
+
Object.keys(stylesWithQuery).forEach(key => {
|
|
14
|
+
if (!(stylesWithQuery !== null && stylesWithQuery !== void 0 && stylesWithQuery[key])) return;
|
|
15
|
+
const mediaQueriesAndPseudoClasses = Object.keys(stylesWithQuery[key]).filter(isMediaOrPseudo);
|
|
16
|
+
cleanStyles = deepClone(stylesWithQuery);
|
|
17
|
+
mediaQueriesAndPseudoClasses.forEach(query => {
|
|
18
|
+
var _ids;
|
|
19
|
+
const css = createDeclarationBlock(stylesWithQuery[key][query]);
|
|
20
|
+
const stringHash = `rnmq-${hash(`${key}${query}${css}`)}`;
|
|
21
|
+
const rule = createCssRule(query, stringHash, css);
|
|
22
|
+
addCss(`${stringHash}`, rule);
|
|
23
|
+
delete cleanStyles[key][query];
|
|
24
|
+
ids = {
|
|
25
|
+
...ids,
|
|
26
|
+
[key]: `${(_ids = ids) !== null && _ids !== void 0 && _ids[key] ? `${ids[key]} ` : ''}${stringHash}`
|
|
27
|
+
};
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
return {
|
|
31
|
+
ids,
|
|
32
|
+
styles: cleanStyles,
|
|
33
|
+
fullStyles: stylesWithQuery
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
export default createStyleSheet;
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import Platform from "react-native-web/dist/exports/Platform";
|
|
3
3
|
const rules = {};
|
|
4
|
+
let styleSheet;
|
|
5
|
+
if (typeof window !== 'undefined' && typeof document !== 'undefined') {
|
|
6
|
+
styleSheet = (() => {
|
|
7
|
+
const style = document.createElement('style');
|
|
8
|
+
style.id = 'RNMQCSS';
|
|
9
|
+
style.appendChild(document.createTextNode(''));
|
|
10
|
+
document.head.appendChild(style);
|
|
11
|
+
return style.sheet;
|
|
12
|
+
})();
|
|
13
|
+
}
|
|
4
14
|
export const hasCss = (id, text) => {
|
|
5
15
|
var _rules$id$text, _rules$id$text$includ;
|
|
6
16
|
return !!rules[id] && !!((_rules$id$text = rules[id].text) !== null && _rules$id$text !== void 0 && (_rules$id$text$includ = _rules$id$text.includes) !== null && _rules$id$text$includ !== void 0 && _rules$id$text$includ.call(_rules$id$text, text));
|
|
@@ -10,6 +20,9 @@ export const addCss = (id, text) => {
|
|
|
10
20
|
var _rules$id;
|
|
11
21
|
rules[id] = (rules === null || rules === void 0 ? void 0 : rules[id]) || {};
|
|
12
22
|
rules[id].text = (((_rules$id = rules[id]) === null || _rules$id === void 0 ? void 0 : _rules$id.text) || '') + text;
|
|
23
|
+
if (styleSheet) {
|
|
24
|
+
styleSheet.insertRule(text, Object.keys(rules).length - 1);
|
|
25
|
+
}
|
|
13
26
|
}
|
|
14
27
|
};
|
|
15
28
|
export const flush = () => {
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"@floating-ui/react-native": "^0.8.1",
|
|
12
12
|
"@gorhom/portal": "^1.0.14",
|
|
13
13
|
"@telus-uds/system-constants": "^1.3.0",
|
|
14
|
-
"@telus-uds/system-theme-tokens": "^2.
|
|
14
|
+
"@telus-uds/system-theme-tokens": "^2.48.0",
|
|
15
15
|
"airbnb-prop-types": "^2.16.0",
|
|
16
16
|
"css-mediaquery": "^0.1.2",
|
|
17
17
|
"lodash.debounce": "^4.0.8",
|
|
@@ -74,5 +74,5 @@
|
|
|
74
74
|
"standard-engine": {
|
|
75
75
|
"skip": true
|
|
76
76
|
},
|
|
77
|
-
"version": "1.
|
|
77
|
+
"version": "1.72.0"
|
|
78
78
|
}
|
|
@@ -241,31 +241,24 @@ const Autocomplete = forwardRef(
|
|
|
241
241
|
}, [nestedSelectedValue, items])
|
|
242
242
|
|
|
243
243
|
const handleClose = (event) => {
|
|
244
|
-
if (
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
} else if (
|
|
252
|
-
event.type === 'click' &&
|
|
253
|
-
openOverlayRef?.current &&
|
|
254
|
-
event.target &&
|
|
255
|
-
!openOverlayRef?.current?.contains(event.target)
|
|
244
|
+
if (
|
|
245
|
+
(event.type === 'keydown' && (event.key === 'Escape' || event.key === '27')) ||
|
|
246
|
+
(event.type === 'click' && !openOverlayRef?.current?.contains(event.target)) ||
|
|
247
|
+
(event.type === 'touchstart' &&
|
|
248
|
+
openOverlayRef?.current &&
|
|
249
|
+
event.touches[0].target &&
|
|
250
|
+
!openOverlayRef?.current?.contains(event.touches[0].target))
|
|
256
251
|
) {
|
|
257
252
|
setIsExpanded(false)
|
|
253
|
+
setNestedSelectedValue(null)
|
|
258
254
|
} else if (
|
|
259
|
-
event.type === '
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
!
|
|
255
|
+
event.type === 'keydown' &&
|
|
256
|
+
event.key === 'ArrowDown' &&
|
|
257
|
+
isExpanded &&
|
|
258
|
+
!isLoading &&
|
|
259
|
+
targetRef?.current
|
|
263
260
|
) {
|
|
264
|
-
|
|
265
|
-
} else if (Platform.OS === 'web') {
|
|
266
|
-
// needed for dropdown to be collapsed when clicking outside on web
|
|
267
|
-
setIsExpanded(false)
|
|
268
|
-
setNestedSelectedValue(null)
|
|
261
|
+
targetRef.current.focus()
|
|
269
262
|
}
|
|
270
263
|
}
|
|
271
264
|
const itemsToShow = currentValue
|
package/src/Card/Card.jsx
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import React, { forwardRef } from 'react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
|
+
import { View } from 'react-native'
|
|
3
4
|
|
|
4
|
-
import { useThemeTokens } from '../ThemeProvider'
|
|
5
|
+
import { useThemeTokens, useThemeTokensCallback } from '../ThemeProvider'
|
|
5
6
|
import { getTokensPropType, variantProp } from '../utils'
|
|
6
7
|
import { useViewport } from '../ViewportProvider'
|
|
7
8
|
import { a11yProps, selectSystemProps, viewProps } from '../utils/props'
|
|
8
9
|
import CardBase from './CardBase'
|
|
10
|
+
import PressableCardBase from './PressableCardBase'
|
|
9
11
|
|
|
10
12
|
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps])
|
|
11
13
|
|
|
@@ -57,24 +59,84 @@ const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, vie
|
|
|
57
59
|
* you automatically make inaccessible its children, which may or may not be appropriate
|
|
58
60
|
* depending on what you are trying to achieve.
|
|
59
61
|
*/
|
|
60
|
-
const Card = forwardRef(
|
|
61
|
-
|
|
62
|
-
|
|
62
|
+
const Card = forwardRef(
|
|
63
|
+
({ children, tokens, variant, dataSet, onPress, interactiveCard, ...rest }, ref) => {
|
|
64
|
+
const viewport = useViewport()
|
|
65
|
+
const themeTokens = useThemeTokens('Card', tokens, variant, { viewport })
|
|
66
|
+
const getThemeTokens = useThemeTokensCallback('Card', interactiveCard?.tokens, {
|
|
67
|
+
interactive: true,
|
|
68
|
+
...(interactiveCard?.variant || {})
|
|
69
|
+
})
|
|
70
|
+
// When interactive area is present, spacing tokens should only be applied
|
|
71
|
+
// to individual Card sections, not Card as a whole
|
|
72
|
+
const { paddingTop, paddingBottom, paddingLeft, paddingRight, ...restOfTokens } = themeTokens
|
|
63
73
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
74
|
+
return (
|
|
75
|
+
<>
|
|
76
|
+
<CardBase
|
|
77
|
+
ref={ref}
|
|
78
|
+
tokens={interactiveCard?.body ? restOfTokens : themeTokens}
|
|
79
|
+
dataSet={dataSet}
|
|
80
|
+
{...selectProps(rest)}
|
|
81
|
+
>
|
|
82
|
+
{interactiveCard?.body ? (
|
|
83
|
+
<>
|
|
84
|
+
<PressableCardBase
|
|
85
|
+
ref={ref}
|
|
86
|
+
tokens={getThemeTokens}
|
|
87
|
+
dataSet={dataSet}
|
|
88
|
+
onPress={onPress}
|
|
89
|
+
{...selectProps(rest)}
|
|
90
|
+
>
|
|
91
|
+
{interactiveCard?.body}
|
|
92
|
+
</PressableCardBase>
|
|
93
|
+
{children ? (
|
|
94
|
+
<View style={{ paddingTop, paddingBottom, paddingLeft, paddingRight }}>
|
|
95
|
+
{children}
|
|
96
|
+
</View>
|
|
97
|
+
) : null}
|
|
98
|
+
</>
|
|
99
|
+
) : (
|
|
100
|
+
children
|
|
101
|
+
)}
|
|
102
|
+
</CardBase>
|
|
103
|
+
</>
|
|
104
|
+
)
|
|
105
|
+
}
|
|
106
|
+
)
|
|
70
107
|
|
|
71
108
|
Card.displayName = 'Card'
|
|
72
109
|
|
|
73
110
|
Card.propTypes = {
|
|
74
111
|
...selectedSystemPropTypes,
|
|
112
|
+
/**
|
|
113
|
+
* Card content.
|
|
114
|
+
*/
|
|
75
115
|
children: PropTypes.node,
|
|
116
|
+
/**
|
|
117
|
+
* Card tokens.
|
|
118
|
+
*/
|
|
76
119
|
tokens: getTokensPropType('Card'),
|
|
77
|
-
|
|
120
|
+
/**
|
|
121
|
+
* Card variant.
|
|
122
|
+
*/
|
|
123
|
+
variant: variantProp.propType,
|
|
124
|
+
/**
|
|
125
|
+
* Function to call on pressing the card.
|
|
126
|
+
* Note: This is only available when `interactiveCard` prop is used.
|
|
127
|
+
*/
|
|
128
|
+
onPress: PropTypes.func,
|
|
129
|
+
/**
|
|
130
|
+
* Object to set interactive card's properties
|
|
131
|
+
* - body: The body of the interactive card, can be any renderable node
|
|
132
|
+
* - tokens: The tokens to be used for the interactive card
|
|
133
|
+
* - variant: The variant to be used for the interactive card
|
|
134
|
+
*/
|
|
135
|
+
interactiveCard: PropTypes.shape({
|
|
136
|
+
body: PropTypes.node,
|
|
137
|
+
tokens: getTokensPropType('Card'),
|
|
138
|
+
variant: variantProp.propType
|
|
139
|
+
})
|
|
78
140
|
}
|
|
79
141
|
|
|
80
142
|
export default Card
|
|
@@ -54,6 +54,7 @@ const PressableCardBase = forwardRef(
|
|
|
54
54
|
inactive,
|
|
55
55
|
href,
|
|
56
56
|
hrefAttrs,
|
|
57
|
+
dataSet,
|
|
57
58
|
accessibilityRole = href ? 'link' : undefined,
|
|
58
59
|
...rawRest
|
|
59
60
|
},
|
|
@@ -103,6 +104,7 @@ const PressableCardBase = forwardRef(
|
|
|
103
104
|
onKeyDown={handleKeyDown}
|
|
104
105
|
hrefAttrs={hrefAttrs}
|
|
105
106
|
style={getOuterBorderStyle}
|
|
107
|
+
dataSet={dataSet}
|
|
106
108
|
{...selectProps({ ...rest, accessibilityRole })}
|
|
107
109
|
>
|
|
108
110
|
{(pressableState) => (
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import React, { forwardRef, useMemo } from 'react'
|
|
2
|
+
import PropTypes from 'prop-types'
|
|
3
|
+
|
|
4
|
+
import { View, Pressable, Platform } from 'react-native'
|
|
5
|
+
import { resolvePressableTokens } from '../utils/pressability'
|
|
6
|
+
import { applyShadowToken } from '../ThemeProvider'
|
|
7
|
+
|
|
8
|
+
const selectGeneralBubbleTokens = ({
|
|
9
|
+
outerBubbleHeight,
|
|
10
|
+
outerBubbleWidth,
|
|
11
|
+
outerBubbleContentAlignItems,
|
|
12
|
+
outerBubbleJustifyContent,
|
|
13
|
+
bubbleBorderColor,
|
|
14
|
+
bubbleBorderWidth,
|
|
15
|
+
bubbleBorderRadius
|
|
16
|
+
}) => ({
|
|
17
|
+
height: outerBubbleHeight,
|
|
18
|
+
width: outerBubbleWidth,
|
|
19
|
+
justifyContent: outerBubbleContentAlignItems,
|
|
20
|
+
alignItems: outerBubbleJustifyContent,
|
|
21
|
+
borderColor: bubbleBorderColor,
|
|
22
|
+
borderWidth: bubbleBorderWidth,
|
|
23
|
+
borderRadius: bubbleBorderRadius,
|
|
24
|
+
...Platform.select({ web: { outline: 'none' } })
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
const selectInnerBubbleTokens = ({
|
|
28
|
+
innerBubbleHeight,
|
|
29
|
+
innerBubbleWidth,
|
|
30
|
+
innerBubbleBorderRadius,
|
|
31
|
+
borderColor,
|
|
32
|
+
borderWidth,
|
|
33
|
+
shadow
|
|
34
|
+
}) => ({
|
|
35
|
+
height: innerBubbleHeight,
|
|
36
|
+
width: innerBubbleWidth,
|
|
37
|
+
borderRadius: innerBubbleBorderRadius,
|
|
38
|
+
borderColor,
|
|
39
|
+
borderWidth,
|
|
40
|
+
...applyShadowToken(shadow)
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
const selectBorderBubbleTokens = ({
|
|
44
|
+
bubbleBorderColor,
|
|
45
|
+
bubbleBorderWidth,
|
|
46
|
+
bubbleBorderRadius
|
|
47
|
+
}) => ({
|
|
48
|
+
borderColor: bubbleBorderColor,
|
|
49
|
+
borderWidth: bubbleBorderWidth,
|
|
50
|
+
borderRadius: bubbleBorderRadius
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
const ColourBubble = forwardRef(
|
|
54
|
+
({ tokens = {}, id, colourHexCode, colourName, isSelected, onPress }, ref) => {
|
|
55
|
+
const defaultTokens = tokens({ selected: isSelected })
|
|
56
|
+
|
|
57
|
+
const resolveColourBubbleTokens = (pressState) => resolvePressableTokens(tokens, pressState, {})
|
|
58
|
+
|
|
59
|
+
const themeTokens = useMemo(() => tokens(), [tokens])
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<Pressable
|
|
63
|
+
style={(state) => [
|
|
64
|
+
selectGeneralBubbleTokens(resolveColourBubbleTokens(state)),
|
|
65
|
+
isSelected && selectBorderBubbleTokens(defaultTokens)
|
|
66
|
+
]}
|
|
67
|
+
onPress={onPress}
|
|
68
|
+
accessible
|
|
69
|
+
accessibilityRole="radio"
|
|
70
|
+
accessibilityLabel={colourName}
|
|
71
|
+
accessibilityState={{ checked: isSelected }}
|
|
72
|
+
ref={ref}
|
|
73
|
+
testID={id}
|
|
74
|
+
>
|
|
75
|
+
<View style={[selectInnerBubbleTokens(themeTokens), { backgroundColor: colourHexCode }]} />
|
|
76
|
+
</Pressable>
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
)
|
|
80
|
+
ColourBubble.displayName = 'ColourBubble'
|
|
81
|
+
|
|
82
|
+
ColourBubble.propTypes = {
|
|
83
|
+
/**
|
|
84
|
+
* Colour toggle tokens callback.
|
|
85
|
+
*/
|
|
86
|
+
tokens: PropTypes.func,
|
|
87
|
+
/**
|
|
88
|
+
* ID of each colour bubble
|
|
89
|
+
*/
|
|
90
|
+
id: PropTypes.string,
|
|
91
|
+
/**
|
|
92
|
+
* Hexadecimal code for the background of the colour bubble
|
|
93
|
+
*/
|
|
94
|
+
colourHexCode: PropTypes.string,
|
|
95
|
+
/**
|
|
96
|
+
* Name of the colour bubble
|
|
97
|
+
*/
|
|
98
|
+
colourName: PropTypes.string,
|
|
99
|
+
/**
|
|
100
|
+
* If the current colour bubble is selected
|
|
101
|
+
*/
|
|
102
|
+
isSelected: PropTypes.bool,
|
|
103
|
+
/**
|
|
104
|
+
* If provided, this function is called when the current selection
|
|
105
|
+
* of the color is changed of all currently `items`.
|
|
106
|
+
* Receives two parameters: item object selected and the event
|
|
107
|
+
*/
|
|
108
|
+
onPress: PropTypes.func
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export default ColourBubble
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import React, { forwardRef, useState } from 'react'
|
|
2
|
+
import { View } from 'react-native'
|
|
3
|
+
import PropTypes from 'prop-types'
|
|
4
|
+
|
|
5
|
+
import { useThemeTokensCallback } from '../ThemeProvider'
|
|
6
|
+
import { a11yProps, getTokensPropType, selectSystemProps, variantProp, viewProps } from '../utils'
|
|
7
|
+
import { StackWrap } from '../StackView'
|
|
8
|
+
import Typography from '../Typography'
|
|
9
|
+
import ColourBubble from './ColourBubble'
|
|
10
|
+
|
|
11
|
+
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps])
|
|
12
|
+
|
|
13
|
+
const ColourToggle = forwardRef(
|
|
14
|
+
({ tokens, variant, defaultColourId, items, onChange, ...rest }, ref) => {
|
|
15
|
+
const [currentColourId, setCurrentColourId] = useState(defaultColourId)
|
|
16
|
+
const getTokens = useThemeTokensCallback('ColourToggle', tokens, variant)
|
|
17
|
+
|
|
18
|
+
const { space } = getTokens()
|
|
19
|
+
const { colourName: currentColourName = '' } =
|
|
20
|
+
items.find((item) => item.id === currentColourId) || ''
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<View ref={ref} {...selectProps(rest)}>
|
|
24
|
+
<Typography>{currentColourName}</Typography>
|
|
25
|
+
<StackWrap space={space} accessibilityRole="radiogroup">
|
|
26
|
+
{items.map(({ id, colourHexCode, colourName }, index) => {
|
|
27
|
+
const colourBubbleId = id || `ColourBubble[${index}]`
|
|
28
|
+
|
|
29
|
+
const handleChangeColour = (event) => {
|
|
30
|
+
setCurrentColourId(id)
|
|
31
|
+
onChange?.(event, { id, colourHexCode, colourName })
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<ColourBubble
|
|
36
|
+
key={colourBubbleId}
|
|
37
|
+
id={colourBubbleId}
|
|
38
|
+
tokens={getTokens}
|
|
39
|
+
isSelected={id === currentColourId}
|
|
40
|
+
colourHexCode={colourHexCode}
|
|
41
|
+
colourName={colourName}
|
|
42
|
+
onPress={handleChangeColour}
|
|
43
|
+
/>
|
|
44
|
+
)
|
|
45
|
+
})}
|
|
46
|
+
</StackWrap>
|
|
47
|
+
</View>
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
)
|
|
51
|
+
ColourToggle.displayName = 'ColourToggle'
|
|
52
|
+
|
|
53
|
+
ColourToggle.propTypes = {
|
|
54
|
+
...selectedSystemPropTypes,
|
|
55
|
+
/**
|
|
56
|
+
* Optional theme token overrides for the outer ColourToggle component
|
|
57
|
+
*/
|
|
58
|
+
tokens: getTokensPropType('ColourToggle'),
|
|
59
|
+
/**
|
|
60
|
+
* Colour toggle variant.
|
|
61
|
+
*/
|
|
62
|
+
variant: variantProp.propType,
|
|
63
|
+
/**
|
|
64
|
+
* Id of the selected color when component mounts
|
|
65
|
+
*/
|
|
66
|
+
defaultColourId: PropTypes.string,
|
|
67
|
+
/**
|
|
68
|
+
* Array of objects containing specifics for each ColourBubble to be rendered in the group.
|
|
69
|
+
*/
|
|
70
|
+
items: PropTypes.arrayOf(
|
|
71
|
+
PropTypes.exact({
|
|
72
|
+
colourHexCode: PropTypes.string,
|
|
73
|
+
colourName: PropTypes.string,
|
|
74
|
+
id: PropTypes.string
|
|
75
|
+
})
|
|
76
|
+
),
|
|
77
|
+
/**
|
|
78
|
+
* If provided, this function is called when the current selection of the color is changed of all currently `items`. Receives two parameters: item object selected and the event
|
|
79
|
+
*/
|
|
80
|
+
onChange: PropTypes.func
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export default ColourToggle
|