From 17065418cf9fd67b8172f0085bc0c2ae56d547dc Mon Sep 17 00:00:00 2001
From: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Sat, 16 Dec 2023 13:18:12 +0900
Subject: (enhance) コード入力をMkCodeEditorに変更 (#12682)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 packages/frontend/src/components/MkCodeEditor.vue | 88 +++++++++++++++++------
 1 file changed, 67 insertions(+), 21 deletions(-)

(limited to 'packages/frontend/src/components/MkCodeEditor.vue')

diff --git a/packages/frontend/src/components/MkCodeEditor.vue b/packages/frontend/src/components/MkCodeEditor.vue
index 60f16f285f..6341c454ae 100644
--- a/packages/frontend/src/components/MkCodeEditor.vue
+++ b/packages/frontend/src/components/MkCodeEditor.vue
@@ -4,30 +4,38 @@ SPDX-License-Identifier: AGPL-3.0-only
 -->
 
 <template>
-<div :class="[$style.codeEditorRoot, { [$style.focused]: focused }]">
-	<div :class="$style.codeEditorScroller">
-		<textarea
-			ref="inputEl"
-			v-model="vModel"
-			:class="[$style.textarea]"
-			:disabled="disabled"
-			:required="required"
-			:readonly="readonly"
-			autocomplete="off"
-			wrap="off"
-			spellcheck="false"
-			@focus="focused = true"
-			@blur="focused = false"
-			@keydown="onKeydown($event)"
-			@input="onInput"
-		></textarea>
-		<XCode :class="$style.codeEditorHighlighter" :codeEditor="true" :code="v" :lang="lang"/>
+<div>
+	<div :class="$style.label" @click="focus"><slot name="label"></slot></div>
+	<div :class="[$style.codeEditorRoot, { [$style.focused]: focused }]">
+		<div :class="$style.codeEditorScroller">
+			<textarea
+				ref="inputEl"
+				v-model="vModel"
+				:class="[$style.textarea]"
+				:disabled="disabled"
+				:required="required"
+				:readonly="readonly"
+				autocomplete="off"
+				wrap="off"
+				spellcheck="false"
+				@focus="focused = true"
+				@blur="focused = false"
+				@keydown="onKeydown($event)"
+				@input="onInput"
+			></textarea>
+			<XCode :class="$style.codeEditorHighlighter" :codeEditor="true" :code="v" :lang="lang"/>
+		</div>
 	</div>
+	<div :class="$style.caption"><slot name="caption"></slot></div>
+	<MkButton v-if="manualSave && changed" primary :class="$style.save" @click="updated"><i class="ti ti-device-floppy"></i> {{ i18n.ts.save }}</MkButton>
 </div>
 </template>
 
 <script lang="ts" setup>
 import { ref, watch, toRefs, shallowRef, nextTick } from 'vue';
+import { debounce } from 'throttle-debounce';
+import MkButton from '@/components/MkButton.vue';
+import { i18n } from '@/i18n.js';
 import XCode from '@/components/MkCode.core.vue';
 
 const props = withDefaults(defineProps<{
@@ -36,6 +44,8 @@ const props = withDefaults(defineProps<{
 	required?: boolean;
 	readonly?: boolean;
 	disabled?: boolean;
+	debounce?: boolean;
+	manualSave?: boolean;
 }>(), {
 	lang: 'js',
 });
@@ -54,6 +64,8 @@ const focused = ref(false);
 const changed = ref(false);
 const inputEl = shallowRef<HTMLTextAreaElement>();
 
+const focus = () => inputEl.value?.focus();
+
 const onInput = (ev) => {
 	v.value = ev.target?.value ?? v.value;
 	changed.value = true;
@@ -100,16 +112,48 @@ const updated = () => {
 	emit('update:modelValue', v.value);
 };
 
+const debouncedUpdated = debounce(1000, updated);
+
 watch(modelValue, newValue => {
 	v.value = newValue ?? '';
 });
 
-watch(v, () => {
-	updated();
+watch(v, newValue => {
+	if (!props.manualSave) {
+		if (props.debounce) {
+			debouncedUpdated();
+		} else {
+			updated();
+		}
+	}
 });
 </script>
 
 <style lang="scss" module>
+.label {
+	font-size: 0.85em;
+	padding: 0 0 8px 0;
+	user-select: none;
+
+	&:empty {
+		display: none;
+	}
+}
+
+.caption {
+	font-size: 0.85em;
+	padding: 8px 0 0 0;
+	color: var(--fgTransparentWeak);
+
+	&:empty {
+		display: none;
+	}
+}
+
+.save {
+	margin: 8px 0 0 0;
+}
+
 .codeEditorRoot {
 	min-width: 100%;
 	max-width: 100%;
@@ -117,6 +161,7 @@ watch(v, () => {
 	overflow-y: hidden;
 	box-sizing: border-box;
 	margin: 0;
+	border-radius: 6px;
 	padding: 0;
 	color: var(--fg);
 	border: solid 1px var(--panel);
@@ -157,9 +202,10 @@ watch(v, () => {
 	caret-color: rgb(225, 228, 232);
 	background-color: transparent;
 	border: 0;
+	border-radius: 6px;
 	outline: 0;
 	min-width: calc(100% - 24px);
-	height: calc(100% - 24px);
+	height: 100%;
 	padding: 12px;
 	line-height: 1.5em;
 	font-size: 1em;
-- 
cgit v1.2.3-freya

