@owdproject/nuxt-theme-ui 0.0.0-stage → 4.0.0-alpha.4
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/i18n/locales/en.d.ts +2 -0
- package/dist/i18n/locales/en.js +1 -0
- package/dist/module.d.mts +7 -0
- package/dist/module.json +9 -0
- package/dist/module.mjs +50 -0
- package/dist/runtime/apps/calculator/app.config.d.ts +34 -0
- package/dist/runtime/apps/calculator/app.config.js +35 -0
- package/dist/runtime/apps/calculator/components/Window/WindowCalculator.d.vue.ts +6 -0
- package/dist/runtime/apps/calculator/components/Window/WindowCalculator.vue +94 -0
- package/dist/runtime/apps/calculator/components/Window/WindowCalculator.vue.d.ts +6 -0
- package/dist/runtime/apps/calculator/plugin.d.ts +2 -0
- package/dist/runtime/apps/calculator/plugin.js +11 -0
- package/dist/runtime/apps/explorer/app.config.d.ts +36 -0
- package/dist/runtime/apps/explorer/app.config.js +39 -0
- package/dist/runtime/apps/explorer/components/Window/WindowExplorer.d.vue.ts +6 -0
- package/dist/runtime/apps/explorer/components/Window/WindowExplorer.vue +30 -0
- package/dist/runtime/apps/explorer/components/Window/WindowExplorer.vue.d.ts +6 -0
- package/dist/runtime/apps/explorer/plugin.d.ts +2 -0
- package/dist/runtime/apps/explorer/plugin.js +11 -0
- package/dist/runtime/apps/installBuiltInApps.d.ts +3 -0
- package/dist/runtime/apps/installBuiltInApps.js +28 -0
- package/dist/runtime/apps/notepad/app.config.d.ts +34 -0
- package/dist/runtime/apps/notepad/app.config.js +35 -0
- package/dist/runtime/apps/notepad/components/Window/WindowNotepad.d.vue.ts +6 -0
- package/dist/runtime/apps/notepad/components/Window/WindowNotepad.vue +47 -0
- package/dist/runtime/apps/notepad/components/Window/WindowNotepad.vue.d.ts +6 -0
- package/dist/runtime/apps/notepad/plugin.d.ts +2 -0
- package/dist/runtime/apps/notepad/plugin.js +11 -0
- package/dist/runtime/apps/registry.d.ts +8 -0
- package/dist/runtime/apps/registry.js +10 -0
- package/dist/runtime/components/Background/DesktopBackground.d.vue.ts +3 -0
- package/dist/runtime/components/Background/DesktopBackground.vue +3 -0
- package/dist/runtime/components/Background/DesktopBackground.vue.d.ts +3 -0
- package/dist/runtime/components/Desktop/DesktopContent.d.vue.ts +13 -0
- package/dist/runtime/components/Desktop/DesktopContent.vue +23 -0
- package/dist/runtime/components/Desktop/DesktopContent.vue.d.ts +13 -0
- package/dist/runtime/components/Desktop.client.d.vue.ts +23 -0
- package/dist/runtime/components/Desktop.client.vue +52 -0
- package/dist/runtime/components/Desktop.client.vue.d.ts +23 -0
- package/dist/runtime/components/NuxtLauncherOverlay.d.vue.ts +3 -0
- package/dist/runtime/components/NuxtLauncherOverlay.vue +110 -0
- package/dist/runtime/components/NuxtLauncherOverlay.vue.d.ts +3 -0
- package/dist/runtime/components/NuxtTopBar.d.vue.ts +3 -0
- package/dist/runtime/components/NuxtTopBar.vue +63 -0
- package/dist/runtime/components/NuxtTopBar.vue.d.ts +3 -0
- package/dist/runtime/components/Window/DesktopWindow.d.vue.ts +43 -0
- package/dist/runtime/components/Window/DesktopWindow.vue +40 -0
- package/dist/runtime/components/Window/DesktopWindow.vue.d.ts +43 -0
- package/dist/runtime/components/Window/DesktopWindowContent.d.vue.ts +13 -0
- package/dist/runtime/components/Window/DesktopWindowContent.vue +5 -0
- package/dist/runtime/components/Window/DesktopWindowContent.vue.d.ts +13 -0
- package/dist/runtime/components/Window/DesktopWindowIframe.d.vue.ts +29 -0
- package/dist/runtime/components/Window/DesktopWindowIframe.vue +13 -0
- package/dist/runtime/components/Window/DesktopWindowIframe.vue.d.ts +29 -0
- package/dist/runtime/components/Window/DesktopWindowNav.d.vue.ts +3 -0
- package/dist/runtime/components/Window/DesktopWindowNav.vue +105 -0
- package/dist/runtime/components/Window/DesktopWindowNav.vue.d.ts +3 -0
- package/dist/runtime/composables/useNuxtStartMenu.d.ts +9 -0
- package/dist/runtime/composables/useNuxtStartMenu.js +57 -0
- package/dist/types.d.mts +7 -0
- package/package.json +70 -4
- package/src/i18n/locales/en.ts +1 -0
- package/src/module.ts +69 -0
- package/src/runtime/apps/calculator/app.config.ts +35 -0
- package/src/runtime/apps/calculator/components/Window/WindowCalculator.vue +104 -0
- package/src/runtime/apps/calculator/plugin.ts +12 -0
- package/src/runtime/apps/explorer/app.config.ts +39 -0
- package/src/runtime/apps/explorer/components/Window/WindowExplorer.vue +34 -0
- package/src/runtime/apps/explorer/plugin.ts +12 -0
- package/src/runtime/apps/installBuiltInApps.ts +36 -0
- package/src/runtime/apps/notepad/app.config.ts +35 -0
- package/src/runtime/apps/notepad/components/Window/WindowNotepad.vue +50 -0
- package/src/runtime/apps/notepad/plugin.ts +12 -0
- package/src/runtime/apps/registry.ts +21 -0
- package/src/runtime/components/Background/DesktopBackground.vue +3 -0
- package/src/runtime/components/Desktop/DesktopContent.vue +37 -0
- package/src/runtime/components/Desktop.client.vue +136 -0
- package/src/runtime/components/NuxtLauncherOverlay.vue +117 -0
- package/src/runtime/components/NuxtTopBar.vue +68 -0
- package/src/runtime/components/Window/DesktopWindow.vue +44 -0
- package/src/runtime/components/Window/DesktopWindowContent.vue +5 -0
- package/src/runtime/components/Window/DesktopWindowIframe.vue +13 -0
- package/src/runtime/components/Window/DesktopWindowNav.vue +110 -0
- package/src/runtime/composables/useNuxtStartMenu.ts +72 -0
- package/README.md +0 -3
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { inject, computed } from "vue";
|
|
3
|
+
import { useToggleWindowMaximize } from "@owdproject/nuxt/runtime/composables/useToggleWindowMaximize";
|
|
4
|
+
const windowController = inject("windowController");
|
|
5
|
+
const toggleWindowMaximize = useToggleWindowMaximize();
|
|
6
|
+
function onWindowMinimize() {
|
|
7
|
+
if (!windowController?.instanced) return;
|
|
8
|
+
windowController.actions.minimize();
|
|
9
|
+
}
|
|
10
|
+
function onWindowMaximize() {
|
|
11
|
+
toggleWindowMaximize(windowController);
|
|
12
|
+
}
|
|
13
|
+
function onWindowNavDestroy() {
|
|
14
|
+
if (!windowController?.instanced) return;
|
|
15
|
+
windowController.actions.destroy();
|
|
16
|
+
}
|
|
17
|
+
const dropdownItems = computed(() => [
|
|
18
|
+
[
|
|
19
|
+
{
|
|
20
|
+
label: "Minimize",
|
|
21
|
+
icon: "i-heroicons-minus",
|
|
22
|
+
click: onWindowMinimize
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
label: windowController?.state?.maximized ? "Restore" : "Maximize",
|
|
26
|
+
icon: "i-heroicons-squares-2x2",
|
|
27
|
+
click: onWindowMaximize
|
|
28
|
+
}
|
|
29
|
+
],
|
|
30
|
+
[
|
|
31
|
+
{
|
|
32
|
+
label: "Close",
|
|
33
|
+
icon: "i-heroicons-x-mark",
|
|
34
|
+
click: onWindowNavDestroy
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
]);
|
|
38
|
+
</script>
|
|
39
|
+
|
|
40
|
+
<template>
|
|
41
|
+
<DesktopCoreWindowNav
|
|
42
|
+
class="flex items-center justify-between px-3 py-1.5 bg-gray-50 dark:bg-gray-900 border-b border-gray-200 dark:border-gray-800 select-none cursor-default"
|
|
43
|
+
@dblclick="onWindowMaximize"
|
|
44
|
+
>
|
|
45
|
+
<div class="flex items-center space-x-2 min-w-0">
|
|
46
|
+
<UDropdown :items="dropdownItems" :popper="{ placement: 'bottom-start' }">
|
|
47
|
+
<UButton
|
|
48
|
+
v-if="windowController?.icon"
|
|
49
|
+
:icon="windowController.icon"
|
|
50
|
+
color="gray"
|
|
51
|
+
variant="ghost"
|
|
52
|
+
size="2xs"
|
|
53
|
+
class="h-5 w-5 p-0 flex items-center justify-center rounded"
|
|
54
|
+
/>
|
|
55
|
+
<UButton
|
|
56
|
+
v-else
|
|
57
|
+
icon="i-heroicons-cog-6-tooth"
|
|
58
|
+
color="gray"
|
|
59
|
+
variant="ghost"
|
|
60
|
+
size="2xs"
|
|
61
|
+
class="h-5 w-5 p-0 flex items-center justify-center rounded"
|
|
62
|
+
/>
|
|
63
|
+
</UDropdown>
|
|
64
|
+
|
|
65
|
+
<div
|
|
66
|
+
v-if="windowController?.title"
|
|
67
|
+
class="text-xs font-semibold text-gray-700 dark:text-gray-300 truncate"
|
|
68
|
+
v-text="windowController?.title"
|
|
69
|
+
/>
|
|
70
|
+
</div>
|
|
71
|
+
|
|
72
|
+
<div class="flex items-center space-x-1 flex-shrink-0">
|
|
73
|
+
<UButton
|
|
74
|
+
v-if="!windowController?.instanced || windowController?.isMinimizable"
|
|
75
|
+
icon="i-heroicons-minus"
|
|
76
|
+
size="2xs"
|
|
77
|
+
color="gray"
|
|
78
|
+
variant="ghost"
|
|
79
|
+
class="h-5 w-5 p-0 flex items-center justify-center rounded"
|
|
80
|
+
@mousedown.stop
|
|
81
|
+
@click.stop="onWindowMinimize"
|
|
82
|
+
/>
|
|
83
|
+
<UButton
|
|
84
|
+
v-if="windowController?.isMaximizable"
|
|
85
|
+
icon="i-heroicons-squares-2x2"
|
|
86
|
+
size="2xs"
|
|
87
|
+
color="gray"
|
|
88
|
+
variant="ghost"
|
|
89
|
+
class="h-5 w-5 p-0 flex items-center justify-center rounded"
|
|
90
|
+
@mousedown.stop
|
|
91
|
+
@click.stop="onWindowMaximize"
|
|
92
|
+
/>
|
|
93
|
+
<UButton
|
|
94
|
+
v-if="!windowController?.instanced || windowController?.isDestroyable"
|
|
95
|
+
icon="i-heroicons-x-mark"
|
|
96
|
+
size="2xs"
|
|
97
|
+
color="red"
|
|
98
|
+
variant="ghost"
|
|
99
|
+
class="h-5 w-5 p-0 flex items-center justify-center rounded hover:bg-red-500 hover:text-white"
|
|
100
|
+
@mousedown.stop
|
|
101
|
+
@click.stop="onWindowNavDestroy"
|
|
102
|
+
/>
|
|
103
|
+
</div>
|
|
104
|
+
</DesktopCoreWindowNav>
|
|
105
|
+
</template>
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
2
|
+
declare const _default: typeof __VLS_export;
|
|
3
|
+
export default _default;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function useNuxtStartMenu(): {
|
|
2
|
+
open: import("vue").Ref<boolean, boolean>;
|
|
3
|
+
searchQuery: import("vue").Ref<string, string>;
|
|
4
|
+
allEntries: import("vue").ComputedRef<any>;
|
|
5
|
+
filteredEntries: import("vue").ComputedRef<any>;
|
|
6
|
+
toggle: () => void;
|
|
7
|
+
close: () => void;
|
|
8
|
+
launchEntry: (entry: any) => Promise<void>;
|
|
9
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { ref, computed } from "vue";
|
|
2
|
+
import { useScrollLock } from "@vueuse/core";
|
|
3
|
+
import { useApplicationManager } from "@owdproject/nuxt/runtime/composables/useApplicationManager";
|
|
4
|
+
import { useApplicationEntries } from "@owdproject/nuxt/runtime/composables/useApplicationEntries";
|
|
5
|
+
const open = ref(false);
|
|
6
|
+
const searchQuery = ref("");
|
|
7
|
+
function isValidEntry(entry) {
|
|
8
|
+
return Boolean(entry?.application?.id && entry.command);
|
|
9
|
+
}
|
|
10
|
+
export function useNuxtStartMenu() {
|
|
11
|
+
const applicationManager = useApplicationManager();
|
|
12
|
+
const applicationEntries = useApplicationEntries();
|
|
13
|
+
const bodyScrollLock = useScrollLock(
|
|
14
|
+
typeof document !== "undefined" ? document.body : null
|
|
15
|
+
);
|
|
16
|
+
const allEntries = computed(() => {
|
|
17
|
+
return applicationEntries.sortedAppEntries("title", "primary").value.filter(isValidEntry);
|
|
18
|
+
});
|
|
19
|
+
const filteredEntries = computed(() => {
|
|
20
|
+
const q = searchQuery.value.trim().toLowerCase();
|
|
21
|
+
const entries = allEntries.value;
|
|
22
|
+
if (!q) return entries;
|
|
23
|
+
return entries.filter(
|
|
24
|
+
(entry) => (entry.title ?? "").toLowerCase().includes(q)
|
|
25
|
+
);
|
|
26
|
+
});
|
|
27
|
+
function syncScrollLock() {
|
|
28
|
+
bodyScrollLock.value = open.value;
|
|
29
|
+
}
|
|
30
|
+
function toggle() {
|
|
31
|
+
open.value = !open.value;
|
|
32
|
+
searchQuery.value = "";
|
|
33
|
+
syncScrollLock();
|
|
34
|
+
}
|
|
35
|
+
function close() {
|
|
36
|
+
open.value = false;
|
|
37
|
+
searchQuery.value = "";
|
|
38
|
+
bodyScrollLock.value = false;
|
|
39
|
+
}
|
|
40
|
+
async function launchEntry(entry) {
|
|
41
|
+
if (!isValidEntry(entry)) return;
|
|
42
|
+
await applicationManager.execAppCommand(
|
|
43
|
+
entry.application.id,
|
|
44
|
+
entry.command
|
|
45
|
+
);
|
|
46
|
+
close();
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
open,
|
|
50
|
+
searchQuery,
|
|
51
|
+
allEntries,
|
|
52
|
+
filteredEntries,
|
|
53
|
+
toggle,
|
|
54
|
+
close,
|
|
55
|
+
launchEntry
|
|
56
|
+
};
|
|
57
|
+
}
|
package/dist/types.d.mts
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,72 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@owdproject/nuxt-theme-ui",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "4.0.0-alpha.4",
|
|
4
|
+
"description": "Nuxt UI theme for Open Web Desktop",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"owd-client",
|
|
7
|
+
"owd-themes",
|
|
8
|
+
"owd-modules"
|
|
9
|
+
],
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"type": "module",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/types.d.mts",
|
|
15
|
+
"development": "./src/module.ts",
|
|
16
|
+
"import": "./dist/module.mjs",
|
|
17
|
+
"default": "./dist/module.mjs"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"main": "./dist/module.mjs",
|
|
21
|
+
"typesVersions": {
|
|
22
|
+
"*": {
|
|
23
|
+
".": [
|
|
24
|
+
"./dist/types.d.mts"
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"src"
|
|
31
|
+
],
|
|
32
|
+
"nx": {
|
|
33
|
+
"name": "theme-nuxt"
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"prepack": "nuxt-module-build build",
|
|
37
|
+
"dev": "pnpm run dev:prepare",
|
|
38
|
+
"dev:prepare": "nuxt-module-build build --stub"
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@nuxt/kit": "^4.4.4",
|
|
42
|
+
"@owdproject/nuxt-kit-nuxt-ui": "^4.0.0-alpha.3",
|
|
43
|
+
"defu": "^6.1.4",
|
|
44
|
+
"@owdproject/nuxt": "^4.0.0-alpha.3"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@nuxt/devtools": "^3.2.4",
|
|
48
|
+
"@nuxt/module-builder": "^1.0.2",
|
|
49
|
+
"@nuxt/schema": "^4.4.4",
|
|
50
|
+
"@owdproject/core": "^4.0.0-alpha.3",
|
|
51
|
+
"@owdproject/nuxt-module-fs": "^4.0.0-alpha.3",
|
|
52
|
+
"nuxt": "^4.4.4",
|
|
53
|
+
"typescript": "catalog:"
|
|
54
|
+
},
|
|
55
|
+
"peerDependencies": {
|
|
56
|
+
"@owdproject/core": "^4.0.0-alpha.3",
|
|
57
|
+
"@owdproject/nuxt-kit-nuxt-ui": "^4.0.0-alpha.3",
|
|
58
|
+
"@owdproject/nuxt-module-fs": "^4.0.0-alpha.3",
|
|
59
|
+
"nuxt": "^4.4.4",
|
|
60
|
+
"@owdproject/nuxt": "^4.0.0-alpha.3"
|
|
61
|
+
},
|
|
62
|
+
"peerDependenciesMeta": {
|
|
63
|
+
"@owdproject/nuxt-module-fs": {
|
|
64
|
+
"optional": true
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
"publishConfig": {
|
|
68
|
+
"access": "public",
|
|
69
|
+
"tag": "alpha",
|
|
70
|
+
"registry": "https://registry.npmjs.org/"
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default {}
|
package/src/module.ts
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs'
|
|
2
|
+
import {
|
|
3
|
+
createResolver,
|
|
4
|
+
addComponentsDir,
|
|
5
|
+
installModule,
|
|
6
|
+
addImportsDir,
|
|
7
|
+
addPlugin,
|
|
8
|
+
} from '@nuxt/kit'
|
|
9
|
+
import { defineDesktopTheme } from '@owdproject/nuxt'
|
|
10
|
+
import {
|
|
11
|
+
registerTailwindPath,
|
|
12
|
+
registerThemeTailwindPath,
|
|
13
|
+
} from '@owdproject/nuxt-kit-nuxt-ui/kit/registerTailwindPath'
|
|
14
|
+
import { installNuxtBuiltInApps } from './runtime/apps/installBuiltInApps'
|
|
15
|
+
|
|
16
|
+
export default defineDesktopTheme({
|
|
17
|
+
meta: {
|
|
18
|
+
name: 'desktop-theme-nuxt',
|
|
19
|
+
},
|
|
20
|
+
defaults: {
|
|
21
|
+
name: 'nuxt',
|
|
22
|
+
systemBar: {
|
|
23
|
+
enabled: true,
|
|
24
|
+
position: 'top',
|
|
25
|
+
startButton: true,
|
|
26
|
+
},
|
|
27
|
+
windows: {
|
|
28
|
+
position: 'fixed',
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
async setup(_options, nuxt) {
|
|
32
|
+
const { resolve } = createResolver(import.meta.url)
|
|
33
|
+
|
|
34
|
+
// Install the Nuxt UI kit module
|
|
35
|
+
await installModule('@owdproject/nuxt-kit-nuxt-ui')
|
|
36
|
+
|
|
37
|
+
// Register Tailwind content scan paths for theme-nuxt components and pages
|
|
38
|
+
registerThemeTailwindPath(nuxt, import.meta.url)
|
|
39
|
+
registerTailwindPath(nuxt, resolve('./runtime/pages/**/*.{vue,mjs,ts}'))
|
|
40
|
+
|
|
41
|
+
// Add theme components
|
|
42
|
+
addComponentsDir({
|
|
43
|
+
path: resolve('./runtime/components'),
|
|
44
|
+
pathPrefix: false,
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
// Register i18n module localization if present
|
|
48
|
+
nuxt.hook('i18n:registerModule', (register) => {
|
|
49
|
+
register({
|
|
50
|
+
langDir: resolve('./i18n'),
|
|
51
|
+
locales: [
|
|
52
|
+
{
|
|
53
|
+
code: 'en',
|
|
54
|
+
file: existsSync(resolve('./i18n/locales/en.js')) ? 'locales/en.js' : 'locales/en.ts',
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
})
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
// Register theme dirs
|
|
61
|
+
addImportsDir(resolve('./runtime/composables'))
|
|
62
|
+
addImportsDir(resolve('./runtime/consts'))
|
|
63
|
+
addImportsDir(resolve('./runtime/stores'))
|
|
64
|
+
addImportsDir(resolve('./runtime/utils'))
|
|
65
|
+
|
|
66
|
+
// Install built-in apps (Explorer, Calculator, Notepad)
|
|
67
|
+
installNuxtBuiltInApps(nuxt, import.meta.url)
|
|
68
|
+
},
|
|
69
|
+
})
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
id: 'org.owdproject.calculator',
|
|
3
|
+
title: 'Calculator',
|
|
4
|
+
singleton: false,
|
|
5
|
+
icon: 'i-heroicons-calculator',
|
|
6
|
+
provides: {
|
|
7
|
+
name: 'calculator',
|
|
8
|
+
entry: 'calculator',
|
|
9
|
+
},
|
|
10
|
+
windows: {
|
|
11
|
+
main: {
|
|
12
|
+
component: () => import('./components/Window/WindowCalculator.vue'),
|
|
13
|
+
resizable: false,
|
|
14
|
+
size: {
|
|
15
|
+
width: 260,
|
|
16
|
+
height: 420,
|
|
17
|
+
},
|
|
18
|
+
position: {
|
|
19
|
+
x: 200,
|
|
20
|
+
y: 150,
|
|
21
|
+
z: 0,
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
entries: {
|
|
26
|
+
calculator: {
|
|
27
|
+
command: 'calculator',
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
commands: {
|
|
31
|
+
calculator: (app: any) => {
|
|
32
|
+
app.openWindow('main')
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
|
|
4
|
+
defineProps<{
|
|
5
|
+
window: any
|
|
6
|
+
}>()
|
|
7
|
+
|
|
8
|
+
const display = ref('0')
|
|
9
|
+
const equation = ref('')
|
|
10
|
+
const isFinished = ref(false)
|
|
11
|
+
|
|
12
|
+
const buttons = [
|
|
13
|
+
['C', '(', ')', '/'],
|
|
14
|
+
['7', '8', '9', '*'],
|
|
15
|
+
['4', '5', '6', '-'],
|
|
16
|
+
['1', '2', '3', '+'],
|
|
17
|
+
['0', '.', '=', '']
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
function handleClick(val: string) {
|
|
21
|
+
if (val === '=') {
|
|
22
|
+
calculate()
|
|
23
|
+
} else if (val === 'C') {
|
|
24
|
+
clear()
|
|
25
|
+
} else if (val === '') {
|
|
26
|
+
// Spacer button
|
|
27
|
+
} else {
|
|
28
|
+
append(val)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function append(val: string) {
|
|
33
|
+
if (isFinished.value) {
|
|
34
|
+
display.value = ''
|
|
35
|
+
isFinished.value = false
|
|
36
|
+
}
|
|
37
|
+
if (display.value === '0' && val !== '.') {
|
|
38
|
+
display.value = val
|
|
39
|
+
} else {
|
|
40
|
+
display.value += val
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function clear() {
|
|
45
|
+
display.value = '0'
|
|
46
|
+
equation.value = ''
|
|
47
|
+
isFinished.value = false
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function calculate() {
|
|
51
|
+
try {
|
|
52
|
+
const expr = display.value
|
|
53
|
+
// Safe evaluation for basic arithmetic only
|
|
54
|
+
if (/^[0-9+\-*/().\s]+$/.test(expr)) {
|
|
55
|
+
// eslint-disable-next-line no-eval
|
|
56
|
+
const res = eval(expr)
|
|
57
|
+
equation.value = expr + ' ='
|
|
58
|
+
display.value = String(res)
|
|
59
|
+
isFinished.value = true
|
|
60
|
+
} else {
|
|
61
|
+
display.value = 'Error'
|
|
62
|
+
}
|
|
63
|
+
} catch (e) {
|
|
64
|
+
display.value = 'Error'
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
</script>
|
|
68
|
+
|
|
69
|
+
<template>
|
|
70
|
+
<DesktopWindow :window="window" :content="{ padded: true }">
|
|
71
|
+
<div class="flex h-full min-h-0 flex-col gap-3">
|
|
72
|
+
<!-- Calculator screen -->
|
|
73
|
+
<div
|
|
74
|
+
class="flex-shrink-0 rounded-lg border border-gray-200 bg-white p-3 text-right shadow-inner dark:border-gray-800 dark:bg-gray-900"
|
|
75
|
+
>
|
|
76
|
+
<div class="mb-0.5 h-4 truncate text-xs text-gray-400 dark:text-gray-500">
|
|
77
|
+
{{ equation }}
|
|
78
|
+
</div>
|
|
79
|
+
<div
|
|
80
|
+
class="truncate font-mono text-2xl font-bold text-gray-800 dark:text-gray-100"
|
|
81
|
+
>
|
|
82
|
+
{{ display }}
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
|
|
86
|
+
<!-- Buttons grid -->
|
|
87
|
+
<div class="grid grid-cols-4 grid-rows-5 gap-2 flex-1 min-h-0">
|
|
88
|
+
<template v-for="(row, rIdx) in buttons" :key="rIdx">
|
|
89
|
+
<template v-for="(btn, bIdx) in row" :key="bIdx">
|
|
90
|
+
<UButton
|
|
91
|
+
v-if="btn !== ''"
|
|
92
|
+
:label="btn"
|
|
93
|
+
class="flex h-full w-full items-center justify-center text-sm font-semibold"
|
|
94
|
+
:color="btn === '=' ? 'primary' : btn === 'C' ? 'red' : ['/', '*', '-', '+'].includes(btn) ? 'orange' : 'gray'"
|
|
95
|
+
variant="solid"
|
|
96
|
+
@click="handleClick(btn)"
|
|
97
|
+
/>
|
|
98
|
+
<div v-else />
|
|
99
|
+
</template>
|
|
100
|
+
</template>
|
|
101
|
+
</div>
|
|
102
|
+
</div>
|
|
103
|
+
</DesktopWindow>
|
|
104
|
+
</template>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { defineNuxtPlugin } from 'nuxt/app'
|
|
2
|
+
import { defineDesktopApp } from '@owdproject/nuxt/kit/defineDesktopApp'
|
|
3
|
+
import configAppCalculator from './app.config'
|
|
4
|
+
|
|
5
|
+
export default defineNuxtPlugin({
|
|
6
|
+
name: 'desktop-theme-nuxt-calculator',
|
|
7
|
+
dependsOn: ['pinia', 'desktop-shell-init'],
|
|
8
|
+
async setup() {
|
|
9
|
+
if (import.meta.server) return
|
|
10
|
+
await defineDesktopApp(configAppCalculator)
|
|
11
|
+
},
|
|
12
|
+
})
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
id: 'org.owdproject.explorer',
|
|
3
|
+
title: 'Explorer',
|
|
4
|
+
singleton: false,
|
|
5
|
+
icon: 'i-heroicons-folder-open',
|
|
6
|
+
provides: {
|
|
7
|
+
name: 'explorer',
|
|
8
|
+
entry: 'explorer',
|
|
9
|
+
},
|
|
10
|
+
windows: {
|
|
11
|
+
main: {
|
|
12
|
+
component: () => import('./components/Window/WindowExplorer.vue'),
|
|
13
|
+
resizable: true,
|
|
14
|
+
size: {
|
|
15
|
+
width: 720,
|
|
16
|
+
height: 480,
|
|
17
|
+
minWidth: 560,
|
|
18
|
+
minHeight: 440,
|
|
19
|
+
},
|
|
20
|
+
position: {
|
|
21
|
+
x: 120,
|
|
22
|
+
y: 80,
|
|
23
|
+
z: 0,
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
entries: {
|
|
28
|
+
explorer: {
|
|
29
|
+
command: 'explorer /',
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
commands: {
|
|
33
|
+
explorer: (app: any, args: any) => {
|
|
34
|
+
const a = args as { _?: string[] } | undefined
|
|
35
|
+
const pathArg = a?._?.[1]
|
|
36
|
+
app.openWindow('main', undefined, { path: pathArg ?? '/' })
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { useI18n } from 'vue-i18n'
|
|
3
|
+
import { inject } from 'vue'
|
|
4
|
+
import { DESKTOP_DIALOG_PROVIDER_KEY } from '@owdproject/nuxt/runtime/constants/desktopShellKeys'
|
|
5
|
+
import { createExplorerWindowMenuItems } from '@owdproject/nuxt-module-fs/runtime/composables/useExplorerWindowMenu'
|
|
6
|
+
|
|
7
|
+
const props = defineProps<{
|
|
8
|
+
window: any
|
|
9
|
+
}>()
|
|
10
|
+
|
|
11
|
+
const { t } = useI18n()
|
|
12
|
+
const dialogs = inject<any>(DESKTOP_DIALOG_PROVIDER_KEY)
|
|
13
|
+
|
|
14
|
+
const explorerMenu = createExplorerWindowMenuItems(
|
|
15
|
+
() => props.window,
|
|
16
|
+
t,
|
|
17
|
+
() => {
|
|
18
|
+
dialogs?.alert('Nuxt UI theme explorer powered by module-fs!', { title: 'About Explorer' })
|
|
19
|
+
}
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
props.window.setMenu(explorerMenu)
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<template>
|
|
26
|
+
<DesktopExplorerWorkspace
|
|
27
|
+
:window="window"
|
|
28
|
+
frame-class="nuxt-explorer-frame"
|
|
29
|
+
>
|
|
30
|
+
<template #nav>
|
|
31
|
+
<DesktopWindowNav />
|
|
32
|
+
</template>
|
|
33
|
+
</DesktopExplorerWorkspace>
|
|
34
|
+
</template>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { defineNuxtPlugin } from 'nuxt/app'
|
|
2
|
+
import { defineDesktopApp } from '@owdproject/nuxt/kit/defineDesktopApp'
|
|
3
|
+
import configAppExplorer from './app.config'
|
|
4
|
+
|
|
5
|
+
export default defineNuxtPlugin({
|
|
6
|
+
name: 'desktop-theme-nuxt-explorer',
|
|
7
|
+
dependsOn: ['pinia', 'desktop-shell-init'],
|
|
8
|
+
async setup() {
|
|
9
|
+
if (import.meta.server) return
|
|
10
|
+
await defineDesktopApp(configAppExplorer)
|
|
11
|
+
},
|
|
12
|
+
})
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import {
|
|
2
|
+
addComponentsDir,
|
|
3
|
+
addPlugin,
|
|
4
|
+
createResolver,
|
|
5
|
+
} from '@nuxt/kit'
|
|
6
|
+
import type { Nuxt } from '@nuxt/schema'
|
|
7
|
+
import { registerTailwindPath } from '@owdproject/nuxt-kit-nuxt-ui/kit/registerTailwindPath'
|
|
8
|
+
import { NUXT_THEME_BUILTIN_APPS } from './registry'
|
|
9
|
+
|
|
10
|
+
/** Register autoload built-in apps from `runtime/apps/<name>/`. */
|
|
11
|
+
export function installNuxtBuiltInApps(nuxt: Nuxt, themeRoot: string) {
|
|
12
|
+
const { resolve } = createResolver(themeRoot)
|
|
13
|
+
|
|
14
|
+
for (const app of NUXT_THEME_BUILTIN_APPS) {
|
|
15
|
+
if (!app.autoload) continue
|
|
16
|
+
if (app.when && !app.when(nuxt)) continue
|
|
17
|
+
|
|
18
|
+
const appRoot = resolve(`./runtime/apps/${app.name}`)
|
|
19
|
+
|
|
20
|
+
addPlugin({
|
|
21
|
+
src: resolve(appRoot, 'plugin'),
|
|
22
|
+
mode: 'client',
|
|
23
|
+
name: `desktop-theme-nuxt-${app.name}`,
|
|
24
|
+
order: 1,
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
addComponentsDir({
|
|
28
|
+
path: resolve(appRoot, 'components'),
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
registerTailwindPath(
|
|
32
|
+
nuxt,
|
|
33
|
+
resolve(appRoot, 'components/**/*.{vue,mjs,ts}'),
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
id: 'org.owdproject.notepad',
|
|
3
|
+
title: 'Notepad',
|
|
4
|
+
singleton: false,
|
|
5
|
+
icon: 'i-heroicons-document-text',
|
|
6
|
+
provides: {
|
|
7
|
+
name: 'notepad',
|
|
8
|
+
entry: 'notepad',
|
|
9
|
+
},
|
|
10
|
+
windows: {
|
|
11
|
+
main: {
|
|
12
|
+
component: () => import('./components/Window/WindowNotepad.vue'),
|
|
13
|
+
resizable: true,
|
|
14
|
+
size: {
|
|
15
|
+
width: 600,
|
|
16
|
+
height: 400,
|
|
17
|
+
},
|
|
18
|
+
position: {
|
|
19
|
+
x: 180,
|
|
20
|
+
y: 120,
|
|
21
|
+
z: 0,
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
entries: {
|
|
26
|
+
notepad: {
|
|
27
|
+
command: 'notepad',
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
commands: {
|
|
31
|
+
notepad: (app: any) => {
|
|
32
|
+
app.openWindow('main')
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
}
|