2025-04-21 21:50:39 -08:00
|
|
|
import React, {useEffect, useRef} from 'react';
|
2023-07-25 09:30:19 -08:00
|
|
|
|
2023-07-25 01:39:51 -08:00
|
|
|
import type {TabProps} from '../../typings/hyper';
|
2016-07-13 12:44:24 -08:00
|
|
|
|
2025-04-21 21:50:39 -08:00
|
|
|
const Tab = (props: TabProps) => {
|
2023-07-06 06:40:14 -08:00
|
|
|
const handleClick = (event: React.MouseEvent) => {
|
2016-07-21 16:33:10 -08:00
|
|
|
const isLeftClick = event.nativeEvent.which === 1;
|
|
|
|
|
|
2023-07-06 06:40:14 -08:00
|
|
|
if (isLeftClick && !props.isActive) {
|
|
|
|
|
props.onSelect();
|
2018-12-21 13:48:23 -09:00
|
|
|
}
|
2019-11-25 07:16:00 -09:00
|
|
|
};
|
2018-12-21 14:00:30 -09:00
|
|
|
|
2023-07-06 06:40:14 -08:00
|
|
|
const handleMouseUp = (event: React.MouseEvent) => {
|
2018-12-21 13:48:23 -09:00
|
|
|
const isMiddleClick = event.nativeEvent.which === 2;
|
2018-12-21 14:00:30 -09:00
|
|
|
|
2018-12-21 13:48:23 -09:00
|
|
|
if (isMiddleClick) {
|
2023-07-06 06:40:14 -08:00
|
|
|
props.onClose();
|
2016-07-21 16:33:10 -08:00
|
|
|
}
|
2019-11-25 07:16:00 -09:00
|
|
|
};
|
2016-07-21 16:33:10 -08:00
|
|
|
|
2025-04-21 21:50:39 -08:00
|
|
|
const ref = useRef<HTMLLIElement>(null);
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (props.lastFocused) {
|
|
|
|
|
ref?.current?.scrollIntoView({
|
|
|
|
|
behavior: 'smooth'
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}, [props.lastFocused]);
|
|
|
|
|
|
2023-07-06 06:40:14 -08:00
|
|
|
const {isActive, isFirst, isLast, borderColor, hasActivity} = props;
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<li
|
|
|
|
|
onClick={props.onClick}
|
|
|
|
|
style={{borderColor}}
|
|
|
|
|
className={`tab_tab ${isFirst ? 'tab_first' : ''} ${isActive ? 'tab_active' : ''} ${
|
|
|
|
|
isFirst && isActive ? 'tab_firstActive' : ''
|
|
|
|
|
} ${hasActivity ? 'tab_hasActivity' : ''}`}
|
2023-07-23 11:21:04 -08:00
|
|
|
ref={ref}
|
2023-07-06 06:40:14 -08:00
|
|
|
>
|
|
|
|
|
{props.customChildrenBefore}
|
|
|
|
|
<span
|
|
|
|
|
className={`tab_text ${isLast ? 'tab_textLast' : ''} ${isActive ? 'tab_textActive' : ''}`}
|
|
|
|
|
onClick={handleClick}
|
|
|
|
|
onMouseUp={handleMouseUp}
|
2018-03-17 04:51:36 -08:00
|
|
|
>
|
2023-07-06 06:40:14 -08:00
|
|
|
<span title={props.text} className="tab_textInner">
|
|
|
|
|
{props.text}
|
2017-09-10 05:35:10 -08:00
|
|
|
</span>
|
2023-07-06 06:40:14 -08:00
|
|
|
</span>
|
|
|
|
|
<i className="tab_icon" onClick={props.onClose}>
|
|
|
|
|
<svg className="tab_shape">
|
|
|
|
|
<use xlinkHref="./renderer/assets/icons.svg#close-tab" />
|
|
|
|
|
</svg>
|
|
|
|
|
</i>
|
|
|
|
|
{props.customChildren}
|
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
|
<style jsx>{`
|
|
|
|
|
.tab_tab {
|
|
|
|
|
color: #ccc;
|
|
|
|
|
border-color: #ccc;
|
|
|
|
|
border-bottom-width: 1px;
|
|
|
|
|
border-bottom-style: solid;
|
|
|
|
|
border-left-width: 1px;
|
|
|
|
|
border-left-style: solid;
|
|
|
|
|
list-style-type: none;
|
|
|
|
|
flex-grow: 1;
|
|
|
|
|
position: relative;
|
2025-04-21 21:50:39 -08:00
|
|
|
min-width: 10em;
|
2023-07-06 06:40:14 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tab_tab:hover {
|
|
|
|
|
color: #ccc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tab_first {
|
|
|
|
|
border-left-width: 0;
|
|
|
|
|
padding-left: 1px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tab_firstActive {
|
|
|
|
|
border-left-width: 1px;
|
|
|
|
|
padding-left: 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tab_active {
|
|
|
|
|
color: #fff;
|
|
|
|
|
border-bottom-width: 0;
|
|
|
|
|
}
|
|
|
|
|
.tab_active:hover {
|
|
|
|
|
color: #fff;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tab_hasActivity {
|
|
|
|
|
color: #50e3c2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tab_hasActivity:hover {
|
|
|
|
|
color: #50e3c2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tab_text {
|
|
|
|
|
transition: color 0.2s ease;
|
|
|
|
|
height: 34px;
|
|
|
|
|
display: block;
|
|
|
|
|
width: 100%;
|
|
|
|
|
position: relative;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tab_textInner {
|
|
|
|
|
position: absolute;
|
|
|
|
|
left: 24px;
|
|
|
|
|
right: 24px;
|
|
|
|
|
top: 0;
|
|
|
|
|
bottom: 0;
|
|
|
|
|
text-align: center;
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tab_icon {
|
2023-07-10 05:56:33 -08:00
|
|
|
transition:
|
|
|
|
|
opacity 0.2s ease,
|
|
|
|
|
color 0.2s ease,
|
|
|
|
|
transform 0.25s ease,
|
|
|
|
|
background-color 0.1s ease;
|
2023-07-06 06:40:14 -08:00
|
|
|
pointer-events: none;
|
|
|
|
|
position: absolute;
|
|
|
|
|
right: 7px;
|
|
|
|
|
top: 10px;
|
|
|
|
|
display: inline-block;
|
|
|
|
|
width: 14px;
|
|
|
|
|
height: 14px;
|
|
|
|
|
border-radius: 100%;
|
|
|
|
|
color: #e9e9e9;
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: scale(0.95);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tab_icon:hover {
|
|
|
|
|
background-color: rgba(255, 255, 255, 0.13);
|
|
|
|
|
color: #fff;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tab_icon:active {
|
|
|
|
|
background-color: rgba(255, 255, 255, 0.1);
|
|
|
|
|
color: #909090;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tab_tab:hover .tab_icon {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
transform: none;
|
|
|
|
|
pointer-events: all;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tab_shape {
|
|
|
|
|
position: absolute;
|
|
|
|
|
left: 4px;
|
|
|
|
|
top: 4px;
|
|
|
|
|
width: 6px;
|
|
|
|
|
height: 6px;
|
|
|
|
|
vertical-align: middle;
|
|
|
|
|
fill: currentColor;
|
|
|
|
|
shape-rendering: crispEdges;
|
|
|
|
|
}
|
|
|
|
|
`}</style>
|
|
|
|
|
</>
|
|
|
|
|
);
|
2025-04-21 21:50:39 -08:00
|
|
|
};
|
2023-07-23 11:21:04 -08:00
|
|
|
|
|
|
|
|
Tab.displayName = 'Tab';
|
2023-07-06 06:40:14 -08:00
|
|
|
|
|
|
|
|
export default Tab;
|