@spaced-out/ui-design-system 0.1.41 → 0.1.43

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.
@@ -2,6 +2,7 @@ amet
2
2
  Anant
3
3
  argstable
4
4
  atleast
5
+ ashwini-sensehq
5
6
  autodocs
6
7
  circlehollow
7
8
  CODEOWNERS
@@ -0,0 +1,54 @@
1
+ # Author: Anant Raj
2
+ # Note: Do not change
3
+
4
+ # Simple workflow for deploying static content to GitHub Pages
5
+ name: Stage - Publish Genesis Design System Storybook to Github Pages
6
+
7
+ on:
8
+ # Allows you to run this workflow manually from the Actions tab
9
+ workflow_dispatch:
10
+
11
+ # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
12
+ permissions:
13
+ contents: read
14
+ pages: write
15
+ id-token: write
16
+
17
+ # Allow one concurrent deployment
18
+ concurrency:
19
+ group: 'pages'
20
+ cancel-in-progress: true
21
+
22
+ jobs:
23
+ # Single deploy job since we're just deploying
24
+ deploy:
25
+ environment:
26
+ name: github-pages
27
+ url: ${{ steps.deployment.outputs.page_url }}/stage
28
+ runs-on: ubuntu-latest
29
+ steps:
30
+ - name: Checkout
31
+ uses: actions/checkout@v3
32
+ - uses: actions/setup-node@v3
33
+ with:
34
+ node-version: 16
35
+ - name: Install and Build 🔧
36
+ # Install npm packages and build the Storybook files
37
+ run: |
38
+ echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
39
+ yarn
40
+ yarn storybook:export
41
+ - name: List files in the repository after build
42
+ run: |
43
+ ls ${{ github.workspace }}
44
+ echo "🍏 This job's status is ${{ job.status }}."
45
+ - name: Setup Pages
46
+ uses: actions/configure-pages@v2
47
+ - name: Upload artifact
48
+ uses: actions/upload-pages-artifact@v1
49
+ with:
50
+ # Upload storybook-static folder's content
51
+ path: './storybook-static/'
52
+ - name: Deploy to GitHub Pages
53
+ id: deployment
54
+ uses: actions/deploy-pages@v1
@@ -22,7 +22,7 @@ jobs:
22
22
  - name: Check Permissions
23
23
  id: check-permissions
24
24
  env:
25
- ALLOWED_USERS: superrover, Anant-Raj, nsfmc
25
+ ALLOWED_USERS: superrover, Anant-Raj, nsfmc, ashwini-sensehq
26
26
  if: ${{ !contains(env.ALLOWED_USERS, github.actor) }}
27
27
  run: |
28
28
  echo "You don't have correct permissions to do this release"
