@lapis-notes/workspace 0.2.1 → 0.3.0

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.
Files changed (39) hide show
  1. package/CHANGELOG.md +103 -12
  2. package/README.md +4 -0
  3. package/dist/WorkspaceShell.svelte +19 -2
  4. package/dist/WorkspaceShell.svelte.d.ts +3 -1
  5. package/dist/desktop/DesktopRecoveryBanner.css +46 -0
  6. package/dist/desktop/DesktopRecoveryBanner.svelte +70 -0
  7. package/dist/desktop/DesktopRecoveryBanner.svelte.d.ts +15 -0
  8. package/dist/desktop/DesktopVaultLauncher.svelte +278 -0
  9. package/dist/desktop/DesktopVaultLauncher.svelte.d.ts +17 -0
  10. package/dist/desktop/DesktopVaultLauncherDialogs.svelte +136 -0
  11. package/dist/desktop/DesktopVaultLauncherDialogs.svelte.d.ts +9 -0
  12. package/dist/desktop/DesktopWorkspaceStartup.css +8 -0
  13. package/dist/desktop/DesktopWorkspaceStartup.svelte +34 -0
  14. package/dist/desktop/DesktopWorkspaceStartup.svelte.d.ts +9 -0
  15. package/dist/desktop/desktop-vault-launcher-controls.css +142 -0
  16. package/dist/desktop/desktop-vault-launcher.css +181 -0
  17. package/dist/desktop/desktop-vault-launcher.d.ts +30 -0
  18. package/dist/desktop/desktop-vault-launcher.js +26 -0
  19. package/dist/desktop/desktop-vault-launcher.svelte.d.ts +36 -0
  20. package/dist/desktop/desktop-vault-launcher.svelte.js +140 -0
  21. package/dist/desktop/lapis-logo.svg +471 -0
  22. package/dist/file-conflicts/ConflictReview.svelte +145 -0
  23. package/dist/file-conflicts/ConflictReview.svelte.d.ts +8 -0
  24. package/dist/file-conflicts/ConflictReviewControls.svelte +66 -0
  25. package/dist/file-conflicts/ConflictReviewControls.svelte.d.ts +12 -0
  26. package/dist/file-conflicts/conflict-review-state.svelte.d.ts +22 -0
  27. package/dist/file-conflicts/conflict-review-state.svelte.js +59 -0
  28. package/dist/file-conflicts/conflict-review-view.d.ts +19 -0
  29. package/dist/file-conflicts/conflict-review-view.js +50 -0
  30. package/dist/file-conflicts/register-conflict-reviews.d.ts +7 -0
  31. package/dist/file-conflicts/register-conflict-reviews.js +132 -0
  32. package/dist/index.d.ts +6 -0
  33. package/dist/index.js +4 -0
  34. package/dist/plugin-management/CorePluginsSettingsPage.svelte +47 -16
  35. package/dist/plugin-management/PluginBrowser.svelte +16 -1
  36. package/dist/plugin-management/PluginRegistryToolbar.svelte.d.ts +1 -1
  37. package/dist/plugin-management/plugin-registry-controller.svelte.js +5 -1
  38. package/dist/plugin-management/register-plugin-management-settings.js +7 -6
  39. package/package.json +5 -4
