@spaced-out/ui-design-system 0.0.7 → 0.0.8
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 +88 -93
- package/design-tokens/size/base-size.json +3 -0
- package/lib/components/Avatar/Avatar.js +7 -5
- package/lib/components/Avatar/Avatar.js.flow +17 -5
- package/lib/components/Icon/Icon.js +6 -1
- package/lib/components/Icon/Icon.js.flow +6 -1
- package/lib/components/Menu/Menu.js +4 -0
- package/lib/components/Menu/Menu.js.flow +47 -28
- package/lib/components/Tab/Tab.js +90 -0
- package/lib/components/Tab/Tab.js.flow +130 -0
- package/lib/components/Tab/Tab.module.css +66 -0
- package/lib/components/Tab/index.js +18 -0
- package/lib/components/Tab/index.js.flow +4 -0
- package/lib/components/TabList/TabDropdown.js +80 -0
- package/lib/components/TabList/TabDropdown.js.flow +110 -0
- package/lib/components/TabList/TabDropdown.module.css +20 -0
- package/lib/components/TabList/TabList.js +127 -0
- package/lib/components/TabList/TabList.js.flow +146 -0
- package/lib/components/TabList/TabList.module.css +11 -0
- package/lib/components/TabList/index.js +16 -0
- package/lib/components/TabList/index.js.flow +4 -0
- package/lib/styles/variables/_size.css +2 -0
- package/lib/styles/variables/_size.js +3 -1
- package/lib/styles/variables/_size.js.flow +2 -0
- package/package.json +1 -1
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.tabSizeOptions = exports.Tab = exports.TAB_SIZE = void 0;
|
|
7
|
+
var React = _interopRequireWildcard(require("react"));
|
|
8
|
+
var _typography = require("../../types/typography");
|
|
9
|
+
var _classify = require("../../utils/classify");
|
|
10
|
+
var _Button = require("../Button");
|
|
11
|
+
var _Icon = require("../Icon");
|
|
12
|
+
var _Text = require("../Text");
|
|
13
|
+
var _TabModule = _interopRequireDefault(require("./Tab.module.css"));
|
|
14
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
15
|
+
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); }
|
|
16
|
+
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; }
|
|
17
|
+
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); }
|
|
18
|
+
const TAB_SIZE = Object.freeze({
|
|
19
|
+
small: 'small',
|
|
20
|
+
medium: 'medium'
|
|
21
|
+
});
|
|
22
|
+
exports.TAB_SIZE = TAB_SIZE;
|
|
23
|
+
const tabSizeOptions = [...Object.keys(TAB_SIZE)];
|
|
24
|
+
exports.tabSizeOptions = tabSizeOptions;
|
|
25
|
+
const Tab = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
26
|
+
let {
|
|
27
|
+
classNames,
|
|
28
|
+
onSelect,
|
|
29
|
+
size = 'medium',
|
|
30
|
+
selectedTab,
|
|
31
|
+
disabled = false,
|
|
32
|
+
tabId,
|
|
33
|
+
label,
|
|
34
|
+
iconName,
|
|
35
|
+
iconType,
|
|
36
|
+
onClick,
|
|
37
|
+
width,
|
|
38
|
+
...props
|
|
39
|
+
} = _ref;
|
|
40
|
+
const selected = tabId && tabId === selectedTab?.tabId;
|
|
41
|
+
const onClickHandler = e => {
|
|
42
|
+
if (!disabled) {
|
|
43
|
+
onSelect && onSelect({
|
|
44
|
+
tabId,
|
|
45
|
+
label
|
|
46
|
+
});
|
|
47
|
+
onClick && onClick(e);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
return /*#__PURE__*/React.createElement(_Button.UnstyledButton, _extends({}, props, {
|
|
51
|
+
disabled: disabled,
|
|
52
|
+
className: (0, _classify.classify)(_TabModule.default.button, {
|
|
53
|
+
[_TabModule.default.selected]: selected === true,
|
|
54
|
+
[_TabModule.default.disabled]: disabled === true,
|
|
55
|
+
[_TabModule.default.mediumSize]: size === 'medium',
|
|
56
|
+
[_TabModule.default.smallSize]: size === 'small'
|
|
57
|
+
}, classNames?.wrapper),
|
|
58
|
+
onClick: onClickHandler,
|
|
59
|
+
style: {
|
|
60
|
+
width
|
|
61
|
+
},
|
|
62
|
+
tabIndex: disabled ? '-1' : 0,
|
|
63
|
+
ref: ref
|
|
64
|
+
}), /*#__PURE__*/React.createElement("span", {
|
|
65
|
+
className: (0, _classify.classify)(_TabModule.default.iconTextWrap, {
|
|
66
|
+
[_TabModule.default.selected]: selected === true,
|
|
67
|
+
[_TabModule.default.disabled]: disabled === true
|
|
68
|
+
}, classNames?.iconTextWrap)
|
|
69
|
+
}, iconName ? /*#__PURE__*/React.createElement(_Icon.Icon, {
|
|
70
|
+
name: iconName,
|
|
71
|
+
type: iconType,
|
|
72
|
+
size: 'medium',
|
|
73
|
+
className: (0, _classify.classify)(_TabModule.default.icon, {
|
|
74
|
+
[_TabModule.default.disabled]: disabled === true
|
|
75
|
+
})
|
|
76
|
+
}) : null, size === TAB_SIZE.medium ? /*#__PURE__*/React.createElement(_Text.ButtonTextMedium, {
|
|
77
|
+
color: _typography.TEXT_COLORS.secondary,
|
|
78
|
+
className: (0, _classify.classify)(_TabModule.default.tabContainer, {
|
|
79
|
+
[_TabModule.default.disabled]: disabled === true
|
|
80
|
+
})
|
|
81
|
+
}, label) : /*#__PURE__*/React.createElement(_Text.ButtonTextSmall, {
|
|
82
|
+
color: _typography.TEXT_COLORS.secondary,
|
|
83
|
+
className: (0, _classify.classify)(_TabModule.default.tabContainer, {
|
|
84
|
+
[_TabModule.default.selected]: selected === true,
|
|
85
|
+
[_TabModule.default.disabled]: disabled === true
|
|
86
|
+
})
|
|
87
|
+
}, label)));
|
|
88
|
+
});
|
|
89
|
+
exports.Tab = Tab;
|
|
90
|
+
Tab.name = Tab.displayName = 'Tab';
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
// @flow strict
|
|
2
|
+
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
|
|
5
|
+
import {TEXT_COLORS} from '../../types/typography';
|
|
6
|
+
import {classify} from '../../utils/classify';
|
|
7
|
+
import {UnstyledButton} from '../Button';
|
|
8
|
+
import type {IconType} from '../Icon';
|
|
9
|
+
import {Icon} from '../Icon';
|
|
10
|
+
import {ButtonTextMedium, ButtonTextSmall} from '../Text';
|
|
11
|
+
|
|
12
|
+
import css from './Tab.module.css';
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
type ClassNames = $ReadOnly<{wrapper?: string, iconTextWrap?: string}>;
|
|
16
|
+
|
|
17
|
+
export const TAB_SIZE = Object.freeze({
|
|
18
|
+
small: 'small',
|
|
19
|
+
medium: 'medium',
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
export const tabSizeOptions: Array<mixed> = [...Object.keys(TAB_SIZE)];
|
|
23
|
+
|
|
24
|
+
export type TabSize = $Keys<typeof TAB_SIZE>;
|
|
25
|
+
|
|
26
|
+
export type TabProps = {
|
|
27
|
+
classNames?: ClassNames,
|
|
28
|
+
onSelect?: ({tabId?: string, label?: string}) => mixed,
|
|
29
|
+
size?: TabSize,
|
|
30
|
+
selectedTab?: {tabId?: string, label?: string},
|
|
31
|
+
disabled?: boolean,
|
|
32
|
+
tabId?: string,
|
|
33
|
+
label?: string,
|
|
34
|
+
iconName?: string,
|
|
35
|
+
iconType?: IconType,
|
|
36
|
+
width?: string,
|
|
37
|
+
onClick?: ?(SyntheticEvent<HTMLElement>) => mixed,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const Tab: React$AbstractComponent<TabProps, HTMLButtonElement> =
|
|
41
|
+
React.forwardRef<TabProps, HTMLButtonElement>(
|
|
42
|
+
(
|
|
43
|
+
{
|
|
44
|
+
classNames,
|
|
45
|
+
onSelect,
|
|
46
|
+
size = 'medium',
|
|
47
|
+
selectedTab,
|
|
48
|
+
disabled = false,
|
|
49
|
+
tabId,
|
|
50
|
+
label,
|
|
51
|
+
iconName,
|
|
52
|
+
iconType,
|
|
53
|
+
onClick,
|
|
54
|
+
width,
|
|
55
|
+
...props
|
|
56
|
+
}: TabProps,
|
|
57
|
+
ref,
|
|
58
|
+
) => {
|
|
59
|
+
const selected = tabId && tabId === selectedTab?.tabId;
|
|
60
|
+
const onClickHandler = (e) => {
|
|
61
|
+
if (!disabled) {
|
|
62
|
+
onSelect && onSelect({tabId, label});
|
|
63
|
+
onClick && onClick(e);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
return (
|
|
67
|
+
<UnstyledButton
|
|
68
|
+
{...props}
|
|
69
|
+
disabled={disabled}
|
|
70
|
+
className={classify(
|
|
71
|
+
css.button,
|
|
72
|
+
{
|
|
73
|
+
[css.selected]: selected === true,
|
|
74
|
+
[css.disabled]: disabled === true,
|
|
75
|
+
[css.mediumSize]: size === 'medium',
|
|
76
|
+
[css.smallSize]: size === 'small',
|
|
77
|
+
},
|
|
78
|
+
classNames?.wrapper,
|
|
79
|
+
)}
|
|
80
|
+
onClick={onClickHandler}
|
|
81
|
+
style={{width}}
|
|
82
|
+
tabIndex={disabled ? '-1' : 0}
|
|
83
|
+
ref={ref}
|
|
84
|
+
>
|
|
85
|
+
<span
|
|
86
|
+
className={classify(
|
|
87
|
+
css.iconTextWrap,
|
|
88
|
+
{
|
|
89
|
+
[css.selected]: selected === true,
|
|
90
|
+
[css.disabled]: disabled === true,
|
|
91
|
+
},
|
|
92
|
+
classNames?.iconTextWrap,
|
|
93
|
+
)}
|
|
94
|
+
>
|
|
95
|
+
{iconName ? (
|
|
96
|
+
<Icon
|
|
97
|
+
name={iconName}
|
|
98
|
+
type={iconType}
|
|
99
|
+
size={'medium'}
|
|
100
|
+
className={classify(css.icon, {
|
|
101
|
+
[css.disabled]: disabled === true,
|
|
102
|
+
})}
|
|
103
|
+
/>
|
|
104
|
+
) : null}
|
|
105
|
+
{size === TAB_SIZE.medium ? (
|
|
106
|
+
<ButtonTextMedium
|
|
107
|
+
color={TEXT_COLORS.secondary}
|
|
108
|
+
className={classify(css.tabContainer, {
|
|
109
|
+
[css.disabled]: disabled === true,
|
|
110
|
+
})}
|
|
111
|
+
>
|
|
112
|
+
{label}
|
|
113
|
+
</ButtonTextMedium>
|
|
114
|
+
) : (
|
|
115
|
+
<ButtonTextSmall
|
|
116
|
+
color={TEXT_COLORS.secondary}
|
|
117
|
+
className={classify(css.tabContainer, {
|
|
118
|
+
[css.selected]: selected === true,
|
|
119
|
+
[css.disabled]: disabled === true,
|
|
120
|
+
})}
|
|
121
|
+
>
|
|
122
|
+
{label}
|
|
123
|
+
</ButtonTextSmall>
|
|
124
|
+
)}
|
|
125
|
+
</span>
|
|
126
|
+
</UnstyledButton>
|
|
127
|
+
);
|
|
128
|
+
},
|
|
129
|
+
);
|
|
130
|
+
Tab.name = Tab.displayName = 'Tab';
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
@value (colorFillPrimary, colorTextSecondary, colorFillNone, colorFocusPrimary, colorTextPrimary, colorTextDisabled) from '../../styles/variables/_color.css';
|
|
2
|
+
|
|
3
|
+
@value (spaceXXSmall) from '../../styles/variables/_space.css';
|
|
4
|
+
|
|
5
|
+
@value (sizeFluid, size42, size38) from '../../styles/variables/_size.css';
|
|
6
|
+
|
|
7
|
+
@value (borderWidthTertiary) from '../../styles/variables/_border.css';
|
|
8
|
+
|
|
9
|
+
.button {
|
|
10
|
+
border: borderWidthTertiary solid colorFillNone;
|
|
11
|
+
box-sizing: border-box;
|
|
12
|
+
display: flex;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.button.mediumSize {
|
|
16
|
+
height: size42;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.button.smallSize {
|
|
20
|
+
height: size38;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.button:focus {
|
|
24
|
+
border: borderWidthTertiary solid colorFocusPrimary;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.button:focus .tabContainer {
|
|
28
|
+
color: colorTextPrimary;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.button .disabled {
|
|
32
|
+
cursor: not-allowed;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.iconTextWrap {
|
|
36
|
+
display: flex;
|
|
37
|
+
flex-direction: row;
|
|
38
|
+
gap: spaceXXSmall;
|
|
39
|
+
align-items: center;
|
|
40
|
+
color: colorTextSecondary;
|
|
41
|
+
border-bottom: borderWidthTertiary solid colorFillNone;
|
|
42
|
+
height: sizeFluid;
|
|
43
|
+
white-space: nowrap;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.iconTextWrap.selected {
|
|
47
|
+
color: colorTextPrimary;
|
|
48
|
+
border-bottom: borderWidthTertiary solid colorFillPrimary;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.iconTextWrap.disabled {
|
|
52
|
+
color: colorTextDisabled;
|
|
53
|
+
border-bottom: borderWidthTertiary solid colorFillNone;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.icon {
|
|
57
|
+
color: inherit;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.tabContainer {
|
|
61
|
+
display: flex;
|
|
62
|
+
align-items: center;
|
|
63
|
+
justify-content: center;
|
|
64
|
+
box-sizing: border-box;
|
|
65
|
+
color: inherit;
|
|
66
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "Tab", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _Tab.Tab;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
Object.defineProperty(exports, "tabSizeOptions", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () {
|
|
15
|
+
return _Tab.tabSizeOptions;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
var _Tab = require("./Tab");
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.TabDropdown = void 0;
|
|
7
|
+
var React = _interopRequireWildcard(require("react"));
|
|
8
|
+
var _reactDom = require("@floating-ui/react-dom");
|
|
9
|
+
var _space = require("../../styles/variables/_space");
|
|
10
|
+
var _classify = require("../../utils/classify");
|
|
11
|
+
var _clickAway = require("../../utils/click-away");
|
|
12
|
+
var _Menu = require("../Menu");
|
|
13
|
+
var _Tab = require("../Tab");
|
|
14
|
+
var _TabDropdownModule = _interopRequireDefault(require("./TabDropdown.module.css"));
|
|
15
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
16
|
+
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); }
|
|
17
|
+
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; }
|
|
18
|
+
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); }
|
|
19
|
+
const TabDropdown = _ref => {
|
|
20
|
+
let {
|
|
21
|
+
anchorPosition = 'bottom-start',
|
|
22
|
+
size,
|
|
23
|
+
onOptionSelect,
|
|
24
|
+
props,
|
|
25
|
+
classNames
|
|
26
|
+
} = _ref;
|
|
27
|
+
const menuBtnRef = React.useRef();
|
|
28
|
+
const {
|
|
29
|
+
x,
|
|
30
|
+
y,
|
|
31
|
+
reference,
|
|
32
|
+
floating,
|
|
33
|
+
strategy
|
|
34
|
+
} = (0, _reactDom.useFloating)({
|
|
35
|
+
strategy: 'absolute',
|
|
36
|
+
placement: anchorPosition,
|
|
37
|
+
whileElementsMounted: _reactDom.autoUpdate,
|
|
38
|
+
middleware: [(0, _reactDom.shift)(), (0, _reactDom.flip)(), (0, _reactDom.offset)(parseInt(_space.spaceXXSmall))]
|
|
39
|
+
});
|
|
40
|
+
return /*#__PURE__*/React.createElement(_clickAway.ClickAway, null, _ref2 => {
|
|
41
|
+
let {
|
|
42
|
+
isOpen,
|
|
43
|
+
onOpen,
|
|
44
|
+
cancelNext,
|
|
45
|
+
clickAway
|
|
46
|
+
} = _ref2;
|
|
47
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
48
|
+
"data-testid": "TabDropdown",
|
|
49
|
+
className: (0, _classify.classify)(_TabDropdownModule.default.tabDropdownContainer, classNames?.wrapper),
|
|
50
|
+
ref: menuBtnRef
|
|
51
|
+
}, /*#__PURE__*/React.createElement(_Tab.Tab, _extends({}, props?.tab, {
|
|
52
|
+
size: size,
|
|
53
|
+
ref: reference,
|
|
54
|
+
onClick: e => {
|
|
55
|
+
e.stopPropagation();
|
|
56
|
+
onOpen();
|
|
57
|
+
},
|
|
58
|
+
classNames: {
|
|
59
|
+
wrapper: _TabDropdownModule.default.dotTabWrapper,
|
|
60
|
+
iconTextWrap: _TabDropdownModule.default.dotTextWrap
|
|
61
|
+
}
|
|
62
|
+
})), isOpen && props?.menu && /*#__PURE__*/React.createElement("div", {
|
|
63
|
+
onClickCapture: cancelNext,
|
|
64
|
+
ref: floating,
|
|
65
|
+
style: {
|
|
66
|
+
display: 'flex',
|
|
67
|
+
position: strategy,
|
|
68
|
+
top: y ?? _space.spaceNone,
|
|
69
|
+
left: x ?? _space.spaceNone
|
|
70
|
+
}
|
|
71
|
+
}, /*#__PURE__*/React.createElement(_Menu.Menu, _extends({}, props.menu, {
|
|
72
|
+
onSelect: option => {
|
|
73
|
+
onOptionSelect && onOptionSelect(option);
|
|
74
|
+
clickAway();
|
|
75
|
+
},
|
|
76
|
+
size: size
|
|
77
|
+
}))));
|
|
78
|
+
});
|
|
79
|
+
};
|
|
80
|
+
exports.TabDropdown = TabDropdown;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
// @flow strict
|
|
2
|
+
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import {
|
|
5
|
+
// $FlowFixMe[untyped-import]
|
|
6
|
+
autoUpdate,
|
|
7
|
+
// $FlowFixMe[untyped-import]
|
|
8
|
+
flip,
|
|
9
|
+
// $FlowFixMe[untyped-import]
|
|
10
|
+
offset,
|
|
11
|
+
// $FlowFixMe[untyped-import]
|
|
12
|
+
shift,
|
|
13
|
+
// $FlowFixMe[untyped-import]
|
|
14
|
+
useFloating,
|
|
15
|
+
} from '@floating-ui/react-dom';
|
|
16
|
+
|
|
17
|
+
import {spaceNone, spaceXXSmall} from '../../styles/variables/_space';
|
|
18
|
+
import {classify} from '../../utils/classify';
|
|
19
|
+
import {ClickAway} from '../../utils/click-away';
|
|
20
|
+
import type {MenuOption, MenuProps} from '../Menu';
|
|
21
|
+
import {Menu} from '../Menu';
|
|
22
|
+
import type {TabProps} from '../Tab';
|
|
23
|
+
import {Tab} from '../Tab';
|
|
24
|
+
|
|
25
|
+
import css from './TabDropdown.module.css';
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
type ClassNames = $ReadOnly<{wrapper?: string}>;
|
|
29
|
+
|
|
30
|
+
export type TabDropdownProps = {
|
|
31
|
+
anchorPosition?:
|
|
32
|
+
| 'top'
|
|
33
|
+
| 'top-start'
|
|
34
|
+
| 'top-end'
|
|
35
|
+
| 'bottom'
|
|
36
|
+
| 'bottom-start'
|
|
37
|
+
| 'bottom-end',
|
|
38
|
+
size?: 'medium' | 'small',
|
|
39
|
+
props?: {
|
|
40
|
+
tab: TabProps,
|
|
41
|
+
menu: MenuProps,
|
|
42
|
+
},
|
|
43
|
+
onOptionSelect?: (option: MenuOption) => mixed,
|
|
44
|
+
classNames?: ClassNames,
|
|
45
|
+
selected?: boolean,
|
|
46
|
+
disabled?: boolean,
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export const TabDropdown = ({
|
|
50
|
+
anchorPosition = 'bottom-start',
|
|
51
|
+
size,
|
|
52
|
+
onOptionSelect,
|
|
53
|
+
props,
|
|
54
|
+
classNames,
|
|
55
|
+
}: TabDropdownProps): React.Node => {
|
|
56
|
+
const menuBtnRef = React.useRef();
|
|
57
|
+
const {x, y, reference, floating, strategy} = useFloating({
|
|
58
|
+
strategy: 'absolute',
|
|
59
|
+
placement: anchorPosition,
|
|
60
|
+
whileElementsMounted: autoUpdate,
|
|
61
|
+
middleware: [shift(), flip(), offset(parseInt(spaceXXSmall))],
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
<ClickAway>
|
|
66
|
+
{({isOpen, onOpen, cancelNext, clickAway}) => (
|
|
67
|
+
<div
|
|
68
|
+
data-testid="TabDropdown"
|
|
69
|
+
className={classify(css.tabDropdownContainer, classNames?.wrapper)}
|
|
70
|
+
ref={menuBtnRef}
|
|
71
|
+
>
|
|
72
|
+
<Tab
|
|
73
|
+
{...props?.tab}
|
|
74
|
+
size={size}
|
|
75
|
+
ref={reference}
|
|
76
|
+
onClick={(e) => {
|
|
77
|
+
e.stopPropagation();
|
|
78
|
+
onOpen();
|
|
79
|
+
}}
|
|
80
|
+
classNames={{
|
|
81
|
+
wrapper: css.dotTabWrapper,
|
|
82
|
+
iconTextWrap: css.dotTextWrap,
|
|
83
|
+
}}
|
|
84
|
+
/>
|
|
85
|
+
{isOpen && props?.menu && (
|
|
86
|
+
<div
|
|
87
|
+
onClickCapture={cancelNext}
|
|
88
|
+
ref={floating}
|
|
89
|
+
style={{
|
|
90
|
+
display: 'flex',
|
|
91
|
+
position: strategy,
|
|
92
|
+
top: y ?? spaceNone,
|
|
93
|
+
left: x ?? spaceNone,
|
|
94
|
+
}}
|
|
95
|
+
>
|
|
96
|
+
<Menu
|
|
97
|
+
{...props.menu}
|
|
98
|
+
onSelect={(option) => {
|
|
99
|
+
onOptionSelect && onOptionSelect(option);
|
|
100
|
+
clickAway();
|
|
101
|
+
}}
|
|
102
|
+
size={size}
|
|
103
|
+
/>
|
|
104
|
+
</div>
|
|
105
|
+
)}
|
|
106
|
+
</div>
|
|
107
|
+
)}
|
|
108
|
+
</ClickAway>
|
|
109
|
+
);
|
|
110
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
@value ( size36) from '../../styles/variables/_size.css';
|
|
2
|
+
@value ( spaceXSmall, spaceNone) from '../../styles/variables/_size.css';
|
|
3
|
+
|
|
4
|
+
.tabDropdownContainer {
|
|
5
|
+
display: flex;
|
|
6
|
+
position: relative;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.dotTabWrapper {
|
|
10
|
+
display: flex;
|
|
11
|
+
align-items: center;
|
|
12
|
+
justify-content: center;
|
|
13
|
+
box-sizing: border-box;
|
|
14
|
+
color: inherit;
|
|
15
|
+
width: size36;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.dotTextWrap {
|
|
19
|
+
padding: spaceNone spaceXSmall;
|
|
20
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.TabList = void 0;
|
|
7
|
+
var React = _interopRequireWildcard(require("react"));
|
|
8
|
+
var _size = require("../../styles/variables/_size");
|
|
9
|
+
var _space = require("../../styles/variables/_space");
|
|
10
|
+
var _classify = require("../../utils/classify");
|
|
11
|
+
var _TabDropdown = require("./TabDropdown.js");
|
|
12
|
+
var _TabListModule = _interopRequireDefault(require("./TabList.module.css"));
|
|
13
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
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); }
|
|
15
|
+
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; }
|
|
16
|
+
|
|
17
|
+
const TabList = _ref => {
|
|
18
|
+
let {
|
|
19
|
+
classNames,
|
|
20
|
+
children,
|
|
21
|
+
size,
|
|
22
|
+
onSelect,
|
|
23
|
+
selectedTab,
|
|
24
|
+
menuWidth
|
|
25
|
+
} = _ref;
|
|
26
|
+
const ref = React.useRef(null);
|
|
27
|
+
const [containerWidth, setContainerWidth] = React.useState(0);
|
|
28
|
+
const childrenWithProps = () => {
|
|
29
|
+
const childrenArray = React.Children.toArray(children);
|
|
30
|
+
const totalChildCount = childrenArray.length;
|
|
31
|
+
let tabListWidth = 0;
|
|
32
|
+
const menuOptions = [];
|
|
33
|
+
let nodes = [];
|
|
34
|
+
const tabListNodes = [];
|
|
35
|
+
for (let i = 0; i < totalChildCount; i++) {
|
|
36
|
+
const child = childrenArray[i];
|
|
37
|
+
const {
|
|
38
|
+
width = _size.size100,
|
|
39
|
+
tabId,
|
|
40
|
+
label,
|
|
41
|
+
disabled,
|
|
42
|
+
iconName,
|
|
43
|
+
iconType
|
|
44
|
+
} = child.props;
|
|
45
|
+
const widthInt = parseInt(width);
|
|
46
|
+
tabListWidth = tabListWidth + widthInt;
|
|
47
|
+
if (tabListWidth < containerWidth || i === 0) {
|
|
48
|
+
const childOnSelect = params => {
|
|
49
|
+
onSelect && onSelect(params); // call the tab level onSelect
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
tabListNodes.push( /*#__PURE__*/React.cloneElement(child, {
|
|
53
|
+
size,
|
|
54
|
+
onSelect: childOnSelect,
|
|
55
|
+
selectedTab
|
|
56
|
+
}));
|
|
57
|
+
} else {
|
|
58
|
+
menuOptions.push({
|
|
59
|
+
key: tabId,
|
|
60
|
+
label,
|
|
61
|
+
disabled,
|
|
62
|
+
iconLeft: iconName,
|
|
63
|
+
iconLeftType: iconType
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const menuOnSelect = _ref2 => {
|
|
68
|
+
let {
|
|
69
|
+
key,
|
|
70
|
+
label
|
|
71
|
+
} = _ref2;
|
|
72
|
+
onSelect && onSelect({
|
|
73
|
+
tabId: key,
|
|
74
|
+
label
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
const selectedOption = {
|
|
78
|
+
key: selectedTab?.tabId,
|
|
79
|
+
label: selectedTab?.label || ''
|
|
80
|
+
};
|
|
81
|
+
const isMenuOptionSelected = (() => {
|
|
82
|
+
for (let i = 0; i < menuOptions.length; i++) {
|
|
83
|
+
if (menuOptions[i].key === selectedTab?.tabId) {
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return false;
|
|
88
|
+
})();
|
|
89
|
+
const tabDropDownNode = menuOptions.length ? /*#__PURE__*/React.createElement(_TabDropdown.TabDropdown, {
|
|
90
|
+
size: size,
|
|
91
|
+
onOptionSelect: menuOnSelect,
|
|
92
|
+
props: {
|
|
93
|
+
tab: {
|
|
94
|
+
label: '...',
|
|
95
|
+
tabId: 'tab-dropdown',
|
|
96
|
+
selectedTab: {
|
|
97
|
+
tabId: isMenuOptionSelected ? 'tab-dropdown' : ''
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
menu: {
|
|
101
|
+
isFluid: false,
|
|
102
|
+
menuDisabled: false,
|
|
103
|
+
options: menuOptions,
|
|
104
|
+
selectedOption,
|
|
105
|
+
width: menuWidth
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}) : null;
|
|
109
|
+
nodes = [...tabListNodes, tabDropDownNode];
|
|
110
|
+
return nodes;
|
|
111
|
+
};
|
|
112
|
+
React.useLayoutEffect(() => {
|
|
113
|
+
if (ref.current && ref.current.offsetWidth) {
|
|
114
|
+
const availableContainerWidth = ref.current.offsetWidth - (parseInt(_size.size36) + parseInt(_space.spaceMedium));
|
|
115
|
+
setContainerWidth(availableContainerWidth);
|
|
116
|
+
}
|
|
117
|
+
}, [ref.current]);
|
|
118
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
119
|
+
ref: ref,
|
|
120
|
+
"data-testid": "Tabs",
|
|
121
|
+
className: (0, _classify.classify)(_TabListModule.default.tabsContainer, {
|
|
122
|
+
[_TabListModule.default.mediumSize]: size === 'medium',
|
|
123
|
+
[_TabListModule.default.smallSize]: size === 'small'
|
|
124
|
+
}, classNames?.wrapper)
|
|
125
|
+
}, containerWidth ? childrenWithProps() : null);
|
|
126
|
+
};
|
|
127
|
+
exports.TabList = TabList;
|