package/CHANGELOG.md CHANGED
@@ -2,6 +2,23 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [0.1.43](https://github.com/spaced-out/ui-design-system/compare/v0.1.42...v0.1.43) (2023-08-17)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * add actions for stage environment ([#137](https://github.com/spaced-out/ui-design-system/issues/137)) ([87b1d4e](https://github.com/spaced-out/ui-design-system/commit/87b1d4e0136f35b09d8fd704740d07112568cd8d))
11
+ * add list reference support to focus manager with arrow key navigation ([#132](https://github.com/spaced-out/ui-design-system/issues/132)) ([4b13735](https://github.com/spaced-out/ui-design-system/commit/4b13735345b3fd998a256f5f815b54223f6b705e))
12
+ * ButtonDropdown menu clipping issue ([#135](https://github.com/spaced-out/ui-design-system/issues/135)) ([0b86e21](https://github.com/spaced-out/ui-design-system/commit/0b86e2183e61b5d6b908617f3f5a269bc9aae51f))
13
+ * highlight text fixes ([#134](https://github.com/spaced-out/ui-design-system/issues/134)) ([831c96f](https://github.com/spaced-out/ui-design-system/commit/831c96fac9036af667e5fb1fd83ff063d01e9434))
14
+
15
+ ### [0.1.42](https://github.com/spaced-out/ui-design-system/compare/v0.1.41...v0.1.42) (2023-08-04)
16
+
17
+
18
+ ### Features
19
+
20
+ * panel background interactivity and background for panel body ([#131](https://github.com/spaced-out/ui-design-system/issues/131)) ([223e692](https://github.com/spaced-out/ui-design-system/commit/223e6928d977cb326ac973fe9103415eeb86300a))
21
+
5
22
  ### [0.1.41](https://github.com/spaced-out/ui-design-system/compare/v0.1.40...v0.1.41) (2023-08-02)
6
23
 
7
24
 
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.ButtonDropdown = exports.ANCHOR_POSITION_TYPE = void 0;
6
+ exports.STRATEGY_TYPE = exports.ButtonDropdown = exports.ANCHOR_POSITION_TYPE = void 0;
7
7
  var React = _interopRequireWildcard(require("react"));
8
8
  var _react2 = require("@floating-ui/react");
9
9
  var _size = require("../../styles/variables/_size");
@@ -28,9 +28,15 @@ const ANCHOR_POSITION_TYPE = Object.freeze({
28
28
  bottomEnd: 'bottom-end'
29
29
  });
30
30
  exports.ANCHOR_POSITION_TYPE = ANCHOR_POSITION_TYPE;
31
+ const STRATEGY_TYPE = Object.freeze({
32
+ absolute: 'absolute',
33
+ fixed: 'fixed'
34
+ });
35
+ exports.STRATEGY_TYPE = STRATEGY_TYPE;
31
36
  const ButtonDropdown = /*#__PURE__*/React.forwardRef((_ref, forwardRef) => {
32
37
  let {
33
38
  anchorPosition = 'bottom-start',
39
+ positionStrategy = STRATEGY_TYPE.absolute,
34
40
  size = 'medium',
35
41
  onOptionSelect,
36
42
  menu,
@@ -56,7 +62,7 @@ const ButtonDropdown = /*#__PURE__*/React.forwardRef((_ref, forwardRef) => {
56
62
  strategy
57
63
  } = (0, _react2.useFloating)({
58
64
  open: true,
59
- strategy: 'absolute',
65
+ strategy: positionStrategy,
60
66
  placement: anchorPosition,
61
67
  whileElementsMounted: _react2.autoUpdate,
62
68
  middleware: [(0, _react2.shift)(), (0, _react2.flip)(), (0, _react2.offset)(parseInt(_space.spaceXXSmall))]
@@ -38,7 +38,14 @@ export const ANCHOR_POSITION_TYPE = Object.freeze({
38
38
  bottomEnd: 'bottom-end',
39
39
  });
40
40
 
41
+ export const STRATEGY_TYPE = Object.freeze({
42
+ absolute: 'absolute',
43
+ fixed: 'fixed',
44
+ });
45
+
41
46
  export type AnchorType = $Values<typeof ANCHOR_POSITION_TYPE>;
47
+ export type Strategy = $Values<typeof STRATEGY_TYPE>;
48
+
42
49
  type ClassNames = $ReadOnly<{
43
50
  buttonWrapper?: string,
44
51
  dropdownContainer?: string,
@@ -49,6 +56,7 @@ export type ButtonDropdownProps = {
49
56
  ...ButtonProps,
50
57
  classNames?: ClassNames,
51
58
  menu?: MenuProps,
59
+ positionStrategy?: Strategy,
52
60
  anchorPosition?: AnchorType,
53
61
  onOptionSelect?: (option: MenuOption) => mixed,
54
62
  onMenuOpen?: () => mixed,
@@ -64,6 +72,7 @@ export const ButtonDropdown: React$AbstractComponent<
64
72
  (
65
73
  {
66
74
  anchorPosition = 'bottom-start',
75
+ positionStrategy = STRATEGY_TYPE.absolute,
67
76
  size = 'medium',
68
77
  onOptionSelect,
69
78
  menu,
@@ -86,7 +95,7 @@ export const ButtonDropdown: React$AbstractComponent<
86
95
  React.useImperativeHandle(forwardRef, () => menuBtnRef.current);
87
96
  const {x, y, refs, strategy} = useFloating({
88
97
  open: true,
89
- strategy: 'absolute',
98
+ strategy: positionStrategy,
90
99
  placement: anchorPosition,
91
100
  whileElementsMounted: autoUpdate,
92
101
  middleware: [shift(), flip(), offset(parseInt(spaceXXSmall))],
@@ -3,16 +3,14 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- Object.defineProperty(exports, "Card", {
7
- enumerable: true,
8
- get: function () {
9
- return _Card.Card;
10
- }
11
- });
12
- Object.defineProperty(exports, "ClickableCard", {
13
- enumerable: true,
14
- get: function () {
15
- return _Card.ClickableCard;
16
- }
17
- });
18
- var _Card = require("./Card");
6
+ var _Card = require("./Card");
7
+ Object.keys(_Card).forEach(function (key) {
8
+ if (key === "default" || key === "__esModule") return;
9
+ if (key in exports && exports[key] === _Card[key]) return;
10
+ Object.defineProperty(exports, key, {
11
+ enumerable: true,
12
+ get: function () {
13
+ return _Card[key];
14
+ }
15
+ });
16
+ });
@@ -1,4 +1,3 @@
1
1
  // @flow strict
2
2
 
3
- export type {CardProps} from './Card';
4
- export {Card, ClickableCard} from './Card';
3
+ export * from './Card';
@@ -37,6 +37,7 @@ const FocusManagerWithArrowKeyNavigation = props => {
37
37
  cols = 1,
38
38
  focusItemOnOpen = 'auto',
39
39
  loop = false,
40
+ listReference,
40
41
  ...restFloatingFocusManagerProps
41
42
  } = props;
42
43
  const {
@@ -61,11 +62,23 @@ const FocusManagerWithArrowKeyNavigation = props => {
61
62
  setActiveIndex(index);
62
63
  };
63
64
 
65
+ // Add childOnClickPassthrough for the list of references passed in case of custom nodes passed
66
+ if (listReference) {
67
+ listReference.current.map((element, index) => {
68
+ const childClickHandler = element.onclick;
69
+ element.onclick = function () {
70
+ for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
71
+ args[_key2] = arguments[_key2];
72
+ }
73
+ childOnClickPassthrough(childClickHandler, index, ...args);
74
+ };
75
+ });
76
+ }
64
77
  // Note(Nishant): Force the list navigation props onto the children
65
78
  // while using this component make sure your all the passed children have a focus state
66
79
 
67
80
  let skippedChildrenCount = 0;
68
- const clonedChildren = childrenArray.map((child, index) => {
81
+ const clonedChildren = listReference ? children : childrenArray.map((child, index) => {
69
82
  const {
70
83
  onClick: childClickHandler
71
84
  } = child.props;
@@ -83,8 +96,8 @@ const FocusManagerWithArrowKeyNavigation = props => {
83
96
  }
84
97
  },
85
98
  onClick: function () {
86
- for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
87
- args[_key2] = arguments[_key2];
99
+ for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
100
+ args[_key3] = arguments[_key3];
88
101
  }
89
102
  childOnClickPassthrough(childClickHandler, adjustedIndex, ...args);
90
103
  }
@@ -93,7 +106,7 @@ const FocusManagerWithArrowKeyNavigation = props => {
93
106
  const listNavigation = (0, _react2.useListNavigation)(context, {
94
107
  orientation,
95
108
  cols,
96
- listRef,
109
+ listRef: listReference ? listReference : listRef,
97
110
  activeIndex,
98
111
  onNavigate: setActiveIndex,
99
112
  focusItemOnOpen,
@@ -48,6 +48,7 @@ export type FocusManagerWithArrowKeyNavigationProps = {
48
48
  orientation?: 'horizontal' | 'vertical',
49
49
  focusItemOnOpen?: 'auto' | boolean,
50
50
  loop?: boolean,
51
+ listReference?: {current: Array<HTMLElement>},
51
52
  };
52
53
 
53
54
  export const FocusManagerWithArrowKeyNavigation = (
@@ -62,6 +63,7 @@ export const FocusManagerWithArrowKeyNavigation = (
62
63
  cols = 1,
63
64
  focusItemOnOpen = 'auto',
64
65
  loop = false,
66
+ listReference,
65
67
  ...restFloatingFocusManagerProps
66
68
  } = props;
67
69
 
@@ -79,39 +81,50 @@ export const FocusManagerWithArrowKeyNavigation = (
79
81
  setActiveIndex(index);
80
82
  };
81
83
 
84
+ // Add childOnClickPassthrough for the list of references passed in case of custom nodes passed
85
+ if (listReference) {
86
+ listReference.current.map((element, index) => {
87
+ const childClickHandler = element.onclick;
88
+ element.onclick = (...args) => {
89
+ childOnClickPassthrough(childClickHandler, index, ...args);
90
+ };
91
+ });
92
+ }
82
93
  // Note(Nishant): Force the list navigation props onto the children
83
94
  // while using this component make sure your all the passed children have a focus state
84
95
 
85
96
  let skippedChildrenCount = 0;
86
97
 
87
- const clonedChildren = childrenArray.map((child, index) => {
88
- const {onClick: childClickHandler} = child.props;
89
-
90
- let adjustedIndex = index - skippedChildrenCount;
91
-
92
- if (child?.type?.displayName === SKIP_ELEMENT_DISPLAY_NAME) {
93
- skippedChildrenCount++;
94
- adjustedIndex = null;
95
- }
96
-
97
- return React.cloneElement(child, {
98
- ...child.props,
99
- tabIndex: activeIndex === index ? 0 : -1,
100
- ref: (node) => {
101
- if (adjustedIndex !== null) {
102
- listRef.current[adjustedIndex] = node;
103
- }
104
- },
105
- onClick: (...args) => {
106
- childOnClickPassthrough(childClickHandler, adjustedIndex, ...args);
107
- },
98
+ const clonedChildren = listReference
99
+ ? children
100
+ : childrenArray.map((child, index) => {
101
+ const {onClick: childClickHandler} = child.props;
102
+
103
+ let adjustedIndex = index - skippedChildrenCount;
104
+
105
+ if (child?.type?.displayName === SKIP_ELEMENT_DISPLAY_NAME) {
106
+ skippedChildrenCount++;
107
+ adjustedIndex = null;
108
+ }
109
+
110
+ return React.cloneElement(child, {
111
+ ...child.props,
112
+ tabIndex: activeIndex === index ? 0 : -1,
113
+ ref: (node) => {
114
+ if (adjustedIndex !== null) {
115
+ listRef.current[adjustedIndex] = node;
116
+ }
117
+ },
118
+ onClick: (...args) => {
119
+ childOnClickPassthrough(childClickHandler, adjustedIndex, ...args);
120
+ },
121
+ });
108
122
  });
109
- });
110
123
 
111
124
  const listNavigation = useListNavigation(context, {
112
125
  orientation,
113
126
  cols,
114
- listRef,
127
+ listRef: listReference ? listReference : listRef,
115
128
  activeIndex,
116
129
  onNavigate: setActiveIndex,
117
130
  focusItemOnOpen,
@@ -121,6 +121,7 @@ const Modal = _ref4 => {
121
121
  tapOutsideToClose = true,
122
122
  initialFocus = -1,
123
123
  customAnimation,
124
+ allowBackgroundInteraction = false,
124
125
  // Size is not set to default for backward compatibility. Don't change if you don't know this.
125
126
  size
126
127
  } = _ref4;
@@ -209,7 +210,7 @@ const Modal = _ref4 => {
209
210
  [_ModalModule.default.in]: isTransitioning,
210
211
  [_ModalModule.default.open]: isOpen
211
212
  }, classNames?.container)
212
- }, /*#__PURE__*/React.createElement("div", {
213
+ }, !allowBackgroundInteraction && /*#__PURE__*/React.createElement("div", {
213
214
  className: (0, _classify.default)(_ModalModule.default.backdrop, {
214
215
  [_ModalModule.default.darkBackdrop]: !hideBackdrop
215
216
  }, classNames?.backdrop),
@@ -52,6 +52,7 @@ export type ModalProps = {
52
52
  onClose?: ?(SyntheticEvent<HTMLElement>) => mixed,
53
53
  hideBackdrop?: boolean,
54
54
  tapOutsideToClose?: boolean,
55
+ allowBackgroundInteraction?: boolean,
55
56
  initialFocus?: number,
56
57
  customAnimation?: UseTransitionStylesProps,
57
58
  };
@@ -194,6 +195,7 @@ export const Modal = ({
194
195
  tapOutsideToClose = true,
195
196
  initialFocus = -1,
196
197
  customAnimation,
198
+ allowBackgroundInteraction = false,
197
199
  // Size is not set to default for backward compatibility. Don't change if you don't know this.
198
200
  size,
199
201
  }: BaseModalProps): React.Node => {
@@ -296,16 +298,19 @@ export const Modal = ({
296
298
  classNames?.container,
297
299
  )}
298
300
  >
299
- <div
300
- className={classify(
301
- css.backdrop,
302
- {
303
- [css.darkBackdrop]: !hideBackdrop,
304
- },
305
- classNames?.backdrop,
306
- )}
307
- onClick={onBackdropClick}
308
- />
301
+ {!allowBackgroundInteraction && (
302
+ <div
303
+ className={classify(
304
+ css.backdrop,
305
+ {
306
+ [css.darkBackdrop]: !hideBackdrop,
307
+ },
308
+ classNames?.backdrop,
309
+ )}
310
+ onClick={onBackdropClick}
311
+ />
312
+ )}
313
+
309
314
  {isMounted && (
310
315
  <div
311
316
  className={classify(
@@ -86,6 +86,8 @@ const Panel = _ref4 => {
86
86
  hideBackdrop = true,
87
87
  classNames,
88
88
  customAnimation,
89
+ tapOutsideToClose = true,
90
+ allowBackgroundInteraction,
89
91
  ...restPanelProps
90
92
  } = _ref4;
91
93
  const isTransitioning = (0, _useMountTransition.default)(isOpen, parseInt(_motion.motionDurationNormal));
@@ -93,7 +95,9 @@ const Panel = _ref4 => {
93
95
  return /*#__PURE__*/React.createElement(_Modal.Modal, _extends({
94
96
  isOpen: isOpen,
95
97
  onClose: onClose,
96
- hideBackdrop: hideBackdrop
98
+ hideBackdrop: hideBackdrop,
99
+ tapOutsideToClose: allowBackgroundInteraction ? false : tapOutsideToClose,
100
+ allowBackgroundInteraction: allowBackgroundInteraction
97
101
  }, restPanelProps, {
98
102
  classNames: {
99
103
  container: (0, _classify.default)(_PanelModule.default.panelContainer, {
@@ -49,6 +49,7 @@ export type PanelBodyProps = {
49
49
 
50
50
  export type PanelProps = {
51
51
  ...ModalProps,
52
+ allowBackgroundInteraction?: boolean,
52
53
  size?: PanelSize,
53
54
  anchor?: PanelAnchor,
54
55
  };
@@ -128,6 +129,8 @@ export const Panel = ({
128
129
  hideBackdrop = true,
129
130
  classNames,
130
131
  customAnimation,
132
+ tapOutsideToClose = true,
133
+ allowBackgroundInteraction,
131
134
  ...restPanelProps
132
135
  }: PanelProps): React.Node => {
133
136
  const isTransitioning = useMountTransition(
@@ -142,6 +145,8 @@ export const Panel = ({
142
145
  isOpen={isOpen}
143
146
  onClose={onClose}
144
147
  hideBackdrop={hideBackdrop}
148
+ tapOutsideToClose={allowBackgroundInteraction ? false : tapOutsideToClose}
149
+ allowBackgroundInteraction={allowBackgroundInteraction}
145
150
  {...restPanelProps}
146
151
  classNames={{
147
152
  container: classify(
@@ -1,7 +1,7 @@
1
1
  @value (spaceNegFluid, spaceNone, spaceMedium, spaceSmall, spaceFluid) from '../../styles/variables/_space.css';
2
2
  @value (size4, size60, size480, size580, size720, sizeFluid) from '../../styles/variables/_size.css';
3
3
  @value (motionDurationNormal, motionEaseInEaseOut) from '../../styles/variables/_motion.css';
4
- @value (colorBackgroundTertiary, colorBackgroundPrimary) from '../../styles/variables/_color.css';
4
+ @value (colorBackgroundTertiary, colorBackgroundPrimary, colorBackgroundSecondary) from '../../styles/variables/_color.css';
5
5
  @value (borderRadiusNone) from '../../styles/variables/_border.css';
6
6
 
7
7
  .panel {
@@ -51,6 +51,7 @@
51
51
  justify-content: space-between;
52
52
  align-items: center;
53
53
  gap: spaceMedium;
54
+ background-color: colorBackgroundTertiary;
54
55
  }
55
56
 
56
57
  .headerContent {
@@ -61,11 +62,12 @@
61
62
  padding: spaceMedium;
62
63
  height: sizeFluid;
63
64
  overflow: auto;
65
+ background-color: colorBackgroundSecondary;
64
66
  }
65
67
 
66
68
  .panelFooter {
67
69
  composes: borderTopPrimary from '../../styles/border.module.css';
68
- background-color: colorBackgroundPrimary;
70
+ background-color: colorBackgroundTertiary;
69
71
  margin-top: auto;
70
72
  padding: spaceMedium;
71
73
  display: flex;
@@ -22,22 +22,22 @@ const HighlightText = /*#__PURE__*/React.forwardRef((_ref, ref) => {
22
22
  highlightWithBackground
23
23
  } = _ref;
24
24
  // Split text on highlight term, include term itself into parts, ignore case
25
- let highlights = '';
26
- if (Array.isArray(highlight)) {
27
- highlights = highlight.map(_string.escapeRegExp).join('|');
28
- } else {
29
- highlights = (0, _string.escapeRegExp)(highlight);
30
- }
25
+ // Convert highlight to an array if it's not already
26
+ const highlightArray = [].concat(highlight).filter(item => item !== '');
27
+ const highlights = highlightArray.map(_string.escapeRegExp).join('|');
31
28
  const parts = text.split(new RegExp(`(${highlights})`, caseSensitiveHighlighting ? '' : 'gi')).filter(part => part !== '');
32
29
  return /*#__PURE__*/React.createElement("span", {
33
30
  ref: ref
34
- }, parts.map((part, idx) => highlights.toLowerCase().includes((0, _string.escapeRegExp)(part).toLowerCase()) ? /*#__PURE__*/React.createElement("span", {
35
- // eslint-disable-next-line react/no-array-index-key
36
- key: idx,
37
- className: (0, _classify.default)(_typographyModule.default.highlightText, {
38
- [_typographyModule.default.bgHighlighting]: highlightWithBackground
39
- }, highlightClassName)
40
- }, part) : part));
31
+ }, parts.map((part, idx) => {
32
+ const isHighlighted = highlightArray.some(highlightTerm => caseSensitiveHighlighting ? (0, _string.escapeRegExp)(part).includes((0, _string.escapeRegExp)(highlightTerm)) : (0, _string.escapeRegExp)(part).toLowerCase().includes((0, _string.escapeRegExp)(highlightTerm).toLowerCase()));
33
+ return isHighlighted ? /*#__PURE__*/React.createElement("span", {
34
+ // eslint-disable-next-line react/no-array-index-key
35
+ key: idx,
36
+ className: (0, _classify.default)(_typographyModule.default.highlightText, {
37
+ [_typographyModule.default.bgHighlighting]: highlightWithBackground
38
+ }, highlightClassName)
39
+ }, part) : part;
40
+ }));
41
41
  });
42
42
  const JumboMedium = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
43
43
  let {
@@ -29,51 +29,64 @@ export type HighlightTextProps = {
29
29
  highlightWithBackground?: boolean,
30
30
  };
31
31
 
32
- const HighlightText: React$AbstractComponent<HighlightTextProps, HTMLSpanElement> =
33
- React.forwardRef<HighlightTextProps, HTMLSpanElement>( ({
34
- text,
35
- highlight,
36
- highlightClassName,
37
- caseSensitiveHighlighting,
38
- highlightWithBackground,
39
- }: HighlightTextProps, ref) => {
40
- // Split text on highlight term, include term itself into parts, ignore case
41
- let highlights = '';
42
- if (Array.isArray(highlight)) {
43
- highlights = highlight.map(escapeRegExp).join('|');
44
- } else {
45
- highlights = escapeRegExp(highlight);
46
- }
32
+ const HighlightText: React$AbstractComponent<
33
+ HighlightTextProps,
34
+ HTMLSpanElement,
35
+ > = React.forwardRef<HighlightTextProps, HTMLSpanElement>(
36
+ (
37
+ {
38
+ text,
39
+ highlight,
40
+ highlightClassName,
41
+ caseSensitiveHighlighting,
42
+ highlightWithBackground,
43
+ }: HighlightTextProps,
44
+ ref,
45
+ ) => {
46
+ // Split text on highlight term, include term itself into parts, ignore case
47
+ // Convert highlight to an array if it's not already
48
+ const highlightArray = [].concat(highlight).filter((item) => item !== '');
49
+ const highlights = highlightArray.map(escapeRegExp).join('|');
47
50
 
48
- const parts = text
49
- .split(new RegExp(`(${highlights})`, caseSensitiveHighlighting ? '' : 'gi'))
50
- .filter((part) => part !== '');
51
+ const parts = text
52
+ .split(
53
+ new RegExp(`(${highlights})`, caseSensitiveHighlighting ? '' : 'gi'),
54
+ )
55
+ .filter((part) => part !== '');
51
56
 
52
- return (
53
- <span ref={ref}>
54
- {parts.map((part, idx) =>
55
- highlights.toLowerCase().includes(escapeRegExp(part).toLowerCase()) ? (
56
- <span
57
- // eslint-disable-next-line react/no-array-index-key
58
- key={idx}
59
- className={classify(
60
- css.highlightText,
61
- {
62
- [css.bgHighlighting]: highlightWithBackground,
63
- },
64
- highlightClassName,
65
- )}
66
- >
67
- {part}
68
- </span>
69
- ) : (
70
- part
71
- ),
72
- )}
73
- </span>
74
- );
75
- }
76
- )
57
+ return (
58
+ <span ref={ref}>
59
+ {parts.map((part, idx) => {
60
+ const isHighlighted = highlightArray.some((highlightTerm) =>
61
+ caseSensitiveHighlighting
62
+ ? escapeRegExp(part).includes(escapeRegExp(highlightTerm))
63
+ : escapeRegExp(part)
64
+ .toLowerCase()
65
+ .includes(escapeRegExp(highlightTerm).toLowerCase()),
66
+ );
67
+
68
+ return isHighlighted ? (
69
+ <span
70
+ // eslint-disable-next-line react/no-array-index-key
71
+ key={idx}
72
+ className={classify(
73
+ css.highlightText,
74
+ {
75
+ [css.bgHighlighting]: highlightWithBackground,
76
+ },
77
+ highlightClassName,
78
+ )}
79
+ >
80
+ {part}
81
+ </span>
82
+ ) : (
83
+ part
84
+ );
85
+ })}
86
+ </span>
87
+ );
88
+ },
89
+ );
77
90
 
78
91
  export const JumboMedium: React$AbstractComponent<TextProps, HTMLSpanElement> =
79
92
  React.forwardRef<TextProps, HTMLSpanElement>(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spaced-out/ui-design-system",
3
- "version": "0.1.41",
3
+ "version": "0.1.43",
4
4
  "main": "index.js",
5
5
  "description": "Sense UI components library",
6
6
  "author": {