refactor components
This commit is contained in:
		
							parent
							
								
									0d3a36e519
								
							
						
					
					
						commit
						1ac1a968b9
					
				
					 179 changed files with 2611 additions and 2386 deletions
				
			
		|  | @ -177,6 +177,10 @@ npx ts-node ./node_modules/typeorm/cli.js migration:generate -n 変更の名前 | |||
| ### JSONのimportに気を付けよう | ||||
| TypeScriptでjsonをimportすると、tscでコンパイルするときにそのjsonファイルも一緒にdistディレクトリに吐き出されてしまう。この挙動により、意図せずファイルの書き換えが発生することがあるので、jsonをimportするときは書き換えられても良いものかどうか確認すること。書き換えされて欲しくない場合は、importで読み込むのではなく、`fs.readFileSync`などの関数を使って読み込むようにすればよい。 | ||||
| 
 | ||||
| ### コンポーネントのスタイル定義でmarginを持たせない | ||||
| コンポーネント自身がmarginを設定するのは問題の元となることはよく知られている | ||||
| marginはそのコンポーネントを使う側が設定する | ||||
| 
 | ||||
| ## その他 | ||||
| ### HTMLのクラス名で follow という単語は使わない | ||||
| 広告ブロッカーで誤ってブロックされる | ||||
|  |  | |||
|  | @ -787,6 +787,8 @@ pubSub: "Pub/Subのアカウント" | |||
| lastCommunication: "直近の通信" | ||||
| resolved: "解決済み" | ||||
| unresolved: "未解決" | ||||
| itsOn: "オンになっています" | ||||
| itsOff: "オフになっています" | ||||
| 
 | ||||
| _accountDelete: | ||||
|   accountDelete: "アカウントの削除" | ||||
|  |  | |||
|  | @ -104,7 +104,7 @@ | |||
| 		"@types/websocket": "1.0.4", | ||||
| 		"@types/ws": "7.4.7", | ||||
| 		"@typescript-eslint/parser": "4.31.2", | ||||
| 		"@vue/compiler-sfc": "3.2.13", | ||||
| 		"@vue/compiler-sfc": "3.2.19", | ||||
| 		"abort-controller": "3.0.0", | ||||
| 		"apexcharts": "3.28.3", | ||||
| 		"autobind-decorator": "2.4.0", | ||||
|  | @ -233,7 +233,7 @@ | |||
| 		"uuid": "8.3.2", | ||||
| 		"v-debounce": "0.1.2", | ||||
| 		"vanilla-tilt": "1.7.2", | ||||
| 		"vue": "3.2.13", | ||||
| 		"vue": "3.2.19", | ||||
| 		"vue-loader": "16.7.0", | ||||
| 		"vue-prism-editor": "2.0.0-alpha.2", | ||||
| 		"vue-router": "4.0.5", | ||||
|  | @ -241,7 +241,7 @@ | |||
| 		"vue-svg-loader": "0.17.0-beta.2", | ||||
| 		"vuedraggable": "4.0.1", | ||||
| 		"web-push": "3.4.5", | ||||
| 		"webpack": "5.53.0", | ||||
| 		"webpack": "5.54.0", | ||||
| 		"webpack-cli": "4.8.0", | ||||
| 		"websocket": "1.0.34", | ||||
| 		"ws": "8.2.2", | ||||
|  |  | |||
|  | @ -25,7 +25,7 @@ | |||
| <script lang="ts"> | ||||
| import { defineComponent, markRaw } from 'vue'; | ||||
| import XWindow from '@client/components/ui/window.vue'; | ||||
| import MkTextarea from '@client/components/ui/textarea.vue'; | ||||
| import MkTextarea from '@client/components/form/textarea.vue'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import * as os from '@client/os'; | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| <template> | ||||
| <button class="nrvgflfu _button" @click="toggle"> | ||||
| 	<b>{{ value ? $ts._cw.hide : $ts._cw.show }}</b> | ||||
| 	<span v-if="!value">{{ label }}</span> | ||||
| 	<b>{{ modelValue ? $ts._cw.hide : $ts._cw.show }}</b> | ||||
| 	<span v-if="!modelValue">{{ label }}</span> | ||||
| </button> | ||||
| </template> | ||||
| 
 | ||||
|  | @ -12,7 +12,7 @@ import { concat } from '../../prelude/array'; | |||
| 
 | ||||
