Skip to content

Commit

Permalink
chore(lib): update Clockpicker
Browse files Browse the repository at this point in the history
- `Clockpicker` migrates to Vue 3. `Radio` is also partially updated.
  Changes sufficient to render the documentation page of `Clockpicker`
  are made. A commit of updates on the documentation page will follow
  this commit.
- In `src/components/clockpicker/Clockpicker.vue`,
    - `$slots.default` is handled as a function.
    - `slot="trigger"` in the trigger slot is removed because it does
      not make sense and the `slot` attribute is also obsoleted.
    - `.native` modifiers on event listeners are removed.
    - `disabled` is replaced with `disabledOrUndefined` that takes
      `true` or `undefined` (see `TimepickerMixin`). Because setting
      a boolean attribute `false` does not remove it on Vue 3, `null`
      or `undefined` has to be given to remove it.
- In `src/components/clockpicker/ClockpickerFace.vue`,
    - Automatic ESLint fix is applied.
- In `src/utils/TimepickerMixin.js`,
    - `v-bind` binding conforms to Vue 3,
        - `value` prop --> `modelValue`
        - `input` event --> `update:modelValue`
    - `update:modelValue` is listed in `emits`.
    - A computed value `disabledOrUndefined` that takes `true` or
      `undefined` is introduced.
    - `beforeDestroy` --> `beforeUnmount`
- In `src/components/radio/Radio.vue`,
    - `disabled` is replaced with `disabledOrUndefined` that takes
      `true` or `undefined`. Because setting a boolean attribute
      `false` does not remove it on Vue 3, `null` or `undefined` has
      to be given to remove it.
- Common,
    - Automatic ESLint fix is applied.
  • Loading branch information
kikuomax committed Jul 7, 2023
1 parent e7bbb74 commit 33e4086
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 56 deletions.
84 changes: 55 additions & 29 deletions src/components/clockpicker/Clockpicker.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,96 +4,117 @@
v-if="!isMobile || inline"
ref="dropdown"
:position="position"
:disabled="disabled"
:disabled="disabledOrUndefined"
:inline="inline"
:mobile-modal="mobileModal"
:append-to-body="appendToBody"
append-to-body-copy-parent
@active-change="onActiveChange">
@active-change="onActiveChange"
>
<template #trigger v-if="!inline">
<slot name="trigger">
<b-input
ref="input"
slot="trigger"
autocomplete="off"
:value="formatValue(computedValue)"
:placeholder="placeholder"
:size="size"
:icon="icon"
:icon-pack="iconPack"
:loading="loading"
:disabled="disabled"
:disabled="disabledOrUndefined"
:readonly="!editable"
:rounded="rounded"
v-bind="$attrs"
:use-html5-validation="useHtml5Validation"
@click.native="onInputClick"
@keyup.native.enter="toggle(true)"
@change.native="onChange($event.target.value)"
@click="onInputClick"
@keyup.enter="toggle(true)"
@change="onChange($event.target.value)"
@focus="handleOnFocus"
@blur="checkHtml5Validity()"/>
@blur="checkHtml5Validity()"
/>
</slot>
</template>
<div
class="card"
:disabled="disabled"
custom>
:disabled="disabledOrUndefined"
custom
>
<header v-if="inline" class="card-header">
<div class="b-clockpicker-header card-header-title">
<div class="b-clockpicker-time">
<span
class="b-clockpicker-btn"
:class="{ active: isSelectingHour }"
@click="isSelectingHour = true">{{ hoursDisplay }}</span>
@click="isSelectingHour = true"
>{{ hoursDisplay }}</span>
<span>{{ hourLiteral }}</span>
<span
class="b-clockpicker-btn"
:class="{ active: !isSelectingHour }"
@click="isSelectingHour = false">{{ minutesDisplay }}</span>
@click="isSelectingHour = false"
>{{ minutesDisplay }}</span>
</div>
<div v-if="!isHourFormat24" class="b-clockpicker-period">
<div
class="b-clockpicker-btn"
:class="{
active: meridienSelected === amString || meridienSelected === AM
}"
@click="onMeridienClick(amString)">{{ amString }}</div>
@click="onMeridienClick(amString)"
>
{{ amString }}
</div>
<div
class="b-clockpicker-btn"
:class="{
active: meridienSelected === pmString || meridienSelected === PM
}"
@click="onMeridienClick(pmString)">{{ pmString }}</div>
@click="onMeridienClick(pmString)"
>
{{ pmString }}
</div>
</div>
</div>
</header>
<div class="card-content">
<div
class="b-clockpicker-body"
:style="{ width: faceSize + 'px', height: faceSize + 'px' }">
:style="{ width: faceSize + 'px', height: faceSize + 'px' }"
>
<div v-if="!inline" class="b-clockpicker-time">
<div
class="b-clockpicker-btn"
:class="{ active: isSelectingHour }"
@click="isSelectingHour = true">{{ hoursLabel }}</div>
@click="isSelectingHour = true"
>
{{ hoursLabel }}
</div>
<span
class="b-clockpicker-btn"
:class="{ active: !isSelectingHour }"
@click="isSelectingHour = false">{{ minutesLabel }}</span>
@click="isSelectingHour = false"
>{{ minutesLabel }}</span>
</div>
<div v-if="!isHourFormat24 && !inline" class="b-clockpicker-period">
<div
class="b-clockpicker-btn"
:class="{
active: meridienSelected === amString || meridienSelected === AM
}"
@click="onMeridienClick(amString)">{{ amString }}</div>
@click="onMeridienClick(amString)"
>
{{ amString }}
</div>
<div
class="b-clockpicker-btn"
:class="{
active: meridienSelected === pmString || meridienSelected === PM
}"
@click="onMeridienClick(pmString)">{{ pmString }}</div>
@click="onMeridienClick(pmString)"
>
{{ pmString }}
</div>
</div>
<b-clockpicker-face
:picker-size="faceSize"
Expand All @@ -104,13 +125,15 @@
:double="isSelectingHour && isHourFormat24"
:value="isSelectingHour ? hoursSelected : minutesSelected"
@input="onClockInput"
@change="onClockChange" />
@change="onClockChange"
/>
</div>
</div>
<footer
v-if="$slots.default !== undefined && $slots.default.length"
class="b-clockpicker-footer card-footer">
<slot/>
v-if="$slots.default !== undefined && $slots.default().length"
class="b-clockpicker-footer card-footer"
>
<slot />
</footer>
</div>
</b-dropdown>
Expand All @@ -127,15 +150,16 @@
:loading="loading"
:max="formatHHMMSS(maxTime)"
:min="formatHHMMSS(minTime)"
:disabled="disabled"
:disabled="disabledOrUndefined"
:readonly="false"
v-bind="$attrs"
:use-html5-validation="useHtml5Validation"
@click.native.stop="toggle(true)"
@keyup.native.enter="toggle(true)"
@change.native="onChangeNativePicker"
@click.stop="toggle(true)"
@keyup.enter="toggle(true)"
@change="onChangeNativePicker"
@focus="handleOnFocus"
@blur="onBlur() && checkHtml5Validity()"/>
@blur="onBlur() && checkHtml5Validity()"
/>
</div>
</template>

