From 9d11c29c3b4bd8fe06ad6a4bce2f3d9cd6531ffe Mon Sep 17 00:00:00 2001 From: syuilo <Syuilotan@yahoo.co.jp> Date: Fri, 22 Oct 2021 06:23:23 +0900 Subject: [PATCH] :art: --- src/client/components/form/input.vue | 2 +- src/client/components/form/select.vue | 65 ++++++++++++++++++++++--- src/client/components/form/textarea.vue | 2 +- src/client/components/ui/menu.vue | 5 ++ src/client/components/ui/popup-menu.vue | 6 ++- src/client/os.ts | 7 ++- 6 files changed, 75 insertions(+), 12 deletions(-) diff --git a/src/client/components/form/input.vue b/src/client/components/form/input.vue index d7b6f77519..591eda9ed5 100644 --- a/src/client/components/form/input.vue +++ b/src/client/components/form/input.vue @@ -33,7 +33,7 @@ <script lang="ts"> 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'; export default defineComponent({ diff --git a/src/client/components/form/select.vue b/src/client/components/form/select.vue index 257e2cc990..30ccfd312b 100644 --- a/src/client/components/form/select.vue +++ b/src/client/components/form/select.vue @@ -1,9 +1,9 @@ <template> <div class="vblkjoeq"> <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> - <select ref="inputEl" + <select class="select" ref="inputEl" v-model="v" :disabled="disabled" :required="required" @@ -25,7 +25,8 @@ <script lang="ts"> 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({ components: { @@ -81,6 +82,7 @@ export default defineComponent({ const inputEl = ref(null); const prefixEl = ref(null); const suffixEl = ref(null); + const container = ref(null); const focus = () => inputEl.value.focus(); 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 { v, focused, @@ -141,8 +184,10 @@ export default defineComponent({ inputEl, prefixEl, suffixEl, + container, focus, onInput, + onClick, updated, }; }, @@ -174,8 +219,15 @@ export default defineComponent({ > .input { $height: 42px; position: relative; + cursor: pointer; - > select { + &:hover { + > .select { + border-color: var(--inputBorderHover); + } + } + + > .select { appearance: none; -webkit-appearance: none; display: block; @@ -195,10 +247,7 @@ export default defineComponent({ box-sizing: border-box; cursor: pointer; transition: border-color 0.1s ease-out; - - &:hover { - border-color: var(--inputBorderHover); - } + pointer-events: none; } > .prefix, diff --git a/src/client/components/form/textarea.vue b/src/client/components/form/textarea.vue index 50be69f930..048e9032df 100644 --- a/src/client/components/form/textarea.vue +++ b/src/client/components/form/textarea.vue @@ -26,7 +26,7 @@ <script lang="ts"> 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'; export default defineComponent({ diff --git a/src/client/components/ui/menu.vue b/src/client/components/ui/menu.vue index da24d90170..aaef527f1a 100644 --- a/src/client/components/ui/menu.vue +++ b/src/client/components/ui/menu.vue @@ -1,5 +1,6 @@ <template> <div class="rrevdjwt" :class="{ center: align === 'center' }" + :style="{ width: width ? width + 'px' : null }" ref="items" @contextmenu.self="e => e.preventDefault()" v-hotkey="keymap" @@ -59,6 +60,10 @@ export default defineComponent({ type: String, requried: false }, + width: { + type: Number, + required: false + }, }, emits: ['close'], data() { diff --git a/src/client/components/ui/popup-menu.vue b/src/client/components/ui/popup-menu.vue index 23f7c89f3b..3ff4c658b1 100644 --- a/src/client/components/ui/popup-menu.vue +++ b/src/client/components/ui/popup-menu.vue @@ -1,6 +1,6 @@ <template> <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> </template> @@ -24,6 +24,10 @@ export default defineComponent({ type: String, required: false }, + width: { + type: Number, + required: false + }, viaKeyboard: { type: Boolean, required: false diff --git a/src/client/os.ts b/src/client/os.ts index 7ae774dd92..743d2d131f 100644 --- a/src/client/os.ts +++ b/src/client/os.ts @@ -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) => { let dispose; popup(import('@client/components/ui/popup-menu.vue'), { items, src, + width: options?.width, align: options?.align, viaKeyboard: options?.viaKeyboard }, {