@spaced-out/ui-design-system 0.0.12 → 0.0.14

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
@@ -2,6 +2,28 @@
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.0.14](https://github.com/spaced-out/ui-design-system/compare/v0.0.13...v0.0.14) (2023-01-17)
6
+
7
+
8
+ ### Features
9
+
10
+ * **OptionButton:** options button component ([#46](https://github.com/spaced-out/ui-design-system/issues/46)) ([7800004](https://github.com/spaced-out/ui-design-system/commit/7800004ffb4ac5e6876a91daff82a5fcd958c3d6))
11
+ * **page-title:** [GDS-117] page title wrapper with page icon, tab slot ([#44](https://github.com/spaced-out/ui-design-system/issues/44)) ([e788f77](https://github.com/spaced-out/ui-design-system/commit/e788f77a2285222961e3d55818939fefe1423831))
12
+
13
+
14
+ ### Bug Fixes
15
+
16
+ * secondary label in menu ([#47](https://github.com/spaced-out/ui-design-system/issues/47)) ([2634b3f](https://github.com/spaced-out/ui-design-system/commit/2634b3fa39b86280dae226f705f2fc62282b36d0))
17
+
18
+ ### [0.0.13](https://github.com/spaced-out/ui-design-system/compare/v0.0.12...v0.0.13) (2023-01-04)
19
+
20
+
21
+ ### Bug Fixes
22
+
23
+ * button dropdown carat standalone fix ([507e1e4](https://github.com/spaced-out/ui-design-system/commit/507e1e4dbd834dfff36e96a569211aea4d84eeb2))
24
+ * button dropdown props change ([542d6e1](https://github.com/spaced-out/ui-design-system/commit/542d6e1bb299d95c29a793e32bd384037572ae00))
25
+ * emit more events from button dropdown ([faa9bf1](https://github.com/spaced-out/ui-design-system/commit/faa9bf15ce9f7fa5a7be4e2b1c24784f4654cb9e))
26
+
5
27
  ### [0.0.12](https://github.com/spaced-out/ui-design-system/compare/v0.0.11...v0.0.12) (2022-12-28)
6
28
 
7
29
 
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.UnstyledButton = exports.Button = exports.BUTTON_TYPES = void 0;
6
+ exports.UnstyledButton = exports.Button = exports.BUTTON_TYPES = exports.BUTTON_ACTION_TYPE = void 0;
7
7
  var React = _interopRequireWildcard(require("react"));
8
8
  var _classify = require("../../utils/classify");
9
9
  var _Icon = require("../Icon");
@@ -20,6 +20,12 @@ const BUTTON_TYPES = Object.freeze({
20
20
  danger: 'danger'
21
21
  });
22
22
  exports.BUTTON_TYPES = BUTTON_TYPES;
23
+ const BUTTON_ACTION_TYPE = Object.freeze({
24
+ button: 'button',
25
+ submit: 'submit',
26
+ reset: 'reset'
27
+ });
28
+ exports.BUTTON_ACTION_TYPE = BUTTON_ACTION_TYPE;
23
29
  const ButtonTypeToIconColorMap = {
24
30
  primary: 'inversePrimary',
25
31
  secondary: 'primary',
@@ -63,10 +69,12 @@ const Button = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
63
69
  type = 'primary',
64
70
  isFluid = false,
65
71
  disabled = false,
72
+ actionType = 'submit',
66
73
  size = 'medium',
67
74
  ...props
68
75
  } = _ref2;
69
76
  return /*#__PURE__*/React.createElement(UnstyledButton, _extends({}, props, {
77
+ type: actionType,
70
78
  className: (0, _classify.classify)(_ButtonModule.default.button, {
71
79
  [_ButtonModule.default.primary]: type === 'primary',
72
80
  [_ButtonModule.default.secondary]: type === 'secondary',
@@ -11,15 +11,6 @@ import css from './Button.module.css';
11
11
 
12
12
  type ClassNames = $ReadOnly<{wrapper?: string}>;
13
13
 
14
- export type UnstyledButtonProps = {
15
- children?: React.Node,
16
- disabled?: mixed,
17
- onClick?: ?(SyntheticEvent<HTMLElement>) => mixed,
18
- className?: string,
19
- ariaLabel?: string,
20
- ...
21
- };
22
-
23
14
  export const BUTTON_TYPES = Object.freeze({
24
15
  primary: 'primary',
25
16
  secondary: 'secondary',
@@ -28,7 +19,24 @@ export const BUTTON_TYPES = Object.freeze({
28
19
  danger: 'danger',
29
20
  });
30
21
 
22
+ export const BUTTON_ACTION_TYPE = Object.freeze({
23
+ button: 'button',
24
+ submit: 'submit',
25
+ reset: 'reset',
26
+ });
27
+
31
28
  export type ButtonType = $Values<typeof BUTTON_TYPES>;
29
+ export type ButtonActionType = $Values<typeof BUTTON_ACTION_TYPE>;
30
+
31
+ export type UnstyledButtonProps = {
32
+ children?: React.Node,
33
+ disabled?: mixed,
34
+ type?: ButtonActionType,
35
+ onClick?: ?(SyntheticEvent<HTMLElement>) => mixed,
36
+ className?: string,
37
+ ariaLabel?: string,
38
+ ...
39
+ };
32
40
 
33
41
  export type ButtonProps = {
34
42
  onClick?: ?(SyntheticEvent<HTMLElement>) => mixed,
@@ -39,6 +47,7 @@ export type ButtonProps = {
39
47
  iconRightType?: IconType,
40
48
  children?: React.Node,
41
49
  type?: ButtonType,
50
+ actionType?: ButtonActionType,
42
51
  isFluid?: boolean,
43
52
  disabled?: boolean,
44
53
  size?: 'medium' | 'small',
@@ -93,6 +102,7 @@ export const Button: React$AbstractComponent<ButtonProps, HTMLButtonElement> =
93
102
  type = 'primary',
94
103
  isFluid = false,
95
104
  disabled = false,
105
+ actionType = 'submit',
96
106
  size = 'medium',
97
107
  ...props
98
108
  }: ButtonProps,
@@ -100,6 +110,7 @@ export const Button: React$AbstractComponent<ButtonProps, HTMLButtonElement> =
100
110
  ) => (
101
111
  <UnstyledButton
102
112
  {...props}
113
+ type={actionType}
103
114
  className={classify(
104
115
  css.button,
105
116
  {
@@ -3,6 +3,12 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
+ Object.defineProperty(exports, "BUTTON_ACTION_TYPE", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _Button.BUTTON_ACTION_TYPE;
10
+ }
11
+ });
6
12
  Object.defineProperty(exports, "BUTTON_TYPES", {
7
13
  enumerable: true,
8
14
  get: function () {
@@ -1,4 +1,9 @@
1
1
  // @flow strict
2
2
 
3
- export type {ButtonProps, ButtonType} from './Button';
4
- export {Button, BUTTON_TYPES, UnstyledButton} from './Button';
3
+ export type {ButtonActionType, ButtonProps, ButtonType} from './Button';
4
+ export {
5
+ Button,
6
+ BUTTON_ACTION_TYPE,
7
+ BUTTON_TYPES,
8
+ UnstyledButton,
9
+ } from './Button';
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.ButtonDropdown = void 0;
6
+ exports.ButtonDropdown = exports.ANCHOR_POSITION_TYPE = void 0;
7
7
  var React = _interopRequireWildcard(require("react"));
8
8
  var _reactDom = require("@floating-ui/react-dom");
9
9
  var _size = require("../../styles/variables/_size");
@@ -17,14 +17,29 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
17
17
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
18
18
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
19
19
  function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
20
+ const ANCHOR_POSITION_TYPE = Object.freeze({
21
+ top: 'top',
22
+ topStart: 'top-start',
23
+ topEnd: 'top-end',
24
+ bottom: 'bottom',
25
+ bottomStart: 'bottom-start',
26
+ bottomEnd: 'bottom-end'
27
+ });
28
+ exports.ANCHOR_POSITION_TYPE = ANCHOR_POSITION_TYPE;
20
29
  const ButtonDropdown = _ref => {
21
30
  let {
22
31
  anchorPosition = 'bottom-start',
23
32
  size,
24
33
  onOptionSelect,
25
- props,
34
+ menu,
26
35
  classNames,
27
- disabled
36
+ disabled,
37
+ onMenuOpen,
38
+ onMenuClose,
39
+ children,
40
+ iconRightName,
41
+ iconRightType,
42
+ ...restButtonProps
28
43
  } = _ref;
29
44
  const menuBtnRef = React.useRef();
30
45
  const {
@@ -39,7 +54,12 @@ const ButtonDropdown = _ref => {
39
54
  whileElementsMounted: _reactDom.autoUpdate,
40
55
  middleware: [(0, _reactDom.shift)(), (0, _reactDom.flip)(), (0, _reactDom.offset)(parseInt(_space.spaceXXSmall))]
41
56
  });
42
- return /*#__PURE__*/React.createElement(_clickAway.ClickAway, null, _ref2 => {
57
+ const onMenuToggle = isOpen => {
58
+ isOpen ? onMenuOpen && onMenuOpen() : onMenuClose && onMenuClose();
59
+ };
60
+ return /*#__PURE__*/React.createElement(_clickAway.ClickAway, {
61
+ onChange: onMenuToggle
62
+ }, _ref2 => {
43
63
  let {
44
64
  isOpen,
45
65
  onOpen,
@@ -48,19 +68,22 @@ const ButtonDropdown = _ref => {
48
68
  } = _ref2;
49
69
  return /*#__PURE__*/React.createElement("div", {
50
70
  "data-testid": "ButtonDropdown",
51
- className: (0, _classify.classify)(_ButtonDropdownModule.default.buttonDropdownContainer, classNames?.wrapper),
71
+ className: (0, _classify.classify)(_ButtonDropdownModule.default.buttonDropdownContainer, classNames?.dropdownContainer),
52
72
  ref: menuBtnRef
53
- }, /*#__PURE__*/React.createElement(_Button.Button, _extends({}, props?.button, {
54
- iconRightName: props?.button.children ? isOpen ? 'caret-up' : 'caret-down' : props?.button.iconRightName,
55
- iconRightType: props?.button.children ? 'solid' : props?.button.iconRightType,
73
+ }, /*#__PURE__*/React.createElement(_Button.Button, _extends({}, restButtonProps, {
74
+ iconRightName: children ? isOpen ? 'caret-up' : 'caret-down' : iconRightName ? iconRightName : isOpen ? 'caret-up' : 'caret-down',
75
+ iconRightType: children ? 'solid' : iconRightType,
56
76
  disabled: disabled,
57
77
  size: size,
58
78
  ref: reference,
59
79
  onClick: e => {
60
80
  e.stopPropagation();
61
81
  onOpen();
82
+ },
83
+ classNames: {
84
+ wrapper: classNames?.buttonWrapper
62
85
  }
63
- })), isOpen && props?.menu && /*#__PURE__*/React.createElement("div", {
86
+ }), children), isOpen && menu && /*#__PURE__*/React.createElement("div", {
64
87
  onClickCapture: cancelNext,
65
88
  ref: floating,
66
89
  style: {
@@ -70,7 +93,7 @@ const ButtonDropdown = _ref => {
70
93
  left: x ?? _space.spaceNone,
71
94
  width: _size.sizeFluid
72
95
  }
73
- }, /*#__PURE__*/React.createElement(_Menu.Menu, _extends({}, props.menu, {
96
+ }, /*#__PURE__*/React.createElement(_Menu.Menu, _extends({}, menu, {
74
97
  onSelect: option => {
75
98
  onOptionSelect && onOptionSelect(option);
76
99
  clickAway();
@@ -26,33 +26,45 @@ import {Menu} from '../Menu';
26
26
  import css from './ButtonDropdown.module.css';
27
27
 
28
28
 
29
- type ClassNames = $ReadOnly<{wrapper?: string}>;
29
+ export const ANCHOR_POSITION_TYPE = Object.freeze({
30
+ top: 'top',
31
+ topStart: 'top-start',
32
+ topEnd: 'top-end',
33
+ bottom: 'bottom',
34
+ bottomStart: 'bottom-start',
35
+ bottomEnd: 'bottom-end',
36
+ });
37
+
38
+ export type AnchorType = $Values<typeof ANCHOR_POSITION_TYPE>;
39
+ type ClassNames = $ReadOnly<{
40
+ buttonWrapper?: string,
41
+ dropdownContainer?: string,
42
+ }>;
30
43
 
31
44
  export type ButtonDropdownProps = {
32
- anchorPosition?:
33
- | 'top'
34
- | 'top-start'
35
- | 'top-end'
36
- | 'bottom'
37
- | 'bottom-start'
38
- | 'bottom-end',
39
- size?: 'medium' | 'small',
40
- props?: {
41
- button: ButtonProps,
42
- menu: MenuProps,
43
- },
44
- onOptionSelect?: (option: MenuOption) => mixed,
45
+ ...ButtonProps,
45
46
  classNames?: ClassNames,
46
- disabled?: boolean,
47
+ menu: MenuProps,
48
+ anchorPosition?: AnchorType,
49
+ onOptionSelect?: (option: MenuOption) => mixed,
50
+ onMenuOpen?: () => mixed,
51
+ onMenuClose?: () => mixed,
52
+ ...
47
53
  };
48
54
 
49
55
  export const ButtonDropdown = ({
50
56
  anchorPosition = 'bottom-start',
51
57
  size,
52
58
  onOptionSelect,
53
- props,
59
+ menu,
54
60
  classNames,
55
61
  disabled,
62
+ onMenuOpen,
63
+ onMenuClose,
64
+ children,
65
+ iconRightName,
66
+ iconRightType,
67
+ ...restButtonProps
56
68
  }: ButtonDropdownProps): React.Node => {
57
69
  const menuBtnRef = React.useRef();
58
70
  const {x, y, reference, floating, strategy} = useFloating({
@@ -62,26 +74,35 @@ export const ButtonDropdown = ({
62
74
  middleware: [shift(), flip(), offset(parseInt(spaceXXSmall))],
63
75
  });
64
76
 
77
+ const onMenuToggle = (isOpen: boolean) => {
78
+ isOpen ? onMenuOpen && onMenuOpen() : onMenuClose && onMenuClose();
79
+ };
80
+
65
81
  return (
66
- <ClickAway>
82
+ <ClickAway onChange={onMenuToggle}>
67
83
  {({isOpen, onOpen, cancelNext, clickAway}) => (
68
84
  <div
69
85
  data-testid="ButtonDropdown"
70
- className={classify(css.buttonDropdownContainer, classNames?.wrapper)}
86
+ className={classify(
87
+ css.buttonDropdownContainer,
88
+ classNames?.dropdownContainer,
89
+ )}
71
90
  ref={menuBtnRef}
72
91
  >
73
92
  <Button
74
- {...props?.button}
93
+ {...restButtonProps}
75
94
  iconRightName={
76
- props?.button.children
95
+ children
77
96
  ? isOpen
78
97
  ? 'caret-up'
79
98
  : 'caret-down'
80
- : props?.button.iconRightName
81
- }
82
- iconRightType={
83
- props?.button.children ? 'solid' : props?.button.iconRightType
99
+ : iconRightName
100
+ ? iconRightName
101
+ : isOpen
102
+ ? 'caret-up'
103
+ : 'caret-down'
84
104
  }
105
+ iconRightType={children ? 'solid' : iconRightType}
85
106
  disabled={disabled}
86
107
  size={size}
87
108
  ref={reference}
@@ -89,8 +110,11 @@ export const ButtonDropdown = ({
89
110
  e.stopPropagation();
90
111
  onOpen();
91
112
  }}
92
- />
93
- {isOpen && props?.menu && (
113
+ classNames={{wrapper: classNames?.buttonWrapper}}
114
+ >
115
+ {children}
116
+ </Button>
117
+ {isOpen && menu && (
94
118
  <div
95
119
  onClickCapture={cancelNext}
96
120
  ref={floating}
@@ -103,7 +127,7 @@ export const ButtonDropdown = ({
103
127
  }}
104
128
  >
105
129
  <Menu
106
- {...props.menu}
130
+ {...menu}
107
131
  onSelect={(option) => {
108
132
  onOptionSelect && onOptionSelect(option);
109
133
  clickAway();
@@ -1,4 +1,8 @@
1
+ @value ( sizeFluid) from '../../styles/variables/_size.css';
2
+
1
3
  .buttonDropdownContainer {
2
4
  display: flex;
3
5
  position: relative;
6
+ height: sizeFluid;
7
+ width: sizeFluid;
4
8
  }
@@ -3,6 +3,12 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
+ Object.defineProperty(exports, "ANCHOR_POSITION_TYPE", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _ButtonDropdown.ANCHOR_POSITION_TYPE;
10
+ }
11
+ });
6
12
  Object.defineProperty(exports, "ButtonDropdown", {
7
13
  enumerable: true,
8
14
  get: function () {
@@ -1,4 +1,4 @@
1
1
  // @flow strict
2
2
 
3
- export type {ButtonDropdownProps} from './ButtonDropdown';
4
- export {ButtonDropdown} from './ButtonDropdown';
3
+ export type {AnchorType, ButtonDropdownProps} from './ButtonDropdown';
4
+ export {ANCHOR_POSITION_TYPE, ButtonDropdown} from './ButtonDropdown';
@@ -27,13 +27,16 @@ const Icon = _ref => {
27
27
  size = 'medium',
28
28
  color = _typography.TEXT_COLORS.primary,
29
29
  className,
30
- onClick
30
+ onClick,
31
+ swapOpacity
31
32
  } = _ref;
32
33
  return /*#__PURE__*/React.createElement(React.Fragment, null, !!name && /*#__PURE__*/React.createElement("div", {
33
34
  className: (0, _classify.default)(_typographyModule.default.centerAlignFlex, _typographyModule.default[`${size}Icon`], _typographyModule.default[color], className),
34
35
  onClick: onClick
35
36
  }, /*#__PURE__*/React.createElement("i", {
36
- className: (0, _classify.default)(`fa-${type} fa-${name}`)
37
+ className: (0, _classify.default)(`fa-${type} fa-${name} `, {
38
+ ['fa-swap-opacity']: swapOpacity
39
+ })
37
40
  })));
38
41
  };
39
42
  exports.Icon = Icon;
@@ -12,7 +12,7 @@ import classify from '../../utils/classify';
12
12
  import typographyStyle from '../../styles/typography.module.css';
13
13
 
14
14
 
15
- export type IconType = 'regular' | 'solid';
15
+ export type IconType = 'regular' | 'solid' | 'duotone';
16
16
 
17
17
  export const ICON_SIZE = Object.freeze({
18
18
  small: 'small',
@@ -29,6 +29,7 @@ export type IconProps = {
29
29
  className?: string,
30
30
  onClick?: ?(SyntheticEvent<HTMLElement>) => mixed,
31
31
  ariaLabel?: string,
32
+ swapOpacity?: boolean,
32
33
  };
33
34
 
34
35
  export const Icon = ({
@@ -38,6 +39,7 @@ export const Icon = ({
38
39
  color = TEXT_COLORS.primary,
39
40
  className,
40
41
  onClick,
42
+ swapOpacity,
41
43
  }: IconProps): React.Node => (
42
44
  <>
43
45
  {!!name && (
@@ -50,7 +52,11 @@ export const Icon = ({
50
52
  )}
51
53
  onClick={onClick}
52
54
  >
53
- <i className={classify(`fa-${type} fa-${name}`)} />
55
+ <i
56
+ className={classify(`fa-${type} fa-${name} `, {
57
+ ['fa-swap-opacity']: swapOpacity,
58
+ })}
59
+ />
54
60
  </div>
55
61
  )}
56
62
  </>
@@ -8,6 +8,7 @@ var React = _interopRequireWildcard(require("react"));
8
8
  var _classify = require("../../utils/classify");
9
9
  var _Button = require("../Button");
10
10
  var _Icon = require("../Icon");
11
+ var _Truncate = require("../Truncate");
11
12
  var _MenuModule = _interopRequireDefault(require("./Menu.module.css"));
12
13
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
14
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
@@ -37,6 +38,7 @@ const Menu = props => {
37
38
  let {
38
39
  key,
39
40
  label,
41
+ secondaryLabel,
40
42
  iconLeft,
41
43
  iconLeftType,
42
44
  iconRight,
@@ -64,9 +66,13 @@ const Menu = props => {
64
66
  type: iconLeftType,
65
67
  size: "small",
66
68
  className: _MenuModule.default.icon
67
- }), /*#__PURE__*/React.createElement("span", {
68
- className: _MenuModule.default.optionText
69
- }, label), !!iconRight && /*#__PURE__*/React.createElement(_Icon.Icon, {
69
+ }), /*#__PURE__*/React.createElement("div", {
70
+ className: _MenuModule.default.optionTextContainer
71
+ }, /*#__PURE__*/React.createElement("div", {
72
+ className: _MenuModule.default.optionTextLabel
73
+ }, /*#__PURE__*/React.createElement(_Truncate.Truncate, null, label)), !!secondaryLabel && /*#__PURE__*/React.createElement("div", {
74
+ className: _MenuModule.default.optionTextSecondaryLabel
75
+ }, /*#__PURE__*/React.createElement(_Truncate.Truncate, null, secondaryLabel))), !!iconRight && /*#__PURE__*/React.createElement(_Icon.Icon, {
70
76
  name: iconRight,
71
77
  type: iconRightType,
72
78
  size: "small",
@@ -5,6 +5,7 @@ import {classify} from '../../utils/classify';
5
5
  import {UnstyledButton} from '../Button';
6
6
  import {Icon} from '../Icon';
7
7
  import type {IconType} from '../Icon/Icon.js';
8
+ import {Truncate} from '../Truncate';
8
9
 
9
10
  import css from './Menu.module.css';
10
11
 
@@ -14,6 +15,7 @@ type ClassNames = $ReadOnly<{wrapper?: string}>;
14
15
  export type MenuOption = {
15
16
  key?: string,
16
17
  label: string,
18
+ secondaryLabel?: string,
17
19
  iconLeft?: string,
18
20
  iconLeftType?: IconType,
19
21
  iconRight?: string,
@@ -57,6 +59,7 @@ export const Menu = (props: MenuProps): React.Node => {
57
59
  ({
58
60
  key,
59
61
  label,
62
+ secondaryLabel,
60
63
  iconLeft,
61
64
  iconLeftType,
62
65
  iconRight,
@@ -85,8 +88,17 @@ export const Menu = (props: MenuProps): React.Node => {
85
88
  className={css.icon}
86
89
  />
87
90
  )}
91
+ <div className={css.optionTextContainer}>
92
+ <div className={css.optionTextLabel}>
93
+ <Truncate>{label}</Truncate>
94
+ </div>
88
95
 
89
- <span className={css.optionText}>{label}</span>
96
+ {!!secondaryLabel && (
97
+ <div className={css.optionTextSecondaryLabel}>
98
+ <Truncate>{secondaryLabel}</Truncate>
99
+ </div>
100
+ )}
101
+ </div>
90
102
 
91
103
  {!!iconRight && (
92
104
  <Icon
@@ -10,6 +10,7 @@
10
10
  colorTextDisabled,
11
11
  colorTextPrimary,
12
12
  colorTextSecondary,
13
+ colorTextTertiary,
13
14
  colorBackgroundTertiary
14
15
  ) from '../../styles/variables/_color.css';
15
16
 
@@ -31,7 +32,8 @@
31
32
  @value (
32
33
  spaceNone,
33
34
  spaceSmall,
34
- spaceXSmall
35
+ spaceXSmall,
36
+ spaceXXSmall
35
37
  ) from '../../styles/variables/_space.css';
36
38
 
37
39
  .menuCard {
@@ -69,15 +71,24 @@
69
71
  width: sizeFluid;
70
72
  display: flex;
71
73
  border-radius: borderRadiusSmall;
72
- padding: spaceNone spaceSmall;
73
74
  align-items: center;
74
75
  cursor: pointer;
75
76
  column-gap: spaceSmall;
76
77
  color: colorTextSecondary;
77
78
  }
78
79
 
79
- .optionText {
80
- composes: truncate from '../../styles/typography.module.css';
80
+ .optionTextContainer {
81
+ display: flex;
82
+ flex-flow: column;
83
+ gap: spaceXXSmall;
84
+ }
85
+
86
+ .optionTextLabel,
87
+ .optionTextSecondaryLabel {
88
+ display: flex;
89
+ flex-flow: column;
90
+ align-items: flex-start;
91
+ text-align: left;
81
92
  }
82
93
 
83
94
  .withIconLeft {
@@ -98,12 +109,17 @@
98
109
 
99
110
  .optionSmall {
100
111
  composes: buttonTextSmall from '../../styles/typography.module.css';
101
- height: size34;
112
+ padding: spaceXSmall spaceSmall;
102
113
  }
103
114
 
104
115
  .optionMedium {
105
116
  composes: buttonTextMedium from '../../styles/typography.module.css';
106
- height: size42;
117
+ padding: spaceSmall spaceSmall;
118
+ }
119
+
120
+ .optionTextSecondaryLabel {
121
+ composes: bodySmall from '../../styles/typography.module.css';
122
+ color: colorTextTertiary;
107
123
  }
108
124
 
109
125
  .option:hover,
@@ -112,13 +128,29 @@
112
128
  color: colorTextPrimary;
113
129
  }
114
130
 
131
+ .option:hover .optionTextSecondaryLabel {
132
+ color: colorTextSecondary;
133
+ }
134
+
135
+ .option:active .optionTextSecondaryLabel {
136
+ color: colorTextSecondary;
137
+ }
138
+
115
139
  .option:focus {
116
140
  background: colorFillSecondary;
117
141
  outline: none;
118
142
  color: colorTextPrimary;
119
143
  }
120
144
 
145
+ .option:focus .optionTextSecondaryLabel {
146
+ color: colorTextSecondary;
147
+ }
148
+
121
149
  .disabled {
122
150
  color: colorTextDisabled;
123
151
  pointer-events: none;
124
152
  }
153
+
154
+ .disabled .optionTextSecondaryLabel {
155
+ color: colorTextDisabled;
156
+ }
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.OptionButton = void 0;
7
+ var React = _interopRequireWildcard(require("react"));
8
+ var _Button = require("../Button");
9
+ var _ButtonDropdown = require("../ButtonDropdown");
10
+ var _OptionButtonModule = _interopRequireDefault(require("./OptionButton.module.css"));
11
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
13
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
14
+
15
+ const OptionButton = _ref => {
16
+ let {
17
+ children,
18
+ iconLeftName,
19
+ iconLeftType,
20
+ type,
21
+ isFluid,
22
+ disabled,
23
+ size,
24
+ menu,
25
+ anchorPosition,
26
+ onOptionSelect,
27
+ onButtonClick,
28
+ onMenuOpen,
29
+ onMenuClose,
30
+ ariaLabel
31
+ } = _ref;
32
+ const [iconName, setIconName] = React.useState('chevron-down');
33
+ return /*#__PURE__*/React.createElement("div", {
34
+ className: _OptionButtonModule.default.container
35
+ }, /*#__PURE__*/React.createElement(_Button.Button, {
36
+ iconLeftName: iconLeftName,
37
+ iconLeftType: iconLeftType,
38
+ onClick: onButtonClick,
39
+ size: size,
40
+ type: type,
41
+ classNames: {
42
+ wrapper: _OptionButtonModule.default.leftButton
43
+ },
44
+ disabled: disabled,
45
+ isFluid: isFluid,
46
+ ariaLabel: ariaLabel
47
+ }, children), /*#__PURE__*/React.createElement(_ButtonDropdown.ButtonDropdown, {
48
+ anchorPosition: anchorPosition,
49
+ ariaLabel: ariaLabel,
50
+ iconRightName: iconName,
51
+ classNames: {
52
+ buttonWrapper: _OptionButtonModule.default.rightButton,
53
+ dropdownContainer: _OptionButtonModule.default.dropDownContainer
54
+ },
55
+ type: type,
56
+ disabled: disabled,
57
+ menu: menu,
58
+ onMenuClose: () => {
59
+ setIconName('chevron-down');
60
+ onMenuOpen && onMenuOpen();
61
+ },
62
+ onMenuOpen: () => {
63
+ setIconName('chevron-up');
64
+ onMenuClose && onMenuClose();
65
+ },
66
+ onOptionSelect: onOptionSelect,
67
+ size: size
68
+ }));
69
+ };
70
+ exports.OptionButton = OptionButton;
@@ -0,0 +1,82 @@
1
+ // @flow strict
2
+
3
+ import * as React from 'react';
4
+
5
+ import type {ButtonProps} from '../Button';
6
+ import {Button} from '../Button';
7
+ import type {AnchorType} from '../ButtonDropdown';
8
+ import {ButtonDropdown} from '../ButtonDropdown';
9
+ import type {MenuOption, MenuProps} from '../Menu';
10
+
11
+ import css from './OptionButton.module.css';
12
+
13
+
14
+ export type OptionButtonProps = {
15
+ ...ButtonProps,
16
+ menu: MenuProps,
17
+ anchorPosition?: AnchorType,
18
+ onOptionSelect?: (option: MenuOption) => mixed,
19
+ onButtonClick?: ?(SyntheticEvent<HTMLElement>) => mixed,
20
+ onMenuOpen?: () => mixed,
21
+ onMenuClose?: () => mixed,
22
+ ...
23
+ };
24
+
25
+ export const OptionButton = ({
26
+ children,
27
+ iconLeftName,
28
+ iconLeftType,
29
+ type,
30
+ isFluid,
31
+ disabled,
32
+ size,
33
+ menu,
34
+ anchorPosition,
35
+ onOptionSelect,
36
+ onButtonClick,
37
+ onMenuOpen,
38
+ onMenuClose,
39
+ ariaLabel,
40
+ }: OptionButtonProps): React.Node => {
41
+ const [iconName, setIconName] = React.useState('chevron-down');
42
+
43
+ return (
44
+ <div className={css.container}>
45
+ <Button
46
+ iconLeftName={iconLeftName}
47
+ iconLeftType={iconLeftType}
48
+ onClick={onButtonClick}
49
+ size={size}
50
+ type={type}
51
+ classNames={{wrapper: css.leftButton}}
52
+ disabled={disabled}
53
+ isFluid={isFluid}
54
+ ariaLabel={ariaLabel}
55
+ >
56
+ {children}
57
+ </Button>
58
+ <ButtonDropdown
59
+ anchorPosition={anchorPosition}
60
+ ariaLabel={ariaLabel}
61
+ iconRightName={iconName}
62
+ classNames={{
63
+ buttonWrapper: css.rightButton,
64
+ dropdownContainer: css.dropDownContainer,
65
+ }}
66
+ type={type}
67
+ disabled={disabled}
68
+ menu={menu}
69
+ onMenuClose={() => {
70
+ setIconName('chevron-down');
71
+ onMenuOpen && onMenuOpen();
72
+ }}
73
+ onMenuOpen={() => {
74
+ setIconName('chevron-up');
75
+ onMenuClose && onMenuClose();
76
+ }}
77
+ onOptionSelect={onOptionSelect}
78
+ size={size}
79
+ />
80
+ </div>
81
+ );
82
+ };
@@ -0,0 +1,29 @@
1
+ @value (
2
+ borderRadiusNone
3
+ ) from '../../styles/variables/_border.css';
4
+
5
+ @value (spaceXXSmall) from '../../styles/variables/_space.css';
6
+
7
+ @value ( sizeFluid, size60) from '../../styles/variables/_size.css';
8
+
9
+ .container {
10
+ display: flex;
11
+ height: sizeFluid;
12
+ width: sizeFluid;
13
+ }
14
+
15
+ .leftButton {
16
+ border-top-right-radius: borderRadiusNone;
17
+ border-bottom-right-radius: borderRadiusNone;
18
+ min-width: initial;
19
+ }
20
+
21
+ .rightButton {
22
+ border-top-left-radius: borderRadiusNone;
23
+ border-bottom-left-radius: borderRadiusNone;
24
+ margin-left: calc(spaceXXSmall / 4);
25
+ }
26
+
27
+ .dropDownContainer {
28
+ width: max-content;
29
+ }
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "OptionButton", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _OptionButton.OptionButton;
10
+ }
11
+ });
12
+ var _OptionButton = require("./OptionButton");
@@ -0,0 +1,3 @@
1
+ //@flow strict
2
+ export type {OptionButtonProps} from './OptionButton';
3
+ export {OptionButton} from './OptionButton';
@@ -0,0 +1,178 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.TabSlot = exports.RightSlot = exports.PageTitle = exports.PageName = exports.PAGE_NAME_LIST = void 0;
7
+ var React = _interopRequireWildcard(require("react"));
8
+ var _classify = _interopRequireDefault(require("../../utils/classify"));
9
+ var _Icon = require("../Icon");
10
+ var _Text = require("../Text");
11
+ var _PageTitleModule = _interopRequireDefault(require("./PageTitle.module.css"));
12
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
14
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
15
+ function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
16
+ const PAGE_NAME_LIST = Object.freeze({
17
+ dashboard: {
18
+ title: 'Dashboard',
19
+ iconName: 'house',
20
+ iconType: 'duotone',
21
+ iconSwapOpacity: true
22
+ },
23
+ engage: {
24
+ title: 'Engage',
25
+ iconName: 'bullseye-pointer',
26
+ iconType: 'duotone',
27
+ iconSwapOpacity: true
28
+ },
29
+ trm: {
30
+ title: 'TRM',
31
+ iconName: 'screen-users',
32
+ iconType: 'duotone',
33
+ iconSwapOpacity: true
34
+ },
35
+ analytics: {
36
+ title: 'Analytics',
37
+ iconName: 'chart-column',
38
+ iconType: 'duotone',
39
+ iconSwapOpacity: true
40
+ },
41
+ messaging: {
42
+ title: 'Messaging',
43
+ iconName: 'messages',
44
+ iconType: 'duotone',
45
+ iconSwapOpacity: true
46
+ },
47
+ chatbot: {
48
+ title: 'Chatbot',
49
+ iconName: 'message-bot',
50
+ iconType: 'duotone',
51
+ iconSwapOpacity: true
52
+ },
53
+ referrals: {
54
+ title: 'Referrals',
55
+ iconName: 'user-check',
56
+ iconType: 'duotone',
57
+ iconSwapOpacity: true
58
+ },
59
+ records: {
60
+ title: 'Records',
61
+ iconName: 'folder-open',
62
+ iconType: 'duotone',
63
+ iconSwapOpacity: true
64
+ },
65
+ bulkCleanup: {
66
+ title: 'Bulk Cleanup',
67
+ iconName: 'retweet',
68
+ iconType: 'duotone',
69
+ iconSwapOpacity: true
70
+ },
71
+ support: {
72
+ title: 'Support',
73
+ iconName: 'headset',
74
+ iconType: 'duotone',
75
+ iconSwapOpacity: true
76
+ },
77
+ audit: {
78
+ title: 'Audit',
79
+ iconName: 'print-magnifying-glass',
80
+ iconType: 'duotone',
81
+ iconSwapOpacity: true
82
+ },
83
+ timeline: {
84
+ title: 'Timeline',
85
+ iconName: 'timeline',
86
+ iconType: 'duotone',
87
+ iconSwapOpacity: true
88
+ },
89
+ people: {
90
+ title: 'People',
91
+ iconName: 'people-group',
92
+ iconType: 'duotone',
93
+ iconSwapOpacity: true
94
+ },
95
+ contacts: {
96
+ title: 'Contacts',
97
+ iconName: 'address-card',
98
+ iconType: 'duotone',
99
+ iconSwapOpacity: true
100
+ },
101
+ contacts2: {
102
+ title: 'Contacts',
103
+ iconName: 'calendars',
104
+ iconType: 'duotone',
105
+ iconSwapOpacity: true
106
+ },
107
+ contacts3: {
108
+ title: 'Contacts',
109
+ iconName: 'browser',
110
+ iconType: 'duotone',
111
+ iconSwapOpacity: true
112
+ }
113
+ });
114
+ exports.PAGE_NAME_LIST = PAGE_NAME_LIST;
115
+ const TabSlot = _ref => {
116
+ let {
117
+ children,
118
+ className,
119
+ ...props
120
+ } = _ref;
121
+ return /*#__PURE__*/React.createElement("div", _extends({}, props, {
122
+ className: (0, _classify.default)(_PageTitleModule.default.tabSlot, className)
123
+ }), children);
124
+ };
125
+ exports.TabSlot = TabSlot;
126
+ const RightSlot = _ref2 => {
127
+ let {
128
+ children,
129
+ ...props
130
+ } = _ref2;
131
+ return /*#__PURE__*/React.createElement("div", props, children);
132
+ };
133
+ exports.RightSlot = RightSlot;
134
+ const PageName = _ref3 => {
135
+ let {
136
+ children,
137
+ ...props
138
+ } = _ref3;
139
+ return /*#__PURE__*/React.createElement("div", _extends({}, props, {
140
+ className: _PageTitleModule.default.pageTitle
141
+ }), children);
142
+ };
143
+ exports.PageName = PageName;
144
+ const PageTitle = _ref4 => {
145
+ let {
146
+ classNames,
147
+ children,
148
+ pageNameKey
149
+ } = _ref4;
150
+ const getNamedComp = comp => {
151
+ const childrenArray = React.Children.toArray(children);
152
+ if (childrenArray.length) {
153
+ const nodes = [];
154
+ for (const child of childrenArray) {
155
+ if (child?.type?.name === comp) {
156
+ nodes.push(child);
157
+ }
158
+ }
159
+ return nodes.length > 1 ? nodes : nodes[0];
160
+ }
161
+ return null;
162
+ };
163
+ return /*#__PURE__*/React.createElement("div", {
164
+ "data-testid": "PageTitle",
165
+ className: (0, _classify.default)(_PageTitleModule.default.pageTitleWrapper, classNames?.wrapper)
166
+ }, /*#__PURE__*/React.createElement("div", {
167
+ className: (0, _classify.default)(_PageTitleModule.default.leftSlot, classNames?.leftSlot)
168
+ }, pageNameKey && PAGE_NAME_LIST[pageNameKey] ? /*#__PURE__*/React.createElement(PageName, null, /*#__PURE__*/React.createElement(_Text.TitleMedium, null, PAGE_NAME_LIST[pageNameKey].title, " "), /*#__PURE__*/React.createElement(_Icon.Icon, {
169
+ type: PAGE_NAME_LIST[pageNameKey].iconType,
170
+ name: PAGE_NAME_LIST[pageNameKey].iconName,
171
+ size: "medium",
172
+ color: _Text.TEXT_COLORS.primary,
173
+ swapOpacity: PAGE_NAME_LIST[pageNameKey].iconSwapOpacity
174
+ })) : getNamedComp('PageName'), getNamedComp('TabSlot')), /*#__PURE__*/React.createElement("div", {
175
+ className: (0, _classify.default)(_PageTitleModule.default.rightSlot, classNames?.rightSlot)
176
+ }, getNamedComp('RightSlot')));
177
+ };
178
+ exports.PageTitle = PageTitle;
@@ -0,0 +1,205 @@
1
+ // @flow strict
2
+
3
+ import * as React from 'react';
4
+
5
+ import classify from '../../utils/classify';
6
+ import {Icon} from '../Icon';
7
+ import {TEXT_COLORS, TitleMedium} from '../Text';
8
+
9
+ import css from './PageTitle.module.css';
10
+
11
+
12
+ type ClassNames = $ReadOnly<{
13
+ wrapper?: string,
14
+ leftSlot?: string,
15
+ rightSlot?: string,
16
+ }>;
17
+
18
+ export type PageTitleProps = {
19
+ classNames?: ClassNames,
20
+ children?: React.Node,
21
+ pageNameKey?: string,
22
+ };
23
+
24
+ export const PAGE_NAME_LIST = Object.freeze({
25
+ dashboard: {
26
+ title: 'Dashboard',
27
+ iconName: 'house',
28
+ iconType: 'duotone',
29
+ iconSwapOpacity: true,
30
+ },
31
+ engage: {
32
+ title: 'Engage',
33
+ iconName: 'bullseye-pointer',
34
+ iconType: 'duotone',
35
+ iconSwapOpacity: true,
36
+ },
37
+ trm: {
38
+ title: 'TRM',
39
+ iconName: 'screen-users',
40
+ iconType: 'duotone',
41
+ iconSwapOpacity: true,
42
+ },
43
+ analytics: {
44
+ title: 'Analytics',
45
+ iconName: 'chart-column',
46
+ iconType: 'duotone',
47
+ iconSwapOpacity: true,
48
+ },
49
+ messaging: {
50
+ title: 'Messaging',
51
+ iconName: 'messages',
52
+ iconType: 'duotone',
53
+ iconSwapOpacity: true,
54
+ },
55
+ chatbot: {
56
+ title: 'Chatbot',
57
+ iconName: 'message-bot',
58
+ iconType: 'duotone',
59
+ iconSwapOpacity: true,
60
+ },
61
+ referrals: {
62
+ title: 'Referrals',
63
+ iconName: 'user-check',
64
+ iconType: 'duotone',
65
+ iconSwapOpacity: true,
66
+ },
67
+ records: {
68
+ title: 'Records',
69
+ iconName: 'folder-open',
70
+ iconType: 'duotone',
71
+ iconSwapOpacity: true,
72
+ },
73
+ bulkCleanup: {
74
+ title: 'Bulk Cleanup',
75
+ iconName: 'retweet',
76
+ iconType: 'duotone',
77
+ iconSwapOpacity: true,
78
+ },
79
+ support: {
80
+ title: 'Support',
81
+ iconName: 'headset',
82
+ iconType: 'duotone',
83
+ iconSwapOpacity: true,
84
+ },
85
+ audit: {
86
+ title: 'Audit',
87
+ iconName: 'print-magnifying-glass',
88
+ iconType: 'duotone',
89
+ iconSwapOpacity: true,
90
+ },
91
+ timeline: {
92
+ title: 'Timeline',
93
+ iconName: 'timeline',
94
+ iconType: 'duotone',
95
+ iconSwapOpacity: true,
96
+ },
97
+ people: {
98
+ title: 'People',
99
+ iconName: 'people-group',
100
+ iconType: 'duotone',
101
+ iconSwapOpacity: true,
102
+ },
103
+ contacts: {
104
+ title: 'Contacts',
105
+ iconName: 'address-card',
106
+ iconType: 'duotone',
107
+ iconSwapOpacity: true,
108
+ },
109
+ contacts2: {
110
+ title: 'Contacts',
111
+ iconName: 'calendars',
112
+ iconType: 'duotone',
113
+ iconSwapOpacity: true,
114
+ },
115
+ contacts3: {
116
+ title: 'Contacts',
117
+ iconName: 'browser',
118
+ iconType: 'duotone',
119
+ iconSwapOpacity: true,
120
+ },
121
+ });
122
+
123
+ export type TabSlotProps = {
124
+ children?: React.Node,
125
+ className: string,
126
+ ...
127
+ };
128
+
129
+ export const TabSlot = ({
130
+ children,
131
+ className,
132
+ ...props
133
+ }: TabSlotProps): React.Node => (
134
+ <div {...props} className={classify(css.tabSlot, className)}>
135
+ {children}
136
+ </div>
137
+ );
138
+
139
+ export type RightSlotProps = {
140
+ children?: React.Node,
141
+ ...
142
+ };
143
+
144
+ export const RightSlot = ({children, ...props}: RightSlotProps): React.Node => (
145
+ <div {...props}>{children}</div>
146
+ );
147
+
148
+ export type PageNameProps = {
149
+ children?: React.Node,
150
+ ...
151
+ };
152
+
153
+ export const PageName = ({children, ...props}: PageNameProps): React.Node => (
154
+ <div {...props} className={css.pageTitle}>
155
+ {children}
156
+ </div>
157
+ );
158
+
159
+ export const PageTitle = ({
160
+ classNames,
161
+ children,
162
+ pageNameKey,
163
+ }: PageTitleProps): React.Node => {
164
+ const getNamedComp = (comp: string) => {
165
+ const childrenArray = React.Children.toArray(children);
166
+ if (childrenArray.length) {
167
+ const nodes: React.Node[] = [];
168
+ for (const child of childrenArray) {
169
+ if (child?.type?.name === comp) {
170
+ nodes.push(child);
171
+ }
172
+ }
173
+ return nodes.length > 1 ? nodes : nodes[0];
174
+ }
175
+ return null;
176
+ };
177
+
178
+ return (
179
+ <div
180
+ data-testid="PageTitle"
181
+ className={classify(css.pageTitleWrapper, classNames?.wrapper)}
182
+ >
183
+ <div className={classify(css.leftSlot, classNames?.leftSlot)}>
184
+ {pageNameKey && PAGE_NAME_LIST[pageNameKey] ? (
185
+ <PageName>
186
+ <TitleMedium>{PAGE_NAME_LIST[pageNameKey].title} </TitleMedium>
187
+ <Icon
188
+ type={PAGE_NAME_LIST[pageNameKey].iconType}
189
+ name={PAGE_NAME_LIST[pageNameKey].iconName}
190
+ size="medium"
191
+ color={TEXT_COLORS.primary}
192
+ swapOpacity={PAGE_NAME_LIST[pageNameKey].iconSwapOpacity}
193
+ />
194
+ </PageName>
195
+ ) : (
196
+ getNamedComp('PageName')
197
+ )}
198
+ {getNamedComp('TabSlot')}
199
+ </div>
200
+ <div className={classify(css.rightSlot, classNames?.rightSlot)}>
201
+ {getNamedComp('RightSlot')}
202
+ </div>
203
+ </div>
204
+ );
205
+ };
@@ -0,0 +1,40 @@
1
+ @value (colorBackgroundTertiary) from '../../styles/variables/_color.css';
2
+ @value (spaceNone, spaceXXSmall, spaceXSmall, spaceSmall, spaceMedium, spaceLarge) from '../../styles/variables/_space.css';
3
+
4
+ @value (sizeFluid, size60) from '../../styles/variables/_size.css';
5
+
6
+ .pageTitleWrapper {
7
+ composes: borderBottomPrimary from '../../styles/border.module.css';
8
+ background: colorBackgroundTertiary;
9
+ display: flex;
10
+ flex-direction: row;
11
+ justify-content: space-between;
12
+ box-sizing: border-box;
13
+ padding: spaceSmall spaceLarge spaceNone spaceLarge;
14
+ width: sizeFluid;
15
+ min-height: size60;
16
+ gap: spaceMedium;
17
+ height: fit-content;
18
+ }
19
+
20
+ .leftSlot {
21
+ display: flex;
22
+ flex-direction: column;
23
+ gap: spaceXSmall;
24
+ margin-bottom: calc(spaceXXSmall * -0.75);
25
+ }
26
+
27
+ .pageTitle {
28
+ display: flex;
29
+ flex-direction: row;
30
+ gap: spaceXSmall;
31
+ justify-content: flex-start;
32
+ align-items: center;
33
+ }
34
+
35
+ .rightSlot {
36
+ display: flex;
37
+ flex-direction: column;
38
+ justify-content: flex-end;
39
+ margin: spaceNone spaceNone spaceSmall spaceNone;
40
+ }
@@ -17,6 +17,7 @@ import {
17
17
  import {spaceNone, spaceXXSmall} from '../../styles/variables/_space';
18
18
  import {classify} from '../../utils/classify';
19
19
  import {ClickAway} from '../../utils/click-away';
20
+ import type {AnchorType} from '../ButtonDropdown';
20
21
  import type {MenuOption, MenuProps} from '../Menu';
21
22
  import {Menu} from '../Menu';
22
23
  import type {TabProps} from '../Tab';
@@ -28,13 +29,7 @@ import css from './TabDropdown.module.css';
28
29
  type ClassNames = $ReadOnly<{wrapper?: string}>;
29
30
 
30
31
  export type TabDropdownProps = {
31
- anchorPosition?:
32
- | 'top'
33
- | 'top-start'
34
- | 'top-end'
35
- | 'bottom'
36
- | 'bottom-start'
37
- | 'bottom-end',
32
+ anchorPosition?: AnchorType,
38
33
  size?: 'medium' | 'small',
39
34
  props?: {
40
35
  tab: TabProps,
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ var _exportNames = {
7
+ Tab: true,
8
+ tabSizeOptions: true
9
+ };
10
+ Object.defineProperty(exports, "Tab", {
11
+ enumerable: true,
12
+ get: function () {
13
+ return _Tab.Tab;
14
+ }
15
+ });
16
+ Object.defineProperty(exports, "tabSizeOptions", {
17
+ enumerable: true,
18
+ get: function () {
19
+ return _Tab.tabSizeOptions;
20
+ }
21
+ });
22
+ var _Tab = require("../Tab");
23
+ var _TabList = require("../TabList");
24
+ Object.keys(_TabList).forEach(function (key) {
25
+ if (key === "default" || key === "__esModule") return;
26
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
27
+ if (key in exports && exports[key] === _TabList[key]) return;
28
+ Object.defineProperty(exports, key, {
29
+ enumerable: true,
30
+ get: function () {
31
+ return _TabList[key];
32
+ }
33
+ });
34
+ });
@@ -0,0 +1,6 @@
1
+ // @flow strict
2
+
3
+ export type {TabProps} from '../Tab';
4
+ export {Tab, tabSizeOptions} from '../Tab';
5
+ export type {TabsProps} from '../TabList';
6
+ export * from '../TabList';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spaced-out/ui-design-system",
3
- "version": "0.0.12",
3
+ "version": "0.0.14",
4
4
  "main": "index.js",
5
5
  "description": "Sense UI components library",
6
6
  "author": {