rune-lab 0.0.19 → 0.0.21

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 (88) hide show
  1. package/README.md +28 -6
  2. package/dist/actions/portal.js +6 -1
  3. package/dist/components/Icon.svelte +13 -2
  4. package/dist/components/RuneProvider.svelte +81 -0
  5. package/dist/components/RuneProvider.svelte.d.ts +9 -0
  6. package/dist/composables/usePersistence.d.ts +2 -0
  7. package/dist/composables/usePersistence.js +5 -0
  8. package/dist/composables/useRuneLab.d.ts +17 -0
  9. package/dist/composables/useRuneLab.js +19 -0
  10. package/dist/config.d.ts +4 -85
  11. package/dist/config.js +6 -32
  12. package/dist/context.d.ts +12 -0
  13. package/dist/context.js +13 -0
  14. package/dist/devtools/API_Monitor.svelte +5 -2
  15. package/dist/devtools/Toaster.svelte +14 -12
  16. package/dist/devtools/createConfigStore.svelte.d.ts +11 -1
  17. package/dist/devtools/createConfigStore.svelte.js +13 -11
  18. package/dist/features/command-palette/CommandPalette.svelte +12 -4
  19. package/dist/features/config/components/AppSettingSelector.svelte +85 -3
  20. package/dist/features/config/components/AppSettingSelector.svelte.d.ts +2 -0
  21. package/dist/features/config/components/CurrencySelector.svelte +27 -9
  22. package/dist/features/config/components/CurrencySelector.svelte.d.ts +3 -1
  23. package/dist/features/config/components/LanguageSelector.svelte +21 -6
  24. package/dist/features/config/components/LanguageSelector.svelte.d.ts +3 -1
  25. package/dist/features/config/components/ThemeSelector.svelte +23 -8
  26. package/dist/features/config/components/ThemeSelector.svelte.d.ts +3 -1
  27. package/dist/features/detail-panels/DashboardPanel.svelte +34 -17
  28. package/dist/features/detail-panels/ShortcutsPanel.svelte +185 -88
  29. package/dist/features/detail-panels/ShowcasePanel.svelte +20 -6
  30. package/dist/features/layout/smart/ConnectedNavigationPanel.svelte +30 -0
  31. package/dist/features/layout/smart/ConnectedNavigationPanel.svelte.d.ts +10 -0
  32. package/dist/features/layout/smart/ConnectedWorkspaceStrip.svelte +23 -0
  33. package/dist/features/layout/smart/ConnectedWorkspaceStrip.svelte.d.ts +9 -0
  34. package/dist/features/shortcuts/ShortcutPalette.svelte +14 -6
  35. package/dist/index.d.ts +14 -2
  36. package/dist/index.js +19 -8
  37. package/dist/layout/NavigationPanel.svelte +97 -121
  38. package/dist/layout/NavigationPanel.svelte.d.ts +5 -1
  39. package/dist/layout/WorkspaceLayout.svelte +109 -30
  40. package/dist/layout/WorkspaceLayout.svelte.d.ts +2 -2
  41. package/dist/layout/WorkspaceStrip.svelte +17 -12
  42. package/dist/layout/WorkspaceStrip.svelte.d.ts +3 -1
  43. package/dist/layout/index.d.ts +1 -1
  44. package/dist/layout/index.js +1 -1
  45. package/dist/paraglide/runtime.d.ts +43 -2
  46. package/dist/paraglide/runtime.js +143 -23
  47. package/dist/paraglide/server.js +37 -14
  48. package/dist/persistence/drivers.d.ts +10 -0
  49. package/dist/persistence/drivers.js +71 -0
  50. package/dist/persistence/types.d.ts +17 -0
  51. package/dist/persistence/types.js +2 -0
  52. package/dist/showcase/AppStateInspector.svelte +26 -11
  53. package/dist/showcase/Showcase.svelte +4 -1
  54. package/dist/state/api.svelte.d.ts +3 -3
  55. package/dist/state/api.svelte.js +9 -2
  56. package/dist/state/app.svelte.d.ts +3 -3
  57. package/dist/state/app.svelte.js +14 -4
  58. package/dist/state/commands.svelte.d.ts +21 -4
  59. package/dist/state/commands.svelte.js +22 -94
  60. package/dist/state/currency.svelte.d.ts +4 -1
  61. package/dist/state/currency.svelte.js +16 -8
  62. package/dist/state/index.d.ts +9 -9
  63. package/dist/state/index.js +10 -9
  64. package/dist/state/language.svelte.d.ts +4 -1
  65. package/dist/state/language.svelte.js +27 -8
  66. package/dist/state/layout.svelte.d.ts +10 -3
  67. package/dist/state/layout.svelte.js +56 -14
  68. package/dist/state/shortcuts.svelte.d.ts +56 -6
  69. package/dist/state/shortcuts.svelte.js +21 -69
  70. package/dist/state/theme.svelte.d.ts +4 -1
  71. package/dist/state/theme.svelte.js +16 -8
  72. package/dist/state/toast.svelte.d.ts +3 -3
  73. package/dist/state/toast.svelte.js +9 -2
  74. package/package.json +9 -9
  75. package/dist/features/command-palette/commands.svelte.d.ts +0 -8
  76. package/dist/features/command-palette/commands.svelte.js +0 -5
  77. package/dist/features/config/stores/api.svelte.d.ts +0 -13
  78. package/dist/features/config/stores/api.svelte.js +0 -5
  79. package/dist/features/config/stores/app.svelte.d.ts +0 -13
  80. package/dist/features/config/stores/app.svelte.js +0 -5
  81. package/dist/features/config/stores/currency.svelte.d.ts +0 -8
  82. package/dist/features/config/stores/currency.svelte.js +0 -5
  83. package/dist/features/config/stores/language.svelte.d.ts +0 -8
  84. package/dist/features/config/stores/language.svelte.js +0 -5
  85. package/dist/features/config/stores/theme.svelte.d.ts +0 -8
  86. package/dist/features/config/stores/theme.svelte.js +0 -5
  87. package/dist/features/config/stores/toast.svelte.d.ts +0 -9
  88. package/dist/features/config/stores/toast.svelte.js +0 -5
