nano-jsx
Version:
SSR first, lightweight 1kB JSX library.
182 lines (161 loc) • 6.05 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.Tabs = exports.Tab = void 0;
const component_js_1 = require("../component.js");
const core_js_1 = require("../core.js");
const _config_js_1 = require("./_config.js");
const _helpers_js_1 = require("./_helpers.js");
const Tab = (props) => {
const classes = [props.itemClass, props.rippleClass];
if (props.active)
classes.push('active');
const link = props.href ? { href: props.href } : {};
const a = (0, core_js_1.h)('a', { ...link }, props.children);
return (0, core_js_1.h)('li', { class: classes.join(' '), onClick: () => props.onClickHandler({ index: props.index }) }, a);
};
exports.Tab = Tab;
class Tabs extends component_js_1.Component {
constructor() {
super(...arguments);
this.active = this.props.active || 0;
}
didMount() {
const adjustLine = (item) => {
var _a;
if (!item)
return;
const first = this.items[0].getBoundingClientRect();
const active = item.getBoundingClientRect();
this.line.style.left = `${active.x - first.x}px`;
this.line.style.width = `${active.width}px`;
// disable old
(_a = document.querySelector('.tabs_item.active')) === null || _a === void 0 ? void 0 : _a.classList.remove('active');
// enable new
item.classList.add('active');
};
const scrollIntoView = (item) => {
if (!this.props.scroll)
return;
item.scrollIntoView({
behavior: 'smooth',
block: 'center',
inline: 'center'
});
};
// @ts-ignore
(0, core_js_1.tick)(() => {
adjustLine(this.items[this.active]);
scrollIntoView(this.items[this.active]);
});
for (let i = 0; i < this.items.length; i++) {
const item = this.items[i];
item.addEventListener('click', () => {
this.active = i;
// looks hacky, but works well :)
setTimeout(() => adjustLine(item), 50);
setTimeout(() => adjustLine(item), 100);
setTimeout(() => adjustLine(item), 150);
// does not work in safari
scrollIntoView(item);
});
}
}
render() {
var _a;
const ripple = (0, _config_js_1.rippleEffect)('#ffffff70', '#5902db');
const { scroll = false, children, active } = this.props;
const cssHash = (0, core_js_1.strToHash)(scroll.toString() + (children === null || children === void 0 ? void 0 : children.length) + active + ripple.class);
const styles = `
.tabs_container-${cssHash} {
background: #6204ee;
width: 100%;
height: 48px;
overflow-x: ${this.props.scroll ? 'scroll' : 'hidden'};
overflow-y: hidden;
${_config_js_1.userSelect}
}
/* Hide scrollbar for Chrome, Safari and Opera */
.tabs_container-${cssHash}::-webkit-scrollbar {
display: none;
}
/* Hide scrollbar for IE, Edge and Firefox */
.tabs_container-${cssHash} {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
.tabs_list-${cssHash} {
${!this.props.scroll ? 'display: flex; justify-content: space-evenly;' : ''}
height: 100%;
display: flex;
list-style-type: none;
margin: 0;
padding: 0;
cursor: pointer;
}
.tabs_item-${cssHash} {
${!this.props.scroll ? 'width: 100%; text-align: center;' : ''}
padding-top: 16px;
font-size: 14px;
text-transform: uppercase;
color: rgba(255, 255, 255, 0.75);
transition: color 0.2s;
}
.tabs_item-${cssHash} a {
font-size: 14px;
padding: 16px 32px;
text-decoration: none;
text-transform: uppercase;
color: rgba(255, 255, 255, 0.75);
transition: color 0.2s;
}
.tabs_item-${cssHash}.active a {
color: rgba(255, 255, 255, 1);
}
.tabs_item-${cssHash}:active {
background: #5902db;
}
/* if the primary input mechanism system of the device can hover over elements with ease, we use hover */
@media (hover: hover) {
.tabs_item-${cssHash}:hover {
background: #5902db;
}
}
${ripple.styles}
.tabs_line-${cssHash} {
border-bottom: 2px solid white;
position: relative;
top: -2px;
opacity: 0;
left: 50%;
width: 0px;
transition: left 0.5s, width 0.5s;
animation-name: tabs_line_fadein;
animation-duration: 0.25s;
animation-delay: 0.25s;
animation-fill-mode: forwards;
}
@keyframes tabs_line_fadein {
from {opacity: 0;}
to {opacity: 1;}
}
`;
(0, _helpers_js_1.addStylesToHead)(styles, cssHash);
// set the active tab
(_a = this.props.children) === null || _a === void 0 ? void 0 : _a.forEach((c, i) => {
// is active
if (i === this.active)
c.props = { ...c.props, active: true };
// add ripple class
c.props = { ...c.props, rippleClass: ripple.class, itemClass: `tabs_item-${cssHash}`, index: i };
// add click events
c.props.onClickHandler = (event) => this.props.onClick(event);
});
this.items = (0, core_js_1.render)(this.props.children);
const list = (0, core_js_1.h)('ul', { class: `tabs_list-${cssHash}` }, this.items);
this.line = (0, core_js_1.h)('div', { class: `tabs_line-${cssHash}` });
const container = (0, core_js_1.h)('div', { class: `tabs_container-${cssHash}` }, list, this.line);
return container;
}
}
exports.Tabs = Tabs;
//# sourceMappingURL=tabs.js.map
;