Add nonfunctional text box to create new notes
This commit is contained in:
parent
6c785ce566
commit
8453f6ee53
4 changed files with 96 additions and 7 deletions
|
|
@ -1,21 +1,25 @@
|
|||
<script setup lang="ts">
|
||||
import { useNotesStore } from "@/stores/notes";
|
||||
import { useUiStore } from "@/stores/ui";
|
||||
import { RiArrowDownSLine, RiArrowRightSLine } from "@remixicon/vue";
|
||||
import {
|
||||
RiArrowDownSLine,
|
||||
RiArrowRightSLine,
|
||||
RiStickyNoteAddLine,
|
||||
} from "@remixicon/vue";
|
||||
import { computed, ref, watchEffect } from "vue";
|
||||
import CNoteButton from "./CNoteButton.vue";
|
||||
import CNoteCreator from "./CNoteCreator.vue";
|
||||
|
||||
const notes = useNotesStore();
|
||||
const ui = useUiStore();
|
||||
|
||||
const props = defineProps<{
|
||||
noteId?: string;
|
||||
noteId: string;
|
||||
path: number[]; // From root to here
|
||||
focusPath?: number[]; // From here to focus
|
||||
}>();
|
||||
|
||||
const note = computed(() =>
|
||||
props.noteId ? notes.notes.get(props.noteId) : undefined,
|
||||
);
|
||||
const note = computed(() => notes.notes.get(props.noteId));
|
||||
|
||||
// Our children and their locally unique keys.
|
||||
const children = computed(() => {
|
||||
|
|
@ -35,6 +39,8 @@ const open = ref(false);
|
|||
|
||||
const focused = computed(() => props.focusPath?.length === 0);
|
||||
|
||||
const creating = ref(false);
|
||||
|
||||
// We want to set open to true when we're on the focus path, but then it should
|
||||
// stay true. Hence a computed() combining open and forceOpen would not suffice.
|
||||
watchEffect(() => {
|
||||
|
|
@ -42,6 +48,16 @@ watchEffect(() => {
|
|||
if (props.focusPath && props.focusPath.length > 0) open.value = true;
|
||||
});
|
||||
|
||||
// Abort creating a child node whenever we stop being focused.
|
||||
watchEffect(() => {
|
||||
if (!focused.value) creating.value = false;
|
||||
});
|
||||
|
||||
// Ensure the creator component is visible.
|
||||
watchEffect(() => {
|
||||
if (creating.value) open.value = true;
|
||||
});
|
||||
|
||||
function focusPathFor(index: number): number[] | undefined {
|
||||
if (!props.focusPath) return undefined;
|
||||
if (index !== props.focusPath[0]) return undefined;
|
||||
|
|
@ -79,7 +95,7 @@ function onClick() {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col">
|
||||
<div class="relative flex flex-col">
|
||||
<div
|
||||
class="flex flex-row gap-1 pl-1"
|
||||
:class="focused ? ['bg-neutral-200'] : ['hover:bg-neutral-100']"
|
||||
|
|
@ -113,5 +129,23 @@ function onClick() {
|
|||
:focusPath="focusPathFor(index)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div v-if="creating" class="pl-2">
|
||||
<CNoteCreator
|
||||
:parent-id="props.noteId"
|
||||
@close="creating = false"
|
||||
@finish="creating = false"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Controls -->
|
||||
<div
|
||||
v-if="focused"
|
||||
class="absolute right-0.5 flex h-6 items-center gap-0.5"
|
||||
>
|
||||
<CNoteButton @click="creating = true">
|
||||
<RiStickyNoteAddLine size="16px" />
|
||||
</CNoteButton>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
7
gdn-app/src/components/CNoteButton.vue
Normal file
7
gdn-app/src/components/CNoteButton.vue
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<template>
|
||||
<div
|
||||
class="flex select-none items-center rounded-sm border bg-white p-0.5 transition hover:scale-110 active:scale-95"
|
||||
>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
43
gdn-app/src/components/CNoteCreator.vue
Normal file
43
gdn-app/src/components/CNoteCreator.vue
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
<script setup lang="ts">
|
||||
import { RiAddLine, RiCheckLine, RiCloseLine } from "@remixicon/vue";
|
||||
import CNoteButton from "./CNoteButton.vue";
|
||||
import { onMounted, ref, useTemplateRef } from "vue";
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: "close"): void;
|
||||
(e: "finish", text: string): void;
|
||||
}>();
|
||||
|
||||
const input = useTemplateRef<HTMLInputElement>("input");
|
||||
const text = ref("");
|
||||
|
||||
onMounted(() => input.value?.focus());
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-row items-center gap-1 pl-1 pr-0.5">
|
||||
<!-- Fold/unfold symbol -->
|
||||
<div class="flex items-center">
|
||||
<div class="rounded">
|
||||
<RiAddLine size="16px" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Text -->
|
||||
<input
|
||||
ref="input"
|
||||
v-model="text"
|
||||
type="text"
|
||||
class="z-1 flex-1 bg-neutral-100"
|
||||
autofocus
|
||||
/>
|
||||
|
||||
<CNoteButton @click="emit('finish', text)">
|
||||
<RiCheckLine size="16px" />
|
||||
</CNoteButton>
|
||||
|
||||
<CNoteButton @click="emit('close')">
|
||||
<RiCloseLine size="16px" />
|
||||
</CNoteButton>
|
||||
</div>
|
||||
</template>
|
||||
Loading…
Add table
Add a link
Reference in a new issue