tweak ui
This commit is contained in:
		
							parent
							
								
									76b2561893
								
							
						
					
					
						commit
						69d7cfc5ce
					
				
					 24 changed files with 170 additions and 1841 deletions
				
			
		|  | @ -1,65 +0,0 @@ | ||||||
| <template> |  | ||||||
| <div v-size="{ max: [400] }" class="rbusrurv" :class="{ wide: forceWide }"> |  | ||||||
| 	<slot></slot> |  | ||||||
| </div> |  | ||||||
| </template> |  | ||||||
| 
 |  | ||||||
| <script lang="ts"> |  | ||||||
| import { defineComponent } from 'vue'; |  | ||||||
| 
 |  | ||||||
| export default defineComponent({ |  | ||||||
| 	props: { |  | ||||||
| 		forceWide: { |  | ||||||
| 			type: Boolean, |  | ||||||
| 			required: false, |  | ||||||
| 			default: false, |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| }); |  | ||||||
| </script> |  | ||||||
| 
 |  | ||||||
| <style lang="scss" scoped> |  | ||||||
| .rbusrurv { |  | ||||||
| 	// 他のCSSからも参照されるので消さないように |  | ||||||
| 	--debobigegoXPadding: 32px; |  | ||||||
| 	--debobigegoYPadding: 32px; |  | ||||||
| 
 |  | ||||||
| 	--debobigegoContentHMargin: 16px; |  | ||||||
| 
 |  | ||||||
| 	font-size: 95%; |  | ||||||
| 	line-height: 1.3em; |  | ||||||
| 	background: var(--bg); |  | ||||||
| 	padding: var(--debobigegoYPadding) var(--debobigegoXPadding); |  | ||||||
| 	max-width: 750px; |  | ||||||
| 	margin: 0 auto; |  | ||||||
| 
 |  | ||||||
| 	&:not(.wide).max-width_400px { |  | ||||||
| 		--debobigegoXPadding: 0px; |  | ||||||
| 
 |  | ||||||
| 		> ::v-deep(*) { |  | ||||||
| 			._debobigegoPanel { |  | ||||||
| 				border: solid 0.5px var(--divider); |  | ||||||
| 				border-radius: 0; |  | ||||||
| 				border-left: none; |  | ||||||
| 				border-right: none; |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			._debobigego_group { |  | ||||||
| 				> *:not(._debobigegoNoConcat) { |  | ||||||
| 					&:not(:last-child):not(._debobigegoNoConcatPrev) { |  | ||||||
| 						&._debobigegoPanel, ._debobigegoPanel { |  | ||||||
| 							border-bottom: solid 0.5px var(--divider); |  | ||||||
| 						} |  | ||||||
| 					} |  | ||||||
| 
 |  | ||||||
| 					&:not(:first-child):not(._debobigegoNoConcatNext) { |  | ||||||
| 						&._debobigegoPanel, ._debobigegoPanel { |  | ||||||
| 							border-top: none; |  | ||||||
| 						} |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| </style> |  | ||||||
|  | @ -1,81 +0,0 @@ | ||||||
| <template> |  | ||||||
| <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> |  | ||||||
| 			<div class="icon"> |  | ||||||
| 				<slot name="suffixIcon"></slot> |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 	</button> |  | ||||||
| 	<div class="_debobigegoCaption"><slot name="desc"></slot></div> |  | ||||||
| </div> |  | ||||||
| </template> |  | ||||||
| 
 |  | ||||||
| <script lang="ts"> |  | ||||||
| import { defineComponent } from 'vue'; |  | ||||||
| import './debobigego.scss'; |  | ||||||
| 
 |  | ||||||
| export default defineComponent({ |  | ||||||
| 	props: { |  | ||||||
| 		primary: { |  | ||||||
| 			type: Boolean, |  | ||||||
| 			required: false, |  | ||||||
| 			default: false, |  | ||||||
| 		}, |  | ||||||
| 		danger: { |  | ||||||
| 			type: Boolean, |  | ||||||
| 			required: false, |  | ||||||
| 			default: false, |  | ||||||
| 		}, |  | ||||||
| 		disabled: { |  | ||||||
| 			type: Boolean, |  | ||||||
| 			required: false, |  | ||||||
| 			default: false, |  | ||||||
| 		}, |  | ||||||
| 		center: { |  | ||||||
| 			type: Boolean, |  | ||||||
| 			required: false, |  | ||||||
| 			default: true, |  | ||||||
| 		} |  | ||||||
| 	}, |  | ||||||
| }); |  | ||||||
| </script> |  | ||||||
| 
 |  | ||||||
| <style lang="scss" scoped> |  | ||||||
| .yzpgjkxe { |  | ||||||
| 	> .main { |  | ||||||
| 		display: flex; |  | ||||||
| 		width: 100%; |  | ||||||
| 		box-sizing: border-box; |  | ||||||
| 		padding: 14px 16px; |  | ||||||
| 		text-align: left; |  | ||||||
| 		align-items: center; |  | ||||||
| 
 |  | ||||||
| 		&.center { |  | ||||||
| 			display: block; |  | ||||||
| 			text-align: center; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		&.primary { |  | ||||||
| 			color: var(--accent); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		&.danger { |  | ||||||
| 			color: #ff2a2a; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		> .suffix { |  | ||||||
| 			display: inline-flex; |  | ||||||
| 			margin-left: auto; |  | ||||||
| 			opacity: 0.7; |  | ||||||
| 
 |  | ||||||
| 			> .icon { |  | ||||||
| 				margin-left: 1em; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| </style> |  | ||||||
|  | @ -1,52 +0,0 @@ | ||||||
| ._debobigegoPanel { |  | ||||||
| 	background: var(--panel); |  | ||||||
| 	border-radius: var(--radius); |  | ||||||
| 	transition: background 0.2s ease; |  | ||||||
| 
 |  | ||||||
| 	&._debobigegoClickable { |  | ||||||
| 		&:hover { |  | ||||||
| 			//background: var(--panelHighlight); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		&:active { |  | ||||||
| 			background: var(--panelHighlight); |  | ||||||
| 			transition: background 0s; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| ._debobigegoLabel, |  | ||||||
| ._debobigegoCaption { |  | ||||||
| 	font-size: 80%; |  | ||||||
| 	color: var(--fgTransparentWeak); |  | ||||||
| 
 |  | ||||||
| 	&:empty { |  | ||||||
| 		display: none; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| ._debobigegoLabel { |  | ||||||
| 	position: sticky; |  | ||||||
| 	top: var(--stickyTop, 0px); |  | ||||||
| 	z-index: 2; |  | ||||||
| 	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_ ._debobigegoLabel { |  | ||||||
| 	transition: none !important; |  | ||||||
| 	background: transparent; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| ._debobigegoCaption { |  | ||||||
| 	padding: 8px var(--debobigegoContentHMargin) 0 var(--debobigegoContentHMargin); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| ._debobigegoItem { |  | ||||||
| 	& + ._debobigegoItem { |  | ||||||
| 		margin-top: 24px; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  | @ -1,78 +0,0 @@ | ||||||
| <template> |  | ||||||
| <div v-size="{ max: [500] }" v-sticky-container class="vrtktovg _debobigegoItem _debobigegoNoConcat"> |  | ||||||
| 	<div class="_debobigegoLabel"><slot name="label"></slot></div> |  | ||||||
| 	<div ref="child" class="main _debobigego_group"> |  | ||||||
| 		<slot></slot> |  | ||||||
| 	</div> |  | ||||||
| 	<div class="_debobigegoCaption"><slot name="caption"></slot></div> |  | ||||||
| </div> |  | ||||||
| </template> |  | ||||||
| 
 |  | ||||||
| <script lang="ts"> |  | ||||||
| import { defineComponent, onMounted, ref } from 'vue'; |  | ||||||
| 
 |  | ||||||
| export default defineComponent({ |  | ||||||
| 	setup(props, context) { |  | ||||||
| 		const child = ref<HTMLElement | null>(null); |  | ||||||
| 
 |  | ||||||
| 		const scanChild = () => { |  | ||||||
| 			if (child.value == null) return; |  | ||||||
| 			const els = Array.from(child.value.children); |  | ||||||
| 			for (let i = 0; i < els.length; i++) { |  | ||||||
| 				const el = els[i]; |  | ||||||
| 				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'); |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		}; |  | ||||||
| 
 |  | ||||||
| 		onMounted(() => { |  | ||||||
| 			scanChild(); |  | ||||||
| 
 |  | ||||||
| 			const observer = new MutationObserver(records => { |  | ||||||
| 				scanChild(); |  | ||||||
| 			}); |  | ||||||
| 
 |  | ||||||
| 			observer.observe(child.value, { |  | ||||||
| 				childList: true, |  | ||||||
| 				subtree: false, |  | ||||||
| 				attributes: false, |  | ||||||
| 				characterData: false, |  | ||||||
| 			}); |  | ||||||
| 		}); |  | ||||||
| 
 |  | ||||||
| 		return { |  | ||||||
| 			child |  | ||||||
| 		}; |  | ||||||
| 	} |  | ||||||
| }); |  | ||||||
| </script> |  | ||||||
| 
 |  | ||||||
| <style lang="scss" scoped> |  | ||||||
| .vrtktovg { |  | ||||||
| 	> .main { |  | ||||||
| 		> ::v-deep(*):not(._debobigegoNoConcat) { |  | ||||||
| 			&:not(._debobigegoNoConcatNext) { |  | ||||||
| 				margin: 0; |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			&: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(._debobigegoNoConcatNext) { |  | ||||||
| 				&._debobigegoPanel, ._debobigegoPanel { |  | ||||||
| 					border-top: none; |  | ||||||
| 					border-top-left-radius: 0; |  | ||||||
| 					border-top-right-radius: 0; |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| </style> |  | ||||||
|  | @ -1,47 +0,0 @@ | ||||||
| <template> |  | ||||||
| <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> |  | ||||||
| 	</div> |  | ||||||
| </div> |  | ||||||
| </template> |  | ||||||
| 
 |  | ||||||
| <script lang="ts"> |  | ||||||
| import { defineComponent } from 'vue'; |  | ||||||
| 
 |  | ||||||
| export default defineComponent({ |  | ||||||
| 	props: { |  | ||||||
| 		warn: { |  | ||||||
| 			type: Boolean, |  | ||||||
| 			required: false, |  | ||||||
| 			default: false |  | ||||||
| 		}, |  | ||||||
| 	}, |  | ||||||
| 	data() { |  | ||||||
| 		return { |  | ||||||
| 		}; |  | ||||||
| 	} |  | ||||||
| }); |  | ||||||
| </script> |  | ||||||
| 
 |  | ||||||
| <style lang="scss" scoped> |  | ||||||
| .fzenkabp { |  | ||||||
| 	> div { |  | ||||||
| 		padding: 14px 16px; |  | ||||||
| 		font-size: 90%; |  | ||||||
| 		background: var(--infoBg); |  | ||||||
| 		color: var(--infoFg); |  | ||||||
| 
 |  | ||||||
| 		&.warn { |  | ||||||
| 			background: var(--infoWarnBg); |  | ||||||
| 			color: var(--infoWarnFg); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		> i { |  | ||||||
| 			margin-right: 4px; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| </style> |  | ||||||
|  | @ -1,292 +0,0 @@ | ||||||
| <template> |  | ||||||
| <FormGroup class="_debobigegoItem"> |  | ||||||
| 	<template #label><slot></slot></template> |  | ||||||
| 	<div class="ztzhwixg _debobigegoItem" :class="{ inline, disabled }"> |  | ||||||
| 		<div ref="icon" class="icon"><slot name="icon"></slot></div> |  | ||||||
| 		<div class="input _debobigegoPanel"> |  | ||||||
| 			<div ref="prefixEl" class="prefix"><slot name="prefix"></slot></div> |  | ||||||
| 			<input ref="inputEl" |  | ||||||
| 				v-model="v" |  | ||||||
| 				:type="type" |  | ||||||
| 				:disabled="disabled" |  | ||||||
| 				:required="required" |  | ||||||
| 				:readonly="readonly" |  | ||||||
| 				:placeholder="placeholder" |  | ||||||
| 				:pattern="pattern" |  | ||||||
| 				:autocomplete="autocomplete" |  | ||||||
| 				:spellcheck="spellcheck" |  | ||||||
| 				:step="step" |  | ||||||
| 				:list="id" |  | ||||||
| 				@focus="focused = true" |  | ||||||
| 				@blur="focused = false" |  | ||||||
| 				@keydown="onKeydown($event)" |  | ||||||
| 				@input="onInput" |  | ||||||
| 			> |  | ||||||
| 			<datalist v-if="datalist" :id="id"> |  | ||||||
| 				<option v-for="data in datalist" :value="data"/> |  | ||||||
| 			</datalist> |  | ||||||
| 			<div ref="suffixEl" class="suffix"><slot name="suffix"></slot></div> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| 	<template #caption><slot name="desc"></slot></template> |  | ||||||
| 
 |  | ||||||
| 	<FormButton v-if="manualSave && changed" primary @click="updated"><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 './debobigego.scss'; |  | ||||||
| import FormButton from './button.vue'; |  | ||||||
| import FormGroup from './group.vue'; |  | ||||||
| 
 |  | ||||||
| export default defineComponent({ |  | ||||||
| 	components: { |  | ||||||
| 		FormGroup, |  | ||||||
| 		FormButton, |  | ||||||
| 	}, |  | ||||||
| 	props: { |  | ||||||
| 		modelValue: { |  | ||||||
| 			required: false |  | ||||||
| 		}, |  | ||||||
| 		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 |  | ||||||
| 		}, |  | ||||||
| 		step: { |  | ||||||
| 			required: false |  | ||||||
| 		}, |  | ||||||
| 		datalist: { |  | ||||||
| 			type: Array, |  | ||||||
| 			required: false, |  | ||||||
| 		}, |  | ||||||
| 		inline: { |  | ||||||
| 			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); |  | ||||||
| 		const id = Math.random().toString(); // TODO: uuid? |  | ||||||
| 		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 onKeydown = (ev: KeyboardEvent) => { |  | ||||||
| 			context.emit('keydown', ev); |  | ||||||
| 
 |  | ||||||
| 			if (ev.code === 'Enter') { |  | ||||||
| 				context.emit('enter'); |  | ||||||
| 			} |  | ||||||
| 		}; |  | ||||||
| 
 |  | ||||||
| 		const updated = () => { |  | ||||||
| 			changed.value = false; |  | ||||||
| 			if (type?.value === 'number') { |  | ||||||
| 				context.emit('update:modelValue', parseFloat(v.value)); |  | ||||||
| 			} else { |  | ||||||
| 				context.emit('update:modelValue', v.value); |  | ||||||
| 			} |  | ||||||
| 		}; |  | ||||||
| 
 |  | ||||||
| 		watch(modelValue.value, 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 { |  | ||||||
| 			id, |  | ||||||
| 			v, |  | ||||||
| 			focused, |  | ||||||
| 			invalid, |  | ||||||
| 			changed, |  | ||||||
| 			filled, |  | ||||||
| 			inputEl, |  | ||||||
| 			prefixEl, |  | ||||||
| 			suffixEl, |  | ||||||
| 			focus, |  | ||||||
| 			onInput, |  | ||||||
| 			onKeydown, |  | ||||||
| 			updated, |  | ||||||
| 		}; |  | ||||||
| 	}, |  | ||||||
| }); |  | ||||||
| </script> |  | ||||||
| 
 |  | ||||||
| <style lang="scss" scoped> |  | ||||||
| .ztzhwixg { |  | ||||||
| 	position: relative; |  | ||||||
| 
 |  | ||||||
| 	> .icon { |  | ||||||
| 		position: absolute; |  | ||||||
| 		top: 0; |  | ||||||
| 		left: 0; |  | ||||||
| 		width: 24px; |  | ||||||
| 		text-align: center; |  | ||||||
| 		line-height: 32px; |  | ||||||
| 
 |  | ||||||
| 		&:not(:empty) + .input { |  | ||||||
| 			margin-left: 28px; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	> .input { |  | ||||||
| 		$height: 48px; |  | ||||||
| 		position: relative; |  | ||||||
| 
 |  | ||||||
| 		> input { |  | ||||||
| 			display: block; |  | ||||||
| 			height: $height; |  | ||||||
| 			width: 100%; |  | ||||||
| 			margin: 0; |  | ||||||
| 			padding: 0 16px; |  | ||||||
| 			font: inherit; |  | ||||||
| 			font-weight: normal; |  | ||||||
| 			font-size: 1em; |  | ||||||
| 			line-height: $height; |  | ||||||
| 			color: var(--inputText); |  | ||||||
| 			background: transparent; |  | ||||||
| 			border: none; |  | ||||||
| 			border-radius: 0; |  | ||||||
| 			outline: none; |  | ||||||
| 			box-shadow: none; |  | ||||||
| 			box-sizing: border-box; |  | ||||||
| 
 |  | ||||||
| 			&[type='file'] { |  | ||||||
| 				display: none; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		> .prefix, |  | ||||||
| 		> .suffix { |  | ||||||
| 			display: block; |  | ||||||
| 			position: absolute; |  | ||||||
| 			z-index: 1; |  | ||||||
| 			top: 0; |  | ||||||
| 			padding: 0 16px; |  | ||||||
| 			font-size: 1em; |  | ||||||
| 			line-height: $height; |  | ||||||
| 			color: var(--inputLabel); |  | ||||||
| 			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: 8px; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		> .suffix { |  | ||||||
| 			right: 0; |  | ||||||
| 			padding-left: 8px; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	&.inline { |  | ||||||
| 		display: inline-block; |  | ||||||
| 		margin: 0; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	&.disabled { |  | ||||||
| 		opacity: 0.7; |  | ||||||
| 
 |  | ||||||
| 		&, * { |  | ||||||
| 			cursor: not-allowed !important; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| </style> |  | ||||||
|  | @ -1,38 +0,0 @@ | ||||||
| <template> |  | ||||||
| <div class="_debobigegoItem"> |  | ||||||
| 	<div class="_debobigegoPanel anocepby"> |  | ||||||
| 		<span class="key"><slot name="key"></slot></span> |  | ||||||
| 		<span class="value"><slot name="value"></slot></span> |  | ||||||
| 	</div> |  | ||||||
| </div> |  | ||||||
| </template> |  | ||||||
| 
 |  | ||||||
| <script lang="ts"> |  | ||||||
| import { defineComponent } from 'vue'; |  | ||||||
| import './debobigego.scss'; |  | ||||||
| 
 |  | ||||||
| export default defineComponent({ |  | ||||||
| 
 |  | ||||||
| }); |  | ||||||
| </script> |  | ||||||
| 
 |  | ||||||
| <style lang="scss" scoped> |  | ||||||
| .anocepby { |  | ||||||
| 	display: flex; |  | ||||||
| 	align-items: center; |  | ||||||
| 	padding: 14px var(--debobigegoContentHMargin); |  | ||||||
| 
 |  | ||||||
| 	> .key { |  | ||||||
| 		margin-right: 12px; |  | ||||||
| 		white-space: nowrap; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	> .value { |  | ||||||
| 		margin-left: auto; |  | ||||||
| 		opacity: 0.7; |  | ||||||
| 		text-overflow: ellipsis; |  | ||||||
| 		white-space: nowrap; |  | ||||||
| 		overflow: hidden; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| </style> |  | ||||||
|  | @ -1,103 +0,0 @@ | ||||||
| <template> |  | ||||||
| <div class="qmfkfnzi _debobigegoItem"> |  | ||||||
| 	<a v-if="external" class="main _button _debobigegoPanel _debobigegoClickable" :href="to" target="_blank"> |  | ||||||
| 		<span class="icon"><slot name="icon"></slot></span> |  | ||||||
| 		<span class="text"><slot></slot></span> |  | ||||||
| 		<span class="right"> |  | ||||||
| 			<span class="text"><slot name="suffix"></slot></span> |  | ||||||
| 			<i class="fas fa-external-link-alt icon"></i> |  | ||||||
| 		</span> |  | ||||||
| 	</a> |  | ||||||
| 	<MkA v-else class="main _button _debobigegoPanel _debobigegoClickable" :class="{ active }" :to="to" :behavior="behavior"> |  | ||||||
| 		<span class="icon"><slot name="icon"></slot></span> |  | ||||||
| 		<span class="text"><slot></slot></span> |  | ||||||
| 		<span class="right"> |  | ||||||
| 			<span class="text"><slot name="suffix"></slot></span> |  | ||||||
| 			<i class="fas fa-chevron-right icon"></i> |  | ||||||
| 		</span> |  | ||||||
| 	</MkA> |  | ||||||
| </div> |  | ||||||
| </template> |  | ||||||
| 
 |  | ||||||
| <script lang="ts"> |  | ||||||
| import { defineComponent } from 'vue'; |  | ||||||
| import './debobigego.scss'; |  | ||||||
| 
 |  | ||||||
| export default defineComponent({ |  | ||||||
| 	props: { |  | ||||||
| 		to: { |  | ||||||
| 			type: String, |  | ||||||
| 			required: true |  | ||||||
| 		}, |  | ||||||
| 		active: { |  | ||||||
| 			type: Boolean, |  | ||||||
| 			required: false |  | ||||||
| 		}, |  | ||||||
| 		external: { |  | ||||||
| 			type: Boolean, |  | ||||||
| 			required: false |  | ||||||
| 		}, |  | ||||||
| 		behavior: { |  | ||||||
| 			type: String, |  | ||||||
| 			required: false, |  | ||||||
| 		}, |  | ||||||
| 	}, |  | ||||||
| 	data() { |  | ||||||
| 		return { |  | ||||||
| 		}; |  | ||||||
| 	} |  | ||||||
| }); |  | ||||||
| </script> |  | ||||||
| 
 |  | ||||||
| <style lang="scss" scoped> |  | ||||||
| .qmfkfnzi { |  | ||||||
| 	> .main { |  | ||||||
| 		display: flex; |  | ||||||
| 		align-items: center; |  | ||||||
| 		width: 100%; |  | ||||||
| 		box-sizing: border-box; |  | ||||||
| 		padding: 14px 16px 14px 14px; |  | ||||||
| 
 |  | ||||||
| 		&:hover { |  | ||||||
| 			text-decoration: none; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		&.active { |  | ||||||
| 			color: var(--accent); |  | ||||||
| 			background: var(--panelHighlight); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		> .icon { |  | ||||||
| 			width: 32px; |  | ||||||
| 			margin-right: 2px; |  | ||||||
| 			flex-shrink: 0; |  | ||||||
| 			text-align: center; |  | ||||||
| 			opacity: 0.8; |  | ||||||
| 
 |  | ||||||
| 			&:empty { |  | ||||||
| 				display: none; |  | ||||||
| 
 |  | ||||||
| 				& + .text { |  | ||||||
| 					padding-left: 4px; |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		> .text { |  | ||||||
| 			white-space: nowrap; |  | ||||||
| 			text-overflow: ellipsis; |  | ||||||
| 			overflow: hidden; |  | ||||||
| 			padding-right: 12px; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		> .right { |  | ||||||
| 			margin-left: auto; |  | ||||||
| 			opacity: 0.7; |  | ||||||
| 
 |  | ||||||
| 			> .text:not(:empty) { |  | ||||||
| 				margin-right: 0.75em; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| </style> |  | ||||||
|  | @ -1,102 +0,0 @@ | ||||||
| <template> |  | ||||||
| <FormGroup class="_debobigegoItem"> |  | ||||||
| 	<template #label><slot></slot></template> |  | ||||||
| 	<div class="drooglns _debobigegoItem" :class="{ tall }"> |  | ||||||
| 		<div class="input _debobigegoPanel"> |  | ||||||
| 			<textarea v-model="v" |  | ||||||
| 				class="_monospace" |  | ||||||
| 				readonly |  | ||||||
| 				:spellcheck="false" |  | ||||||
| 			></textarea> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| 	<template #caption><slot name="desc"></slot></template> |  | ||||||
| </FormGroup> |  | ||||||
| </template> |  | ||||||
| 
 |  | ||||||
| <script lang="ts"> |  | ||||||
| import { defineComponent, ref, toRefs, watch } from 'vue'; |  | ||||||
| import * as JSON5 from 'json5'; |  | ||||||
| import './debobigego.scss'; |  | ||||||
| import FormGroup from './group.vue'; |  | ||||||
| 
 |  | ||||||
| export default defineComponent({ |  | ||||||
| 	components: { |  | ||||||
| 		FormGroup, |  | ||||||
| 	}, |  | ||||||
| 	props: { |  | ||||||
| 		value: { |  | ||||||
| 			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 { value } = toRefs(props); |  | ||||||
| 		const v = ref(''); |  | ||||||
| 
 |  | ||||||
| 		watch(() => value, newValue => { |  | ||||||
| 			v.value = JSON5.stringify(newValue.value, null, '\t'); |  | ||||||
| 		}, { |  | ||||||
| 			immediate: true |  | ||||||
| 		}); |  | ||||||
| 
 |  | ||||||
| 		return { |  | ||||||
| 			v, |  | ||||||
| 		}; |  | ||||||
| 	} |  | ||||||
| }); |  | ||||||
| </script> |  | ||||||
| 
 |  | ||||||
| <style lang="scss" scoped> |  | ||||||
| .drooglns { |  | ||||||
| 	position: relative; |  | ||||||
| 
 |  | ||||||
| 	> .input { |  | ||||||
| 		position: relative; |  | ||||||
| 	 |  | ||||||
| 		> textarea { |  | ||||||
| 			display: block; |  | ||||||
| 			width: 100%; |  | ||||||
| 			min-width: 100%; |  | ||||||
| 			max-width: 100%; |  | ||||||
| 			min-height: 130px; |  | ||||||
| 			margin: 0; |  | ||||||
| 			padding: 16px var(--debobigegoContentHMargin); |  | ||||||
| 			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); |  | ||||||
| 			tab-size: 2; |  | ||||||
| 			white-space: pre; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	&.tall { |  | ||||||
| 		> .input { |  | ||||||
| 			> textarea { |  | ||||||
| 				min-height: 200px; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| </style> |  | ||||||
|  | @ -1,42 +0,0 @@ | ||||||
| <template> |  | ||||||
| <FormGroup class="uljviswt _debobigegoItem"> |  | ||||||
| 	<template #label><slot name="label"></slot></template> |  | ||||||
| 	<slot :items="items"></slot> |  | ||||||
| 	<div v-if="empty" key="_empty_" class="empty"> |  | ||||||
| 		<slot name="empty"></slot> |  | ||||||
| 	</div> |  | ||||||
| 	<FormButton v-show="more" class="button" :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }" primary @click="fetchMore"> |  | ||||||
| 		<template v-if="!moreFetching">{{ $ts.loadMore }}</template> |  | ||||||
| 		<template v-if="moreFetching"><MkLoading inline/></template> |  | ||||||
| 	</FormButton> |  | ||||||
| </FormGroup> |  | ||||||
| </template> |  | ||||||
| 
 |  | ||||||
| <script lang="ts"> |  | ||||||
| import { defineComponent } from 'vue'; |  | ||||||
| import FormButton from './button.vue'; |  | ||||||
| import FormGroup from './group.vue'; |  | ||||||
| import paging from '@/scripts/paging'; |  | ||||||
| 
 |  | ||||||
| export default defineComponent({ |  | ||||||
| 	components: { |  | ||||||
| 		FormButton, |  | ||||||
| 		FormGroup, |  | ||||||
| 	}, |  | ||||||
| 
 |  | ||||||
| 	mixins: [ |  | ||||||
| 		paging({}), |  | ||||||
| 	], |  | ||||||
| 
 |  | ||||||
| 	props: { |  | ||||||
| 		pagination: { |  | ||||||
| 			required: true |  | ||||||
| 		}, |  | ||||||
| 	}, |  | ||||||
| }); |  | ||||||
| </script> |  | ||||||
| 
 |  | ||||||
| <style lang="scss" scoped> |  | ||||||
| .uljviswt { |  | ||||||
| } |  | ||||||
| </style> |  | ||||||
|  | @ -1,112 +0,0 @@ | ||||||
| <script lang="ts"> |  | ||||||
| import { defineComponent, h } from 'vue'; |  | ||||||
| import MkRadio from '@/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> |  | ||||||
|  | @ -1,122 +0,0 @@ | ||||||
| <template> |  | ||||||
| <div class="ifitouly _debobigegoItem" :class="{ focused, disabled }"> |  | ||||||
| 	<div class="_debobigegoLabel"><slot name="label"></slot></div> |  | ||||||
| 	<div class="_debobigegoPanel main"> |  | ||||||
| 		<input |  | ||||||
| 			ref="input" |  | ||||||
| 			v-model="v" |  | ||||||
| 			type="range" |  | ||||||
| 			: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> |  | ||||||
|  | @ -1,145 +0,0 @@ | ||||||
| <template> |  | ||||||
| <div class="yrtfrpux _debobigegoItem" :class="{ disabled, inline }"> |  | ||||||
| 	<div class="_debobigegoLabel"><slot name="label"></slot></div> |  | ||||||
| 	<div ref="icon" class="icon"><slot name="icon"></slot></div> |  | ||||||
| 	<div class="input _debobigegoPanel _debobigegoClickable" @click="focus"> |  | ||||||
| 		<div ref="prefix" class="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,101 +0,0 @@ | ||||||
| <template> |  | ||||||
| <transition name="fade" mode="out-in"> |  | ||||||
| 	<div v-if="pending" class="_debobigegoItem"> |  | ||||||
| 		<div class="_debobigegoPanel"> |  | ||||||
| 			<MkLoading/> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| 	<div v-else-if="resolved" class="_debobigegoItem"> |  | ||||||
| 		<slot :result="result"></slot> |  | ||||||
| 	</div> |  | ||||||
| 	<div v-else class="_debobigegoItem"> |  | ||||||
| 		<div class="_debobigegoPanel eiurkvay"> |  | ||||||
| 			<div><i class="fas fa-exclamation-triangle"></i> {{ $ts.somethingHappened }}</div> |  | ||||||
| 			<MkButton inline class="retry" @click="retry"><i class="fas fa-redo-alt"></i> {{ $ts.retry }}</MkButton> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| </transition> |  | ||||||
| </template> |  | ||||||
| 
 |  | ||||||
| <script lang="ts"> |  | ||||||
| import { defineComponent, PropType, ref, watch } from 'vue'; |  | ||||||
| import './debobigego.scss'; |  | ||||||
| import MkButton from '@/components/ui/button.vue'; |  | ||||||
| 
 |  | ||||||
| export default defineComponent({ |  | ||||||
| 	components: { |  | ||||||
| 		MkButton |  | ||||||
| 	}, |  | ||||||
| 
 |  | ||||||
| 	props: { |  | ||||||
| 		p: { |  | ||||||
| 			type: Function as PropType<() => Promise<any>>, |  | ||||||
| 			required: true, |  | ||||||
| 		} |  | ||||||
| 	}, |  | ||||||
| 
 |  | ||||||
| 	setup(props, context) { |  | ||||||
| 		const pending = ref(true); |  | ||||||
| 		const resolved = ref(false); |  | ||||||
| 		const rejected = ref(false); |  | ||||||
| 		const result = ref(null); |  | ||||||
| 
 |  | ||||||
| 		const process = () => { |  | ||||||
| 			if (props.p == null) { |  | ||||||
| 				return; |  | ||||||
| 			} |  | ||||||
| 			const promise = props.p(); |  | ||||||
| 			pending.value = true; |  | ||||||
| 			resolved.value = false; |  | ||||||
| 			rejected.value = false; |  | ||||||
| 			promise.then((_result) => { |  | ||||||
| 				pending.value = false; |  | ||||||
| 				resolved.value = true; |  | ||||||
| 				result.value = _result; |  | ||||||
| 			}); |  | ||||||
| 			promise.catch(() => { |  | ||||||
| 				pending.value = false; |  | ||||||
| 				rejected.value = true; |  | ||||||
| 			}); |  | ||||||
| 		}; |  | ||||||
| 
 |  | ||||||
| 		watch(() => props.p, () => { |  | ||||||
| 			process(); |  | ||||||
| 		}, { |  | ||||||
| 			immediate: true |  | ||||||
| 		}); |  | ||||||
| 
 |  | ||||||
| 		const retry = () => { |  | ||||||
| 			process(); |  | ||||||
| 		}; |  | ||||||
| 
 |  | ||||||
| 		return { |  | ||||||
| 			pending, |  | ||||||
| 			resolved, |  | ||||||
| 			rejected, |  | ||||||
| 			result, |  | ||||||
| 			retry, |  | ||||||
| 		}; |  | ||||||
| 	} |  | ||||||
| }); |  | ||||||
| </script> |  | ||||||
| 
 |  | ||||||
| <style lang="scss" scoped> |  | ||||||
| .fade-enter-active, |  | ||||||
| .fade-leave-active { |  | ||||||
| 	transition: opacity 0.125s ease; |  | ||||||
| } |  | ||||||
| .fade-enter-from, |  | ||||||
| .fade-leave-to { |  | ||||||
| 	opacity: 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .eiurkvay { |  | ||||||
| 	padding: 16px; |  | ||||||
| 	text-align: center; |  | ||||||
| 
 |  | ||||||
| 	> .retry { |  | ||||||
| 		margin-top: 16px; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| </style> |  | ||||||
|  | @ -1,132 +0,0 @@ | ||||||
| <template> |  | ||||||
| <div class="ijnpvmgr _debobigegoItem"> |  | ||||||
| 	<div class="main _debobigegoPanel _debobigegoClickable" |  | ||||||
| 		:class="{ disabled, checked }" |  | ||||||
| 		:aria-checked="checked" |  | ||||||
| 		:aria-disabled="disabled" |  | ||||||
| 		@click.prevent="toggle" |  | ||||||
| 	> |  | ||||||
| 		<input |  | ||||||
| 			ref="input" |  | ||||||
| 			type="checkbox" |  | ||||||
| 			:disabled="disabled" |  | ||||||
| 			@keydown.enter="toggle" |  | ||||||
| 		> |  | ||||||
| 		<span v-tooltip="checked ? $ts.itsOn : $ts.itsOff" class="button"> |  | ||||||
| 			<span class="handle"></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; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		> input { |  | ||||||
| 			position: absolute; |  | ||||||
| 			width: 0; |  | ||||||
| 			height: 0; |  | ||||||
| 			opacity: 0; |  | ||||||
| 			margin: 0; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		> .button { |  | ||||||
| 			position: relative; |  | ||||||
| 			display: inline-block; |  | ||||||
| 			flex-shrink: 0; |  | ||||||
| 			margin: 0; |  | ||||||
| 			width: 34px; |  | ||||||
| 			height: 22px; |  | ||||||
| 			background: var(--switchBg); |  | ||||||
| 			outline: none; |  | ||||||
| 			border-radius: 999px; |  | ||||||
| 			transition: all 0.3s; |  | ||||||
| 			cursor: pointer; |  | ||||||
| 
 |  | ||||||
| 			> .handle { |  | ||||||
| 				position: absolute; |  | ||||||
| 				top: 0; |  | ||||||
| 				left: 3px; |  | ||||||
| 				bottom: 0; |  | ||||||
| 				margin: auto 0; |  | ||||||
| 				border-radius: 100%; |  | ||||||
| 				transition: background-color 0.3s, transform 0.3s; |  | ||||||
| 				width: 16px; |  | ||||||
| 				height: 16px; |  | ||||||
| 				background-color: #fff; |  | ||||||
| 				pointer-events: none; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		> .label { |  | ||||||
| 			margin-left: 12px; |  | ||||||
| 			display: block; |  | ||||||
| 			transition: inherit; |  | ||||||
| 			color: var(--fg); |  | ||||||
| 
 |  | ||||||
| 			> span { |  | ||||||
| 				display: block; |  | ||||||
| 				line-height: 20px; |  | ||||||
| 				transition: inherit; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		&.disabled { |  | ||||||
| 			opacity: 0.6; |  | ||||||
| 			cursor: not-allowed; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		&.checked { |  | ||||||
| 			> .button { |  | ||||||
| 				background-color: var(--accent); |  | ||||||
| 
 |  | ||||||
| 				> .handle { |  | ||||||
| 					transform: translateX(12px); |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| </style> |  | ||||||
|  | @ -1,161 +0,0 @@ | ||||||
| <template> |  | ||||||
| <FormGroup class="_debobigegoItem"> |  | ||||||
| 	<template #label><slot></slot></template> |  | ||||||
| 	<div class="rivhosbp _debobigegoItem" :class="{ tall, pre }"> |  | ||||||
| 		<div class="input _debobigegoPanel"> |  | ||||||
| 			<textarea ref="input" v-model="v" |  | ||||||
| 				:class="{ code, _monospace: code }" |  | ||||||
| 				: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" primary @click="updated"><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,36 +0,0 @@ | ||||||
| <template> |  | ||||||
| <div v-size="{ max: [500] }" class="wthhikgt _debobigegoItem"> |  | ||||||
| 	<slot></slot> |  | ||||||
| </div> |  | ||||||
| </template> |  | ||||||
| 
 |  | ||||||
| <script lang="ts"> |  | ||||||
| import { defineComponent } from 'vue'; |  | ||||||
| 
 |  | ||||||
| export default defineComponent({ |  | ||||||
| }); |  | ||||||
| </script> |  | ||||||
| 
 |  | ||||||
| <style lang="scss" scoped> |  | ||||||
| .wthhikgt { |  | ||||||
| 	position: relative; |  | ||||||
| 	display: flex; |  | ||||||
| 
 |  | ||||||
| 	> ::v-deep(*) { |  | ||||||
| 		flex: 1; |  | ||||||
| 		margin: 0; |  | ||||||
| 
 |  | ||||||
| 		&:not(:last-child) { |  | ||||||
| 			margin-right: 16px; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	&.max-width_500px { |  | ||||||
| 		display: block; |  | ||||||
| 
 |  | ||||||
| 		> ::v-deep(*) { |  | ||||||
| 			margin: inherit; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| </style> |  | ||||||
|  | @ -20,8 +20,14 @@ | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <script lang="ts" setup> | <script lang="ts" setup> | ||||||
| let opened = $ref(false); | const props = withDefaults(defineProps<{ | ||||||
| let openedAtLeastOnce = $ref(false); | 	defaultOpen: boolean; | ||||||
|  | }>(), { | ||||||
|  |   defaultOpen: false, | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | let opened = $ref(props.defaultOpen); | ||||||
|  | let openedAtLeastOnce = $ref(props.defaultOpen); | ||||||
| 
 | 
 | ||||||
| const toggle = () => { | const toggle = () => { | ||||||
| 	opened = !opened; | 	opened = !opened; | ||||||
|  |  | ||||||
							
								
								
									
										29
									
								
								packages/client/src/components/object-view.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								packages/client/src/components/object-view.vue
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,29 @@ | ||||||
|  | <template> | ||||||
|  | <div class="zhyxdalp"> | ||||||
|  | 
 | ||||||
|  | </div> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <script lang="ts"> | ||||||
|  | import { computed, defineComponent } from 'vue'; | ||||||
|  | import number from '@/filters/number'; | ||||||
|  | 
 | ||||||
|  | export default defineComponent({ | ||||||
|  | 	props: { | ||||||
|  | 		value: { | ||||||
|  | 			type: Object, | ||||||
|  | 			required: true, | ||||||
|  | 		}, | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	setup(props) { | ||||||
|  | 
 | ||||||
|  | 	} | ||||||
|  | }); | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <style lang="scss" scoped> | ||||||
|  | .zhyxdalp { | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | </style> | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| <template> | <template> | ||||||
| <MkSpacer :content-max="700" :margin-min="16" :margin-max="32"> | <MkSpacer :content-max="800" :margin-min="16" :margin-max="32"> | ||||||
| 	<FormSuspense v-slot="{ result: database }" :p="databasePromiseFactory"> | 	<FormSuspense v-slot="{ result: database }" :p="databasePromiseFactory"> | ||||||
| 		<MkKeyValue v-for="table in database" :key="table[0]" oneline style="margin: 1em 0;"> | 		<MkKeyValue v-for="table in database" :key="table[0]" oneline style="margin: 1em 0;"> | ||||||
| 			<template #key>{{ table[0] }}</template> | 			<template #key>{{ table[0] }}</template> | ||||||
|  |  | ||||||
|  | @ -1,12 +1,12 @@ | ||||||
| <template> | <template> | ||||||
| <FormBase> | <div> | ||||||
| 	<FormSuspense :p="init"> | 	<FormSuspense :p="init"> | ||||||
| 		<FormInput v-model="title"> | 		<FormInput v-model="title"> | ||||||
| 			<span>{{ $ts.title }}</span> | 			<template #label>{{ $ts.title }}</template> | ||||||
| 		</FormInput> | 		</FormInput> | ||||||
| 
 | 
 | ||||||
| 		<FormTextarea v-model="description" :max="500"> | 		<FormTextarea v-model="description" :max="500"> | ||||||
| 			<span>{{ $ts.description }}</span> | 			<template #label>{{ $ts.description }}</template> | ||||||
| 		</FormTextarea> | 		</FormTextarea> | ||||||
| 
 | 
 | ||||||
| 		<FormGroup> | 		<FormGroup> | ||||||
|  | @ -24,19 +24,17 @@ | ||||||
| 
 | 
 | ||||||
| 		<FormButton v-if="postId" danger @click="del"><i class="fas fa-trash-alt"></i> {{ $ts.delete }}</FormButton> | 		<FormButton v-if="postId" danger @click="del"><i class="fas fa-trash-alt"></i> {{ $ts.delete }}</FormButton> | ||||||
| 	</FormSuspense> | 	</FormSuspense> | ||||||
| </FormBase> | </div> | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <script lang="ts"> | <script lang="ts"> | ||||||
| import { computed, defineComponent } from 'vue'; | import { computed, defineComponent } from 'vue'; | ||||||
| import FormButton from '@/components/debobigego/button.vue'; | import FormButton from '@/components/ui/button.vue'; | ||||||
| import FormInput from '@/components/debobigego/input.vue'; | import FormInput from '@/components/form/input.vue'; | ||||||
| import FormTextarea from '@/components/debobigego/textarea.vue'; | import FormTextarea from '@/components/form/textarea.vue'; | ||||||
| import FormSwitch from '@/components/debobigego/switch.vue'; | import FormSwitch from '@/components/form/switch.vue'; | ||||||
| import FormTuple from '@/components/debobigego/tuple.vue'; | import FormGroup from '@/components/form/group.vue'; | ||||||
| import FormBase from '@/components/debobigego/base.vue'; | import FormSuspense from '@/components/form/suspense.vue'; | ||||||
| import FormGroup from '@/components/debobigego/group.vue'; |  | ||||||
| import FormSuspense from '@/components/debobigego/suspense.vue'; |  | ||||||
| import { selectFiles } from '@/scripts/select-file'; | import { selectFiles } from '@/scripts/select-file'; | ||||||
| import * as os from '@/os'; | import * as os from '@/os'; | ||||||
| import * as symbols from '@/symbols'; | import * as symbols from '@/symbols'; | ||||||
|  | @ -47,7 +45,6 @@ export default defineComponent({ | ||||||
| 		FormInput, | 		FormInput, | ||||||
| 		FormTextarea, | 		FormTextarea, | ||||||
| 		FormSwitch, | 		FormSwitch, | ||||||
| 		FormBase, |  | ||||||
| 		FormGroup, | 		FormGroup, | ||||||
| 		FormSuspense, | 		FormSuspense, | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
|  | @ -89,9 +89,8 @@ | ||||||
| 			</div> | 			</div> | ||||||
| 		</FormSection> | 		</FormSection> | ||||||
| 
 | 
 | ||||||
| 		<FormObjectView tall :value="instance"> | 		<MkObjectView tall :value="instance"> | ||||||
| 			<span>Raw</span> | 		</MkObjectView> | ||||||
| 		</FormObjectView> |  | ||||||
| 
 | 
 | ||||||
| 		<FormSection> | 		<FormSection> | ||||||
| 			<template #label>Well-known resources</template> | 			<template #label>Well-known resources</template> | ||||||
|  | @ -108,7 +107,7 @@ | ||||||
| <script lang="ts"> | <script lang="ts"> | ||||||
| import { defineAsyncComponent, defineComponent } from 'vue'; | import { defineAsyncComponent, defineComponent } from 'vue'; | ||||||
| import MkChart from '@/components/chart.vue'; | import MkChart from '@/components/chart.vue'; | ||||||
| import FormObjectView from '@/components/debobigego/object-view.vue'; | import MkObjectView from '@/components/object-view.vue'; | ||||||
| import FormTextarea from '@/components/form/textarea.vue'; | import FormTextarea from '@/components/form/textarea.vue'; | ||||||
| import FormLink from '@/components/form/link.vue'; | import FormLink from '@/components/form/link.vue'; | ||||||
| import MkLink from '@/components/link.vue'; | import MkLink from '@/components/link.vue'; | ||||||
|  | @ -125,7 +124,7 @@ import * as symbols from '@/symbols'; | ||||||
| export default defineComponent({ | export default defineComponent({ | ||||||
| 	components: { | 	components: { | ||||||
| 		FormTextarea, | 		FormTextarea, | ||||||
| 		FormObjectView, | 		MkObjectView, | ||||||
| 		FormButton, | 		FormButton, | ||||||
| 		FormLink, | 		FormLink, | ||||||
| 		FormSection, | 		FormSection, | ||||||
|  |  | ||||||
|  | @ -1,61 +1,67 @@ | ||||||
| <template> | <template> | ||||||
| <FormBase class="cwepdizn"> | <MkSpacer :content-max="800" :margin-min="16" :margin-max="32"> | ||||||
| 	<div class="_debobigegoItem colorPicker"> | 	<div class="cwepdizn _formRoot"> | ||||||
| 		<div class="_debobigegoLabel">{{ $ts.backgroundColor }}</div> | 		<FormFolder :default-open="true" class="_formBlock"> | ||||||
| 		<div class="_debobigegoPanel colors"> | 			<template #label>{{ $ts.backgroundColor }}</template> | ||||||
| 			<div class="row"> | 			<div class="cwepdizn-colors"> | ||||||
| 				<button v-for="color in bgColors.filter(x => x.kind === 'light')" :key="color.color" class="color _button" :class="{ active: theme.props.bg === color.color }" @click="setBgColor(color)"> | 				<div class="row"> | ||||||
| 					<div class="preview" :style="{ background: color.forPreview }"></div> | 					<button v-for="color in bgColors.filter(x => x.kind === 'light')" :key="color.color" class="color _button" :class="{ active: theme.props.bg === color.color }" @click="setBgColor(color)"> | ||||||
| 				</button> | 						<div class="preview" :style="{ background: color.forPreview }"></div> | ||||||
|  | 					</button> | ||||||
|  | 				</div> | ||||||
|  | 				<div class="row"> | ||||||
|  | 					<button v-for="color in bgColors.filter(x => x.kind === 'dark')" :key="color.color" class="color _button" :class="{ active: theme.props.bg === color.color }" @click="setBgColor(color)"> | ||||||
|  | 						<div class="preview" :style="{ background: color.forPreview }"></div> | ||||||
|  | 					</button> | ||||||
|  | 				</div> | ||||||
| 			</div> | 			</div> | ||||||
| 			<div class="row"> | 		</FormFolder> | ||||||
| 				<button v-for="color in bgColors.filter(x => x.kind === 'dark')" :key="color.color" class="color _button" :class="{ active: theme.props.bg === color.color }" @click="setBgColor(color)"> |  | ||||||
| 					<div class="preview" :style="{ background: color.forPreview }"></div> |  | ||||||
| 				</button> |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| 	<div class="_debobigegoItem colorPicker"> |  | ||||||
| 		<div class="_debobigegoLabel">{{ $ts.accentColor }}</div> |  | ||||||
| 		<div class="_debobigegoPanel colors"> |  | ||||||
| 			<div class="row"> |  | ||||||
| 				<button v-for="color in accentColors" :key="color" class="color rounded _button" :class="{ active: theme.props.accent === color }" @click="setAccentColor(color)"> |  | ||||||
| 					<div class="preview" :style="{ background: color }"></div> |  | ||||||
| 				</button> |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| 	<div class="_debobigegoItem colorPicker"> |  | ||||||
| 		<div class="_debobigegoLabel">{{ $ts.textColor }}</div> |  | ||||||
| 		<div class="_debobigegoPanel colors"> |  | ||||||
| 			<div class="row"> |  | ||||||
| 				<button v-for="color in fgColors" :key="color" class="color char _button" :class="{ active: (theme.props.fg === color.forLight) || (theme.props.fg === color.forDark) }" @click="setFgColor(color)"> |  | ||||||
| 					<div class="preview" :style="{ color: color.forPreview ? color.forPreview : theme.base === 'light' ? '#5f5f5f' : '#dadada' }">A</div> |  | ||||||
| 				</button> |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| 
 | 
 | ||||||
| 	<FormGroup v-if="codeEnabled"> | 		<FormFolder :default-open="true" class="_formBlock"> | ||||||
| 		<FormTextarea v-model="themeCode" tall> | 			<template #label>{{ $ts.accentColor }}</template> | ||||||
| 			<span>{{ $ts._theme.code }}</span> | 			<div class="cwepdizn-colors"> | ||||||
| 		</FormTextarea> | 				<div class="row"> | ||||||
| 		<FormButton primary @click="applyThemeCode">{{ $ts.apply }}</FormButton> | 					<button v-for="color in accentColors" :key="color" class="color rounded _button" :class="{ active: theme.props.accent === color }" @click="setAccentColor(color)"> | ||||||
| 	</FormGroup> | 						<div class="preview" :style="{ background: color }"></div> | ||||||
| 	<FormButton v-else @click="codeEnabled = true"><i class="fas fa-code"></i> {{ $ts.editCode }}</FormButton> | 					</button> | ||||||
|  | 				</div> | ||||||
|  | 			</div> | ||||||
|  | 		</FormFolder> | ||||||
| 
 | 
 | ||||||
| 	<FormGroup v-if="descriptionEnabled"> | 		<FormFolder :default-open="true" class="_formBlock"> | ||||||
| 		<FormTextarea v-model="description"> | 			<template #label>{{ $ts.textColor }}</template> | ||||||
| 			<span>{{ $ts._theme.description }}</span> | 			<div class="cwepdizn-colors"> | ||||||
| 		</FormTextarea> | 				<div class="row"> | ||||||
| 	</FormGroup> | 					<button v-for="color in fgColors" :key="color" class="color char _button" :class="{ active: (theme.props.fg === color.forLight) || (theme.props.fg === color.forDark) }" @click="setFgColor(color)"> | ||||||
| 	<FormButton v-else @click="descriptionEnabled = true">{{ $ts.addDescription }}</FormButton> | 						<div class="preview" :style="{ color: color.forPreview ? color.forPreview : theme.base === 'light' ? '#5f5f5f' : '#dadada' }">A</div> | ||||||
|  | 					</button> | ||||||
|  | 				</div> | ||||||
|  | 			</div> | ||||||
|  | 		</FormFolder> | ||||||
| 
 | 
 | ||||||
| 	<FormGroup> | 		<FormFolder :default-open="false" class="_formBlock"> | ||||||
| 		<FormButton @click="showPreview"><i class="fas fa-eye"></i> {{ $ts.preview }}</FormButton> | 			<template #icon><i class="fas fa-code"></i></template> | ||||||
| 		<FormButton primary @click="saveAs"><i class="fas fa-save"></i> {{ $ts.saveAs }}</FormButton> | 			<template #label>{{ $ts.editCode }}</template> | ||||||
| 	</FormGroup> | 
 | ||||||
| </FormBase> | 			<div class="_formRoot"> | ||||||
|  | 				<FormTextarea v-model="themeCode" tall class="_formBlock"> | ||||||
|  | 					<template #label>{{ $ts._theme.code }}</template> | ||||||
|  | 				</FormTextarea> | ||||||
|  | 				<FormButton primary class="_formBlock" @click="applyThemeCode">{{ $ts.apply }}</FormButton> | ||||||
|  | 			</div> | ||||||
|  | 		</FormFolder> | ||||||
|  | 
 | ||||||
|  | 		<FormFolder :default-open="false" class="_formBlock"> | ||||||
|  | 			<template #label>{{ $ts.addDescription }}</template> | ||||||
|  | 
 | ||||||
|  | 			<div class="_formRoot"> | ||||||
|  | 				<FormTextarea v-model="description"> | ||||||
|  | 					<template #label>{{ $ts._theme.description }}</template> | ||||||
|  | 				</FormTextarea> | ||||||
|  | 			</div> | ||||||
|  | 		</FormFolder> | ||||||
|  | 	</div> | ||||||
|  | </MkSpacer> | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <script lang="ts"> | <script lang="ts"> | ||||||
|  | @ -65,12 +71,11 @@ import * as tinycolor from 'tinycolor2'; | ||||||
| import { v4 as uuid} from 'uuid'; | import { v4 as uuid} from 'uuid'; | ||||||
| import * as JSON5 from 'json5'; | import * as JSON5 from 'json5'; | ||||||
| 
 | 
 | ||||||
| import FormBase from '@/components/debobigego/base.vue'; | import FormButton from '@/components/ui/button.vue'; | ||||||
| import FormButton from '@/components/debobigego/button.vue'; | import FormTextarea from '@/components/form/textarea.vue'; | ||||||
| import FormTextarea from '@/components/debobigego/textarea.vue'; | import FormFolder from '@/components/form/folder.vue'; | ||||||
| import FormGroup from '@/components/debobigego/group.vue'; |  | ||||||
| 
 | 
 | ||||||
| import { Theme, applyTheme, validateTheme, darkTheme, lightTheme } from '@/scripts/theme'; | import { Theme, applyTheme, darkTheme, lightTheme } from '@/scripts/theme'; | ||||||
| import { host } from '@/config'; | import { host } from '@/config'; | ||||||
| import * as os from '@/os'; | import * as os from '@/os'; | ||||||
| import { ColdDeviceStorage } from '@/store'; | import { ColdDeviceStorage } from '@/store'; | ||||||
|  | @ -79,10 +84,9 @@ import * as symbols from '@/symbols'; | ||||||
| 
 | 
 | ||||||
| export default defineComponent({ | export default defineComponent({ | ||||||
| 	components: { | 	components: { | ||||||
| 		FormBase, |  | ||||||
| 		FormButton, | 		FormButton, | ||||||
| 		FormTextarea, | 		FormTextarea, | ||||||
| 		FormGroup, | 		FormFolder, | ||||||
| 	}, | 	}, | ||||||
| 
 | 
 | ||||||
| 	async beforeRouteLeave(to, from) { | 	async beforeRouteLeave(to, from) { | ||||||
|  | @ -96,13 +100,23 @@ export default defineComponent({ | ||||||
| 			[symbols.PAGE_INFO]: { | 			[symbols.PAGE_INFO]: { | ||||||
| 				title: this.$ts.themeEditor, | 				title: this.$ts.themeEditor, | ||||||
| 				icon: 'fas fa-palette', | 				icon: 'fas fa-palette', | ||||||
|  | 				bg: 'var(--bg)', | ||||||
|  | 				actions: [{ | ||||||
|  | 					asFullButton: true, | ||||||
|  | 					icon: 'fas fa-eye', | ||||||
|  | 					text: this.$ts.preview, | ||||||
|  | 					handler: this.showPreview, | ||||||
|  | 				}, { | ||||||
|  | 					asFullButton: true, | ||||||
|  | 					icon: 'fas fa-check', | ||||||
|  | 					text: this.$ts.saveAs, | ||||||
|  | 					handler: this.saveAs, | ||||||
|  | 				}], | ||||||
| 			}, | 			}, | ||||||
| 			theme: { | 			theme: { | ||||||
| 				base: 'light', | 				base: 'light', | ||||||
| 				props: lightTheme.props | 				props: lightTheme.props | ||||||
| 			} as Theme, | 			} as Theme, | ||||||
| 			codeEnabled: false, |  | ||||||
| 			descriptionEnabled: false, |  | ||||||
| 			description: null, | 			description: null, | ||||||
| 			themeCode: null, | 			themeCode: null, | ||||||
| 			bgColors: [ | 			bgColors: [ | ||||||
|  | @ -244,57 +258,51 @@ export default defineComponent({ | ||||||
| 
 | 
 | ||||||
| <style lang="scss" scoped> | <style lang="scss" scoped> | ||||||
| .cwepdizn { | .cwepdizn { | ||||||
| 	max-width: 800px; | 	::v-deep(.cwepdizn-colors) { | ||||||
| 	margin: 0 auto; | 		text-align: center; | ||||||
| 
 | 
 | ||||||
| 	> .colorPicker { | 		> .row { | ||||||
| 		> .colors { | 			> .color { | ||||||
| 			padding: 32px; | 				display: inline-block; | ||||||
| 			text-align: center; | 				position: relative; | ||||||
|  | 				width: 64px; | ||||||
|  | 				height: 64px; | ||||||
|  | 				border-radius: 8px; | ||||||
| 
 | 
 | ||||||
| 			> .row { | 				> .preview { | ||||||
| 				> .color { | 					position: absolute; | ||||||
| 					display: inline-block; | 					top: 0; | ||||||
| 					position: relative; | 					left: 0; | ||||||
| 					width: 64px; | 					right: 0; | ||||||
| 					height: 64px; | 					bottom: 0; | ||||||
| 					border-radius: 8px; | 					margin: auto; | ||||||
|  | 					width: 42px; | ||||||
|  | 					height: 42px; | ||||||
|  | 					border-radius: 4px; | ||||||
|  | 					box-shadow: 0 2px 4px rgb(0 0 0 / 30%); | ||||||
|  | 					transition: transform 0.15s ease; | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				&:hover { | ||||||
|  | 					> .preview { | ||||||
|  | 						transform: scale(1.1); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				&.active { | ||||||
|  | 					box-shadow: 0 0 0 2px var(--divider) inset; | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				&.rounded { | ||||||
|  | 					border-radius: 999px; | ||||||
| 
 | 
 | ||||||
| 					> .preview { | 					> .preview { | ||||||
| 						position: absolute; |  | ||||||
| 						top: 0; |  | ||||||
| 						left: 0; |  | ||||||
| 						right: 0; |  | ||||||
| 						bottom: 0; |  | ||||||
| 						margin: auto; |  | ||||||
| 						width: 42px; |  | ||||||
| 						height: 42px; |  | ||||||
| 						border-radius: 4px; |  | ||||||
| 						box-shadow: 0 2px 4px rgb(0 0 0 / 30%); |  | ||||||
| 						transition: transform 0.15s ease; |  | ||||||
| 					} |  | ||||||
| 
 |  | ||||||
| 					&:hover { |  | ||||||
| 						> .preview { |  | ||||||
| 							transform: scale(1.1); |  | ||||||
| 						} |  | ||||||
| 					} |  | ||||||
| 
 |  | ||||||
| 					&.active { |  | ||||||
| 						box-shadow: 0 0 0 2px var(--divider) inset; |  | ||||||
| 					} |  | ||||||
| 
 |  | ||||||
| 					&.rounded { |  | ||||||
| 						border-radius: 999px; | 						border-radius: 999px; | ||||||
| 
 |  | ||||||
| 						> .preview { |  | ||||||
| 							border-radius: 999px; |  | ||||||
| 						} |  | ||||||
| 					} | 					} | ||||||
|  | 				} | ||||||
| 
 | 
 | ||||||
| 					&.char { | 				&.char { | ||||||
| 						line-height: 42px; | 					line-height: 42px; | ||||||
| 					} |  | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -53,9 +53,8 @@ | ||||||
| 				<FormButton v-if="user.host != null" class="_formBlock" @click="updateRemoteUser"><i class="fas fa-sync"></i> {{ $ts.updateRemoteUser }}</FormButton> | 				<FormButton v-if="user.host != null" class="_formBlock" @click="updateRemoteUser"><i class="fas fa-sync"></i> {{ $ts.updateRemoteUser }}</FormButton> | ||||||
| 			</FormSection> | 			</FormSection> | ||||||
| 
 | 
 | ||||||
| 			<FormObjectView tall :value="user"> | 			<MkObjectView tall :value="user"> | ||||||
| 				<span>Raw</span> | 			</MkObjectView> | ||||||
| 			</FormObjectView> |  | ||||||
| 		</div> | 		</div> | ||||||
| 	</FormSuspense> | 	</FormSuspense> | ||||||
| </MkSpacer> | </MkSpacer> | ||||||
|  | @ -63,7 +62,7 @@ | ||||||
| 
 | 
 | ||||||
| <script lang="ts"> | <script lang="ts"> | ||||||
| import { computed, defineAsyncComponent, defineComponent } from 'vue'; | import { computed, defineAsyncComponent, defineComponent } from 'vue'; | ||||||
| import FormObjectView from '@/components/debobigego/object-view.vue'; | import MkObjectView from '@/components/object-view.vue'; | ||||||
| import FormTextarea from '@/components/form/textarea.vue'; | import FormTextarea from '@/components/form/textarea.vue'; | ||||||
| import FormSwitch from '@/components/form/switch.vue'; | import FormSwitch from '@/components/form/switch.vue'; | ||||||
| import FormLink from '@/components/form/link.vue'; | import FormLink from '@/components/form/link.vue'; | ||||||
|  | @ -83,7 +82,7 @@ export default defineComponent({ | ||||||
| 		FormSection, | 		FormSection, | ||||||
| 		FormTextarea, | 		FormTextarea, | ||||||
| 		FormSwitch, | 		FormSwitch, | ||||||
| 		FormObjectView, | 		MkObjectView, | ||||||
| 		FormButton, | 		FormButton, | ||||||
| 		FormLink, | 		FormLink, | ||||||
| 		MkKeyValue, | 		MkKeyValue, | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue