refactor(frontend): use composition api
This commit is contained in:
@@ -1,118 +0,0 @@
|
||||
<template>
|
||||
<div class="">
|
||||
<div class="">
|
||||
<MkInput v-model="text">
|
||||
<template #label>Text</template>
|
||||
</MkInput>
|
||||
<MkSwitch v-model="flag">
|
||||
<span>Switch is now {{ flag ? 'on' : 'off' }}</span>
|
||||
</MkSwitch>
|
||||
<div style="margin: 32px 0;">
|
||||
<MkRadio v-model="radio" value="misskey">Misskey</MkRadio>
|
||||
<MkRadio v-model="radio" value="mastodon">Mastodon</MkRadio>
|
||||
<MkRadio v-model="radio" value="pleroma">Pleroma</MkRadio>
|
||||
</div>
|
||||
<MkButton inline>This is</MkButton>
|
||||
<MkButton inline primary>the button</MkButton>
|
||||
</div>
|
||||
<div class="" style="pointer-events: none;">
|
||||
<Mfm :text="mfm"/>
|
||||
</div>
|
||||
<div class="">
|
||||
<MkButton inline primary @click="openMenu">Open menu</MkButton>
|
||||
<MkButton inline primary @click="openDialog">Open dialog</MkButton>
|
||||
<MkButton inline primary @click="openForm">Open form</MkButton>
|
||||
<MkButton inline primary @click="openDrive">Open drive</MkButton>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import MkInput from '@/components/MkInput.vue';
|
||||
import MkSwitch from '@/components/MkSwitch.vue';
|
||||
import MkTextarea from '@/components/MkTextarea.vue';
|
||||
import MkRadio from '@/components/MkRadio.vue';
|
||||
import * as os from '@/os';
|
||||
import * as config from '@/config';
|
||||
import { $i } from '@/account';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
MkButton,
|
||||
MkInput,
|
||||
MkSwitch,
|
||||
MkTextarea,
|
||||
MkRadio,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
text: '',
|
||||
flag: true,
|
||||
radio: 'misskey',
|
||||
$i,
|
||||
mfm: `Hello world! This is an @example mention. BTW you are @${this.$i ? this.$i.username : 'guest'}.\nAlso, here is ${config.url} and [example link](${config.url}). for more details, see https://example.com.\nAs you know #misskey is open-source software.`,
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
async openDialog() {
|
||||
os.alert({
|
||||
type: 'warning',
|
||||
title: 'Oh my Aichan',
|
||||
text: 'Lorem ipsum dolor sit amet, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
|
||||
});
|
||||
},
|
||||
|
||||
async openForm() {
|
||||
os.form('Example form', {
|
||||
foo: {
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
label: 'This is a boolean property',
|
||||
},
|
||||
bar: {
|
||||
type: 'number',
|
||||
default: 300,
|
||||
label: 'This is a number property',
|
||||
},
|
||||
baz: {
|
||||
type: 'string',
|
||||
default: 'Misskey makes you happy.',
|
||||
label: 'This is a string property',
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
async openDrive() {
|
||||
os.selectDriveFile(false);
|
||||
},
|
||||
|
||||
async selectUser() {
|
||||
os.selectUser();
|
||||
},
|
||||
|
||||
async openMenu(ev) {
|
||||
os.popupMenu([{
|
||||
type: 'label',
|
||||
text: 'Fruits',
|
||||
}, {
|
||||
text: 'Create some apples',
|
||||
action: () => {},
|
||||
}, {
|
||||
text: 'Read some oranges',
|
||||
action: () => {},
|
||||
}, {
|
||||
text: 'Update some melons',
|
||||
action: () => {},
|
||||
}, null, {
|
||||
text: 'Delete some bananas',
|
||||
danger: true,
|
||||
action: () => {},
|
||||
}], ev.currentTarget ?? ev.target);
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
@@ -23,22 +23,13 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
<script lang="ts" setup>
|
||||
import { } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
def: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
grid: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
defineProps<{
|
||||
def: any[];
|
||||
grid?: boolean;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
@@ -26,153 +26,88 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, onMounted, nextTick, ref, watch, computed, toRefs } from 'vue';
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, nextTick, ref, watch, computed, toRefs, shallowRef } from 'vue';
|
||||
import { debounce } from 'throttle-debounce';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import { i18n } from '@/i18n';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
MkButton,
|
||||
},
|
||||
const props = defineProps<{
|
||||
modelValue: string | null;
|
||||
required?: boolean;
|
||||
readonly?: boolean;
|
||||
disabled?: boolean;
|
||||
pattern?: string;
|
||||
placeholder?: string;
|
||||
autofocus?: boolean;
|
||||
autocomplete?: string;
|
||||
spellcheck?: boolean;
|
||||
debounce?: boolean;
|
||||
manualSave?: boolean;
|
||||
code?: boolean;
|
||||
tall?: boolean;
|
||||
pre?: boolean;
|
||||
}>();
|
||||
|
||||
props: {
|
||||
modelValue: {
|
||||
required: true,
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
required: false,
|
||||
},
|
||||
required: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
},
|
||||
readonly: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
},
|
||||
pattern: {
|
||||
type: String,
|
||||
required: false,
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
required: false,
|
||||
},
|
||||
autofocus: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
autocomplete: {
|
||||
required: false,
|
||||
},
|
||||
spellcheck: {
|
||||
required: false,
|
||||
},
|
||||
code: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
},
|
||||
tall: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
pre: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
debounce: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
manualSave: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
const emit = defineEmits<{
|
||||
(ev: 'change', _ev: KeyboardEvent): void;
|
||||
(ev: 'keydown', _ev: KeyboardEvent): void;
|
||||
(ev: 'enter'): void;
|
||||
(ev: 'update:modelValue', value: string): void;
|
||||
}>();
|
||||
|
||||
emits: ['change', 'keydown', 'enter', 'update:modelValue'],
|
||||
const { modelValue, autofocus } = toRefs(props);
|
||||
const v = ref<string>(modelValue.value ?? '');
|
||||
const focused = ref(false);
|
||||
const changed = ref(false);
|
||||
const invalid = ref(false);
|
||||
const filled = computed(() => v.value !== '' && v.value != null);
|
||||
const inputEl = shallowRef<HTMLTextAreaElement>();
|
||||
|
||||
setup(props, context) {
|
||||
const { modelValue, autofocus } = toRefs(props);
|
||||
const v = ref(modelValue.value);
|
||||
const focused = ref(false);
|
||||
const changed = ref(false);
|
||||
const invalid = ref(false);
|
||||
const filled = computed(() => v.value !== '' && v.value != null);
|
||||
const inputEl = ref(null);
|
||||
const focus = () => inputEl.value.focus();
|
||||
const onInput = (ev) => {
|
||||
changed.value = true;
|
||||
emit('change', ev);
|
||||
};
|
||||
const onKeydown = (ev: KeyboardEvent) => {
|
||||
if (ev.isComposing || ev.key === 'Process' || ev.keyCode === 229) return;
|
||||
|
||||
const focus = () => inputEl.value.focus();
|
||||
const onInput = (ev) => {
|
||||
changed.value = true;
|
||||
context.emit('change', ev);
|
||||
};
|
||||
const onKeydown = (ev: KeyboardEvent) => {
|
||||
if (ev.isComposing || ev.key === 'Process' || ev.keyCode === 229) return;
|
||||
emit('keydown', ev);
|
||||
|
||||
context.emit('keydown', ev);
|
||||
if (ev.code === 'Enter') {
|
||||
emit('enter');
|
||||
}
|
||||
};
|
||||
|
||||
if (ev.code === 'Enter') {
|
||||
context.emit('enter');
|
||||
}
|
||||
};
|
||||
const updated = () => {
|
||||
changed.value = false;
|
||||
emit('update:modelValue', v.value ?? '');
|
||||
};
|
||||
|
||||
const updated = () => {
|
||||
changed.value = false;
|
||||
context.emit('update:modelValue', v.value);
|
||||
};
|
||||
const debouncedUpdated = debounce(1000, updated);
|
||||
|
||||
const debouncedUpdated = debounce(1000, updated);
|
||||
watch(modelValue, newValue => {
|
||||
v.value = newValue;
|
||||
});
|
||||
|
||||
watch(modelValue, newValue => {
|
||||
v.value = newValue;
|
||||
});
|
||||
watch(v, newValue => {
|
||||
if (!props.manualSave) {
|
||||
if (props.debounce) {
|
||||
debouncedUpdated();
|
||||
} else {
|
||||
updated();
|
||||
}
|
||||
}
|
||||
|
||||
watch(v, newValue => {
|
||||
if (!props.manualSave) {
|
||||
if (props.debounce) {
|
||||
debouncedUpdated();
|
||||
} else {
|
||||
updated();
|
||||
}
|
||||
}
|
||||
invalid.value = inputEl.value.validity.badInput;
|
||||
});
|
||||
|
||||
invalid.value = inputEl.value.validity.badInput;
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
if (autofocus.value) {
|
||||
focus();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
v,
|
||||
focused,
|
||||
invalid,
|
||||
changed,
|
||||
filled,
|
||||
inputEl,
|
||||
focus,
|
||||
onInput,
|
||||
onKeydown,
|
||||
updated,
|
||||
i18n,
|
||||
};
|
||||
},
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
if (autofocus.value) {
|
||||
focus();
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
Reference in New Issue
Block a user