rune-lab 0.4.2-beta.6 → 0.4.2-beta.8
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/.gitignore +12 -0
- package/deno.json +47 -0
- package/justfile +5 -0
- package/package.json +3 -31
- package/scripts/ci.just +25 -0
- package/scripts/deploy.just +20 -0
- package/scripts/dev.just +4 -0
- package/scripts/inject.just +72 -0
- package/src/app.d.ts +13 -0
- package/src/app.html +12 -0
- package/src/{i18n/message-resolver.test.js → lib/i18n/message-resolver.test.ts} +23 -3
- package/src/{i18n/message-resolver.d.ts → lib/i18n/message-resolver.ts} +47 -9
- package/src/{kernel/src/actions/portal.js → lib/kernel/src/actions/portal.ts} +11 -3
- package/src/{kernel/src/actions/shortcut-listener.js → lib/kernel/src/actions/shortcut-listener.ts} +20 -5
- package/src/lib/kernel/src/context/app.svelte.ts +98 -0
- package/src/{kernel/src/context/context.js → lib/kernel/src/context/context.ts} +17 -2
- package/src/lib/kernel/src/context/stores.svelte.ts +96 -0
- package/src/{kernel/src/context/types.d.ts → lib/kernel/src/context/types.ts} +12 -0
- package/src/{kernel/src/context/useRuneLab.d.ts → lib/kernel/src/context/useRuneLab.ts} +14 -1
- package/src/lib/kernel/src/persistence/createConfigStore.svelte.ts +120 -0
- package/src/{kernel/src/persistence/drivers.test.js → lib/kernel/src/persistence/drivers.test.ts} +17 -1
- package/src/lib/kernel/src/persistence/drivers.ts +77 -0
- package/src/{kernel/src/persistence/provider.test.js → lib/kernel/src/persistence/provider.test.ts} +9 -2
- package/src/{kernel/src/persistence/provider.js → lib/kernel/src/persistence/provider.ts} +17 -4
- package/src/{kernel/src/persistence/types.d.ts → lib/kernel/src/persistence/types.ts} +2 -0
- package/src/lib/kernel/src/persistence/usePersistence.ts +9 -0
- package/src/{kernel/src/registry/mod.d.ts → lib/kernel/src/registry/mod.ts} +116 -14
- package/src/{kernel/src/registry/registry.test.js → lib/kernel/src/registry/registry.test.ts} +58 -17
- package/src/{kernel/src/tokens/props.d.ts → lib/kernel/src/tokens/props.ts} +32 -5
- package/src/{mod.js → lib/mod.ts} +2 -0
- package/src/{runes/layout/src/APP_CONFIGURATIONS.d.ts → lib/runes/layout/src/APP_CONFIGURATIONS.ts} +28 -1
- package/src/{runes/layout/src/connection-factory.d.ts → lib/runes/layout/src/connection-factory.ts} +41 -7
- package/src/{runes/layout/src/language.svelte.js → lib/runes/layout/src/language.svelte.ts} +23 -9
- package/src/{runes/layout/src/mod.js → lib/runes/layout/src/mod.ts} +18 -14
- package/src/{runes/layout/src/store.svelte.js → lib/runes/layout/src/store.svelte.ts} +57 -32
- package/src/{runes/layout/src/theme.svelte.js → lib/runes/layout/src/theme.svelte.ts} +15 -5
- package/src/{runes/layout/src/types.js → lib/runes/layout/src/types.ts} +3 -0
- package/src/lib/runes/palettes/src/commands/store.svelte.ts +80 -0
- package/src/{runes/palettes/src/mod.js → lib/runes/palettes/src/mod.ts} +9 -5
- package/src/{runes/palettes/src/notifications/bridge.js → lib/runes/palettes/src/notifications/bridge.ts} +22 -10
- package/src/{runes/palettes/src/notifications/store.svelte.js → lib/runes/palettes/src/notifications/store.svelte.ts} +24 -9
- package/src/{runes/palettes/src/shortcuts/store.svelte.js → lib/runes/palettes/src/shortcuts/store.svelte.ts} +34 -35
- package/src/{runes/palettes/src/shortcuts/types.js → lib/runes/palettes/src/shortcuts/types.ts} +2 -1
- package/src/{runes/palettes/src/shortcuts/useShortcuts.js → lib/runes/palettes/src/shortcuts/useShortcuts.ts} +16 -7
- package/src/{runes/plugins/money/src/currency.svelte.js → lib/runes/plugins/money/src/currency.svelte.ts} +42 -19
- package/src/{runes/plugins/money/src/currency.test.js → lib/runes/plugins/money/src/currency.test.ts} +10 -2
- package/src/{runes/plugins/money/src/exchange-rate.svelte.js → lib/runes/plugins/money/src/exchange-rate.svelte.ts} +49 -43
- package/src/{runes/plugins/money/src/exchange-rate.test.js → lib/runes/plugins/money/src/exchange-rate.test.ts} +23 -2
- package/src/{runes/plugins/money/src/mod.js → lib/runes/plugins/money/src/mod.ts} +34 -10
- package/src/{runes/plugins/money/src/money-primitive.test.js → lib/runes/plugins/money/src/money-primitive.test.ts} +40 -0
- package/src/{runes/plugins/money/src/money-primitive.js → lib/runes/plugins/money/src/money-primitive.ts} +68 -26
- package/src/{runes/plugins/money/src/money.test.js → lib/runes/plugins/money/src/money.test.ts} +29 -0
- package/src/{runes/plugins/money/src/money.js → lib/runes/plugins/money/src/money.ts} +129 -32
- package/src/{runes/plugins/money/src/strategies.test.js → lib/runes/plugins/money/src/strategies.test.ts} +30 -2
- package/src/{runes/plugins/money/src/strategies.js → lib/runes/plugins/money/src/strategies.ts} +27 -12
- package/src/{runes/plugins/money/src/useMoney.js → lib/runes/plugins/money/src/useMoney.ts} +131 -12
- package/src/{runes/plugins/money/src/useMoneyFilter.js → lib/runes/plugins/money/src/useMoneyFilter.ts} +40 -5
- package/src/routes/+page.svelte +3 -0
- package/tsconfig.json +41 -0
- package/vite.config.ts +30 -0
- package/src/RuneProvider.svelte.d.ts +0 -32
- package/src/i18n/message-resolver.js +0 -49
- package/src/kernel/src/actions/portal.d.ts +0 -10
- package/src/kernel/src/actions/shortcut-listener.d.ts +0 -18
- package/src/kernel/src/context/app.svelte.d.ts +0 -45
- package/src/kernel/src/context/app.svelte.js +0 -89
- package/src/kernel/src/context/context.d.ts +0 -15
- package/src/kernel/src/context/stores.svelte.d.ts +0 -67
- package/src/kernel/src/context/stores.svelte.js +0 -49
- package/src/kernel/src/context/types.js +0 -1
- package/src/kernel/src/context/useRuneLab.js +0 -26
- package/src/kernel/src/mod.js +0 -13
- package/src/kernel/src/persistence/createConfigStore.svelte.d.ts +0 -30
- package/src/kernel/src/persistence/createConfigStore.svelte.js +0 -76
- package/src/kernel/src/persistence/drivers.d.ts +0 -12
- package/src/kernel/src/persistence/drivers.js +0 -87
- package/src/kernel/src/persistence/provider.d.ts +0 -30
- package/src/kernel/src/persistence/types.js +0 -2
- package/src/kernel/src/persistence/usePersistence.d.ts +0 -2
- package/src/kernel/src/persistence/usePersistence.js +0 -5
- package/src/kernel/src/registry/mod.js +0 -140
- package/src/kernel/src/tokens/props.js +0 -35
- package/src/mod.d.ts +0 -5
- package/src/runes/layout/src/APP_CONFIGURATIONS.js +0 -38
- package/src/runes/layout/src/AppSettingSelector.svelte.d.ts +0 -18
- package/src/runes/layout/src/ConnectedNavigationPanel.svelte.d.ts +0 -18
- package/src/runes/layout/src/ConnectedWorkspaceStrip.svelte.d.ts +0 -18
- package/src/runes/layout/src/ContentArea.svelte.d.ts +0 -18
- package/src/runes/layout/src/DetailPanel.svelte.d.ts +0 -18
- package/src/runes/layout/src/Icon.svelte.d.ts +0 -15
- package/src/runes/layout/src/LanguageSelector.svelte.d.ts +0 -18
- package/src/runes/layout/src/NavigationPanel.svelte.d.ts +0 -18
- package/src/runes/layout/src/ResourceSelector.svelte.d.ts +0 -21
- package/src/runes/layout/src/ThemeSelector.svelte.d.ts +0 -18
- package/src/runes/layout/src/WorkspaceLayout.svelte.d.ts +0 -47
- package/src/runes/layout/src/WorkspaceStrip.svelte.d.ts +0 -18
- package/src/runes/layout/src/connection-factory.js +0 -58
- package/src/runes/layout/src/language.svelte.d.ts +0 -50
- package/src/runes/layout/src/mod.d.ts +0 -22
- package/src/runes/layout/src/store.svelte.d.ts +0 -37
- package/src/runes/layout/src/theme.svelte.d.ts +0 -6
- package/src/runes/layout/src/types.d.ts +0 -6
- package/src/runes/palettes/src/commands/CommandPalette.svelte.d.ts +0 -18
- package/src/runes/palettes/src/commands/mod.js +0 -2
- package/src/runes/palettes/src/commands/store.svelte.d.ts +0 -33
- package/src/runes/palettes/src/commands/store.svelte.js +0 -63
- package/src/runes/palettes/src/mod.d.ts +0 -9
- package/src/runes/palettes/src/notifications/NotificationBell.svelte.d.ts +0 -26
- package/src/runes/palettes/src/notifications/Toaster.svelte.d.ts +0 -15
- package/src/runes/palettes/src/notifications/bridge.d.ts +0 -33
- package/src/runes/palettes/src/notifications/mod.js +0 -4
- package/src/runes/palettes/src/notifications/store.svelte.d.ts +0 -23
- package/src/runes/palettes/src/shortcuts/ShortcutPalette.svelte.d.ts +0 -23
- package/src/runes/palettes/src/shortcuts/mod.js +0 -4
- package/src/runes/palettes/src/shortcuts/store.svelte.d.ts +0 -37
- package/src/runes/palettes/src/shortcuts/types.d.ts +0 -1
- package/src/runes/palettes/src/shortcuts/useShortcuts.d.ts +0 -32
- package/src/runes/plugins/money/src/CurrencySelector.svelte.d.ts +0 -18
- package/src/runes/plugins/money/src/MoneyDisplay.svelte.d.ts +0 -18
- package/src/runes/plugins/money/src/MoneyInput.svelte.d.ts +0 -49
- package/src/runes/plugins/money/src/currency.svelte.d.ts +0 -29
- package/src/runes/plugins/money/src/exchange-rate.svelte.d.ts +0 -44
- package/src/runes/plugins/money/src/mod.d.ts +0 -13
- package/src/runes/plugins/money/src/money-primitive.d.ts +0 -106
- package/src/runes/plugins/money/src/money.d.ts +0 -170
- package/src/runes/plugins/money/src/strategies.d.ts +0 -55
- package/src/runes/plugins/money/src/types.js +0 -21
- package/src/runes/plugins/money/src/useMoney.d.ts +0 -69
- package/src/runes/plugins/money/src/useMoneyFilter.d.ts +0 -23
- /package/src/{RuneProvider.svelte → lib/RuneProvider.svelte} +0 -0
- /package/src/{i18n → lib/i18n}/project.inlang/settings.json +0 -0
- /package/src/{i18n → lib/i18n}/translations/ar.json +0 -0
- /package/src/{i18n → lib/i18n}/translations/de.json +0 -0
- /package/src/{i18n → lib/i18n}/translations/en.json +0 -0
- /package/src/{i18n → lib/i18n}/translations/es.json +0 -0
- /package/src/{i18n → lib/i18n}/translations/fr.json +0 -0
- /package/src/{i18n → lib/i18n}/translations/hi.json +0 -0
- /package/src/{i18n → lib/i18n}/translations/it.json +0 -0
- /package/src/{i18n → lib/i18n}/translations/ja.json +0 -0
- /package/src/{i18n → lib/i18n}/translations/ko.json +0 -0
- /package/src/{i18n → lib/i18n}/translations/pt.json +0 -0
- /package/src/{i18n → lib/i18n}/translations/ru.json +0 -0
- /package/src/{i18n → lib/i18n}/translations/vi.json +0 -0
- /package/src/{i18n → lib/i18n}/translations/zh.json +0 -0
- /package/src/{kernel → lib/kernel}/deno.json +0 -0
- /package/src/{kernel/src/mod.d.ts → lib/kernel/src/mod.ts} +0 -0
- /package/src/{runes → lib/runes}/layout/deno.json +0 -0
- /package/src/{runes → lib/runes}/layout/src/AppSettingSelector.svelte +0 -0
- /package/src/{runes → lib/runes}/layout/src/ConnectedNavigationPanel.svelte +0 -0
- /package/src/{runes → lib/runes}/layout/src/ConnectedWorkspaceStrip.svelte +0 -0
- /package/src/{runes → lib/runes}/layout/src/ContentArea.svelte +0 -0
- /package/src/{runes → lib/runes}/layout/src/DetailPanel.svelte +0 -0
- /package/src/{runes → lib/runes}/layout/src/Icon.svelte +0 -0
- /package/src/{runes → lib/runes}/layout/src/LanguageSelector.svelte +0 -0
- /package/src/{runes → lib/runes}/layout/src/NavigationPanel.svelte +0 -0
- /package/src/{runes → lib/runes}/layout/src/ResourceSelector.svelte +0 -0
- /package/src/{runes → lib/runes}/layout/src/ThemeSelector.svelte +0 -0
- /package/src/{runes → lib/runes}/layout/src/WorkspaceLayout.svelte +0 -0
- /package/src/{runes → lib/runes}/layout/src/WorkspaceStrip.svelte +0 -0
- /package/src/{runes → lib/runes}/palettes/deno.json +0 -0
- /package/src/{runes → lib/runes}/palettes/src/commands/CommandPalette.svelte +0 -0
- /package/src/{runes/palettes/src/commands/mod.d.ts → lib/runes/palettes/src/commands/mod.ts} +0 -0
- /package/src/{runes → lib/runes}/palettes/src/notifications/NotificationBell.svelte +0 -0
- /package/src/{runes → lib/runes}/palettes/src/notifications/Toaster.svelte +0 -0
- /package/src/{runes/palettes/src/notifications/mod.d.ts → lib/runes/palettes/src/notifications/mod.ts} +0 -0
- /package/src/{runes → lib/runes}/palettes/src/shortcuts/ShortcutPalette.svelte +0 -0
- /package/src/{runes/palettes/src/shortcuts/mod.d.ts → lib/runes/palettes/src/shortcuts/mod.ts} +0 -0
- /package/src/{runes → lib/runes}/plugins/money/deno.json +0 -0
- /package/src/{runes → lib/runes}/plugins/money/src/CurrencySelector.svelte +0 -0
- /package/src/{runes → lib/runes}/plugins/money/src/MoneyDisplay.svelte +0 -0
- /package/src/{runes → lib/runes}/plugins/money/src/MoneyInput.svelte +0 -0
- /package/src/{runes/plugins/money/src/types.d.ts → lib/runes/plugins/money/src/types.ts} +0 -0
package/.gitignore
ADDED
package/deno.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@yrrrrrf/rune-lab",
|
|
3
|
+
"version": "0.4.2-beta.8",
|
|
4
|
+
"description": "Modern toolkit for Svelte 5 Runes applications.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"readme": "README.md",
|
|
8
|
+
"author": "Fernando Bryan Reza Campos",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/Yrrrrrf/rune-lab.git"
|
|
12
|
+
},
|
|
13
|
+
"exports": {
|
|
14
|
+
".": "./src/lib/mod.ts"
|
|
15
|
+
},
|
|
16
|
+
"nodeModulesDir": "manual",
|
|
17
|
+
"workspace": [
|
|
18
|
+
"./src/lib/kernel",
|
|
19
|
+
"./src/lib/runes/layout",
|
|
20
|
+
"./src/lib/runes/palettes",
|
|
21
|
+
"./src/lib/runes/plugins/money"
|
|
22
|
+
],
|
|
23
|
+
"imports": {
|
|
24
|
+
"@rune-lab/core": "./src/lib/mod.ts",
|
|
25
|
+
"@rune-lab/i18n/": "./src/lib/i18n/",
|
|
26
|
+
"typescript": "npm:typescript@5.9.3",
|
|
27
|
+
"@tailwindcss/vite": "npm:@tailwindcss/vite",
|
|
28
|
+
"esm-env": "npm:esm-env",
|
|
29
|
+
"vite": "npm:vite",
|
|
30
|
+
"vite-plus": "npm:vite-plus",
|
|
31
|
+
"daisyui/": "npm:daisyui/",
|
|
32
|
+
"hotkeys-js": "npm:hotkeys-js",
|
|
33
|
+
"@inlang/paraglide-js": "npm:@inlang/paraglide-js",
|
|
34
|
+
"svelte": "npm:svelte",
|
|
35
|
+
"@sveltejs/kit": "npm:@sveltejs/kit",
|
|
36
|
+
"@sveltejs/vite-plugin-svelte": "npm:@sveltejs/vite-plugin-svelte",
|
|
37
|
+
"@sveltejs/adapter-static": "npm:@sveltejs/adapter-static",
|
|
38
|
+
"jsdom": "npm:jsdom",
|
|
39
|
+
"@testing-library/jest-dom": "npm:@testing-library/jest-dom"
|
|
40
|
+
},
|
|
41
|
+
"exclude": [
|
|
42
|
+
".*",
|
|
43
|
+
"scripts/**",
|
|
44
|
+
"dist/**",
|
|
45
|
+
"**/*.test.ts"
|
|
46
|
+
]
|
|
47
|
+
}
|
package/justfile
ADDED
package/package.json
CHANGED
|
@@ -1,33 +1,5 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rune-lab",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
|
|
6
|
-
"license": "MIT",
|
|
7
|
-
"repository": {
|
|
8
|
-
"type": "git",
|
|
9
|
-
"url": "git+https://github.com/Yrrrrrf/rune-lab.git"
|
|
10
|
-
},
|
|
11
|
-
"type": "module",
|
|
12
|
-
"exports": {
|
|
13
|
-
".": {
|
|
14
|
-
"types": "./src/mod.d.ts",
|
|
15
|
-
"default": "./src/mod.js"
|
|
16
|
-
}
|
|
17
|
-
},
|
|
18
|
-
"peerDependencies": {
|
|
19
|
-
"svelte": "^5.55.0",
|
|
20
|
-
"@sveltejs/kit": "^2.55.0",
|
|
21
|
-
"@inlang/paraglide-js": "^2.15.1",
|
|
22
|
-
"hotkeys-js": "^4.0.2",
|
|
23
|
-
"dinero.js": "^2.0.2",
|
|
24
|
-
"esm-env": "^1.2.2"
|
|
25
|
-
},
|
|
26
|
-
"keywords": [
|
|
27
|
-
"svelte",
|
|
28
|
-
"svelte-5",
|
|
29
|
-
"runes",
|
|
30
|
-
"ui",
|
|
31
|
-
"components"
|
|
32
|
-
]
|
|
33
|
-
}
|
|
3
|
+
"version": "0.4.2-beta.8",
|
|
4
|
+
"packageManager": "pnpm@10.33.0"
|
|
5
|
+
}
|
package/scripts/ci.just
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
[doc('Format Client code')]
|
|
2
|
+
[group('CI')]
|
|
3
|
+
fmt:
|
|
4
|
+
deno fmt .
|
|
5
|
+
@echo "✓ Client code formatted"
|
|
6
|
+
|
|
7
|
+
[doc('Lint Client code')]
|
|
8
|
+
[group('CI')]
|
|
9
|
+
lint:
|
|
10
|
+
deno lint .
|
|
11
|
+
@echo "✓ Client code linted"
|
|
12
|
+
|
|
13
|
+
[doc('Type-check Client workspace')]
|
|
14
|
+
[group('CI')]
|
|
15
|
+
typecheck:
|
|
16
|
+
# check ts types with strict deno.ns
|
|
17
|
+
deno check .
|
|
18
|
+
# check svelte types
|
|
19
|
+
deno run -A npm:svelte-check
|
|
20
|
+
@echo "✓ Client type-checked"
|
|
21
|
+
|
|
22
|
+
[doc('Full client quality gate')]
|
|
23
|
+
[group('CI')]
|
|
24
|
+
quality: fmt lint typecheck
|
|
25
|
+
@echo "✓ Client quality checks passed"
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
[doc('Build Client')]
|
|
2
|
+
[group('Build')]
|
|
3
|
+
build:
|
|
4
|
+
# * Clean up previous build
|
|
5
|
+
rm -rf dist/
|
|
6
|
+
deno run -A npm:@inlang/paraglide-js compile --project ./src/lib/i18n/project.inlang --outdir ./src/lib/i18n/paraglide
|
|
7
|
+
deno run -A npm:@sveltejs/package -- -i src -o dist
|
|
8
|
+
# * Build ESM package
|
|
9
|
+
# deno run -A scripts/build_pkg.ts
|
|
10
|
+
@echo "✓ build done"
|
|
11
|
+
|
|
12
|
+
[doc('Publish to jsr')]
|
|
13
|
+
[group('Deploy')]
|
|
14
|
+
deploy: build
|
|
15
|
+
# * Format build output
|
|
16
|
+
deno fmt --no-config dist
|
|
17
|
+
# * Publish to npm
|
|
18
|
+
(cd dist && bun publish)
|
|
19
|
+
# * Publish to jsr
|
|
20
|
+
@echo "✓ deploy done"
|
package/scripts/dev.just
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# inject.just — surgical local rune-lab injection
|
|
2
|
+
#
|
|
3
|
+
# ⚠ IMPORTANT: `just -f` changes cwd to the justfile's directory.
|
|
4
|
+
# Never pass `.` as dest — pass $PWD or an absolute path instead.
|
|
5
|
+
#
|
|
6
|
+
# Usage:
|
|
7
|
+
# just -f ~/rune-lab/scripts/inject.just inject $PWD
|
|
8
|
+
# just -f ~/rune-lab/scripts/inject.just inject /absolute/path/to/project
|
|
9
|
+
# just -f ~/rune-lab/scripts/inject.just inject-clean $PWD
|
|
10
|
+
#``
|
|
11
|
+
# Recipes:
|
|
12
|
+
# inject — build rune-lab, then hot-swap node_modules/rune-lab
|
|
13
|
+
# inject-clean — full dep reset (yog reborn --deep), then inject
|
|
14
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
15
|
+
|
|
16
|
+
# Hot-swap: rebuild rune-lab and inject into <dest>/node_modules/rune-lab
|
|
17
|
+
inject dest: _build-for-inject
|
|
18
|
+
#!/usr/bin/env bash
|
|
19
|
+
set -euo pipefail
|
|
20
|
+
|
|
21
|
+
dest_abs="{{ dest }}"
|
|
22
|
+
|
|
23
|
+
# Reject relative paths — they resolve to rune-lab's own dir, not the caller's
|
|
24
|
+
if [[ "$dest_abs" != /* ]]; then
|
|
25
|
+
echo "❌ dest must be an absolute path."
|
|
26
|
+
echo " Call with: just -f ... inject \$PWD"
|
|
27
|
+
echo " Got: $dest_abs"
|
|
28
|
+
exit 1
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
if [ ! -d "$dest_abs/node_modules" ]; then
|
|
32
|
+
echo "❌ No node_modules/ found in $dest_abs"
|
|
33
|
+
echo " Run your package manager's install first, then retry."
|
|
34
|
+
exit 1
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
echo "🗑 Removing stale $dest_abs/node_modules/rune-lab..."
|
|
38
|
+
rm -rf "$dest_abs/node_modules/rune-lab"
|
|
39
|
+
|
|
40
|
+
echo "📦 Copying local dist into $dest_abs/node_modules/rune-lab..."
|
|
41
|
+
mkdir -p "$dest_abs/node_modules/rune-lab"
|
|
42
|
+
cp -r "{{ justfile_directory() }}/../dist" "$dest_abs/node_modules/rune-lab/dist"
|
|
43
|
+
cp "{{ justfile_directory() }}/../package.json" "$dest_abs/node_modules/rune-lab/package.json"
|
|
44
|
+
|
|
45
|
+
echo "✅ Done! node_modules/rune-lab → $(du -sh $dest_abs/node_modules/rune-lab | cut -f1)"
|
|
46
|
+
echo " Source: {{ justfile_directory() }}/../dist"
|
|
47
|
+
echo " Target: $dest_abs/node_modules/rune-lab"
|
|
48
|
+
|
|
49
|
+
# Full reset: nuke deps in <dest>, reinstall, then hot-swap rune-lab
|
|
50
|
+
inject-clean dest: _build-for-inject
|
|
51
|
+
#!/usr/bin/env bash
|
|
52
|
+
set -euo pipefail
|
|
53
|
+
|
|
54
|
+
dest_abs="{{ dest }}"
|
|
55
|
+
|
|
56
|
+
if [[ "$dest_abs" != /* ]]; then
|
|
57
|
+
echo "❌ dest must be an absolute path. Call with: just -f ... inject-clean \$PWD"
|
|
58
|
+
exit 1
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
echo "💀 Running yog reborn --deep in $dest_abs..."
|
|
62
|
+
(cd "$dest_abs" && yog reborn --deep)
|
|
63
|
+
|
|
64
|
+
just -f "{{ justfile_directory() }}/inject.just" inject "$dest_abs"
|
|
65
|
+
|
|
66
|
+
# ── Internal ──────────────────────────────────────────────────────────────────
|
|
67
|
+
|
|
68
|
+
[private]
|
|
69
|
+
_build-for-inject:
|
|
70
|
+
@echo "🔨 Building rune-lab from {{ justfile_directory() }}/.."
|
|
71
|
+
just --justfile "{{ justfile_directory() }}/../justfile" --working-directory "{{ justfile_directory() }}/.." build
|
|
72
|
+
@echo "✅ rune-lab built."
|
package/src/app.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// See https://svelte.dev/docs/kit/types#app.d.ts
|
|
2
|
+
// for information about these interfaces
|
|
3
|
+
declare global {
|
|
4
|
+
namespace App {
|
|
5
|
+
// interface Error {}
|
|
6
|
+
// interface Locals {}
|
|
7
|
+
// interface PageData {}
|
|
8
|
+
// interface PageState {}
|
|
9
|
+
// interface Platform {}
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export {};
|
package/src/app.html
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<link rel="icon" href="%sveltekit.assets%/favicon.svg" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
|
+
%sveltekit.head%
|
|
8
|
+
</head>
|
|
9
|
+
<body data-sveltekit-preload-data="hover">
|
|
10
|
+
<div style="display: contents">%sveltekit.body%</div>
|
|
11
|
+
</body>
|
|
12
|
+
</html>
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { describe, expect, it, vi } from "vite-plus/test";
|
|
2
|
+
|
|
2
3
|
// Mock esm-env before importing the module
|
|
3
4
|
vi.mock("esm-env", () => ({ DEV: true }));
|
|
5
|
+
|
|
4
6
|
import {
|
|
5
7
|
batchResolveMessages,
|
|
6
8
|
createMessageResolver,
|
|
7
9
|
hasMessage,
|
|
8
10
|
} from "./message-resolver.ts";
|
|
11
|
+
|
|
9
12
|
describe("MessageResolver", () => {
|
|
10
13
|
const mockMessages = {
|
|
11
14
|
usd: () => "US Dollar",
|
|
@@ -13,70 +16,87 @@ describe("MessageResolver", () => {
|
|
|
13
16
|
mxn: () => "Mexican Peso",
|
|
14
17
|
jpy: () => "Japanese Yen",
|
|
15
18
|
};
|
|
19
|
+
|
|
16
20
|
describe("createMessageResolver", () => {
|
|
17
21
|
it("should resolve a key via keyExtractor", () => {
|
|
18
|
-
const resolver = createMessageResolver(mockMessages, {
|
|
22
|
+
const resolver = createMessageResolver<{ code: string }>(mockMessages, {
|
|
19
23
|
keyExtractor: (opt) => opt.code,
|
|
20
24
|
keyTransformer: (key) => key.toLowerCase(),
|
|
21
25
|
});
|
|
26
|
+
|
|
22
27
|
expect(resolver({ code: "USD" })).toBe("US Dollar");
|
|
23
28
|
expect(resolver({ code: "EUR" })).toBe("Euro");
|
|
24
29
|
});
|
|
30
|
+
|
|
25
31
|
it("should use untransformed key when no transformer provided", () => {
|
|
26
|
-
const resolver = createMessageResolver(mockMessages, {
|
|
32
|
+
const resolver = createMessageResolver<{ code: string }>(mockMessages, {
|
|
27
33
|
keyExtractor: (opt) => opt.code,
|
|
28
34
|
});
|
|
35
|
+
|
|
29
36
|
// Without transformer, keys must match exactly
|
|
30
37
|
expect(resolver({ code: "usd" })).toBe("US Dollar");
|
|
31
38
|
});
|
|
39
|
+
|
|
32
40
|
it("should fall back to the raw key for missing translations", () => {
|
|
33
41
|
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
|
|
34
|
-
|
|
42
|
+
|
|
43
|
+
const resolver = createMessageResolver<{ code: string }>(mockMessages, {
|
|
35
44
|
keyExtractor: (opt) => opt.code,
|
|
36
45
|
keyTransformer: (key) => key.toLowerCase(),
|
|
37
46
|
});
|
|
47
|
+
|
|
38
48
|
const result = resolver({ code: "UNKNOWN" });
|
|
39
49
|
expect(result).toBe("UNKNOWN"); // falls back to original key
|
|
40
50
|
expect(warnSpy).toHaveBeenCalledWith(
|
|
41
51
|
expect.stringContaining("Missing translation"),
|
|
42
52
|
);
|
|
53
|
+
|
|
43
54
|
warnSpy.mockRestore();
|
|
44
55
|
});
|
|
45
56
|
});
|
|
57
|
+
|
|
46
58
|
describe("hasMessage", () => {
|
|
47
59
|
it("should return true for existing keys", () => {
|
|
48
60
|
expect(hasMessage(mockMessages, "usd")).toBe(true);
|
|
49
61
|
expect(hasMessage(mockMessages, "eur")).toBe(true);
|
|
50
62
|
});
|
|
63
|
+
|
|
51
64
|
it("should return false for missing keys", () => {
|
|
52
65
|
expect(hasMessage(mockMessages, "UNKNOWN")).toBe(false);
|
|
53
66
|
expect(hasMessage(mockMessages, "")).toBe(false);
|
|
54
67
|
});
|
|
55
68
|
});
|
|
69
|
+
|
|
56
70
|
describe("batchResolveMessages", () => {
|
|
57
71
|
it("should resolve all options at once", () => {
|
|
58
72
|
const options = [{ code: "USD" }, { code: "EUR" }, { code: "MXN" }];
|
|
73
|
+
|
|
59
74
|
const result = batchResolveMessages(mockMessages, options, {
|
|
60
75
|
keyExtractor: (opt) => opt.code,
|
|
61
76
|
keyTransformer: (key) => key.toLowerCase(),
|
|
62
77
|
});
|
|
78
|
+
|
|
63
79
|
expect(result).toEqual({
|
|
64
80
|
USD: "US Dollar",
|
|
65
81
|
EUR: "Euro",
|
|
66
82
|
MXN: "Mexican Peso",
|
|
67
83
|
});
|
|
68
84
|
});
|
|
85
|
+
|
|
69
86
|
it("should include fallback values for missing keys", () => {
|
|
70
87
|
vi.spyOn(console, "warn").mockImplementation(() => {});
|
|
88
|
+
|
|
71
89
|
const options = [{ code: "USD" }, { code: "XYZ" }];
|
|
72
90
|
const result = batchResolveMessages(mockMessages, options, {
|
|
73
91
|
keyExtractor: (opt) => opt.code,
|
|
74
92
|
keyTransformer: (key) => key.toLowerCase(),
|
|
75
93
|
});
|
|
94
|
+
|
|
76
95
|
expect(result).toEqual({
|
|
77
96
|
USD: "US Dollar",
|
|
78
97
|
XYZ: "XYZ", // fallback
|
|
79
98
|
});
|
|
99
|
+
|
|
80
100
|
vi.restoreAllMocks();
|
|
81
101
|
});
|
|
82
102
|
});
|
|
@@ -1,22 +1,29 @@
|
|
|
1
|
+
// sdk/devtools/src/patterns/message-resolver.ts
|
|
2
|
+
import { DEV } from "esm-env";
|
|
3
|
+
|
|
1
4
|
/**
|
|
2
5
|
* Dynamic i18n Message Resolver Pattern
|
|
3
6
|
*
|
|
4
7
|
* Enables dynamic message function calls for config selectors.
|
|
5
8
|
* Creates a resolver that dynamically looks up and calls message functions.
|
|
6
9
|
*/
|
|
10
|
+
|
|
7
11
|
type MessageBundle = Record<string, (...args: unknown[]) => string>;
|
|
12
|
+
|
|
8
13
|
interface MessageResolverConfig<T> {
|
|
9
14
|
/**
|
|
10
15
|
* Function to extract the message key from an option
|
|
11
16
|
* @example (currency) => currency.code // "USD"
|
|
12
17
|
*/
|
|
13
18
|
keyExtractor: (option: T) => string;
|
|
19
|
+
|
|
14
20
|
/**
|
|
15
21
|
* Optional transformer for the key before message lookup
|
|
16
22
|
* @example (key) => key.toLowerCase() // "USD" -> "usd"
|
|
17
23
|
*/
|
|
18
24
|
keyTransformer?: (key: string) => string;
|
|
19
25
|
}
|
|
26
|
+
|
|
20
27
|
/**
|
|
21
28
|
* Creates a message resolver function for dynamic i18n lookups
|
|
22
29
|
*
|
|
@@ -29,23 +36,54 @@ interface MessageResolverConfig<T> {
|
|
|
29
36
|
* getCurrencyLabel({ code: "EUR", symbol: "€" }); // "Euro"
|
|
30
37
|
* ```
|
|
31
38
|
*/
|
|
32
|
-
export
|
|
39
|
+
export function createMessageResolver<T>(
|
|
33
40
|
messages: MessageBundle,
|
|
34
41
|
config: MessageResolverConfig<T>,
|
|
35
|
-
)
|
|
42
|
+
) {
|
|
43
|
+
return (option: T): string => {
|
|
44
|
+
const key = config.keyExtractor(option);
|
|
45
|
+
const transformedKey = config.keyTransformer
|
|
46
|
+
? config.keyTransformer(key)
|
|
47
|
+
: key;
|
|
48
|
+
|
|
49
|
+
const messageFn = messages[transformedKey];
|
|
50
|
+
|
|
51
|
+
if (!messageFn || typeof messageFn !== "function") {
|
|
52
|
+
if (DEV) {
|
|
53
|
+
console.warn(
|
|
54
|
+
`[MessageResolver] Missing translation for key: "${transformedKey}"`,
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
return key; // Fallback to key
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return messageFn();
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
36
64
|
/**
|
|
37
65
|
* Type guard to check if a message key exists
|
|
38
66
|
*/
|
|
39
|
-
export
|
|
40
|
-
messages
|
|
41
|
-
|
|
42
|
-
|
|
67
|
+
export function hasMessage(messages: MessageBundle, key: string): boolean {
|
|
68
|
+
return key in messages && typeof messages[key] === "function";
|
|
69
|
+
}
|
|
70
|
+
|
|
43
71
|
/**
|
|
44
72
|
* Batch resolver for multiple options at once
|
|
45
73
|
*/
|
|
46
|
-
export
|
|
74
|
+
export function batchResolveMessages<T>(
|
|
47
75
|
messages: MessageBundle,
|
|
48
76
|
options: T[],
|
|
49
77
|
config: MessageResolverConfig<T>,
|
|
50
|
-
): Record<string, string
|
|
51
|
-
|
|
78
|
+
): Record<string, string> {
|
|
79
|
+
const resolver = createMessageResolver(messages, config);
|
|
80
|
+
|
|
81
|
+
return options.reduce(
|
|
82
|
+
(acc, option) => {
|
|
83
|
+
const key = config.keyExtractor(option);
|
|
84
|
+
acc[key] = resolver(option);
|
|
85
|
+
return acc;
|
|
86
|
+
},
|
|
87
|
+
{} as Record<string, string>,
|
|
88
|
+
);
|
|
89
|
+
}
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import { DEV } from "esm-env";
|
|
2
|
+
|
|
2
3
|
/**
|
|
3
4
|
* Svelte action to teleport a DOM element to a different target (e.g. body)
|
|
4
5
|
*/
|
|
5
|
-
export function portal(
|
|
6
|
-
|
|
6
|
+
export function portal(
|
|
7
|
+
node: HTMLElement,
|
|
8
|
+
target: string | HTMLElement = "body",
|
|
9
|
+
): { update(newTarget: string | HTMLElement): void; destroy(): void } {
|
|
10
|
+
let targetNode: HTMLElement | null;
|
|
7
11
|
let isTeleported = false;
|
|
8
|
-
|
|
12
|
+
|
|
13
|
+
function update(newTarget: string | HTMLElement) {
|
|
9
14
|
if (typeof newTarget === "string") {
|
|
10
15
|
targetNode = document.querySelector(newTarget);
|
|
11
16
|
if (!targetNode && DEV) {
|
|
@@ -16,12 +21,15 @@ export function portal(node, target = "body") {
|
|
|
16
21
|
} else {
|
|
17
22
|
targetNode = newTarget;
|
|
18
23
|
}
|
|
24
|
+
|
|
19
25
|
if (targetNode) {
|
|
20
26
|
targetNode.appendChild(node);
|
|
21
27
|
isTeleported = true;
|
|
22
28
|
}
|
|
23
29
|
}
|
|
30
|
+
|
|
24
31
|
update(target);
|
|
32
|
+
|
|
25
33
|
return {
|
|
26
34
|
update,
|
|
27
35
|
destroy() {
|
package/src/{kernel/src/actions/shortcut-listener.js → lib/kernel/src/actions/shortcut-listener.ts}
RENAMED
|
@@ -1,31 +1,46 @@
|
|
|
1
1
|
import hotkeys from "hotkeys-js";
|
|
2
2
|
import { untrack } from "svelte";
|
|
3
|
+
|
|
4
|
+
export interface ShortcutStoreLike {
|
|
5
|
+
entries: {
|
|
6
|
+
enabled?: boolean;
|
|
7
|
+
keys: string;
|
|
8
|
+
when?: () => boolean;
|
|
9
|
+
handler: (event: KeyboardEvent) => void;
|
|
10
|
+
}[];
|
|
11
|
+
}
|
|
12
|
+
|
|
3
13
|
/**
|
|
4
14
|
* Svelte Action to listen for shortcuts registered in shortcutStore.
|
|
5
15
|
* Applied to the root element of the layout.
|
|
6
16
|
*/
|
|
7
|
-
export function shortcutListener(
|
|
17
|
+
export function shortcutListener(
|
|
18
|
+
_node: HTMLElement,
|
|
19
|
+
shortcutStore: ShortcutStoreLike,
|
|
20
|
+
): { destroy(): void } {
|
|
8
21
|
// Use $effect to reactively sync shortcuts
|
|
9
22
|
const cleanup = $effect.root(() => {
|
|
10
23
|
$effect(() => {
|
|
11
24
|
// Unbind everything first to ensure clean state
|
|
12
25
|
hotkeys.unbind();
|
|
26
|
+
|
|
13
27
|
// We read entries here, so this effect re-runs when entries change.
|
|
14
28
|
for (const entry of shortcutStore.entries) {
|
|
15
29
|
// @ts-ignore: enabled might not be on the interface but we check it anyway
|
|
16
|
-
if (entry.enabled === false)
|
|
17
|
-
|
|
18
|
-
}
|
|
30
|
+
if (entry.enabled === false) continue;
|
|
31
|
+
|
|
19
32
|
hotkeys(entry.keys, "all", (event, _handler) => {
|
|
20
33
|
// Check "when" predicate if it exists
|
|
21
|
-
if (entry.when && !untrack(() => entry.when())) {
|
|
34
|
+
if (entry.when && !untrack(() => entry.when!())) {
|
|
22
35
|
return;
|
|
23
36
|
}
|
|
37
|
+
|
|
24
38
|
entry.handler(event);
|
|
25
39
|
});
|
|
26
40
|
}
|
|
27
41
|
});
|
|
28
42
|
});
|
|
43
|
+
|
|
29
44
|
return {
|
|
30
45
|
destroy() {
|
|
31
46
|
cleanup();
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// src/kernel/src/context/app.svelte.ts
|
|
2
|
+
import { getContext } from "svelte";
|
|
3
|
+
import { RUNE_LAB_CONTEXT } from "./context.ts";
|
|
4
|
+
import { DEV } from "esm-env";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Application metadata interface
|
|
8
|
+
*/
|
|
9
|
+
export interface AppData {
|
|
10
|
+
name: string;
|
|
11
|
+
version: string;
|
|
12
|
+
description: string;
|
|
13
|
+
author: string;
|
|
14
|
+
repository?: string;
|
|
15
|
+
license?: string;
|
|
16
|
+
homepage?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* App Store
|
|
21
|
+
* Manages application metadata and identity
|
|
22
|
+
*/
|
|
23
|
+
export class AppStore {
|
|
24
|
+
// State
|
|
25
|
+
name: string = $state("Rune Lab");
|
|
26
|
+
version: string = $state("0.0.1");
|
|
27
|
+
description: string = $state("Modern toolkit for Svelte 5 Runes");
|
|
28
|
+
author: string = $state("Yrrrrrf");
|
|
29
|
+
repository: string = $state("https://github.com/Yrrrrrf/rune-lab");
|
|
30
|
+
license: string = $state("MIT");
|
|
31
|
+
homepage: string = $state("https://jsr.io/@yrrrrrf/rune-lab");
|
|
32
|
+
customIcons: Record<string, string> = $state<Record<string, string>>({});
|
|
33
|
+
|
|
34
|
+
#initialized = false;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Initialize app store with metadata.
|
|
38
|
+
*/
|
|
39
|
+
init(data: Partial<AppData>): void {
|
|
40
|
+
if (this.#initialized) {
|
|
41
|
+
if (DEV) {
|
|
42
|
+
console.warn(
|
|
43
|
+
"AppStore.init() called multiple times. Ignoring subsequent calls.",
|
|
44
|
+
"Overwritten properties would have been:",
|
|
45
|
+
data,
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (data.name) this.name = data.name;
|
|
52
|
+
if (data.version) this.version = data.version;
|
|
53
|
+
if (data.description) this.description = data.description;
|
|
54
|
+
if (data.author) this.author = data.author;
|
|
55
|
+
if (data.repository) this.repository = data.repository;
|
|
56
|
+
if (data.license) this.license = data.license;
|
|
57
|
+
if (data.homepage) this.homepage = data.homepage;
|
|
58
|
+
|
|
59
|
+
this.#initialized = true;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @internal Test-only. Resets initialization guard.
|
|
64
|
+
*/
|
|
65
|
+
__reset(): void {
|
|
66
|
+
this.#initialized = false;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Get full app information object
|
|
71
|
+
*/
|
|
72
|
+
get info(): AppData {
|
|
73
|
+
return {
|
|
74
|
+
name: this.name,
|
|
75
|
+
version: this.version,
|
|
76
|
+
description: this.description,
|
|
77
|
+
author: this.author,
|
|
78
|
+
repository: this.repository,
|
|
79
|
+
license: this.license,
|
|
80
|
+
homepage: this.homepage,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Registers custom SVG icons to be available globally in the Icon component
|
|
86
|
+
*/
|
|
87
|
+
registerIcons(icons: Record<string, string>) {
|
|
88
|
+
this.customIcons = { ...this.customIcons, ...icons };
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function createAppStore(): AppStore {
|
|
93
|
+
return new AppStore();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function getAppStore(): AppStore {
|
|
97
|
+
return getContext<AppStore>(RUNE_LAB_CONTEXT.app);
|
|
98
|
+
}
|
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
// src/lib/context.ts
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
export const RUNE_LAB_CONTEXT: {
|
|
4
|
+
app: symbol;
|
|
5
|
+
api: symbol;
|
|
6
|
+
toast: symbol;
|
|
7
|
+
theme: symbol;
|
|
8
|
+
language: symbol;
|
|
9
|
+
currency: symbol;
|
|
10
|
+
shortcut: symbol;
|
|
11
|
+
layout: symbol;
|
|
12
|
+
commands: symbol;
|
|
13
|
+
persistence: symbol;
|
|
14
|
+
cart: symbol;
|
|
15
|
+
session: symbol;
|
|
16
|
+
exchangeRate: symbol;
|
|
17
|
+
} = {
|
|
3
18
|
app: Symbol("rl:app"),
|
|
4
19
|
api: Symbol("rl:api"),
|
|
5
20
|
toast: Symbol("rl:toast"),
|
|
@@ -13,4 +28,4 @@ export const RUNE_LAB_CONTEXT = {
|
|
|
13
28
|
cart: Symbol("rl:cart"),
|
|
14
29
|
session: Symbol("rl:session"),
|
|
15
30
|
exchangeRate: Symbol("rl:exchange-rate"),
|
|
16
|
-
};
|
|
31
|
+
} as const;
|