@onesy/ui-react
Version:
UI for React
426 lines (417 loc) • 20.5 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = _interopRequireDefault(require("react"));
var _utils = require("@onesy/utils");
var _styleReact = require("@onesy/style-react");
var _IconMaterialExpandLessW = _interopRequireDefault(require("@onesy/icons-material-rounded-react/IconMaterialExpandLessW100"));
var _IconMaterialExpandMoreW = _interopRequireDefault(require("@onesy/icons-material-rounded-react/IconMaterialExpandMoreW100"));
var _IconMaterialNavigateNextW = _interopRequireDefault(require("@onesy/icons-material-rounded-react/IconMaterialNavigateNextW100"));
var _IconMaterialNavigateBeforeW = _interopRequireDefault(require("@onesy/icons-material-rounded-react/IconMaterialNavigateBeforeW100"));
var _Surface = _interopRequireDefault(require("../Surface"));
var _Line = _interopRequireDefault(require("../Line"));
var _IconButton = _interopRequireDefault(require("../IconButton"));
var _Divider = _interopRequireDefault(require("../Divider"));
var _useMediaQuery = _interopRequireDefault(require("../useMediaQuery"));
var _utils2 = require("../utils");
var _jsxRuntime = require("react/jsx-runtime");
const _excluded = ["ref", "tonal", "color", "version", "value", "valueDefault", "onChange", "isActive", "activateOnFocus", "align", "justify", "orientation", "size", "initialLineUpdateTimeout", "arrows", "arrowsMobile", "fixed", "noDivider", "IconStart", "IconEnd", "IconTop", "IconBottom", "SurfaceProps", "Component", "className", "children"];
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
const useStyle = (0, _styleReact.style)(theme => ({
root: {
position: 'relative',
overflow: 'hidden',
flex: '0 0 auto'
},
size_small: {
minHeight: '39px'
},
size_regular: {
minHeight: '44px'
},
size_large: {
minHeight: '62px'
},
tabs: {
position: 'relative'
},
orientation_horizontal: {
width: '100%'
},
tabs_orientation_horizontal: {
height: '100%',
overflowX: 'auto'
},
tabs_orientation_vertical: {
width: '100%',
overflowY: 'auto'
},
arrow: {
flex: '0 0 auto',
alignSelf: 'center',
justifySelf: 'center',
transition: theme.methods.transitions.make(['opacity'], {
duration: 'xxs'
}),
'&[disabled]': {
opacity: '0'
}
},
line: {
display: 'inline-block',
position: 'absolute',
background: 'currentColor',
transition: theme.methods.transitions.make(['top', 'left', 'width']),
zIndex: '1'
},
line_version_primary_size_small_orientation_horizontal: {
height: '2px',
bottom: '0',
borderRadius: `${theme.methods.shape.radius.value(40, 'px')} ${theme.methods.shape.radius.value(40, 'px')} 0 0`
},
line_version_primary_size_regular_orientation_horizontal: {
height: '3px',
bottom: '0',
borderRadius: `${theme.methods.shape.radius.value(40, 'px')} ${theme.methods.shape.radius.value(40, 'px')} 0 0`
},
line_version_primary_size_large_orientation_horizontal: {
height: '4px',
bottom: '0',
borderRadius: `${theme.methods.shape.radius.value(40, 'px')} ${theme.methods.shape.radius.value(40, 'px')} 0 0`
},
line_version_primary_size_small_orientation_vertical: {
width: '2px',
insetInlineEnd: '0',
borderRadius: `${theme.methods.shape.radius.value(40, 'px')} 0 0 ${theme.methods.shape.radius.value(40, 'px')}`
},
line_version_primary_size_regular_orientation_vertical: {
width: '3px',
insetInlineEnd: '0',
borderRadius: `${theme.methods.shape.radius.value(40, 'px')} 0 0 ${theme.methods.shape.radius.value(40, 'px')}`
},
line_version_primary_size_large_orientation_vertical: {
width: '4px',
insetInlineEnd: '0',
borderRadius: `${theme.methods.shape.radius.value(40, 'px')} 0 0 ${theme.methods.shape.radius.value(40, 'px')}`
},
line_version_secondary_size_small_orientation_horizontal: {
height: '1px',
bottom: '0'
},
line_version_secondary_size_regular_orientation_horizontal: {
height: '2px',
bottom: '0'
},
line_version_secondary_size_large_orientation_horizontal: {
height: '3px',
bottom: '0'
},
line_version_secondary_size_small_orientation_vertical: {
width: '1px',
insetInlineEnd: '0'
},
line_version_secondary_size_regular_orientation_vertical: {
width: '2px',
insetInlineEnd: '0'
},
line_version_secondary_size_large_orientation_vertical: {
width: '3px',
insetInlineEnd: '0'
},
divider: {
position: 'absolute',
'&.onesy-Divider-root': {
margin: '0px',
background: 'currentColor',
opacity: '0.14',
zIndex: '1'
}
},
divider_orientation_horizontal: {
'&.onesy-Divider-root': {
left: '0',
right: '0',
bottom: '0'
}
},
divider_orientation_vertical: {
'&.onesy-Divider-root': {
top: '0',
bottom: '0',
insetInlineEnd: '0'
}
},
fixed: {
position: 'fixed',
top: '0',
insetInline: '0'
}
}), {
name: 'onesy-Tabs'
});
const Tabs = props_ => {
var _theme$ui, _theme$ui2, _theme$elements, _theme$elements2, _theme$elements3, _theme$elements4, _refs$tabsRoot$curren3, _refs$tabsRoot$curren4, _refs$tabsRoot$curren5, _refs$tabsRoot$curren6, _refs$tabsRoot$curren7, _refs$tabsRoot$curren8, _refs$tabsRoot$curren9;
const theme = (0, _styleReact.useOnesyTheme)();
const props = _objectSpread(_objectSpread(_objectSpread({}, theme === null || theme === void 0 || (_theme$ui = theme.ui) === null || _theme$ui === void 0 || (_theme$ui = _theme$ui.elements) === null || _theme$ui === void 0 || (_theme$ui = _theme$ui.all) === null || _theme$ui === void 0 || (_theme$ui = _theme$ui.props) === null || _theme$ui === void 0 ? void 0 : _theme$ui.default), theme === null || theme === void 0 || (_theme$ui2 = theme.ui) === null || _theme$ui2 === void 0 || (_theme$ui2 = _theme$ui2.elements) === null || _theme$ui2 === void 0 || (_theme$ui2 = _theme$ui2.onesyTabs) === null || _theme$ui2 === void 0 || (_theme$ui2 = _theme$ui2.props) === null || _theme$ui2 === void 0 ? void 0 : _theme$ui2.default), props_);
const Line = (theme === null || theme === void 0 || (_theme$elements = theme.elements) === null || _theme$elements === void 0 ? void 0 : _theme$elements.Line) || _Line.default;
const Surface = (theme === null || theme === void 0 || (_theme$elements2 = theme.elements) === null || _theme$elements2 === void 0 ? void 0 : _theme$elements2.Surface) || _Surface.default;
const IconButton = (theme === null || theme === void 0 || (_theme$elements3 = theme.elements) === null || _theme$elements3 === void 0 ? void 0 : _theme$elements3.IconButton) || _IconButton.default;
const Divider = (theme === null || theme === void 0 || (_theme$elements4 = theme.elements) === null || _theme$elements4 === void 0 ? void 0 : _theme$elements4.Divider) || _Divider.default;
const {
ref,
tonal = true,
color = 'primary',
version = 'primary',
value: value_ = 0,
valueDefault,
onChange: onChange_,
isActive,
activateOnFocus,
align = 'flex-start',
justify = 'flex-start',
orientation = 'horizontal',
size = 'regular',
initialLineUpdateTimeout = 0,
arrows,
arrowsMobile,
fixed,
noDivider,
IconStart = _IconMaterialNavigateBeforeW.default,
IconEnd = _IconMaterialNavigateNextW.default,
IconTop = _IconMaterialExpandLessW.default,
IconBottom = _IconMaterialExpandMoreW.default,
SurfaceProps,
Component = 'div',
className,
children
} = props,
other = (0, _objectWithoutProperties2.default)(props, _excluded);
const {
classes
} = useStyle();
const setMoveValue = _react.default.useState({})[1];
const [init, setInit] = _react.default.useState(false);
const [lineValues, setLineValues] = _react.default.useState({});
const [value, setValue] = _react.default.useState(valueDefault !== undefined ? valueDefault : value_);
const refs = {
root: _react.default.useRef(undefined),
tabsRoot: _react.default.useRef(undefined),
value: _react.default.useRef(undefined),
props: _react.default.useRef(undefined),
mobile: _react.default.useRef(undefined),
version: _react.default.useRef(undefined),
isActive: _react.default.useRef(undefined),
initialLineUpdateTimeout: _react.default.useRef(undefined)
};
const mobile = (0, _useMediaQuery.default)('(pointer: coarse)', {
element: refs.root.current
});
refs.value.current = value;
refs.props.current = props;
refs.mobile.current = mobile;
refs.version.current = version;
refs.isActive.current = isActive;
refs.initialLineUpdateTimeout.current = initialLineUpdateTimeout;
_react.default.useEffect(() => {
// Update lineValues value
// with the first tab
// For elements within a modal
// being transitioned, minor bug fix
setTimeout(updateLine, refs.initialLineUpdateTimeout.current);
const observerMethod = () => updateLine();
// Mutation observer
const observerMutation = new ResizeObserver(observerMethod);
observerMutation.observe(refs.tabsRoot.current);
// Update theme subscription method
const method = () => updateLine();
theme.subscriptions.update.subscribe(method);
setInit(true);
return () => {
// Unsubscribe
theme.subscriptions.update.unsubscribe(method);
observerMutation.disconnect();
};
}, []);
const onScroll = event => {
const useArrows_ = refs.props.current.arrows && (!refs.mobile.current || refs.props.current.arrowsMobile);
if (useArrows_) {
setMoveValue({
left: refs.tabsRoot.current.scrollLeft,
top: refs.tabsRoot.current.scrollTop
});
}
};
_react.default.useEffect(() => {
if (init) {
if (value_ !== refs.value.current) {
setValue(value_);
// Update lineValues value
updateLine();
}
}
}, [value_]);
const onChange = (valueItem, index) => {
// Update inner or controlled
if (!props.hasOwnProperty('value')) {
setValue(valueItem);
// Update line
updateLine();
}
if ((0, _utils.is)('function', onChange_)) onChange_(valueItem);
};
const move = (forward_ = true) => {
const forward = theme.direction === 'ltr' || orientation === 'vertical' ? forward_ : !forward_;
const rect = refs.tabsRoot.current.getBoundingClientRect();
let moveValue_;
if (orientation === 'horizontal') moveValue_ = {
left: refs.tabsRoot.current.scrollLeft + (forward ? 1 : -1) * rect.width,
behavior: 'smooth'
};else moveValue_ = {
top: refs.tabsRoot.current.scrollTop + (forward ? 1 : -1) * rect.height,
behavior: 'smooth'
};
refs.tabsRoot.current.scrollTo(moveValue_);
};
const updateLine = async () => {
var _refs$tabsRoot$curren;
await (0, _utils.wait)(40);
const valueProp = refs.value.current;
const tabs = Array.from(((_refs$tabsRoot$curren = refs.tabsRoot.current) === null || _refs$tabsRoot$curren === void 0 ? void 0 : _refs$tabsRoot$curren.querySelectorAll(`[data-onesy-tab-value]`)) || []);
const tab = tabs.find(item => (0, _utils.is)('function', refs.isActive.current) ? refs.isActive.current(valueProp, item.dataset.onesyTabValue) : String(item.dataset.onesyTabValue) === String(valueProp));
if (tab) {
var _refs$tabsRoot$curren2, _ref;
const rect_0 = {
parent: (_refs$tabsRoot$curren2 = refs.tabsRoot.current) === null || _refs$tabsRoot$curren2 === void 0 ? void 0 : _refs$tabsRoot$curren2.getBoundingClientRect(),
tab: tab.getBoundingClientRect(),
line: (_ref = refs.version.current === 'primary' ? tab.children[1] : tab) === null || _ref === void 0 ? void 0 : _ref.getBoundingClientRect()
};
// Update
if (rect_0.parent && rect_0.line && rect_0.tab) {
// Update left scroll
if (orientation === 'horizontal') {
if (rect_0.tab.x < rect_0.parent.x || rect_0.parent.x + rect_0.parent.width < rect_0.tab.x + rect_0.tab.width) {
let left = refs.tabsRoot.current.scrollLeft;
if (rect_0.tab.x < rect_0.parent.x) left += rect_0.tab.x - rect_0.parent.x;else left += rect_0.tab.x + rect_0.tab.width - (rect_0.parent.x + rect_0.parent.width);
// Update
refs.tabsRoot.current.scrollTo({
left,
behavior: 'smooth'
});
}
} else {
if (rect_0.tab.y < rect_0.parent.y || rect_0.parent.y + rect_0.parent.height < rect_0.tab.y + rect_0.tab.height) {
let top = refs.tabsRoot.current.scrollTop;
if (rect_0.tab.y < rect_0.parent.y) top += rect_0.tab.y - rect_0.parent.y;else top += rect_0.tab.y + rect_0.tab.height - (rect_0.parent.y + rect_0.parent.height);
// Update
refs.tabsRoot.current.scrollTo({
top,
behavior: 'smooth'
});
}
}
// Update lineValues value
setLineValues({
x: rect_0.line.x - rect_0.parent.x + refs.tabsRoot.current.scrollLeft,
y: rect_0.line.y - rect_0.parent.y + refs.tabsRoot.current.scrollTop,
width: rect_0.line.width,
height: rect_0.line.height
});
}
}
};
const direction = orientation === 'horizontal' ? 'row' : 'column';
const propPosition = orientation === 'horizontal' ? 'left' : 'top';
const propMain = orientation === 'horizontal' ? 'width' : 'height';
const useArrows = arrows && (!mobile || arrowsMobile);
const ArrowPre = /*#__PURE__*/(0, _jsxRuntime.jsx)(IconButton, {
color: "inherit",
onClick: () => move(false),
className: (0, _styleReact.classNames)([(0, _utils2.staticClassName)('Tabs', theme) && ['onesy-Tabs-arrow'], classes.arrow]),
disabled: ((_refs$tabsRoot$curren3 = refs.tabsRoot.current) === null || _refs$tabsRoot$curren3 === void 0 ? void 0 : _refs$tabsRoot$curren3[orientation === 'horizontal' ? 'scrollLeft' : 'scrollTop']) === 0,
children: orientation === 'horizontal' ? /*#__PURE__*/(0, _jsxRuntime.jsx)(IconStart, {}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(IconTop, {})
});
const ArrowPost = /*#__PURE__*/(0, _jsxRuntime.jsx)(IconButton, {
color: "inherit",
onClick: () => move(),
className: (0, _styleReact.classNames)([(0, _utils2.staticClassName)('Tabs', theme) && ['onesy-Tabs-arrow'], classes.arrow]),
disabled: orientation === 'horizontal' ? Math.ceil(((_refs$tabsRoot$curren4 = refs.tabsRoot.current) === null || _refs$tabsRoot$curren4 === void 0 ? void 0 : _refs$tabsRoot$curren4.clientWidth) + ((_refs$tabsRoot$curren5 = refs.tabsRoot.current) === null || _refs$tabsRoot$curren5 === void 0 ? void 0 : _refs$tabsRoot$curren5.scrollLeft)) === ((_refs$tabsRoot$curren6 = refs.tabsRoot.current) === null || _refs$tabsRoot$curren6 === void 0 ? void 0 : _refs$tabsRoot$curren6.scrollWidth) : Math.ceil(((_refs$tabsRoot$curren7 = refs.tabsRoot.current) === null || _refs$tabsRoot$curren7 === void 0 ? void 0 : _refs$tabsRoot$curren7.clientHeight) + ((_refs$tabsRoot$curren8 = refs.tabsRoot.current) === null || _refs$tabsRoot$curren8 === void 0 ? void 0 : _refs$tabsRoot$curren8.scrollTop)) === ((_refs$tabsRoot$curren9 = refs.tabsRoot.current) === null || _refs$tabsRoot$curren9 === void 0 ? void 0 : _refs$tabsRoot$curren9.scrollHeight),
children: orientation === 'horizontal' ? /*#__PURE__*/(0, _jsxRuntime.jsx)(IconEnd, {}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(IconBottom, {})
});
const TabElements = _react.default.Children.toArray(children).filter(item_0 => {
var _item_0$type;
return item_0 === null || item_0 === void 0 || (_item_0$type = item_0.type) === null || _item_0$type === void 0 || (_item_0$type = _item_0$type.displayName) === null || _item_0$type === void 0 ? void 0 : _item_0$type.endsWith('Tab');
});
const tabActive = TabElements.find((item_1, index_0) => {
const valueItem_0 = item_1.props.value !== undefined ? item_1.props.value : index_0;
return (0, _utils.is)('function', refs.isActive.current) ? refs.isActive.current(value, valueItem_0) : value === valueItem_0;
});
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(Surface, _objectSpread(_objectSpread(_objectSpread({
ref: item_2 => {
if (ref) {
if ((0, _utils.is)('function', ref)) ref(item_2);else ref.current = item_2;
}
refs.root.current = item_2;
},
tonal: tonal,
color: color,
gap: 0,
direction: direction,
align: align,
justify: justify,
role: "tablist",
"aria-orientation": orientation,
Component: Line,
AdditionalProps: {
Component
}
}, SurfaceProps), {}, {
className: (0, _styleReact.classNames)([(0, _utils2.staticClassName)('Tabs', theme) && ['onesy-Tabs-root', `onesy-Tabs-version-${version}`, `onesy-Tabs-size-${size}`], SurfaceProps === null || SurfaceProps === void 0 ? void 0 : SurfaceProps.className, className, classes.root, classes[`size_${size}`], classes[`orientation_${orientation}`], fixed && classes.fixed])
}, other), {}, {
children: [useArrows && ArrowPre, !noDivider && /*#__PURE__*/(0, _jsxRuntime.jsx)(Divider, {
tonal: tonal,
color: color,
orientation: orientation,
className: (0, _styleReact.classNames)([(0, _utils2.staticClassName)('Tabs', theme) && ['onesy-Tabs-divider'], classes.divider, classes[`divider_orientation_${orientation}`]])
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(Line, {
ref: refs.tabsRoot,
gap: 0,
direction: direction,
align: "flex-start",
justify: "flex-start",
onScroll: onScroll,
className: (0, _styleReact.classNames)([(0, _utils2.staticClassName)('Tabs', theme) && ['onesy-Tabs-tabs'], classes.tabs, classes[`tabs_orientation_${orientation}`]]),
children: [tabActive && /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
className: (0, _styleReact.classNames)([(0, _utils2.staticClassName)('Tabs', theme) && ['onesy-Tabs-line'], classes.line, classes[`line_version_${version}_size_${size}_orientation_${orientation}`], orientation === 'vertical' && theme.direction === 'rtl' && classes[`line_version_${version}_orientation_vertical_rtl`]]),
style: {
[propPosition]: orientation === 'horizontal' ? lineValues.x : lineValues.y,
[propMain]: lineValues[propMain]
}
}), TabElements.map((item_3, index_1) => {
const valueItem_1 = item_3.props.value !== undefined ? item_3.props.value : index_1;
return /*#__PURE__*/_react.default.cloneElement(item_3, {
tonal: item_3.props.tonal !== undefined ? item_3.props.tonal : tonal,
color: item_3.props.color !== undefined ? item_3.props.color : color,
version: item_3.props.version !== undefined ? item_3.props.version : version,
value: item_3.props.value !== undefined ? item_3.props.value : index_1,
size: item_3.props.size !== undefined ? item_3.props.size : size,
index: index_1,
onChange,
activateOnFocus: item_3.props.activateOnFocus !== undefined ? item_3.props.activateOnFocus : activateOnFocus,
active: (0, _utils.is)('function', refs.isActive.current) ? refs.isActive.current(value, valueItem_1) : value === valueItem_1,
onClick: event_0 => {
onChange(valueItem_1, index_1);
if ((0, _utils.is)('function', item_3.props.onClick)) item_3.props.onClick(event_0);
}
});
})]
}), useArrows && ArrowPost]
}));
};
Tabs.displayName = 'onesy-Tabs';
var _default = exports.default = Tabs;