Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
package.lib.labs.VTimePicker.VTimePickerClock.mjs Maven / Gradle / Ivy
import { createVNode as _createVNode } from "vue";
// StylesthisValue
// Styles
import "./VTimePickerClock.css";
// Composables
import { useBackgroundColor, useTextColor } from "../../composables/color.mjs"; // Utilities
import { computed, ref, toRef, watch } from 'vue';
import { genericComponent, propsFactory, useRender } from "../../util/index.mjs"; // Types
export const makeVTimePickerClockProps = propsFactory({
allowedValues: Function,
ampm: Boolean,
color: String,
disabled: Boolean,
displayedValue: null,
double: Boolean,
format: {
type: Function,
default: val => val
},
max: {
type: Number,
required: true
},
min: {
type: Number,
required: true
},
scrollable: Boolean,
readonly: Boolean,
rotate: {
type: Number,
default: 0
},
step: {
type: Number,
default: 1
},
modelValue: {
type: Number
}
}, 'VTimePickerClock');
export const VTimePickerClock = genericComponent()({
name: 'VTimePickerClock',
props: makeVTimePickerClockProps(),
emits: {
change: val => true,
input: val => true
},
setup(props, _ref) {
let {
emit
} = _ref;
const clockRef = ref(null);
const innerClockRef = ref(null);
const inputValue = ref(undefined);
const isDragging = ref(false);
const valueOnMouseDown = ref(null);
const valueOnMouseUp = ref(null);
const {
textColorClasses,
textColorStyles
} = useTextColor(toRef(props, 'color'));
const {
backgroundColorClasses,
backgroundColorStyles
} = useBackgroundColor(toRef(props, 'color'));
const count = computed(() => props.max - props.min + 1);
const roundCount = computed(() => props.double ? count.value / 2 : count.value);
const degreesPerUnit = computed(() => 360 / roundCount.value);
const degrees = computed(() => degreesPerUnit.value * Math.PI / 180);
const displayedValue = computed(() => props.modelValue == null ? props.min : props.modelValue);
const innerRadiusScale = computed(() => 0.62);
const genChildren = computed(() => {
const children = [];
for (let value = props.min; value <= props.max; value = value + props.step) {
children.push(value);
}
return children;
});
watch(() => props.modelValue, val => {
inputValue.value = val;
});
function update(value) {
if (inputValue.value !== value) {
inputValue.value = value;
}
emit('input', value);
}
function isAllowed(value) {
return !props.allowedValues || props.allowedValues(value);
}
function wheel(e) {
if (!props.scrollable || props.disabled) return;
e.preventDefault();
const delta = Math.sign(-e.deltaY || 1);
let value = displayedValue.value;
do {
value = value + delta;
value = (value - props.min + count.value) % count.value + props.min;
} while (!isAllowed(value) && value !== displayedValue.value);
if (value !== props.displayedValue) {
update(value);
}
}
function isInner(value) {
return props.double && value - props.min >= roundCount.value;
}
function handScale(value) {
return isInner(value) ? innerRadiusScale.value : 1;
}
function getPosition(value) {
const rotateRadians = props.rotate * Math.PI / 180;
return {
x: Math.sin((value - props.min) * degrees.value + rotateRadians) * handScale(value),
y: -Math.cos((value - props.min) * degrees.value + rotateRadians) * handScale(value)
};
}
function angleToValue(angle, insideClick) {
const value = (Math.round(angle / degreesPerUnit.value) + (insideClick ? roundCount.value : 0)) % count.value + props.min;
// Necessary to fix edge case when selecting left part of the value(s) at 12 o'clock
if (angle < 360 - degreesPerUnit.value / 2) return value;
return insideClick ? props.max - roundCount.value + 1 : props.min;
}
function getTransform(i) {
const {
x,
y
} = getPosition(i);
return {
left: `${50 + x * 50}%`,
top: `${50 + y * 50}%`
};
}
function euclidean(p0, p1) {
const dx = p1.x - p0.x;
const dy = p1.y - p0.y;
return Math.sqrt(dx * dx + dy * dy);
}
function angle(center, p1) {
const value = 2 * Math.atan2(p1.y - center.y - euclidean(center, p1), p1.x - center.x);
return Math.abs(value * 180 / Math.PI);
}
function setMouseDownValue(value) {
if (valueOnMouseDown.value === null) {
valueOnMouseDown.value = value;
}
valueOnMouseUp.value = value;
update(value);
}
function onDragMove(e) {
e.preventDefault();
if (!isDragging.value && e.type !== 'click' || !clockRef.value) return;
const {
width,
top,
left
} = clockRef.value?.getBoundingClientRect();
const {
width: innerWidth
} = innerClockRef.value?.getBoundingClientRect() ?? {
width: 0
};
const {
clientX,
clientY
} = 'touches' in e ? e.touches[0] : e;
const center = {
x: width / 2,
y: -width / 2
};
const coords = {
x: clientX - left,
y: top - clientY
};
const handAngle = Math.round(angle(center, coords) - props.rotate + 360) % 360;
const insideClick = props.double && euclidean(center, coords) < (innerWidth + innerWidth * innerRadiusScale.value) / 4;
const checksCount = Math.ceil(15 / degreesPerUnit.value);
let value;
for (let i = 0; i < checksCount; i++) {
value = angleToValue(handAngle + i * degreesPerUnit.value, insideClick);
if (isAllowed(value)) return setMouseDownValue(value);
value = angleToValue(handAngle - i * degreesPerUnit.value, insideClick);
if (isAllowed(value)) return setMouseDownValue(value);
}
}
function onMouseDown(e) {
if (props.disabled) return;
e.preventDefault();
window.addEventListener('mousemove', onDragMove);
window.addEventListener('touchmove', onDragMove);
window.addEventListener('mouseup', onMouseUp);
window.addEventListener('touchend', onMouseUp);
valueOnMouseDown.value = null;
valueOnMouseUp.value = null;
isDragging.value = true;
onDragMove(e);
}
function onMouseUp(e) {
e.stopPropagation();
window.removeEventListener('mousemove', onDragMove);
window.removeEventListener('touchmove', onDragMove);
window.removeEventListener('mouseup', onMouseUp);
window.removeEventListener('touchend', onMouseUp);
isDragging.value = false;
if (valueOnMouseUp.value !== null && isAllowed(valueOnMouseUp.value)) {
emit('change', valueOnMouseUp.value);
}
}
useRender(() => {
return _createVNode("div", {
"class": [{
'v-time-picker-clock': true,
'v-time-picker-clock--indeterminate': props.modelValue == null,
'v-time-picker-clock--readonly': props.readonly
}],
"onMousedown": onMouseDown,
"onTouchstart": onMouseDown,
"onWheel": wheel,
"ref": clockRef
}, [_createVNode("div", {
"class": "v-time-picker-clock__inner",
"ref": innerClockRef
}, [_createVNode("div", {
"class": [{
'v-time-picker-clock__hand': true,
'v-time-picker-clock__hand--inner': isInner(props.modelValue)
}, textColorClasses.value],
"style": [{
transform: `rotate(${props.rotate + degreesPerUnit.value * (displayedValue.value - props.min)}deg) scaleY(${handScale(displayedValue.value)})`
}, textColorStyles.value]
}, null), genChildren.value.map(value => {
const isActive = value === displayedValue.value;
return _createVNode("div", {
"class": [{
'v-time-picker-clock__item': true,
'v-time-picker-clock__item--active': isActive,
'v-time-picker-clock__item--disabled': props.disabled || !isAllowed(value)
}, isActive && backgroundColorClasses.value],
"style": [getTransform(value), isActive && backgroundColorStyles.value]
}, [_createVNode("span", null, [props.format(value)])]);
})])]);
});
}
});
//# sourceMappingURL=VTimePickerClock.mjs.map