rune-lab 0.0.12 → 0.0.13
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/features/CommandPalette.svelte +4 -17
- package/dist/features/CommandPalette.svelte.d.ts +1 -8
- package/dist/features/config/API_Monitor.svelte +102 -0
- package/dist/features/config/API_Monitor.svelte.d.ts +3 -0
- package/dist/features/config/CurrencySelector.svelte +9 -2
- package/dist/features/config/CurrencySelector.svelte.d.ts +4 -1
- package/dist/features/config/LanguageSelector.svelte +14 -1
- package/dist/features/config/LanguageSelector.svelte.d.ts +4 -1
- package/dist/features/config/ThemeSelector.svelte +9 -1
- package/dist/features/config/ThemeSelector.svelte.d.ts +4 -1
- package/dist/features/config/Toaster.svelte +33 -0
- package/dist/features/config/Toaster.svelte.d.ts +18 -0
- package/dist/features/config/api.svelte.d.ts +25 -0
- package/dist/features/config/api.svelte.js +45 -0
- package/dist/features/config/app.svelte.d.ts +3 -44
- package/dist/features/config/app.svelte.js +8 -88
- package/dist/features/config/commands.svelte.d.ts +27 -0
- package/dist/features/config/commands.svelte.js +28 -0
- package/dist/features/config/toast.svelte.d.ts +27 -0
- package/dist/features/config/toast.svelte.js +36 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +10 -6
- package/dist/paraglide/README.md +1 -1
- package/dist/paraglide/messages/_index.d.ts +5 -0
- package/dist/paraglide/messages/_index.js +5 -0
- package/dist/paraglide/messages/all_currencies.d.ts +16 -0
- package/dist/paraglide/messages/all_currencies.js +84 -0
- package/dist/paraglide/messages/all_languages.d.ts +16 -0
- package/dist/paraglide/messages/all_languages.js +84 -0
- package/dist/paraglide/messages/all_themes.d.ts +16 -0
- package/dist/paraglide/messages/all_themes.js +84 -0
- package/dist/paraglide/messages/extended_controls.d.ts +16 -0
- package/dist/paraglide/messages/extended_controls.js +84 -0
- package/dist/paraglide/messages/themes.d.ts +16 -0
- package/dist/paraglide/messages/themes.js +84 -0
- package/dist/showcase/AppSettingsManager.svelte +73 -0
- package/dist/showcase/AppSettingsManager.svelte.d.ts +8 -0
- package/package.json +7 -3
- package/dist/mod.d.ts +0 -1
- package/dist/mod.js +0 -2
|
@@ -1,29 +1,16 @@
|
|
|
1
1
|
<!-- src/client/sdk/ui/src/features/config/CommandPalette.svelte -->
|
|
2
2
|
<script lang="ts">
|
|
3
3
|
import { onMount } from "svelte";
|
|
4
|
+
import { commandStore } from "./config/commands.svelte";
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
id: string;
|
|
7
|
-
title: string;
|
|
8
|
-
category?: string;
|
|
9
|
-
icon?: string;
|
|
10
|
-
action: () => void;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
let { commands = [] }: { commands: Command[] } = $props();
|
|
6
|
+
let { shortcutKey = "k" } = $props<{ shortcutKey?: string }>();
|
|
14
7
|
|
|
15
8
|
let dialog: HTMLDialogElement;
|
|
16
9
|
let query = $state("");
|
|
17
10
|
let isOpen = $state(false);
|
|
18
11
|
|
|
19
12
|
// Filter commands based on query
|
|
20
|
-
let filtered = $derived(
|
|
21
|
-
query === ""
|
|
22
|
-
? commands
|
|
23
|
-
: commands.filter((c) =>
|
|
24
|
-
c.title.toLowerCase().includes(query.toLowerCase()),
|
|
25
|
-
),
|
|
26
|
-
);
|
|
13
|
+
let filtered = $derived(commandStore.search(query));
|
|
27
14
|
|
|
28
15
|
function toggle() {
|
|
29
16
|
isOpen = !isOpen;
|
|
@@ -38,7 +25,7 @@
|
|
|
38
25
|
// Global keyboard listener
|
|
39
26
|
onMount(() => {
|
|
40
27
|
function handleKeydown(e: KeyboardEvent) {
|
|
41
|
-
if ((e.metaKey || e.ctrlKey) && e.key ===
|
|
28
|
+
if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === shortcutKey.toLowerCase()) {
|
|
42
29
|
e.preventDefault();
|
|
43
30
|
toggle();
|
|
44
31
|
}
|
|
@@ -1,12 +1,5 @@
|
|
|
1
|
-
interface Command {
|
|
2
|
-
id: string;
|
|
3
|
-
title: string;
|
|
4
|
-
category?: string;
|
|
5
|
-
icon?: string;
|
|
6
|
-
action: () => void;
|
|
7
|
-
}
|
|
8
1
|
type $$ComponentProps = {
|
|
9
|
-
|
|
2
|
+
shortcutKey?: string;
|
|
10
3
|
};
|
|
11
4
|
declare const CommandPalette: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
12
5
|
type CommandPalette = ReturnType<typeof CommandPalette>;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Book, Copy, CheckCircle, RefreshCw } from "lucide-svelte";
|
|
3
|
+
import { apiStore } from "./api.svelte";
|
|
4
|
+
import { toastStore } from "./toast.svelte";
|
|
5
|
+
|
|
6
|
+
let copied = $state(false);
|
|
7
|
+
let isVisible = $state(true);
|
|
8
|
+
|
|
9
|
+
function copyToClipboard() {
|
|
10
|
+
navigator.clipboard.writeText(apiStore.URL);
|
|
11
|
+
copied = true;
|
|
12
|
+
toastStore.success("API URL copied to clipboard!");
|
|
13
|
+
setTimeout(() => (copied = false), 2000);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function handleKeyDown(event: KeyboardEvent) {
|
|
17
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
18
|
+
copyToClipboard();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const containerClass = $derived(`
|
|
23
|
+
fixed bottom-4 left-4 z-50
|
|
24
|
+
flex items-center space-x-2
|
|
25
|
+
transition-all duration-300 transform
|
|
26
|
+
${isVisible ? "translate-y-0 opacity-100" : "translate-y-16 opacity-0"}
|
|
27
|
+
`);
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<div class={containerClass}>
|
|
31
|
+
<div
|
|
32
|
+
class="flex items-center space-x-2 backdrop-blur-sm bg-base-300/80 rounded-xl p-1 shadow-lg border border-base-content/10"
|
|
33
|
+
>
|
|
34
|
+
<!-- API Status Indicator -->
|
|
35
|
+
{#if apiStore.IS_CONNECTED}
|
|
36
|
+
<div class="tooltip tooltip-right" data-tip="Connected">
|
|
37
|
+
<div
|
|
38
|
+
aria-label="success"
|
|
39
|
+
class="status status-success status-md"
|
|
40
|
+
></div>
|
|
41
|
+
</div>
|
|
42
|
+
{:else if apiStore.IS_LOADING}
|
|
43
|
+
<div class="tooltip tooltip-right" data-tip="Connecting...">
|
|
44
|
+
<div class="inline-grid *:[grid-area:1/1]">
|
|
45
|
+
<div class="status status-warning animate-ping"></div>
|
|
46
|
+
<div class="status status-warning"></div>
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
{:else}
|
|
50
|
+
<div class="tooltip tooltip-right" data-tip="Disconnected">
|
|
51
|
+
<div class="status status-error animate-bounce"></div>
|
|
52
|
+
</div>
|
|
53
|
+
{/if}
|
|
54
|
+
|
|
55
|
+
<!-- API Docs / Reload -->
|
|
56
|
+
{#if apiStore.connectionState === "connected"}
|
|
57
|
+
<button
|
|
58
|
+
class="btn btn-circle btn-xs btn-primary"
|
|
59
|
+
onclick={() => window.open(`${apiStore.URL}/docs`, "_blank")}
|
|
60
|
+
aria-label="Go to API Documentation"
|
|
61
|
+
>
|
|
62
|
+
<Book size={14} />
|
|
63
|
+
</button>
|
|
64
|
+
{:else}
|
|
65
|
+
<button
|
|
66
|
+
class="btn btn-circle btn-xs btn-error"
|
|
67
|
+
onclick={() => apiStore.reconnect()}
|
|
68
|
+
aria-label="Reconnect to API"
|
|
69
|
+
disabled={apiStore.connectionState === "connecting"}
|
|
70
|
+
>
|
|
71
|
+
<RefreshCw
|
|
72
|
+
size={14}
|
|
73
|
+
class={apiStore.connectionState === "connecting"
|
|
74
|
+
? "animate-spin"
|
|
75
|
+
: ""}
|
|
76
|
+
/>
|
|
77
|
+
</button>
|
|
78
|
+
{/if}
|
|
79
|
+
|
|
80
|
+
<button
|
|
81
|
+
class="group flex items-center space-x-2 px-3 py-1 rounded-lg hover:bg-base-200 transition-colors duration-200"
|
|
82
|
+
onclick={copyToClipboard}
|
|
83
|
+
onkeydown={handleKeyDown}
|
|
84
|
+
aria-label="Copy API URL"
|
|
85
|
+
>
|
|
86
|
+
<span class="text-xs font-mono"
|
|
87
|
+
>{apiStore.URL.replace(
|
|
88
|
+
/^https?:\/\//,
|
|
89
|
+
"",
|
|
90
|
+
)}/{apiStore.VERSION}</span
|
|
91
|
+
>
|
|
92
|
+
{#if copied}
|
|
93
|
+
<CheckCircle size={14} class="text-success" />
|
|
94
|
+
{:else}
|
|
95
|
+
<Copy
|
|
96
|
+
size={14}
|
|
97
|
+
class="opacity-50 group-hover:opacity-100 transition-all duration-200"
|
|
98
|
+
/>
|
|
99
|
+
{/if}
|
|
100
|
+
</button>
|
|
101
|
+
</div>
|
|
102
|
+
</div>
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import AppSettingSelector from "./AppSettingSelector.svelte";
|
|
3
3
|
import { currencyStore, type Currency } from "./currency.svelte";
|
|
4
|
-
import { setLocale, locales } from "../../paraglide/runtime";
|
|
5
4
|
import * as m from "../../paraglide/messages.js";
|
|
6
5
|
import { createMessageResolver } from "../../devtools/message-resolver";
|
|
7
6
|
|
|
7
|
+
let { codes = [] }: { codes?: string[] } = $props();
|
|
8
|
+
|
|
8
9
|
const getLabel = createMessageResolver<Currency>(m as any, {
|
|
9
10
|
keyExtractor: (c) => c.code,
|
|
10
11
|
});
|
|
@@ -12,9 +13,15 @@
|
|
|
12
13
|
let active = $derived(
|
|
13
14
|
currencyStore.get(currencyStore.current) ?? currencyStore.available[0],
|
|
14
15
|
);
|
|
16
|
+
|
|
17
|
+
let available = $derived(
|
|
18
|
+
codes.length > 0
|
|
19
|
+
? currencyStore.available.filter(c => codes.includes(c.code))
|
|
20
|
+
: currencyStore.available
|
|
21
|
+
);
|
|
15
22
|
</script>
|
|
16
23
|
|
|
17
|
-
<AppSettingSelector value={active} options={
|
|
24
|
+
<AppSettingSelector value={active} options={available}>
|
|
18
25
|
{#snippet triggerLabel(c)}
|
|
19
26
|
<span class="font-bold">{c.symbol}</span>
|
|
20
27
|
<span class="uppercase font-medium text-xs tracking-wide">{c.code}</span
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
type $$ComponentProps = {
|
|
2
|
+
codes?: string[];
|
|
3
|
+
};
|
|
4
|
+
declare const CurrencySelector: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
2
5
|
type CurrencySelector = ReturnType<typeof CurrencySelector>;
|
|
3
6
|
export default CurrencySelector;
|
|
@@ -5,6 +5,13 @@
|
|
|
5
5
|
import * as m from "../../paraglide/messages.js";
|
|
6
6
|
import { createMessageResolver } from "../../devtools/message-resolver";
|
|
7
7
|
|
|
8
|
+
let { languages: allowedLocales = locales }: { languages?: string[] } =
|
|
9
|
+
$props();
|
|
10
|
+
// what the line above does:
|
|
11
|
+
// it allows the component to be used in two ways:
|
|
12
|
+
// 1. <LanguageSelector /> - this will use all available locales
|
|
13
|
+
// 2. <LanguageSelector languages={["en", "es"]} /> - this will only use the specified locales
|
|
14
|
+
|
|
8
15
|
const getLabel = createMessageResolver<Language>(m as any, {
|
|
9
16
|
keyExtractor: (l) => l.code,
|
|
10
17
|
});
|
|
@@ -12,9 +19,15 @@
|
|
|
12
19
|
let active = $derived(
|
|
13
20
|
languageStore.get(languageStore.current) ?? languageStore.available[0],
|
|
14
21
|
);
|
|
22
|
+
|
|
23
|
+
let available = $derived(
|
|
24
|
+
languageStore.available.filter((l) =>
|
|
25
|
+
allowedLocales.includes(l.code as any),
|
|
26
|
+
),
|
|
27
|
+
);
|
|
15
28
|
</script>
|
|
16
29
|
|
|
17
|
-
<AppSettingSelector value={active} options={
|
|
30
|
+
<AppSettingSelector value={active} options={available}>
|
|
18
31
|
{#snippet triggerLabel(l)}
|
|
19
32
|
<span class="text-lg">{l?.flag ?? active.flag}</span>
|
|
20
33
|
<span class="uppercase font-medium text-xs tracking-wide"
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
type $$ComponentProps = {
|
|
2
|
+
languages?: string[];
|
|
3
|
+
};
|
|
4
|
+
declare const LanguageSelector: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
2
5
|
type LanguageSelector = ReturnType<typeof LanguageSelector>;
|
|
3
6
|
export default LanguageSelector;
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
import * as m from "../../paraglide/messages.js";
|
|
5
5
|
import { createMessageResolver } from "../../devtools/message-resolver";
|
|
6
6
|
|
|
7
|
+
let { themes = [] }: { themes?: string[] } = $props();
|
|
8
|
+
|
|
7
9
|
const getThemeLabel = createMessageResolver<Theme>(m as any, {
|
|
8
10
|
keyExtractor: (t) => t.name,
|
|
9
11
|
});
|
|
@@ -11,9 +13,15 @@
|
|
|
11
13
|
let activeTheme = $derived(
|
|
12
14
|
themeStore.get(themeStore.current) ?? themeStore.available[0],
|
|
13
15
|
);
|
|
16
|
+
|
|
17
|
+
let available = $derived(
|
|
18
|
+
themes.length > 0
|
|
19
|
+
? themeStore.available.filter(t => themes.includes(t.name))
|
|
20
|
+
: themeStore.available
|
|
21
|
+
);
|
|
14
22
|
</script>
|
|
15
23
|
|
|
16
|
-
<AppSettingSelector value={activeTheme} options={
|
|
24
|
+
<AppSettingSelector value={activeTheme} options={available}>
|
|
17
25
|
{#snippet triggerLabel(t)}
|
|
18
26
|
<span class="text-lg">{t?.icon ?? activeTheme.icon}</span>
|
|
19
27
|
<!-- Translate the name in the button -->
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
type $$ComponentProps = {
|
|
2
|
+
themes?: string[];
|
|
3
|
+
};
|
|
4
|
+
declare const ThemeSelector: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
2
5
|
type ThemeSelector = ReturnType<typeof ThemeSelector>;
|
|
3
6
|
export default ThemeSelector;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { toastStore } from "./toast.svelte";
|
|
3
|
+
import { flip } from "svelte/animate";
|
|
4
|
+
import { fade, fly } from "svelte/transition";
|
|
5
|
+
|
|
6
|
+
const typeClasses = {
|
|
7
|
+
info: "alert-info",
|
|
8
|
+
success: "alert-success",
|
|
9
|
+
warning: "alert-warning",
|
|
10
|
+
error: "alert-error"
|
|
11
|
+
};
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<div class="toast toast-end toast-bottom z-[100] p-4">
|
|
15
|
+
{#each toastStore.toasts as toast (toast.id)}
|
|
16
|
+
<div
|
|
17
|
+
animate:flip={{ duration: 300 }}
|
|
18
|
+
in:fly={{ y: 20, duration: 300 }}
|
|
19
|
+
out:fade={{ duration: 200 }}
|
|
20
|
+
class="alert {typeClasses[toast.type]} shadow-lg min-w-[250px] border-none"
|
|
21
|
+
>
|
|
22
|
+
<div class="flex items-center gap-2 w-full">
|
|
23
|
+
<span>{toast.message}</span>
|
|
24
|
+
<button
|
|
25
|
+
class="btn btn-ghost btn-xs btn-circle ml-auto"
|
|
26
|
+
onclick={() => toastStore.dismiss(toast.id)}
|
|
27
|
+
>
|
|
28
|
+
✕
|
|
29
|
+
</button>
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
{/each}
|
|
33
|
+
</div>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
2
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
3
|
+
$$bindings?: Bindings;
|
|
4
|
+
} & Exports;
|
|
5
|
+
(internal: unknown, props: {
|
|
6
|
+
$$events?: Events;
|
|
7
|
+
$$slots?: Slots;
|
|
8
|
+
}): Exports & {
|
|
9
|
+
$set?: any;
|
|
10
|
+
$on?: any;
|
|
11
|
+
};
|
|
12
|
+
z_$$bindings?: Bindings;
|
|
13
|
+
}
|
|
14
|
+
declare const Toaster: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
|
|
15
|
+
[evt: string]: CustomEvent<any>;
|
|
16
|
+
}, {}, {}, string>;
|
|
17
|
+
type Toaster = InstanceType<typeof Toaster>;
|
|
18
|
+
export default Toaster;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API connection state and configuration
|
|
3
|
+
*/
|
|
4
|
+
export type ConnectionState = "connected" | "connecting" | "disconnected";
|
|
5
|
+
declare class ApiStore {
|
|
6
|
+
url: string;
|
|
7
|
+
version: string;
|
|
8
|
+
connectionState: ConnectionState;
|
|
9
|
+
isConnected: boolean;
|
|
10
|
+
isLoading: boolean;
|
|
11
|
+
get URL(): string;
|
|
12
|
+
get VERSION(): string;
|
|
13
|
+
get IS_CONNECTED(): boolean;
|
|
14
|
+
get IS_LOADING(): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Reconnect to the API
|
|
17
|
+
*/
|
|
18
|
+
reconnect(): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Initialize API settings
|
|
21
|
+
*/
|
|
22
|
+
init(url: string, version?: string): void;
|
|
23
|
+
}
|
|
24
|
+
export declare const apiStore: ApiStore;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
class ApiStore {
|
|
2
|
+
// State
|
|
3
|
+
url = $state("http://localhost:8000");
|
|
4
|
+
version = $state("v1");
|
|
5
|
+
connectionState = $state("disconnected");
|
|
6
|
+
// Derived
|
|
7
|
+
isConnected = $derived(this.connectionState === "connected");
|
|
8
|
+
isLoading = $derived(this.connectionState === "connecting");
|
|
9
|
+
// Short aliases for compatibility with the user's snippet
|
|
10
|
+
get URL() {
|
|
11
|
+
return this.url;
|
|
12
|
+
}
|
|
13
|
+
get VERSION() {
|
|
14
|
+
return this.version;
|
|
15
|
+
}
|
|
16
|
+
get IS_CONNECTED() {
|
|
17
|
+
return this.isConnected;
|
|
18
|
+
}
|
|
19
|
+
get IS_LOADING() {
|
|
20
|
+
return this.isLoading;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Reconnect to the API
|
|
24
|
+
*/
|
|
25
|
+
async reconnect() {
|
|
26
|
+
this.connectionState = "connecting";
|
|
27
|
+
// Simulate connection
|
|
28
|
+
try {
|
|
29
|
+
await new Promise((resolve) => setTimeout(resolve, 1500));
|
|
30
|
+
this.connectionState = "connected";
|
|
31
|
+
}
|
|
32
|
+
catch (e) {
|
|
33
|
+
this.connectionState = "disconnected";
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Initialize API settings
|
|
38
|
+
*/
|
|
39
|
+
init(url, version = "v1") {
|
|
40
|
+
this.url = url;
|
|
41
|
+
this.version = version;
|
|
42
|
+
this.reconnect();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export const apiStore = new ApiStore();
|
|
@@ -13,65 +13,24 @@ export interface AppData {
|
|
|
13
13
|
/**
|
|
14
14
|
* App Store
|
|
15
15
|
* Manages application metadata and identity
|
|
16
|
-
*
|
|
17
|
-
* Features:
|
|
18
|
-
* - App name, version, description
|
|
19
|
-
* - Author and repository information
|
|
20
|
-
* - Initialization with partial updates
|
|
21
|
-
* - Console branding on init
|
|
22
16
|
*/
|
|
23
17
|
declare class AppStore {
|
|
24
18
|
name: string;
|
|
25
19
|
version: string;
|
|
26
20
|
description: string;
|
|
27
21
|
author: string;
|
|
28
|
-
repository
|
|
29
|
-
license
|
|
30
|
-
homepage
|
|
22
|
+
repository: string;
|
|
23
|
+
license: string;
|
|
24
|
+
homepage: string;
|
|
31
25
|
private initialized;
|
|
32
26
|
/**
|
|
33
27
|
* Initialize app store with metadata
|
|
34
|
-
*
|
|
35
|
-
* @param data - Application metadata (partial update)
|
|
36
|
-
* @param data.name - Application name
|
|
37
|
-
* @param data.version - Application version (semver recommended)
|
|
38
|
-
* @param data.description - Application description
|
|
39
|
-
* @param data.author - Application author
|
|
40
|
-
* @param data.repository - Repository URL (optional)
|
|
41
|
-
* @param data.license - License identifier (optional)
|
|
42
|
-
* @param data.homepage - Homepage URL (optional)
|
|
43
28
|
*/
|
|
44
29
|
init(data: Partial<AppData>): void;
|
|
45
30
|
/**
|
|
46
31
|
* Get full app information object
|
|
47
32
|
*/
|
|
48
33
|
get info(): AppData;
|
|
49
|
-
/**
|
|
50
|
-
* Get formatted version string
|
|
51
|
-
* Useful for display purposes
|
|
52
|
-
*/
|
|
53
|
-
get versionString(): string;
|
|
54
|
-
/**
|
|
55
|
-
* Get app title with version
|
|
56
|
-
*/
|
|
57
|
-
get titleWithVersion(): string;
|
|
58
|
-
/**
|
|
59
|
-
* Check if repository is available
|
|
60
|
-
*/
|
|
61
|
-
get hasRepository(): boolean;
|
|
62
|
-
/**
|
|
63
|
-
* Check if homepage is available
|
|
64
|
-
*/
|
|
65
|
-
get hasHomepage(): boolean;
|
|
66
|
-
/**
|
|
67
|
-
* Update app version
|
|
68
|
-
* Useful for version management during development
|
|
69
|
-
*/
|
|
70
|
-
updateVersion(version: string): void;
|
|
71
|
-
/**
|
|
72
|
-
* Log app initialization to console with styling
|
|
73
|
-
*/
|
|
74
|
-
private _logAppInit;
|
|
75
34
|
}
|
|
76
35
|
export declare const appStore: AppStore;
|
|
77
36
|
export {};
|
|
@@ -3,41 +3,23 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* App Store
|
|
5
5
|
* Manages application metadata and identity
|
|
6
|
-
*
|
|
7
|
-
* Features:
|
|
8
|
-
* - App name, version, description
|
|
9
|
-
* - Author and repository information
|
|
10
|
-
* - Initialization with partial updates
|
|
11
|
-
* - Console branding on init
|
|
12
6
|
*/
|
|
13
7
|
class AppStore {
|
|
14
8
|
// State
|
|
15
|
-
name = $state("
|
|
16
|
-
version = $state("0.1
|
|
17
|
-
description = $state("
|
|
18
|
-
author = $state("
|
|
19
|
-
repository = $state(
|
|
20
|
-
license = $state(
|
|
21
|
-
homepage = $state(
|
|
9
|
+
name = $state("Rune Lab");
|
|
10
|
+
version = $state("0.0.1");
|
|
11
|
+
description = $state("Modern toolkit for Svelte 5 Runes");
|
|
12
|
+
author = $state("Yrrrrrf");
|
|
13
|
+
repository = $state("https://github.com/Yrrrrrf/rune-lab");
|
|
14
|
+
license = $state("MIT");
|
|
15
|
+
homepage = $state("https://jsr.io/@yrrrrrf/rune-lab");
|
|
22
16
|
initialized = false;
|
|
23
17
|
/**
|
|
24
18
|
* Initialize app store with metadata
|
|
25
|
-
*
|
|
26
|
-
* @param data - Application metadata (partial update)
|
|
27
|
-
* @param data.name - Application name
|
|
28
|
-
* @param data.version - Application version (semver recommended)
|
|
29
|
-
* @param data.description - Application description
|
|
30
|
-
* @param data.author - Application author
|
|
31
|
-
* @param data.repository - Repository URL (optional)
|
|
32
|
-
* @param data.license - License identifier (optional)
|
|
33
|
-
* @param data.homepage - Homepage URL (optional)
|
|
34
19
|
*/
|
|
35
20
|
init(data) {
|
|
36
|
-
if (this.initialized)
|
|
37
|
-
console.warn("⚠️ AppStore already initialized");
|
|
21
|
+
if (this.initialized)
|
|
38
22
|
return;
|
|
39
|
-
}
|
|
40
|
-
// Update only provided values
|
|
41
23
|
if (data.name)
|
|
42
24
|
this.name = data.name;
|
|
43
25
|
if (data.version)
|
|
@@ -53,8 +35,6 @@ class AppStore {
|
|
|
53
35
|
if (data.homepage)
|
|
54
36
|
this.homepage = data.homepage;
|
|
55
37
|
this.initialized = true;
|
|
56
|
-
// Pretty console output
|
|
57
|
-
this._logAppInit();
|
|
58
38
|
}
|
|
59
39
|
/**
|
|
60
40
|
* Get full app information object
|
|
@@ -70,66 +50,6 @@ class AppStore {
|
|
|
70
50
|
homepage: this.homepage,
|
|
71
51
|
};
|
|
72
52
|
}
|
|
73
|
-
/**
|
|
74
|
-
* Get formatted version string
|
|
75
|
-
* Useful for display purposes
|
|
76
|
-
*/
|
|
77
|
-
get versionString() {
|
|
78
|
-
return `v${this.version}`;
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Get app title with version
|
|
82
|
-
*/
|
|
83
|
-
get titleWithVersion() {
|
|
84
|
-
return `${this.name} v${this.version}`;
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Check if repository is available
|
|
88
|
-
*/
|
|
89
|
-
get hasRepository() {
|
|
90
|
-
return !!this.repository;
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Check if homepage is available
|
|
94
|
-
*/
|
|
95
|
-
get hasHomepage() {
|
|
96
|
-
return !!this.homepage;
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* Update app version
|
|
100
|
-
* Useful for version management during development
|
|
101
|
-
*/
|
|
102
|
-
updateVersion(version) {
|
|
103
|
-
this.version = version;
|
|
104
|
-
console.log(`📦 Version updated to: v${version}`);
|
|
105
|
-
}
|
|
106
|
-
// Private methods
|
|
107
|
-
/**
|
|
108
|
-
* Log app initialization to console with styling
|
|
109
|
-
*/
|
|
110
|
-
_logAppInit() {
|
|
111
|
-
console.clear();
|
|
112
|
-
// Banner style
|
|
113
|
-
console.log("%c╔══════════════════════════════════════════════╗", "color: #00d9ff; font-weight: bold;");
|
|
114
|
-
console.log(`%c║ ${this.name.padEnd(42)} ║`, "color: #00d9ff; font-weight: bold;");
|
|
115
|
-
console.log("%c╚══════════════════════════════════════════════╝", "color: #00d9ff; font-weight: bold;");
|
|
116
|
-
// App details
|
|
117
|
-
console.log("\n📦 Application Details:");
|
|
118
|
-
console.log(` Name: ${this.name}`);
|
|
119
|
-
console.log(` Version: v${this.version}`);
|
|
120
|
-
console.log(` Author: ${this.author}`);
|
|
121
|
-
console.log(` Description: ${this.description}`);
|
|
122
|
-
if (this.repository) {
|
|
123
|
-
console.log(` Repository: ${this.repository}`);
|
|
124
|
-
}
|
|
125
|
-
if (this.license) {
|
|
126
|
-
console.log(` License: ${this.license}`);
|
|
127
|
-
}
|
|
128
|
-
if (this.homepage) {
|
|
129
|
-
console.log(` Homepage: ${this.homepage}`);
|
|
130
|
-
}
|
|
131
|
-
console.log("\n✨ Application initialized successfully!\n");
|
|
132
|
-
}
|
|
133
53
|
}
|
|
134
54
|
// Export singleton instance
|
|
135
55
|
export const appStore = new AppStore();
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command Palette Store
|
|
3
|
+
*/
|
|
4
|
+
export interface Command {
|
|
5
|
+
id: string;
|
|
6
|
+
title: string;
|
|
7
|
+
category?: string;
|
|
8
|
+
icon?: string;
|
|
9
|
+
action: () => void;
|
|
10
|
+
}
|
|
11
|
+
declare class CommandStore {
|
|
12
|
+
commands: Command[];
|
|
13
|
+
/**
|
|
14
|
+
* Register a new command
|
|
15
|
+
*/
|
|
16
|
+
register(command: Command): void;
|
|
17
|
+
/**
|
|
18
|
+
* Remove a command
|
|
19
|
+
*/
|
|
20
|
+
unregister(id: string): void;
|
|
21
|
+
/**
|
|
22
|
+
* Search commands
|
|
23
|
+
*/
|
|
24
|
+
search(query: string): Command[];
|
|
25
|
+
}
|
|
26
|
+
export declare const commandStore: CommandStore;
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
class CommandStore {
|
|
2
|
+
commands = $state([]);
|
|
3
|
+
/**
|
|
4
|
+
* Register a new command
|
|
5
|
+
*/
|
|
6
|
+
register(command) {
|
|
7
|
+
if (this.commands.find((c) => c.id === command.id))
|
|
8
|
+
return;
|
|
9
|
+
this.commands.push(command);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Remove a command
|
|
13
|
+
*/
|
|
14
|
+
unregister(id) {
|
|
15
|
+
this.commands = this.commands.filter((c) => c.id !== id);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Search commands
|
|
19
|
+
*/
|
|
20
|
+
search(query) {
|
|
21
|
+
if (!query)
|
|
22
|
+
return this.commands;
|
|
23
|
+
const q = query.toLowerCase();
|
|
24
|
+
return this.commands.filter((c) => c.title.toLowerCase().includes(q) ||
|
|
25
|
+
c.category?.toLowerCase().includes(q));
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export const commandStore = new CommandStore();
|