@spaced-out/ui-design-system 0.0.7 → 0.0.9
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 +97 -93
- package/design-tokens/color/app-color.json +15 -0
- 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/Button/Button.module.css +2 -0
- package/lib/components/Icon/Icon.js +6 -1
- package/lib/components/Icon/Icon.js.flow +6 -1
- package/lib/components/InContextAlert/InContextAlert.module.css +16 -0
- 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 +128 -0
- package/lib/components/TabList/TabList.js.flow +147 -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/components/Text/Text.js +26 -14
- package/lib/components/Text/Text.js.flow +14 -0
- package/lib/components/Text/index.js +6 -0
- package/lib/components/Text/index.js.flow +1 -0
- package/lib/styles/typography.module.css +6 -0
- package/lib/styles/variables/_color.css +10 -0
- package/lib/styles/variables/_color.js +11 -1
- package/lib/styles/variables/_color.js.flow +10 -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
|
@@ -4,6 +4,7 @@ import * as React from 'react';
|
|
|
4
4
|
import {classify} from '../../utils/classify';
|
|
5
5
|
import {UnstyledButton} from '../Button';
|
|
6
6
|
import {Icon} from '../Icon';
|
|
7
|
+
import type {IconType} from '../Icon/Icon.js';
|
|
7
8
|
|
|
8
9
|
import css from './Menu.module.css';
|
|
9
10
|
|
|
@@ -14,7 +15,9 @@ export type MenuOption = {
|
|
|
14
15
|
key?: string,
|
|
15
16
|
label: string,
|
|
16
17
|
iconLeft?: string,
|
|
18
|
+
iconLeftType?: IconType,
|
|
17
19
|
iconRight?: string,
|
|
20
|
+
iconRightType?: IconType,
|
|
18
21
|
disabled?: boolean,
|
|
19
22
|
};
|
|
20
23
|
|
|
@@ -50,36 +53,52 @@ export const Menu = (props: MenuProps): React.Node => {
|
|
|
50
53
|
})}
|
|
51
54
|
style={{width}}
|
|
52
55
|
>
|
|
53
|
-
{options.map(
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
56
|
+
{options.map(
|
|
57
|
+
({
|
|
58
|
+
key,
|
|
59
|
+
label,
|
|
60
|
+
iconLeft,
|
|
61
|
+
iconLeftType,
|
|
62
|
+
iconRight,
|
|
63
|
+
iconRightType,
|
|
64
|
+
disabled,
|
|
65
|
+
}) => (
|
|
66
|
+
<UnstyledButton
|
|
67
|
+
className={classify(css.option, {
|
|
68
|
+
[css.selected]: key === selectedOption?.key,
|
|
69
|
+
[css.optionSmall]: size === 'small',
|
|
70
|
+
[css.optionMedium]: size === 'medium',
|
|
71
|
+
[css.disabled]: menuDisabled || disabled,
|
|
72
|
+
[css.withIconLeft]: !!iconLeft,
|
|
73
|
+
[css.withIconRight]: !!iconRight,
|
|
74
|
+
})}
|
|
75
|
+
key={key}
|
|
76
|
+
disabled={menuDisabled || disabled}
|
|
77
|
+
onClick={() => onSelect && onSelect({key, label})}
|
|
78
|
+
autoFocus={selectedOption?.key === key}
|
|
79
|
+
>
|
|
80
|
+
{!!iconLeft && (
|
|
81
|
+
<Icon
|
|
82
|
+
name={iconLeft}
|
|
83
|
+
type={iconLeftType}
|
|
84
|
+
size="small"
|
|
85
|
+
className={css.icon}
|
|
86
|
+
/>
|
|
87
|
+
)}
|
|
71
88
|
|
|
72
|
-
|
|
89
|
+
<span className={css.optionText}>{label}</span>
|
|
73
90
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
91
|
+
{!!iconRight && (
|
|
92
|
+
<Icon
|
|
93
|
+
name={iconRight}
|
|
94
|
+
type={iconRightType}
|
|
95
|
+
size="small"
|
|
96
|
+
className={classify(css.icon, css.rightIcon)}
|
|
97
|
+
/>
|
|
98
|
+
)}
|
|
99
|
+
</UnstyledButton>
|
|
100
|
+
),
|
|
101
|
+
)}
|
|
83
102
|
</div>
|
|
84
103
|
);
|
|
85
104
|
};
|
|
@@ -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
|
+
}
|