@@ -1,16 +1,98 @@
1
1
  <script lang="ts">
2
2
  import { type Snippet } from "svelte";
3
3
 
4
- let { options, value, item, triggerLabel, tooltip } = $props<{
4
+ let {
5
+ options,
6
+ value,
7
+ item,
8
+ triggerLabel,
9
+ tooltip,
10
+ direction = "bottom",
11
+ responsive = true,
12
+ } = $props<{
5
13
  options: any[];
6
14
  value: any;
7
15
  item: Snippet<[any]>;
8
16
  triggerLabel: Snippet<[any]>;
9
17
  tooltip?: string;
18
+ direction?: "top" | "bottom" | "left" | "right" | "end";
19
+ responsive?: boolean;
10
20
  }>();
21
+
22
+ let modal = $state<HTMLDialogElement>();
23
+
24
+ // Use derived to compute the class, though simple reactive assignment works too
25
+ const directionClass = $derived(
26
+ (() => {
27
+ switch (direction) {
28
+ case "top":
29
+ return "dropdown-top";
30
+ case "left":
31
+ return "dropdown-left";
32
+ case "right":
33
+ return "dropdown-right";
34
+ case "end":
35
+ return "dropdown-end"; // same as right in LTR, but specifically for alignment
36
+ default:
37
+ return "dropdown-bottom";
38
+ }
39
+ })(),
40
+ );
11
41
  </script>
12
42
 
13
- <div class="dropdown dropdown-end">
43
+ <!-- Mobile Modal Implementation -->
44
+ {#if responsive}
45
+ <div class="md:hidden inline-block">
46
+ <button
47
+ type="button"
48
+ class="btn btn-ghost btn-sm m-1 h-auto min-h-[2rem] px-2"
49
+ onclick={() => modal?.showModal()}
50
+ >
51
+ <span class="flex items-center gap-2">
52
+ {@render triggerLabel(value)}
53
+ </span>
54
+ </button>
55
+
56
+ <dialog bind:this={modal} class="modal modal-bottom sm:modal-middle">
57
+ <div class="modal-box p-0 overflow-hidden">
58
+ <div
59
+ class="p-4 bg-base-200 border-b border-base-300 flex justify-between items-center"
60
+ >
61
+ <h3 class="font-bold text-lg">Select Option</h3>
62
+ <form method="dialog">
63
+ <button class="btn btn-sm btn-circle btn-ghost"
64
+ >✕</button
65
+ >
66
+ </form>
67
+ </div>
68
+ <div class="max-h-[60vh] overflow-y-auto p-2">
69
+ <ul class="menu bg-base-100 w-full p-0">
70
+ {#each options as option}
71
+ <li class="border-b border-base-100 last:border-0">
72
+ <button
73
+ class="w-full text-left py-3"
74
+ onclick={() => modal?.close()}
75
+ >
76
+ {@render item(option)}
77
+ </button>
78
+ </li>
79
+ {/each}
80
+ </ul>
81
+ </div>
82
+ </div>
83
+ <form method="dialog" class="modal-backdrop">
84
+ <button>close</button>
85
+ </form>
86
+ </dialog>
87
+ </div>
88
+ {/if}
89
+
90
+ <!-- Desktop Dropdown Implementation -->
91
+ <div
92
+ class="dropdown {directionClass} {responsive
93
+ ? 'hidden md:inline-block'
94
+ : 'inline-block'}"
95
+ >
14
96
  <div
15
97
  tabindex="0"
16
98
  role="button"
@@ -25,7 +107,7 @@
25
107
  </div>
26
108
 
27
109
  <ul
28
- class="menu dropdown-content bg-base-100 rounded-box z-1 w-52 p-2 shadow-sm max-h-96 overflow-y-auto border border-base-200"
110
+ 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"
29
111
  >
30
112
  {#each options as option}
31
113
  <li>
@@ -5,6 +5,8 @@ type $$ComponentProps = {
5
5
  item: Snippet<[any]>;
6
6
  triggerLabel: Snippet<[any]>;
7
7
  tooltip?: string;
8
+ direction?: "top" | "bottom" | "left" | "right" | "end";
9
+ responsive?: boolean;
8
10
  };
9
11
  declare const AppSettingSelector: import("svelte").Component<$$ComponentProps, {}, "">;
10
12
  type AppSettingSelector = ReturnType<typeof AppSettingSelector>;
@@ -1,13 +1,27 @@
1
1
  <script lang="ts">
2
2
  import AppSettingSelector from "./AppSettingSelector.svelte";
3
- import { currencyStore, type Currency } from "../../../state/currency.svelte";
3
+ import {
4
+ getCurrencyStore,
5
+ type Currency,
6
+ } from "../../../state/currency.svelte";
7
+
8
+ const currencyStore = getCurrencyStore();
9
+
4
10
  import * as m from "../../../paraglide/messages.js";
5
11
  import { createMessageResolver } from "../../../devtools/message-resolver";
6
12
 
7
- let { codes = [] }: { codes?: string[] } = $props();
13
+ let {
14
+ codes = [],
15
+ current = $bindable(String(currencyStore.current)),
16
+ onchange,
17
+ }: {
18
+ codes?: string[];
19
+ current?: string;
20
+ onchange?: (value: string) => void;
21
+ } = $props();
8
22
 
9
23
  const getLabel = createMessageResolver<Currency>(m as any, {
10
- keyExtractor: (c) => c.code,
24
+ keyExtractor: (c) => String(c.code),
11
25
  });
12
26
 
13
27
  let active = $derived(
@@ -15,14 +29,14 @@
15
29
  );
16
30
 
17
31
  let available = $derived(
18
- codes.length > 0
19
- ? currencyStore.available.filter(c => codes.includes(c.code))
20
- : currencyStore.available
32
+ codes.length > 0
33
+ ? currencyStore.available.filter((c) => codes.includes(c.code))
34
+ : currencyStore.available,
21
35
  );
22
36
  </script>
23
37
 
24
- <AppSettingSelector
25
- value={active}
38
+ <AppSettingSelector
39
+ value={active}
26
40
  options={available}
27
41
  tooltip={getLabel(active)}
28
42
  >
@@ -33,7 +47,11 @@
33
47
  {#snippet item(c)}
34
48
  <button
35
49
  class="flex items-center gap-3 w-full"
36
- onclick={() => currencyStore.set(c.code)}
50
+ onclick={() => {
51
+ currencyStore.set(c.code);
52
+ current = c.code;
53
+ onchange?.(c.code);
54
+ }}
37
55
  >
38
56
  <span class="badge badge-sm badge-ghost w-8">{c.symbol}</span>
39
57
  <span>{getLabel(c)}</span>
@@ -1,6 +1,8 @@
1
1
  type $$ComponentProps = {
2
2
  codes?: string[];
3
+ current?: string;
4
+ onchange?: (value: string) => void;
3
5
  };
4
- declare const CurrencySelector: import("svelte").Component<$$ComponentProps, {}, "">;
6
+ declare const CurrencySelector: import("svelte").Component<$$ComponentProps, {}, "current">;
5
7
  type CurrencySelector = ReturnType<typeof CurrencySelector>;
6
8
  export default CurrencySelector;
@@ -1,12 +1,25 @@
1
1
  <script lang="ts">
2
2
  import AppSettingSelector from "./AppSettingSelector.svelte";
3
- import { languageStore, type Language } from "../../../state/language.svelte";
3
+ import {
4
+ getLanguageStore,
5
+ type Language,
6
+ } from "../../../state/language.svelte";
7
+
8
+ const languageStore = getLanguageStore();
9
+
4
10
  import { setLocale, locales } from "../../../paraglide/runtime";
5
11
  import * as m from "../../../paraglide/messages.js";
6
12
  import { createMessageResolver } from "../../../devtools/message-resolver";
7
13
 
8
-
9
- let { languages: allowedLocales = locales }: { languages?: ReadonlyArray<string> } = $props();
14
+ let {
15
+ languages: allowedLocales = locales,
16
+ current = $bindable(languageStore.current),
17
+ onchange,
18
+ }: {
19
+ languages?: ReadonlyArray<string>;
20
+ current?: string;
21
+ onchange?: (value: string) => void;
22
+ } = $props();
10
23
 
11
24
  const getLabel = createMessageResolver<Language>(m as any, {
12
25
  keyExtractor: (l) => l.code,
@@ -23,8 +36,8 @@
23
36
  );
24
37
  </script>
25
38
 
26
- <AppSettingSelector
27
- value={active}
39
+ <AppSettingSelector
40
+ value={active}
28
41
  options={available}
29
42
  tooltip={getLabel(active)}
30
43
  >
@@ -37,7 +50,9 @@
37
50
  class="flex items-center gap-3 w-full"
38
51
  onclick={() => {
39
52
  languageStore.set(l.code);
40
- setLocale(l.code);
53
+ setLocale(l.code as any);
54
+ current = l.code;
55
+ onchange?.(l.code);
41
56
  }}
42
57
  >
43
58
  <span class="text-lg">{l.flag}</span>
@@ -1,6 +1,8 @@
1
1
  type $$ComponentProps = {
2
2
  languages?: ReadonlyArray<string>;
3
+ current?: string;
4
+ onchange?: (value: string) => void;
3
5
  };
4
- declare const LanguageSelector: import("svelte").Component<$$ComponentProps, {}, "">;
6
+ declare const LanguageSelector: import("svelte").Component<$$ComponentProps, {}, "current">;
5
7
  type LanguageSelector = ReturnType<typeof LanguageSelector>;
6
8
  export default LanguageSelector;
@@ -1,10 +1,21 @@
1
1
  <script lang="ts">
2
2
  import AppSettingSelector from "./AppSettingSelector.svelte";
3
- import { themeStore, type Theme } from "../../../state/theme.svelte";
3
+ import { getThemeStore, type Theme } from "../../../state/theme.svelte";
4
+
5
+ const themeStore = getThemeStore();
6
+
4
7
  import * as m from "../../../paraglide/messages.js";
5
8
  import { createMessageResolver } from "../../../devtools/message-resolver";
6
9
 
7
- let { themes = [] }: { themes?: string[] } = $props();
10
+ let {
11
+ themes = [],
12
+ current = $bindable(themeStore.current),
13
+ onchange,
14
+ }: {
15
+ themes?: string[];
16
+ current?: string;
17
+ onchange?: (value: string) => void;
18
+ } = $props();
8
19
 
9
20
  const getThemeLabel = createMessageResolver<Theme>(m as any, {
10
21
  keyExtractor: (t) => t.name,
@@ -16,14 +27,14 @@
16
27
 
17
28
  let available = $derived(
18
29
  themes.length > 0
19
- ? themeStore.available.filter(t => themes.includes(t.name))
20
- : themeStore.available
30
+ ? themeStore.available.filter((t) => themes.includes(t.name))
31
+ : themeStore.available,
21
32
  );
22
33
  </script>
23
34
 
24
- <AppSettingSelector
25
- value={activeTheme}
26
- options={available}
35
+ <AppSettingSelector
36
+ value={activeTheme}
37
+ options={available}
27
38
  tooltip={getThemeLabel(activeTheme)}
28
39
  >
29
40
  {#snippet triggerLabel(t)}
@@ -33,7 +44,11 @@
33
44
  {#snippet item(t)}
34
45
  <button
35
46
  class="flex items-center gap-3 w-full"
36
- onclick={() => themeStore.set(t.name)}
47
+ onclick={() => {
48
+ themeStore.set(t.name);
49
+ current = t.name;
50
+ onchange?.(t.name);
51
+ }}
37
52
  >
38
53
  <input
39
54
  type="radio"
@@ -1,6 +1,8 @@
1
1
  type $$ComponentProps = {
2
2
  themes?: string[];
3
+ current?: string;
4
+ onchange?: (value: string) => void;
3
5
  };
4
- declare const ThemeSelector: import("svelte").Component<$$ComponentProps, {}, "">;
6
+ declare const ThemeSelector: import("svelte").Component<$$ComponentProps, {}, "current">;
5
7
  type ThemeSelector = ReturnType<typeof ThemeSelector>;
6
8
  export default ThemeSelector;
@@ -1,13 +1,21 @@
1
1
  <script lang="ts">
2
- import { appConfig } from "../../config";
3
- import { toastStore } from "../../state/toast.svelte";
4
- import { apiStore } from "../../state/api.svelte";
5
- import { themeStore } from "../../state/theme.svelte";
6
- import { shortcutStore } from "../../state/shortcuts.svelte";
7
- import { commandStore } from "../../state/commands.svelte";
8
- import { appStore } from "../../state/app.svelte";
9
- import { languageStore } from "../../state/language.svelte";
10
- import { currencyStore } from "../../state/currency.svelte";
2
+ import { getToastStore } from "../../state/toast.svelte";
3
+
4
+ import { getApiStore } from "../../state/api.svelte";
5
+ import { getThemeStore } from "../../state/theme.svelte";
6
+ import { getShortcutStore } from "../../state/shortcuts.svelte";
7
+ // import { getCommandStore } from "../../state/commands.svelte";
8
+ import { getAppStore } from "../../state/app.svelte";
9
+ import { getLanguageStore } from "../../state/language.svelte";
10
+ import { getCurrencyStore } from "../../state/currency.svelte";
11
+
12
+ const appStore = getAppStore();
13
+ const apiStore = getApiStore();
14
+ const themeStore = getThemeStore();
15
+ const shortcutStore = getShortcutStore();
16
+ const toastStore = getToastStore();
17
+ const languageStore = getLanguageStore();
18
+ // const currencyStore = getCurrencyStore();
11
19
 
12
20
  let beat = $state(false);
13
21
  let logs = $state<{ time: string; what: string }[]>([]);
@@ -24,7 +32,7 @@
24
32
  );
25
33
 
26
34
  $effect(() => {
27
- stateHash;
35
+ stateHash; // Subscribe
28
36
  beat = true;
29
37
  const timer = setTimeout(() => (beat = false), 300);
30
38
 
@@ -44,7 +52,9 @@
44
52
  // Section 3: Quick-fire actions
45
53
  function cycleTheme() {
46
54
  const themes = themeStore.available;
47
- const currentIndex = themes.findIndex((t) => t.name === themeStore.current);
55
+ const currentIndex = themes.findIndex(
56
+ (t) => t.name === themeStore.current,
57
+ );
48
58
  const nextIndex = (currentIndex + 1) % themes.length;
49
59
  themeStore.set(themes[nextIndex].name);
50
60
  }
@@ -92,8 +102,7 @@
92
102
  </tr>
93
103
  <tr>
94
104
  <td class="opacity-50">Shortcuts</td>
95
- <td class="font-mono"
96
- >{shortcutStore.entries.length}</td
105
+ <td class="font-mono">{shortcutStore.entries.length}</td
97
106
  >
98
107
  </tr>
99
108
  </tbody>
@@ -137,16 +146,24 @@
137
146
  {#each logs as log, i}
138
147
  <li>
139
148
  {#if i !== 0}<hr class="bg-base-content/10" />{/if}
140
- <div class="timeline-start font-mono text-[10px] opacity-40">
149
+ <div
150
+ class="timeline-start font-mono text-[10px] opacity-40"
151
+ >
141
152
  {log.time}
142
153
  </div>
143
154
  <div class="timeline-middle">
144
- <div class="w-1.5 h-1.5 rounded-full bg-primary/50"></div>
155
+ <div
156
+ class="w-1.5 h-1.5 rounded-full bg-primary/50"
157
+ ></div>
145
158
  </div>
146
- <div class="timeline-end text-[10px] truncate max-w-[160px]">
159
+ <div
160
+ class="timeline-end text-[10px] truncate max-w-[160px]"
161
+ >
147
162
  {log.what}
148
163
  </div>
149
- {#if i !== logs.length - 1}<hr class="bg-base-content/10" />{/if}
164
+ {#if i !== logs.length - 1}<hr
165
+ class="bg-base-content/10"
166
+ />{/if}
150
167
  </li>
151
168
  {/each}
152
169
  </ul>