Expand Down Expand Up @@ -215,7 +239,9 @@ export default {
minFaceValue() {
return this.isSelectingHour &&
!this.isHourFormat24 &&
this.meridienSelected === this.pmString ? 12 : 0
this.meridienSelected === this.pmString
? 12
: 0
},
maxFaceValue() {
return this.isSelectingHour
Expand Down
24 changes: 14 additions & 10 deletions src/components/clockpicker/ClockpickerFace.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,23 @@
@mousemove="onDragMove"
@touchstart="onMouseDown"
@touchend="onMouseUp"
@touchmove="onDragMove">
@touchmove="onDragMove"
>
<div
class="b-clockpicker-face-outer-ring"
ref="clock">
ref="clock"
>
<div
class="b-clockpicker-face-hand"
:style="handStyle" />
:style="handStyle"
/>
<span
v-for="(num, index) of faceNumbers"
:key="index"
class="b-clockpicker-face-number"
:class="getFaceNumberClasses(num)"
:style="{ transform: getNumberTranslate(num.value) }">
:style="{ transform: getNumberTranslate(num.value) }"
>
<span>{{ num.label }}</span>
</span>
</div>
Expand Down Expand Up @@ -103,9 +107,9 @@ export default {
handRotateAngle() {
let currentAngle = this.prevAngle
while (currentAngle < 0) currentAngle += 360
let targetAngle = this.calcHandAngle(this.displayedValue)
let degreesDiff = this.shortestDistanceDegrees(currentAngle, targetAngle)
let angle = this.prevAngle + degreesDiff
const targetAngle = this.calcHandAngle(this.displayedValue)
const degreesDiff = this.shortestDistanceDegrees(currentAngle, targetAngle)
const angle = this.prevAngle + degreesDiff
return angle
},
/**
Expand Down Expand Up @@ -151,7 +155,7 @@ export default {
},
shortestDistanceDegrees(start, stop) {
const modDiff = (stop - start) % 360
let shortestDistance = 180 - Math.abs(Math.abs(modDiff) - 180)
const shortestDistance = 180 - Math.abs(Math.abs(modDiff) - 180)
return (modDiff + 360) % 360 < 180 ? shortestDistance * 1 : shortestDistance * -1
},
/**
Expand Down Expand Up @@ -185,8 +189,8 @@ export default {
},
getFaceNumberClasses(num) {
return {
'active': num.value === this.displayedValue,
'disabled': this.isDisabled(num.value)
active: num.value === this.displayedValue,
disabled: this.isDisabled(num.value)
}
},
/**
Expand Down
14 changes: 8 additions & 6 deletions src/components/radio/Radio.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,22 @@
class="b-radio radio"
ref="label"
:class="[size, { 'is-disabled': disabled }]"
:disabled="disabled"
:disabled="disabledOrUndefined"
@click="focus"
@keydown.prevent.enter="$refs.label.click()">
@keydown.prevent.enter="$refs.label.click()"
>
<input
v-model="computedValue"
type="radio"
ref="input"
@click.stop
:disabled="disabled"
:required="required"
:disabled="disabledOrUndefined"
:required="requiredOrUndefined"
:name="name"
:value="nativeValue">
:value="nativeValue"
>
<span class="check" :class="type" />
<span class="control-label"><slot/></span>
<span class="control-label"><slot /></span>
</label>
</template>

Expand Down
27 changes: 16 additions & 11 deletions src/utils/TimepickerMixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export default {
mixins: [FormElementMixin],
inheritAttrs: false,
props: {
value: Date,
modelValue: Date,
inline: Boolean,
minTime: Date,
maxTime: Date,
Expand Down Expand Up @@ -179,9 +179,10 @@ export default {
default: false
}
},
emits: ['update:modelValue'],
data() {
return {
dateSelected: this.value,
dateSelected: this.modelValue,
hoursSelected: null,
minutesSelected: null,
secondsSelected: null,
Expand All @@ -200,7 +201,7 @@ export default {
},
set(value) {
this.dateSelected = value
this.$emit('input', this.dateSelected)
this.$emit('update:modelValue', this.dateSelected)
}
},
localeOptions() {
Expand All @@ -223,7 +224,7 @@ export default {
return this.hourFormat || (this.localeOptions.hour12 ? HOUR_FORMAT_12 : HOUR_FORMAT_24)
},
sampleTime() {
let d = this.timeCreator()
const d = this.timeCreator()
d.setHours(10)
d.setSeconds(0)
d.setMinutes(0)
Expand All @@ -232,7 +233,7 @@ export default {
},
hourLiteral() {
if (this.dtf.formatToParts && typeof this.dtf.formatToParts === 'function') {
let d = this.sampleTime
const d = this.sampleTime
const parts = this.dtf.formatToParts(d)
const literal = parts.find((part, idx) => (idx > 0 && parts[idx - 1].type === 'hour'))
if (literal) {
Expand All @@ -243,7 +244,7 @@ export default {
},
minuteLiteral() {
if (this.dtf.formatToParts && typeof this.dtf.formatToParts === 'function') {
let d = this.sampleTime
const d = this.sampleTime
const parts = this.dtf.formatToParts(d)
const literal = parts.find((part, idx) => (idx > 0 && parts[idx - 1].type === 'minute'))
if (literal) {
Expand All @@ -254,7 +255,7 @@ export default {
},
secondLiteral() {
if (this.dtf.formatToParts && typeof this.dtf.formatToParts === 'function') {
let d = this.sampleTime
const d = this.sampleTime
const parts = this.dtf.formatToParts(d)
const literal = parts.find((part, idx) => (idx > 0 && parts[idx - 1].type === 'second'))
if (literal) {
Expand All @@ -264,7 +265,7 @@ export default {
},
amString() {
if (this.dtf.formatToParts && typeof this.dtf.formatToParts === 'function') {
let d = this.sampleTime
const d = this.sampleTime
d.setHours(10)
const dayPeriod = this.dtf.formatToParts(d).find((part) => part.type === 'dayPeriod')
if (dayPeriod) {
Expand All @@ -275,7 +276,7 @@ export default {
},
pmString() {
if (this.dtf.formatToParts && typeof this.dtf.formatToParts === 'function') {
let d = this.sampleTime
const d = this.sampleTime
d.setHours(20)
const dayPeriod = this.dtf.formatToParts(d).find((part) => part.type === 'dayPeriod')
if (dayPeriod) {
Expand Down Expand Up @@ -346,6 +347,10 @@ export default {

isHourFormat24() {
return this.newHourFormat === HOUR_FORMAT_24
},

disabledOrUndefined() {
return this.disabled || undefined
}
},
watch: {
Expand All @@ -365,7 +370,7 @@ export default {
* 1. Update internal value.
* 2. If it's invalid, validate again.
*/
value: {
modelValue: {
handler(value) {
this.updateInternalState(value)
!this.isValid && this.$refs.input.checkHtml5Validity()
Expand Down Expand Up @@ -714,7 +719,7 @@ export default {
document.addEventListener('keyup', this.keyPress)
}
},
beforeDestroy() {
beforeUnmounted() {
if (typeof window !== 'undefined') {
document.removeEventListener('keyup', this.keyPress)
}
Expand Down

0 comments on commit 33e4086

Please sign in to comment.