rune-lab 0.0.21 → 0.1.1
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/README.md +107 -0
- package/dist/components/ApiMonitor.svelte.d.ts +3 -0
- package/dist/components/Icon.svelte +52 -12
- package/dist/components/Icon.svelte.d.ts +2 -1
- package/dist/components/RuneProvider.svelte +49 -10
- package/dist/components/RuneProvider.svelte.d.ts +11 -1
- package/dist/{devtools → components}/Toaster.svelte +2 -2
- package/dist/features/config/{components/AppSettingSelector.svelte → AppSettingSelector.svelte} +9 -3
- package/dist/features/config/{components/CurrencySelector.svelte → CurrencySelector.svelte} +6 -4
- package/dist/features/config/{components/LanguageSelector.svelte → LanguageSelector.svelte} +7 -7
- package/dist/features/config/{components/ThemeSelector.svelte → ThemeSelector.svelte} +6 -4
- package/dist/features/detail-panels/ShowcasePanel.svelte +4 -6
- package/dist/index.d.ts +12 -13
- package/dist/index.js +10 -13
- package/dist/layout/WorkspaceLayout.svelte +81 -40
- package/dist/layout/WorkspaceLayout.svelte.d.ts +18 -4
- package/dist/persistence/drivers.js +10 -12
- package/dist/server/index.d.ts +15 -0
- package/dist/server/index.js +20 -0
- package/dist/showcase/AppStateInspector.svelte +27 -9
- package/dist/showcase/Showcase.svelte +5 -4
- package/dist/showcase/state.svelte.d.ts +3 -0
- package/dist/showcase/state.svelte.js +3 -0
- package/dist/state/api.svelte.d.ts +2 -1
- package/dist/state/api.svelte.js +16 -4
- package/dist/state/app.svelte.d.ts +5 -0
- package/dist/state/app.svelte.js +7 -0
- package/dist/state/commands.svelte.d.ts +1 -1
- package/dist/state/currency.svelte.d.ts +1 -1
- package/dist/state/currency.svelte.js +1 -1
- package/dist/state/index.d.ts +3 -1
- package/dist/state/index.js +3 -1
- package/dist/state/language.svelte.d.ts +6 -2
- package/dist/state/language.svelte.js +12 -4
- package/dist/state/layout.svelte.d.ts +0 -2
- package/dist/state/layout.svelte.js +0 -4
- package/dist/state/shortcuts.svelte.d.ts +14 -14
- package/dist/state/shortcuts.svelte.js +0 -10
- package/dist/state/theme.svelte.d.ts +1 -1
- package/dist/state/theme.svelte.js +1 -1
- package/dist/state/toast-bridge.d.ts +29 -0
- package/dist/state/toast-bridge.js +43 -0
- package/package.json +10 -6
- package/dist/devtools/API_Monitor.svelte.d.ts +0 -3
- /package/dist/{devtools/API_Monitor.svelte → components/ApiMonitor.svelte} +0 -0
- /package/dist/{devtools → components}/Toaster.svelte.d.ts +0 -0
- /package/dist/features/config/{components/AppSettingSelector.svelte.d.ts → AppSettingSelector.svelte.d.ts} +0 -0
- /package/dist/features/config/{components/CurrencySelector.svelte.d.ts → CurrencySelector.svelte.d.ts} +0 -0
- /package/dist/features/config/{components/LanguageSelector.svelte.d.ts → LanguageSelector.svelte.d.ts} +0 -0
- /package/dist/features/config/{components/ThemeSelector.svelte.d.ts → ThemeSelector.svelte.d.ts} +0 -0
- /package/dist/{devtools → internal}/message-resolver.d.ts +0 -0
- /package/dist/{devtools → internal}/message-resolver.js +0 -0
- /package/dist/{devtools → state}/createConfigStore.svelte.d.ts +0 -0
- /package/dist/{devtools → state}/createConfigStore.svelte.js +0 -0
package/README.md
CHANGED
|
@@ -58,6 +58,43 @@ npm install rune-lab
|
|
|
58
58
|
bun install rune-lab
|
|
59
59
|
```
|
|
60
60
|
|
|
61
|
+
## Quick Start
|
|
62
|
+
|
|
63
|
+
Get your application shell running in less than 20 lines. Inside your
|
|
64
|
+
`+layout.svelte`:
|
|
65
|
+
|
|
66
|
+
```svelte
|
|
67
|
+
<script lang="ts">
|
|
68
|
+
import { RuneProvider, WorkspaceLayout, ConnectedNavigationPanel } from "rune-lab";
|
|
69
|
+
import { cookieDriver } from "rune-lab";
|
|
70
|
+
|
|
71
|
+
let { children } = $props();
|
|
72
|
+
|
|
73
|
+
// Example navigation
|
|
74
|
+
const sections = [{ id: "main", title: "Main", items: [{ id: "home", label: "Home" }] }];
|
|
75
|
+
</script>
|
|
76
|
+
|
|
77
|
+
<RuneProvider
|
|
78
|
+
app={{ name: "My App", version: "1.0.0" }}
|
|
79
|
+
persistence={cookieDriver}
|
|
80
|
+
>
|
|
81
|
+
<WorkspaceLayout>
|
|
82
|
+
{#snippet navigationPanel()}
|
|
83
|
+
<ConnectedNavigationPanel {sections} />
|
|
84
|
+
{/snippet}
|
|
85
|
+
|
|
86
|
+
{#snippet content()}
|
|
87
|
+
<div class="p-8">
|
|
88
|
+
{@render children()}
|
|
89
|
+
</div>
|
|
90
|
+
{/snippet}
|
|
91
|
+
</WorkspaceLayout>
|
|
92
|
+
</RuneProvider>
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
You now have a fully functional reactive layout, keyboard command palette, toast
|
|
96
|
+
notification system, and theme switcher ready to go.
|
|
97
|
+
|
|
61
98
|
## Project Configuration
|
|
62
99
|
|
|
63
100
|
After installing, two configuration steps are required to ensure components are
|
|
@@ -103,6 +140,76 @@ also scan the `rune-lab` dist output:
|
|
|
103
140
|
> component classes used by `rune-lab` will be included in your build and theme
|
|
104
141
|
> switching will work across library components and your own code alike.
|
|
105
142
|
|
|
143
|
+
## Persistence Drivers
|
|
144
|
+
|
|
145
|
+
Rune Lab provides built-in drivers to remember user preferences (like theme,
|
|
146
|
+
layout state, or language) across reloads. Pass one of these to the
|
|
147
|
+
`persistence` prop on `<RuneProvider>`:
|
|
148
|
+
|
|
149
|
+
- `cookieDriver`: Best for SSR applications (like SvelteKit) because the server
|
|
150
|
+
can read the cookie and prevent a "theme flash" on initial load.
|
|
151
|
+
- `localStorageDriver`: Best for client-only applications (SPA) looking for
|
|
152
|
+
long-term persistence.
|
|
153
|
+
- `sessionStorageDriver`: For preferences that should clear when the browser tab
|
|
154
|
+
closes.
|
|
155
|
+
|
|
156
|
+
```svelte
|
|
157
|
+
<script lang="ts">
|
|
158
|
+
import { cookieDriver } from "rune-lab";
|
|
159
|
+
// Then pass directly: <RuneProvider persistence={cookieDriver}>
|
|
160
|
+
</script>
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Advanced Patterns
|
|
164
|
+
|
|
165
|
+
### SvelteKit Route Syncing
|
|
166
|
+
|
|
167
|
+
To keep your layout's active navigation state synchronized with the SvelteKit
|
|
168
|
+
router, use an `$effect` inside your `+layout.svelte` right after the provider:
|
|
169
|
+
|
|
170
|
+
```svelte
|
|
171
|
+
<script lang="ts">
|
|
172
|
+
import { page } from "$app/state";
|
|
173
|
+
import { getLayoutStore } from "rune-lab";
|
|
174
|
+
|
|
175
|
+
const layoutStore = getLayoutStore();
|
|
176
|
+
|
|
177
|
+
$effect(() => {
|
|
178
|
+
// Example: Use the first path segment as the active nav item
|
|
179
|
+
const segment = page.url.pathname.split("/")[1] || "home";
|
|
180
|
+
layoutStore.navigate(segment);
|
|
181
|
+
});
|
|
182
|
+
</script>
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
_(Note: Use `$app/state`, not the older Svelte 4 `$app/stores`)_
|
|
186
|
+
|
|
187
|
+
### Keyboard Shortcuts
|
|
188
|
+
|
|
189
|
+
Any component deep in your tree can register its own keyboard shortcuts
|
|
190
|
+
dynamically. To ensure they clean up when the component unmounts, **always
|
|
191
|
+
register them inside an `$effect` returning a cleanup function**:
|
|
192
|
+
|
|
193
|
+
```svelte
|
|
194
|
+
<script lang="ts">
|
|
195
|
+
import { getShortcutStore, getToastStore } from "rune-lab";
|
|
196
|
+
|
|
197
|
+
const shortcuts = getShortcutStore();
|
|
198
|
+
const toasts = getToastStore();
|
|
199
|
+
|
|
200
|
+
$effect(() => {
|
|
201
|
+
shortcuts.register({
|
|
202
|
+
id: "feature.save",
|
|
203
|
+
keys: "ctrl s",
|
|
204
|
+
label: "Save Document",
|
|
205
|
+
handler: () => toasts.success("Document Saved!")
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
return () => shortcuts.unregister("feature.save"); // Important!
|
|
209
|
+
});
|
|
210
|
+
</script>
|
|
211
|
+
```
|
|
212
|
+
|
|
106
213
|
## License
|
|
107
214
|
|
|
108
215
|
MIT License - See [LICENSE](LICENSE) for details.
|
|
@@ -1,32 +1,72 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { getAppStore } from "../state/app.svelte";
|
|
3
|
+
|
|
2
4
|
/**
|
|
3
5
|
* Simple Icon component for Rune Lab
|
|
4
6
|
* Centralizes SVG paths to reduce boilerplate
|
|
5
7
|
*/
|
|
6
|
-
let {
|
|
7
|
-
name
|
|
8
|
+
let {
|
|
9
|
+
name,
|
|
10
|
+
size = "w-5 h-5",
|
|
11
|
+
class: className = "",
|
|
12
|
+
icons = {},
|
|
13
|
+
} = $props<{
|
|
14
|
+
name: string;
|
|
8
15
|
size?: string;
|
|
9
16
|
class?: string;
|
|
17
|
+
icons?: Record<string, string>;
|
|
10
18
|
}>();
|
|
11
19
|
|
|
20
|
+
let appStore: ReturnType<typeof getAppStore> | undefined;
|
|
21
|
+
try {
|
|
22
|
+
appStore = getAppStore();
|
|
23
|
+
} catch {
|
|
24
|
+
// Graceful fallback if Icon is used outside RuneProvider
|
|
25
|
+
}
|
|
26
|
+
|
|
12
27
|
const paths: Record<string, string> = {
|
|
13
|
-
search:
|
|
28
|
+
search:
|
|
29
|
+
'<circle cx="11" cy="11" r="8"></circle><path d="m21 21-4.3-4.3"></path>',
|
|
14
30
|
"chevron-down": '<path d="m6 9 6 6 6-6" />',
|
|
31
|
+
"chevron-right": '<path d="m9 18 6-6-6-6" />',
|
|
15
32
|
info: '<circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/>',
|
|
16
|
-
shortcut:
|
|
33
|
+
shortcut:
|
|
34
|
+
'<rect width="18" height="11" x="3" y="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/>',
|
|
17
35
|
close: '<path d="M18 6 6 18"/><path d="m6 6 12 12"/>',
|
|
18
|
-
external:
|
|
19
|
-
|
|
36
|
+
external:
|
|
37
|
+
'<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/>',
|
|
38
|
+
plus: '<path d="M5 12h14"/><path d="M12 5v14"/>',
|
|
39
|
+
minus: '<path d="M5 12h14"/>',
|
|
40
|
+
check: '<path d="M20 6 9 17l-5-5"/>',
|
|
41
|
+
trash:
|
|
42
|
+
'<path d="M3 6h18"/><path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"/><path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"/>',
|
|
43
|
+
edit: '<path d="M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z"/><path d="m15 5 4 4"/>',
|
|
44
|
+
grid: '<rect width="7" height="7" x="3" y="3" rx="1"/><rect width="7" height="7" x="14" y="3" rx="1"/><rect width="7" height="7" x="14" y="14" rx="1"/><rect width="7" height="7" x="3" y="14" rx="1"/>',
|
|
45
|
+
list: '<line x1="8" x2="21" y1="6" y2="6"/><line x1="8" x2="21" y1="12" y2="12"/><line x1="8" x2="21" y1="18" y2="18"/><line x1="3" x2="3.01" y1="6" y2="6"/><line x1="3" x2="3.01" y1="12" y2="12"/><line x1="3" x2="3.01" y1="18" y2="18"/>',
|
|
46
|
+
table:
|
|
47
|
+
'<rect width="18" height="18" x="3" y="3" rx="2" ry="2"/><line x1="3" x2="21" y1="9" y2="9"/><line x1="3" x2="21" y1="15" y2="15"/><line x1="9" x2="9" y1="3" y2="21"/><line x1="15" x2="15" y1="3" y2="21"/>',
|
|
48
|
+
"arrow-left": '<path d="m12 19-7-7 7-7"/><path d="M19 12H5"/>',
|
|
49
|
+
"arrow-right": '<path d="M5 12h14"/><path d="m12 5 7 7-7 7"/>',
|
|
50
|
+
menu: '<line x1="4" x2="20" y1="12" y2="12"/><line x1="4" x2="20" y1="6" y2="6"/><line x1="4" x2="20" y1="18" y2="18"/>',
|
|
51
|
+
bell: '<path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"/><path d="M10.3 21a1.94 1.94 0 0 0 3.4 0"/>',
|
|
52
|
+
user: '<path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/>',
|
|
53
|
+
settings:
|
|
54
|
+
'<path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"/><circle cx="12" cy="12" r="3"/>',
|
|
55
|
+
logout:
|
|
56
|
+
'<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" x2="9" y1="12" y2="12"/>',
|
|
57
|
+
unknown:
|
|
58
|
+
'<circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><path d="M12 17h.01"/>',
|
|
20
59
|
};
|
|
21
60
|
|
|
22
61
|
const path = $derived.by(() => {
|
|
23
|
-
if (
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
62
|
+
if (icons[name]) return icons[name];
|
|
63
|
+
if (appStore?.customIcons?.[name]) return appStore.customIcons[name];
|
|
64
|
+
if (paths[name]) return paths[name];
|
|
65
|
+
|
|
66
|
+
if (import.meta.env?.DEV) {
|
|
67
|
+
console.warn(`[Icon] Unknown icon name: "${name}"`);
|
|
28
68
|
}
|
|
29
|
-
return paths
|
|
69
|
+
return paths.unknown;
|
|
30
70
|
});
|
|
31
71
|
</script>
|
|
32
72
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
type $$ComponentProps = {
|
|
2
|
-
name:
|
|
2
|
+
name: string;
|
|
3
3
|
size?: string;
|
|
4
4
|
class?: string;
|
|
5
|
+
icons?: Record<string, string>;
|
|
5
6
|
};
|
|
6
7
|
declare const Icon: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
7
8
|
type Icon = ReturnType<typeof Icon>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { setContext, untrack, type Snippet } from "svelte";
|
|
2
|
+
import { setContext, untrack, type Snippet, onMount } from "svelte";
|
|
3
3
|
import {
|
|
4
4
|
createAppStore,
|
|
5
5
|
createLayoutStore,
|
|
@@ -11,14 +11,26 @@
|
|
|
11
11
|
createCurrencyStore,
|
|
12
12
|
createShortcutStore,
|
|
13
13
|
} from "../state/index";
|
|
14
|
+
import { wire } from "../state/toast-bridge";
|
|
14
15
|
import { Toaster, CommandPalette, ShortcutPalette } from "../index";
|
|
15
16
|
|
|
16
17
|
import type { PersistenceDriver } from "../persistence/types";
|
|
17
18
|
import { RUNE_LAB_CONTEXT } from "../context";
|
|
19
|
+
import type { AppData } from "../state/app.svelte";
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
children: Snippet;
|
|
21
|
+
export interface RuneLabConfig {
|
|
21
22
|
persistence?: PersistenceDriver;
|
|
23
|
+
app?: Partial<AppData>;
|
|
24
|
+
apiUrl?: string;
|
|
25
|
+
apiHealthCheck?: () => Promise<boolean>;
|
|
26
|
+
favicon?: string;
|
|
27
|
+
manageHead?: boolean;
|
|
28
|
+
dictionary?: Record<string, any>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
let { children, config = {} } = $props<{
|
|
32
|
+
children: Snippet;
|
|
33
|
+
config?: RuneLabConfig;
|
|
22
34
|
}>();
|
|
23
35
|
|
|
24
36
|
// 1. Initialize Base Configuration Stores
|
|
@@ -26,11 +38,16 @@
|
|
|
26
38
|
const apiStore = createApiStore();
|
|
27
39
|
const toastStore = createToastStore();
|
|
28
40
|
|
|
41
|
+
// Wire global toast bridge
|
|
42
|
+
wire(toastStore);
|
|
43
|
+
|
|
29
44
|
// Capture the initial persistence prop to avoid Svelte 5 reactive capture warnings
|
|
30
|
-
const initialPersistence = untrack(() => persistence);
|
|
45
|
+
const initialPersistence = untrack(() => config.persistence);
|
|
31
46
|
|
|
32
47
|
const themeStore = createThemeStore(initialPersistence);
|
|
33
|
-
const languageStore = createLanguageStore(
|
|
48
|
+
const languageStore = createLanguageStore({
|
|
49
|
+
driver: initialPersistence,
|
|
50
|
+
});
|
|
34
51
|
const currencyStore = createCurrencyStore(initialPersistence);
|
|
35
52
|
const shortcutStore = createShortcutStore();
|
|
36
53
|
|
|
@@ -57,6 +74,24 @@
|
|
|
57
74
|
setContext(RUNE_LAB_CONTEXT.commands, commandStore);
|
|
58
75
|
setContext(RUNE_LAB_CONTEXT.persistence, initialPersistence);
|
|
59
76
|
|
|
77
|
+
const initialDictionary = untrack(() => config.dictionary);
|
|
78
|
+
if (initialDictionary) {
|
|
79
|
+
setContext("rl:dictionary", initialDictionary);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Track config changes dynamically
|
|
83
|
+
$effect(() => {
|
|
84
|
+
if (config.app) appStore.init(config.app);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
$effect(() => {
|
|
88
|
+
if (config.apiUrl) apiStore.init(config.apiUrl, "v1", config.apiHealthCheck);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
onMount(() => {
|
|
92
|
+
layoutStore.init();
|
|
93
|
+
});
|
|
94
|
+
|
|
60
95
|
// Meta tags derived from app store state
|
|
61
96
|
const metaTags = $derived([
|
|
62
97
|
{ name: "description", content: appStore.description },
|
|
@@ -65,11 +100,15 @@
|
|
|
65
100
|
</script>
|
|
66
101
|
|
|
67
102
|
<svelte:head>
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
103
|
+
{#if config.manageHead !== false}
|
|
104
|
+
<title>{appStore.name}</title>
|
|
105
|
+
{#if config.favicon}
|
|
106
|
+
<link rel="icon" href={config.favicon} />
|
|
107
|
+
{/if}
|
|
108
|
+
{#each metaTags as meta}
|
|
109
|
+
<meta name={meta.name} content={meta.content} />
|
|
110
|
+
{/each}
|
|
111
|
+
{/if}
|
|
73
112
|
</svelte:head>
|
|
74
113
|
|
|
75
114
|
<!-- Global Overlays -->
|
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
import { type Snippet } from "svelte";
|
|
2
2
|
import type { PersistenceDriver } from "../persistence/types";
|
|
3
|
+
import type { AppData } from "../state/app.svelte";
|
|
4
|
+
export interface RuneLabConfig {
|
|
5
|
+
persistence?: PersistenceDriver;
|
|
6
|
+
app?: Partial<AppData>;
|
|
7
|
+
apiUrl?: string;
|
|
8
|
+
apiHealthCheck?: () => Promise<boolean>;
|
|
9
|
+
favicon?: string;
|
|
10
|
+
manageHead?: boolean;
|
|
11
|
+
dictionary?: Record<string, any>;
|
|
12
|
+
}
|
|
3
13
|
type $$ComponentProps = {
|
|
4
14
|
children: Snippet;
|
|
5
|
-
|
|
15
|
+
config?: RuneLabConfig;
|
|
6
16
|
};
|
|
7
17
|
declare const RuneProvider: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
8
18
|
type RuneProvider = ReturnType<typeof RuneProvider>;
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"bg-blue-500/10 border-blue-500/20 text-blue-600 dark:text-blue-400",
|
|
16
16
|
iconColor: "text-blue-500",
|
|
17
17
|
iconPath:
|
|
18
|
-
"
|
|
18
|
+
"M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12zm8.706-1.442c1.146-.573 2.437.463 2.126 1.706l-.709 2.836.042-.02a.75.75 0 01.67 1.34l-.04.022c-1.147.573-2.438-.463-2.127-1.706l.71-2.836-.042.02a.75.75 0 11-.671-1.34l.041-.022zM12 9a.75.75 0 100-1.5.75.75 0 000 1.5z",
|
|
19
19
|
},
|
|
20
20
|
success: {
|
|
21
21
|
colors:
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"bg-amber-500/10 border-amber-500/20 text-amber-600 dark:text-amber-400",
|
|
30
30
|
iconColor: "text-amber-500",
|
|
31
31
|
iconPath:
|
|
32
|
-
"M12
|
|
32
|
+
"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z", // Proper warning icon
|
|
33
33
|
},
|
|
34
34
|
error: {
|
|
35
35
|
colors: "bg-red-500/10 border-red-500/20 text-red-600 dark:text-red-400",
|
package/dist/features/config/{components/AppSettingSelector.svelte → AppSettingSelector.svelte}
RENAMED
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
<button
|
|
47
47
|
type="button"
|
|
48
48
|
class="btn btn-ghost btn-sm m-1 h-auto min-h-[2rem] px-2"
|
|
49
|
+
aria-haspopup="dialog"
|
|
49
50
|
onclick={() => modal?.showModal()}
|
|
50
51
|
>
|
|
51
52
|
<span class="flex items-center gap-2">
|
|
@@ -66,9 +67,12 @@
|
|
|
66
67
|
</form>
|
|
67
68
|
</div>
|
|
68
69
|
<div class="max-h-[60vh] overflow-y-auto p-2">
|
|
69
|
-
<ul class="menu bg-base-100 w-full p-0">
|
|
70
|
+
<ul class="menu bg-base-100 w-full p-0" role="menu">
|
|
70
71
|
{#each options as option}
|
|
71
|
-
<li
|
|
72
|
+
<li
|
|
73
|
+
class="border-b border-base-100 last:border-0"
|
|
74
|
+
role="menuitem"
|
|
75
|
+
>
|
|
72
76
|
<button
|
|
73
77
|
class="w-full text-left py-3"
|
|
74
78
|
onclick={() => modal?.close()}
|
|
@@ -96,6 +100,7 @@
|
|
|
96
100
|
<div
|
|
97
101
|
tabindex="0"
|
|
98
102
|
role="button"
|
|
103
|
+
aria-haspopup="menu"
|
|
99
104
|
class="btn btn-ghost btn-sm m-1 {tooltip
|
|
100
105
|
? 'tooltip tooltip-bottom'
|
|
101
106
|
: ''}"
|
|
@@ -107,10 +112,11 @@
|
|
|
107
112
|
</div>
|
|
108
113
|
|
|
109
114
|
<ul
|
|
115
|
+
role="menu"
|
|
110
116
|
class="dropdown-content menu bg-base-100 rounded-box z-[1] w-52 p-2 shadow-xl border border-base-200 max-h-96 overflow-y-auto"
|
|
111
117
|
>
|
|
112
118
|
{#each options as option}
|
|
113
|
-
<li>
|
|
119
|
+
<li role="menuitem">
|
|
114
120
|
{@render item(option)}
|
|
115
121
|
</li>
|
|
116
122
|
{/each}
|
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
import {
|
|
4
4
|
getCurrencyStore,
|
|
5
5
|
type Currency,
|
|
6
|
-
} from "
|
|
6
|
+
} from "../../state/currency.svelte";
|
|
7
7
|
|
|
8
8
|
const currencyStore = getCurrencyStore();
|
|
9
9
|
|
|
10
|
-
import
|
|
11
|
-
import { createMessageResolver } from "
|
|
10
|
+
import { getContext } from "svelte";
|
|
11
|
+
import { createMessageResolver } from "../../internal/message-resolver";
|
|
12
12
|
|
|
13
13
|
let {
|
|
14
14
|
codes = [],
|
|
@@ -20,7 +20,9 @@
|
|
|
20
20
|
onchange?: (value: string) => void;
|
|
21
21
|
} = $props();
|
|
22
22
|
|
|
23
|
-
const
|
|
23
|
+
const dictionary = getContext<Record<string, any>>("rl:dictionary") || {};
|
|
24
|
+
|
|
25
|
+
const getLabel = createMessageResolver<Currency>(dictionary as any, {
|
|
24
26
|
keyExtractor: (c) => String(c.code),
|
|
25
27
|
});
|
|
26
28
|
|
|
@@ -3,16 +3,15 @@
|
|
|
3
3
|
import {
|
|
4
4
|
getLanguageStore,
|
|
5
5
|
type Language,
|
|
6
|
-
} from "
|
|
6
|
+
} from "../../state/language.svelte";
|
|
7
7
|
|
|
8
8
|
const languageStore = getLanguageStore();
|
|
9
9
|
|
|
10
|
-
import {
|
|
11
|
-
import
|
|
12
|
-
import { createMessageResolver } from "../../../devtools/message-resolver";
|
|
10
|
+
import { getContext } from "svelte";
|
|
11
|
+
import { createMessageResolver } from "../../internal/message-resolver";
|
|
13
12
|
|
|
14
13
|
let {
|
|
15
|
-
languages: allowedLocales =
|
|
14
|
+
languages: allowedLocales = languageStore.available.map((l) => l.code),
|
|
16
15
|
current = $bindable(languageStore.current),
|
|
17
16
|
onchange,
|
|
18
17
|
}: {
|
|
@@ -21,7 +20,9 @@
|
|
|
21
20
|
onchange?: (value: string) => void;
|
|
22
21
|
} = $props();
|
|
23
22
|
|
|
24
|
-
const
|
|
23
|
+
const dictionary = getContext<Record<string, any>>("rl:dictionary") || {};
|
|
24
|
+
|
|
25
|
+
const getLabel = createMessageResolver<Language>(dictionary as any, {
|
|
25
26
|
keyExtractor: (l) => l.code,
|
|
26
27
|
});
|
|
27
28
|
|
|
@@ -50,7 +51,6 @@
|
|
|
50
51
|
class="flex items-center gap-3 w-full"
|
|
51
52
|
onclick={() => {
|
|
52
53
|
languageStore.set(l.code);
|
|
53
|
-
setLocale(l.code as any);
|
|
54
54
|
current = l.code;
|
|
55
55
|
onchange?.(l.code);
|
|
56
56
|
}}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import AppSettingSelector from "./AppSettingSelector.svelte";
|
|
3
|
-
import { getThemeStore, type Theme } from "
|
|
3
|
+
import { getThemeStore, type Theme } from "../../state/theme.svelte";
|
|
4
4
|
|
|
5
5
|
const themeStore = getThemeStore();
|
|
6
6
|
|
|
7
|
-
import
|
|
8
|
-
import { createMessageResolver } from "
|
|
7
|
+
import { getContext } from "svelte";
|
|
8
|
+
import { createMessageResolver } from "../../internal/message-resolver";
|
|
9
9
|
|
|
10
10
|
let {
|
|
11
11
|
themes = [],
|
|
@@ -17,7 +17,9 @@
|
|
|
17
17
|
onchange?: (value: string) => void;
|
|
18
18
|
} = $props();
|
|
19
19
|
|
|
20
|
-
const
|
|
20
|
+
const dictionary = getContext<Record<string, any>>("rl:dictionary") || {};
|
|
21
|
+
|
|
22
|
+
const getThemeLabel = createMessageResolver<Theme>(dictionary as any, {
|
|
21
23
|
keyExtractor: (t) => t.name,
|
|
22
24
|
});
|
|
23
25
|
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
const layoutStore = getLayoutStore();
|
|
2
|
+
import { showcaseState } from "../../showcase/state.svelte";
|
|
5
3
|
|
|
6
4
|
import { getToastStore } from "../../state/toast.svelte";
|
|
7
5
|
|
|
@@ -21,7 +19,7 @@
|
|
|
21
19
|
"visual",
|
|
22
20
|
];
|
|
23
21
|
|
|
24
|
-
const currentTabId = $derived(tabs[
|
|
22
|
+
const currentTabId = $derived(tabs[showcaseState.activeTab]);
|
|
25
23
|
const components = $derived(SHOWCASE_COMPONENTS[currentTabId] || []);
|
|
26
24
|
const snippet = $derived(SHOWCASE_SNIPPETS[currentTabId] || "");
|
|
27
25
|
|
|
@@ -52,8 +50,8 @@
|
|
|
52
50
|
{#each tabs as tab, i}
|
|
53
51
|
<li>
|
|
54
52
|
<button
|
|
55
|
-
class:active={
|
|
56
|
-
onclick={() =>
|
|
53
|
+
class:active={showcaseState.activeTab === i}
|
|
54
|
+
onclick={() => (showcaseState.activeTab = i)}
|
|
57
55
|
class="capitalize"
|
|
58
56
|
>
|
|
59
57
|
{tab.replace("-", " ")}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { createConfigStore } from "./
|
|
2
|
-
export { createMessageResolver } from "./
|
|
1
|
+
export { createConfigStore } from "./state/createConfigStore.svelte";
|
|
2
|
+
export { createMessageResolver } from "./internal/message-resolver";
|
|
3
3
|
export { RUNE_LAB_CONTEXT } from "./context";
|
|
4
4
|
export type { PersistenceDriver } from "./persistence/types";
|
|
5
5
|
export { cookieDriver, inMemoryDriver, localStorageDriver, sessionStorageDriver, } from "./persistence/drivers";
|
|
@@ -8,24 +8,23 @@ export { usePersistence } from "./composables/usePersistence.js";
|
|
|
8
8
|
export { portal } from "./actions/portal";
|
|
9
9
|
export { default as RuneProvider } from "./components/RuneProvider.svelte";
|
|
10
10
|
export { default as Icon } from "./components/Icon.svelte";
|
|
11
|
-
export { default as Toaster } from "./
|
|
12
|
-
export { default as ApiMonitor } from "./
|
|
11
|
+
export { default as Toaster } from "./components/Toaster.svelte";
|
|
12
|
+
export { default as ApiMonitor } from "./components/ApiMonitor.svelte";
|
|
13
13
|
export { default as CommandPalette } from "./features/command-palette/CommandPalette.svelte";
|
|
14
14
|
export { default as ShortcutPalette } from "./features/shortcuts/ShortcutPalette.svelte";
|
|
15
|
-
export { default as WorkspaceLayout } from "./layout/WorkspaceLayout.svelte";
|
|
15
|
+
export { default as WorkspaceLayout, type WorkspaceLayoutProps, } from "./layout/WorkspaceLayout.svelte";
|
|
16
16
|
export { default as WorkspaceStrip } from "./layout/WorkspaceStrip.svelte";
|
|
17
17
|
export { default as NavigationPanel } from "./layout/NavigationPanel.svelte";
|
|
18
18
|
export { default as ContentArea } from "./layout/ContentArea.svelte";
|
|
19
19
|
export { default as DetailPanel } from "./layout/DetailPanel.svelte";
|
|
20
20
|
export { default as ConnectedNavigationPanel } from "./features/layout/smart/ConnectedNavigationPanel.svelte";
|
|
21
21
|
export { default as ConnectedWorkspaceStrip } from "./features/layout/smart/ConnectedWorkspaceStrip.svelte";
|
|
22
|
-
export { default as AppSettingSelector } from "./features/config/
|
|
23
|
-
export { default as ThemeSelector } from "./features/config/
|
|
24
|
-
export { default as LanguageSelector } from "./features/config/
|
|
25
|
-
export { default as CurrencySelector } from "./features/config/
|
|
26
|
-
export { createApiStore, createAppStore, createCommandStore, createCurrencyStore, createLanguageStore, createLayoutStore, createShortcutStore, createThemeStore, createToastStore, getApiStore, getAppStore, getCommandStore, getCurrencyStore, getLanguageStore, getLayoutStore, getShortcutStore, getThemeStore, getToastStore, } from "./state/index";
|
|
22
|
+
export { default as AppSettingSelector } from "./features/config/AppSettingSelector.svelte";
|
|
23
|
+
export { default as ThemeSelector } from "./features/config/ThemeSelector.svelte";
|
|
24
|
+
export { default as LanguageSelector } from "./features/config/LanguageSelector.svelte";
|
|
25
|
+
export { default as CurrencySelector } from "./features/config/CurrencySelector.svelte";
|
|
26
|
+
export { createApiStore, createAppStore, createCommandStore, createCurrencyStore, createLanguageStore, createLayoutStore, createShortcutStore, createThemeStore, createToastBridge, createToastStore, getApiStore, getAppStore, getCommandStore, getCurrencyStore, getLanguageStore, getLayoutStore, getShortcutStore, getThemeStore, getToastStore, notify, } from "./state/index";
|
|
27
27
|
export { default as AppStateInspector } from "./showcase/AppStateInspector.svelte";
|
|
28
|
-
export {
|
|
29
|
-
export {
|
|
30
|
-
export type { AppData, Command, Currency, Language, NavigationItem, NavigationSection, ShortcutEntry, Theme, WorkspaceItem, } from "./state/index";
|
|
28
|
+
export type { AppData, Command, ConfigStore, Currency, Language, NavigationItem, NavigationSection, ShortcutEntry, Theme, WorkspaceItem, } from "./state/index";
|
|
29
|
+
export type { ConnectionState } from "./state/api.svelte";
|
|
31
30
|
export * as sdkMessages from "./paraglide/messages.js";
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// src/lib/index.ts
|
|
2
2
|
// Public surface of rune-lab.
|
|
3
3
|
// ── Devtools utilities ────────────────────────────────────────────────────────
|
|
4
|
-
export { createConfigStore } from "./
|
|
5
|
-
export { createMessageResolver } from "./
|
|
4
|
+
export { createConfigStore } from "./state/createConfigStore.svelte";
|
|
5
|
+
export { createMessageResolver } from "./internal/message-resolver";
|
|
6
6
|
export { RUNE_LAB_CONTEXT } from "./context";
|
|
7
7
|
export { cookieDriver, inMemoryDriver, localStorageDriver, sessionStorageDriver, } from "./persistence/drivers";
|
|
8
8
|
// ── Composables ───────────────────────────────────────────────────────────────
|
|
@@ -15,12 +15,12 @@ export { portal } from "./actions/portal";
|
|
|
15
15
|
export { default as RuneProvider } from "./components/RuneProvider.svelte";
|
|
16
16
|
export { default as Icon } from "./components/Icon.svelte";
|
|
17
17
|
// Core overlays
|
|
18
|
-
export { default as Toaster } from "./
|
|
19
|
-
export { default as ApiMonitor } from "./
|
|
18
|
+
export { default as Toaster } from "./components/Toaster.svelte";
|
|
19
|
+
export { default as ApiMonitor } from "./components/ApiMonitor.svelte";
|
|
20
20
|
export { default as CommandPalette } from "./features/command-palette/CommandPalette.svelte";
|
|
21
21
|
export { default as ShortcutPalette } from "./features/shortcuts/ShortcutPalette.svelte";
|
|
22
22
|
// Layout - Dumb Primitives
|
|
23
|
-
export { default as WorkspaceLayout } from "./layout/WorkspaceLayout.svelte";
|
|
23
|
+
export { default as WorkspaceLayout, } from "./layout/WorkspaceLayout.svelte";
|
|
24
24
|
export { default as WorkspaceStrip } from "./layout/WorkspaceStrip.svelte";
|
|
25
25
|
export { default as NavigationPanel } from "./layout/NavigationPanel.svelte";
|
|
26
26
|
export { default as ContentArea } from "./layout/ContentArea.svelte";
|
|
@@ -29,15 +29,12 @@ export { default as DetailPanel } from "./layout/DetailPanel.svelte";
|
|
|
29
29
|
export { default as ConnectedNavigationPanel } from "./features/layout/smart/ConnectedNavigationPanel.svelte";
|
|
30
30
|
export { default as ConnectedWorkspaceStrip } from "./features/layout/smart/ConnectedWorkspaceStrip.svelte";
|
|
31
31
|
// Setting selectors
|
|
32
|
-
export { default as AppSettingSelector } from "./features/config/
|
|
33
|
-
export { default as ThemeSelector } from "./features/config/
|
|
34
|
-
export { default as LanguageSelector } from "./features/config/
|
|
35
|
-
export { default as CurrencySelector } from "./features/config/
|
|
32
|
+
export { default as AppSettingSelector } from "./features/config/AppSettingSelector.svelte";
|
|
33
|
+
export { default as ThemeSelector } from "./features/config/ThemeSelector.svelte";
|
|
34
|
+
export { default as LanguageSelector } from "./features/config/LanguageSelector.svelte";
|
|
35
|
+
export { default as CurrencySelector } from "./features/config/CurrencySelector.svelte";
|
|
36
36
|
// ── Stores ────────────────────────────────────────────────────────────────────
|
|
37
|
-
export { createApiStore, createAppStore, createCommandStore, createCurrencyStore, createLanguageStore, createLayoutStore, createShortcutStore, createThemeStore, createToastStore, getApiStore, getAppStore, getCommandStore, getCurrencyStore, getLanguageStore, getLayoutStore, getShortcutStore, getThemeStore, getToastStore, } from "./state/index";
|
|
38
|
-
// ── Showcase ──────────────────────────────────────────────────────────────────
|
|
37
|
+
export { createApiStore, createAppStore, createCommandStore, createCurrencyStore, createLanguageStore, createLayoutStore, createShortcutStore, createThemeStore, createToastBridge, createToastStore, getApiStore, getAppStore, getCommandStore, getCurrencyStore, getLanguageStore, getLayoutStore, getShortcutStore, getThemeStore, getToastStore, notify, } from "./state/index";
|
|
39
38
|
export { default as AppStateInspector } from "./showcase/AppStateInspector.svelte";
|
|
40
|
-
export { default as ShowcaseMain } from "./showcase/Showcase.svelte";
|
|
41
|
-
export { default as ShowcaseCard } from "./showcase/ShowcaseCard.svelte";
|
|
42
39
|
// ── Paraglide compiled messages ───────────────────────────────────────────────
|
|
43
40
|
export * as sdkMessages from "./paraglide/messages.js";
|