This commit is contained in:
darenhsu
2022-07-17 13:16:16 +08:00
parent 84759556ff
commit befd344ab0
28070 changed files with 4008428 additions and 1 deletions
+10
View File
@@ -0,0 +1,10 @@
var SelectingTimes;
(function (SelectingTimes) {
SelectingTimes[SelectingTimes["Hour"] = 1] = "Hour";
SelectingTimes[SelectingTimes["Minute"] = 2] = "Minute";
SelectingTimes[SelectingTimes["Second"] = 3] = "Second";
})(SelectingTimes || (SelectingTimes = {}));
export { SelectingTimes };
//# sourceMappingURL=SelectingTimes.js.map
@@ -0,0 +1 @@
{"version":3,"sources":["../../../src/components/VTimePicker/SelectingTimes.ts"],"names":[],"mappings":"AAAA,IAAK,cAAL;;AAAA,CAAA,UAAK,cAAL,EAAmB;AACjB,EAAA,cAAA,CAAA,cAAA,CAAA,MAAA,CAAA,GAAA,CAAA,CAAA,GAAA,MAAA;AACA,EAAA,cAAA,CAAA,cAAA,CAAA,QAAA,CAAA,GAAA,CAAA,CAAA,GAAA,QAAA;AACA,EAAA,cAAA,CAAA,cAAA,CAAA,QAAA,CAAA,GAAA,CAAA,CAAA,GAAA,QAAA;AACD,CAJD,EAAK,cAAc,KAAd,cAAc,GAAA,EAAA,CAAnB;;AAMA,SAAS,cAAT","sourcesContent":["enum SelectingTimes {\n Hour = 1,\n Minute = 2,\n Second = 3\n}\n\nexport { SelectingTimes }\n"],"sourceRoot":"","file":"SelectingTimes.js"}
+334
View File
@@ -0,0 +1,334 @@
// Components
import VTimePickerTitle from './VTimePickerTitle';
import VTimePickerClock from './VTimePickerClock'; // Mixins
import Picker from '../../mixins/picker';
import PickerButton from '../../mixins/picker-button'; // Utils
import { createRange } from '../../util/helpers';
import pad from '../VDatePicker/util/pad';
import mixins from '../../util/mixins';
import { SelectingTimes } from './SelectingTimes';
const rangeHours24 = createRange(24);
const rangeHours12am = createRange(12);
const rangeHours12pm = rangeHours12am.map(v => v + 12);
const range60 = createRange(60);
const selectingNames = {
1: 'hour',
2: 'minute',
3: 'second'
};
export { SelectingTimes };
export default mixins(Picker, PickerButton
/* @vue/component */
).extend({
name: 'v-time-picker',
props: {
allowedHours: [Function, Array],
allowedMinutes: [Function, Array],
allowedSeconds: [Function, Array],
disabled: Boolean,
format: {
type: String,
default: 'ampm',
validator(val) {
return ['ampm', '24hr'].includes(val);
}
},
min: String,
max: String,
readonly: Boolean,
scrollable: Boolean,
useSeconds: Boolean,
value: null,
ampmInTitle: Boolean
},
data() {
return {
inputHour: null,
inputMinute: null,
inputSecond: null,
lazyInputHour: null,
lazyInputMinute: null,
lazyInputSecond: null,
period: 'am',
selecting: SelectingTimes.Hour
};
},
computed: {
selectingHour: {
get() {
return this.selecting === SelectingTimes.Hour;
},
set(v) {
this.selecting = SelectingTimes.Hour;
}
},
selectingMinute: {
get() {
return this.selecting === SelectingTimes.Minute;
},
set(v) {
this.selecting = SelectingTimes.Minute;
}
},
selectingSecond: {
get() {
return this.selecting === SelectingTimes.Second;
},
set(v) {
this.selecting = SelectingTimes.Second;
}
},
isAllowedHourCb() {
let cb;
if (this.allowedHours instanceof Array) {
cb = val => this.allowedHours.includes(val);
} else {
cb = this.allowedHours;
}
if (!this.min && !this.max) return cb;
const minHour = this.min ? Number(this.min.split(':')[0]) : 0;
const maxHour = this.max ? Number(this.max.split(':')[0]) : 23;
return val => {
return val >= minHour * 1 && val <= maxHour * 1 && (!cb || cb(val));
};
},
isAllowedMinuteCb() {
let cb;
const isHourAllowed = !this.isAllowedHourCb || this.inputHour === null || this.isAllowedHourCb(this.inputHour);
if (this.allowedMinutes instanceof Array) {
cb = val => this.allowedMinutes.includes(val);
} else {
cb = this.allowedMinutes;
}
if (!this.min && !this.max) {
return isHourAllowed ? cb : () => false;
}
const [minHour, minMinute] = this.min ? this.min.split(':').map(Number) : [0, 0];
const [maxHour, maxMinute] = this.max ? this.max.split(':').map(Number) : [23, 59];
const minTime = minHour * 60 + minMinute * 1;
const maxTime = maxHour * 60 + maxMinute * 1;
return val => {
const time = 60 * this.inputHour + val;
return time >= minTime && time <= maxTime && isHourAllowed && (!cb || cb(val));
};
},
isAllowedSecondCb() {
let cb;
const isHourAllowed = !this.isAllowedHourCb || this.inputHour === null || this.isAllowedHourCb(this.inputHour);
const isMinuteAllowed = isHourAllowed && (!this.isAllowedMinuteCb || this.inputMinute === null || this.isAllowedMinuteCb(this.inputMinute));
if (this.allowedSeconds instanceof Array) {
cb = val => this.allowedSeconds.includes(val);
} else {
cb = this.allowedSeconds;
}
if (!this.min && !this.max) {
return isMinuteAllowed ? cb : () => false;
}
const [minHour, minMinute, minSecond] = this.min ? this.min.split(':').map(Number) : [0, 0, 0];
const [maxHour, maxMinute, maxSecond] = this.max ? this.max.split(':').map(Number) : [23, 59, 59];
const minTime = minHour * 3600 + minMinute * 60 + (minSecond || 0) * 1;
const maxTime = maxHour * 3600 + maxMinute * 60 + (maxSecond || 0) * 1;
return val => {
const time = 3600 * this.inputHour + 60 * this.inputMinute + val;
return time >= minTime && time <= maxTime && isMinuteAllowed && (!cb || cb(val));
};
},
isAmPm() {
return this.format === 'ampm';
}
},
watch: {
value: 'setInputData'
},
mounted() {
this.setInputData(this.value);
this.$on('update:period', this.setPeriod);
},
methods: {
genValue() {
if (this.inputHour != null && this.inputMinute != null && (!this.useSeconds || this.inputSecond != null)) {
return `${pad(this.inputHour)}:${pad(this.inputMinute)}` + (this.useSeconds ? `:${pad(this.inputSecond)}` : '');
}
return null;
},
emitValue() {
const value = this.genValue();
if (value !== null) this.$emit('input', value);
},
setPeriod(period) {
this.period = period;
if (this.inputHour != null) {
const newHour = this.inputHour + (period === 'am' ? -12 : 12);
this.inputHour = this.firstAllowed('hour', newHour);
this.emitValue();
}
},
setInputData(value) {
if (value == null || value === '') {
this.inputHour = null;
this.inputMinute = null;
this.inputSecond = null;
} else if (value instanceof Date) {
this.inputHour = value.getHours();
this.inputMinute = value.getMinutes();
this.inputSecond = value.getSeconds();
} else {
const [, hour, minute,, second, period] = value.trim().toLowerCase().match(/^(\d+):(\d+)(:(\d+))?([ap]m)?$/) || new Array(6);
this.inputHour = period ? this.convert12to24(parseInt(hour, 10), period) : parseInt(hour, 10);
this.inputMinute = parseInt(minute, 10);
this.inputSecond = parseInt(second || 0, 10);
}
this.period = this.inputHour == null || this.inputHour < 12 ? 'am' : 'pm';
},
convert24to12(hour) {
return hour ? (hour - 1) % 12 + 1 : 12;
},
convert12to24(hour, period) {
return hour % 12 + (period === 'pm' ? 12 : 0);
},
onInput(value) {
if (this.selecting === SelectingTimes.Hour) {
this.inputHour = this.isAmPm ? this.convert12to24(value, this.period) : value;
} else if (this.selecting === SelectingTimes.Minute) {
this.inputMinute = value;
} else {
this.inputSecond = value;
}
this.emitValue();
},
onChange(value) {
this.$emit(`click:${selectingNames[this.selecting]}`, value);
const emitChange = this.selecting === (this.useSeconds ? SelectingTimes.Second : SelectingTimes.Minute);
if (this.selecting === SelectingTimes.Hour) {
this.selecting = SelectingTimes.Minute;
} else if (this.useSeconds && this.selecting === SelectingTimes.Minute) {
this.selecting = SelectingTimes.Second;
}
if (this.inputHour === this.lazyInputHour && this.inputMinute === this.lazyInputMinute && (!this.useSeconds || this.inputSecond === this.lazyInputSecond)) return;
const time = this.genValue();
if (time === null) return;
this.lazyInputHour = this.inputHour;
this.lazyInputMinute = this.inputMinute;
this.useSeconds && (this.lazyInputSecond = this.inputSecond);
emitChange && this.$emit('change', time);
},
firstAllowed(type, value) {
const allowedFn = type === 'hour' ? this.isAllowedHourCb : type === 'minute' ? this.isAllowedMinuteCb : this.isAllowedSecondCb;
if (!allowedFn) return value; // TODO: clean up
const range = type === 'minute' ? range60 : type === 'second' ? range60 : this.isAmPm ? value < 12 ? rangeHours12am : rangeHours12pm : rangeHours24;
const first = range.find(v => allowedFn((v + value) % range.length + range[0]));
return ((first || 0) + value) % range.length + range[0];
},
genClock() {
return this.$createElement(VTimePickerClock, {
props: {
allowedValues: this.selecting === SelectingTimes.Hour ? this.isAllowedHourCb : this.selecting === SelectingTimes.Minute ? this.isAllowedMinuteCb : this.isAllowedSecondCb,
color: this.color,
dark: this.dark,
disabled: this.disabled,
double: this.selecting === SelectingTimes.Hour && !this.isAmPm,
format: this.selecting === SelectingTimes.Hour ? this.isAmPm ? this.convert24to12 : val => val : val => pad(val, 2),
light: this.light,
max: this.selecting === SelectingTimes.Hour ? this.isAmPm && this.period === 'am' ? 11 : 23 : 59,
min: this.selecting === SelectingTimes.Hour && this.isAmPm && this.period === 'pm' ? 12 : 0,
readonly: this.readonly,
scrollable: this.scrollable,
size: Number(this.width) - (!this.fullWidth && this.landscape ? 80 : 20),
step: this.selecting === SelectingTimes.Hour ? 1 : 5,
value: this.selecting === SelectingTimes.Hour ? this.inputHour : this.selecting === SelectingTimes.Minute ? this.inputMinute : this.inputSecond
},
on: {
input: this.onInput,
change: this.onChange
},
ref: 'clock'
});
},
genClockAmPm() {
return this.$createElement('div', this.setTextColor(this.color || 'primary', {
staticClass: 'v-time-picker-clock__ampm'
}), [this.genPickerButton('period', 'am', this.$vuetify.lang.t('$vuetify.timePicker.am'), this.disabled || this.readonly), this.genPickerButton('period', 'pm', this.$vuetify.lang.t('$vuetify.timePicker.pm'), this.disabled || this.readonly)]);
},
genPickerBody() {
return this.$createElement('div', {
staticClass: 'v-time-picker-clock__container',
key: this.selecting
}, [!this.ampmInTitle && this.isAmPm && this.genClockAmPm(), this.genClock()]);
},
genPickerTitle() {
return this.$createElement(VTimePickerTitle, {
props: {
ampm: this.isAmPm,
ampmReadonly: this.isAmPm && !this.ampmInTitle,
disabled: this.disabled,
hour: this.inputHour,
minute: this.inputMinute,
second: this.inputSecond,
period: this.period,
readonly: this.readonly,
useSeconds: this.useSeconds,
selecting: this.selecting
},
on: {
'update:selecting': value => this.selecting = value,
'update:period': period => this.$emit('update:period', period)
},
ref: 'title',
slot: 'title'
});
}
},
render() {
return this.genPicker('v-picker--time');
}
});
//# sourceMappingURL=VTimePicker.js.map
File diff suppressed because one or more lines are too long
+281
View File
@@ -0,0 +1,281 @@
import "../../../src/components/VTimePicker/VTimePickerClock.sass"; // Mixins
import Colorable from '../../mixins/colorable';
import Themeable from '../../mixins/themeable'; // Types
import mixins from '../../util/mixins';
export default mixins(Colorable, Themeable
/* @vue/component */
).extend({
name: 'v-time-picker-clock',
props: {
allowedValues: Function,
ampm: Boolean,
disabled: Boolean,
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
},
value: Number
},
data() {
return {
inputValue: this.value,
isDragging: false,
valueOnMouseDown: null,
valueOnMouseUp: null
};
},
computed: {
count() {
return this.max - this.min + 1;
},
degreesPerUnit() {
return 360 / this.roundCount;
},
degrees() {
return this.degreesPerUnit * Math.PI / 180;
},
displayedValue() {
return this.value == null ? this.min : this.value;
},
innerRadiusScale() {
return 0.62;
},
roundCount() {
return this.double ? this.count / 2 : this.count;
}
},
watch: {
value(value) {
this.inputValue = value;
}
},
methods: {
wheel(e) {
e.preventDefault();
const delta = Math.sign(-e.deltaY || 1);
let value = this.displayedValue;
do {
value = value + delta;
value = (value - this.min + this.count) % this.count + this.min;
} while (!this.isAllowed(value) && value !== this.displayedValue);
if (value !== this.displayedValue) {
this.update(value);
}
},
isInner(value) {
return this.double && value - this.min >= this.roundCount;
},
handScale(value) {
return this.isInner(value) ? this.innerRadiusScale : 1;
},
isAllowed(value) {
return !this.allowedValues || this.allowedValues(value);
},
genValues() {
const children = [];
for (let value = this.min; value <= this.max; value = value + this.step) {
const color = value === this.value && (this.color || 'accent');
children.push(this.$createElement('span', this.setBackgroundColor(color, {
staticClass: 'v-time-picker-clock__item',
class: {
'v-time-picker-clock__item--active': value === this.displayedValue,
'v-time-picker-clock__item--disabled': this.disabled || !this.isAllowed(value)
},
style: this.getTransform(value),
domProps: {
innerHTML: `<span>${this.format(value)}</span>`
}
})));
}
return children;
},
genHand() {
const scale = `scaleY(${this.handScale(this.displayedValue)})`;
const angle = this.rotate + this.degreesPerUnit * (this.displayedValue - this.min);
const color = this.value != null && (this.color || 'accent');
return this.$createElement('div', this.setBackgroundColor(color, {
staticClass: 'v-time-picker-clock__hand',
class: {
'v-time-picker-clock__hand--inner': this.isInner(this.value)
},
style: {
transform: `rotate(${angle}deg) ${scale}`
}
}));
},
getTransform(i) {
const {
x,
y
} = this.getPosition(i);
return {
left: `${50 + x * 50}%`,
top: `${50 + y * 50}%`
};
},
getPosition(value) {
const rotateRadians = this.rotate * Math.PI / 180;
return {
x: Math.sin((value - this.min) * this.degrees + rotateRadians) * this.handScale(value),
y: -Math.cos((value - this.min) * this.degrees + rotateRadians) * this.handScale(value)
};
},
onMouseDown(e) {
e.preventDefault();
this.valueOnMouseDown = null;
this.valueOnMouseUp = null;
this.isDragging = true;
this.onDragMove(e);
},
onMouseUp(e) {
e.stopPropagation();
this.isDragging = false;
if (this.valueOnMouseUp !== null && this.isAllowed(this.valueOnMouseUp)) {
this.$emit('change', this.valueOnMouseUp);
}
},
onDragMove(e) {
e.preventDefault();
if (!this.isDragging && e.type !== 'click') return;
const {
width,
top,
left
} = this.$refs.clock.getBoundingClientRect();
const {
width: innerWidth
} = this.$refs.innerClock.getBoundingClientRect();
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(this.angle(center, coords) - this.rotate + 360) % 360;
const insideClick = this.double && this.euclidean(center, coords) < (innerWidth + innerWidth * this.innerRadiusScale) / 4;
const checksCount = Math.ceil(15 / this.degreesPerUnit);
let value;
for (let i = 0; i < checksCount; i++) {
value = this.angleToValue(handAngle + i * this.degreesPerUnit, insideClick);
if (this.isAllowed(value)) return this.setMouseDownValue(value);
value = this.angleToValue(handAngle - i * this.degreesPerUnit, insideClick);
if (this.isAllowed(value)) return this.setMouseDownValue(value);
}
},
angleToValue(angle, insideClick) {
const value = (Math.round(angle / this.degreesPerUnit) + (insideClick ? this.roundCount : 0)) % this.count + this.min; // Necessary to fix edge case when selecting left part of the value(s) at 12 o'clock
if (angle < 360 - this.degreesPerUnit / 2) return value;
return insideClick ? this.max - this.roundCount + 1 : this.min;
},
setMouseDownValue(value) {
if (this.valueOnMouseDown === null) {
this.valueOnMouseDown = value;
}
this.valueOnMouseUp = value;
this.update(value);
},
update(value) {
if (this.inputValue !== value) {
this.inputValue = value;
this.$emit('input', value);
}
},
euclidean(p0, p1) {
const dx = p1.x - p0.x;
const dy = p1.y - p0.y;
return Math.sqrt(dx * dx + dy * dy);
},
angle(center, p1) {
const value = 2 * Math.atan2(p1.y - center.y - this.euclidean(center, p1), p1.x - center.x);
return Math.abs(value * 180 / Math.PI);
}
},
render(h) {
const data = {
staticClass: 'v-time-picker-clock',
class: {
'v-time-picker-clock--indeterminate': this.value == null,
...this.themeClasses
},
on: this.readonly || this.disabled ? undefined : Object.assign({
mousedown: this.onMouseDown,
mouseup: this.onMouseUp,
mouseleave: e => this.isDragging && this.onMouseUp(e),
touchstart: this.onMouseDown,
touchend: this.onMouseUp,
mousemove: this.onDragMove,
touchmove: this.onDragMove
}, this.scrollable ? {
wheel: this.wheel
} : {}),
ref: 'clock'
};
return h('div', data, [h('div', {
staticClass: 'v-time-picker-clock__inner',
ref: 'innerClock'
}, [this.genHand(), this.genValues()])]);
}
});
//# sourceMappingURL=VTimePickerClock.js.map
File diff suppressed because one or more lines are too long
+70
View File
@@ -0,0 +1,70 @@
import "../../../src/components/VTimePicker/VTimePickerTitle.sass"; // Mixins
import PickerButton from '../../mixins/picker-button'; // Utils
import { pad } from '../VDatePicker/util';
import mixins from '../../util/mixins';
import { SelectingTimes } from './SelectingTimes';
export default mixins(PickerButton
/* @vue/component */
).extend({
name: 'v-time-picker-title',
props: {
ampm: Boolean,
ampmReadonly: Boolean,
disabled: Boolean,
hour: Number,
minute: Number,
second: Number,
period: {
type: String,
validator: period => period === 'am' || period === 'pm'
},
readonly: Boolean,
useSeconds: Boolean,
selecting: Number
},
methods: {
genTime() {
let hour = this.hour;
if (this.ampm) {
hour = hour ? (hour - 1) % 12 + 1 : 12;
}
const displayedHour = this.hour == null ? '--' : this.ampm ? String(hour) : pad(hour);
const displayedMinute = this.minute == null ? '--' : pad(this.minute);
const titleContent = [this.genPickerButton('selecting', SelectingTimes.Hour, displayedHour, this.disabled), this.$createElement('span', ':'), this.genPickerButton('selecting', SelectingTimes.Minute, displayedMinute, this.disabled)];
if (this.useSeconds) {
const displayedSecond = this.second == null ? '--' : pad(this.second);
titleContent.push(this.$createElement('span', ':'));
titleContent.push(this.genPickerButton('selecting', SelectingTimes.Second, displayedSecond, this.disabled));
}
return this.$createElement('div', {
class: 'v-time-picker-title__time'
}, titleContent);
},
genAmPm() {
return this.$createElement('div', {
staticClass: 'v-time-picker-title__ampm',
class: {
'v-time-picker-title__ampm--readonly': this.ampmReadonly
}
}, [!this.ampmReadonly || this.period === 'am' ? this.genPickerButton('period', 'am', this.$vuetify.lang.t('$vuetify.timePicker.am'), this.disabled || this.readonly) : null, !this.ampmReadonly || this.period === 'pm' ? this.genPickerButton('period', 'pm', this.$vuetify.lang.t('$vuetify.timePicker.pm'), this.disabled || this.readonly) : null]);
}
},
render(h) {
const children = [this.genTime()];
this.ampm && children.push(this.genAmPm());
return h('div', {
staticClass: 'v-time-picker-title'
}, children);
}
});
//# sourceMappingURL=VTimePickerTitle.js.map
File diff suppressed because one or more lines are too long
+12
View File
@@ -0,0 +1,12 @@
import VTimePicker from './VTimePicker';
import VTimePickerClock from './VTimePickerClock';
import VTimePickerTitle from './VTimePickerTitle';
export { VTimePicker, VTimePickerClock, VTimePickerTitle };
export default {
$_vuetify_subcomponents: {
VTimePicker,
VTimePickerClock,
VTimePickerTitle
}
};
//# sourceMappingURL=index.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["../../../src/components/VTimePicker/index.ts"],"names":[],"mappings":"AAAA,OAAO,WAAP,MAAwB,eAAxB;AACA,OAAO,gBAAP,MAA6B,oBAA7B;AACA,OAAO,gBAAP,MAA6B,oBAA7B;AAEA,SAAS,WAAT,EAAsB,gBAAtB,EAAwC,gBAAxC;AAEA,eAAe;AACb,EAAA,uBAAuB,EAAE;AACvB,IAAA,WADuB;AAEvB,IAAA,gBAFuB;AAGvB,IAAA;AAHuB;AADZ,CAAf","sourcesContent":["import VTimePicker from './VTimePicker'\nimport VTimePickerClock from './VTimePickerClock'\nimport VTimePickerTitle from './VTimePickerTitle'\n\nexport { VTimePicker, VTimePickerClock, VTimePickerTitle }\n\nexport default {\n $_vuetify_subcomponents: {\n VTimePicker,\n VTimePickerClock,\n VTimePickerTitle,\n },\n}\n"],"sourceRoot":"","file":"index.js"}