vuetify
Version:
Vue Material Component Framework
92 lines (91 loc) • 3.34 kB
JavaScript
// Utilities
import { computed, toRef, toValue } from 'vue';
import { clamp, convertToUnit, propsFactory } from "../../util/index.js"; // Types
// Composables
export const makeChunksProps = propsFactory({
chunkCount: {
type: [Number, String],
default: null
},
chunkWidth: {
type: [Number, String],
default: null
},
chunkGap: {
type: [Number, String],
default: 4
},
variant: {
type: String,
default: undefined,
validator: v => ['split'].includes(v)
}
}, 'chunks');
export function useChunks(props, containerWidth, value, bufferValue, reversed) {
const isSplit = toRef(() => props.variant === 'split');
const chunkCount = toRef(() => isSplit.value ? 2 : Number(props.chunkCount) || 0);
const hasChunks = toRef(() => !isSplit.value && (!!chunkCount.value || !!props.chunkWidth));
const chunkWidth = computed(() => {
const containerSize = toValue(containerWidth);
if (!containerSize) return 0;
if (chunkCount.value) {
const availableWidth = containerSize - Number(props.chunkGap) * (chunkCount.value - 1);
return availableWidth / chunkCount.value;
}
return Number(props.chunkWidth);
});
const chunkGap = toRef(() => Number(props.chunkGap));
const chunksMaskStyles = computed(() => {
if (!hasChunks.value) return {};
const chunkGapPx = convertToUnit(chunkGap.value);
const chunkWidthPx = convertToUnit(chunkWidth.value);
return {
maskRepeat: 'repeat-x',
maskImage: `linear-gradient(90deg, #000, #000 ${chunkWidthPx}, transparent ${chunkWidthPx}, transparent)`,
maskSize: `calc(${chunkWidthPx} + ${chunkGapPx}) 100%`
};
});
const splitStyles = computed(() => {
if (!isSplit.value) return undefined;
const halfGap = convertToUnit(chunkGap.value / 2);
const position = toValue(reversed) ? 'right' : 'left';
const val = toValue(value);
if (val <= 0 || val >= 100) return undefined;
const buffer = toValue(bufferValue);
const split = convertToUnit(val, '%');
const hasBuffer = buffer > val && buffer < 100;
const bufferSplit = convertToUnit(buffer, '%');
return {
bar: {
width: `calc(${split} - ${halfGap})`
},
buffer: hasBuffer ? {
[position]: `calc(${split} + ${halfGap})`,
width: `calc(${bufferSplit} - ${split} - ${convertToUnit(chunkGap.value)})`
} : undefined,
background: {
[position]: `calc(${hasBuffer ? bufferSplit : split} + ${halfGap})`,
width: `calc(100% - ${hasBuffer ? bufferSplit : split} - ${halfGap})`
}
};
});
function snapValueToChunk(val) {
if (isSplit.value) return val;
const containerSize = toValue(containerWidth);
if (!containerSize) return val;
const gapRelativeSize = 100 * chunkGap.value / containerSize;
const chunkRelativeSize = 100 * (chunkWidth.value + chunkGap.value) / containerSize;
// low-effort workaround to floating-point rounding in the division
const filledChunks = Math.floor((val + gapRelativeSize) / chunkRelativeSize + 1e-9);
return clamp(filledChunks * chunkRelativeSize - gapRelativeSize / 2, 0, 100);
}
return {
hasChunks: toRef(() => hasChunks.value || isSplit.value),
isSplit,
chunkCount,
chunksMaskStyles,
splitStyles,
snapValueToChunk
};
}
//# sourceMappingURL=chunks.js.map