summaryrefslogtreecommitdiff
path: root/src/client/components/form/input.vue
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2021-09-30 00:50:45 +0900
committersyuilo <Syuilotan@yahoo.co.jp>2021-09-30 00:50:45 +0900
commit1ac1a968b9edd801aa13e8dae56ca378744d9e2e (patch)
tree858fc2a3f93db6590334e1056fc4a93814c8cfcc /src/client/components/form/input.vue
parentadd todo (diff)
downloadmisskey-1ac1a968b9edd801aa13e8dae56ca378744d9e2e.tar.gz
misskey-1ac1a968b9edd801aa13e8dae56ca378744d9e2e.tar.bz2
misskey-1ac1a968b9edd801aa13e8dae56ca378744d9e2e.zip
refactor components
Diffstat (limited to 'src/client/components/form/input.vue')
-rw-r--r--src/client/components/form/input.vue183
1 files changed, 103 insertions, 80 deletions
diff --git a/src/client/components/form/input.vue b/src/client/components/form/input.vue
index 942ac4dfd2..d7b6f77519 100644
--- a/src/client/components/form/input.vue
+++ b/src/client/components/form/input.vue
@@ -1,53 +1,49 @@
<template>
-<FormGroup class="_formItem">
- <template #label><slot></slot></template>
- <div class="ztzhwixg _formItem" :class="{ inline, disabled }">
- <div class="icon" ref="icon"><slot name="icon"></slot></div>
- <div class="input _formPanel">
- <div class="prefix" ref="prefixEl"><slot name="prefix"></slot></div>
- <input ref="inputEl"
- :type="type"
- v-model="v"
- :disabled="disabled"
- :required="required"
- :readonly="readonly"
- :placeholder="placeholder"
- :pattern="pattern"
- :autocomplete="autocomplete"
- :spellcheck="spellcheck"
- :step="step"
- @focus="focused = true"
- @blur="focused = false"
- @keydown="onKeydown($event)"
- @input="onInput"
- :list="id"
- >
- <datalist :id="id" v-if="datalist">
- <option v-for="data in datalist" :value="data"/>
- </datalist>
- <div class="suffix" ref="suffixEl"><slot name="suffix"></slot></div>
- </div>
+<div class="matxzzsk">
+ <div class="label" @click="focus"><slot name="label"></slot></div>
+ <div class="input" :class="{ inline, disabled, focused }">
+ <div class="prefix" ref="prefixEl"><slot name="prefix"></slot></div>
+ <input ref="inputEl"
+ :type="type"
+ v-model="v"
+ :disabled="disabled"
+ :required="required"
+ :readonly="readonly"
+ :placeholder="placeholder"
+ :pattern="pattern"
+ :autocomplete="autocomplete"
+ :spellcheck="spellcheck"
+ :step="step"
+ @focus="focused = true"
+ @blur="focused = false"
+ @keydown="onKeydown($event)"
+ @input="onInput"
+ :list="id"
+ >
+ <datalist :id="id" v-if="datalist">
+ <option v-for="data in datalist" :value="data"/>
+ </datalist>
+ <div class="suffix" ref="suffixEl"><slot name="suffix"></slot></div>
</div>
- <template #caption><slot name="desc"></slot></template>
+ <div class="caption"><slot name="caption"></slot></div>
- <FormButton v-if="manualSave && changed" @click="updated" primary><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
-</FormGroup>
+ <MkButton v-if="manualSave && changed" @click="updated" primary><i class="fas fa-save"></i> {{ $ts.save }}</MkButton>
+</div>
</template>
<script lang="ts">
import { defineComponent, onMounted, onUnmounted, nextTick, ref, watch, computed, toRefs } from 'vue';
-import './form.scss';
-import FormButton from './button.vue';
-import FormGroup from './group.vue';
+import MkButton from '../ui/button.vue';
+import { debounce } from 'throttle-debounce';
export default defineComponent({
components: {
- FormGroup,
- FormButton,
+ MkButton,
},
+
props: {
- value: {
- required: false
+ modelValue: {
+ required: true
},
type: {
type: String,
@@ -96,16 +92,23 @@ export default defineComponent({
required: false,
default: false
},
+ debounce: {
+ type: Boolean,
+ required: false,
+ default: false
+ },
manualSave: {
type: Boolean,
required: false,
default: false
},
},
- emits: ['change', 'keydown', 'enter'],
+
+ emits: ['change', 'keydown', 'enter', 'update:modelValue'],
+
setup(props, context) {
- const { value, type, autofocus } = toRefs(props);
- const v = ref(value.value);
+ const { modelValue, type, autofocus } = toRefs(props);
+ const v = ref(modelValue.value);
const id = Math.random().toString(); // TODO: uuid?
const focused = ref(false);
const changed = ref(false);
@@ -131,19 +134,25 @@ export default defineComponent({
const updated = () => {
changed.value = false;
if (type?.value === 'number') {
- context.emit('update:value', parseFloat(v.value));
+ context.emit('update:modelValue', parseFloat(v.value));
} else {
- context.emit('update:value', v.value);
+ context.emit('update:modelValue', v.value);
}
};
- watch(value, newValue => {
+ const debouncedUpdated = debounce(1000, updated);
+
+ watch(modelValue, newValue => {
v.value = newValue;
});
watch(v, newValue => {
if (!props.manualSave) {
- updated();
+ if (props.debounce) {
+ debouncedUpdated();
+ } else {
+ updated();
+ }
}
invalid.value = inputEl.value.validity.badInput;
@@ -196,59 +205,66 @@ export default defineComponent({
</script>
<style lang="scss" scoped>
-.ztzhwixg {
- position: relative;
+.matxzzsk {
+ > .label {
+ font-size: 0.85em;
+ padding: 0 0 8px 12px;
+ user-select: none;
+
+ &:empty {
+ display: none;
+ }
+ }
- > .icon {
- position: absolute;
- top: 0;
- left: 0;
- width: 24px;
- text-align: center;
- line-height: 32px;
+ > .caption {
+ font-size: 0.8em;
+ padding: 8px 0 0 12px;
+ color: var(--fgTransparentWeak);
- &:not(:empty) + .input {
- margin-left: 28px;
+ &:empty {
+ display: none;
}
}
> .input {
- $height: 48px;
+ $height: 42px;
position: relative;
> input {
+ appearance: none;
+ -webkit-appearance: none;
display: block;
height: $height;
width: 100%;
margin: 0;
- padding: 0 16px;
+ padding: 0 12px;
font: inherit;
font-weight: normal;
font-size: 1em;
- line-height: $height;
- color: var(--inputText);
- background: transparent;
- border: none;
- border-radius: 0;
+ color: var(--fg);
+ background: var(--panel);
+ border: solid 0.5px var(--inputBorder);
+ border-radius: 6px;
outline: none;
box-shadow: none;
box-sizing: border-box;
+ transition: border-color 0.1s ease-out;
- &[type='file'] {
- display: none;
+ &:hover {
+ border-color: var(--inputBorderHover);
}
}
> .prefix,
> .suffix {
- display: block;
+ display: flex;
+ align-items: center;
position: absolute;
z-index: 1;
top: 0;
- padding: 0 16px;
+ padding: 0 12px;
font-size: 1em;
- line-height: $height;
- color: var(--inputLabel);
+ height: $height;
pointer-events: none;
&:empty {
@@ -267,25 +283,32 @@ export default defineComponent({
> .prefix {
left: 0;
- padding-right: 8px;
+ padding-right: 6px;
}
> .suffix {
right: 0;
- padding-left: 8px;
+ padding-left: 6px;
}
- }
- &.inline {
- display: inline-block;
- margin: 0;
- }
+ &.inline {
+ display: inline-block;
+ margin: 0;
+ }
+
+ &.focused {
+ > input {
+ border-color: var(--accent);
+ //box-shadow: 0 0 0 4px var(--focus);
+ }
+ }
- &.disabled {
- opacity: 0.7;
+ &.disabled {
+ opacity: 0.7;
- &, * {
- cursor: not-allowed !important;
+ &, * {
+ cursor: not-allowed !important;
+ }
}
}
}