123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 |
- import { mergeProps as _mergeProps, createVNode as _createVNode, Fragment as _Fragment } from "vue";
- // Styles
- import "./VTab.css";
- // Components
- import { makeVBtnProps, VBtn } from "../VBtn/VBtn.mjs"; // Composables
- import { useTextColor } from "../../composables/color.mjs";
- import { forwardRefs } from "../../composables/forwardRefs.mjs"; // Utilities
- import { computed, ref } from 'vue';
- import { VTabsSymbol } from "./shared.mjs";
- import { animate, genericComponent, omit, propsFactory, standardEasing, useRender } from "../../util/index.mjs"; // Types
- export const makeVTabProps = propsFactory({
- fixed: Boolean,
- sliderColor: String,
- hideSlider: Boolean,
- direction: {
- type: String,
- default: 'horizontal'
- },
- ...omit(makeVBtnProps({
- selectedClass: 'v-tab--selected',
- variant: 'text'
- }), ['active', 'block', 'flat', 'location', 'position', 'symbol'])
- }, 'VTab');
- export const VTab = genericComponent()({
- name: 'VTab',
- props: makeVTabProps(),
- setup(props, _ref) {
- let {
- slots,
- attrs
- } = _ref;
- const {
- textColorClasses: sliderColorClasses,
- textColorStyles: sliderColorStyles
- } = useTextColor(props, 'sliderColor');
- const rootEl = ref();
- const sliderEl = ref();
- const isHorizontal = computed(() => props.direction === 'horizontal');
- const isSelected = computed(() => rootEl.value?.group?.isSelected.value ?? false);
- function updateSlider(_ref2) {
- let {
- value
- } = _ref2;
- if (value) {
- const prevEl = rootEl.value?.$el.parentElement?.querySelector('.v-tab--selected .v-tab__slider');
- const nextEl = sliderEl.value;
- if (!prevEl || !nextEl) return;
- const color = getComputedStyle(prevEl).color;
- const prevBox = prevEl.getBoundingClientRect();
- const nextBox = nextEl.getBoundingClientRect();
- const xy = isHorizontal.value ? 'x' : 'y';
- const XY = isHorizontal.value ? 'X' : 'Y';
- const rightBottom = isHorizontal.value ? 'right' : 'bottom';
- const widthHeight = isHorizontal.value ? 'width' : 'height';
- const prevPos = prevBox[xy];
- const nextPos = nextBox[xy];
- const delta = prevPos > nextPos ? prevBox[rightBottom] - nextBox[rightBottom] : prevBox[xy] - nextBox[xy];
- const origin = Math.sign(delta) > 0 ? isHorizontal.value ? 'right' : 'bottom' : Math.sign(delta) < 0 ? isHorizontal.value ? 'left' : 'top' : 'center';
- const size = Math.abs(delta) + (Math.sign(delta) < 0 ? prevBox[widthHeight] : nextBox[widthHeight]);
- const scale = size / Math.max(prevBox[widthHeight], nextBox[widthHeight]) || 0;
- const initialScale = prevBox[widthHeight] / nextBox[widthHeight] || 0;
- const sigma = 1.5;
- animate(nextEl, {
- backgroundColor: [color, 'currentcolor'],
- transform: [`translate${XY}(${delta}px) scale${XY}(${initialScale})`, `translate${XY}(${delta / sigma}px) scale${XY}(${(scale - 1) / sigma + 1})`, 'none'],
- transformOrigin: Array(3).fill(origin)
- }, {
- duration: 225,
- easing: standardEasing
- });
- }
- }
- useRender(() => {
- const btnProps = VBtn.filterProps(props);
- return _createVNode(VBtn, _mergeProps({
- "symbol": VTabsSymbol,
- "ref": rootEl,
- "class": ['v-tab', props.class],
- "style": props.style,
- "tabindex": isSelected.value ? 0 : -1,
- "role": "tab",
- "aria-selected": String(isSelected.value),
- "active": false
- }, btnProps, attrs, {
- "block": props.fixed,
- "maxWidth": props.fixed ? 300 : undefined,
- "onGroup:selected": updateSlider
- }), {
- ...slots,
- default: () => _createVNode(_Fragment, null, [slots.default?.() ?? props.text, !props.hideSlider && _createVNode("div", {
- "ref": sliderEl,
- "class": ['v-tab__slider', sliderColorClasses.value],
- "style": sliderColorStyles.value
- }, null)])
- });
- });
- return forwardRefs({}, rootEl);
- }
- });
- //# sourceMappingURL=VTab.mjs.map
|