This commit is contained in:
syuilo 2021-10-22 06:23:23 +09:00
parent 90b62a3e95
commit 9d11c29c3b
6 changed files with 75 additions and 12 deletions

View file

@ -33,7 +33,7 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, onMounted, onUnmounted, nextTick, ref, watch, computed, toRefs } from 'vue'; import { defineComponent, onMounted, onUnmounted, nextTick, ref, watch, computed, toRefs } from 'vue';
import MkButton from '../ui/button.vue'; import MkButton from '@client/components/ui/button.vue';
import { debounce } from 'throttle-debounce'; import { debounce } from 'throttle-debounce';
export default defineComponent({ export default defineComponent({

View file

@ -1,9 +1,9 @@
<template> <template>
<div class="vblkjoeq"> <div class="vblkjoeq">
<div class="label" @click="focus"><slot name="label"></slot></div> <div class="label" @click="focus"><slot name="label"></slot></div>
<div class="input" :class="{ inline, disabled, focused }"> <div class="input" :class="{ inline, disabled, focused }" @click.prevent="onClick" ref="container">
<div class="prefix" ref="prefixEl"><slot name="prefix"></slot></div> <div class="prefix" ref="prefixEl"><slot name="prefix"></slot></div>
<select ref="inputEl" <select class="select" ref="inputEl"
v-model="v" v-model="v"
:disabled="disabled" :disabled="disabled"
:required="required" :required="required"
@ -25,7 +25,8 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, onMounted, onUnmounted, nextTick, ref, watch, computed, toRefs } from 'vue'; import { defineComponent, onMounted, onUnmounted, nextTick, ref, watch, computed, toRefs } from 'vue';
import MkButton from '../ui/button.vue'; import MkButton from '@client/components/ui/button.vue';
import * as os from '@client/os';
export default defineComponent({ export default defineComponent({
components: { components: {
@ -81,6 +82,7 @@ export default defineComponent({
const inputEl = ref(null); const inputEl = ref(null);
const prefixEl = ref(null); const prefixEl = ref(null);
const suffixEl = ref(null); const suffixEl = ref(null);
const container = ref(null);
const focus = () => inputEl.value.focus(); const focus = () => inputEl.value.focus();
const onInput = (ev) => { const onInput = (ev) => {
@ -132,6 +134,47 @@ export default defineComponent({
}); });
}); });
const onClick = (ev: MouseEvent) => {
focused.value = true;
const menu = [];
let options = context.slots.default();
for (const optionOrOptgroup of options) {
if (optionOrOptgroup.type === 'optgroup') {
const optgroup = optionOrOptgroup;
menu.push({
type: 'label',
text: optgroup.props.label,
});
for (const option of optgroup.children) {
menu.push({
text: option.children,
active: v.value === option.props.value,
action: () => {
v.value = option.props.value;
},
});
}
} else {
const option = optionOrOptgroup;
menu.push({
text: option.children,
active: v.value === option.props.value,
action: () => {
v.value = option.props.value;
},
});
}
}
os.popupMenu(menu, container.value, {
width: container.value.offsetWidth,
}).then(() => {
focused.value = false;
});
};
return { return {
v, v,
focused, focused,
@ -141,8 +184,10 @@ export default defineComponent({
inputEl, inputEl,
prefixEl, prefixEl,
suffixEl, suffixEl,
container,
focus, focus,
onInput, onInput,
onClick,
updated, updated,
}; };
}, },
@ -174,8 +219,15 @@ export default defineComponent({
> .input { > .input {
$height: 42px; $height: 42px;
position: relative; position: relative;
cursor: pointer;
> select { &:hover {
> .select {
border-color: var(--inputBorderHover);
}
}
> .select {
appearance: none; appearance: none;
-webkit-appearance: none; -webkit-appearance: none;
display: block; display: block;
@ -195,10 +247,7 @@ export default defineComponent({
box-sizing: border-box; box-sizing: border-box;
cursor: pointer; cursor: pointer;
transition: border-color 0.1s ease-out; transition: border-color 0.1s ease-out;
pointer-events: none;
&:hover {
border-color: var(--inputBorderHover);
}
} }
> .prefix, > .prefix,

View file

@ -26,7 +26,7 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, onMounted, onUnmounted, nextTick, ref, watch, computed, toRefs } from 'vue'; import { defineComponent, onMounted, onUnmounted, nextTick, ref, watch, computed, toRefs } from 'vue';
import MkButton from '../ui/button.vue'; import MkButton from '@client/components/ui/button.vue';
import { debounce } from 'throttle-debounce'; import { debounce } from 'throttle-debounce';
export default defineComponent({ export default defineComponent({

View file

@ -1,5 +1,6 @@
<template> <template>
<div class="rrevdjwt" :class="{ center: align === 'center' }" <div class="rrevdjwt" :class="{ center: align === 'center' }"
:style="{ width: width ? width + 'px' : null }"
ref="items" ref="items"
@contextmenu.self="e => e.preventDefault()" @contextmenu.self="e => e.preventDefault()"
v-hotkey="keymap" v-hotkey="keymap"
@ -59,6 +60,10 @@ export default defineComponent({
type: String, type: String,
requried: false requried: false
}, },
width: {
type: Number,
required: false
},
}, },
emits: ['close'], emits: ['close'],
data() { data() {

View file

@ -1,6 +1,6 @@
<template> <template>
<MkPopup ref="popup" :src="src" @closed="$emit('closed')"> <MkPopup ref="popup" :src="src" @closed="$emit('closed')">
<MkMenu :items="items" :align="align" @close="$refs.popup.close()" class="_popup _shadow"/> <MkMenu :items="items" :align="align" :width="width" @close="$refs.popup.close()" class="_popup _shadow"/>
</MkPopup> </MkPopup>
</template> </template>
@ -24,6 +24,10 @@ export default defineComponent({
type: String, type: String,
required: false required: false
}, },
width: {
type: Number,
required: false
},
viaKeyboard: { viaKeyboard: {
type: Boolean, type: Boolean,
required: false required: false

View file

@ -372,12 +372,17 @@ export async function openEmojiPicker(src?: HTMLElement, opts, initialTextarea:
}); });
} }
export function popupMenu(items: any[] | Ref<any[]>, src?: HTMLElement, options?: { align?: string; viaKeyboard?: boolean }) { export function popupMenu(items: any[] | Ref<any[]>, src?: HTMLElement, options?: {
align?: string;
width?: number;
viaKeyboard?: boolean;
}) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let dispose; let dispose;
popup(import('@client/components/ui/popup-menu.vue'), { popup(import('@client/components/ui/popup-menu.vue'), {
items, items,
src, src,
width: options?.width,
align: options?.align, align: options?.align,
viaKeyboard: options?.viaKeyboard viaKeyboard: options?.viaKeyboard
}, { }, {