@owdproject/core
Version:
Nuxt Desktop module for browser desktop experiences (windows, shell, apps)
532 lines (405 loc) • 10.8 kB
TypeScript
import type { Nuxt } from '@nuxt/schema'
import type { ShallowRef } from 'vue'
declare module 'nuxt/schema' {
interface PublicRuntimeConfig {
desktop: DesktopConfig
}
}
declare global {
interface IApplicationManager {
apps: Map<string, IApplicationController>
get appsEntries(): Reactive<ApplicationEntry[]>
get appsRunning(): Reactive<IApplicationController[]>
get windowsOpened(): Reactive<Map<string, IWindowController>>
get appCategories(): string[]
get appsByCategory(): { [category: string]: IApplicationController[] }
defineApp(
id: string,
config: ApplicationConfig,
): Promise<IApplicationController>
closeApp(id: string): void
launchAppEntry(
id: string,
entry: string,
): Promise<IApplicationController | undefined | void>
execAppCommand(
id: string,
command: string,
meta: undefined | any,
): Promise<CommandOutput | void>
isAppDefined(id: string): boolean
isAppRunning(id: string): boolean
}
type ApplicationCommand = (app: IApplicationController, args: any) => void
interface ApplicationConfig {
id: string
title: string
icon?: string
category?: string
version?: string
description?: string
provides?: ApplicationConfigProvide
singleton?: boolean
meta?: IApplicationMeta
permissions?: ApplicationPermission[]
windows?: { [key: string]: WindowConfig }
entries: { [key: string]: ApplicationEntry }
commands?: { [key: string]: ApplicationCommand }
terminal?: { [commandName: string]: Omit<TerminalCommand, 'name' | 'applicationId'> }
onReady?(app: IApplicationController): void | Promise<void>
onLaunch?(app: IApplicationController): void | Promise<void>
onRestore?(app: IApplicationController): void | Promise<void>
onClose?(app: IApplicationController): void | Promise<void>
}
interface ApplicationConfigProvide {
name: string
entry: string
command?: string
}
type IApplicationMeta = { [key: string]: any }
interface IApplicationController {
id: string
config: ApplicationConfig
get meta(): { [key: string]: any }
store: Pinia
windows: Map<string, IWindowController>
openWindowCount: ShallowRef<number>
isRunning: boolean
setRunning(value: boolean): void
initApplication(): Promise<void>
restoreApplication(): Promise<boolean>
getWindowsByModel(model: string): IWindowController[]
getFirstWindowByModel(model: string): IWindowController | undefined
openWindow(
model: string,
windowStoredState?: WindowStoredState,
options?: {
isRestoring?: boolean
},
)
closeWindow(windowId: string): void
closeAllWindows(): void
execCommand(command: string): Promise<CommandOutput | void>
// deprecated
get windowsOpened(): Reactive<Map<string, IWindowController>>
}
export interface IWindowController {
application: IApplicationController
instanced: boolean
model: string
config: WindowConfig
override: WindowOverride
get state(): WindowState
// common
get title(): string
get windowTitle(): string
get icon(): string | undefined
// sizes
get size(): WindowSize
get position(): WindowPosition | undefined
// minimize
get isMinimizable(): boolean
// maximize
get isMaximizable(): boolean
get isMaximized(): boolean
// destroy
get isDestroyable(): boolean
// draggable
get isDraggable(): boolean
// resizable
get isResizable(): boolean
get actions(): {
// position
setActive(value: boolean)
setFocus(value: boolean)
bringToFront()
setPosition(data: WindowPosition)
// size
setSize(data: WindowSize)
// minimize
minimize(): boolean
// maximize
toggleMaximize(): boolean
maximize(): boolean
unmaximize(): boolean
// layout (snap / tiled zones)
setLayout(layout: WindowLayout): boolean
clearLayout(): boolean
saveBoundsBeforeLayout(): void
// destroy
destroy(): boolean
// workspace
setWorkspace(workspaceId: string)
// override
setTitleOverride(title: string | undefined): void
resetTitleOverride(): void
setWindowTitleOverride(title: string | undefined): void
resetWindowTitleOverride(): void
}
/** Payload restored with window state (e.g. explorer cwd in `path`). */
get meta(): { path?: string } & Record<string, unknown>
/** Chrome menu model ({@link DesktopMenuItem}[]; Menubar-compatible). */
menu: import('../runtime/types/desktopMenu').DesktopMenuItem[]
setMenu(menu: unknown[]): void
destroy(): boolean
/** Set by module-fs when an explorer surface mounts on this window. */
fsExplorer?: any
}
export interface WindowContent {
padded?: boolean
centered?: boolean
}
export interface WindowConfig {
title?: string
category?: string
icon?: string
component?: Raw<Component>
// position
position?: WindowPosition
// sizes
size: WindowSize
// minimize
minimizable?: boolean
// maximize
maximized?: boolean
maximizable?: boolean
// destroy
destroyable?: boolean
// draggable
draggable?: boolean
// draggable
resizable?: boolean
overridable?: Partial<
Record<
| 'position'
| 'size'
| 'maximized'
| 'draggable'
| 'resizable'
| 'destroyable'
| 'minimizable',
boolean
>
>
}
interface WindowStoredState {
model: string
state: WindowState
meta: any
}
interface WindowOverride {
title?: undefined | string
windowTitle?: undefined | string
icon?: undefined | string
}
interface WindowState {
id: string
createdAt: number
category?: string
workspace: string
// position
position?: WindowPosition
// sizes
size?: WindowSize
// focused
focused: boolean
// minimize
active?: boolean
minimizable?: boolean
// maximize
maximized?: boolean
maximizable?: boolean
// destroy
destroyable?: boolean
// draggable
draggable?: boolean
// draggable
resizable?: boolean
/** Snap zone layout; `normal` is unset or explicit restore. */
layout?: WindowLayout
/** Bounds saved before first snap so restore can revert geometry. */
boundsBeforeLayout?: WindowBounds
}
export type WindowLayout =
| 'normal'
| 'maximize'
| 'bottom-half'
| 'left-half'
| 'right-half'
| 'top-left'
| 'top-right'
| 'bottom-left'
| 'bottom-right'
export interface WindowBounds {
x: number
y: number
width: number
height: number
}
export interface DesktopWorkAreaRect {
x: number
y: number
width: number
height: number
}
interface WindowSize {
width?: WindowSizeValue
height?: WindowSizeValue
minWidth?: WindowSizeValue
minHeight?: WindowSizeValue
maxWidth?: WindowSizeValue
maxHeight?: WindowSizeValue
}
interface WindowPosition {
x?: number
y?: number
z?: number
}
type WindowSizeValue = number | string | undefined
interface ApplicationEntry {
title?: string
icon?: string
category?: string
visibility?: ApplicationEntryVisibility
command: string | any
}
interface ApplicationEntryWithInherited extends ApplicationEntry {
application: IApplicationController
visibility: ApplicationEntryVisibility
}
type ApplicationEntryVisibility = 'primary' | 'secondary' | 'hidden'
// DESKTOP
interface IDesktopManager {
defaultApps: import('vue').ComputedRef<Record<string, DefaultAppConfig>>
getDefaultApp(feature: string): DefaultAppConfig | undefined
setDefaultApp(
feature: string,
application: IApplicationController,
entry: string,
): void
}
interface DocsModuleUserSourceConfig {
cwd: string
prefix?: string
include?: string
exclude?: string[]
}
interface DocsModuleConfig {
basePath?: string
title?: string
sources?: DocsModuleUserSourceConfig[]
}
interface DesktopConfig {
coreVersion?: string
theme?: string
modules?: string[]
apps?: string[]
docs?: DocsModuleConfig
name?: string
defaultApps?: DefaultAppsConfig
features?: string[]
systemBar?: DesktopSystemBarConfig
dockBar?: DesktopDockBarConfig
workspaces?: DesktopWorkspacesConfig
windows?: DesktopWindowsConfig
}
interface DesktopWindowsConfig {
position: 'relative' | 'absolute' | 'fixed'
}
interface DesktopDockBarConfig {
enabled?: boolean
position?: 'top' | 'bottom'
}
interface DesktopSystemBarConfig {
enabled?: boolean
position?: 'top' | 'bottom'
startButton?: boolean
}
interface DesktopWorkspacesConfig {
enabled?: boolean
}
// TERMINAL
type TerminalCommandArg = {
name: string
description?: string
required?: boolean
}
type TerminalCommandOption = {
flag: string
description?: string
}
type TerminalCommand = {
name: string
applicationId: string
description?: string
usage?: string
args?: TerminalCommandArg[]
options?: TerminalCommandOption[]
}
interface ITerminalManager {
addCommand(command: TerminalCommand): void
listCommands(): string[]
getCommand(name: string): TerminalCommand | undefined
getAllCommands(): TerminalCommand[]
execCommand(input: string): Promise<CommandOutput | void>
}
interface CommandOutput {
message: string
isError?: boolean
}
// DEFAULT APP
interface DefaultAppsConfig {
terminal?: DefaultAppConfig
browser?: DefaultAppConfig
editor?: DefaultAppConfig
[key: string]: DefaultAppConfig
}
/** Stored default for a feature: which app and which entry key to use. */
interface DefaultAppConfig {
applicationId: string
entry: string
}
module '*.vue' {
import type { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}
}
export function defineDesktopApp(config: ApplicationConfig)
export function defineDesktopConfig(config: DesktopConfig)
export function defineDesktopModule(
definition: import('@nuxt/kit').NuxtModule<
Record<string, unknown>,
Record<string, unknown>,
false
> & { meta: { name: string; configKey: string } },
): ReturnType<typeof import('@nuxt/kit').defineNuxtModule>
export function defineDesktopTheme(
definition: import('@nuxt/kit').NuxtModule<
Record<string, unknown>,
Record<string, unknown>,
false
>,
): ReturnType<typeof import('@nuxt/kit').defineNuxtModule>
export function setDesktopExtensionConfig(
nuxt: Nuxt,
configKey: string,
resolved: Record<string, unknown>,
): void
export function mergeDesktopExtensionConfig(
nuxt: Nuxt,
configKey: string,
partial: Record<string, unknown>,
): void
export function useDesktopConfig(): import('vue').ComputedRef<DesktopConfig>
export function useDesktopExtension<K extends string>(
key: K,
): import('vue').ComputedRef<unknown>
export function hasDesktopModule(
pkg: string,
): import('vue').ComputedRef<boolean>
export function hasDesktopApp(pkg: string): import('vue').ComputedRef<boolean>
export function hasDesktopExtension(
key: string,
): import('vue').ComputedRef<boolean>
export {}