refactor: button.vue to composition api

Disabled require-default-prop for the to prop since it's only used when
link is true.

use null as default for props.to

FoundKeyGang/FoundKey#79
This commit is contained in:
Norm 2022-08-19 23:55:26 -04:00 committed by Johann150
parent 6fde66df1a
commit 7621e5461f
Signed by untrusted user: Johann150
GPG key ID: 9EE6577A2A06F8F1

View file

@ -1,18 +1,6 @@
<template> <template>
<button
v-if="!link" class="bghgjjyj _button"
:class="{ inline, primary, gradate, danger, rounded, full }"
:type="type"
@click="$emit('click', $event)"
@mousedown="onMousedown"
>
<div ref="ripples" class="ripples"></div>
<div class="content">
<slot></slot>
</div>
</button>
<MkA <MkA
v-else class="bghgjjyj _button" v-if="link && to" class="bghgjjyj _button"
:class="{ inline, primary, gradate, danger, rounded, full }" :class="{ inline, primary, gradate, danger, rounded, full }"
:to="to" :to="to"
@mousedown="onMousedown" @mousedown="onMousedown"
@ -22,116 +10,109 @@
<slot></slot> <slot></slot>
</div> </div>
</MkA> </MkA>
<button
v-else ref="button"
class="bghgjjyj _button"
:class="{ inline, primary, gradate, danger, rounded, full }"
:type="type"
@click="emit('click', $event)"
@mousedown="onMousedown"
>
<div ref="ripples" class="ripples"></div>
<div class="content">
<slot></slot>
</div>
</button>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent } from 'vue'; import { onMounted, nextTick } from 'vue';
export default defineComponent({ const props = withDefaults(defineProps<{
props: { type?: 'button' | 'submit' | 'reset' | undefined;
type: { primary?: boolean;
type: String, gradate?: boolean;
required: false, rounded?: boolean;
}, inline?: boolean;
primary: { link?: boolean;
type: Boolean, to?: string | null;
required: false, autofocus?: boolean;
default: false, wait?: boolean;
}, danger?: boolean;
gradate: { full?: boolean;
type: Boolean, }>(), {
required: false, type: 'button',
default: false, primary: false,
}, gradate: false,
rounded: { rounded: false,
type: Boolean, inline: false,
required: false, to: null,
default: false, link: false,
}, autofocus: false,
inline: { wait: false,
type: Boolean, danger: false,
required: false, full: false,
default: false,
},
link: {
type: Boolean,
required: false,
default: false,
},
to: {
type: String,
required: false,
},
autofocus: {
type: Boolean,
required: false,
default: false,
},
wait: {
type: Boolean,
required: false,
default: false,
},
danger: {
type: Boolean,
required: false,
default: false,
},
full: {
type: Boolean,
required: false,
default: false,
},
},
emits: ['click'],
mounted() {
if (this.autofocus) {
this.$nextTick(() => {
this.$el.focus();
});
}
},
methods: {
onMousedown(evt: MouseEvent) {
function distance(p, q) {
return Math.hypot(p.x - q.x, p.y - q.y);
}
function calcCircleScale(boxW, boxH, circleCenterX, circleCenterY) {
const origin = { x: circleCenterX, y: circleCenterY };
const dist1 = distance({ x: 0, y: 0 }, origin);
const dist2 = distance({ x: boxW, y: 0 }, origin);
const dist3 = distance({ x: 0, y: boxH }, origin);
const dist4 = distance({ x: boxW, y: boxH }, origin);
return Math.max(dist1, dist2, dist3, dist4) * 2;
}
const rect = evt.target.getBoundingClientRect();
const ripple = document.createElement('div');
ripple.style.top = (evt.clientY - rect.top - 1).toString() + 'px';
ripple.style.left = (evt.clientX - rect.left - 1).toString() + 'px';
this.$refs.ripples.appendChild(ripple);
const circleCenterX = evt.clientX - rect.left;
const circleCenterY = evt.clientY - rect.top;
const scale = calcCircleScale(evt.target.clientWidth, evt.target.clientHeight, circleCenterX, circleCenterY);
window.setTimeout(() => {
ripple.style.transform = 'scale(' + (scale / 2) + ')';
}, 1);
window.setTimeout(() => {
ripple.style.transition = 'all 1s ease';
ripple.style.opacity = '0';
}, 1000);
window.setTimeout(() => {
if (this.$refs.ripples) this.$refs.ripples.removeChild(ripple);
}, 2000);
},
},
}); });
const emit = defineEmits<{
(ev: 'click', mouseEvent: MouseEvent): void;
}>();
let button: HTMLElement | null = $ref(null);
let ripples: HTMLElement | null = $ref(null);
onMounted(() => {
if (props.autofocus) {
nextTick(() => {
button?.focus();
});
}
});
type Point = {
x: number;
y: number;
};
function onMousedown(evt: MouseEvent): void {
function distance(p: Point, q: Point): number {
return Math.hypot(p.x - q.x, p.y - q.y);
}
function calcCircleScale(boxW: number, boxH: number, circleCenterX: number, circleCenterY: number): number {
const origin = { x: circleCenterX, y: circleCenterY };
const dist1 = distance({ x: 0, y: 0 }, origin);
const dist2 = distance({ x: boxW, y: 0 }, origin);
const dist3 = distance({ x: 0, y: boxH }, origin);
const dist4 = distance({ x: boxW, y: boxH }, origin);
return Math.max(dist1, dist2, dist3, dist4) * 2;
}
const targetEl = evt.target as HTMLElement;
const rect = targetEl.getBoundingClientRect();
const ripple = document.createElement('div');
ripple.style.top = (evt.clientY - rect.top - 1).toString() + 'px';
ripple.style.left = (evt.clientX - rect.left - 1).toString() + 'px';
ripples?.appendChild(ripple);
const circleCenterX = evt.clientX - rect.left;
const circleCenterY = evt.clientY - rect.top;
const scale = calcCircleScale(targetEl.clientWidth, targetEl.clientHeight, circleCenterX, circleCenterY);
window.setTimeout(() => {
ripple.style.transform = 'scale(' + (scale / 2) + ')';
}, 1);
window.setTimeout(() => {
ripple.style.transition = 'all 1s ease';
ripple.style.opacity = '0';
}, 1000);
window.setTimeout(() => {
ripples?.removeChild(ripple);
}, 2000);
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>