@@ -0,0 +1,136 @@
1
+ <script lang="ts">
2
+ import Search from "@lucide/svelte/icons/search";
3
+ import type { VaultProfile } from "@lapis-notes/api";
4
+ import * as Button from "@lapismd/design-core/shadcn/button";
5
+ import * as CommandView from "@lapismd/design-core/shadcn/command-view";
6
+ import * as Dialog from "@lapismd/design-core/shadcn/dialog";
7
+ import * as Input from "@lapismd/design-core/shadcn/input";
8
+ import { desktopAppearanceOptions } from "./desktop-vault-launcher";
9
+ import type { DesktopVaultLauncherState } from "./desktop-vault-launcher.svelte";
10
+ let {
11
+ model,
12
+ onOpenRecent,
13
+ }: {
14
+ model: DesktopVaultLauncherState;
15
+ onOpenRecent(profile: VaultProfile): Promise<void>;
16
+ } = $props();
17
+ $effect(() => {
18
+ if (!model.recentVaultDialogOpen) model.recentVaultQuery = "";
19
+ });
20
+ $effect(() => {
21
+ if (!model.renameDialogOpen) {
22
+ model.renameTarget = null;
23
+ model.renameDialogName = "";
24
+ }
25
+ });
26
+ </script>
27
+
28
+ <Dialog.Root bind:open={model.settingsOpen}>
29
+ <Dialog.Content class="desktop-launcher__settings">
30
+ <Dialog.Header>
31
+ <Dialog.Title>Desktop Settings</Dialog.Title>
32
+ <Dialog.Description
33
+ >Choose how the vault chooser follows light and dark mode.</Dialog.Description
34
+ >
35
+ </Dialog.Header>
36
+ <div class="desktop-launcher__options">
37
+ {#each desktopAppearanceOptions as option (option.value)}
38
+ <Button.Root
39
+ variant={model.appearanceMode === option.value
40
+ ? "default"
41
+ : "outline"}
42
+ class={`desktop-launcher__option${model.appearanceMode === option.value ? "" : " desktop-launcher__outline"}`}
43
+ onclick={() => void model.updateAppearance(option.value)}
44
+ >
45
+ <span class="desktop-launcher__option-copy">
46
+ <span class="desktop-launcher__label">{option.label}</span>
47
+ <span class="desktop-launcher__hint">{option.description}</span>
48
+ </span>
49
+ </Button.Root>
50
+ {/each}
51
+ </div>
52
+ </Dialog.Content>
53
+ </Dialog.Root>
54
+
55
+ <Dialog.Root bind:open={model.recentVaultDialogOpen}>
56
+ <Dialog.Content class="desktop-launcher__command" showCloseButton={false}>
57
+ <Dialog.Header class="sr-only">
58
+ <Dialog.Title>Recent Projects</Dialog.Title>
59
+ <Dialog.Description>Search and open a recent vault</Dialog.Description>
60
+ </Dialog.Header>
61
+ <CommandView.Root shouldFilter={false} label="Search recent vaults">
62
+ <CommandView.Input
63
+ bind:value={model.recentVaultQuery}
64
+ placeholder="Search recent vaults..."
65
+ aria-label="Search recent vaults"
66
+ autocomplete="off"
67
+ spellcheck="false"
68
+ />
69
+ <CommandView.List aria-label="Recent projects">
70
+ <CommandView.Empty>No matching recent vaults</CommandView.Empty>
71
+ {#if model.filteredRecentVaults.length > 0}
72
+ <CommandView.Group>
73
+ {#each model.filteredRecentVaults as entry (entry.profile.id)}
74
+ <CommandView.Item
75
+ value={`${entry.name} ${entry.location}`}
76
+ onSelect={() =>
77
+ void model.invoke(() => onOpenRecent(entry.profile))}
78
+ >
79
+ <CommandView.ItemIcon>
80
+ <Search />
81
+ </CommandView.ItemIcon>
82
+ <CommandView.ItemLabel>{entry.name}</CommandView.ItemLabel>
83
+ <CommandView.ItemDescription>
84
+ {entry.location}
85
+ </CommandView.ItemDescription>
86
+ </CommandView.Item>
87
+ {/each}
88
+ </CommandView.Group>
89
+ {/if}
90
+ </CommandView.List>
91
+ </CommandView.Root>
92
+ </Dialog.Content>
93
+ </Dialog.Root>
94
+
95
+ <Dialog.Root bind:open={model.renameDialogOpen}>
96
+ <Dialog.Content class="desktop-launcher__rename">
97
+ <Dialog.Header>
98
+ <Dialog.Title>Rename vault</Dialog.Title>
99
+ <Dialog.Description
100
+ >Update the stored vault name used in recent projects and app URLs.</Dialog.Description
101
+ >
102
+ </Dialog.Header>
103
+ <form
104
+ class="desktop-launcher__form"
105
+ onsubmit={(event) => {
106
+ event.preventDefault();
107
+ void model.submitRename();
108
+ }}
109
+ >
110
+ <label class="desktop-launcher__field">
111
+ <span>Name</span>
112
+ <Input.Root
113
+ bind:value={model.renameDialogName}
114
+ autocomplete="off"
115
+ autofocus
116
+ />
117
+ </label>
118
+ <Dialog.Footer>
119
+ <Button.Root
120
+ type="button"
121
+ variant="ghost"
122
+ onclick={() => (model.renameDialogOpen = false)}
123
+ >
124
+ Cancel
125
+ </Button.Root>
126
+ <Button.Root
127
+ type="submit"
128
+ disabled={!model.renameDialogName.trim() ||
129
+ model.activeActionId === model.renameTarget?.id}
130
+ >
131
+ Save
132
+ </Button.Root>
133
+ </Dialog.Footer>
134
+ </form>
135
+ </Dialog.Content>
136
+ </Dialog.Root>
@@ -0,0 +1,9 @@
1
+ import type { VaultProfile } from "@lapis-notes/api";
2
+ import type { DesktopVaultLauncherState } from "./desktop-vault-launcher.svelte";
3
+ type $$ComponentProps = {
4
+ model: DesktopVaultLauncherState;
5
+ onOpenRecent(profile: VaultProfile): Promise<void>;
6
+ };
7
+ declare const DesktopVaultLauncherDialogs: import("svelte").Component<$$ComponentProps, {}, "">;
8
+ type DesktopVaultLauncherDialogs = ReturnType<typeof DesktopVaultLauncherDialogs>;
9
+ export default DesktopVaultLauncherDialogs;
@@ -0,0 +1,8 @@
1
+ .desktop-workspace-startup__logo {
2
+ width: 5rem;
3
+ height: 5rem;
4
+ object-fit: contain;
5
+ filter: drop-shadow(
6
+ 0 1rem 2rem color-mix(in srgb, var(--ui-workspace-accent) 18%, transparent)
7
+ );
8
+ }
@@ -0,0 +1,34 @@
1
+ <script lang="ts">
2
+ import {
3
+ WorkspaceStartup,
4
+ type WorkspaceStartupFailure,
5
+ type WorkspaceStartupTask,
6
+ } from "@lapismd/design-core/workspace/startup";
7
+ import lapisLogo from "./lapis-logo.svg";
8
+ import "./DesktopWorkspaceStartup.css";
9
+
10
+ let {
11
+ tasks = [],
12
+ failure = null,
13
+ }: {
14
+ tasks?: WorkspaceStartupTask[];
15
+ failure?: WorkspaceStartupFailure | null;
16
+ } = $props();
17
+ </script>
18
+
19
+ {#snippet lapisVisual()}
20
+ <img
21
+ class="desktop-workspace-startup__logo"
22
+ data-ui-component="desktop-workspace-startup"
23
+ data-ui-part="logo"
24
+ src={lapisLogo}
25
+ alt=""
26
+ />
27
+ {/snippet}
28
+
29
+ <WorkspaceStartup
30
+ title="Opening Lapis Notes"
31
+ loadingVisual={lapisVisual}
32
+ {tasks}
33
+ {failure}
34
+ />
@@ -0,0 +1,9 @@
1
+ import { type WorkspaceStartupFailure, type WorkspaceStartupTask } from "@lapismd/design-core/workspace/startup";
2
+ import "./DesktopWorkspaceStartup.css";
3
+ type $$ComponentProps = {
4
+ tasks?: WorkspaceStartupTask[];
5
+ failure?: WorkspaceStartupFailure | null;
6
+ };
7
+ declare const DesktopWorkspaceStartup: import("svelte").Component<$$ComponentProps, {}, "">;
8
+ type DesktopWorkspaceStartup = ReturnType<typeof DesktopWorkspaceStartup>;
9
+ export default DesktopWorkspaceStartup;
@@ -0,0 +1,142 @@
1
+ .desktop-launcher__action[data-ui-component="button"],
2
+ .desktop-launcher__option[data-ui-component="button"] {
3
+ width: 100%;
4
+ height: auto;
5
+ min-width: 0;
6
+ align-items: flex-start;
7
+ justify-content: flex-start;
8
+ white-space: normal;
9
+ border-radius: 0.75rem;
10
+ padding: 1rem;
11
+ text-align: start;
12
+ }
13
+ .desktop-launcher__action-copy,
14
+ .desktop-launcher__option-copy {
15
+ display: flex;
16
+ min-width: 0;
17
+ flex: 1;
18
+ flex-direction: column;
19
+ align-items: flex-start;
20
+ gap: 0.25rem;
21
+ text-align: start;
22
+ }
23
+ .desktop-launcher__hint {
24
+ font-size: 0.75rem;
25
+ font-weight: 400;
26
+ opacity: 0.8;
27
+ }
28
+ .desktop-launcher__icon {
29
+ width: 1rem;
30
+ height: 1rem;
31
+ }
32
+ .desktop-launcher__large-icon {
33
+ width: 1.25rem;
34
+ height: 1.25rem;
35
+ flex-shrink: 0;
36
+ }
37
+ .desktop-launcher__settings-trigger[data-ui-component="button"],
38
+ .desktop-launcher__link[data-ui-component="button"] {
39
+ padding-inline: 0;
40
+ }
41
+ .desktop-launcher__close[data-ui-component="button"] {
42
+ border: 0;
43
+ border-radius: 50%;
44
+ box-shadow: none;
45
+ color: var(--secondary-foreground);
46
+ background: var(--secondary);
47
+ }
48
+ .desktop-launcher__close[data-ui-component="button"]:hover:not(:disabled) {
49
+ color: var(--ui-workspace-panel-action-hover-foreground);
50
+ background: var(--ui-workspace-panel-action-hover-background);
51
+ }
52
+ .desktop-launcher__recent-open {
53
+ display: flex;
54
+ min-width: 0;
55
+ flex: 1;
56
+ align-items: flex-start;
57
+ gap: 0.75rem;
58
+ border: 0;
59
+ border-radius: 0.5rem;
60
+ padding: 0.5rem 0.75rem;
61
+ color: inherit;
62
+ background: transparent;
63
+ font: inherit;
64
+ text-align: start;
65
+ cursor: pointer;
66
+ }
67
+ .desktop-launcher__recent-open:disabled {
68
+ opacity: 0.5;
69
+ cursor: default;
70
+ }
71
+ .desktop-launcher__recent-icon {
72
+ width: 1rem;
73
+ height: 1rem;
74
+ flex-shrink: 0;
75
+ margin-block-start: 0.125rem;
76
+ color: var(--ui-workspace-muted-foreground);
77
+ }
78
+ .desktop-launcher__outline[data-ui-component="button"]:hover:not(:disabled),
79
+ .desktop-launcher__recent-open:hover:not(:disabled) {
80
+ color: var(--ui-workspace-foreground);
81
+ background: var(--background-modifier-active-hover);
82
+ }
83
+ .desktop-launcher__recent-menu {
84
+ display: flex;
85
+ width: 2rem;
86
+ height: 2rem;
87
+ flex-shrink: 0;
88
+ align-items: center;
89
+ justify-content: center;
90
+ margin-block: auto;
91
+ border: 0;
92
+ border-radius: 0.5rem;
93
+ color: var(--ui-workspace-muted-foreground);
94
+ background: transparent;
95
+ }
96
+ .desktop-launcher__recent-menu:hover {
97
+ color: var(--ui-workspace-foreground);
98
+ background: var(--ui-workspace-panel-action-hover-background);
99
+ }
100
+ .desktop-launcher__recent-menu:focus-visible,
101
+ .desktop-launcher__recent-open:focus-visible {
102
+ outline: 3px solid var(--ring);
103
+ outline-offset: 2px;
104
+ }
105
+ .desktop-launcher__settings[data-ui-component="dialog"][data-ui-part="dialog-content"],
106
+ .desktop-launcher__rename[data-ui-component="dialog"][data-ui-part="dialog-content"] {
107
+ top: 50%;
108
+ left: 50%;
109
+ width: min(28rem, calc(100% - 2rem));
110
+ max-width: 28rem;
111
+ max-height: calc(100% - 2rem);
112
+ overflow: auto;
113
+ translate: -50% -50%;
114
+ }
115
+ .desktop-launcher__command[data-ui-component="dialog"][data-ui-part="dialog-content"] {
116
+ top: 20vh;
117
+ left: 50%;
118
+ width: min(34rem, calc(100% - 2rem));
119
+ max-width: 34rem;
120
+ max-height: calc(80vh - 1rem);
121
+ overflow: hidden;
122
+ translate: -50% 0;
123
+ gap: 0;
124
+ padding: 0;
125
+ --ui-command-view-list-max-height: min(20rem, calc(80vh - 6rem));
126
+ }
127
+ .desktop-launcher__options {
128
+ display: grid;
129
+ gap: 0.75rem;
130
+ }
131
+ .desktop-launcher__option[data-ui-component="button"] {
132
+ padding-block: 0.75rem;
133
+ }
134
+ .desktop-launcher__form {
135
+ display: grid;
136
+ gap: 1rem;
137
+ }
138
+ .desktop-launcher__field {
139
+ display: grid;
140
+ gap: 0.5rem;
141
+ font-size: 0.875rem;
142
+ }
@@ -0,0 +1,181 @@
1
+ .desktop-launcher {
2
+ display: flex;
3
+ height: 100%;
4
+ min-height: 100%;
5
+ overflow: auto;
6
+ padding: 2.5rem 1rem;
7
+ color: var(--ui-workspace-foreground);
8
+ background: var(--ui-workspace-background);
9
+ }
10
+ .desktop-launcher__content {
11
+ display: grid;
12
+ width: 100%;
13
+ max-width: 64rem;
14
+ min-width: 0;
15
+ gap: 1.5rem;
16
+ margin: auto;
17
+ }
18
+ .desktop-launcher__header {
19
+ display: flex;
20
+ flex-direction: column;
21
+ justify-content: space-between;
22
+ gap: 1.25rem;
23
+ }
24
+ .desktop-launcher__brand {
25
+ display: flex;
26
+ min-width: 0;
27
+ align-items: center;
28
+ gap: 1rem;
29
+ }
30
+ .desktop-launcher__logo {
31
+ width: 3.5rem;
32
+ height: 3.5rem;
33
+ flex-shrink: 0;
34
+ border: 1px solid
35
+ color-mix(in srgb, var(--ui-workspace-border) 70%, transparent);
36
+ border-radius: 1rem;
37
+ background: var(--ui-workspace-panel-background);
38
+ object-fit: cover;
39
+ box-shadow: 0 1px 2px #0000000d;
40
+ }
41
+ .desktop-launcher__copy {
42
+ min-width: 0;
43
+ }
44
+ .desktop-launcher__eyebrow {
45
+ color: var(--ui-workspace-muted-foreground);
46
+ font-size: 0.75rem;
47
+ font-weight: 600;
48
+ letter-spacing: 0.28em;
49
+ text-transform: uppercase;
50
+ }
51
+ .desktop-launcher__heading {
52
+ margin: 0;
53
+ font-size: 1.5rem;
54
+ font-weight: 600;
55
+ letter-spacing: -0.025em;
56
+ line-height: 1.2;
57
+ }
58
+ .desktop-launcher__description {
59
+ margin: 0.25rem 0 0;
60
+ color: var(--ui-workspace-muted-foreground);
61
+ font-size: 0.875rem;
62
+ }
63
+ .desktop-launcher__header-actions {
64
+ display: flex;
65
+ flex-shrink: 0;
66
+ align-items: center;
67
+ gap: 0.25rem;
68
+ }
69
+ .desktop-launcher__columns {
70
+ display: grid;
71
+ min-width: 0;
72
+ gap: 1.25rem;
73
+ }
74
+ .desktop-launcher__card[data-ui-component="card"] {
75
+ min-width: 0;
76
+ gap: 0;
77
+ --ui-card-border-color: color-mix(
78
+ in srgb,
79
+ var(--ui-workspace-border) 70%,
80
+ transparent
81
+ );
82
+ --ui-card-background: color-mix(
83
+ in srgb,
84
+ var(--ui-workspace-panel-background) 90%,
85
+ transparent
86
+ );
87
+ backdrop-filter: blur(8px);
88
+ }
89
+ .desktop-launcher__card-header {
90
+ padding-inline: 1.5rem;
91
+ padding-block-end: 0;
92
+ }
93
+ .desktop-launcher__card-title {
94
+ font-size: 1.25rem;
95
+ }
96
+ .desktop-launcher__action-list {
97
+ display: grid;
98
+ gap: 0.75rem;
99
+ padding: 0 1.5rem 1.5rem;
100
+ }
101
+ .desktop-launcher__recents-header {
102
+ display: flex;
103
+ align-items: flex-start;
104
+ justify-content: space-between;
105
+ gap: 0.75rem;
106
+ }
107
+ .desktop-launcher__recent-list {
108
+ display: grid;
109
+ gap: 0.5rem;
110
+ padding: 0 1rem 1rem;
111
+ }
112
+ .desktop-launcher__recent {
113
+ display: flex;
114
+ width: 100%;
115
+ align-items: stretch;
116
+ gap: 0.25rem;
117
+ border: 1px solid
118
+ color-mix(in srgb, var(--ui-workspace-border) 60%, transparent);
119
+ border-radius: 0.75rem;
120
+ padding: 0.25rem;
121
+ }
122
+ .desktop-launcher__recent-copy {
123
+ display: flex;
124
+ min-width: 0;
125
+ flex: 1;
126
+ flex-direction: column;
127
+ gap: 0.25rem;
128
+ }
129
+ .desktop-launcher__recent-name,
130
+ .desktop-launcher__location {
131
+ overflow: hidden;
132
+ white-space: nowrap;
133
+ text-overflow: ellipsis;
134
+ }
135
+ .desktop-launcher__recent-name,
136
+ .desktop-launcher__label {
137
+ font-weight: 500;
138
+ }
139
+ .desktop-launcher__location {
140
+ color: var(--ui-workspace-muted-foreground);
141
+ font-size: 0.75rem;
142
+ }
143
+ .desktop-launcher__empty {
144
+ padding: 1.25rem 1rem;
145
+ border: 1px dashed
146
+ color-mix(in srgb, var(--ui-workspace-border) 70%, transparent);
147
+ border-radius: 0.75rem;
148
+ color: var(--ui-workspace-muted-foreground);
149
+ font-size: 0.875rem;
150
+ }
151
+ .desktop-launcher__error,
152
+ .desktop-launcher__message {
153
+ border: 1px solid
154
+ color-mix(in srgb, var(--ui-workspace-border) 70%, transparent);
155
+ border-radius: 0.75rem;
156
+ padding: 0.75rem 1rem;
157
+ font-size: 0.875rem;
158
+ background: var(--ui-workspace-panel-background);
159
+ }
160
+ .desktop-launcher__error {
161
+ border-color: color-mix(in srgb, var(--destructive) 40%, transparent);
162
+ color: var(--destructive);
163
+ background: color-mix(in srgb, var(--destructive) 10%, transparent);
164
+ }
165
+ @media (min-width: 40rem) {
166
+ .desktop-launcher {
167
+ padding-inline: 1.5rem;
168
+ }
169
+ .desktop-launcher__header {
170
+ flex-direction: row;
171
+ align-items: flex-start;
172
+ }
173
+ .desktop-launcher__heading {
174
+ font-size: 1.875rem;
175
+ }
176
+ }
177
+ @media (min-width: 64rem) {
178
+ .desktop-launcher__columns {
179
+ grid-template-columns: minmax(0, 420px) minmax(0, 1fr);
180
+ }
181
+ }
@@ -0,0 +1,30 @@
1
+ import type { VaultProfile } from "@lapis-notes/api";
2
+ export type LauncherStatus = "loading" | "landing" | "opening" | "error";
3
+ export type DesktopLauncherAppearance = "system" | "light" | "dark";
4
+ /** Storage and native actions belong to the consuming desktop host. */
5
+ export interface DesktopVaultLauncherHost {
6
+ listProfiles(): Promise<VaultProfile[]>;
7
+ getAppearance(): Promise<DesktopLauncherAppearance>;
8
+ saveAppearance(mode: DesktopLauncherAppearance): Promise<void>;
9
+ copyId?(profile: VaultProfile): Promise<void>;
10
+ rename?(profile: VaultProfile, name: string): Promise<void>;
11
+ move?(profile: VaultProfile): Promise<boolean>;
12
+ reveal?(profile: VaultProfile): Promise<void>;
13
+ remove?(profile: VaultProfile): Promise<void>;
14
+ revealLabel?: string;
15
+ }
16
+ export declare function getVaultProfileRootPath(profile: VaultProfile): string | null;
17
+ export declare function getVaultProfileLocation(profile: VaultProfile): string;
18
+ export declare const desktopAppearanceOptions: readonly [{
19
+ readonly value: "system";
20
+ readonly label: "Match System";
21
+ readonly description: "Follow the current system appearance.";
22
+ }, {
23
+ readonly value: "light";
24
+ readonly label: "Light";
25
+ readonly description: "Use the light workspace palette on the vault chooser.";
26
+ }, {
27
+ readonly value: "dark";
28
+ readonly label: "Dark";
29
+ readonly description: "Use the dark workspace palette on the vault chooser.";
30
+ }];
@@ -0,0 +1,26 @@
1
+ export function getVaultProfileRootPath(profile) {
2
+ const handle = profile.handle;
3
+ if (typeof handle === "string")
4
+ return handle;
5
+ return typeof handle?.rootPath === "string" ? handle.rootPath : null;
6
+ }
7
+ export function getVaultProfileLocation(profile) {
8
+ return getVaultProfileRootPath(profile) ?? "Desktop vault";
9
+ }
10
+ export const desktopAppearanceOptions = [
11
+ {
12
+ value: "system",
13
+ label: "Match System",
14
+ description: "Follow the current system appearance.",
15
+ },
16
+ {
17
+ value: "light",
18
+ label: "Light",
19
+ description: "Use the light workspace palette on the vault chooser.",
20
+ },
21
+ {
22
+ value: "dark",
23
+ label: "Dark",
24
+ description: "Use the dark workspace palette on the vault chooser.",
25
+ },
26
+ ];
@@ -0,0 +1,36 @@
1
+ import type { VaultProfile } from "@lapis-notes/api";
2
+ import { type DesktopLauncherAppearance, type DesktopVaultLauncherHost } from "./desktop-vault-launcher";
3
+ /** State from the Deno chooser, shared without depending on a native bridge. */
4
+ export declare class DesktopVaultLauncherState {
5
+ readonly host: DesktopVaultLauncherHost;
6
+ recentVaults: VaultProfile[];
7
+ recentVaultQuery: string;
8
+ recentVaultDialogOpen: boolean;
9
+ settingsOpen: boolean;
10
+ appearanceMode: DesktopLauncherAppearance;
11
+ activeActionId: string | null;
12
+ renameDialogOpen: boolean;
13
+ renameDialogName: string;
14
+ renameTarget: VaultProfile | null;
15
+ actionError: string;
16
+ actionMessage: string;
17
+ constructor(host: DesktopVaultLauncherHost);
18
+ get inlineRecentVaults(): VaultProfile[];
19
+ get filteredRecentVaults(): {
20
+ profile: VaultProfile;
21
+ name: string;
22
+ location: string;
23
+ kind: import("@lapis-notes/api").VaultStorageKind;
24
+ }[];
25
+ applyAppearance(mode: DesktopLauncherAppearance): void;
26
+ refresh(): Promise<void>;
27
+ invoke(action: () => Promise<void>): Promise<void>;
28
+ runAction(profile: VaultProfile, action: () => Promise<void>, message?: string): Promise<void>;
29
+ openRenameDialog(profile: VaultProfile): void;
30
+ submitRename(): Promise<void>;
31
+ moveRecentVault(profile: VaultProfile): Promise<void>;
32
+ copyVaultId(profile: VaultProfile): Promise<void>;
33
+ revealRecentVault(profile: VaultProfile): Promise<void>;
34
+ removeRecentVault(profile: VaultProfile): Promise<void>;
35
+ updateAppearance(mode: DesktopLauncherAppearance): Promise<void>;
36
+ }