@owdproject/nuxt-kit-nuxt-ui 0.0.0-stage → 4.0.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/module.d.mts +14 -0
- package/dist/module.json +9 -0
- package/dist/module.mjs +90 -0
- package/dist/runtime/components/dialogs/NuxtUIAlertModal.d.vue.ts +8 -0
- package/dist/runtime/components/dialogs/NuxtUIAlertModal.vue +40 -0
- package/dist/runtime/components/dialogs/NuxtUIAlertModal.vue.d.ts +8 -0
- package/dist/runtime/components/dialogs/NuxtUIConfirmModal.d.vue.ts +12 -0
- package/dist/runtime/components/dialogs/NuxtUIConfirmModal.vue +47 -0
- package/dist/runtime/components/dialogs/NuxtUIConfirmModal.vue.d.ts +12 -0
- package/dist/runtime/components/explorer/AddressBar.d.vue.ts +17 -0
- package/dist/runtime/components/explorer/AddressBar.vue +39 -0
- package/dist/runtime/components/explorer/AddressBar.vue.d.ts +17 -0
- package/dist/runtime/components/explorer/Chrome.d.vue.ts +13 -0
- package/dist/runtime/components/explorer/Chrome.vue +5 -0
- package/dist/runtime/components/explorer/Chrome.vue.d.ts +13 -0
- package/dist/runtime/components/explorer/DefaultToolbar.d.vue.ts +31 -0
- package/dist/runtime/components/explorer/DefaultToolbar.vue +92 -0
- package/dist/runtime/components/explorer/DefaultToolbar.vue.d.ts +31 -0
- package/dist/runtime/components/explorer/FileContextMenu.d.vue.ts +18 -0
- package/dist/runtime/components/explorer/FileContextMenu.vue +90 -0
- package/dist/runtime/components/explorer/FileContextMenu.vue.d.ts +18 -0
- package/dist/runtime/components/explorer/FileEntry.d.vue.ts +109 -0
- package/dist/runtime/components/explorer/FileEntry.vue +263 -0
- package/dist/runtime/components/explorer/FileEntry.vue.d.ts +109 -0
- package/dist/runtime/components/explorer/FileIcon.d.vue.ts +29 -0
- package/dist/runtime/components/explorer/FileIcon.vue +41 -0
- package/dist/runtime/components/explorer/FileIcon.vue.d.ts +29 -0
- package/dist/runtime/components/explorer/FilePane.d.vue.ts +13 -0
- package/dist/runtime/components/explorer/FilePane.vue +5 -0
- package/dist/runtime/components/explorer/FilePane.vue.d.ts +13 -0
- package/dist/runtime/components/explorer/Frame.d.vue.ts +75 -0
- package/dist/runtime/components/explorer/Frame.vue +73 -0
- package/dist/runtime/components/explorer/Frame.vue.d.ts +75 -0
- package/dist/runtime/components/explorer/Nav.d.vue.ts +17 -0
- package/dist/runtime/components/explorer/Nav.vue +83 -0
- package/dist/runtime/components/explorer/Nav.vue.d.ts +17 -0
- package/dist/runtime/components/explorer/SelectableArea.d.vue.ts +33 -0
- package/dist/runtime/components/explorer/SelectableArea.vue +83 -0
- package/dist/runtime/components/explorer/SelectableArea.vue.d.ts +33 -0
- package/dist/runtime/components/explorer/Workspace.d.vue.ts +24 -0
- package/dist/runtime/components/explorer/Workspace.vue +116 -0
- package/dist/runtime/components/explorer/Workspace.vue.d.ts +24 -0
- package/dist/runtime/dialogs/createDesktopDialogs.d.ts +2 -0
- package/dist/runtime/dialogs/createDesktopDialogs.js +47 -0
- package/dist/runtime/plugins/01.desktop-nuxt-ui-dialogs.client.d.ts +2 -0
- package/dist/runtime/plugins/01.desktop-nuxt-ui-dialogs.client.js +13 -0
- package/dist/types.d.mts +9 -0
- package/package.json +78 -4
- package/src/kit/registerTailwindPath.ts +44 -0
- package/src/runtime/components/dialogs/NuxtUIAlertModal.vue +42 -0
- package/src/runtime/components/dialogs/NuxtUIConfirmModal.vue +49 -0
- package/src/runtime/components/explorer/AddressBar.vue +44 -0
- package/src/runtime/components/explorer/Chrome.vue +5 -0
- package/src/runtime/components/explorer/DefaultToolbar.vue +92 -0
- package/src/runtime/components/explorer/FileContextMenu.vue +99 -0
- package/src/runtime/components/explorer/FileEntry.vue +286 -0
- package/src/runtime/components/explorer/FileIcon.vue +43 -0
- package/src/runtime/components/explorer/FilePane.vue +5 -0
- package/src/runtime/components/explorer/Frame.vue +106 -0
- package/src/runtime/components/explorer/Nav.vue +87 -0
- package/src/runtime/components/explorer/SelectableArea.vue +93 -0
- package/src/runtime/components/explorer/Workspace.vue +119 -0
- package/src/runtime/dialogs/createDesktopDialogs.ts +56 -0
- package/src/runtime/plugins/01.desktop-nuxt-ui-dialogs.client.ts +14 -0
- package/README.md +0 -3
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { useModal } from "#imports";
|
|
2
|
+
import NuxtUIConfirmModal from "../components/dialogs/NuxtUIConfirmModal.vue";
|
|
3
|
+
import NuxtUIAlertModal from "../components/dialogs/NuxtUIAlertModal.vue";
|
|
4
|
+
export function createDesktopDialogs() {
|
|
5
|
+
return {
|
|
6
|
+
confirm(opts) {
|
|
7
|
+
return new Promise((resolve) => {
|
|
8
|
+
const modal = useModal();
|
|
9
|
+
const toTrash = opts.extras?.toTrash;
|
|
10
|
+
modal.open(NuxtUIConfirmModal, {
|
|
11
|
+
title: opts.title ?? "Confirm",
|
|
12
|
+
message: typeof opts.message === "string" ? opts.message : opts.message?.message ?? "",
|
|
13
|
+
acceptLabel: opts.acceptLabel ?? "OK",
|
|
14
|
+
rejectLabel: opts.rejectLabel ?? "Cancel",
|
|
15
|
+
toTrash: !!toTrash,
|
|
16
|
+
onSuccess: () => {
|
|
17
|
+
modal.close();
|
|
18
|
+
resolve(true);
|
|
19
|
+
},
|
|
20
|
+
onCancel: () => {
|
|
21
|
+
modal.close();
|
|
22
|
+
resolve(false);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
},
|
|
27
|
+
alert(message, options) {
|
|
28
|
+
return new Promise((resolve) => {
|
|
29
|
+
const modal = useModal();
|
|
30
|
+
modal.open(NuxtUIAlertModal, {
|
|
31
|
+
title: options?.title ?? "Alert",
|
|
32
|
+
message,
|
|
33
|
+
onSuccess: () => {
|
|
34
|
+
modal.close();
|
|
35
|
+
resolve();
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
},
|
|
40
|
+
prompt(message, defaultValue = "") {
|
|
41
|
+
if (import.meta.server) return Promise.resolve(null);
|
|
42
|
+
const g = globalThis;
|
|
43
|
+
const v = typeof g.prompt === "function" ? g.prompt(message, defaultValue) : null;
|
|
44
|
+
return Promise.resolve(v === null ? null : v);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { defineNuxtPlugin } from "nuxt/app";
|
|
2
|
+
import { DESKTOP_DIALOG_PROVIDER_KEY } from "@owdproject/nuxt/runtime/constants/desktopShellKeys";
|
|
3
|
+
import { createDesktopDialogs } from "../dialogs/createDesktopDialogs.js";
|
|
4
|
+
export default defineNuxtPlugin({
|
|
5
|
+
name: "owd-kit-nuxt-ui-dialogs",
|
|
6
|
+
enforce: "pre",
|
|
7
|
+
setup(nuxtApp) {
|
|
8
|
+
nuxtApp.vueApp.provide(
|
|
9
|
+
DESKTOP_DIALOG_PROVIDER_KEY,
|
|
10
|
+
createDesktopDialogs()
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
});
|
package/dist/types.d.mts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { NuxtModule } from '@nuxt/schema'
|
|
2
|
+
|
|
3
|
+
import type { default as Module } from './module.mjs'
|
|
4
|
+
|
|
5
|
+
export type ModuleOptions = typeof Module extends NuxtModule<infer O> ? Partial<O> : Record<string, any>
|
|
6
|
+
|
|
7
|
+
export { default } from './module.mjs'
|
|
8
|
+
|
|
9
|
+
export { type KitNuxtUiModuleOptions } from './module.mjs'
|
package/package.json
CHANGED
|
@@ -1,6 +1,80 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@owdproject/nuxt-kit-nuxt-ui",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "4.0.0-alpha.3",
|
|
4
|
+
"description": "Nuxt UI for OWD themes: dialogs (always) and optional DesktopExplorer* UI (requires @owdproject/nuxt-module-fs; use { explorer: false } for dialogs only).",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/types.d.mts",
|
|
10
|
+
"development": "./src/module.ts",
|
|
11
|
+
"import": "./dist/module.mjs",
|
|
12
|
+
"default": "./dist/module.mjs"
|
|
13
|
+
},
|
|
14
|
+
"./runtime/dialogs/createDesktopDialogs": {
|
|
15
|
+
"types": "./src/runtime/dialogs/createDesktopDialogs.ts",
|
|
16
|
+
"import": "./src/runtime/dialogs/createDesktopDialogs.ts"
|
|
17
|
+
},
|
|
18
|
+
"./runtime/dialogs/*": {
|
|
19
|
+
"types": "./src/runtime/dialogs/*",
|
|
20
|
+
"import": "./src/runtime/dialogs/*"
|
|
21
|
+
},
|
|
22
|
+
"./runtime/components/*": {
|
|
23
|
+
"types": "./src/runtime/components/*",
|
|
24
|
+
"import": "./src/runtime/components/*"
|
|
25
|
+
},
|
|
26
|
+
"./kit/registerTailwindPath": {
|
|
27
|
+
"types": "./src/kit/registerTailwindPath.ts",
|
|
28
|
+
"import": "./src/kit/registerTailwindPath.ts"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"main": "./dist/module.mjs",
|
|
32
|
+
"typesVersions": {
|
|
33
|
+
"*": {
|
|
34
|
+
".": [
|
|
35
|
+
"./dist/types.d.mts"
|
|
36
|
+
]
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"files": [
|
|
40
|
+
"dist",
|
|
41
|
+
"src/runtime",
|
|
42
|
+
"src/kit"
|
|
43
|
+
],
|
|
44
|
+
"scripts": {
|
|
45
|
+
"prepack": "nuxt-module-build build",
|
|
46
|
+
"dev": "pnpm run dev:prepare",
|
|
47
|
+
"dev:prepare": "nuxt-module-build build --stub",
|
|
48
|
+
"build:module": "nuxt-module-build build"
|
|
49
|
+
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"@nuxt/kit": "^4.4.4",
|
|
52
|
+
"@nuxt/ui": "^2.21.0",
|
|
53
|
+
"defu": "^6.1.4",
|
|
54
|
+
"vue3-selecto": "^1.12.3",
|
|
55
|
+
"@owdproject/nuxt": "^4.0.0-alpha.3"
|
|
56
|
+
},
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"@nuxt/module-builder": "^1.0.2",
|
|
59
|
+
"@nuxt/schema": "^4.4.4",
|
|
60
|
+
"@owdproject/core": "^4.0.0-alpha.3",
|
|
61
|
+
"@owdproject/nuxt-module-fs": "^4.0.0-alpha.3",
|
|
62
|
+
"nuxt": "^4.4.4",
|
|
63
|
+
"typescript": "catalog:"
|
|
64
|
+
},
|
|
65
|
+
"peerDependencies": {
|
|
66
|
+
"@owdproject/core": "^4.0.0-alpha.3",
|
|
67
|
+
"@owdproject/nuxt-module-fs": "^4.0.0-alpha.3",
|
|
68
|
+
"@owdproject/nuxt": "^4.0.0-alpha.3"
|
|
69
|
+
},
|
|
70
|
+
"peerDependenciesMeta": {
|
|
71
|
+
"@owdproject/nuxt-module-fs": {
|
|
72
|
+
"optional": true
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
"publishConfig": {
|
|
76
|
+
"access": "public",
|
|
77
|
+
"tag": "alpha",
|
|
78
|
+
"registry": "https://registry.npmjs.org/"
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { createResolver } from '@nuxt/kit'
|
|
2
|
+
import type { Nuxt } from '@nuxt/schema'
|
|
3
|
+
|
|
4
|
+
declare module '@nuxt/schema' {
|
|
5
|
+
interface NuxtConfig {
|
|
6
|
+
desktopTailwindContent?: string[]
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const DEFAULT_THEME_TAILWIND_GLOBS = [
|
|
11
|
+
'./runtime/components/**/*.{vue,mjs,ts}',
|
|
12
|
+
'./runtime/apps/**/*.{vue,mjs,ts}',
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
function tailwindContentPaths(nuxt: Nuxt): string[] {
|
|
16
|
+
nuxt.options.desktopTailwindContent ??= []
|
|
17
|
+
return nuxt.options.desktopTailwindContent
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Register a Tailwind content glob; merged on `tailwindcss:config` when kit installs `@nuxtjs/tailwindcss`.
|
|
22
|
+
* Call from themes, built-in apps, or extension modules that ship Vue templates with utility classes.
|
|
23
|
+
*/
|
|
24
|
+
export function registerTailwindPath(nuxt: Nuxt, path: string): void {
|
|
25
|
+
const paths = tailwindContentPaths(nuxt)
|
|
26
|
+
if (!paths.includes(path)) {
|
|
27
|
+
paths.push(path)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Register default theme component globs relative to a theme module root (`import.meta.url`).
|
|
33
|
+
*/
|
|
34
|
+
export function registerThemeTailwindPath(
|
|
35
|
+
nuxt: Nuxt,
|
|
36
|
+
moduleUrl: string,
|
|
37
|
+
glob: string | string[] = DEFAULT_THEME_TAILWIND_GLOBS,
|
|
38
|
+
): void {
|
|
39
|
+
const { resolve } = createResolver(moduleUrl)
|
|
40
|
+
const globs = Array.isArray(glob) ? glob : [glob]
|
|
41
|
+
for (const entry of globs) {
|
|
42
|
+
registerTailwindPath(nuxt, resolve(entry))
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
|
|
4
|
+
defineProps<{
|
|
5
|
+
title: string
|
|
6
|
+
message: string
|
|
7
|
+
onSuccess: () => void
|
|
8
|
+
}>()
|
|
9
|
+
|
|
10
|
+
const isOpen = ref(true)
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<template>
|
|
14
|
+
<UModal v-model="isOpen" prevent-close>
|
|
15
|
+
<UCard :ui="{ ring: '', divide: 'y divide-gray-100 dark:divide-gray-800' }">
|
|
16
|
+
<template #header>
|
|
17
|
+
<div class="flex items-center justify-between">
|
|
18
|
+
<h3 class="text-base font-semibold leading-6 text-gray-900 dark:text-white">
|
|
19
|
+
{{ title }}
|
|
20
|
+
</h3>
|
|
21
|
+
</div>
|
|
22
|
+
</template>
|
|
23
|
+
|
|
24
|
+
<div class="flex items-start space-x-4">
|
|
25
|
+
<div class="text-blue-500 flex-shrink-0 mt-0.5">
|
|
26
|
+
<UIcon name="i-heroicons-information-circle" class="w-6 h-6" />
|
|
27
|
+
</div>
|
|
28
|
+
<div class="text-sm text-gray-600 dark:text-gray-300">
|
|
29
|
+
{{ message }}
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
<template #footer>
|
|
34
|
+
<div class="flex justify-end">
|
|
35
|
+
<UButton color="primary" @click="onSuccess">
|
|
36
|
+
OK
|
|
37
|
+
</UButton>
|
|
38
|
+
</div>
|
|
39
|
+
</template>
|
|
40
|
+
</UCard>
|
|
41
|
+
</UModal>
|
|
42
|
+
</template>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
|
|
4
|
+
defineProps<{
|
|
5
|
+
title: string
|
|
6
|
+
message: string
|
|
7
|
+
acceptLabel: string
|
|
8
|
+
rejectLabel: string
|
|
9
|
+
toTrash?: boolean
|
|
10
|
+
onSuccess: () => void
|
|
11
|
+
onCancel: () => void
|
|
12
|
+
}>()
|
|
13
|
+
|
|
14
|
+
const isOpen = ref(true)
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
<template>
|
|
18
|
+
<UModal v-model="isOpen" prevent-close>
|
|
19
|
+
<UCard :ui="{ ring: '', divide: 'y divide-gray-100 dark:divide-gray-800' }">
|
|
20
|
+
<template #header>
|
|
21
|
+
<div class="flex items-center justify-between">
|
|
22
|
+
<h3 class="text-base font-semibold leading-6 text-gray-900 dark:text-white">
|
|
23
|
+
{{ title }}
|
|
24
|
+
</h3>
|
|
25
|
+
</div>
|
|
26
|
+
</template>
|
|
27
|
+
|
|
28
|
+
<div class="flex items-start space-x-4">
|
|
29
|
+
<div class="text-amber-500 flex-shrink-0 mt-0.5">
|
|
30
|
+
<UIcon name="i-heroicons-exclamation-triangle" class="w-6 h-6" />
|
|
31
|
+
</div>
|
|
32
|
+
<div class="text-sm text-gray-600 dark:text-gray-300">
|
|
33
|
+
{{ message }}
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
<template #footer>
|
|
38
|
+
<div class="flex justify-end space-x-2">
|
|
39
|
+
<UButton color="gray" variant="ghost" @click="onCancel">
|
|
40
|
+
{{ rejectLabel }}
|
|
41
|
+
</UButton>
|
|
42
|
+
<UButton color="primary" @click="onSuccess">
|
|
43
|
+
{{ acceptLabel }}
|
|
44
|
+
</UButton>
|
|
45
|
+
</div>
|
|
46
|
+
</template>
|
|
47
|
+
</UCard>
|
|
48
|
+
</UModal>
|
|
49
|
+
</template>
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref, watch } from 'vue'
|
|
3
|
+
import {
|
|
4
|
+
formatExplorerDisplayPath,
|
|
5
|
+
parseExplorerVfsPath,
|
|
6
|
+
} from '@owdproject/nuxt-module-fs/runtime/utils/utilExplorerDisplayPath'
|
|
7
|
+
|
|
8
|
+
const props = defineProps({
|
|
9
|
+
address: { type: String, required: true },
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
const emit = defineEmits(['update:modelValue'])
|
|
13
|
+
|
|
14
|
+
const addressInput = ref(formatExplorerDisplayPath(props.address))
|
|
15
|
+
|
|
16
|
+
watch(
|
|
17
|
+
() => props.address,
|
|
18
|
+
(address) => {
|
|
19
|
+
addressInput.value = formatExplorerDisplayPath(address)
|
|
20
|
+
},
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
function onEnter() {
|
|
24
|
+
emit('update:modelValue', parseExplorerVfsPath(addressInput.value))
|
|
25
|
+
}
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
<template>
|
|
29
|
+
<div class="flex items-center space-x-2 p-2 bg-gray-50 dark:bg-gray-900 border-b border-gray-200 dark:border-gray-800">
|
|
30
|
+
<span class="text-xs font-semibold text-gray-500 dark:text-gray-400 select-none">
|
|
31
|
+
{{ $t('apps.explorer.address') }}
|
|
32
|
+
</span>
|
|
33
|
+
<UInput
|
|
34
|
+
v-model="addressInput"
|
|
35
|
+
class="flex-1"
|
|
36
|
+
size="sm"
|
|
37
|
+
color="gray"
|
|
38
|
+
variant="outline"
|
|
39
|
+
spellcheck="false"
|
|
40
|
+
icon="i-heroicons-folder-open"
|
|
41
|
+
@keydown.enter="onEnter"
|
|
42
|
+
/>
|
|
43
|
+
</div>
|
|
44
|
+
</template>
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
defineProps({
|
|
3
|
+
arrowsDisabled: { type: Boolean, required: true },
|
|
4
|
+
})
|
|
5
|
+
defineEmits([
|
|
6
|
+
'back',
|
|
7
|
+
'forward',
|
|
8
|
+
'up',
|
|
9
|
+
'cut',
|
|
10
|
+
'copy',
|
|
11
|
+
'paste',
|
|
12
|
+
'delete',
|
|
13
|
+
'properties',
|
|
14
|
+
])
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
<template>
|
|
18
|
+
<div class="flex items-center space-x-1 p-2 bg-gray-50 dark:bg-gray-900 border-b border-gray-200 dark:border-gray-800">
|
|
19
|
+
<UButton
|
|
20
|
+
icon="i-heroicons-arrow-left"
|
|
21
|
+
color="gray"
|
|
22
|
+
variant="ghost"
|
|
23
|
+
size="sm"
|
|
24
|
+
:disabled="arrowsDisabled"
|
|
25
|
+
@click="$emit('back')"
|
|
26
|
+
:title="$t('apps.explorer.action.back')"
|
|
27
|
+
/>
|
|
28
|
+
<UButton
|
|
29
|
+
icon="i-heroicons-arrow-right"
|
|
30
|
+
color="gray"
|
|
31
|
+
variant="ghost"
|
|
32
|
+
size="sm"
|
|
33
|
+
:disabled="arrowsDisabled"
|
|
34
|
+
@click="$emit('forward')"
|
|
35
|
+
:title="$t('apps.explorer.action.forward')"
|
|
36
|
+
/>
|
|
37
|
+
<UButton
|
|
38
|
+
icon="i-heroicons-arrow-up-circle"
|
|
39
|
+
color="gray"
|
|
40
|
+
variant="ghost"
|
|
41
|
+
size="sm"
|
|
42
|
+
@click="$emit('up')"
|
|
43
|
+
:title="$t('apps.explorer.action.up')"
|
|
44
|
+
/>
|
|
45
|
+
|
|
46
|
+
<div class="border-l border-gray-200 dark:border-gray-800 h-5 mx-1" />
|
|
47
|
+
|
|
48
|
+
<UButton
|
|
49
|
+
icon="i-heroicons-scissors"
|
|
50
|
+
color="gray"
|
|
51
|
+
variant="ghost"
|
|
52
|
+
size="sm"
|
|
53
|
+
@click="$emit('cut')"
|
|
54
|
+
:title="$t('apps.explorer.action.cut')"
|
|
55
|
+
/>
|
|
56
|
+
<UButton
|
|
57
|
+
icon="i-heroicons-document-duplicate"
|
|
58
|
+
color="gray"
|
|
59
|
+
variant="ghost"
|
|
60
|
+
size="sm"
|
|
61
|
+
@click="$emit('copy')"
|
|
62
|
+
:title="$t('apps.explorer.action.copy')"
|
|
63
|
+
/>
|
|
64
|
+
<UButton
|
|
65
|
+
icon="i-heroicons-clipboard"
|
|
66
|
+
color="gray"
|
|
67
|
+
variant="ghost"
|
|
68
|
+
size="sm"
|
|
69
|
+
@click="$emit('paste')"
|
|
70
|
+
:title="$t('apps.explorer.action.paste')"
|
|
71
|
+
/>
|
|
72
|
+
<UButton
|
|
73
|
+
icon="i-heroicons-trash"
|
|
74
|
+
color="red"
|
|
75
|
+
variant="ghost"
|
|
76
|
+
size="sm"
|
|
77
|
+
@click="$emit('delete')"
|
|
78
|
+
:title="$t('apps.explorer.action.delete')"
|
|
79
|
+
/>
|
|
80
|
+
|
|
81
|
+
<div class="border-l border-gray-200 dark:border-gray-800 h-5 mx-1" />
|
|
82
|
+
|
|
83
|
+
<UButton
|
|
84
|
+
icon="i-heroicons-information-circle"
|
|
85
|
+
color="gray"
|
|
86
|
+
variant="ghost"
|
|
87
|
+
size="sm"
|
|
88
|
+
@click="$emit('properties')"
|
|
89
|
+
:title="$t('apps.explorer.action.properties')"
|
|
90
|
+
/>
|
|
91
|
+
</div>
|
|
92
|
+
</template>
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref, computed } from 'vue'
|
|
3
|
+
import { useI18n } from 'vue-i18n'
|
|
4
|
+
import { explorerEntryAbsolutePath } from '@owdproject/nuxt-module-fs/runtime/utils/utilExplorerEntryPath'
|
|
5
|
+
|
|
6
|
+
const { t } = useI18n()
|
|
7
|
+
|
|
8
|
+
const props = defineProps<{
|
|
9
|
+
fileName: string
|
|
10
|
+
window: any
|
|
11
|
+
isDirectory?: boolean
|
|
12
|
+
openPathInNewTab?: (p: string) => void
|
|
13
|
+
}>()
|
|
14
|
+
|
|
15
|
+
const emit = defineEmits(['open', 'rename'])
|
|
16
|
+
|
|
17
|
+
const isOpen = ref(false)
|
|
18
|
+
const virtualElement = ref({ getBoundingClientRect: () => ({} as any) })
|
|
19
|
+
|
|
20
|
+
const entryPath = computed(() =>
|
|
21
|
+
explorerEntryAbsolutePath(
|
|
22
|
+
props.window.fsExplorer.basePath.value,
|
|
23
|
+
props.fileName,
|
|
24
|
+
),
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
function selectEntry() {
|
|
28
|
+
props.window.fsExplorer.selectFiles([entryPath.value])
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const items = computed(() => [
|
|
32
|
+
[
|
|
33
|
+
{
|
|
34
|
+
label: t('fs.contextMenu.open'),
|
|
35
|
+
click: () => {
|
|
36
|
+
emit('open', props.fileName)
|
|
37
|
+
},
|
|
38
|
+
}
|
|
39
|
+
],
|
|
40
|
+
[
|
|
41
|
+
{
|
|
42
|
+
label: t('fs.contextMenu.cut'),
|
|
43
|
+
click: () => {
|
|
44
|
+
selectEntry()
|
|
45
|
+
props.window.fsExplorer.cutSelectedFiles()
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
label: t('fs.contextMenu.copy'),
|
|
50
|
+
click: () => {
|
|
51
|
+
selectEntry()
|
|
52
|
+
props.window.fsExplorer.copySelectedFiles()
|
|
53
|
+
},
|
|
54
|
+
}
|
|
55
|
+
],
|
|
56
|
+
[
|
|
57
|
+
{
|
|
58
|
+
label: t('fs.contextMenu.delete'),
|
|
59
|
+
click: () => {
|
|
60
|
+
selectEntry()
|
|
61
|
+
props.window.fsExplorer.fsController.deleteSelectedFiles()
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
label: t('fs.contextMenu.rename'),
|
|
66
|
+
click: () => {
|
|
67
|
+
emit('rename', props.fileName)
|
|
68
|
+
},
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
])
|
|
72
|
+
|
|
73
|
+
function show(event: MouseEvent) {
|
|
74
|
+
event.preventDefault()
|
|
75
|
+
virtualElement.value = {
|
|
76
|
+
getBoundingClientRect: () => ({
|
|
77
|
+
width: 0,
|
|
78
|
+
height: 0,
|
|
79
|
+
top: event.clientY,
|
|
80
|
+
right: event.clientX,
|
|
81
|
+
bottom: event.clientY,
|
|
82
|
+
left: event.clientX,
|
|
83
|
+
}) as any
|
|
84
|
+
}
|
|
85
|
+
isOpen.value = true
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
defineExpose({
|
|
89
|
+
show,
|
|
90
|
+
})
|
|
91
|
+
</script>
|
|
92
|
+
|
|
93
|
+
<template>
|
|
94
|
+
<UContextMenu v-model="isOpen" :virtual-element="virtualElement">
|
|
95
|
+
<UCard :ui="{ body: { padding: 'p-1' } }">
|
|
96
|
+
<UVerticalNavigation :links="[items[0], items[1], items[2]]" />
|
|
97
|
+
</UCard>
|
|
98
|
+
</UContextMenu>
|
|
99
|
+
</template>
|