From d6f4fe3f1a3f8765d0b963e70d7d6565ffc2d6e5 Mon Sep 17 00:00:00 2001 From: abdelouahed oumoussa Date: Mon, 28 Apr 2025 02:11:03 +0100 Subject: [PATCH 1/6] chore: extract file selector logic into a composable --- src/composables/useFileSelector.ts | 119 ++++++++++++++++++++++++ src/editor/FileSelector.vue | 141 ++++++++--------------------- 2 files changed, 158 insertions(+), 102 deletions(-) create mode 100644 src/composables/useFileSelector.ts diff --git a/src/composables/useFileSelector.ts b/src/composables/useFileSelector.ts new file mode 100644 index 00000000..aaff452f --- /dev/null +++ b/src/composables/useFileSelector.ts @@ -0,0 +1,119 @@ +import { Store, importMapFile, tsconfigFile, stripSrcPrefix } from '../store' +import { computed, inject, ref, VNode, Ref } from 'vue' + +export function useFileSelector() { + const store = inject('store') as Store + + /** + * When `true`: indicates adding a new file + * When `string`: indicates renaming a file, and holds the old filename in case + * of cancel. + */ + const pending = ref(false) + /** + * Text shown in the input box when editing a file's name + * This is a display name so it should always strip off the `src/` prefix. + */ + const pendingFilename = ref('Comp.vue') + const linksFile = 'links.json' + const showTsConfig = inject>('tsconfig') + const showImportMap = inject('import-map') as Ref + const files = computed(() => + Object.entries(store.state.files) + .filter( + ([name, file]) => + ![importMapFile, linksFile, tsconfigFile].includes(name) && + !file.hidden + ) + .map(([name]) => name) + ) + + function startAddFile() { + let i = 0 + let name = `Comp.vue` + + while (true) { + let hasConflict = false + for (const filename in store.state.files) { + if (stripSrcPrefix(filename) === name) { + hasConflict = true + name = `Comp${++i}.vue` + break + } + } + if (!hasConflict) { + break + } + } + + pendingFilename.value = name + pending.value = true + } + + function cancelNameFile() { + pending.value = false + } + + function focus({ el }: VNode) { + ;(el as HTMLInputElement).focus() + } + + function doneNameFile() { + if (!pending.value) return + // add back the src prefix + const filename = 'src/' + pendingFilename.value + const oldFilename = pending.value === true ? '' : pending.value + + if (!/\.(vue|js|ts|css|json)$/.test(filename)) { + store.state.errors = [ + `Playground only supports *.vue, *.js, *.ts, *.css, *.json files.`, + ] + return + } + + if (filename !== oldFilename && filename in store.state.files) { + store.state.errors = [`File "${filename}" already exists.`] + return + } + + store.state.errors = [] + cancelNameFile() + + if (filename === oldFilename) { + return + } + + if (oldFilename) { + store.renameFile(oldFilename, filename) + } else { + store.addFile(filename) + } + } + + const fileSel = ref(null) + + const activeFile = computed({ + get: () => store.state.activeFile.filename, + set: (val) => { + if (!pending.value) store.setActive(val) + }, + }) + + return { + files, + pending, + pendingFilename, + startAddFile, + cancelNameFile, + focus, + doneNameFile, + fileSel, + activeFile, + showTsConfig, + showImportMap, + linksFile, + tsconfigFile, + importMapFile, + stripSrcPrefix, + } +} diff --git a/src/editor/FileSelector.vue b/src/editor/FileSelector.vue index b4dc17d6..2d041df5 100644 --- a/src/editor/FileSelector.vue +++ b/src/editor/FileSelector.vue @@ -9,14 +9,14 @@ density="comfortable" show-arrows > - + {{ stripSrcPrefix(file) }} - + - + tsconfig.json - + Import Map - - Links - + Links diff --git a/src/editor/EditorContainer.vue b/src/editor/EditorContainer.vue index 40b3de41..3ea4353f 100644 --- a/src/editor/EditorContainer.vue +++ b/src/editor/EditorContainer.vue @@ -1,5 +1,4 @@ - - diff --git a/src/editor/FileExplorer.vue b/src/editor/FileExplorer.vue new file mode 100644 index 00000000..a4b01e23 --- /dev/null +++ b/src/editor/FileExplorer.vue @@ -0,0 +1,129 @@ + + + From 6246ae670a8287c9fed19282815daaa7d887791a Mon Sep 17 00:00:00 2001 From: abdelouahed oumoussa Date: Tue, 29 Apr 2025 00:34:59 +0100 Subject: [PATCH 3/6] chore: added ability to open and close file explorer --- src/editor/FileExplorer.vue | 6 ++---- src/monaco/Monaco.vue | 21 +++++++++++++-------- src/store.ts | 16 +++++++++++----- 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/editor/FileExplorer.vue b/src/editor/FileExplorer.vue index a4b01e23..f2d80c01 100644 --- a/src/editor/FileExplorer.vue +++ b/src/editor/FileExplorer.vue @@ -1,12 +1,11 @@