| export default defineComponent({ | ||||
| 	props: { | ||||
| 		value: { | ||||
| 		modelValue: { | ||||
| 			type: Boolean, | ||||
| 			required: true | ||||
| 		}, | ||||
|  | @ -36,7 +36,7 @@ export default defineComponent({ | |||
| 		length, | ||||
| 
 | ||||
| 		toggle() { | ||||
| 			this.$emit('update:value', !this.value); | ||||
| 			this.$emit('update:modelValue', !this.modelValue); | ||||
| 		} | ||||
| 	} | ||||
| }); | ||||
|  |  | |||
|  | @ -21,39 +21,39 @@ export default defineComponent({ | |||
| <style lang="scss" scoped> | ||||
| .rbusrurv { | ||||
| 	// 他のCSSからも参照されるので消さないように | ||||
| 	--formXPadding: 32px; | ||||
| 	--formYPadding: 32px; | ||||
| 	--debobigegoXPadding: 32px; | ||||
| 	--debobigegoYPadding: 32px; | ||||
| 
 | ||||
| 	--formContentHMargin: 16px; | ||||
| 	--debobigegoContentHMargin: 16px; | ||||
| 
 | ||||
| 	font-size: 95%; | ||||
| 	line-height: 1.3em; | ||||
| 	background: var(--bg); | ||||
| 	padding: var(--formYPadding) var(--formXPadding); | ||||
| 	padding: var(--debobigegoYPadding) var(--debobigegoXPadding); | ||||
| 	max-width: 750px; | ||||
| 	margin: 0 auto; | ||||
| 
 | ||||
| 	&:not(.wide).max-width_400px { | ||||
| 		--formXPadding: 0px; | ||||
| 		--debobigegoXPadding: 0px; | ||||
| 
 | ||||
| 		> ::v-deep(*) { | ||||
| 			._formPanel { | ||||
| 			._debobigegoPanel { | ||||
| 				border: solid 0.5px var(--divider); | ||||
| 				border-radius: 0; | ||||
| 				border-left: none; | ||||
| 				border-right: none; | ||||
| 			} | ||||
| 
 | ||||
| 			._form_group { | ||||
| 				> *:not(._formNoConcat) { | ||||
| 					&:not(:last-child):not(._formNoConcatPrev) { | ||||
| 						&._formPanel, ._formPanel { | ||||
| 			._debobigego_group { | ||||
| 				> *:not(._debobigegoNoConcat) { | ||||
| 					&:not(:last-child):not(._debobigegoNoConcatPrev) { | ||||
| 						&._debobigegoPanel, ._debobigegoPanel { | ||||
| 							border-bottom: solid 0.5px var(--divider); | ||||
| 						} | ||||
| 					} | ||||
| 
 | ||||
| 					&:not(:first-child):not(._formNoConcatNext) { | ||||
| 						&._formPanel, ._formPanel { | ||||
| 					&:not(:first-child):not(._debobigegoNoConcatNext) { | ||||
| 						&._debobigegoPanel, ._debobigegoPanel { | ||||
| 							border-top: none; | ||||
| 						} | ||||
| 					} | ||||
|  | @ -1,7 +1,7 @@ | |||
| <template> | ||||
| <div class="yzpgjkxe _formItem"> | ||||
| 	<div class="_formLabel"><slot name="label"></slot></div> | ||||
| 	<button class="main _button _formPanel _formClickable" :class="{ center, primary, danger }"> | ||||
| <div class="yzpgjkxe _debobigegoItem"> | ||||
| 	<div class="_debobigegoLabel"><slot name="label"></slot></div> | ||||
| 	<button class="main _button _debobigegoPanel _debobigegoClickable" :class="{ center, primary, danger }"> | ||||
| 		<slot></slot> | ||||
| 		<div class="suffix"> | ||||
| 			<slot name="suffix"></slot> | ||||
|  | @ -10,13 +10,13 @@ | |||
| 			</div> | ||||
| 		</div> | ||||
| 	</button> | ||||
| 	<div class="_formCaption"><slot name="desc"></slot></div> | ||||
| 	<div class="_debobigegoCaption"><slot name="desc"></slot></div> | ||||
| </div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import './form.scss'; | ||||
| import './debobigego.scss'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	props: { | ||||
|  | @ -1,9 +1,9 @@ | |||
| ._formPanel { | ||||
| ._debobigegoPanel { | ||||
| 	background: var(--panel); | ||||
| 	border-radius: var(--radius); | ||||
| 	transition: background 0.2s ease; | ||||
| 
 | ||||
| 	&._formClickable { | ||||
| 	&._debobigegoClickable { | ||||
| 		&:hover { | ||||
| 			//background: var(--panelHighlight); | ||||
| 		} | ||||
|  | @ -15,8 +15,8 @@ | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| ._formLabel, | ||||
| ._formCaption { | ||||
| ._debobigegoLabel, | ||||
| ._debobigegoCaption { | ||||
| 	font-size: 80%; | ||||
| 	color: var(--fgTransparentWeak); | ||||
| 
 | ||||
|  | @ -25,28 +25,28 @@ | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| ._formLabel { | ||||
| ._debobigegoLabel { | ||||
| 	position: sticky; | ||||
| 	top: var(--stickyTop, 0px); | ||||
| 	z-index: 2; | ||||
| 	margin: -8px calc(var(--formXPadding) * -1) 0 calc(var(--formXPadding) * -1); | ||||
| 	padding: 8px calc(var(--formContentHMargin) + var(--formXPadding)) 8px calc(var(--formContentHMargin) + var(--formXPadding)); | ||||
| 	margin: -8px calc(var(--debobigegoXPadding) * -1) 0 calc(var(--debobigegoXPadding) * -1); | ||||
| 	padding: 8px calc(var(--debobigegoContentHMargin) + var(--debobigegoXPadding)) 8px calc(var(--debobigegoContentHMargin) + var(--debobigegoXPadding)); | ||||
| 	background: var(--X17); | ||||
| 	-webkit-backdrop-filter: var(--blur, blur(10px)); | ||||
| 	backdrop-filter: var(--blur, blur(10px)); | ||||
| } | ||||
| 
 | ||||
| ._themeChanging_ ._formLabel { | ||||
| ._themeChanging_ ._debobigegoLabel { | ||||
| 	transition: none !important; | ||||
| 	background: transparent; | ||||
| } | ||||
| 
 | ||||
| ._formCaption { | ||||
| 	padding: 8px var(--formContentHMargin) 0 var(--formContentHMargin); | ||||
| ._debobigegoCaption { | ||||
| 	padding: 8px var(--debobigegoContentHMargin) 0 var(--debobigegoContentHMargin); | ||||
| } | ||||
| 
 | ||||
| ._formItem { | ||||
| 	& + ._formItem { | ||||
| ._debobigegoItem { | ||||
| 	& + ._debobigegoItem { | ||||
| 		margin-top: 24px; | ||||
| 	} | ||||
| } | ||||
|  | @ -1,10 +1,10 @@ | |||
| <template> | ||||
| <div class="vrtktovg _formItem _formNoConcat" v-size="{ max: [500] }" v-sticky-container> | ||||
| 	<div class="_formLabel"><slot name="label"></slot></div> | ||||
| 	<div class="main _form_group" ref="child"> | ||||
| <div class="vrtktovg _debobigegoItem _debobigegoNoConcat" v-size="{ max: [500] }" v-sticky-container> | ||||
| 	<div class="_debobigegoLabel"><slot name="label"></slot></div> | ||||
| 	<div class="main _debobigego_group" ref="child"> | ||||
| 		<slot></slot> | ||||
| 	</div> | ||||
| 	<div class="_formCaption"><slot name="caption"></slot></div> | ||||
| 	<div class="_debobigegoCaption"><slot name="caption"></slot></div> | ||||
| </div> | ||||
| </template> | ||||
| 
 | ||||
|  | @ -20,9 +20,9 @@ export default defineComponent({ | |||
| 			const els = Array.from(child.value.children); | ||||
| 			for (let i = 0; i < els.length; i++) { | ||||
| 				const el = els[i]; | ||||
| 				if (el.classList.contains('_formNoConcat')) { | ||||
| 					if (els[i - 1]) els[i - 1].classList.add('_formNoConcatPrev'); | ||||
| 					if (els[i + 1]) els[i + 1].classList.add('_formNoConcatNext'); | ||||
| 				if (el.classList.contains('_debobigegoNoConcat')) { | ||||
| 					if (els[i - 1]) els[i - 1].classList.add('_debobigegoNoConcatPrev'); | ||||
| 					if (els[i + 1]) els[i + 1].classList.add('_debobigegoNoConcatNext'); | ||||
| 				} | ||||
| 			} | ||||
| 		}; | ||||
|  | @ -52,21 +52,21 @@ export default defineComponent({ | |||
| <style lang="scss" scoped> | ||||
| .vrtktovg { | ||||
| 	> .main { | ||||
| 		> ::v-deep(*):not(._formNoConcat) { | ||||
| 			&:not(._formNoConcatNext) { | ||||
| 		> ::v-deep(*):not(._debobigegoNoConcat) { | ||||
| 			&:not(._debobigegoNoConcatNext) { | ||||
| 				margin: 0; | ||||
| 			} | ||||
| 
 | ||||
| 			&:not(:last-child):not(._formNoConcatPrev) { | ||||
| 				&._formPanel, ._formPanel { | ||||
| 			&:not(:last-child):not(._debobigegoNoConcatPrev) { | ||||
| 				&._debobigegoPanel, ._debobigegoPanel { | ||||
| 					border-bottom: solid 0.5px var(--divider); | ||||
| 					border-bottom-left-radius: 0; | ||||
| 					border-bottom-right-radius: 0; | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			&:not(:first-child):not(._formNoConcatNext) { | ||||
| 				&._formPanel, ._formPanel { | ||||
| 			&:not(:first-child):not(._debobigegoNoConcatNext) { | ||||
| 				&._debobigegoPanel, ._debobigegoPanel { | ||||
| 					border-top: none; | ||||
| 					border-top-left-radius: 0; | ||||
| 					border-top-right-radius: 0; | ||||
|  | @ -1,6 +1,6 @@ | |||
| <template> | ||||
| <div class="fzenkabp _formItem"> | ||||
| 	<div class="_formPanel" :class="{ warn }"> | ||||
| <div class="fzenkabp _debobigegoItem"> | ||||
| 	<div class="_debobigegoPanel" :class="{ warn }"> | ||||
| 		<i v-if="warn" class="fas fa-exclamation-triangle"></i> | ||||
| 		<i v-else class="fas fa-info-circle"></i> | ||||
| 		<slot></slot> | ||||
|  | @ -1,49 +1,53 @@ | |||
| <template> | ||||
| <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> | ||||
| <FormGroup class="_debobigegoItem"> | ||||
| 	<template #label><slot></slot></template> | ||||
| 	<div class="ztzhwixg _debobigegoItem" :class="{ inline, disabled }"> | ||||
| 		<div class="icon" ref="icon"><slot name="icon"></slot></div> | ||||
| 		<div class="input _debobigegoPanel"> | ||||
| 			<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> | ||||
| 	<div class="caption"><slot name="caption"></slot></div> | ||||
| 	<template #caption><slot name="desc"></slot></template> | ||||
| 
 | ||||
| 	<MkButton v-if="manualSave && changed" @click="updated" primary><i class="fas fa-save"></i> {{ $ts.save }}</MkButton> | ||||
| </div> | ||||
| 	<FormButton v-if="manualSave && changed" @click="updated" primary><i class="fas fa-save"></i> {{ $ts.save }}</FormButton> | ||||
| </FormGroup> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent, onMounted, onUnmounted, nextTick, ref, watch, computed, toRefs } from 'vue'; | ||||
| import MkButton from './button.vue'; | ||||
| import { debounce } from 'throttle-debounce'; | ||||
| import './debobigego.scss'; | ||||
| import FormButton from './button.vue'; | ||||
| import FormGroup from './group.vue'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
| 		MkButton, | ||||
| 		FormGroup, | ||||
| 		FormButton, | ||||
| 	}, | ||||
| 
 | ||||
| 	props: { | ||||
| 		modelValue: { | ||||
| 			required: true | ||||
| 			required: false | ||||
| 		}, | ||||
| 		type: { | ||||
| 			type: String, | ||||
|  | @ -92,20 +96,13 @@ 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', 'update:modelValue'], | ||||
| 
 | ||||
| 	setup(props, context) { | ||||
| 		const { modelValue, type, autofocus } = toRefs(props); | ||||
| 		const v = ref(modelValue.value); | ||||
|  | @ -140,19 +137,13 @@ export default defineComponent({ | |||
| 			} | ||||
| 		}; | ||||
| 
 | ||||
| 		const debouncedUpdated = debounce(1000, updated); | ||||
| 
 | ||||
| 		watch(modelValue, newValue => { | ||||
| 		watch(modelValue.value, newValue => { | ||||
| 			v.value = newValue; | ||||
| 		}); | ||||
| 
 | ||||
| 		watch(v, newValue => { | ||||
| 			if (!props.manualSave) { | ||||
| 				if (props.debounce) { | ||||
| 					debouncedUpdated(); | ||||
| 				} else { | ||||
| 					updated(); | ||||
| 				} | ||||
| 				updated(); | ||||
| 			} | ||||
| 
 | ||||
| 			invalid.value = inputEl.value.validity.badInput; | ||||
|  | @ -205,68 +196,59 @@ export default defineComponent({ | |||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| .matxzzsk { | ||||
| 	margin: 1.5em 0; | ||||
| .ztzhwixg { | ||||
| 	position: relative; | ||||
| 
 | ||||
| 	> .label { | ||||
| 		font-size: 0.85em; | ||||
| 		padding: 0 0 8px 12px; | ||||
| 		user-select: none; | ||||
| 	> .icon { | ||||
| 		position: absolute; | ||||
| 		top: 0; | ||||
| 		left: 0; | ||||
| 		width: 24px; | ||||
| 		text-align: center; | ||||
| 		line-height: 32px; | ||||
| 
 | ||||
| 		&:empty { | ||||
| 			display: none; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	> .caption { | ||||
| 		font-size: 0.8em; | ||||
| 		padding: 8px 0 0 12px; | ||||
| 		color: var(--fgTransparentWeak); | ||||
| 
 | ||||
| 		&:empty { | ||||
| 			display: none; | ||||
| 		&:not(:empty) + .input { | ||||
| 			margin-left: 28px; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	> .input { | ||||
| 		$height: 42px; | ||||
| 		$height: 48px; | ||||
| 		position: relative; | ||||
| 
 | ||||
| 		> input { | ||||
| 			appearance: none; | ||||
| 			-webkit-appearance: none; | ||||
| 			display: block; | ||||
| 			height: $height; | ||||
| 			width: 100%; | ||||
| 			margin: 0; | ||||
| 			padding: 0 12px; | ||||
| 			padding: 0 16px; | ||||
| 			font: inherit; | ||||
| 			font-weight: normal; | ||||
| 			font-size: 1em; | ||||
| 			color: var(--fg); | ||||
| 			background: var(--panel); | ||||
| 			border: solid 0.5px var(--inputBorder); | ||||
| 			border-radius: 6px; | ||||
| 			line-height: $height; | ||||
| 			color: var(--inputText); | ||||
| 			background: transparent; | ||||
| 			border: none; | ||||
| 			border-radius: 0; | ||||
| 			outline: none; | ||||
| 			box-shadow: none; | ||||
| 			box-sizing: border-box; | ||||
| 			transition: border-color 0.1s ease-out; | ||||
| 
 | ||||
| 			&:hover { | ||||
| 				border-color: var(--inputBorderHover); | ||||
| 			&[type='file'] { | ||||
| 				display: none; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		> .prefix, | ||||
| 		> .suffix { | ||||
| 			display: flex; | ||||
| 			align-items: center; | ||||
| 			display: block; | ||||
| 			position: absolute; | ||||
| 			z-index: 1; | ||||
| 			top: 0; | ||||
| 			padding: 0 12px; | ||||
| 			padding: 0 16px; | ||||
| 			font-size: 1em; | ||||
| 			height: $height; | ||||
| 			line-height: $height; | ||||
| 			color: var(--inputLabel); | ||||
| 			pointer-events: none; | ||||
| 
 | ||||
| 			&:empty { | ||||
|  | @ -285,32 +267,25 @@ export default defineComponent({ | |||
| 
 | ||||
| 		> .prefix { | ||||
| 			left: 0; | ||||
| 			padding-right: 6px; | ||||
| 			padding-right: 8px; | ||||
| 		} | ||||
| 
 | ||||
| 		> .suffix { | ||||
| 			right: 0; | ||||
| 			padding-left: 6px; | ||||
| 			padding-left: 8px; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 		&.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; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | @ -1,6 +1,6 @@ | |||
| <template> | ||||
| <div class="_formItem"> | ||||
| 	<div class="_formPanel anocepby"> | ||||
| <div class="_debobigegoItem"> | ||||
| 	<div class="_debobigegoPanel anocepby"> | ||||
| 		<span class="key"><slot name="key"></slot></span> | ||||
| 		<span class="value"><slot name="value"></slot></span> | ||||
| 	</div> | ||||
|  | @ -9,7 +9,7 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import './form.scss'; | ||||
| import './debobigego.scss'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 
 | ||||
|  | @ -20,7 +20,7 @@ export default defineComponent({ | |||
| .anocepby { | ||||
| 	display: flex; | ||||
| 	align-items: center; | ||||
| 	padding: 14px var(--formContentHMargin); | ||||
| 	padding: 14px var(--debobigegoContentHMargin); | ||||
| 
 | ||||
| 	> .key { | ||||
| 		margin-right: 12px; | ||||
|  | @ -1,6 +1,6 @@ | |||
| <template> | ||||
| <div class="qmfkfnzi _formItem"> | ||||
| 	<a class="main _button _formPanel _formClickable" :href="to" target="_blank" v-if="external"> | ||||
| <div class="qmfkfnzi _debobigegoItem"> | ||||
| 	<a class="main _button _debobigegoPanel _debobigegoClickable" :href="to" target="_blank" v-if="external"> | ||||
| 		<span class="icon"><slot name="icon"></slot></span> | ||||
| 		<span class="text"><slot></slot></span> | ||||
| 		<span class="right"> | ||||
|  | @ -8,7 +8,7 @@ | |||
| 			<i class="fas fa-external-link-alt icon"></i> | ||||
| 		</span> | ||||
| 	</a> | ||||
| 	<MkA class="main _button _formPanel _formClickable" :class="{ active }" :to="to" :behavior="behavior" v-else> | ||||
| 	<MkA class="main _button _debobigegoPanel _debobigegoClickable" :class="{ active }" :to="to" :behavior="behavior" v-else> | ||||
| 		<span class="icon"><slot name="icon"></slot></span> | ||||
| 		<span class="text"><slot></slot></span> | ||||
| 		<span class="right"> | ||||
|  | @ -21,7 +21,7 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import './form.scss'; | ||||
| import './debobigego.scss'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	props: { | ||||
|  | @ -1,8 +1,8 @@ | |||
| <template> | ||||
| <FormGroup class="_formItem"> | ||||
| <FormGroup class="_debobigegoItem"> | ||||
| 	<template #label><slot></slot></template> | ||||
| 	<div class="drooglns _formItem" :class="{ tall }"> | ||||
| 		<div class="input _formPanel"> | ||||
| 	<div class="drooglns _debobigegoItem" :class="{ tall }"> | ||||
| 		<div class="input _debobigegoPanel"> | ||||
| 			<textarea class="_monospace" | ||||
| 				v-model="v" | ||||
| 				readonly | ||||
|  | @ -17,7 +17,7 @@ | |||
| <script lang="ts"> | ||||
| import { defineComponent, ref, toRefs, watch } from 'vue'; | ||||
| import * as JSON5 from 'json5'; | ||||
| import './form.scss'; | ||||
| import './debobigego.scss'; | ||||
| import FormGroup from './group.vue'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
|  | @ -75,7 +75,7 @@ export default defineComponent({ | |||
| 			max-width: 100%; | ||||
| 			min-height: 130px; | ||||
| 			margin: 0; | ||||
| 			padding: 16px var(--formContentHMargin); | ||||
| 			padding: 16px var(--debobigegoContentHMargin); | ||||
| 			box-sizing: border-box; | ||||
| 			font: inherit; | ||||
| 			font-weight: normal; | ||||
|  | @ -1,5 +1,5 @@ | |||
| <template> | ||||
| <FormGroup class="uljviswt _formItem"> | ||||
| <FormGroup class="uljviswt _debobigegoItem"> | ||||
| 	<template #label><slot name="label"></slot></template> | ||||
| 	<slot :items="items"></slot> | ||||
| 	<div class="empty" v-if="empty" key="_empty_"> | ||||
							
								
								
									
										112
									
								
								src/client/components/debobigego/radios.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								src/client/components/debobigego/radios.vue
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,112 @@ | |||
| <script lang="ts"> | ||||
| import { defineComponent, h } from 'vue'; | ||||
| import MkRadio from '@client/components/form/radio.vue'; | ||||
| import './debobigego.scss'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
| 		MkRadio | ||||
| 	}, | ||||
| 	props: { | ||||
| 		modelValue: { | ||||
| 			required: false | ||||
| 		}, | ||||
| 	}, | ||||
| 	data() { | ||||
| 		return { | ||||
| 			value: this.modelValue, | ||||
| 		} | ||||
| 	}, | ||||
| 	watch: { | ||||
| 		modelValue() { | ||||
| 			this.value = this.modelValue; | ||||
| 		}, | ||||
| 		value() { | ||||
| 			this.$emit('update:modelValue', this.value); | ||||
| 		} | ||||
| 	}, | ||||
| 	render() { | ||||
| 		const label = this.$slots.desc(); | ||||
| 		let options = this.$slots.default(); | ||||
| 
 | ||||
| 		// なぜかFragmentになることがあるため | ||||
| 		if (options.length === 1 && options[0].props == null) options = options[0].children; | ||||
| 
 | ||||
| 		return h('div', { | ||||
| 			class: 'cnklmpwm _debobigegoItem' | ||||
| 		}, [ | ||||
| 			h('div', { | ||||
| 				class: '_debobigegoLabel', | ||||
| 			}, label), | ||||
| 			...options.map(option => h('button', { | ||||
| 				class: '_button _debobigegoPanel _debobigegoClickable', | ||||
| 				key: option.key, | ||||
| 				onClick: () => this.value = option.props.value, | ||||
| 			}, [h('span', { | ||||
| 				class: ['check', { checked: this.value === option.props.value }], | ||||
| 			}), option.children])) | ||||
| 		]); | ||||
| 	} | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss"> | ||||
| .cnklmpwm { | ||||
| 	> button { | ||||
| 		display: block; | ||||
| 		width: 100%; | ||||
| 		box-sizing: border-box; | ||||
| 		padding: 14px 18px; | ||||
| 		text-align: left; | ||||
| 
 | ||||
| 		&:not(:first-of-type) { | ||||
| 			border-top: none !important; | ||||
| 			border-top-left-radius: 0; | ||||
| 			border-top-right-radius: 0; | ||||
| 		} | ||||
| 
 | ||||
| 		&:not(:last-of-type) { | ||||
| 			border-bottom: solid 0.5px var(--divider); | ||||
| 			border-bottom-left-radius: 0; | ||||
| 			border-bottom-right-radius: 0; | ||||
| 		} | ||||
| 
 | ||||
| 		> .check { | ||||
| 			display: inline-block; | ||||
| 			vertical-align: bottom; | ||||
| 			position: relative; | ||||
| 			width: 16px; | ||||
| 			height: 16px; | ||||
| 			margin-right: 8px; | ||||
| 			background: none; | ||||
| 			border: 2px solid var(--inputBorder); | ||||
| 			border-radius: 100%; | ||||
| 			transition: inherit; | ||||
| 
 | ||||
| 			&:after { | ||||
| 				content: ""; | ||||
| 				display: block; | ||||
| 				position: absolute; | ||||
| 				top: 3px; | ||||
| 				right: 3px; | ||||
| 				bottom: 3px; | ||||
| 				left: 3px; | ||||
| 				border-radius: 100%; | ||||
| 				opacity: 0; | ||||
| 				transform: scale(0); | ||||
| 				transition: .4s cubic-bezier(.25,.8,.25,1); | ||||
| 			} | ||||
| 
 | ||||
| 			&.checked { | ||||
| 				border-color: var(--accent); | ||||
| 
 | ||||
| 				&:after { | ||||
| 					background-color: var(--accent); | ||||
| 					transform: scale(1); | ||||
| 					opacity: 1; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										122
									
								
								src/client/components/debobigego/range.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								src/client/components/debobigego/range.vue
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,122 @@ | |||
| <template> | ||||
| <div class="ifitouly _debobigegoItem" :class="{ focused, disabled }"> | ||||
| 	<div class="_debobigegoLabel"><slot name="label"></slot></div> | ||||
| 	<div class="_debobigegoPanel main"> | ||||
| 		<input | ||||
| 			type="range" | ||||
| 			ref="input" | ||||
| 			v-model="v" | ||||
| 			:disabled="disabled" | ||||
| 			:min="min" | ||||
| 			:max="max" | ||||
| 			:step="step" | ||||
| 			@focus="focused = true" | ||||
| 			@blur="focused = false" | ||||
| 			@input="$emit('update:value', $event.target.value)" | ||||
| 		/> | ||||
| 	</div> | ||||
| 	<div class="_debobigegoCaption"><slot name="caption"></slot></div> | ||||
| </div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	props: { | ||||
| 		value: { | ||||
| 			type: Number, | ||||
| 			required: false, | ||||
| 			default: 0 | ||||
| 		}, | ||||
| 		disabled: { | ||||
| 			type: Boolean, | ||||
| 			required: false, | ||||
| 			default: false | ||||
| 		}, | ||||
| 		min: { | ||||
| 			type: Number, | ||||
| 			required: false, | ||||
| 			default: 0 | ||||
| 		}, | ||||
| 		max: { | ||||
| 			type: Number, | ||||
| 			required: false, | ||||
| 			default: 100 | ||||
| 		}, | ||||
| 		step: { | ||||
| 			type: Number, | ||||
| 			required: false, | ||||
| 			default: 1 | ||||
| 		}, | ||||
| 	}, | ||||
| 	data() { | ||||
| 		return { | ||||
| 			v: this.value, | ||||
| 			focused: false | ||||
| 		}; | ||||
| 	}, | ||||
| 	watch: { | ||||
| 		value(v) { | ||||
| 			this.v = parseFloat(v); | ||||
| 		} | ||||
| 	}, | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| .ifitouly { | ||||
| 	position: relative; | ||||
| 
 | ||||
| 	> .main { | ||||
| 		padding: 22px 16px; | ||||
| 
 | ||||
| 		> input { | ||||
| 			display: block; | ||||
| 			-webkit-appearance: none; | ||||
| 			-moz-appearance: none; | ||||
| 			appearance: none; | ||||
| 			background: var(--X10); | ||||
| 			height: 4px; | ||||
| 			width: 100%; | ||||
| 			box-sizing: border-box; | ||||
| 			margin: 0; | ||||
| 			outline: 0; | ||||
| 			border: 0; | ||||
| 			border-radius: 7px; | ||||
| 
 | ||||
| 			&.disabled { | ||||
| 				opacity: 0.6; | ||||
| 				cursor: not-allowed; | ||||
| 			} | ||||
| 
 | ||||
| 			&::-webkit-slider-thumb { | ||||
| 				-webkit-appearance: none; | ||||
| 				appearance: none; | ||||
| 				cursor: pointer; | ||||
| 				width: 20px; | ||||
| 				height: 20px; | ||||
| 				display: block; | ||||
| 				border-radius: 50%; | ||||
| 				border: none; | ||||
| 				background: var(--accent); | ||||
| 				box-shadow: 0 0 6px rgba(0, 0, 0, 0.3); | ||||
| 				box-sizing: content-box; | ||||
| 			} | ||||
| 
 | ||||
| 			&::-moz-range-thumb { | ||||
| 				-moz-appearance: none; | ||||
| 				appearance: none; | ||||
| 				cursor: pointer; | ||||
| 				width: 20px; | ||||
| 				height: 20px; | ||||
| 				display: block; | ||||
| 				border-radius: 50%; | ||||
| 				border: none; | ||||
| 				background: var(--accent); | ||||
| 				box-shadow: 0 0 6px rgba(0, 0, 0, 0.3); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										145
									
								
								src/client/components/debobigego/select.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								src/client/components/debobigego/select.vue
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,145 @@ | |||
| <template> | ||||
| <div class="yrtfrpux _debobigegoItem" :class="{ disabled, inline }"> | ||||
| 	<div class="_debobigegoLabel"><slot name="label"></slot></div> | ||||
| 	<div class="icon" ref="icon"><slot name="icon"></slot></div> | ||||
| 	<div class="input _debobigegoPanel _debobigegoClickable" @click="focus"> | ||||
| 		<div class="prefix" ref="prefix"><slot name="prefix"></slot></div> | ||||
| 		<select ref="input" | ||||
| 			v-model="v" | ||||
| 			:required="required" | ||||
| 			:disabled="disabled" | ||||
| 			@focus="focused = true" | ||||
| 			@blur="focused = false" | ||||
| 		> | ||||
| 			<slot></slot> | ||||
| 		</select> | ||||
| 		<div class="suffix"> | ||||
| 			<i class="fas fa-chevron-down"></i> | ||||
| 		</div> | ||||
| 	</div> | ||||
| 	<div class="_debobigegoCaption"><slot name="caption"></slot></div> | ||||
| </div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import './debobigego.scss'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	props: { | ||||
| 		modelValue: { | ||||
| 			required: false | ||||
| 		}, | ||||
| 		required: { | ||||
| 			type: Boolean, | ||||
| 			required: false | ||||
| 		}, | ||||
| 		disabled: { | ||||
| 			type: Boolean, | ||||
| 			required: false | ||||
| 		}, | ||||
| 		inline: { | ||||
| 			type: Boolean, | ||||
| 			required: false, | ||||
| 			default: false | ||||
| 		}, | ||||
| 	}, | ||||
| 	data() { | ||||
| 		return { | ||||
| 		}; | ||||
| 	}, | ||||
| 	computed: { | ||||
| 		v: { | ||||
| 			get() { | ||||
| 				return this.modelValue; | ||||
| 			}, | ||||
| 			set(v) { | ||||
| 				this.$emit('update:modelValue', v); | ||||
| 			} | ||||
| 		}, | ||||
| 	}, | ||||
| 	methods: { | ||||
| 		focus() { | ||||
| 			this.$refs.input.focus(); | ||||
| 		} | ||||
| 	} | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| .yrtfrpux { | ||||
| 	position: relative; | ||||
| 
 | ||||
| 	> .icon { | ||||
| 		position: absolute; | ||||
| 		top: 0; | ||||
| 		left: 0; | ||||
| 		width: 24px; | ||||
| 		text-align: center; | ||||
| 		line-height: 32px; | ||||
| 
 | ||||
| 		&:not(:empty) + .input { | ||||
| 			margin-left: 28px; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	> .input { | ||||
| 		display: flex; | ||||
| 		position: relative; | ||||
| 
 | ||||
| 		> select { | ||||
| 			display: block; | ||||
| 			flex: 1; | ||||
| 			width: 100%; | ||||
| 			padding: 0 16px; | ||||
| 			font: inherit; | ||||
| 			font-weight: normal; | ||||
| 			font-size: 1em; | ||||
| 			height: 48px; | ||||
| 			background: none; | ||||
| 			border: none; | ||||
| 			border-radius: 0; | ||||
| 			outline: none; | ||||
| 			box-shadow: none; | ||||
| 			appearance: none; | ||||
| 			-webkit-appearance: none; | ||||
| 			color: var(--fg); | ||||
| 
 | ||||
| 			option, | ||||
| 			optgroup { | ||||
| 				color: var(--fg); | ||||
| 				background: var(--bg); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		> .prefix, | ||||
| 		> .suffix { | ||||
| 			display: block; | ||||
| 			align-self: center; | ||||
| 			justify-self: center; | ||||
| 			font-size: 1em; | ||||
| 			line-height: 32px; | ||||
| 			color: var(--inputLabel); | ||||
| 			pointer-events: none; | ||||
| 
 | ||||
| 			&:empty { | ||||
| 				display: none; | ||||
| 			} | ||||
| 
 | ||||
| 			> * { | ||||
| 				display: block; | ||||
| 				min-width: 16px; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		> .prefix { | ||||
| 			padding-right: 4px; | ||||
| 		} | ||||
| 
 | ||||
| 		> .suffix { | ||||
| 			padding: 0 16px 0 0; | ||||
| 			opacity: 0.7; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| </style> | ||||
|  | @ -1,15 +1,15 @@ | |||
| <template> | ||||
| <transition name="fade" mode="out-in"> | ||||
| 	<div class="_formItem" v-if="pending"> | ||||
| 		<div class="_formPanel"> | ||||
| 	<div class="_debobigegoItem" v-if="pending"> | ||||
| 		<div class="_debobigegoPanel"> | ||||
| 			<MkLoading/> | ||||
| 		</div> | ||||
| 	</div> | ||||
| 	<div v-else-if="resolved" class="_formItem"> | ||||
| 	<div v-else-if="resolved" class="_debobigegoItem"> | ||||
| 		<slot :result="result"></slot> | ||||
| 	</div> | ||||
| 	<div class="_formItem" v-else> | ||||
| 		<div class="_formPanel eiurkvay"> | ||||
| 	<div class="_debobigegoItem" v-else> | ||||
| 		<div class="_debobigegoPanel eiurkvay"> | ||||
| 			<div><i class="fas fa-exclamation-triangle"></i> {{ $ts.somethingHappened }}</div> | ||||
| 			<MkButton inline @click="retry" class="retry"><i class="fas fa-redo-alt"></i> {{ $ts.retry }}</MkButton> | ||||
| 		</div> | ||||
|  | @ -19,7 +19,7 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent, PropType, ref, watch } from 'vue'; | ||||
| import './form.scss'; | ||||
| import './debobigego.scss'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
							
								
								
									
										132
									
								
								src/client/components/debobigego/switch.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								src/client/components/debobigego/switch.vue
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,132 @@ | |||
| <template> | ||||
| <div class="ijnpvmgr _debobigegoItem"> | ||||
| 	<div class="main _debobigegoPanel _debobigegoClickable" | ||||
| 		:class="{ disabled, checked }" | ||||
| 		:aria-checked="checked" | ||||
| 		:aria-disabled="disabled" | ||||
| 		@click.prevent="toggle" | ||||
| 	> | ||||
| 		<input | ||||
| 			type="checkbox" | ||||
| 			ref="input" | ||||
| 			:disabled="disabled" | ||||
| 			@keydown.enter="toggle" | ||||
| 		> | ||||
| 		<span class="button" v-tooltip="checked ? $ts.itsOn : $ts.itsOff"> | ||||
| 			<span></span> | ||||
| 		</span> | ||||
| 		<span class="label"> | ||||
| 			<span><slot></slot></span> | ||||
| 		</span> | ||||
| 	</div> | ||||
| 	<div class="_debobigegoCaption"><slot name="desc"></slot></div> | ||||
| </div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import './debobigego.scss'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	props: { | ||||
| 		modelValue: { | ||||
| 			type: Boolean, | ||||
| 			default: false | ||||
| 		}, | ||||
| 		disabled: { | ||||
| 			type: Boolean, | ||||
| 			default: false | ||||
| 		} | ||||
| 	}, | ||||
| 	computed: { | ||||
| 		checked(): boolean { | ||||
| 			return this.modelValue; | ||||
| 		} | ||||
| 	}, | ||||
| 	methods: { | ||||
| 		toggle() { | ||||
| 			if (this.disabled) return; | ||||
| 			this.$emit('update:modelValue', !this.checked); | ||||
| 		} | ||||
| 	} | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| .ijnpvmgr { | ||||
| 	> .main { | ||||
| 		position: relative; | ||||
| 		display: flex; | ||||
| 		padding: 14px 16px; | ||||
| 		cursor: pointer; | ||||
| 
 | ||||
| 		> * { | ||||
| 			user-select: none; | ||||
| 		} | ||||
| 
 | ||||
| 		&.disabled { | ||||
| 			opacity: 0.6; | ||||
| 			cursor: not-allowed; | ||||
| 		} | ||||
| 
 | ||||
| 		&.checked { | ||||
| 			> .button { | ||||
| 				background-color: var(--X10); | ||||
| 				border-color: var(--X10); | ||||
| 
 | ||||
| 				> * { | ||||
| 					background-color: var(--accent); | ||||
| 					transform: translateX(14px); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		> input { | ||||
| 			position: absolute; | ||||
| 			width: 0; | ||||
| 			height: 0; | ||||
| 			opacity: 0; | ||||
| 			margin: 0; | ||||
| 		} | ||||
| 
 | ||||
| 		> .button { | ||||
| 			position: relative; | ||||
| 			display: inline-block; | ||||
| 			flex-shrink: 0; | ||||
| 			margin: 3px 0 0 0; | ||||
| 			width: 34px; | ||||
| 			height: 14px; | ||||
| 			background: var(--X6); | ||||
| 			outline: none; | ||||
| 			border-radius: 14px; | ||||
| 			transition: all 0.3s; | ||||
| 			cursor: pointer; | ||||
| 
 | ||||
| 			> * { | ||||
| 				position: absolute; | ||||
| 				top: -3px; | ||||
| 				left: 0; | ||||
| 				border-radius: 100%; | ||||
| 				transition: background-color 0.3s, transform 0.3s; | ||||
| 				width: 20px; | ||||
| 				height: 20px; | ||||
| 				background-color: #fff; | ||||
| 				box-shadow: 0 2px 1px -1px rgba(#000, 0.2), 0 1px 1px 0 rgba(#000, 0.14), 0 1px 3px 0 rgba(#000, 0.12); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		> .label { | ||||
| 			margin-left: 12px; | ||||
| 			display: block; | ||||
| 			transition: inherit; | ||||
| 			color: var(--fg); | ||||
| 
 | ||||
| 			> span { | ||||
| 				display: block; | ||||
| 				line-height: 20px; | ||||
| 				transition: inherit; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										161
									
								
								src/client/components/debobigego/textarea.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										161
									
								
								src/client/components/debobigego/textarea.vue
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,161 @@ | |||
| <template> | ||||
| <FormGroup class="_debobigegoItem"> | ||||
| 	<template #label><slot></slot></template> | ||||
| 	<div class="rivhosbp _debobigegoItem" :class="{ tall, pre }"> | ||||
| 		<div class="input _debobigegoPanel"> | ||||
| 			<textarea ref="input" :class="{ code, _monospace: code }" | ||||
| 				v-model="v" | ||||
| 				:required="required" | ||||
| 				:readonly="readonly" | ||||
| 				:pattern="pattern" | ||||
| 				:autocomplete="autocomplete" | ||||
| 				:spellcheck="!code" | ||||
| 				@input="onInput" | ||||
| 				@focus="focused = true" | ||||
| 				@blur="focused = false" | ||||
| 			></textarea> | ||||
| 		</div> | ||||
| 	</div> | ||||
| 	<template #caption><slot name="desc"></slot></template> | ||||
| 
 | ||||
| 	<FormButton v-if="manualSave && changed" @click="updated" primary><i class="fas fa-save"></i> {{ $ts.save }}</FormButton> | ||||
| </FormGroup> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent, ref, toRefs, watch } from 'vue'; | ||||
| import './debobigego.scss'; | ||||
| import FormButton from './button.vue'; | ||||
| import FormGroup from './group.vue'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
| 		FormGroup, | ||||
| 		FormButton, | ||||
| 	}, | ||||
| 	props: { | ||||
| 		modelValue: { | ||||
| 			required: false | ||||
| 		}, | ||||
| 		required: { | ||||
| 			type: Boolean, | ||||
| 			required: false | ||||
| 		}, | ||||
| 		readonly: { | ||||
| 			type: Boolean, | ||||
| 			required: false | ||||
| 		}, | ||||
| 		pattern: { | ||||
| 			type: String, | ||||
| 			required: false | ||||
| 		}, | ||||
| 		autocomplete: { | ||||
| 			type: String, | ||||
| 			required: false | ||||
| 		}, | ||||
| 		code: { | ||||
| 			type: Boolean, | ||||
| 			required: false | ||||
| 		}, | ||||
| 		tall: { | ||||
| 			type: Boolean, | ||||
| 			required: false, | ||||
| 			default: false | ||||
| 		}, | ||||
| 		pre: { | ||||
| 			type: Boolean, | ||||
| 			required: false, | ||||
| 			default: false | ||||
| 		}, | ||||
| 		manualSave: { | ||||
| 			type: Boolean, | ||||
| 			required: false, | ||||
| 			default: false | ||||
| 		}, | ||||
| 	}, | ||||
| 	setup(props, context) { | ||||
| 		const { modelValue } = toRefs(props); | ||||
| 		const v = ref(modelValue.value); | ||||
| 		const changed = ref(false); | ||||
| 		const inputEl = ref(null); | ||||
| 		const focus = () => inputEl.value.focus(); | ||||
| 		const onInput = (ev) => { | ||||
| 			changed.value = true; | ||||
| 			context.emit('change', ev); | ||||
| 		}; | ||||
| 
 | ||||
| 		const updated = () => { | ||||
| 			changed.value = false; | ||||
| 			context.emit('update:modelValue', v.value); | ||||
| 		}; | ||||
| 
 | ||||
| 		watch(modelValue.value, newValue => { | ||||
| 			v.value = newValue; | ||||
| 		}); | ||||
| 
 | ||||
| 		watch(v, newValue => { | ||||
| 			if (!props.manualSave) { | ||||
| 				updated(); | ||||
| 			} | ||||
| 		}); | ||||
| 		 | ||||
| 		return { | ||||
| 			v, | ||||
| 			updated, | ||||
| 			changed, | ||||
| 			focus, | ||||
| 			onInput, | ||||
| 		}; | ||||
| 	} | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| .rivhosbp { | ||||
| 	position: relative; | ||||
| 
 | ||||
| 	> .input { | ||||
| 		position: relative; | ||||
| 	 | ||||
| 		> textarea { | ||||
| 			display: block; | ||||
| 			width: 100%; | ||||
| 			min-width: 100%; | ||||
| 			max-width: 100%; | ||||
| 			min-height: 130px; | ||||
| 			margin: 0; | ||||
| 			padding: 16px; | ||||
| 			box-sizing: border-box; | ||||
| 			font: inherit; | ||||
| 			font-weight: normal; | ||||
| 			font-size: 1em; | ||||
| 			background: transparent; | ||||
| 			border: none; | ||||
| 			border-radius: 0; | ||||
| 			outline: none; | ||||
| 			box-shadow: none; | ||||
| 			color: var(--fg); | ||||
| 
 | ||||
| 			&.code { | ||||
| 				tab-size: 2; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	&.tall { | ||||
| 		> .input { | ||||
| 			> textarea { | ||||
| 				min-height: 200px; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	&.pre { | ||||
| 		> .input { | ||||
| 			> textarea { | ||||
| 				white-space: pre; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| </style> | ||||
|  | @ -1,5 +1,5 @@ | |||
| <template> | ||||
| <div class="wthhikgt _formItem" v-size="{ max: [500] }"> | ||||
| <div class="wthhikgt _debobigegoItem" v-size="{ max: [500] }"> | ||||
| 	<slot></slot> | ||||
| </div> | ||||
| </template> | ||||
|  | @ -40,8 +40,8 @@ | |||
| import { defineComponent } from 'vue'; | ||||
| import MkModal from '@client/components/ui/modal.vue'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import MkInput from '@client/components/ui/input.vue'; | ||||
| import MkSelect from '@client/components/ui/select.vue'; | ||||
| import MkInput from '@client/components/form/input.vue'; | ||||
| import MkSelect from '@client/components/form/select.vue'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
|  |  | |||
|  | @ -35,7 +35,7 @@ | |||
| import { defineComponent } from 'vue'; | ||||
| import XModalWindow from '@client/components/ui/modal-window.vue'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import MkInput from '@client/components/ui/input.vue'; | ||||
| import MkInput from '@client/components/form/input.vue'; | ||||
| import * as os from '@client/os'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
|  |  | |||
|  | @ -14,23 +14,23 @@ | |||
| 	</template> | ||||
| 	<FormBase class="xkpnjxcv"> | ||||
| 		<template v-for="item in Object.keys(form).filter(item => !form[item].hidden)"> | ||||
| 			<FormInput v-if="form[item].type === 'number'" v-model:value="values[item]" type="number" :step="form[item].step || 1"> | ||||
| 			<FormInput v-if="form[item].type === 'number'" v-model="values[item]" type="number" :step="form[item].step || 1"> | ||||
| 				<span v-text="form[item].label || item"></span><span v-if="form[item].required === false"> ({{ $ts.optional }})</span> | ||||
| 				<template v-if="form[item].description" #desc>{{ form[item].description }}</template> | ||||
| 			</FormInput> | ||||
| 			<FormInput v-else-if="form[item].type === 'string' && !form[item].multiline" v-model:value="values[item]" type="text"> | ||||
| 			<FormInput v-else-if="form[item].type === 'string' && !form[item].multiline" v-model="values[item]" type="text"> | ||||
| 				<span v-text="form[item].label || item"></span><span v-if="form[item].required === false"> ({{ $ts.optional }})</span> | ||||
| 				<template v-if="form[item].description" #desc>{{ form[item].description }}</template> | ||||
| 			</FormInput> | ||||
| 			<FormTextarea v-else-if="form[item].type === 'string' && form[item].multiline" v-model:value="values[item]"> | ||||
| 			<FormTextarea v-else-if="form[item].type === 'string' && form[item].multiline" v-model="values[item]"> | ||||
| 				<span v-text="form[item].label || item"></span><span v-if="form[item].required === false"> ({{ $ts.optional }})</span> | ||||
| 				<template v-if="form[item].description" #desc>{{ form[item].description }}</template> | ||||
| 			</FormTextarea> | ||||
| 			<FormSwitch v-else-if="form[item].type === 'boolean'" v-model:value="values[item]"> | ||||
| 			<FormSwitch v-else-if="form[item].type === 'boolean'" v-model="values[item]"> | ||||
| 				<span v-text="form[item].label || item"></span> | ||||
| 				<template v-if="form[item].description" #desc>{{ form[item].description }}</template> | ||||
| 			</FormSwitch> | ||||
| 			<FormSelect v-else-if="form[item].type === 'enum'" v-model:value="values[item]"> | ||||
| 			<FormSelect v-else-if="form[item].type === 'enum'" v-model="values[item]"> | ||||
| 				<template #label><span v-text="form[item].label || item"></span><span v-if="form[item].required === false"> ({{ $ts.optional }})</span></template> | ||||
| 				<option v-for="item in form[item].enum" :value="item.value" :key="item.value">{{ item.label }}</option> | ||||
| 			</FormSelect> | ||||
|  | @ -38,7 +38,7 @@ | |||
| 				<template #desc><span v-text="form[item].label || item"></span><span v-if="form[item].required === false"> ({{ $ts.optional }})</span></template> | ||||
| 				<option v-for="item in form[item].options" :value="item.value" :key="item.value">{{ item.label }}</option> | ||||
| 			</FormRadios> | ||||
| 			<FormRange v-else-if="form[item].type === 'range'" v-model:value="values[item]" :min="form[item].mim" :max="form[item].max" :step="form[item].step"> | ||||
| 			<FormRange v-else-if="form[item].type === 'range'" v-model="values[item]" :min="form[item].mim" :max="form[item].max" :step="form[item].step"> | ||||
| 				<template #label><span v-text="form[item].label || item"></span><span v-if="form[item].required === false"> ({{ $ts.optional }})</span></template> | ||||
| 				<template v-if="form[item].description" #desc>{{ form[item].description }}</template> | ||||
| 			</FormRange> | ||||
|  | @ -53,14 +53,14 @@ | |||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import XModalWindow from '@client/components/ui/modal-window.vue'; | ||||
| import FormBase from './form/base.vue'; | ||||
| import FormInput from './form/input.vue'; | ||||
| import FormTextarea from './form/textarea.vue'; | ||||
| import FormSwitch from './form/switch.vue'; | ||||
| import FormSelect from './form/select.vue'; | ||||
| import FormRange from './form/range.vue'; | ||||
| import FormButton from './form/button.vue'; | ||||
| import FormRadios from './form/radios.vue'; | ||||
| import FormBase from './debobigego/base.vue'; | ||||
| import FormInput from './debobigego/input.vue'; | ||||
| import FormTextarea from './debobigego/textarea.vue'; | ||||
| import FormSwitch from './debobigego/switch.vue'; | ||||
| import FormSelect from './debobigego/select.vue'; | ||||
| import FormRange from './debobigego/range.vue'; | ||||
| import FormButton from './debobigego/button.vue'; | ||||
| import FormRadios from './debobigego/radios.vue'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
|  |  | |||
|  | @ -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; | ||||
| 
 | ||||
| 	> .icon { | ||||
| 		position: absolute; | ||||
| 		top: 0; | ||||
| 		left: 0; | ||||
| 		width: 24px; | ||||
| 		text-align: center; | ||||
| 		line-height: 32px; | ||||
| 		&:empty { | ||||
| 			display: none; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 		&:not(:empty) + .input { | ||||
| 			margin-left: 28px; | ||||
| 	> .caption { | ||||
| 		font-size: 0.8em; | ||||
| 		padding: 8px 0 0 12px; | ||||
| 		color: var(--fgTransparentWeak); | ||||
| 
 | ||||
| 		&: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; | ||||
| 		} | ||||
| 
 | ||||
| 	&.disabled { | ||||
| 		opacity: 0.7; | ||||
| 		&.focused { | ||||
| 			> input { | ||||
| 				border-color: var(--accent); | ||||
| 				//box-shadow: 0 0 0 4px var(--focus); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		&, * { | ||||
| 			cursor: not-allowed !important; | ||||
| 		&.disabled { | ||||
| 			opacity: 0.7; | ||||
| 
 | ||||
| 			&, * { | ||||
| 				cursor: not-allowed !important; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -1,7 +1,6 @@ | |||
| <script lang="ts"> | ||||
| import { defineComponent, h } from 'vue'; | ||||
| import MkRadio from '@client/components/ui/radio.vue'; | ||||
| import './form.scss'; | ||||
| import MkRadio from './radio.vue'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
|  | @ -18,9 +17,6 @@ export default defineComponent({ | |||
| 		} | ||||
| 	}, | ||||
| 	watch: { | ||||
| 		modelValue() { | ||||
| 			this.value = this.modelValue; | ||||
| 		}, | ||||
| 		value() { | ||||
| 			this.$emit('update:modelValue', this.value); | ||||
| 		} | ||||
|  | @ -33,80 +29,38 @@ export default defineComponent({ | |||
| 		if (options.length === 1 && options[0].props == null) options = options[0].children; | ||||
| 
 | ||||
| 		return h('div', { | ||||
| 			class: 'cnklmpwm _formItem' | ||||
| 			class: 'novjtcto' | ||||
| 		}, [ | ||||
| 			h('div', { | ||||
| 				class: '_formLabel', | ||||
| 			}, label), | ||||
| 			...options.map(option => h('button', { | ||||
| 				class: '_button _formPanel _formClickable', | ||||
| 			h('div', { class: 'label' }, label), | ||||
| 			...options.map(option => h(MkRadio, { | ||||
| 				key: option.key, | ||||
| 				onClick: () => this.value = option.props.value, | ||||
| 			}, [h('span', { | ||||
| 				class: ['check', { checked: this.value === option.props.value }], | ||||
| 			}), option.children])) | ||||
| 				value: option.props.value, | ||||
| 				modelValue: this.value, | ||||
| 				'onUpdate:modelValue': value => this.value = value, | ||||
| 			}, option.children)) | ||||
| 		]); | ||||
| 	} | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss"> | ||||
| .cnklmpwm { | ||||
| 	> button { | ||||
| 		display: block; | ||||
| 		width: 100%; | ||||
| 		box-sizing: border-box; | ||||
| 		padding: 14px 18px; | ||||
| 		text-align: left; | ||||
| .novjtcto { | ||||
| 	> .label { | ||||
| 		font-size: 0.85em; | ||||
| 		padding: 0 0 8px 12px; | ||||
| 		user-select: none; | ||||
| 
 | ||||
| 		&:not(:first-of-type) { | ||||
| 			border-top: none !important; | ||||
| 			border-top-left-radius: 0; | ||||
| 			border-top-right-radius: 0; | ||||
| 		&:empty { | ||||
| 			display: none; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 		&:not(:last-of-type) { | ||||
| 			border-bottom: solid 0.5px var(--divider); | ||||
| 			border-bottom-left-radius: 0; | ||||
| 			border-bottom-right-radius: 0; | ||||
| 		} | ||||
| 	&:first-child { | ||||
| 		margin-top: 0; | ||||
| 	} | ||||
| 
 | ||||
| 		> .check { | ||||
| 			display: inline-block; | ||||
| 			vertical-align: bottom; | ||||
| 			position: relative; | ||||
| 			width: 16px; | ||||
| 			height: 16px; | ||||
| 			margin-right: 8px; | ||||
| 			background: none; | ||||
| 			border: 2px solid var(--inputBorder); | ||||
| 			border-radius: 100%; | ||||
| 			transition: inherit; | ||||
| 
 | ||||
| 			&:after { | ||||
| 				content: ""; | ||||
| 				display: block; | ||||
| 				position: absolute; | ||||
| 				top: 3px; | ||||
| 				right: 3px; | ||||
| 				bottom: 3px; | ||||
| 				left: 3px; | ||||
| 				border-radius: 100%; | ||||
| 				opacity: 0; | ||||
| 				transform: scale(0); | ||||
| 				transition: .4s cubic-bezier(.25,.8,.25,1); | ||||
| 			} | ||||
| 
 | ||||
| 			&.checked { | ||||
| 				border-color: var(--accent); | ||||
| 
 | ||||
| 				&:after { | ||||
| 					background-color: var(--accent); | ||||
| 					transform: scale(1); | ||||
| 					opacity: 1; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	&:last-child { | ||||
| 		margin-bottom: 0; | ||||
| 	} | ||||
| } | ||||
| </style> | ||||
|  |  | |||
|  | @ -1,21 +1,20 @@ | |||
| <template> | ||||
| <div class="ifitouly _formItem" :class="{ focused, disabled }"> | ||||
| 	<div class="_formLabel"><slot name="label"></slot></div> | ||||
| 	<div class="_formPanel main"> | ||||
| 		<input | ||||
| 			type="range" | ||||
| 			ref="input" | ||||
| 			v-model="v" | ||||
| 			:disabled="disabled" | ||||
| 			:min="min" | ||||
| 			:max="max" | ||||
| 			:step="step" | ||||
| 			@focus="focused = true" | ||||
| 			@blur="focused = false" | ||||
| 			@input="$emit('update:value', $event.target.value)" | ||||
| 		/> | ||||
| 	</div> | ||||
| 	<div class="_formCaption"><slot name="caption"></slot></div> | ||||
| <div class="timctyfi" :class="{ focused, disabled }"> | ||||
| 	<div class="icon"><slot name="icon"></slot></div> | ||||
| 	<span class="label"><slot name="label"></slot></span> | ||||
| 	<input | ||||
| 		type="range" | ||||
| 		ref="input" | ||||
| 		v-model="v" | ||||
| 		:disabled="disabled" | ||||
| 		:min="min" | ||||
| 		:max="max" | ||||
| 		:step="step" | ||||
| 		:autofocus="autofocus" | ||||
| 		@focus="focused = true" | ||||
| 		@blur="focused = false" | ||||
| 		@input="$emit('update:value', $event.target.value)" | ||||
| 	/> | ||||
| </div> | ||||
| </template> | ||||
| 
 | ||||
|  | @ -49,6 +48,10 @@ export default defineComponent({ | |||
| 			required: false, | ||||
| 			default: 1 | ||||
| 		}, | ||||
| 		autofocus: { | ||||
| 			type: Boolean, | ||||
| 			required: false | ||||
| 		} | ||||
| 	}, | ||||
| 	data() { | ||||
| 		return { | ||||
|  | @ -61,61 +64,75 @@ export default defineComponent({ | |||
| 			this.v = parseFloat(v); | ||||
| 		} | ||||
| 	}, | ||||
| 	mounted() { | ||||
| 		if (this.autofocus) { | ||||
| 			this.$nextTick(() => { | ||||
| 				this.$refs.input.focus(); | ||||
| 			}); | ||||
| 		} | ||||
| 	} | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| .ifitouly { | ||||
| .timctyfi { | ||||
| 	position: relative; | ||||
| 	margin: 8px; | ||||
| 
 | ||||
| 	> .main { | ||||
| 		padding: 22px 16px; | ||||
| 	> .icon { | ||||
| 		display: inline-block; | ||||
| 		width: 24px; | ||||
| 		text-align: center; | ||||
| 	} | ||||
| 
 | ||||
| 		> input { | ||||
| 			display: block; | ||||
| 	> .title { | ||||
| 		pointer-events: none; | ||||
| 		font-size: 16px; | ||||
| 		color: var(--inputLabel); | ||||
| 		overflow: hidden; | ||||
| 	} | ||||
| 
 | ||||
| 	> input { | ||||
| 		-webkit-appearance: none; | ||||
| 		-moz-appearance: none; | ||||
| 		appearance: none; | ||||
| 		background: var(--X10); | ||||
| 		height: 7px; | ||||
| 		margin: 0 8px; | ||||
| 		outline: 0; | ||||
| 		border: 0; | ||||
| 		border-radius: 7px; | ||||
| 
 | ||||
| 		&.disabled { | ||||
| 			opacity: 0.6; | ||||
| 			cursor: not-allowed; | ||||
| 		} | ||||
| 
 | ||||
| 		&::-webkit-slider-thumb { | ||||
| 			-webkit-appearance: none; | ||||
| 			appearance: none; | ||||
| 			cursor: pointer; | ||||
| 			width: 20px; | ||||
| 			height: 20px; | ||||
| 			display: block; | ||||
| 			border-radius: 50%; | ||||
| 			border: none; | ||||
| 			background: var(--accent); | ||||
| 			box-shadow: 0 0 6px rgba(0, 0, 0, 0.3); | ||||
| 			box-sizing: content-box; | ||||
| 		} | ||||
| 
 | ||||
| 		&::-moz-range-thumb { | ||||
| 			-moz-appearance: none; | ||||
| 			appearance: none; | ||||
| 			background: var(--X10); | ||||
| 			height: 4px; | ||||
| 			width: 100%; | ||||
| 			box-sizing: border-box; | ||||
| 			margin: 0; | ||||
| 			outline: 0; | ||||
| 			border: 0; | ||||
| 			border-radius: 7px; | ||||
| 
 | ||||
| 			&.disabled { | ||||
| 				opacity: 0.6; | ||||
| 				cursor: not-allowed; | ||||
| 			} | ||||
| 
 | ||||
| 			&::-webkit-slider-thumb { | ||||
| 				-webkit-appearance: none; | ||||
| 				appearance: none; | ||||
| 				cursor: pointer; | ||||
| 				width: 20px; | ||||
| 				height: 20px; | ||||
| 				display: block; | ||||
| 				border-radius: 50%; | ||||
| 				border: none; | ||||
| 				background: var(--accent); | ||||
| 				box-shadow: 0 0 6px rgba(0, 0, 0, 0.3); | ||||
| 				box-sizing: content-box; | ||||
| 			} | ||||
| 
 | ||||
| 			&::-moz-range-thumb { | ||||
| 				-moz-appearance: none; | ||||
| 				appearance: none; | ||||
| 				cursor: pointer; | ||||
| 				width: 20px; | ||||
| 				height: 20px; | ||||
| 				display: block; | ||||
| 				border-radius: 50%; | ||||
| 				border: none; | ||||
| 				background: var(--accent); | ||||
| 				box-shadow: 0 0 6px rgba(0, 0, 0, 0.3); | ||||
| 			} | ||||
| 			cursor: pointer; | ||||
| 			width: 20px; | ||||
| 			height: 20px; | ||||
| 			display: block; | ||||
| 			border-radius: 50%; | ||||
| 			border: none; | ||||
| 			background: var(--accent); | ||||
| 			box-shadow: 0 0 6px rgba(0, 0, 0, 0.3); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
							
								
								
									
										31
									
								
								src/client/components/form/section.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/client/components/form/section.vue
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,31 @@ | |||
| <template> | ||||
| <div class="vrtktovh" v-size="{ max: [500] }" v-sticky-container> | ||||
| 	<div class="label"><slot name="label"></slot></div> | ||||
| 	<div class="main"> | ||||
| 		<slot></slot> | ||||
| 	</div> | ||||
| </div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 
 | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| .vrtktovh { | ||||
| 	border-top: solid 0.5px var(--divider); | ||||
| 
 | ||||
| 	> .label { | ||||
| 		font-weight: bold; | ||||
| 		padding: 24px 0 16px 0; | ||||
| 	} | ||||
| 
 | ||||
| 	> .main { | ||||
| 		margin-bottom: 32px; | ||||
| 	} | ||||
| } | ||||
| </style> | ||||
|  | @ -1,125 +1,216 @@ | |||
| <template> | ||||
| <div class="yrtfrpux _formItem" :class="{ disabled, inline }"> | ||||
| 	<div class="_formLabel"><slot name="label"></slot></div> | ||||
| 	<div class="icon" ref="icon"><slot name="icon"></slot></div> | ||||
| 	<div class="input _formPanel _formClickable" @click="focus"> | ||||
| 		<div class="prefix" ref="prefix"><slot name="prefix"></slot></div> | ||||
| 		<select ref="input" | ||||
| <div class="vblkjoeq"> | ||||
| 	<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> | ||||
| 		<select ref="inputEl" | ||||
| 			v-model="v" | ||||
| 			:required="required" | ||||
| 			:disabled="disabled" | ||||
| 			:required="required" | ||||
| 			:readonly="readonly" | ||||
| 			:placeholder="placeholder" | ||||
| 			@focus="focused = true" | ||||
| 			@blur="focused = false" | ||||
| 			@input="onInput" | ||||
| 		> | ||||
| 			<slot></slot> | ||||
| 		</select> | ||||
| 		<div class="suffix"> | ||||
| 			<i class="fas fa-chevron-down"></i> | ||||
| 		</div> | ||||
| 		<div class="suffix" ref="suffixEl"><i class="fas fa-chevron-down"></i></div> | ||||
| 	</div> | ||||
| 	<div class="_formCaption"><slot name="caption"></slot></div> | ||||
| 	<div class="caption"><slot name="caption"></slot></div> | ||||
| 
 | ||||
| 	<MkButton v-if="manualSave && changed" @click="updated" primary><i class="fas fa-save"></i> {{ $ts.save }}</MkButton> | ||||
| </div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import './form.scss'; | ||||
| import { defineComponent, onMounted, onUnmounted, nextTick, ref, watch, computed, toRefs } from 'vue'; | ||||
| import MkButton from '../ui/button.vue'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
| 		MkButton, | ||||
| 	}, | ||||
| 
 | ||||
| 	props: { | ||||
| 		value: { | ||||
| 			required: false | ||||
| 		modelValue: { | ||||
| 			required: true | ||||
| 		}, | ||||
| 		required: { | ||||
| 			type: Boolean, | ||||
| 			required: false | ||||
| 		}, | ||||
| 		readonly: { | ||||
| 			type: Boolean, | ||||
| 			required: false | ||||
| 		}, | ||||
| 		disabled: { | ||||
| 			type: Boolean, | ||||
| 			required: false | ||||
| 		}, | ||||
| 		placeholder: { | ||||
| 			type: String, | ||||
| 			required: false | ||||
| 		}, | ||||
| 		autofocus: { | ||||
| 			type: Boolean, | ||||
| 			required: false, | ||||
| 			default: false | ||||
| 		}, | ||||
| 		inline: { | ||||
| 			type: Boolean, | ||||
| 			required: false, | ||||
| 			default: false | ||||
| 		}, | ||||
| 	}, | ||||
| 	data() { | ||||
| 		return { | ||||
| 		}; | ||||
| 	}, | ||||
| 	computed: { | ||||
| 		v: { | ||||
| 			get() { | ||||
| 				return this.value; | ||||
| 			}, | ||||
| 			set(v) { | ||||
| 				this.$emit('update:value', v); | ||||
| 			} | ||||
| 		manualSave: { | ||||
| 			type: Boolean, | ||||
| 			required: false, | ||||
| 			default: false | ||||
| 		}, | ||||
| 	}, | ||||
| 	methods: { | ||||
| 		focus() { | ||||
| 			this.$refs.input.focus(); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	emits: ['change', 'update:modelValue'], | ||||
| 
 | ||||
| 	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 prefixEl = ref(null); | ||||
| 		const suffixEl = ref(null); | ||||
| 
 | ||||
| 		const focus = () => inputEl.value.focus(); | ||||
| 		const onInput = (ev) => { | ||||
| 			changed.value = true; | ||||
| 			context.emit('change', ev); | ||||
| 		}; | ||||
| 
 | ||||
| 		const updated = () => { | ||||
| 			changed.value = false; | ||||
| 			context.emit('update:modelValue', v.value); | ||||
| 		}; | ||||
| 
 | ||||
| 		watch(modelValue, newValue => { | ||||
| 			v.value = newValue; | ||||
| 		}); | ||||
| 
 | ||||
| 		watch(v, newValue => { | ||||
| 			if (!props.manualSave) { | ||||
| 				updated(); | ||||
| 			} | ||||
| 
 | ||||
| 			invalid.value = inputEl.value.validity.badInput; | ||||
| 		}); | ||||
| 
 | ||||
| 		onMounted(() => { | ||||
| 			nextTick(() => { | ||||
| 				if (autofocus.value) { | ||||
| 					focus(); | ||||
| 				} | ||||
| 
 | ||||
| 				// このコンポーネントが作成された時、非表示状態である場合がある | ||||
| 				// 非表示状態だと要素の幅などは0になってしまうので、定期的に計算する | ||||
| 				const clock = setInterval(() => { | ||||
| 					if (prefixEl.value) { | ||||
| 						if (prefixEl.value.offsetWidth) { | ||||
| 							inputEl.value.style.paddingLeft = prefixEl.value.offsetWidth + 'px'; | ||||
| 						} | ||||
| 					} | ||||
| 					if (suffixEl.value) { | ||||
| 						if (suffixEl.value.offsetWidth) { | ||||
| 							inputEl.value.style.paddingRight = suffixEl.value.offsetWidth + 'px'; | ||||
| 						} | ||||
| 					} | ||||
| 				}, 100); | ||||
| 
 | ||||
| 				onUnmounted(() => { | ||||
| 					clearInterval(clock); | ||||
| 				}); | ||||
| 			}); | ||||
| 		}); | ||||
| 
 | ||||
| 		return { | ||||
| 			v, | ||||
| 			focused, | ||||
| 			invalid, | ||||
| 			changed, | ||||
| 			filled, | ||||
| 			inputEl, | ||||
| 			prefixEl, | ||||
| 			suffixEl, | ||||
| 			focus, | ||||
| 			onInput, | ||||
| 			updated, | ||||
| 		}; | ||||
| 	}, | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| .yrtfrpux { | ||||
| 	position: relative; | ||||
| .vblkjoeq { | ||||
| 	> .label { | ||||
| 		font-size: 0.85em; | ||||
| 		padding: 0 0 8px 12px; | ||||
| 		user-select: none; | ||||
| 
 | ||||
| 	> .icon { | ||||
| 		position: absolute; | ||||
| 		top: 0; | ||||
| 		left: 0; | ||||
| 		width: 24px; | ||||
| 		text-align: center; | ||||
| 		line-height: 32px; | ||||
| 		&:empty { | ||||
| 			display: none; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 		&:not(:empty) + .input { | ||||
| 			margin-left: 28px; | ||||
| 	> .caption { | ||||
| 		font-size: 0.8em; | ||||
| 		padding: 8px 0 0 12px; | ||||
| 		color: var(--fgTransparentWeak); | ||||
| 
 | ||||
| 		&:empty { | ||||
| 			display: none; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	> .input { | ||||
| 		display: flex; | ||||
| 		$height: 42px; | ||||
| 		position: relative; | ||||
| 
 | ||||
| 		> select { | ||||
| 			appearance: none; | ||||
| 			-webkit-appearance: none; | ||||
| 			display: block; | ||||
| 			flex: 1; | ||||
| 			height: $height; | ||||
| 			width: 100%; | ||||
| 			padding: 0 16px; | ||||
| 			margin: 0; | ||||
| 			padding: 0 12px; | ||||
| 			font: inherit; | ||||
| 			font-weight: normal; | ||||
| 			font-size: 1em; | ||||
| 			height: 48px; | ||||
| 			background: none; | ||||
| 			border: none; | ||||
| 			border-radius: 0; | ||||
| 			color: var(--fg); | ||||
| 			background: var(--panel); | ||||
| 			border: solid 1px var(--inputBorder); | ||||
| 			border-radius: 6px; | ||||
| 			outline: none; | ||||
| 			box-shadow: none; | ||||
| 			appearance: none; | ||||
| 			-webkit-appearance: none; | ||||
| 			color: var(--fg); | ||||
| 			box-sizing: border-box; | ||||
| 			cursor: pointer; | ||||
| 			transition: border-color 0.1s ease-out; | ||||
| 
 | ||||
| 			option, | ||||
| 			optgroup { | ||||
| 				color: var(--fg); | ||||
| 				background: var(--bg); | ||||
| 			&:hover { | ||||
| 				border-color: var(--inputBorderHover); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		> .prefix, | ||||
| 		> .suffix { | ||||
| 			display: block; | ||||
| 			align-self: center; | ||||
| 			justify-self: center; | ||||
| 			display: flex; | ||||
| 			align-items: center; | ||||
| 			position: absolute; | ||||
| 			z-index: 1; | ||||
| 			top: 0; | ||||
| 			padding: 0 12px; | ||||
| 			font-size: 1em; | ||||
| 			line-height: 32px; | ||||
| 			color: var(--inputLabel); | ||||
| 			height: $height; | ||||
| 			pointer-events: none; | ||||
| 
 | ||||
| 			&:empty { | ||||
|  | @ -127,18 +218,42 @@ export default defineComponent({ | |||
| 			} | ||||
| 
 | ||||
| 			> * { | ||||
| 				display: block; | ||||
| 				display: inline-block; | ||||
| 				min-width: 16px; | ||||
| 				max-width: 150px; | ||||
| 				overflow: hidden; | ||||
| 				white-space: nowrap; | ||||
| 				text-overflow: ellipsis; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		> .prefix { | ||||
| 			padding-right: 4px; | ||||
| 			left: 0; | ||||
| 			padding-right: 6px; | ||||
| 		} | ||||
| 
 | ||||
| 		> .suffix { | ||||
| 			padding: 0 16px 0 0; | ||||
| 			right: 0; | ||||
| 			padding-left: 6px; | ||||
| 		} | ||||
| 
 | ||||
| 		&.inline { | ||||
| 			display: inline-block; | ||||
| 			margin: 0; | ||||
| 		} | ||||
| 
 | ||||
| 		&.focused { | ||||
| 			> select { | ||||
| 				border-color: var(--accent); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		&.disabled { | ||||
| 			opacity: 0.7; | ||||
| 
 | ||||
| 			&, * { | ||||
| 				cursor: not-allowed !important; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
							
								
								
									
										50
									
								
								src/client/components/form/slot.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								src/client/components/form/slot.vue
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,50 @@ | |||
| <template> | ||||
| <div class="adhpbeou"> | ||||
| 	<div class="label" @click="focus"><slot name="label"></slot></div> | ||||
| 	<div class="content"> | ||||
| 		<slot></slot> | ||||
| 	</div> | ||||
| 	<div class="caption"><slot name="caption"></slot></div> | ||||
| </div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 
 | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| .adhpbeou { | ||||
| 	margin: 1.5em 0; | ||||
| 
 | ||||
| 	> .label { | ||||
| 		font-size: 0.85em; | ||||
| 		padding: 0 0 8px 12px; | ||||
| 		user-select: none; | ||||
| 
 | ||||
| 		&:empty { | ||||
| 			display: none; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	> .caption { | ||||
| 		font-size: 0.8em; | ||||
| 		padding: 8px 0 0 12px; | ||||
| 		color: var(--fgTransparentWeak); | ||||
| 
 | ||||
| 		&:empty { | ||||
| 			display: none; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	> .content { | ||||
| 		position: relative; | ||||
| 		background: var(--panel); | ||||
| 		border: solid 0.5px var(--inputBorder); | ||||
| 		border-radius: 6px; | ||||
| 	} | ||||
| } | ||||
| </style> | ||||
|  | @ -1,35 +1,34 @@ | |||
| <template> | ||||
| <div class="ijnpvmgr _formItem"> | ||||
| 	<div class="main _formPanel _formClickable" | ||||
| 		:class="{ disabled, checked }" | ||||
| 		:aria-checked="checked" | ||||
| 		:aria-disabled="disabled" | ||||
| 		@click.prevent="toggle" | ||||
| <div | ||||
| 	class="ziffeoms" | ||||
| 	:class="{ disabled, checked }" | ||||
| 	role="switch" | ||||
| 	:aria-checked="checked" | ||||
| 	:aria-disabled="disabled" | ||||
| 	@click.prevent="toggle" | ||||
| > | ||||
| 	<input | ||||
| 		type="checkbox" | ||||
| 		ref="input" | ||||
| 		:disabled="disabled" | ||||
| 		@keydown.enter="toggle" | ||||
| 	> | ||||
| 		<input | ||||
| 			type="checkbox" | ||||
| 			ref="input" | ||||
| 			:disabled="disabled" | ||||
| 			@keydown.enter="toggle" | ||||
| 		> | ||||
| 		<span class="button"> | ||||
| 			<span></span> | ||||
| 		</span> | ||||
| 		<span class="label"> | ||||
| 			<span><slot></slot></span> | ||||
| 		</span> | ||||
| 	</div> | ||||
| 	<div class="_formCaption"><slot name="desc"></slot></div> | ||||
| 	<span class="button" v-tooltip="checked ? $ts.itsOn : $ts.itsOff"> | ||||
| 		<span class="handle"></span> | ||||
| 	</span> | ||||
| 	<span class="label"> | ||||
| 		<span><slot></slot></span> | ||||
| 		<p><slot name="caption"></slot></p> | ||||
| 	</span> | ||||
| </div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import './form.scss'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	props: { | ||||
| 		value: { | ||||
| 		modelValue: { | ||||
| 			type: Boolean, | ||||
| 			default: false | ||||
| 		}, | ||||
|  | @ -40,91 +39,110 @@ export default defineComponent({ | |||
| 	}, | ||||
| 	computed: { | ||||
| 		checked(): boolean { | ||||
| 			return this.value; | ||||
| 			return this.modelValue; | ||||
| 		} | ||||
| 	}, | ||||
| 	methods: { | ||||
| 		toggle() { | ||||
| 			if (this.disabled) return; | ||||
| 			this.$emit('update:value', !this.checked); | ||||
| 			this.$emit('update:modelValue', !this.checked); | ||||
| 		} | ||||
| 	} | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| .ijnpvmgr { | ||||
| 	> .main { | ||||
| .ziffeoms { | ||||
| 	position: relative; | ||||
| 	display: flex; | ||||
| 	cursor: pointer; | ||||
| 	transition: all 0.3s; | ||||
| 
 | ||||
| 	&:first-child { | ||||
| 		margin-top: 0; | ||||
| 	} | ||||
| 
 | ||||
| 	&:last-child { | ||||
| 		margin-bottom: 0; | ||||
| 	} | ||||
| 
 | ||||
| 	> * { | ||||
| 		user-select: none; | ||||
| 	} | ||||
| 
 | ||||
| 	> input { | ||||
| 		position: absolute; | ||||
| 		width: 0; | ||||
| 		height: 0; | ||||
| 		opacity: 0; | ||||
| 		margin: 0; | ||||
| 	} | ||||
| 
 | ||||
| 	> .button { | ||||
| 		position: relative; | ||||
| 		display: flex; | ||||
| 		padding: 14px 16px; | ||||
| 		cursor: pointer; | ||||
| 		display: inline-block; | ||||
| 		flex-shrink: 0; | ||||
| 		margin: 0; | ||||
| 		width: 36px; | ||||
| 		height: 26px; | ||||
| 		background: var(--switchBg); | ||||
| 		outline: none; | ||||
| 		border-radius: 999px; | ||||
| 		transition: inherit; | ||||
| 
 | ||||
| 		> * { | ||||
| 			user-select: none; | ||||
| 		} | ||||
| 
 | ||||
| 		&.disabled { | ||||
| 			opacity: 0.6; | ||||
| 			cursor: not-allowed; | ||||
| 		} | ||||
| 
 | ||||
| 		&.checked { | ||||
| 			> .button { | ||||
| 				background-color: var(--X10); | ||||
| 				border-color: var(--X10); | ||||
| 
 | ||||
| 				> * { | ||||
| 					background-color: var(--accent); | ||||
| 					transform: translateX(14px); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		> input { | ||||
| 		> .handle { | ||||
| 			position: absolute; | ||||
| 			width: 0; | ||||
| 			height: 0; | ||||
| 			opacity: 0; | ||||
| 			margin: 0; | ||||
| 			top: 0; | ||||
| 			bottom: 0; | ||||
| 			left: 5px; | ||||
| 			margin: auto 0; | ||||
| 			border-radius: 100%; | ||||
| 			transition: background-color 0.3s, transform 0.3s; | ||||
| 			width: 16px; | ||||
| 			height: 16px; | ||||
| 			background-color: #fff; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 		> .button { | ||||
| 			position: relative; | ||||
| 			display: inline-block; | ||||
| 			flex-shrink: 0; | ||||
| 			margin: 3px 0 0 0; | ||||
| 			width: 34px; | ||||
| 			height: 14px; | ||||
| 			background: var(--X6); | ||||
| 			outline: none; | ||||
| 			border-radius: 14px; | ||||
| 			transition: all 0.3s; | ||||
| 			cursor: pointer; | ||||
| 	> .label { | ||||
| 		margin-left: 16px; | ||||
| 		margin-top: 2px; | ||||
| 		display: block; | ||||
| 		cursor: pointer; | ||||
| 		transition: inherit; | ||||
| 		color: var(--fg); | ||||
| 
 | ||||
| 			> * { | ||||
| 				position: absolute; | ||||
| 				top: -3px; | ||||
| 				left: 0; | ||||
| 				border-radius: 100%; | ||||
| 				transition: background-color 0.3s, transform 0.3s; | ||||
| 				width: 20px; | ||||
| 				height: 20px; | ||||
| 				background-color: #fff; | ||||
| 				box-shadow: 0 2px 1px -1px rgba(#000, 0.2), 0 1px 1px 0 rgba(#000, 0.14), 0 1px 3px 0 rgba(#000, 0.12); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		> .label { | ||||
| 			margin-left: 12px; | ||||
| 		> span { | ||||
| 			display: block; | ||||
| 			line-height: 20px; | ||||
| 			transition: inherit; | ||||
| 			color: var(--fg); | ||||
| 		} | ||||
| 
 | ||||
| 			> span { | ||||
| 				display: block; | ||||
| 				line-height: 20px; | ||||
| 				transition: inherit; | ||||
| 		> p { | ||||
| 			margin: 0; | ||||
| 			color: var(--fgTransparentWeak); | ||||
| 			font-size: 90%; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	&:hover { | ||||
| 		> .button { | ||||
| 			background-color: var(--accentedBg); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	&.disabled { | ||||
| 		opacity: 0.6; | ||||
| 		cursor: not-allowed; | ||||
| 	} | ||||
| 
 | ||||
| 	&.checked { | ||||
| 		> .button { | ||||
| 			background-color: var(--accent); | ||||
| 			border-color: var(--accent); | ||||
| 
 | ||||
| 			> .handle { | ||||
| 				transform: translateX(10px); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  |  | |||
|  | @ -1,40 +1,45 @@ | |||
| <template> | ||||
| <FormGroup class="_formItem"> | ||||
| 	<template #label><slot></slot></template> | ||||
| 	<div class="rivhosbp _formItem" :class="{ tall, pre }"> | ||||
| 		<div class="input _formPanel"> | ||||
| 			<textarea ref="input" :class="{ code, _monospace: code }" | ||||
| 				v-model="v" | ||||
| 				:required="required" | ||||
| 				:readonly="readonly" | ||||
| 				:pattern="pattern" | ||||
| 				:autocomplete="autocomplete" | ||||
| 				:spellcheck="!code" | ||||
| 				@input="onInput" | ||||
| 				@focus="focused = true" | ||||
| 				@blur="focused = false" | ||||
| 			></textarea> | ||||
| 		</div> | ||||
| <div class="adhpbeos"> | ||||
| 	<div class="label" @click="focus"><slot name="label"></slot></div> | ||||
| 	<div class="input" :class="{ disabled, focused, tall, pre }"> | ||||
| 		<textarea ref="inputEl" | ||||
| 			:class="{ code, _monospace: code }" | ||||
| 			v-model="v" | ||||
| 			:disabled="disabled" | ||||
| 			:required="required" | ||||
| 			:readonly="readonly" | ||||
| 			:placeholder="placeholder" | ||||
| 			:pattern="pattern" | ||||
| 			:autocomplete="autocomplete" | ||||
| 			:spellcheck="spellcheck" | ||||
| 			@focus="focused = true" | ||||
| 			@blur="focused = false" | ||||
| 			@keydown="onKeydown($event)" | ||||
| 			@input="onInput" | ||||
| 		></textarea> | ||||
| 	</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, ref, toRefs, watch } from 'vue'; | ||||
| import './form.scss'; | ||||
| import FormButton from './button.vue'; | ||||
| import FormGroup from './group.vue'; | ||||
| import { defineComponent, onMounted, onUnmounted, nextTick, ref, watch, computed, toRefs } from 'vue'; | ||||
| import MkButton from '../ui/button.vue'; | ||||
| import { debounce } from 'throttle-debounce'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
| 		FormGroup, | ||||
| 		FormButton, | ||||
| 		MkButton, | ||||
| 	}, | ||||
| 
 | ||||
| 	props: { | ||||
| 		value: { | ||||
| 		modelValue: { | ||||
| 			required: true | ||||
| 		}, | ||||
| 		type: { | ||||
| 			type: String, | ||||
| 			required: false | ||||
| 		}, | ||||
| 		required: { | ||||
|  | @ -45,14 +50,29 @@ export default defineComponent({ | |||
| 			type: Boolean, | ||||
| 			required: false | ||||
| 		}, | ||||
| 		disabled: { | ||||
| 			type: Boolean, | ||||
| 			required: false | ||||
| 		}, | ||||
| 		pattern: { | ||||
| 			type: String, | ||||
| 			required: false | ||||
| 		}, | ||||
| 		autocomplete: { | ||||
| 		placeholder: { | ||||
| 			type: String, | ||||
| 			required: false | ||||
| 		}, | ||||
| 		autofocus: { | ||||
| 			type: Boolean, | ||||
| 			required: false, | ||||
| 			default: false | ||||
| 		}, | ||||
| 		autocomplete: { | ||||
| 			required: false | ||||
| 		}, | ||||
| 		spellcheck: { | ||||
| 			required: false | ||||
| 		}, | ||||
| 		code: { | ||||
| 			type: Boolean, | ||||
| 			required: false | ||||
|  | @ -67,91 +87,162 @@ 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', 'update:modelValue'], | ||||
| 
 | ||||
| 	setup(props, context) { | ||||
| 		const { value } = toRefs(props); | ||||
| 		const v = ref(value.value); | ||||
| 		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; | ||||
| 			context.emit('change', ev); | ||||
| 		}; | ||||
| 		const onKeydown = (ev: KeyboardEvent) => { | ||||
| 			context.emit('keydown', ev); | ||||
| 
 | ||||
| 			if (ev.code === 'Enter') { | ||||
| 				context.emit('enter'); | ||||
| 			} | ||||
| 		}; | ||||
| 
 | ||||
| 		const updated = () => { | ||||
| 			changed.value = false; | ||||
| 			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; | ||||
| 		}); | ||||
| 		 | ||||
| 
 | ||||
| 		onMounted(() => { | ||||
| 			nextTick(() => { | ||||
| 				if (autofocus.value) { | ||||
| 					focus(); | ||||
| 				} | ||||
| 			}); | ||||
| 		}); | ||||
| 
 | ||||
| 		return { | ||||
| 			v, | ||||
| 			updated, | ||||
| 			focused, | ||||
| 			invalid, | ||||
| 			changed, | ||||
| 			filled, | ||||
| 			inputEl, | ||||
| 			focus, | ||||
| 			onInput, | ||||
| 			onKeydown, | ||||
| 			updated, | ||||
| 		}; | ||||
| 	} | ||||
| 	}, | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| .rivhosbp { | ||||
| 	position: relative; | ||||
| .adhpbeos { | ||||
| 	> .label { | ||||
| 		font-size: 0.85em; | ||||
| 		padding: 0 0 8px 12px; | ||||
| 		user-select: none; | ||||
| 
 | ||||
| 		&:empty { | ||||
| 			display: none; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	> .caption { | ||||
| 		font-size: 0.8em; | ||||
| 		padding: 8px 0 0 12px; | ||||
| 		color: var(--fgTransparentWeak); | ||||
| 
 | ||||
| 		&:empty { | ||||
| 			display: none; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	> .input { | ||||
| 		position: relative; | ||||
| 	 | ||||
| 
 | ||||
| 		> textarea { | ||||
| 			appearance: none; | ||||
| 			-webkit-appearance: none; | ||||
| 			display: block; | ||||
| 			width: 100%; | ||||
| 			min-width: 100%; | ||||
| 			max-width: 100%; | ||||
| 			min-height: 130px; | ||||
| 			margin: 0; | ||||
| 			padding: 16px; | ||||
| 			box-sizing: border-box; | ||||
| 			padding: 12px; | ||||
| 			font: inherit; | ||||
| 			font-weight: normal; | ||||
| 			font-size: 1em; | ||||
| 			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; | ||||
| 			color: var(--fg); | ||||
| 			box-sizing: border-box; | ||||
| 			transition: border-color 0.1s ease-out; | ||||
| 
 | ||||
| 			&.code { | ||||
| 				tab-size: 2; | ||||
| 			&:hover { | ||||
| 				border-color: var(--inputBorderHover); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	&.tall { | ||||
| 		> .input { | ||||
| 		&.focused { | ||||
| 			> textarea { | ||||
| 				border-color: var(--accent); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		&.disabled { | ||||
| 			opacity: 0.7; | ||||
| 
 | ||||
| 			&, * { | ||||
| 				cursor: not-allowed !important; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		&.tall { | ||||
| 			> textarea { | ||||
| 				min-height: 200px; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	&.pre { | ||||
| 		> .input { | ||||
| 		&.pre { | ||||
| 			> textarea { | ||||
| 				white-space: pre; | ||||
| 			} | ||||
|  |  | |||
|  | @ -36,7 +36,7 @@ | |||
| <script lang="ts"> | ||||
| import { defineComponent, markRaw } from 'vue'; | ||||
| import Chart from 'chart.js'; | ||||
| import MkSelect from './ui/select.vue'; | ||||
| import MkSelect from './form/select.vue'; | ||||
| import number from '@client/filters/number'; | ||||
| 
 | ||||
| const sum = (...arr) => arr.reduce((r, a) => r.map((b, i) => a[i] + b)); | ||||
|  |  | |||
|  | @ -59,7 +59,7 @@ | |||
| 			<div class="body"> | ||||
| 				<p v-if="appearNote.cw != null" class="cw"> | ||||
| 					<Mfm v-if="appearNote.cw != ''" class="text" :text="appearNote.cw" :author="appearNote.user" :i="$i" :custom-emojis="appearNote.emojis"/> | ||||
| 					<XCwButton v-model:value="showContent" :note="appearNote"/> | ||||
| 					<XCwButton v-model="showContent" :note="appearNote"/> | ||||
| 				</p> | ||||
| 				<div class="content" v-show="appearNote.cw == null || showContent"> | ||||
| 					<div class="text"> | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ | |||
| 		<div class="body"> | ||||
| 			<p v-if="note.cw != null" class="cw"> | ||||
| 				<span class="text" v-if="note.cw != ''">{{ note.cw }}</span> | ||||
| 				<XCwButton v-model:value="showContent" :note="note"/> | ||||
| 				<XCwButton v-model="showContent" :note="note"/> | ||||
| 			</p> | ||||
| 			<div class="content" v-show="note.cw == null || showContent"> | ||||
| 				<XSubNote-content class="text" :note="note"/> | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ | |||
| 			<div class="body"> | ||||
| 				<p v-if="note.cw != null" class="cw"> | ||||
| 					<Mfm v-if="note.cw != ''" class="text" :text="note.cw" :author="note.user" :i="$i" :custom-emojis="note.emojis" /> | ||||
| 					<XCwButton v-model:value="showContent" :note="note"/> | ||||
| 					<XCwButton v-model="showContent" :note="note"/> | ||||
| 				</p> | ||||
| 				<div class="content" v-show="note.cw == null || showContent"> | ||||
| 					<XSubNote-content class="text" :note="note"/> | ||||
|  |  | |||
|  | @ -43,7 +43,7 @@ | |||
| 			<div class="body"> | ||||
| 				<p v-if="appearNote.cw != null" class="cw"> | ||||
| 					<Mfm v-if="appearNote.cw != ''" class="text" :text="appearNote.cw" :author="appearNote.user" :i="$i" :custom-emojis="appearNote.emojis"/> | ||||
| 					<XCwButton v-model:value="showContent" :note="appearNote"/> | ||||
| 					<XCwButton v-model="showContent" :note="appearNote"/> | ||||
| 				</p> | ||||
| 				<div class="content" :class="{ collapsed }" v-show="appearNote.cw == null || showContent"> | ||||
| 					<div class="text"> | ||||
|  |  | |||
|  | @ -29,7 +29,7 @@ | |||
| <script lang="ts"> | ||||
| import { defineComponent, PropType } from 'vue'; | ||||
| import XModalWindow from '@client/components/ui/modal-window.vue'; | ||||
| import MkSwitch from './ui/switch.vue'; | ||||
| import MkSwitch from './form/switch.vue'; | ||||
| import MkInfo from './ui/info.vue'; | ||||
| import MkButton from './ui/button.vue'; | ||||
| import { notificationTypes } from '../../types'; | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { computed, defineComponent, PropType } from 'vue'; | ||||
| import MkInput from '../ui/input.vue'; | ||||
| import MkInput from '../form/input.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import { Hpml } from '@client/scripts/hpml/evaluator'; | ||||
| import { NumberInputVarBlock } from '@client/scripts/hpml/block'; | ||||
|  |  | |||
|  | @ -10,7 +10,7 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent, PropType } from 'vue'; | ||||
| import MkTextarea from '../ui/textarea.vue'; | ||||
| import MkTextarea from '../form/textarea.vue'; | ||||
| import MkButton from '../ui/button.vue'; | ||||
| import { apiUrl } from '@client/config'; | ||||
| import * as os from '@client/os'; | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { computed, defineComponent, PropType } from 'vue'; | ||||
| import MkRadio from '../ui/radio.vue'; | ||||
| import MkRadio from '../form/radio.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import { Hpml } from '@client/scripts/hpml/evaluator'; | ||||
| import { RadioButtonVarBlock } from '@client/scripts/hpml/block'; | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { computed, defineComponent, PropType } from 'vue'; | ||||
| import MkSwitch from '../ui/switch.vue'; | ||||
| import MkSwitch from '../form/switch.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import { Hpml } from '@client/scripts/hpml/evaluator'; | ||||
| import { SwitchVarBlock } from '@client/scripts/hpml/block'; | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { computed, defineComponent, PropType } from 'vue'; | ||||
| import MkInput from '../ui/input.vue'; | ||||
| import MkInput from '../form/input.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import { Hpml } from '@client/scripts/hpml/evaluator'; | ||||
| import { TextInputVarBlock } from '@client/scripts/hpml/block'; | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { computed, defineComponent, PropType } from 'vue'; | ||||
| import MkTextarea from '../ui/textarea.vue'; | ||||
| import MkTextarea from '../form/textarea.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import { Hpml } from '@client/scripts/hpml/evaluator'; | ||||
| import { HpmlTextInput } from '@client/scripts/hpml'; | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ | |||
| import { TextBlock } from '@client/scripts/hpml/block'; | ||||
| import { Hpml } from '@client/scripts/hpml/evaluator'; | ||||
| import { defineComponent, PropType } from 'vue'; | ||||
| import MkTextarea from '../ui/textarea.vue'; | ||||
| import MkTextarea from '../form/textarea.vue'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
|  |  | |||
|  | @ -51,9 +51,9 @@ | |||
| import { defineComponent } from 'vue'; | ||||
| import { addTime } from '../../prelude/time'; | ||||
| import { formatDateTimeString } from '@/misc/format-time-string'; | ||||
| import MkInput from './ui/input.vue'; | ||||
| import MkSelect from './ui/select.vue'; | ||||
| import MkSwitch from './ui/switch.vue'; | ||||
| import MkInput from './form/input.vue'; | ||||
| import MkSelect from './form/select.vue'; | ||||
| import MkSwitch from './form/switch.vue'; | ||||
| import MkButton from './ui/button.vue'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
|  |  | |||
|  | @ -30,10 +30,10 @@ | |||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import MkInput from '@client/components/ui/input.vue'; | ||||
| import MkSwitch from '@client/components/ui/switch.vue'; | ||||
| import MkTextarea from '@client/components/ui/textarea.vue'; | ||||
| import MkRadio from '@client/components/ui/radio.vue'; | ||||
| import MkInput from '@client/components/form/input.vue'; | ||||
| import MkSwitch from '@client/components/form/switch.vue'; | ||||
| import MkTextarea from '@client/components/form/textarea.vue'; | ||||
| import MkRadio from '@client/components/form/radio.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import * as config from '@client/config'; | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,17 +1,17 @@ | |||
| <template> | ||||
| <form class="eppvobhk _monolithic_" :class="{ signing, totpLogin }" @submit.prevent="onSubmit"> | ||||
| 	<div class="auth _section"> | ||||
| 	<div class="auth _section _formRoot"> | ||||
| 		<div class="avatar" :style="{ backgroundImage: user ? `url('${ user.avatarUrl }')` : null }" v-show="withAvatar"></div> | ||||
| 		<div class="normal-signin" v-if="!totpLogin"> | ||||
| 			<MkInput v-model="username" :placeholder="$ts.username" type="text" pattern="^[a-zA-Z0-9_]+$" spellcheck="false" autofocus required @update:modelValue="onUsernameChange" data-cy-signin-username> | ||||
| 			<MkInput class="_formBlock" v-model="username" :placeholder="$ts.username" type="text" pattern="^[a-zA-Z0-9_]+$" spellcheck="false" autofocus required @update:modelValue="onUsernameChange" data-cy-signin-username> | ||||
| 				<template #prefix>@</template> | ||||
| 				<template #suffix>@{{ host }}</template> | ||||
| 			</MkInput> | ||||
| 			<MkInput v-model="password" :placeholder="$ts.password" type="password" :with-password-toggle="true" v-if="!user || user && !user.usePasswordLessLogin" required data-cy-signin-password> | ||||
| 			<MkInput class="_formBlock" v-model="password" :placeholder="$ts.password" type="password" :with-password-toggle="true" v-if="!user || user && !user.usePasswordLessLogin" required data-cy-signin-password> | ||||
| 				<template #prefix><i class="fas fa-lock"></i></template> | ||||
| 				<template #caption><button class="_textButton" @click="resetPassword" type="button">{{ $ts.forgotPassword }}</button></template> | ||||
| 			</MkInput> | ||||
| 			<MkButton type="submit" primary :disabled="signing" style="margin: 0 auto;">{{ signing ? $ts.loggingIn : $ts.login }}</MkButton> | ||||
| 			<MkButton class="_formBlock" type="submit" primary :disabled="signing" style="margin: 0 auto;">{{ signing ? $ts.loggingIn : $ts.login }}</MkButton> | ||||
| 		</div> | ||||
| 		<div class="2fa-signin" v-if="totpLogin" :class="{ securityKeys: user && user.securityKeys }"> | ||||
| 			<div v-if="user && user.securityKeys" class="twofa-group tap-group"> | ||||
|  | @ -49,7 +49,7 @@ | |||
| import { defineComponent } from 'vue'; | ||||
| import { toUnicode } from 'punycode/'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import MkInput from '@client/components/ui/input.vue'; | ||||
| import MkInput from '@client/components/form/input.vue'; | ||||
| import { apiUrl, host } from '@client/config'; | ||||
| import { byteify, hexify } from '@client/scripts/2fa'; | ||||
| import * as os from '@client/os'; | ||||
|  |  | |||
|  | @ -1,11 +1,11 @@ | |||
| <template> | ||||
| <form class="qlvuhzng" @submit.prevent="onSubmit" :autocomplete="Math.random()"> | ||||
| <form class="qlvuhzng _formRoot" @submit.prevent="onSubmit" :autocomplete="Math.random()"> | ||||
| 	<template v-if="meta"> | ||||
| 		<MkInput class="_inputNoTopMargin" v-if="meta.disableRegistration" v-model="invitationCode" type="text" :autocomplete="Math.random()" spellcheck="false" required> | ||||
| 		<MkInput class="_formBlock" v-if="meta.disableRegistration" v-model="invitationCode" type="text" :autocomplete="Math.random()" spellcheck="false" required> | ||||
| 			<template #label>{{ $ts.invitationCode }}</template> | ||||
| 			<template #prefix><i class="fas fa-key"></i></template> | ||||
| 		</MkInput> | ||||
| 		<MkInput class="_inputNoTopMargin" v-model="username" type="text" pattern="^[a-zA-Z0-9_]{1,20}$" :autocomplete="Math.random()" spellcheck="false" required @update:modelValue="onChangeUsername" data-cy-signup-username> | ||||
| 		<MkInput class="_formBlock" v-model="username" type="text" pattern="^[a-zA-Z0-9_]{1,20}$" :autocomplete="Math.random()" spellcheck="false" required @update:modelValue="onChangeUsername" data-cy-signup-username> | ||||
| 			<template #label>{{ $ts.username }} <div class="_button _help" v-tooltip:dialog="$ts.usernameInfo"><i class="far fa-question-circle"></i></div></template> | ||||
| 			<template #prefix>@</template> | ||||
| 			<template #suffix>@{{ host }}</template> | ||||
|  | @ -19,7 +19,7 @@ | |||
| 				<span v-if="usernameState == 'max-range'" style="color: var(--error)"><i class="fas fa-exclamation-triangle fa-fw"></i> {{ $ts.tooLong }}</span> | ||||
| 			</template> | ||||
| 		</MkInput> | ||||
| 		<MkInput v-model="password" type="password" :autocomplete="Math.random()" required @update:modelValue="onChangePassword" data-cy-signup-password> | ||||
| 		<MkInput class="_formBlock" v-model="password" type="password" :autocomplete="Math.random()" required @update:modelValue="onChangePassword" data-cy-signup-password> | ||||
| 			<template #label>{{ $ts.password }}</template> | ||||
| 			<template #prefix><i class="fas fa-lock"></i></template> | ||||
| 			<template #caption> | ||||
|  | @ -28,7 +28,7 @@ | |||
| 				<span v-if="passwordStrength == 'high'" style="color: var(--success)"><i class="fas fa-check fa-fw"></i> {{ $ts.strongPassword }}</span> | ||||
| 			</template> | ||||
| 		</MkInput> | ||||
| 		<MkInput v-model="retypedPassword" type="password" :autocomplete="Math.random()" required @update:modelValue="onChangePasswordRetype" data-cy-signup-password-retype> | ||||
| 		<MkInput class="_formBlock" v-model="retypedPassword" type="password" :autocomplete="Math.random()" required @update:modelValue="onChangePasswordRetype" data-cy-signup-password-retype> | ||||
| 			<template #label>{{ $ts.password }} ({{ $ts.retype }})</template> | ||||
| 			<template #prefix><i class="fas fa-lock"></i></template> | ||||
| 			<template #caption> | ||||
|  | @ -36,7 +36,7 @@ | |||
| 				<span v-if="passwordRetypeState == 'not-match'" style="color: var(--error)"><i class="fas fa-exclamation-triangle fa-fw"></i> {{ $ts.passwordNotMatched }}</span> | ||||
| 			</template> | ||||
| 		</MkInput> | ||||
| 		<label v-if="meta.tosUrl" class="tou"> | ||||
| 		<label v-if="meta.tosUrl" class="_formBlock tou"> | ||||
| 			<input type="checkbox" v-model="ToSAgreement"> | ||||
| 			<I18n :src="$ts.agreeTo"> | ||||
| 				<template #0> | ||||
|  | @ -44,9 +44,9 @@ | |||
| 				</template> | ||||
| 			</I18n> | ||||
| 		</label> | ||||
| 		<captcha v-if="meta.enableHcaptcha" class="captcha" provider="hcaptcha" ref="hcaptcha" v-model:value="hCaptchaResponse" :sitekey="meta.hcaptchaSiteKey"/> | ||||
| 		<captcha v-if="meta.enableRecaptcha" class="captcha" provider="recaptcha" ref="recaptcha" v-model:value="reCaptchaResponse" :sitekey="meta.recaptchaSiteKey"/> | ||||
| 		<MkButton type="submit" :disabled="shouldDisableSubmitting" primary data-cy-signup-submit>{{ $ts.start }}</MkButton> | ||||
| 		<captcha v-if="meta.enableHcaptcha" class="_formBlock captcha" provider="hcaptcha" ref="hcaptcha" v-model="hCaptchaResponse" :sitekey="meta.hcaptchaSiteKey"/> | ||||
| 		<captcha v-if="meta.enableRecaptcha" class="_formBlock captcha" provider="recaptcha" ref="recaptcha" v-model="reCaptchaResponse" :sitekey="meta.recaptchaSiteKey"/> | ||||
| 		<MkButton class="_formBlock" type="submit" :disabled="shouldDisableSubmitting" primary data-cy-signup-submit>{{ $ts.start }}</MkButton> | ||||
| 	</template> | ||||
| </form> | ||||
| </template> | ||||
|  | @ -57,8 +57,8 @@ const getPasswordStrength = require('syuilo-password-strength'); | |||
| import { toUnicode } from 'punycode/'; | ||||
| import { host, url } from '@client/config'; | ||||
| import MkButton from './ui/button.vue'; | ||||
| import MkInput from './ui/input.vue'; | ||||
| import MkSwitch from './ui/switch.vue'; | ||||
| import MkInput from './form/input.vue'; | ||||
| import MkSwitch from './form/switch.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import { login } from '@client/account'; | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ import { defineComponent, h, resolveDirective, withDirectives } from 'vue'; | |||
| 
 | ||||
| export default defineComponent({ | ||||
| 	props: { | ||||
| 		value: { | ||||
| 		modelValue: { | ||||
| 			required: true, | ||||
| 		}, | ||||
| 	}, | ||||
|  | @ -13,11 +13,11 @@ export default defineComponent({ | |||
| 		return withDirectives(h('div', { | ||||
| 			class: 'pxhvhrfw', | ||||
| 		}, options.map(option => withDirectives(h('button', { | ||||
| 			class: ['_button', { active: this.value === option.props.value }], | ||||
| 			class: ['_button', { active: this.modelValue === option.props.modelValue }], | ||||
| 			key: option.key, | ||||
| 			disabled: this.value === option.props.value, | ||||
| 			disabled: this.modelValue === option.props.modelValue, | ||||
| 			onClick: () => { | ||||
| 				this.$emit('update:value', option.props.value); | ||||
| 				this.$emit('update:modelValue', option.props.modelValue); | ||||
| 			} | ||||
| 		}, option.children), [ | ||||
| 			[resolveDirective('click-anime')] | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ | |||
| 	<template #header>Req Viewer</template> | ||||
| 
 | ||||
| 	<div class="rlkneywz"> | ||||
| 		<MkTab v-model:value="tab" style="border-bottom: solid 0.5px var(--divider);"> | ||||
| 		<MkTab v-model="tab" style="border-bottom: solid 0.5px var(--divider);"> | ||||
| 			<option value="req">Request</option> | ||||
| 			<option value="res">Response</option> | ||||
| 		</MkTab> | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ | |||
| 		<i class="fas fa-terminal" style="margin-right: 0.5em;"></i>Task Manager | ||||
| 	</template> | ||||
| 	<div class="qljqmnzj _monospace"> | ||||
| 		<MkTab v-model:value="tab" style="border-bottom: solid 0.5px var(--divider);"> | ||||
| 		<MkTab v-model="tab" style="border-bottom: solid 0.5px var(--divider);"> | ||||
| 			<option value="windows">Windows</option> | ||||
| 			<option value="stream">Stream</option> | ||||
| 			<option value="streamPool">Stream (Pool)</option> | ||||
|  |  | |||
|  | @ -31,9 +31,9 @@ | |||
| import { defineComponent } from 'vue'; | ||||
| import { kinds } from '@/misc/api-permissions'; | ||||
| import XModalWindow from '@client/components/ui/modal-window.vue'; | ||||
| import MkInput from './ui/input.vue'; | ||||
| import MkTextarea from './ui/textarea.vue'; | ||||
| import MkSwitch from './ui/switch.vue'; | ||||
| import MkInput from './form/input.vue'; | ||||
| import MkTextarea from './form/textarea.vue'; | ||||
| import MkSwitch from './form/switch.vue'; | ||||
| import MkButton from './ui/button.vue'; | ||||
| import MkInfo from './ui/info.vue'; | ||||
| 
 | ||||
|  |  | |||
|  | @ -181,14 +181,6 @@ export default defineComponent({ | |||
| 		outline-offset: 2px; | ||||
| 	} | ||||
| 
 | ||||
| 	&.inline + .bghgjjyj { | ||||
| 		margin-left: 12px; | ||||
| 	} | ||||
| 
 | ||||
| 	&:not(.inline) + .bghgjjyj { | ||||
| 		margin-top: 16px; | ||||
| 	} | ||||
| 
 | ||||
| 	&.inline { | ||||
| 		display: inline-block; | ||||
| 		width: auto; | ||||
|  |  | |||
|  | @ -1,58 +0,0 @@ | |||
| <script lang="ts"> | ||||
| import { defineComponent, h } from 'vue'; | ||||
| import MkRadio from '@client/components/ui/radio.vue'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
| 		MkRadio | ||||
| 	}, | ||||
| 	props: { | ||||
| 		modelValue: { | ||||
| 			required: false | ||||
| 		}, | ||||
| 	}, | ||||
| 	data() { | ||||
| 		return { | ||||
| 			value: this.modelValue, | ||||
| 		} | ||||
| 	}, | ||||
| 	watch: { | ||||
| 		value() { | ||||
| 			this.$emit('update:modelValue', this.value); | ||||
| 		} | ||||
| 	}, | ||||
| 	render() { | ||||
| 		const label = this.$slots.desc(); | ||||
| 		let options = this.$slots.default(); | ||||
| 
 | ||||
| 		// なぜかFragmentになることがあるため | ||||
| 		if (options.length === 1 && options[0].props == null) options = options[0].children; | ||||
| 
 | ||||
| 		return h('div', { | ||||
| 			class: 'novjtcto' | ||||
| 		}, [ | ||||
| 			h('div', label), | ||||
| 			...options.map(option => h(MkRadio, { | ||||
| 				key: option.key, | ||||
| 				value: option.props.value, | ||||
| 				modelValue: this.value, | ||||
| 				'onUpdate:modelValue': value => this.value = value, | ||||
| 			}, option.children)) | ||||
| 		]); | ||||
| 	} | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss"> | ||||
| .novjtcto { | ||||
| 	margin: 32px 0; | ||||
| 
 | ||||
| 	&:first-child { | ||||
| 		margin-top: 0; | ||||
| 	} | ||||
| 
 | ||||
| 	&:last-child { | ||||
| 		margin-bottom: 0; | ||||
| 	} | ||||
| } | ||||
| </style> | ||||
|  | @ -1,139 +0,0 @@ | |||
| <template> | ||||
| <div class="timctyfi" :class="{ focused, disabled }"> | ||||
| 	<div class="icon"><slot name="icon"></slot></div> | ||||
| 	<span class="label"><slot name="label"></slot></span> | ||||
| 	<input | ||||
| 		type="range" | ||||
| 		ref="input" | ||||
| 		v-model="v" | ||||
| 		:disabled="disabled" | ||||
| 		:min="min" | ||||
| 		:max="max" | ||||
| 		:step="step" | ||||
| 		:autofocus="autofocus" | ||||
| 		@focus="focused = true" | ||||
| 		@blur="focused = false" | ||||
| 		@input="$emit('update:value', $event.target.value)" | ||||
| 	/> | ||||
| </div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	props: { | ||||
| 		value: { | ||||
| 			type: Number, | ||||
| 			required: false, | ||||
| 			default: 0 | ||||
| 		}, | ||||
| 		disabled: { | ||||
| 			type: Boolean, | ||||
| 			required: false, | ||||
| 			default: false | ||||
| 		}, | ||||
| 		min: { | ||||
| 			type: Number, | ||||
| 			required: false, | ||||
| 			default: 0 | ||||
| 		}, | ||||
| 		max: { | ||||
| 			type: Number, | ||||
| 			required: false, | ||||
| 			default: 100 | ||||
| 		}, | ||||
| 		step: { | ||||
| 			type: Number, | ||||
| 			required: false, | ||||
| 			default: 1 | ||||
| 		}, | ||||
| 		autofocus: { | ||||
| 			type: Boolean, | ||||
| 			required: false | ||||
| 		} | ||||
| 	}, | ||||
| 	data() { | ||||
| 		return { | ||||
| 			v: this.value, | ||||
| 			focused: false | ||||
| 		}; | ||||
| 	}, | ||||
| 	watch: { | ||||
| 		value(v) { | ||||
| 			this.v = parseFloat(v); | ||||
| 		} | ||||
| 	}, | ||||
| 	mounted() { | ||||
| 		if (this.autofocus) { | ||||
| 			this.$nextTick(() => { | ||||
| 				this.$refs.input.focus(); | ||||
| 			}); | ||||
| 		} | ||||
| 	} | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| .timctyfi { | ||||
| 	position: relative; | ||||
| 	margin: 8px; | ||||
| 
 | ||||
| 	> .icon { | ||||
| 		display: inline-block; | ||||
| 		width: 24px; | ||||
| 		text-align: center; | ||||
| 	} | ||||
| 
 | ||||
| 	> .title { | ||||
| 		pointer-events: none; | ||||
| 		font-size: 16px; | ||||
| 		color: var(--inputLabel); | ||||
| 		overflow: hidden; | ||||
| 	} | ||||
| 
 | ||||
| 	> input { | ||||
| 		-webkit-appearance: none; | ||||
| 		-moz-appearance: none; | ||||
| 		appearance: none; | ||||
| 		background: var(--X10); | ||||
| 		height: 7px; | ||||
| 		margin: 0 8px; | ||||
| 		outline: 0; | ||||
| 		border: 0; | ||||
| 		border-radius: 7px; | ||||
| 
 | ||||
| 		&.disabled { | ||||
| 			opacity: 0.6; | ||||
| 			cursor: not-allowed; | ||||
| 		} | ||||
| 
 | ||||
| 		&::-webkit-slider-thumb { | ||||
| 			-webkit-appearance: none; | ||||
| 			appearance: none; | ||||
| 			cursor: pointer; | ||||
| 			width: 20px; | ||||
| 			height: 20px; | ||||
| 			display: block; | ||||
| 			border-radius: 50%; | ||||
| 			border: none; | ||||
| 			background: var(--accent); | ||||
| 			box-shadow: 0 0 6px rgba(0, 0, 0, 0.3); | ||||
| 			box-sizing: content-box; | ||||
| 		} | ||||
| 
 | ||||
| 		&::-moz-range-thumb { | ||||
| 			-moz-appearance: none; | ||||
| 			appearance: none; | ||||
| 			cursor: pointer; | ||||
| 			width: 20px; | ||||
| 			height: 20px; | ||||
| 			display: block; | ||||
| 			border-radius: 50%; | ||||
| 			border: none; | ||||
| 			background: var(--accent); | ||||
| 			box-shadow: 0 0 6px rgba(0, 0, 0, 0.3); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| </style> | ||||
|  | @ -1,262 +0,0 @@ | |||
| <template> | ||||
| <div class="vblkjoeq"> | ||||
| 	<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> | ||||
| 		<select ref="inputEl" | ||||
| 			v-model="v" | ||||
| 			:disabled="disabled" | ||||
| 			:required="required" | ||||
| 			:readonly="readonly" | ||||
| 			:placeholder="placeholder" | ||||
| 			@focus="focused = true" | ||||
| 			@blur="focused = false" | ||||
| 			@input="onInput" | ||||
| 		> | ||||
| 			<slot></slot> | ||||
| 		</select> | ||||
| 		<div class="suffix" ref="suffixEl"><i class="fas fa-chevron-down"></i></div> | ||||
| 	</div> | ||||
| 	<div class="caption"><slot name="caption"></slot></div> | ||||
| 
 | ||||
| 	<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 MkButton from './button.vue'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
| 		MkButton, | ||||
| 	}, | ||||
| 
 | ||||
| 	props: { | ||||
| 		modelValue: { | ||||
| 			required: true | ||||
| 		}, | ||||
| 		required: { | ||||
| 			type: Boolean, | ||||
| 			required: false | ||||
| 		}, | ||||
| 		readonly: { | ||||
| 			type: Boolean, | ||||
| 			required: false | ||||
| 		}, | ||||
| 		disabled: { | ||||
| 			type: Boolean, | ||||
| 			required: false | ||||
| 		}, | ||||
| 		placeholder: { | ||||
| 			type: String, | ||||
| 			required: false | ||||
| 		}, | ||||
| 		autofocus: { | ||||
| 			type: Boolean, | ||||
| 			required: false, | ||||
| 			default: false | ||||
| 		}, | ||||
| 		inline: { | ||||
| 			type: Boolean, | ||||
| 			required: false, | ||||
| 			default: false | ||||
| 		}, | ||||
| 		manualSave: { | ||||
| 			type: Boolean, | ||||
| 			required: false, | ||||
| 			default: false | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	emits: ['change', 'update:modelValue'], | ||||
| 
 | ||||
| 	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 prefixEl = ref(null); | ||||
| 		const suffixEl = ref(null); | ||||
| 
 | ||||
| 		const focus = () => inputEl.value.focus(); | ||||
| 		const onInput = (ev) => { | ||||
| 			changed.value = true; | ||||
| 			context.emit('change', ev); | ||||
| 		}; | ||||
| 
 | ||||
| 		const updated = () => { | ||||
| 			changed.value = false; | ||||
| 			context.emit('update:modelValue', v.value); | ||||
| 		}; | ||||
| 
 | ||||
| 		watch(modelValue, newValue => { | ||||
| 			v.value = newValue; | ||||
| 		}); | ||||
| 
 | ||||
| 		watch(v, newValue => { | ||||
| 			if (!props.manualSave) { | ||||
| 				updated(); | ||||
| 			} | ||||
| 
 | ||||
| 			invalid.value = inputEl.value.validity.badInput; | ||||
| 		}); | ||||
| 
 | ||||
| 		onMounted(() => { | ||||
| 			nextTick(() => { | ||||
| 				if (autofocus.value) { | ||||
| 					focus(); | ||||
| 				} | ||||
| 
 | ||||
| 				// このコンポーネントが作成された時、非表示状態である場合がある | ||||
| 				// 非表示状態だと要素の幅などは0になってしまうので、定期的に計算する | ||||
| 				const clock = setInterval(() => { | ||||
| 					if (prefixEl.value) { | ||||
| 						if (prefixEl.value.offsetWidth) { | ||||
| 							inputEl.value.style.paddingLeft = prefixEl.value.offsetWidth + 'px'; | ||||
| 						} | ||||
| 					} | ||||
| 					if (suffixEl.value) { | ||||
| 						if (suffixEl.value.offsetWidth) { | ||||
| 							inputEl.value.style.paddingRight = suffixEl.value.offsetWidth + 'px'; | ||||
| 						} | ||||
| 					} | ||||
| 				}, 100); | ||||
| 
 | ||||
| 				onUnmounted(() => { | ||||
| 					clearInterval(clock); | ||||
| 				}); | ||||
| 			}); | ||||
| 		}); | ||||
| 
 | ||||
| 		return { | ||||
| 			v, | ||||
| 			focused, | ||||
| 			invalid, | ||||
| 			changed, | ||||
| 			filled, | ||||
| 			inputEl, | ||||
| 			prefixEl, | ||||
| 			suffixEl, | ||||
| 			focus, | ||||
| 			onInput, | ||||
| 			updated, | ||||
| 		}; | ||||
| 	}, | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| .vblkjoeq { | ||||
| 	margin: 1.5em 0; | ||||
| 
 | ||||
| 	> .label { | ||||
| 		font-size: 0.85em; | ||||
| 		padding: 0 0 8px 12px; | ||||
| 		user-select: none; | ||||
| 
 | ||||
| 		&:empty { | ||||
| 			display: none; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	> .caption { | ||||
| 		font-size: 0.8em; | ||||
| 		padding: 8px 0 0 12px; | ||||
| 		color: var(--fgTransparentWeak); | ||||
| 
 | ||||
| 		&:empty { | ||||
| 			display: none; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	> .input { | ||||
| 		$height: 42px; | ||||
| 		position: relative; | ||||
| 
 | ||||
| 		> select { | ||||
| 			appearance: none; | ||||
| 			-webkit-appearance: none; | ||||
| 			display: block; | ||||
| 			height: $height; | ||||
| 			width: 100%; | ||||
| 			margin: 0; | ||||
| 			padding: 0 12px; | ||||
| 			font: inherit; | ||||
| 			font-weight: normal; | ||||
| 			font-size: 1em; | ||||
| 			color: var(--fg); | ||||
| 			background: var(--panel); | ||||
| 			border: solid 1px var(--inputBorder); | ||||
| 			border-radius: 6px; | ||||
| 			outline: none; | ||||
| 			box-shadow: none; | ||||
| 			box-sizing: border-box; | ||||
| 			cursor: pointer; | ||||
| 			transition: border-color 0.1s ease-out; | ||||
| 
 | ||||
| 			&:hover { | ||||
| 				border-color: var(--inputBorderHover); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		> .prefix, | ||||
| 		> .suffix { | ||||
| 			display: flex; | ||||
| 			align-items: center; | ||||
| 			position: absolute; | ||||
| 			z-index: 1; | ||||
| 			top: 0; | ||||
| 			padding: 0 12px; | ||||
| 			font-size: 1em; | ||||
| 			height: $height; | ||||
| 			pointer-events: none; | ||||
| 
 | ||||
| 			&:empty { | ||||
| 				display: none; | ||||
| 			} | ||||
| 
 | ||||
| 			> * { | ||||
| 				display: inline-block; | ||||
| 				min-width: 16px; | ||||
| 				max-width: 150px; | ||||
| 				overflow: hidden; | ||||
| 				white-space: nowrap; | ||||
| 				text-overflow: ellipsis; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		> .prefix { | ||||
| 			left: 0; | ||||
| 			padding-right: 6px; | ||||
| 		} | ||||
| 
 | ||||
| 		> .suffix { | ||||
| 			right: 0; | ||||
| 			padding-left: 6px; | ||||
| 		} | ||||
| 
 | ||||
| 		&.inline { | ||||
| 			display: inline-block; | ||||
| 			margin: 0; | ||||
| 		} | ||||
| 
 | ||||
| 		&.focused { | ||||
| 			> select { | ||||
| 				border-color: var(--accent); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		&.disabled { | ||||
| 			opacity: 0.7; | ||||
| 
 | ||||
| 			&, * { | ||||
| 				cursor: not-allowed !important; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| </style> | ||||
|  | @ -1,144 +0,0 @@ | |||
| <template> | ||||
| <div | ||||
| 	class="ziffeoms" | ||||
| 	:class="{ disabled, checked }" | ||||
| 	role="switch" | ||||
| 	:aria-checked="checked" | ||||
| 	:aria-disabled="disabled" | ||||
| 	@click.prevent="toggle" | ||||
| > | ||||
| 	<input | ||||
| 		type="checkbox" | ||||
| 		ref="input" | ||||
| 		:disabled="disabled" | ||||
| 		@keydown.enter="toggle" | ||||
| 	> | ||||
| 	<span class="button"> | ||||
| 		<span></span> | ||||
| 	</span> | ||||
| 	<span class="label"> | ||||
| 		<span><slot></slot></span> | ||||
| 		<p><slot name="caption"></slot></p> | ||||
| 	</span> | ||||
| </div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	props: { | ||||
| 		modelValue: { | ||||
| 			type: Boolean, | ||||
| 			default: false | ||||
| 		}, | ||||
| 		disabled: { | ||||
| 			type: Boolean, | ||||
| 			default: false | ||||
| 		} | ||||
| 	}, | ||||
| 	computed: { | ||||
| 		checked(): boolean { | ||||
| 			return this.modelValue; | ||||
| 		} | ||||
| 	}, | ||||
| 	methods: { | ||||
| 		toggle() { | ||||
| 			if (this.disabled) return; | ||||
| 			this.$emit('update:modelValue', !this.checked); | ||||
| 		} | ||||
| 	} | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| .ziffeoms { | ||||
| 	position: relative; | ||||
| 	display: flex; | ||||
| 	margin: 32px 0; | ||||
| 	cursor: pointer; | ||||
| 	transition: all 0.3s; | ||||
| 
 | ||||
| 	&:first-child { | ||||
| 		margin-top: 0; | ||||
| 	} | ||||
| 
 | ||||
| 	&:last-child { | ||||
| 		margin-bottom: 0; | ||||
| 	} | ||||
| 
 | ||||
| 	> * { | ||||
| 		user-select: none; | ||||
| 	} | ||||
| 
 | ||||
| 	&.disabled { | ||||
| 		opacity: 0.6; | ||||
| 		cursor: not-allowed; | ||||
| 	} | ||||
| 
 | ||||
| 	&.checked { | ||||
| 		> .button { | ||||
| 			background-color: var(--X10); | ||||
| 			border-color: var(--X10); | ||||
| 
 | ||||
| 			> * { | ||||
| 				background-color: var(--accent); | ||||
| 				transform: translateX(14px); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	> input { | ||||
| 		position: absolute; | ||||
| 		width: 0; | ||||
| 		height: 0; | ||||
| 		opacity: 0; | ||||
| 		margin: 0; | ||||
| 	} | ||||
| 
 | ||||
| 	> .button { | ||||
| 		position: relative; | ||||
| 		display: inline-block; | ||||
| 		flex-shrink: 0; | ||||
| 		margin: 3px 0 0 0; | ||||
| 		width: 34px; | ||||
| 		height: 14px; | ||||
| 		background: var(--X6); | ||||
| 		outline: none; | ||||
| 		border-radius: 14px; | ||||
| 		transition: inherit; | ||||
| 
 | ||||
| 		> * { | ||||
| 			position: absolute; | ||||
| 			top: -3px; | ||||
| 			left: 0; | ||||
| 			border-radius: 100%; | ||||
| 			transition: background-color 0.3s, transform 0.3s; | ||||
| 			width: 20px; | ||||
| 			height: 20px; | ||||
| 			background-color: #fff; | ||||
| 			box-shadow: 0 2px 1px -1px rgba(#000, 0.2), 0 1px 1px 0 rgba(#000, 0.14), 0 1px 3px 0 rgba(#000, 0.12); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	> .label { | ||||
| 		margin-left: 8px; | ||||
| 		display: block; | ||||
| 		cursor: pointer; | ||||
| 		transition: inherit; | ||||
| 		color: var(--fg); | ||||
| 
 | ||||
| 		> span { | ||||
| 			display: block; | ||||
| 			line-height: 20px; | ||||
| 			transition: inherit; | ||||
| 		} | ||||
| 
 | ||||
| 		> p { | ||||
| 			margin: 0; | ||||
| 			color: var(--fgTransparentWeak); | ||||
| 			font-size: 90%; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| </style> | ||||
|  | @ -1,254 +0,0 @@ | |||
| <template> | ||||
| <div class="adhpbeos"> | ||||
| 	<div class="label" @click="focus"><slot name="label"></slot></div> | ||||
| 	<div class="input" :class="{ disabled, focused, tall, pre }"> | ||||
| 		<textarea ref="inputEl" | ||||
| 			:class="{ code, _monospace: code }" | ||||
| 			v-model="v" | ||||
| 			:disabled="disabled" | ||||
| 			:required="required" | ||||
| 			:readonly="readonly" | ||||
| 			:placeholder="placeholder" | ||||
| 			:pattern="pattern" | ||||
| 			:autocomplete="autocomplete" | ||||
| 			:spellcheck="spellcheck" | ||||
| 			@focus="focused = true" | ||||
| 			@blur="focused = false" | ||||
| 			@keydown="onKeydown($event)" | ||||
| 			@input="onInput" | ||||
| 		></textarea> | ||||
| 	</div> | ||||
| 	<div class="caption"><slot name="caption"></slot></div> | ||||
| 
 | ||||
| 	<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 MkButton from './button.vue'; | ||||
| import { debounce } from 'throttle-debounce'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
| 		MkButton, | ||||
| 	}, | ||||
| 
 | ||||
| 	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 | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	emits: ['change', 'keydown', 'enter', 'update:modelValue'], | ||||
| 
 | ||||
| 	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; | ||||
| 			context.emit('change', ev); | ||||
| 		}; | ||||
| 		const onKeydown = (ev: KeyboardEvent) => { | ||||
| 			context.emit('keydown', ev); | ||||
| 
 | ||||
| 			if (ev.code === 'Enter') { | ||||
| 				context.emit('enter'); | ||||
| 			} | ||||
| 		}; | ||||
| 
 | ||||
| 		const updated = () => { | ||||
| 			changed.value = false; | ||||
| 			context.emit('update:modelValue', v.value); | ||||
| 		}; | ||||
| 
 | ||||
| 		const debouncedUpdated = debounce(1000, updated); | ||||
| 
 | ||||
| 		watch(modelValue, newValue => { | ||||
| 			v.value = newValue; | ||||
| 		}); | ||||
| 
 | ||||
| 		watch(v, newValue => { | ||||
| 			if (!props.manualSave) { | ||||
| 				if (props.debounce) { | ||||
| 					debouncedUpdated(); | ||||
| 				} else { | ||||
| 					updated(); | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			invalid.value = inputEl.value.validity.badInput; | ||||
| 		}); | ||||
| 
 | ||||
| 		onMounted(() => { | ||||
| 			nextTick(() => { | ||||
| 				if (autofocus.value) { | ||||
| 					focus(); | ||||
| 				} | ||||
| 			}); | ||||
| 		}); | ||||
| 
 | ||||
| 		return { | ||||
| 			v, | ||||
| 			focused, | ||||
| 			invalid, | ||||
| 			changed, | ||||
| 			filled, | ||||
| 			inputEl, | ||||
| 			focus, | ||||
| 			onInput, | ||||
| 			onKeydown, | ||||
| 			updated, | ||||
| 		}; | ||||
| 	}, | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| .adhpbeos { | ||||
| 	margin: 1.5em 0; | ||||
| 
 | ||||
| 	> .label { | ||||
| 		font-size: 0.85em; | ||||
| 		padding: 0 0 8px 12px; | ||||
| 		user-select: none; | ||||
| 
 | ||||
| 		&:empty { | ||||
| 			display: none; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	> .caption { | ||||
| 		font-size: 0.8em; | ||||
| 		padding: 8px 0 0 12px; | ||||
| 		color: var(--fgTransparentWeak); | ||||
| 
 | ||||
| 		&:empty { | ||||
| 			display: none; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	> .input { | ||||
| 		position: relative; | ||||
| 
 | ||||
| 		> textarea { | ||||
| 			appearance: none; | ||||
| 			-webkit-appearance: none; | ||||
| 			display: block; | ||||
| 			width: 100%; | ||||
| 			min-width: 100%; | ||||
| 			max-width: 100%; | ||||
| 			min-height: 130px; | ||||
| 			margin: 0; | ||||
| 			padding: 12px; | ||||
| 			font: inherit; | ||||
| 			font-weight: normal; | ||||
| 			font-size: 1em; | ||||
| 			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; | ||||
| 
 | ||||
| 			&:hover { | ||||
| 				border-color: var(--inputBorderHover); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		&.focused { | ||||
| 			> textarea { | ||||
| 				border-color: var(--accent); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		&.disabled { | ||||
| 			opacity: 0.7; | ||||
| 
 | ||||
| 			&, * { | ||||
| 				cursor: not-allowed !important; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		&.tall { | ||||
| 			> textarea { | ||||
| 				min-height: 200px; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		&.pre { | ||||
| 			> textarea { | ||||
| 				white-space: pre; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| </style> | ||||
|  | @ -10,7 +10,7 @@ | |||
| 	<template #header>{{ $ts.selectUser }}</template> | ||||
| 	<div class="tbhwbxda _monolithic_"> | ||||
| 		<div class="_section"> | ||||
| 			<div class="_inputSplit _inputNoTopMargin _inputNoBottomMargin"> | ||||
| 			<div class="_inputSplit"> | ||||
| 				<MkInput v-model="username" class="input" @update:modelValue="search" ref="username"> | ||||
| 					<template #label>{{ $ts.username }}</template> | ||||
| 					<template #prefix>@</template> | ||||
|  | @ -52,7 +52,7 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import MkInput from './ui/input.vue'; | ||||
| import MkInput from './form/input.vue'; | ||||
| import XModalWindow from '@client/components/ui/modal-window.vue'; | ||||
| import * as os from '@client/os'; | ||||
| 
 | ||||
|  |  | |||
|  | @ -30,7 +30,7 @@ | |||
| <script lang="ts"> | ||||
| import { defineComponent, defineAsyncComponent } from 'vue'; | ||||
| import { v4 as uuid } from 'uuid'; | ||||
| import MkSelect from '@client/components/ui/select.vue'; | ||||
| import MkSelect from '@client/components/form/select.vue'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import { widgets as widgetDefs } from '@client/widgets'; | ||||
| 
 | ||||
|  |  | |||
|  | @ -2,15 +2,15 @@ | |||
| <div style="overflow: clip;"> | ||||
| 	<FormBase class="znqjceqz"> | ||||
| 		<div id="debug"></div> | ||||
| 		<section class="_formItem about"> | ||||
| 			<div class="_formPanel panel" :class="{ playing: easterEggEngine != null }" ref="about"> | ||||
| 		<section class="_debobigegoItem about"> | ||||
| 			<div class="_debobigegoPanel panel" :class="{ playing: easterEggEngine != null }" ref="about"> | ||||
| 				<img src="/static-assets/client/about-icon.png" alt="" class="icon" @load="iconLoaded" draggable="false" @click="gravity"/> | ||||
| 				<div class="misskey">Misskey</div> | ||||
| 				<div class="version">v{{ version }}</div> | ||||
| 				<span class="emoji" v-for="emoji in easterEggEmojis" :key="emoji.id" :data-physics-x="emoji.left" :data-physics-y="emoji.top" :class="{ _physics_circle_: !emoji.emoji.startsWith(':') }"><MkEmoji class="emoji" :emoji="emoji.emoji" :custom-emojis="$instance.emojis" :is-reaction="false" :normal="true" :no-style="true"/></span> | ||||
| 			</div> | ||||
| 		</section> | ||||
| 		<section class="_formItem" style="text-align: center; padding: 0 16px;"> | ||||
| 		<section class="_debobigegoItem" style="text-align: center; padding: 0 16px;"> | ||||
| 			{{ $ts._aboutMisskey.about }}<br><MkA class="_link" to="/docs/general/misskey">{{ $ts.learnMore }}</MkA> | ||||
| 		</section> | ||||
| 		<FormGroup> | ||||
|  | @ -55,10 +55,10 @@ | |||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { version } from '@client/config'; | ||||
| import FormLink from '@client/components/form/link.vue'; | ||||
| import FormBase from '@client/components/form/base.vue'; | ||||
| import FormGroup from '@client/components/form/group.vue'; | ||||
| import FormKeyValueView from '@client/components/form/key-value-view.vue'; | ||||
| import FormLink from '@client/components/debobigego/link.vue'; | ||||
| import FormBase from '@client/components/debobigego/base.vue'; | ||||
| import FormGroup from '@client/components/debobigego/group.vue'; | ||||
| import FormKeyValueView from '@client/components/debobigego/key-value-view.vue'; | ||||
| import MkLink from '@client/components/link.vue'; | ||||
| import { physics } from '@client/scripts/physics'; | ||||
| import * as symbols from '@client/symbols'; | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| <template> | ||||
| <FormBase> | ||||
| 	<div class="_formItem"> | ||||
| 		<div class="_formPanel fwhjspax"> | ||||
| 	<div class="_debobigegoItem"> | ||||
| 		<div class="_debobigegoPanel fwhjspax"> | ||||
| 			<img :src="$instance.iconUrl || $instance.faviconUrl || '/favicon.ico'" alt="" class="icon"/> | ||||
| 			<span class="name">{{ $instance.name || host }}</span> | ||||
| 		</div> | ||||
|  | @ -59,12 +59,12 @@ | |||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { version, instanceName } from '@client/config'; | ||||
| import FormLink from '@client/components/form/link.vue'; | ||||
| import FormBase from '@client/components/form/base.vue'; | ||||
| import FormGroup from '@client/components/form/group.vue'; | ||||
| import FormKeyValueView from '@client/components/form/key-value-view.vue'; | ||||
| import FormTextarea from '@client/components/form/textarea.vue'; | ||||
| import FormSuspense from '@client/components/form/suspense.vue'; | ||||
| import FormLink from '@client/components/debobigego/link.vue'; | ||||
| import FormBase from '@client/components/debobigego/base.vue'; | ||||
| import FormGroup from '@client/components/debobigego/group.vue'; | ||||
| import FormKeyValueView from '@client/components/debobigego/key-value-view.vue'; | ||||
| import FormTextarea from '@client/components/debobigego/textarea.vue'; | ||||
| import FormSuspense from '@client/components/debobigego/suspense.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import number from '@client/filters/number'; | ||||
| import * as symbols from '@client/symbols'; | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ | |||
| 		<div class="_content"> | ||||
| 			<details> | ||||
| 				<summary>{{ $ts.import }}</summary> | ||||
| 				<MkTextarea v-model:value="themeToImport"> | ||||
| 				<MkTextarea v-model="themeToImport"> | ||||
| 					{{ $ts._theme.importInfo }} | ||||
| 				</MkTextarea> | ||||
| 				<MkButton :disabled="!themeToImport.trim()" @click="importTheme">{{ $ts.import }}</MkButton> | ||||
|  | @ -14,9 +14,9 @@ | |||
| 	<section class="_section"> | ||||
| 		<div class="_content _card _gap"> | ||||
| 			<div class="_content"> | ||||
| 				<MkInput v-model:value="name" required><span>{{ $ts.name }}</span></MkInput> | ||||
| 				<MkInput v-model:value="author" required><span>{{ $ts.author }}</span></MkInput> | ||||
| 				<MkTextarea v-model:value="description"><span>{{ $ts.description }}</span></MkTextarea> | ||||
| 				<MkInput v-model="name" required><span>{{ $ts.name }}</span></MkInput> | ||||
| 				<MkInput v-model="author" required><span>{{ $ts.author }}</span></MkInput> | ||||
| 				<MkTextarea v-model="description"><span>{{ $ts.description }}</span></MkTextarea> | ||||
| 				<div class="_inputs"> | ||||
| 					<div v-text="$ts._theme.base" /> | ||||
| 					<MkRadio v-model="baseTheme" value="light">{{ $ts.light }}</MkRadio> | ||||
|  | @ -41,31 +41,31 @@ | |||
| 							<!-- color --> | ||||
| 							<div v-else-if="typeof v === 'string'" class="color"> | ||||
| 								<input type="color" :value="v" @input="colorChanged($event.target.value, i)"/> | ||||
| 								<MkInput class="select" :value="v" @update:value="colorChanged($event, i)"/> | ||||
| 								<MkInput class="select" :value="v" @update:modelValue="colorChanged($event, i)"/> | ||||
| 							</div> | ||||
| 							<!-- ref const --> | ||||
| 							<MkInput v-else-if="v.type === 'refConst'" v-model:value="v.key"> | ||||
| 							<MkInput v-else-if="v.type === 'refConst'" v-model="v.key"> | ||||
| 								<template #prefix>$</template> | ||||
| 								<span>{{ $ts.name }}</span> | ||||
| 							</MkInput> | ||||
| 							<!-- ref props --> | ||||
| 							<MkSelect class="select" v-else-if="v.type === 'refProp'" v-model:value="v.key"> | ||||
| 							<MkSelect class="select" v-else-if="v.type === 'refProp'" v-model="v.key"> | ||||
| 								<option v-for="key in themeProps" :value="key" :key="key">{{ $t('_theme.keys.' + key) }}</option> | ||||
| 							</MkSelect> | ||||
| 							<!-- func --> | ||||
| 							<template v-else-if="v.type === 'func'"> | ||||
| 								<MkSelect class="select" v-model:value="v.name"> | ||||
| 								<MkSelect class="select" v-model="v.name"> | ||||
| 									<template #label>{{ $ts._theme.funcKind }}</template> | ||||
| 									<option v-for="n in ['alpha', 'darken', 'lighten']" :value="n" :key="n">{{ $t('_theme.' + n) }}</option> | ||||
| 								</MkSelect> | ||||
| 								<MkInput type="number" v-model:value="v.arg"><span>{{ $ts._theme.argument }}</span></MkInput> | ||||
| 								<MkSelect class="select" v-model:value="v.value"> | ||||
| 								<MkInput type="number" v-model="v.arg"><span>{{ $ts._theme.argument }}</span></MkInput> | ||||
| 								<MkSelect class="select" v-model="v.value"> | ||||
| 									<template #label>{{ $ts._theme.basedProp }}</template> | ||||
| 									<option v-for="key in themeProps" :value="key" :key="key">{{ $t('_theme.keys.' + key) }}</option> | ||||
| 								</MkSelect> | ||||
| 							</template> | ||||
| 							<!-- CSS --> | ||||
| 							<MkInput v-else-if="v.type === 'css'" v-model:value="v.value"> | ||||
| 							<MkInput v-else-if="v.type === 'css'" v-model="v.value"> | ||||
| 								<span>CSS</span> | ||||
| 							</MkInput> | ||||
| 						</div> | ||||
|  | @ -95,11 +95,11 @@ import { defineComponent } from 'vue'; | |||
| import * as JSON5 from 'json5'; | ||||
| import { toUnicode } from 'punycode/'; | ||||
| 
 | ||||
| import MkRadio from '@client/components/ui/radio.vue'; | ||||
| import MkRadio from '@client/components/form/radio.vue'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import MkInput from '@client/components/ui/input.vue'; | ||||
| import MkTextarea from '@client/components/ui/textarea.vue'; | ||||
| import MkSelect from '@client/components/ui/select.vue'; | ||||
| import MkInput from '@client/components/form/input.vue'; | ||||
| import MkTextarea from '@client/components/form/textarea.vue'; | ||||
| import MkSelect from '@client/components/form/select.vue'; | ||||
| import MkSample from '@client/components/sample.vue'; | ||||
| 
 | ||||
| import { convertToMisskeyTheme, ThemeValue, convertToViewModel, ThemeViewModel } from '@client/scripts/theme-editor'; | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| <template> | ||||
| <div class="_root"> | ||||
| 	<div class="_block" style="padding: 24px;"> | ||||
| 		<MkInput v-model="endpoint" :datalist="endpoints" @update:modelValue="onEndpointChange()" class="_inputNoTopMargin"> | ||||
| 		<MkInput v-model="endpoint" :datalist="endpoints" @update:modelValue="onEndpointChange()" class=""> | ||||
| 			<template #label>Endpoint</template> | ||||
| 		</MkInput> | ||||
| 		<MkTextarea v-model="body" code> | ||||
|  | @ -27,9 +27,9 @@ | |||
| import { defineComponent } from 'vue'; | ||||
| import * as JSON5 from 'json5'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import MkInput from '@client/components/ui/input.vue'; | ||||
| import MkTextarea from '@client/components/ui/textarea.vue'; | ||||
| import MkSwitch from '@client/components/ui/switch.vue'; | ||||
| import MkInput from '@client/components/form/input.vue'; | ||||
| import MkTextarea from '@client/components/form/textarea.vue'; | ||||
| import MkSwitch from '@client/components/form/switch.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| 
 | ||||
|  |  | |||
|  | @ -27,9 +27,9 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { computed, defineComponent } from 'vue'; | ||||
| import MkTextarea from '@client/components/ui/textarea.vue'; | ||||
| import MkTextarea from '@client/components/form/textarea.vue'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import MkInput from '@client/components/ui/input.vue'; | ||||
| import MkInput from '@client/components/form/input.vue'; | ||||
| import { selectFile } from '@client/scripts/select-file'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| <template> | ||||
| <div> | ||||
| 	<div class="_section" style="padding: 0;" v-if="$i"> | ||||
| 		<MkTab class="_content" v-model:value="tab"> | ||||
| 		<MkTab class="_content" v-model="tab"> | ||||
| 			<option value="featured"><i class="fas fa-fire-alt"></i> {{ $ts._channel.featured }}</option> | ||||
| 			<option value="following"><i class="fas fa-heart"></i> {{ $ts._channel.following }}</option> | ||||
| 			<option value="owned"><i class="fas fa-edit"></i> {{ $ts._channel.owned }}</option> | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ | |||
| <div class="vtaihdtm"> | ||||
| 	<div class="body"> | ||||
| 		<div class="search"> | ||||
| 			<MkInput v-model="query" :debounce="true" type="search" class="_inputNoTopMargin _inputNoBottomMargin" :placeholder="$ts.search"> | ||||
| 			<MkInput v-model="query" :debounce="true" type="search" class="" :placeholder="$ts.search"> | ||||
| 				<template #prefix><i class="fas fa-search"></i></template> | ||||
| 			</MkInput> | ||||
| 		</div> | ||||
|  | @ -57,7 +57,7 @@ import { defineComponent } from 'vue'; | |||
| import { url, lang } from '@client/config'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| import MkFolder from '@client/components/ui/folder.vue'; | ||||
| import MkInput from '@client/components/ui/input.vue'; | ||||
| import MkInput from '@client/components/form/input.vue'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| <template> | ||||
| <div class="driuhtrh"> | ||||
| 	<div class="query"> | ||||
| 		<MkInput v-model="q" class="_inputNoTopMargin _inputNoBottomMargin" :placeholder="$ts.search"> | ||||
| 		<MkInput v-model="q" class="" :placeholder="$ts.search"> | ||||
| 			<template #prefix><i class="fas fa-search"></i></template> | ||||
| 		</MkInput> | ||||
| 
 | ||||
|  | @ -31,8 +31,8 @@ | |||
| <script lang="ts"> | ||||
| import { defineComponent, computed } from 'vue'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import MkInput from '@client/components/ui/input.vue'; | ||||
| import MkSelect from '@client/components/ui/select.vue'; | ||||
| import MkInput from '@client/components/form/input.vue'; | ||||
| import MkSelect from '@client/components/form/select.vue'; | ||||
| import MkFolder from '@client/components/ui/folder.vue'; | ||||
| import MkTab from '@client/components/tab.vue'; | ||||
| import * as os from '@client/os'; | ||||
|  |  | |||
|  | @ -75,7 +75,7 @@ | |||
| import { computed, defineComponent } from 'vue'; | ||||
| import XUserList from '@client/components/user-list.vue'; | ||||
| import MkFolder from '@client/components/ui/folder.vue'; | ||||
| import MkInput from '@client/components/ui/input.vue'; | ||||
| import MkInput from '@client/components/form/input.vue'; | ||||
| import number from '@client/filters/number'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
|  |  | |||
|  | @ -1,11 +1,11 @@ | |||
| <template> | ||||
| <div class="taeiyria"> | ||||
| 	<div class="query"> | ||||
| 		<MkInput v-model="host" :debounce="true" class="_inputNoTopMargin"> | ||||
| 		<MkInput v-model="host" :debounce="true" class=""> | ||||
| 			<template #prefix><i class="fas fa-search"></i></template> | ||||
| 			<template #label>{{ $ts.host }}</template> | ||||
| 		</MkInput> | ||||
| 		<div class="_inputSplit _inputNoBottomMargin"> | ||||
| 		<div class="_inputSplit"> | ||||
| 			<MkSelect v-model="state"> | ||||
| 				<template #label>{{ $ts.state }}</template> | ||||
| 				<option value="all">{{ $ts.all }}</option> | ||||
|  | @ -96,8 +96,8 @@ | |||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import MkInput from '@client/components/ui/input.vue'; | ||||
| import MkSelect from '@client/components/ui/select.vue'; | ||||
| import MkInput from '@client/components/form/input.vue'; | ||||
| import MkSelect from '@client/components/form/select.vue'; | ||||
| import MkPagination from '@client/components/ui/pagination.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
|  |  | |||
|  | @ -1,23 +1,23 @@ | |||
| <template> | ||||
| <FormBase> | ||||
| 	<FormSuspense :p="init"> | ||||
| 		<FormInput v-model:value="title"> | ||||
| 		<FormInput v-model="title"> | ||||
| 			<span>{{ $ts.title }}</span> | ||||
| 		</FormInput> | ||||
| 
 | ||||
| 		<FormTextarea v-model:value="description" :max="500"> | ||||
| 		<FormTextarea v-model="description" :max="500"> | ||||
| 			<span>{{ $ts.description }}</span> | ||||
| 		</FormTextarea> | ||||
| 
 | ||||
| 		<FormGroup> | ||||
| 			<div v-for="file in files" :key="file.id" class="_formItem _formPanel wqugxsfx" :style="{ backgroundImage: file ? `url(${ file.thumbnailUrl })` : null }"> | ||||
| 			<div v-for="file in files" :key="file.id" class="_debobigegoItem _debobigegoPanel wqugxsfx" :style="{ backgroundImage: file ? `url(${ file.thumbnailUrl })` : null }"> | ||||
| 				<div class="name">{{ file.name }}</div> | ||||
| 				<button class="remove _button" @click="remove(file)" v-tooltip="$ts.remove"><i class="fas fa-times"></i></button> | ||||
| 			</div> | ||||
| 			<FormButton @click="selectFile" primary><i class="fas fa-plus"></i> {{ $ts.attachFile }}</FormButton> | ||||
| 		</FormGroup> | ||||
| 
 | ||||
| 		<FormSwitch v-model:value="isSensitive">{{ $ts.markAsSensitive }}</FormSwitch> | ||||
| 		<FormSwitch v-model="isSensitive">{{ $ts.markAsSensitive }}</FormSwitch> | ||||
| 
 | ||||
| 		<FormButton v-if="postId" @click="save" primary><i class="fas fa-save"></i> {{ $ts.save }}</FormButton> | ||||
| 		<FormButton v-else @click="save" primary><i class="fas fa-save"></i> {{ $ts.publish }}</FormButton> | ||||
|  | @ -29,14 +29,14 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { computed, defineComponent } from 'vue'; | ||||
| import FormButton from '@client/components/form/button.vue'; | ||||
| import FormInput from '@client/components/form/input.vue'; | ||||
| import FormTextarea from '@client/components/form/textarea.vue'; | ||||
| import FormSwitch from '@client/components/form/switch.vue'; | ||||
| import FormTuple from '@client/components/form/tuple.vue'; | ||||
| import FormBase from '@client/components/form/base.vue'; | ||||
| import FormGroup from '@client/components/form/group.vue'; | ||||
| import FormSuspense from '@client/components/form/suspense.vue'; | ||||
| import FormButton from '@client/components/debobigego/button.vue'; | ||||
| import FormInput from '@client/components/debobigego/input.vue'; | ||||
| import FormTextarea from '@client/components/debobigego/textarea.vue'; | ||||
| import FormSwitch from '@client/components/debobigego/switch.vue'; | ||||
| import FormTuple from '@client/components/debobigego/tuple.vue'; | ||||
| import FormBase from '@client/components/debobigego/base.vue'; | ||||
| import FormGroup from '@client/components/debobigego/group.vue'; | ||||
| import FormSuspense from '@client/components/debobigego/suspense.vue'; | ||||
| import { selectFile } from '@client/scripts/select-file'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| <template> | ||||
| <div class="xprsixdl _root"> | ||||
| 	<MkTab v-model:value="tab" v-if="$i"> | ||||
| 	<MkTab v-model="tab" v-if="$i"> | ||||
| 		<option value="explore"><i class="fas fa-icons"></i> {{ $ts.gallery }}</option> | ||||
| 		<option value="liked"><i class="fas fa-heart"></i> {{ $ts._gallery.liked }}</option> | ||||
| 		<option value="my"><i class="fas fa-edit"></i> {{ $ts._gallery.my }}</option> | ||||
|  | @ -46,7 +46,7 @@ | |||
| import { computed, defineComponent } from 'vue'; | ||||
| import XUserList from '@client/components/user-list.vue'; | ||||
| import MkFolder from '@client/components/ui/folder.vue'; | ||||
| import MkInput from '@client/components/ui/input.vue'; | ||||
| import MkInput from '@client/components/form/input.vue'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import MkTab from '@client/components/tab.vue'; | ||||
| import MkPagination from '@client/components/ui/pagination.vue'; | ||||
|  |  | |||
|  | @ -3,8 +3,8 @@ | |||
| 	<FormGroup v-if="instance"> | ||||
| 		<template #label>{{ instance.host }}</template> | ||||
| 		<FormGroup> | ||||
| 			<div class="_formItem"> | ||||
| 				<div class="_formPanel fnfelxur"> | ||||
| 			<div class="_debobigegoItem"> | ||||
| 				<div class="_debobigegoPanel fnfelxur"> | ||||
| 					<img :src="instance.iconUrl || instance.faviconUrl" alt="" class="icon"/> | ||||
| 				</div> | ||||
| 			</div> | ||||
|  | @ -60,9 +60,9 @@ | |||
| 				<template #value>{{ instance.openRegistrations ? $ts.yes : $ts.no }}</template> | ||||
| 			</FormKeyValueView> | ||||
| 		</FormGroup> | ||||
| 		<div class="_formItem"> | ||||
| 			<div class="_formLabel">{{ $ts.statistics }}</div> | ||||
| 			<div class="_formPanel cmhjzshl"> | ||||
| 		<div class="_debobigegoItem"> | ||||
| 			<div class="_debobigegoLabel">{{ $ts.statistics }}</div> | ||||
| 			<div class="_debobigegoPanel cmhjzshl"> | ||||
| 				<div class="selects"> | ||||
| 					<MkSelect v-model="chartSrc" style="margin: 0; flex: 1;"> | ||||
| 						<option value="requests">{{ $ts._instanceCharts.requests }}</option> | ||||
|  | @ -136,15 +136,15 @@ | |||
| <script lang="ts"> | ||||
| import { defineAsyncComponent, defineComponent } from 'vue'; | ||||
| import Chart from 'chart.js'; | ||||
| import FormObjectView from '@client/components/form/object-view.vue'; | ||||
| import FormTextarea from '@client/components/form/textarea.vue'; | ||||
| import FormLink from '@client/components/form/link.vue'; | ||||
| import FormBase from '@client/components/form/base.vue'; | ||||
| import FormGroup from '@client/components/form/group.vue'; | ||||
| import FormButton from '@client/components/form/button.vue'; | ||||
| import FormKeyValueView from '@client/components/form/key-value-view.vue'; | ||||
| import FormSuspense from '@client/components/form/suspense.vue'; | ||||
| import MkSelect from '@client/components/ui/select.vue'; | ||||
| import FormObjectView from '@client/components/debobigego/object-view.vue'; | ||||
| import FormTextarea from '@client/components/debobigego/textarea.vue'; | ||||
| import FormLink from '@client/components/debobigego/link.vue'; | ||||
| import FormBase from '@client/components/debobigego/base.vue'; | ||||
| import FormGroup from '@client/components/debobigego/group.vue'; | ||||
| import FormButton from '@client/components/debobigego/button.vue'; | ||||
| import FormKeyValueView from '@client/components/debobigego/key-value-view.vue'; | ||||
| import FormSuspense from '@client/components/debobigego/suspense.vue'; | ||||
| import MkSelect from '@client/components/form/select.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import number from '@client/filters/number'; | ||||
| import bytes from '@client/filters/bytes'; | ||||
|  |  | |||
|  | @ -24,10 +24,10 @@ | |||
| 			</div> | ||||
| 			<!-- TODO | ||||
| 			<div class="inputs" style="display: flex; padding-top: 1.2em;"> | ||||
| 				<MkInput v-model:value="searchUsername" style="margin: 0; flex: 1;" type="text" spellcheck="false" @update:value="$refs.reports.reload()"> | ||||
| 				<MkInput v-model="searchUsername" style="margin: 0; flex: 1;" type="text" spellcheck="false" @update:modelValue="$refs.reports.reload()"> | ||||
| 					<span>{{ $ts.username }}</span> | ||||
| 				</MkInput> | ||||
| 				<MkInput v-model:value="searchHost" style="margin: 0; flex: 1;" type="text" spellcheck="false" @update:value="$refs.reports.reload()" :disabled="pagination.params().origin === 'local'"> | ||||
| 				<MkInput v-model="searchHost" style="margin: 0; flex: 1;" type="text" spellcheck="false" @update:modelValue="$refs.reports.reload()" :disabled="pagination.params().origin === 'local'"> | ||||
| 					<span>{{ $ts.host }}</span> | ||||
| 				</MkInput> | ||||
| 			</div> | ||||
|  | @ -65,8 +65,8 @@ | |||
| import { defineComponent } from 'vue'; | ||||
| import { parseAcct } from '@/misc/acct'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import MkInput from '@client/components/ui/input.vue'; | ||||
| import MkSelect from '@client/components/ui/select.vue'; | ||||
| import MkInput from '@client/components/form/input.vue'; | ||||
| import MkSelect from '@client/components/form/select.vue'; | ||||
| import MkPagination from '@client/components/ui/pagination.vue'; | ||||
| import { acct } from '@client/filters/user'; | ||||
| import * as os from '@client/os'; | ||||
|  |  | |||
|  | @ -44,9 +44,9 @@ | |||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import MkInput from '@client/components/ui/input.vue'; | ||||
| import MkTextarea from '@client/components/ui/textarea.vue'; | ||||
| import MkRadio from '@client/components/ui/radio.vue'; | ||||
| import MkInput from '@client/components/form/input.vue'; | ||||
| import MkTextarea from '@client/components/form/textarea.vue'; | ||||
| import MkRadio from '@client/components/form/radio.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| 
 | ||||
|  |  | |||
|  | @ -25,8 +25,8 @@ | |||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import MkInput from '@client/components/ui/input.vue'; | ||||
| import MkTextarea from '@client/components/ui/textarea.vue'; | ||||
| import MkInput from '@client/components/form/input.vue'; | ||||
| import MkTextarea from '@client/components/form/textarea.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| 
 | ||||
|  |  | |||
|  | @ -9,43 +9,43 @@ | |||
| 		</FormRadios> | ||||
| 
 | ||||
| 		<template v-if="provider === 'hcaptcha'"> | ||||
| 			<div class="_formItem _formNoConcat" v-sticky-container> | ||||
| 				<div class="_formLabel">hCaptcha</div> | ||||
| 			<div class="_debobigegoItem _debobigegoNoConcat" v-sticky-container> | ||||
| 				<div class="_debobigegoLabel">hCaptcha</div> | ||||
| 				<div class="main"> | ||||
| 					<FormInput v-model:value="hcaptchaSiteKey"> | ||||
| 					<FormInput v-model="hcaptchaSiteKey"> | ||||
| 						<template #prefix><i class="fas fa-key"></i></template> | ||||
| 						<span>{{ $ts.hcaptchaSiteKey }}</span> | ||||
| 					</FormInput> | ||||
| 					<FormInput v-model:value="hcaptchaSecretKey"> | ||||
| 					<FormInput v-model="hcaptchaSecretKey"> | ||||
| 						<template #prefix><i class="fas fa-key"></i></template> | ||||
| 						<span>{{ $ts.hcaptchaSecretKey }}</span> | ||||
| 					</FormInput> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 			<div class="_formItem _formNoConcat" v-sticky-container> | ||||
| 				<div class="_formLabel">{{ $ts.preview }}</div> | ||||
| 				<div class="_formPanel" style="padding: var(--formContentHMargin);"> | ||||
| 			<div class="_debobigegoItem _debobigegoNoConcat" v-sticky-container> | ||||
| 				<div class="_debobigegoLabel">{{ $ts.preview }}</div> | ||||
| 				<div class="_debobigegoPanel" style="padding: var(--debobigegoContentHMargin);"> | ||||
| 					<MkCaptcha provider="hcaptcha" :sitekey="hcaptchaSiteKey || '10000000-ffff-ffff-ffff-000000000001'"/> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		</template> | ||||
| 		<template v-else-if="provider === 'recaptcha'"> | ||||
| 			<div class="_formItem _formNoConcat" v-sticky-container> | ||||
| 				<div class="_formLabel">reCAPTCHA</div> | ||||
| 			<div class="_debobigegoItem _debobigegoNoConcat" v-sticky-container> | ||||
| 				<div class="_debobigegoLabel">reCAPTCHA</div> | ||||
| 				<div class="main"> | ||||
| 					<FormInput v-model:value="recaptchaSiteKey"> | ||||
| 					<FormInput v-model="recaptchaSiteKey"> | ||||
| 						<template #prefix><i class="fas fa-key"></i></template> | ||||
| 						<span>{{ $ts.recaptchaSiteKey }}</span> | ||||
| 					</FormInput> | ||||
| 					<FormInput v-model:value="recaptchaSecretKey"> | ||||
| 					<FormInput v-model="recaptchaSecretKey"> | ||||
| 						<template #prefix><i class="fas fa-key"></i></template> | ||||
| 						<span>{{ $ts.recaptchaSecretKey }}</span> | ||||
| 					</FormInput> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 			<div v-if="recaptchaSiteKey" class="_formItem _formNoConcat" v-sticky-container> | ||||
| 				<div class="_formLabel">{{ $ts.preview }}</div> | ||||
| 				<div class="_formPanel" style="padding: var(--formContentHMargin);"> | ||||
| 			<div v-if="recaptchaSiteKey" class="_debobigegoItem _debobigegoNoConcat" v-sticky-container> | ||||
| 				<div class="_debobigegoLabel">{{ $ts.preview }}</div> | ||||
| 				<div class="_debobigegoPanel" style="padding: var(--debobigegoContentHMargin);"> | ||||
| 					<MkCaptcha provider="recaptcha" :sitekey="recaptchaSiteKey"/> | ||||
| 				</div> | ||||
| 			</div> | ||||
|  | @ -58,13 +58,13 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineAsyncComponent, defineComponent } from 'vue'; | ||||
| import FormRadios from '@client/components/form/radios.vue'; | ||||
| import FormInput from '@client/components/form/input.vue'; | ||||
| import FormButton from '@client/components/form/button.vue'; | ||||
| import FormBase from '@client/components/form/base.vue'; | ||||
| import FormGroup from '@client/components/form/group.vue'; | ||||
| import FormInfo from '@client/components/form/info.vue'; | ||||
| import FormSuspense from '@client/components/form/suspense.vue'; | ||||
| import FormRadios from '@client/components/debobigego/radios.vue'; | ||||
| import FormInput from '@client/components/debobigego/input.vue'; | ||||
| import FormButton from '@client/components/debobigego/button.vue'; | ||||
| import FormBase from '@client/components/debobigego/base.vue'; | ||||
| import FormGroup from '@client/components/debobigego/group.vue'; | ||||
| import FormInfo from '@client/components/debobigego/info.vue'; | ||||
| import FormSuspense from '@client/components/debobigego/suspense.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| import { fetchInstance } from '@client/instance'; | ||||
|  |  | |||
|  | @ -18,11 +18,11 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import FormSuspense from '@client/components/form/suspense.vue'; | ||||
| import FormKeyValueView from '@client/components/form/key-value-view.vue'; | ||||
| import FormLink from '@client/components/form/link.vue'; | ||||
| import FormBase from '@client/components/form/base.vue'; | ||||
| import FormGroup from '@client/components/form/group.vue'; | ||||
| import FormSuspense from '@client/components/debobigego/suspense.vue'; | ||||
| import FormKeyValueView from '@client/components/debobigego/key-value-view.vue'; | ||||
| import FormLink from '@client/components/debobigego/link.vue'; | ||||
| import FormBase from '@client/components/debobigego/base.vue'; | ||||
| import FormGroup from '@client/components/debobigego/group.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| import bytes from '@client/filters/bytes'; | ||||
|  |  | |||
|  | @ -1,30 +1,30 @@ | |||
| <template> | ||||
| <FormBase> | ||||
| 	<FormSuspense :p="init"> | ||||
| 		<FormSwitch v-model:value="enableEmail">{{ $ts.enableEmail }}<template #desc>{{ $ts.emailConfigInfo }}</template></FormSwitch> | ||||
| 		<FormSwitch v-model="enableEmail">{{ $ts.enableEmail }}<template #desc>{{ $ts.emailConfigInfo }}</template></FormSwitch> | ||||
| 
 | ||||
| 		<template v-if="enableEmail"> | ||||
| 			<FormInput v-model:value="email" type="email"> | ||||
| 			<FormInput v-model="email" type="email"> | ||||
| 				<span>{{ $ts.emailAddress }}</span> | ||||
| 			</FormInput> | ||||
| 
 | ||||
| 			<div class="_formItem _formNoConcat" v-sticky-container> | ||||
| 				<div class="_formLabel">{{ $ts.smtpConfig }}</div> | ||||
| 			<div class="_debobigegoItem _debobigegoNoConcat" v-sticky-container> | ||||
| 				<div class="_debobigegoLabel">{{ $ts.smtpConfig }}</div> | ||||
| 				<div class="main"> | ||||
| 					<FormInput v-model:value="smtpHost"> | ||||
| 					<FormInput v-model="smtpHost"> | ||||
| 						<span>{{ $ts.smtpHost }}</span> | ||||
| 					</FormInput> | ||||
| 					<FormInput v-model:value="smtpPort" type="number"> | ||||
| 					<FormInput v-model="smtpPort" type="number"> | ||||
| 						<span>{{ $ts.smtpPort }}</span> | ||||
| 					</FormInput> | ||||
| 					<FormInput v-model:value="smtpUser"> | ||||
| 					<FormInput v-model="smtpUser"> | ||||
| 						<span>{{ $ts.smtpUser }}</span> | ||||
| 					</FormInput> | ||||
| 					<FormInput v-model:value="smtpPass" type="password"> | ||||
| 					<FormInput v-model="smtpPass" type="password"> | ||||
| 						<span>{{ $ts.smtpPass }}</span> | ||||
| 					</FormInput> | ||||
| 					<FormInfo>{{ $ts.emptyToDisableSmtpAuth }}</FormInfo> | ||||
| 					<FormSwitch v-model:value="smtpSecure">{{ $ts.smtpSecure }}<template #desc>{{ $ts.smtpSecureInfo }}</template></FormSwitch> | ||||
| 					<FormSwitch v-model="smtpSecure">{{ $ts.smtpSecure }}<template #desc>{{ $ts.smtpSecureInfo }}</template></FormSwitch> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 
 | ||||
|  | @ -38,13 +38,13 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import FormSwitch from '@client/components/form/switch.vue'; | ||||
| import FormInput from '@client/components/form/input.vue'; | ||||
| import FormButton from '@client/components/form/button.vue'; | ||||
| import FormBase from '@client/components/form/base.vue'; | ||||
| import FormGroup from '@client/components/form/group.vue'; | ||||
| import FormInfo from '@client/components/form/info.vue'; | ||||
| import FormSuspense from '@client/components/form/suspense.vue'; | ||||
| import FormSwitch from '@client/components/debobigego/switch.vue'; | ||||
| import FormInput from '@client/components/debobigego/input.vue'; | ||||
| import FormButton from '@client/components/debobigego/button.vue'; | ||||
| import FormBase from '@client/components/debobigego/base.vue'; | ||||
| import FormGroup from '@client/components/debobigego/group.vue'; | ||||
| import FormInfo from '@client/components/debobigego/info.vue'; | ||||
| import FormSuspense from '@client/components/debobigego/suspense.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| import { fetchInstance } from '@client/instance'; | ||||
|  |  | |||
|  | @ -31,7 +31,7 @@ | |||
| import { defineComponent } from 'vue'; | ||||
| import XModalWindow from '@client/components/ui/modal-window.vue'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import MkInput from '@client/components/ui/input.vue'; | ||||
| import MkInput from '@client/components/form/input.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import { unique } from '../../../prelude/array'; | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| <template> | ||||
| <div class="ogwlenmc"> | ||||
| 	<MkTab v-model:value="tab"> | ||||
| 	<MkTab v-model="tab"> | ||||
| 		<option value="local">{{ $ts.local }}</option> | ||||
| 		<option value="remote">{{ $ts.remote }}</option> | ||||
| 	</MkTab> | ||||
|  | @ -56,7 +56,7 @@ | |||
| <script lang="ts"> | ||||
| import { computed, defineComponent } from 'vue'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import MkInput from '@client/components/ui/input.vue'; | ||||
| import MkInput from '@client/components/form/input.vue'; | ||||
| import MkPagination from '@client/components/ui/pagination.vue'; | ||||
| import MkTab from '@client/components/tab.vue'; | ||||
| import { selectFile } from '@client/scripts/select-file'; | ||||
|  |  | |||
|  | @ -37,7 +37,7 @@ | |||
| <script lang="ts"> | ||||
| import { computed, defineComponent } from 'vue'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import MkSwitch from '@client/components/ui/switch.vue'; | ||||
| import MkSwitch from '@client/components/form/switch.vue'; | ||||
| import XModalWindow from '@client/components/ui/modal-window.vue'; | ||||
| import MkDriveFileThumbnail from '@client/components/drive-file-thumbnail.vue'; | ||||
| import Progress from '@client/scripts/loading'; | ||||
|  |  | |||
|  | @ -1,23 +1,23 @@ | |||
| <template> | ||||
| <FormBase> | ||||
| 	<FormSuspense :p="init"> | ||||
| 		<FormSwitch v-model:value="cacheRemoteFiles"> | ||||
| 		<FormSwitch v-model="cacheRemoteFiles"> | ||||
| 			{{ $ts.cacheRemoteFiles }} | ||||
| 			<template #desc>{{ $ts.cacheRemoteFilesDescription }}</template> | ||||
| 		</FormSwitch> | ||||
| 
 | ||||
| 		<FormSwitch v-model:value="proxyRemoteFiles"> | ||||
| 		<FormSwitch v-model="proxyRemoteFiles"> | ||||
| 			{{ $ts.proxyRemoteFiles }} | ||||
| 			<template #desc>{{ $ts.proxyRemoteFilesDescription }}</template> | ||||
| 		</FormSwitch> | ||||
| 
 | ||||
| 		<FormInput v-model:value="localDriveCapacityMb" type="number"> | ||||
| 		<FormInput v-model="localDriveCapacityMb" type="number"> | ||||
| 			<span>{{ $ts.driveCapacityPerLocalAccount }}</span> | ||||
| 			<template #suffix>MB</template> | ||||
| 			<template #desc>{{ $ts.inMb }}</template> | ||||
| 		</FormInput> | ||||
| 
 | ||||
| 		<FormInput v-model:value="remoteDriveCapacityMb" type="number" :disabled="!cacheRemoteFiles"> | ||||
| 		<FormInput v-model="remoteDriveCapacityMb" type="number" :disabled="!cacheRemoteFiles"> | ||||
| 			<span>{{ $ts.driveCapacityPerRemoteAccount }}</span> | ||||
| 			<template #suffix>MB</template> | ||||
| 			<template #desc>{{ $ts.inMb }}</template> | ||||
|  | @ -30,12 +30,12 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import FormSwitch from '@client/components/form/switch.vue'; | ||||
| import FormInput from '@client/components/form/input.vue'; | ||||
| import FormButton from '@client/components/form/button.vue'; | ||||
| import FormBase from '@client/components/form/base.vue'; | ||||
| import FormGroup from '@client/components/form/group.vue'; | ||||
| import FormSuspense from '@client/components/form/suspense.vue'; | ||||
| import FormSwitch from '@client/components/debobigego/switch.vue'; | ||||
| import FormInput from '@client/components/debobigego/input.vue'; | ||||
| import FormButton from '@client/components/debobigego/button.vue'; | ||||
| import FormBase from '@client/components/debobigego/base.vue'; | ||||
| import FormGroup from '@client/components/debobigego/group.vue'; | ||||
| import FormSuspense from '@client/components/debobigego/suspense.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| import { fetchInstance } from '@client/instance'; | ||||
|  |  | |||
|  | @ -63,8 +63,8 @@ | |||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import MkInput from '@client/components/ui/input.vue'; | ||||
| import MkSelect from '@client/components/ui/select.vue'; | ||||
| import MkInput from '@client/components/form/input.vue'; | ||||
| import MkSelect from '@client/components/form/select.vue'; | ||||
| import MkPagination from '@client/components/ui/pagination.vue'; | ||||
| import MkDriveFileThumbnail from '@client/components/drive-file-thumbnail.vue'; | ||||
| import bytes from '@client/filters/bytes'; | ||||
|  |  | |||
|  | @ -3,8 +3,8 @@ | |||
| 	<div class="nav" v-if="!narrow || page == null"> | ||||
| 		<FormBase> | ||||
| 			<FormGroup> | ||||
| 				<div class="_formItem"> | ||||
| 					<div class="_formPanel lxpfedzu"> | ||||
| 				<div class="_debobigegoItem"> | ||||
| 					<div class="_debobigegoPanel lxpfedzu"> | ||||
| 						<img :src="$instance.iconUrl || '/favicon.ico'" alt="" class="icon"/> | ||||
| 					</div> | ||||
| 				</div> | ||||
|  | @ -56,10 +56,10 @@ | |||
| <script lang="ts"> | ||||
| import { computed, defineAsyncComponent, defineComponent, nextTick, onMounted, reactive, ref, watch } from 'vue'; | ||||
| import { i18n } from '@client/i18n'; | ||||
| import FormLink from '@client/components/form/link.vue'; | ||||
| import FormGroup from '@client/components/form/group.vue'; | ||||
| import FormBase from '@client/components/form/base.vue'; | ||||
| import FormButton from '@client/components/form/button.vue'; | ||||
| import FormLink from '@client/components/debobigego/link.vue'; | ||||
| import FormGroup from '@client/components/debobigego/group.vue'; | ||||
| import FormBase from '@client/components/debobigego/base.vue'; | ||||
| import FormButton from '@client/components/debobigego/button.vue'; | ||||
| import { scroll } from '@client/scripts/scroll'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| import * as os from '@client/os'; | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| <template> | ||||
| <FormBase> | ||||
| 	<FormSuspense :p="init"> | ||||
| 		<FormTextarea v-model:value="blockedHosts"> | ||||
| 		<FormTextarea v-model="blockedHosts"> | ||||
| 			<span>{{ $ts.blockedInstances }}</span> | ||||
| 			<template #desc>{{ $ts.blockedInstancesDescription }}</template> | ||||
| 		</FormTextarea> | ||||
|  | @ -13,14 +13,14 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import FormSwitch from '@client/components/form/switch.vue'; | ||||
| import FormInput from '@client/components/form/input.vue'; | ||||
| import FormButton from '@client/components/form/button.vue'; | ||||
| import FormBase from '@client/components/form/base.vue'; | ||||
| import FormGroup from '@client/components/form/group.vue'; | ||||
| import FormTextarea from '@client/components/form/textarea.vue'; | ||||
| import FormInfo from '@client/components/form/info.vue'; | ||||
| import FormSuspense from '@client/components/form/suspense.vue'; | ||||
| import FormSwitch from '@client/components/debobigego/switch.vue'; | ||||
| import FormInput from '@client/components/debobigego/input.vue'; | ||||
| import FormButton from '@client/components/debobigego/button.vue'; | ||||
| import FormBase from '@client/components/debobigego/base.vue'; | ||||
| import FormGroup from '@client/components/debobigego/group.vue'; | ||||
| import FormTextarea from '@client/components/debobigego/textarea.vue'; | ||||
| import FormInfo from '@client/components/debobigego/info.vue'; | ||||
| import FormSuspense from '@client/components/debobigego/suspense.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| import { fetchInstance } from '@client/instance'; | ||||
|  |  | |||
|  | @ -127,9 +127,9 @@ import { defineComponent, markRaw } from 'vue'; | |||
| import Chart from 'chart.js'; | ||||
| import XModalWindow from '@client/components/ui/modal-window.vue'; | ||||
| import MkUsersDialog from '@client/components/users-dialog.vue'; | ||||
| import MkSelect from '@client/components/ui/select.vue'; | ||||
| import MkSelect from '@client/components/form/select.vue'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import MkSwitch from '@client/components/ui/switch.vue'; | ||||
| import MkSwitch from '@client/components/form/switch.vue'; | ||||
| import MkInfo from '@client/components/ui/info.vue'; | ||||
| import bytes from '@client/filters/bytes'; | ||||
| import number from '@client/filters/number'; | ||||
|  |  | |||
|  | @ -1,19 +1,19 @@ | |||
| <template> | ||||
| <FormBase> | ||||
| 	<FormSuspense :p="init"> | ||||
| 		<FormSwitch v-model:value="enableDiscordIntegration"> | ||||
| 		<FormSwitch v-model="enableDiscordIntegration"> | ||||
| 			{{ $ts.enable }} | ||||
| 		</FormSwitch> | ||||
| 
 | ||||
| 		<template v-if="enableDiscordIntegration"> | ||||
| 			<FormInfo>Callback URL: {{ `${url}/api/dc/cb` }}</FormInfo> | ||||
| 		 | ||||
| 			<FormInput v-model:value="discordClientId"> | ||||
| 			<FormInput v-model="discordClientId"> | ||||
| 				<template #prefix><i class="fas fa-key"></i></template> | ||||
| 				Client ID | ||||
| 			</FormInput> | ||||
| 
 | ||||
| 			<FormInput v-model:value="discordClientSecret"> | ||||
| 			<FormInput v-model="discordClientSecret"> | ||||
| 				<template #prefix><i class="fas fa-key"></i></template> | ||||
| 				Client Secret | ||||
| 			</FormInput> | ||||
|  | @ -26,12 +26,12 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import FormSwitch from '@client/components/form/switch.vue'; | ||||
| import FormInput from '@client/components/form/input.vue'; | ||||
| import FormButton from '@client/components/form/button.vue'; | ||||
| import FormBase from '@client/components/form/base.vue'; | ||||
| import FormInfo from '@client/components/form/info.vue'; | ||||
| import FormSuspense from '@client/components/form/suspense.vue'; | ||||
| import FormSwitch from '@client/components/debobigego/switch.vue'; | ||||
| import FormInput from '@client/components/debobigego/input.vue'; | ||||
| import FormButton from '@client/components/debobigego/button.vue'; | ||||
| import FormBase from '@client/components/debobigego/base.vue'; | ||||
| import FormInfo from '@client/components/debobigego/info.vue'; | ||||
| import FormSuspense from '@client/components/debobigego/suspense.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| import { fetchInstance } from '@client/instance'; | ||||
|  |  | |||
|  | @ -1,19 +1,19 @@ | |||
| <template> | ||||
| <FormBase> | ||||
| 	<FormSuspense :p="init"> | ||||
| 		<FormSwitch v-model:value="enableGithubIntegration"> | ||||
| 		<FormSwitch v-model="enableGithubIntegration"> | ||||
| 			{{ $ts.enable }} | ||||
| 		</FormSwitch> | ||||
| 
 | ||||
| 		<template v-if="enableGithubIntegration"> | ||||
| 			<FormInfo>Callback URL: {{ `${url}/api/gh/cb` }}</FormInfo> | ||||
| 		 | ||||
| 			<FormInput v-model:value="githubClientId"> | ||||
| 			<FormInput v-model="githubClientId"> | ||||
| 				<template #prefix><i class="fas fa-key"></i></template> | ||||
| 				Client ID | ||||
| 			</FormInput> | ||||
| 
 | ||||
| 			<FormInput v-model:value="githubClientSecret"> | ||||
| 			<FormInput v-model="githubClientSecret"> | ||||
| 				<template #prefix><i class="fas fa-key"></i></template> | ||||
| 				Client Secret | ||||
| 			</FormInput> | ||||
|  | @ -26,12 +26,12 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import FormSwitch from '@client/components/form/switch.vue'; | ||||
| import FormInput from '@client/components/form/input.vue'; | ||||
| import FormButton from '@client/components/form/button.vue'; | ||||
| import FormBase from '@client/components/form/base.vue'; | ||||
| import FormInfo from '@client/components/form/info.vue'; | ||||
| import FormSuspense from '@client/components/form/suspense.vue'; | ||||
| import FormSwitch from '@client/components/debobigego/switch.vue'; | ||||
| import FormInput from '@client/components/debobigego/input.vue'; | ||||
| import FormButton from '@client/components/debobigego/button.vue'; | ||||
| import FormBase from '@client/components/debobigego/base.vue'; | ||||
| import FormInfo from '@client/components/debobigego/info.vue'; | ||||
| import FormSuspense from '@client/components/debobigego/suspense.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| import { fetchInstance } from '@client/instance'; | ||||
|  |  | |||
|  | @ -1,19 +1,19 @@ | |||
| <template> | ||||
| <FormBase> | ||||
| 	<FormSuspense :p="init"> | ||||
| 		<FormSwitch v-model:value="enableTwitterIntegration"> | ||||
| 		<FormSwitch v-model="enableTwitterIntegration"> | ||||
| 			{{ $ts.enable }} | ||||
| 		</FormSwitch> | ||||
| 
 | ||||
| 		<template v-if="enableTwitterIntegration"> | ||||
| 			<FormInfo>Callback URL: {{ `${url}/api/tw/cb` }}</FormInfo> | ||||
| 		 | ||||
| 			<FormInput v-model:value="twitterConsumerKey"> | ||||
| 			<FormInput v-model="twitterConsumerKey"> | ||||
| 				<template #prefix><i class="fas fa-key"></i></template> | ||||
| 				Consumer Key | ||||
| 			</FormInput> | ||||
| 
 | ||||
| 			<FormInput v-model:value="twitterConsumerSecret"> | ||||
| 			<FormInput v-model="twitterConsumerSecret"> | ||||
| 				<template #prefix><i class="fas fa-key"></i></template> | ||||
| 				Consumer Secret | ||||
| 			</FormInput> | ||||
|  | @ -26,12 +26,12 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import FormSwitch from '@client/components/form/switch.vue'; | ||||
| import FormInput from '@client/components/form/input.vue'; | ||||
| import FormButton from '@client/components/form/button.vue'; | ||||
| import FormBase from '@client/components/form/base.vue'; | ||||
| import FormInfo from '@client/components/form/info.vue'; | ||||
| import FormSuspense from '@client/components/form/suspense.vue'; | ||||
| import FormSwitch from '@client/components/debobigego/switch.vue'; | ||||
| import FormInput from '@client/components/debobigego/input.vue'; | ||||
| import FormButton from '@client/components/debobigego/button.vue'; | ||||
| import FormBase from '@client/components/debobigego/base.vue'; | ||||
| import FormInfo from '@client/components/debobigego/info.vue'; | ||||
| import FormSuspense from '@client/components/debobigego/suspense.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| import { fetchInstance } from '@client/instance'; | ||||
|  |  | |||
|  | @ -19,14 +19,14 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import FormLink from '@client/components/form/link.vue'; | ||||
| import FormInput from '@client/components/form/input.vue'; | ||||
| import FormButton from '@client/components/form/button.vue'; | ||||
| import FormBase from '@client/components/form/base.vue'; | ||||
| import FormGroup from '@client/components/form/group.vue'; | ||||
| import FormTextarea from '@client/components/form/textarea.vue'; | ||||
| import FormInfo from '@client/components/form/info.vue'; | ||||
| import FormSuspense from '@client/components/form/suspense.vue'; | ||||
| import FormLink from '@client/components/debobigego/link.vue'; | ||||
| import FormInput from '@client/components/debobigego/input.vue'; | ||||
| import FormButton from '@client/components/debobigego/button.vue'; | ||||
| import FormBase from '@client/components/debobigego/base.vue'; | ||||
| import FormGroup from '@client/components/debobigego/group.vue'; | ||||
| import FormTextarea from '@client/components/debobigego/textarea.vue'; | ||||
| import FormInfo from '@client/components/debobigego/info.vue'; | ||||
| import FormSuspense from '@client/components/debobigego/suspense.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| import { fetchInstance } from '@client/instance'; | ||||
|  |  | |||
|  | @ -31,9 +31,9 @@ | |||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import MkInput from '@client/components/ui/input.vue'; | ||||
| import MkSelect from '@client/components/ui/select.vue'; | ||||
| import MkTextarea from '@client/components/ui/textarea.vue'; | ||||
| import MkInput from '@client/components/form/input.vue'; | ||||
| import MkSelect from '@client/components/form/select.vue'; | ||||
| import MkTextarea from '@client/components/form/textarea.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| <template> | ||||
| <div class="_formItem"> | ||||
| 	<div class="_formLabel"><i class="fas fa-microchip"></i> {{ $ts.cpuAndMemory }}</div> | ||||
| 	<div class="_formPanel xhexznfu"> | ||||
| <div class="_debobigegoItem"> | ||||
| 	<div class="_debobigegoLabel"><i class="fas fa-microchip"></i> {{ $ts.cpuAndMemory }}</div> | ||||
| 	<div class="_debobigegoPanel xhexznfu"> | ||||
| 		<div> | ||||
| 			<canvas :ref="cpumem"></canvas> | ||||
| 		</div> | ||||
|  | @ -16,9 +16,9 @@ | |||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
| <div class="_formItem"> | ||||
| 	<div class="_formLabel"><i class="fas fa-hdd"></i> {{ $ts.disk }}</div> | ||||
| 	<div class="_formPanel xhexznfu"> | ||||
| <div class="_debobigegoItem"> | ||||
| 	<div class="_debobigegoLabel"><i class="fas fa-hdd"></i> {{ $ts.disk }}</div> | ||||
| 	<div class="_debobigegoPanel xhexznfu"> | ||||
| 		<div> | ||||
| 			<canvas :ref="disk"></canvas> | ||||
| 		</div> | ||||
|  | @ -33,9 +33,9 @@ | |||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
| <div class="_formItem"> | ||||
| 	<div class="_formLabel"><i class="fas fa-exchange-alt"></i> {{ $ts.network }}</div> | ||||
| 	<div class="_formPanel xhexznfu"> | ||||
| <div class="_debobigegoItem"> | ||||
| 	<div class="_debobigegoLabel"><i class="fas fa-exchange-alt"></i> {{ $ts.network }}</div> | ||||
| 	<div class="_debobigegoPanel xhexznfu"> | ||||
| 		<div> | ||||
| 			<canvas :ref="net"></canvas> | ||||
| 		</div> | ||||
|  | @ -54,8 +54,8 @@ | |||
| import { defineComponent, markRaw } from 'vue'; | ||||
| import Chart from 'chart.js'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import MkSelect from '@client/components/ui/select.vue'; | ||||
| import MkInput from '@client/components/ui/input.vue'; | ||||
| import MkSelect from '@client/components/form/select.vue'; | ||||
| import MkInput from '@client/components/form/input.vue'; | ||||
| import MkContainer from '@client/components/ui/container.vue'; | ||||
| import MkFolder from '@client/components/ui/folder.vue'; | ||||
| import MkwFederation from '../../widgets/federation.vue'; | ||||
|  |  | |||
|  | @ -1,59 +1,59 @@ | |||
| <template> | ||||
| <FormBase> | ||||
| 	<FormSuspense :p="init"> | ||||
| 		<FormSwitch v-model:value="useObjectStorage">{{ $ts.useObjectStorage }}</FormSwitch> | ||||
| 		<FormSwitch v-model="useObjectStorage">{{ $ts.useObjectStorage }}</FormSwitch> | ||||
| 
 | ||||
| 		<template v-if="useObjectStorage"> | ||||
| 			<FormInput v-model:value="objectStorageBaseUrl"> | ||||
| 			<FormInput v-model="objectStorageBaseUrl"> | ||||
| 				<span>{{ $ts.objectStorageBaseUrl }}</span> | ||||
| 				<template #desc>{{ $ts.objectStorageBaseUrlDesc }}</template> | ||||
| 			</FormInput> | ||||
| 
 | ||||
| 			<FormInput v-model:value="objectStorageBucket"> | ||||
| 			<FormInput v-model="objectStorageBucket"> | ||||
| 				<span>{{ $ts.objectStorageBucket }}</span> | ||||
| 				<template #desc>{{ $ts.objectStorageBucketDesc }}</template> | ||||
| 			</FormInput> | ||||
| 
 | ||||
| 			<FormInput v-model:value="objectStoragePrefix"> | ||||
| 			<FormInput v-model="objectStoragePrefix"> | ||||
| 				<span>{{ $ts.objectStoragePrefix }}</span> | ||||
| 				<template #desc>{{ $ts.objectStoragePrefixDesc }}</template> | ||||
| 			</FormInput> | ||||
| 
 | ||||
| 			<FormInput v-model:value="objectStorageEndpoint"> | ||||
| 			<FormInput v-model="objectStorageEndpoint"> | ||||
| 				<span>{{ $ts.objectStorageEndpoint }}</span> | ||||
| 				<template #desc>{{ $ts.objectStorageEndpointDesc }}</template> | ||||
| 			</FormInput> | ||||
| 
 | ||||
| 			<FormInput v-model:value="objectStorageRegion"> | ||||
| 			<FormInput v-model="objectStorageRegion"> | ||||
| 				<span>{{ $ts.objectStorageRegion }}</span> | ||||
| 				<template #desc>{{ $ts.objectStorageRegionDesc }}</template> | ||||
| 			</FormInput> | ||||
| 
 | ||||
| 			<FormInput v-model:value="objectStorageAccessKey"> | ||||
| 			<FormInput v-model="objectStorageAccessKey"> | ||||
| 				<template #prefix><i class="fas fa-key"></i></template> | ||||
| 				<span>Access key</span> | ||||
| 			</FormInput> | ||||
| 
 | ||||
| 			<FormInput v-model:value="objectStorageSecretKey"> | ||||
| 			<FormInput v-model="objectStorageSecretKey"> | ||||
| 				<template #prefix><i class="fas fa-key"></i></template> | ||||
| 				<span>Secret key</span> | ||||
| 			</FormInput> | ||||
| 
 | ||||
| 			<FormSwitch v-model:value="objectStorageUseSSL"> | ||||
| 			<FormSwitch v-model="objectStorageUseSSL"> | ||||
| 				{{ $ts.objectStorageUseSSL }} | ||||
| 				<template #desc>{{ $ts.objectStorageUseSSLDesc }}</template> | ||||
| 			</FormSwitch> | ||||
| 
 | ||||
| 			<FormSwitch v-model:value="objectStorageUseProxy"> | ||||
| 			<FormSwitch v-model="objectStorageUseProxy"> | ||||
| 				{{ $ts.objectStorageUseProxy }} | ||||
| 				<template #desc>{{ $ts.objectStorageUseProxyDesc }}</template> | ||||
| 			</FormSwitch> | ||||
| 
 | ||||
| 			<FormSwitch v-model:value="objectStorageSetPublicRead"> | ||||
| 			<FormSwitch v-model="objectStorageSetPublicRead"> | ||||
| 				{{ $ts.objectStorageSetPublicRead }} | ||||
| 			</FormSwitch> | ||||
| 
 | ||||
| 			<FormSwitch v-model:value="objectStorageS3ForcePathStyle"> | ||||
| 			<FormSwitch v-model="objectStorageS3ForcePathStyle"> | ||||
| 				s3ForcePathStyle | ||||
| 			</FormSwitch> | ||||
| 		</template> | ||||
|  | @ -65,12 +65,12 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import FormSwitch from '@client/components/form/switch.vue'; | ||||
| import FormInput from '@client/components/form/input.vue'; | ||||
| import FormButton from '@client/components/form/button.vue'; | ||||
| import FormBase from '@client/components/form/base.vue'; | ||||
| import FormGroup from '@client/components/form/group.vue'; | ||||
| import FormSuspense from '@client/components/form/suspense.vue'; | ||||
| import FormSwitch from '@client/components/debobigego/switch.vue'; | ||||
| import FormInput from '@client/components/debobigego/input.vue'; | ||||
| import FormButton from '@client/components/debobigego/button.vue'; | ||||
| import FormBase from '@client/components/debobigego/base.vue'; | ||||
| import FormGroup from '@client/components/debobigego/group.vue'; | ||||
| import FormSuspense from '@client/components/debobigego/suspense.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| import { fetchInstance } from '@client/instance'; | ||||
|  |  | |||
|  | @ -2,17 +2,17 @@ | |||
| <FormBase> | ||||
| 	<FormSuspense :p="init"> | ||||
| 		<FormGroup> | ||||
| 			<FormInput v-model:value="summalyProxy"> | ||||
| 			<FormInput v-model="summalyProxy"> | ||||
| 				<template #prefix><i class="fas fa-link"></i></template> | ||||
| 				Summaly Proxy URL | ||||
| 			</FormInput> | ||||
| 		</FormGroup> | ||||
| 		<FormGroup> | ||||
| 			<FormInput v-model:value="deeplAuthKey"> | ||||
| 			<FormInput v-model="deeplAuthKey"> | ||||
| 				<template #prefix><i class="fas fa-key"></i></template> | ||||
| 				DeepL Auth Key | ||||
| 			</FormInput> | ||||
| 			<FormSwitch v-model:value="deeplIsPro"> | ||||
| 			<FormSwitch v-model="deeplIsPro"> | ||||
| 				Pro account | ||||
| 			</FormSwitch> | ||||
| 		</FormGroup> | ||||
|  | @ -23,12 +23,12 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import FormSwitch from '@client/components/form/switch.vue'; | ||||
| import FormInput from '@client/components/form/input.vue'; | ||||
| import FormButton from '@client/components/form/button.vue'; | ||||
| import FormBase from '@client/components/form/base.vue'; | ||||
| import FormGroup from '@client/components/form/group.vue'; | ||||
| import FormSuspense from '@client/components/form/suspense.vue'; | ||||
| import FormSwitch from '@client/components/debobigego/switch.vue'; | ||||
| import FormInput from '@client/components/debobigego/input.vue'; | ||||
| import FormButton from '@client/components/debobigego/button.vue'; | ||||
| import FormBase from '@client/components/debobigego/base.vue'; | ||||
| import FormGroup from '@client/components/debobigego/group.vue'; | ||||
| import FormSuspense from '@client/components/debobigego/suspense.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| import { fetchInstance } from '@client/instance'; | ||||
|  |  | |||
|  | @ -17,8 +17,8 @@ | |||
| 			</FormGroup> | ||||
| 		</FormSuspense> | ||||
| 	 | ||||
| 		<div class="_formItem"> | ||||
| 			<div class="_formPanel"> | ||||
| 		<div class="_debobigegoItem"> | ||||
| 			<div class="_debobigegoPanel"> | ||||
| 				<MkInstanceStats :chart-limit="300" :detailed="true"/> | ||||
| 			</div> | ||||
| 		</div> | ||||
|  | @ -47,18 +47,18 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { computed, defineComponent, markRaw } from 'vue'; | ||||
| import FormKeyValueView from '@client/components/form/key-value-view.vue'; | ||||
| import FormInput from '@client/components/form/input.vue'; | ||||
| import FormButton from '@client/components/form/button.vue'; | ||||
| import FormBase from '@client/components/form/base.vue'; | ||||
| import FormGroup from '@client/components/form/group.vue'; | ||||
| import FormTextarea from '@client/components/form/textarea.vue'; | ||||
| import FormInfo from '@client/components/form/info.vue'; | ||||
| import FormSuspense from '@client/components/form/suspense.vue'; | ||||
| import FormKeyValueView from '@client/components/debobigego/key-value-view.vue'; | ||||
| import FormInput from '@client/components/debobigego/input.vue'; | ||||
| import FormButton from '@client/components/debobigego/button.vue'; | ||||
| import FormBase from '@client/components/debobigego/base.vue'; | ||||
| import FormGroup from '@client/components/debobigego/group.vue'; | ||||
| import FormTextarea from '@client/components/debobigego/textarea.vue'; | ||||
| import FormInfo from '@client/components/debobigego/info.vue'; | ||||
| import FormSuspense from '@client/components/debobigego/suspense.vue'; | ||||
| import MkInstanceStats from '@client/components/instance-stats.vue'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import MkSelect from '@client/components/ui/select.vue'; | ||||
| import MkInput from '@client/components/ui/input.vue'; | ||||
| import MkSelect from '@client/components/form/select.vue'; | ||||
| import MkInput from '@client/components/form/input.vue'; | ||||
| import MkContainer from '@client/components/ui/container.vue'; | ||||
| import MkFolder from '@client/components/ui/folder.vue'; | ||||
| import { version, url } from '@client/config'; | ||||
|  |  | |||
|  | @ -16,14 +16,14 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import FormKeyValueView from '@client/components/form/key-value-view.vue'; | ||||
| import FormInput from '@client/components/form/input.vue'; | ||||
| import FormButton from '@client/components/form/button.vue'; | ||||
| import FormBase from '@client/components/form/base.vue'; | ||||
| import FormGroup from '@client/components/form/group.vue'; | ||||
| import FormTextarea from '@client/components/form/textarea.vue'; | ||||
| import FormInfo from '@client/components/form/info.vue'; | ||||
| import FormSuspense from '@client/components/form/suspense.vue'; | ||||
| import FormKeyValueView from '@client/components/debobigego/key-value-view.vue'; | ||||
| import FormInput from '@client/components/debobigego/input.vue'; | ||||
| import FormButton from '@client/components/debobigego/button.vue'; | ||||
| import FormBase from '@client/components/debobigego/base.vue'; | ||||
| import FormGroup from '@client/components/debobigego/group.vue'; | ||||
| import FormTextarea from '@client/components/debobigego/textarea.vue'; | ||||
| import FormInfo from '@client/components/debobigego/info.vue'; | ||||
| import FormSuspense from '@client/components/debobigego/suspense.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| import { fetchInstance } from '@client/instance'; | ||||
|  |  | |||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue