sh3-core 0.5.4 → 0.5.6

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.

Potentially problematic release.


This version of sh3-core might be problematic. Click here for more details.

package/dist/build.js CHANGED
@@ -112,7 +112,7 @@ export function sh3Artifact(options = {}) {
112
112
  }
113
113
  },
114
114
  async closeBundle() {
115
- var _a, _b, _c, _d;
115
+ var _a, _b, _c, _d, _e;
116
116
  if (!entryFileName)
117
117
  return;
118
118
  const clientSrc = join(outDir, entryFileName);
@@ -122,7 +122,7 @@ export function sh3Artifact(options = {}) {
122
122
  try {
123
123
  source = readFileSync(clientSrc, 'utf-8');
124
124
  }
125
- catch (_e) {
125
+ catch (_f) {
126
126
  console.warn('[sh3-artifact] Could not read entry chunk:', clientSrc);
127
127
  return;
128
128
  }
@@ -131,17 +131,71 @@ export function sh3Artifact(options = {}) {
131
131
  writeFileSync(clientDest, source);
132
132
  unlinkSync(clientSrc);
133
133
  }
134
- // --- Extract manifest fields via regex ---
135
- const extract = (pattern) => {
136
- const m = source.match(pattern);
137
- return m ? m[1] : '';
138
- };
139
- const id = extract(/\bid\s*:\s*["']([^"']+)["']/);
140
- const label = extract(/\blabel\s*:\s*["']([^"']+)["']/);
141
- const version = extract(/\bversion\s*:\s*["']([^"']+)["']/);
142
- const hasShard = /\bviews\s*:\s*\[/.test(source);
134
+ // --- Extract manifest fields from App or Shard block ---
135
+ //
136
+ // The bundle may contain both an App manifest (has `requiredShards`)
137
+ // and a Shard manifest (has `views: [`). We extract id/label/version
138
+ // from the App block first, then fall back to the Shard block.
139
+ // If neither block exists, the build fails with a clear error.
143
140
  const hasApp = /\brequiredShards\s*:\s*\[/.test(source);
141
+ const hasShard = /\bviews\s*:\s*\[/.test(source);
142
+ if (!hasApp && !hasShard) {
143
+ throw new Error('[sh3-artifact] Could not find an App manifest (requiredShards) or Shard manifest (views) in the entry chunk. '
144
+ + 'Ensure the entry exports an App or Shard object.');
145
+ }
144
146
  const type = hasShard && hasApp ? 'combo' : hasApp ? 'app' : 'shard';
147
+ /**
148
+ * Extract id, label, and version from the manifest object block that
149
+ * contains `anchor`. Walks backwards from the anchor to find the
150
+ * opening `{`, then forward to find the matching `}`, and extracts
151
+ * fields from within that slice.
152
+ */
153
+ function extractFromBlock(anchor) {
154
+ const anchorMatch = anchor.exec(source);
155
+ if (!anchorMatch)
156
+ return null;
157
+ // Walk backwards from the anchor to find the enclosing `{`.
158
+ let depth = 0;
159
+ let blockStart = anchorMatch.index;
160
+ for (let i = anchorMatch.index - 1; i >= 0; i--) {
161
+ if (source[i] === '}')
162
+ depth++;
163
+ if (source[i] === '{') {
164
+ if (depth === 0) {
165
+ blockStart = i;
166
+ break;
167
+ }
168
+ depth--;
169
+ }
170
+ }
171
+ // Walk forwards from the anchor to find the matching `}`.
172
+ depth = 0;
173
+ let blockEnd = source.length;
174
+ for (let i = blockStart; i < source.length; i++) {
175
+ if (source[i] === '{')
176
+ depth++;
177
+ if (source[i] === '}') {
178
+ depth--;
179
+ if (depth === 0) {
180
+ blockEnd = i + 1;
181
+ break;
182
+ }
183
+ }
184
+ }
185
+ const block = source.slice(blockStart, blockEnd);
186
+ const get = (pattern) => {
187
+ const m = block.match(pattern);
188
+ return m ? m[1] : '';
189
+ };
190
+ return {
191
+ id: get(/\bid\s*:\s*["']([^"']+)["']/),
192
+ label: get(/\blabel\s*:\s*["']([^"']+)["']/),
193
+ version: get(/\bversion\s*:\s*["']([^"']+)["']/),
194
+ };
195
+ }
196
+ // App first, then Shard.
197
+ const extracted = (_a = extractFromBlock(/\brequiredShards\s*:\s*\[/)) !== null && _a !== void 0 ? _a : extractFromBlock(/\bviews\s*:\s*\[/);
198
+ const { id, label, version } = extracted;
145
199
  // --- Optional server bundle ---
146
200
  let hasServer = false;
147
201
  if (options.serverEntry && existsSync(options.serverEntry)) {
@@ -156,13 +210,13 @@ export function sh3Artifact(options = {}) {
156
210
  pkgDescription = typeof pkg.description === 'string' ? pkg.description : undefined;
157
211
  pkgAuthor = typeof pkg.author === 'string'
158
212
  ? pkg.author
159
- : typeof ((_a = pkg.author) === null || _a === void 0 ? void 0 : _a.name) === 'string' ? pkg.author.name : undefined;
213
+ : typeof ((_b = pkg.author) === null || _b === void 0 ? void 0 : _b.name) === 'string' ? pkg.author.name : undefined;
160
214
  }
161
- catch ( /* no package.json or unreadable */_f) { /* no package.json or unreadable */ }
215
+ catch ( /* no package.json or unreadable */_g) { /* no package.json or unreadable */ }
162
216
  // --- Write manifest.json ---
163
- const overrides = (_b = options.manifest) !== null && _b !== void 0 ? _b : {};
164
- const finalDescription = (_c = overrides.description) !== null && _c !== void 0 ? _c : pkgDescription;
165
- const finalAuthor = (_d = overrides.author) !== null && _d !== void 0 ? _d : pkgAuthor;
217
+ const overrides = (_c = options.manifest) !== null && _c !== void 0 ? _c : {};
218
+ const finalDescription = (_d = overrides.description) !== null && _d !== void 0 ? _d : pkgDescription;
219
+ const finalAuthor = (_e = overrides.author) !== null && _e !== void 0 ? _e : pkgAuthor;
166
220
  if (!finalDescription) {
167
221
  throw new Error('[sh3-artifact] Missing "description". Add it to package.json or pass it via sh3Artifact({ manifest: { description } }).');
168
222
  }
@@ -2,8 +2,6 @@ import type { Shard, App } from './index';
2
2
  export interface ShellConfig {
3
3
  /** Framework shard IDs to exclude (all included by default) */
4
4
  excludeShards?: string[];
5
- /** Framework app IDs to exclude (all included by default) */
6
- excludeApps?: string[];
7
5
  /** Additional shards to register */
8
6
  shards?: Shard[];
9
7
  /** Additional apps to register */
@@ -20,5 +18,7 @@ export interface ShellConfig {
20
18
  }>;
21
19
  /** Mount target — CSS selector or element (defaults to '#app') */
22
20
  target?: string | HTMLElement;
21
+ /** Server base URL ('' for same-origin) */
22
+ serverUrl?: string;
23
23
  }
24
24
  export declare function createShell(config?: ShellConfig): Promise<void>;
@@ -3,20 +3,22 @@
3
3
  *
4
4
  * Consumers call this from their own main.ts instead of manually
5
5
  * importing registerShard / registerApp / bootstrap / Shell. The
6
- * factory handles platform detection, registration, bootstrap, and
7
- * mounting in the correct order.
6
+ * factory handles platform detection, boot config, auth gating,
7
+ * registration, bootstrap, and mounting in the correct order.
8
8
  */
9
- import { mount } from 'svelte';
9
+ import { mount, unmount } from 'svelte';
10
10
  import { Shell } from './index';
11
11
  import { registerShard, registerApp, bootstrap, __setBackend, setLocalOwner, } from './host';
12
12
  import { resolvePlatform } from './platform/index';
13
13
  import { hydrateTokenOverrides } from './theme';
14
14
  import { __setEnvServerUrl } from './env/index';
15
+ import { __setTenantId } from './documents/config';
16
+ import { initFromBoot } from './auth/index';
17
+ import SignInWall from './auth/SignInWall.svelte';
15
18
  export async function createShell(config) {
16
- var _a, _b;
17
- // 1. Platform detection must run before bootstrap so state zones
18
- // hydrate from the right backend, and local-owner environments
19
- // auto-elevate to admin.
19
+ var _a, _b, _c;
20
+ const sUrl = (_a = config === null || config === void 0 ? void 0 : config.serverUrl) !== null && _a !== void 0 ? _a : '';
21
+ // 1. Platform detection
20
22
  const platform = await resolvePlatform();
21
23
  if (platform.backends) {
22
24
  __setBackend('workspace', platform.backends.workspace);
@@ -25,15 +27,52 @@ export async function createShell(config) {
25
27
  if (platform.localOwner) {
26
28
  setLocalOwner();
27
29
  }
28
- // 1d. Default env state to same-origin. The server frontend overrides
29
- // this if it knows a specific URL, but this ensures env() works for
30
- // same-origin deployments without explicit configuration.
31
- __setEnvServerUrl('');
32
- // 1c. Apply persisted theme token overrides before any component mounts,
33
- // so the first frame renders with the user's chosen theme.
30
+ __setEnvServerUrl(sUrl);
34
31
  hydrateTokenOverrides();
35
- // 1b. Load server-discovered packages (fetched by frontend from /api/packages).
36
- if ((_a = config === null || config === void 0 ? void 0 : config.discoveredPackages) === null || _a === void 0 ? void 0 : _a.length) {
32
+ // 2. Resolve mount target early (needed for both sign-in wall and shell)
33
+ const target = typeof (config === null || config === void 0 ? void 0 : config.target) === 'string'
34
+ ? document.querySelector(config.target)
35
+ : (_b = config === null || config === void 0 ? void 0 : config.target) !== null && _b !== void 0 ? _b : document.getElementById('app');
36
+ if (!target) {
37
+ throw new Error('SH3: mount target not found');
38
+ }
39
+ // 3. Fetch boot config (skip for local-owner platforms like Tauri/dev)
40
+ let bootConfig = null;
41
+ if (!platform.localOwner) {
42
+ try {
43
+ const res = await fetch(`${sUrl}/api/boot`, { credentials: 'include' });
44
+ if (res.ok) {
45
+ bootConfig = await res.json();
46
+ }
47
+ }
48
+ catch (_d) {
49
+ // Server unreachable — boot without auth (offline mode)
50
+ }
51
+ }
52
+ // 4. Auth decision point
53
+ if (platform.localOwner) {
54
+ // Local-owner (Tauri/dev): no auth, no sign-in, tenant is 'local'.
55
+ // setLocalOwner() already called above — admin is assumed.
56
+ __setTenantId('local');
57
+ }
58
+ else if (bootConfig) {
59
+ initFromBoot(sUrl, bootConfig);
60
+ __setTenantId(bootConfig.tenantId);
61
+ const { auth, session } = bootConfig;
62
+ // Hard gate: no session, auth required, no guest allowed → sign-in wall
63
+ if (!session && auth.required && !auth.guestAllowed) {
64
+ await showSignInWall(target, sUrl, bootConfig);
65
+ // After successful sign-in, re-fetch boot config
66
+ const res = await fetch(`${sUrl}/api/boot`, { credentials: 'include' });
67
+ if (res.ok) {
68
+ bootConfig = await res.json();
69
+ initFromBoot(sUrl, bootConfig);
70
+ __setTenantId(bootConfig.tenantId);
71
+ }
72
+ }
73
+ }
74
+ // 5. Load server-discovered packages
75
+ if ((_c = config === null || config === void 0 ? void 0 : config.discoveredPackages) === null || _c === void 0 ? void 0 : _c.length) {
37
76
  const { loadBundleModule } = await import('./registry/loader');
38
77
  for (const pkg of config.discoveredPackages) {
39
78
  try {
@@ -55,33 +94,39 @@ export async function createShell(config) {
55
94
  }
56
95
  }
57
96
  }
58
- // 2. Register consumer-provided shards and apps. These go in before
59
- // bootstrap() so they appear in registeredShards, but framework
60
- // shards activate first (insertion-order guarantee in bootstrap).
97
+ // 6. Register consumer-provided shards and apps
61
98
  if (config === null || config === void 0 ? void 0 : config.shards) {
62
- for (const shard of config.shards) {
99
+ for (const shard of config.shards)
63
100
  registerShard(shard);
64
- }
65
101
  }
66
102
  if (config === null || config === void 0 ? void 0 : config.apps) {
67
- for (const app of config.apps) {
103
+ for (const app of config.apps)
68
104
  registerApp(app);
69
- }
70
105
  }
71
- // 3. Bootstrap — framework shards/apps registered internally,
72
- // filtered by the exclude lists.
106
+ // 7. Bootstrap
73
107
  const bootstrapConfig = {};
74
108
  if (config === null || config === void 0 ? void 0 : config.excludeShards)
75
109
  bootstrapConfig.excludeShards = config.excludeShards;
76
- if (config === null || config === void 0 ? void 0 : config.excludeApps)
77
- bootstrapConfig.excludeApps = config.excludeApps;
78
110
  await bootstrap(bootstrapConfig);
79
- // 4. Mount the shell.
80
- const target = typeof (config === null || config === void 0 ? void 0 : config.target) === 'string'
81
- ? document.querySelector(config.target)
82
- : (_b = config === null || config === void 0 ? void 0 : config.target) !== null && _b !== void 0 ? _b : document.getElementById('app');
83
- if (!target) {
84
- throw new Error('SH3: mount target not found');
85
- }
111
+ // 8. Mount the shell
86
112
  mount(Shell, { target });
87
113
  }
114
+ /**
115
+ * Show the sign-in wall and wait until the user authenticates.
116
+ * Returns a promise that resolves after successful login.
117
+ */
118
+ function showSignInWall(target, serverUrl, bootConfig) {
119
+ return new Promise((resolve) => {
120
+ const instance = mount(SignInWall, {
121
+ target,
122
+ props: {
123
+ serverUrl,
124
+ selfRegistration: bootConfig.auth.selfRegistration,
125
+ onSuccess: () => {
126
+ unmount(instance);
127
+ resolve();
128
+ },
129
+ },
130
+ });
131
+ });
132
+ }
@@ -7,6 +7,7 @@ export { HttpDocumentBackend } from './documents/http-backend';
7
7
  export { __setEnvServerUrl } from './env/index';
8
8
  export { installPackage, uninstallPackage, listInstalledPackages, loadInstalledPackages, } from './registry/index';
9
9
  export type { InstalledPackage, InstallResult, PackageMeta } from './registry/types';
10
- export { initAuth, elevate, deescalate } from './auth/index';
10
+ export { initFromBoot, login, logout, register, setLocalOwner as setLocalOwnerAuth } from './auth/index';
11
+ export type { AuthUser, AuthSession, BootConfig, GlobalSettings } from './auth/types';
11
12
  export { createShell } from './createShell';
12
13
  export type { ShellConfig } from './createShell';
@@ -11,7 +11,7 @@ export { HttpDocumentBackend } from './documents/http-backend';
11
11
  export { __setEnvServerUrl } from './env/index';
12
12
  // Install API (host-only).
13
13
  export { installPackage, uninstallPackage, listInstalledPackages, loadInstalledPackages, } from './registry/index';
14
- // Admin mode (host-only — elevate/deescalate drive the shell UI, initAuth runs at boot).
15
- export { initAuth, elevate, deescalate } from './auth/index';
14
+ // Auth (host-only — session lifecycle, boot initialization).
15
+ export { initFromBoot, login, logout, register, setLocalOwner as setLocalOwnerAuth } from './auth/index';
16
16
  // Shell boot factory.
17
17
  export { createShell } from './createShell';
package/dist/host.d.ts CHANGED
@@ -10,8 +10,6 @@ export { registerApp };
10
10
  export interface BootstrapConfig {
11
11
  /** Framework shard IDs to skip registration for */
12
12
  excludeShards?: string[];
13
- /** Framework app IDs to skip registration for */
14
- excludeApps?: string[];
15
13
  }
16
14
  export declare function bootstrap(config?: BootstrapConfig): Promise<void>;
17
15
  export { installPackage, listInstalledPackages } from './registry/installer';
package/dist/host.js CHANGED
@@ -22,10 +22,12 @@ import { shellShard } from './shell-shard/shellShard.svelte';
22
22
  import { storeShard } from './store/storeShard.svelte';
23
23
  import { __setBackend } from './state/zones.svelte';
24
24
  import { loadInstalledPackages } from './registry/installer';
25
- import { initAuth, isAdmin, setLocalOwner } from './auth/index';
25
+ import { setLocalOwner } from './auth/index';
26
26
  import { storeApp } from './store/storeApp';
27
27
  import { diagnosticShard } from './diagnostic/diagnosticShard.svelte';
28
28
  import { diagnosticApp } from './diagnostic/diagnosticApp';
29
+ import { adminShard } from './admin/adminShard.svelte';
30
+ import { adminApp } from './admin/adminApp';
29
31
  export { __setBackend };
30
32
  export { setLocalOwner };
31
33
  export { __setTenantId, __setDocumentBackend } from './documents/config';
@@ -35,43 +37,27 @@ export function registerShard(shard) {
35
37
  export { registerApp };
36
38
  export async function bootstrap(config) {
37
39
  const exShards = new Set(config === null || config === void 0 ? void 0 : config.excludeShards);
38
- const exApps = new Set(config === null || config === void 0 ? void 0 : config.excludeApps);
39
- // 1. Framework-owned shards registered first so installed packages
40
- // cannot claim reserved IDs like __shell__ or sh3-store.
41
- const frameworkShards = [shellShard, storeShard, diagnosticShard];
40
+ // 1. Framework-owned shards
41
+ const frameworkShards = [shellShard, storeShard, diagnosticShard, adminShard];
42
42
  for (const shard of frameworkShards) {
43
43
  if (!exShards.has(shard.manifest.id)) {
44
44
  registerShardInternal(shard);
45
45
  }
46
46
  }
47
- // 2. Framework-shipped admin apps.
48
- const frameworkApps = [storeApp, diagnosticApp];
47
+ // 2. Framework-shipped apps
48
+ const frameworkApps = [storeApp, diagnosticApp, adminApp];
49
49
  for (const app of frameworkApps) {
50
- if (!exApps.has(app.manifest.id)) {
51
- registerApp(app);
52
- }
53
- }
54
- // 3. Auth — if the host already called setLocalOwner() (Tauri / dev),
55
- // skip server verification. Otherwise verify the stored admin key
56
- // against the server (3s timeout, fails open).
57
- if (!isAdmin()) {
58
- await initAuth();
50
+ registerApp(app);
59
51
  }
60
- // 4. Load any packages that were hot-installed in a previous session
61
- // from IndexedDB. Runs after framework shards but before activation
62
- // so installed packages participate in the self-starting pass.
52
+ // 3. Load any packages installed in a previous session from IndexedDB
63
53
  await loadInstalledPackages();
64
- // 5. Activate every self-starting shard (any shard whose `autostart`
65
- // field is defined). Iteration order is insertion order, which
66
- // puts __shell__ first and glob-discovered shards after — exactly
67
- // what we need.
54
+ // 4. Activate every self-starting shard
68
55
  for (const [id, shard] of registeredShards) {
69
56
  if (shard.autostart) {
70
57
  await activateShard(id);
71
58
  }
72
59
  }
73
- // 6. Read the last-active app from the user zone. If it names a still-
74
- // registered app, launch it; otherwise leave the shell on home.
60
+ // 5. Read the last-active app from the user zone
75
61
  const lastId = readLastApp();
76
62
  if (lastId && registeredApps.has(lastId)) {
77
63
  await launchApp(lastId);
@@ -2,37 +2,18 @@
2
2
  /*
3
3
  * Shell home — the view shown when no app is active. Sections:
4
4
  * 1. User apps — always visible
5
- * 2. Admin apps — visible when elevated (admin mode)
6
- * 3. Elevate prompt — shown when not elevated
5
+ * 2. Admin apps — visible when user has admin role
7
6
  */
8
7
 
9
8
  import { listRegisteredApps, launchApp, isAdmin, VERSION } from '../api';
10
- import { elevate, deescalate } from '../auth/index';
9
+ import { logout, isAuthenticated, getUser } from '../auth/index';
11
10
 
12
11
  const apps = $derived(listRegisteredApps());
13
12
  const userApps = $derived(apps.filter(m => !m.admin));
14
13
  const adminApps = $derived(apps.filter(m => m.admin));
15
14
  const elevated = $derived(isAdmin());
16
-
17
- let keyInput = $state('');
18
- let elevateError = $state<string | null>(null);
19
- let elevating = $state(false);
20
-
21
- async function handleElevate() {
22
- if (!keyInput.trim() || elevating) return;
23
- elevating = true;
24
- elevateError = null;
25
- const ok = await elevate(keyInput.trim());
26
- if (!ok) {
27
- elevateError = 'Invalid API key';
28
- }
29
- keyInput = '';
30
- elevating = false;
31
- }
32
-
33
- function handleDeescalate() {
34
- deescalate();
35
- }
15
+ const authenticated = $derived(isAuthenticated());
16
+ const user = $derived(getUser());
36
17
  </script>
37
18
 
38
19
  <div class="shell-home">
@@ -40,9 +21,10 @@
40
21
  <h1>SH3</h1>
41
22
  <span class="shell-home-version">v{VERSION}</span>
42
23
  <span class="shell-home-alpha">alpha</span>
43
- {#if elevated}
44
- <button type="button" class="shell-home-deescalate" onclick={handleDeescalate}>
45
- Exit admin mode
24
+ {#if authenticated && user}
25
+ <span class="shell-home-user">{user.displayName}</span>
26
+ <button type="button" class="shell-home-deescalate" onclick={() => logout()}>
27
+ Sign out
46
28
  </button>
47
29
  {/if}
48
30
  </header>
@@ -70,54 +52,26 @@
70
52
  </section>
71
53
  {/if}
72
54
 
73
- {#if elevated}
74
- {#if adminApps.length > 0}
75
- <section class="shell-home-section">
76
- <h2 class="shell-home-section-title">Admin</h2>
77
- <ul class="shell-home-list">
78
- {#each adminApps as manifest (manifest.id)}
79
- <li class="shell-home-entry">
80
- <div class="shell-home-entry-label">{manifest.label}</div>
81
- <div class="shell-home-entry-meta">
82
- {manifest.id} · v{manifest.version}
83
- </div>
84
- <button
85
- type="button"
86
- class="shell-home-launch"
87
- onclick={() => launchApp(manifest.id)}
88
- >
89
- Launch
90
- </button>
91
- </li>
92
- {/each}
93
- </ul>
94
- </section>
95
- {/if}
96
- {:else}
55
+ {#if elevated && adminApps.length > 0}
97
56
  <section class="shell-home-section">
98
- <h2 class="shell-home-section-title">Admin Mode</h2>
99
- <p class="shell-home-elevate-hint">
100
- Elevate Permissions
101
- </p>
102
- <form class="shell-home-elevate-form" onsubmit={(e) => { e.preventDefault(); handleElevate(); }}>
103
- <input
104
- class="shell-home-key-input"
105
- type="password"
106
- placeholder="API key"
107
- bind:value={keyInput}
108
- disabled={elevating}
109
- />
110
- <button
111
- type="submit"
112
- class="shell-home-elevate-btn"
113
- disabled={elevating || !keyInput.trim()}
114
- >
115
- {elevating ? 'Verifying...' : 'Elevate'}
116
- </button>
117
- </form>
118
- {#if elevateError}
119
- <div class="shell-home-elevate-error">{elevateError}</div>
120
- {/if}
57
+ <h2 class="shell-home-section-title">Admin</h2>
58
+ <ul class="shell-home-list">
59
+ {#each adminApps as manifest (manifest.id)}
60
+ <li class="shell-home-entry">
61
+ <div class="shell-home-entry-label">{manifest.label}</div>
62
+ <div class="shell-home-entry-meta">
63
+ {manifest.id} · v{manifest.version}
64
+ </div>
65
+ <button
66
+ type="button"
67
+ class="shell-home-launch"
68
+ onclick={() => launchApp(manifest.id)}
69
+ >
70
+ Launch
71
+ </button>
72
+ </li>
73
+ {/each}
74
+ </ul>
121
75
  </section>
122
76
  {/if}
123
77
 
@@ -243,48 +197,8 @@
243
197
  color: var(--shell-fg);
244
198
  border-color: var(--shell-fg-subtle);
245
199
  }
246
- .shell-home-elevate-hint {
247
- margin: 0 0 12px;
200
+ .shell-home-user {
248
201
  font-size: 13px;
249
- color: var(--shell-fg-muted);
250
- }
251
- .shell-home-elevate-form {
252
- display: flex;
253
- gap: 8px;
254
- }
255
- .shell-home-key-input {
256
- flex: 1;
257
- padding: 8px 12px;
258
- background: var(--shell-grad-bg-elevated, var(--shell-bg-elevated));
259
- color: var(--shell-fg);
260
- border: 1px solid var(--shell-border);
261
- border-radius: var(--shell-radius);
262
- font-family: monospace;
263
- font-size: 13px;
264
- }
265
- .shell-home-key-input::placeholder {
266
- color: var(--shell-fg-muted);
267
- }
268
- .shell-home-elevate-btn {
269
- padding: 8px 16px;
270
- background: var(--shell-accent);
271
- color: var(--shell-bg);
272
- border: none;
273
- border-radius: var(--shell-radius);
274
- font-weight: 600;
275
- cursor: pointer;
276
- white-space: nowrap;
277
- }
278
- .shell-home-elevate-btn:disabled {
279
- opacity: 0.6;
280
- cursor: not-allowed;
281
- }
282
- .shell-home-elevate-error {
283
- margin-top: 8px;
284
- padding: 6px 10px;
285
- font-size: 12px;
286
- color: var(--shell-error, #d32f2f);
287
- background: color-mix(in srgb, var(--shell-error, #d32f2f) 10%, transparent);
288
- border-radius: var(--shell-radius);
202
+ color: var(--shell-fg-subtle);
289
203
  }
290
204
  </style>
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- /** sh3-core package version. Keep in sync with package.json. */
2
- export declare const VERSION = "0.5.4";
1
+ /** Auto-generated from package.json do not edit manually. */
2
+ export declare const VERSION = "0.5.6";
package/dist/version.js CHANGED
@@ -1,2 +1,2 @@
1
- /** sh3-core package version. Keep in sync with package.json. */
2
- export const VERSION = '0.5.4';
1
+ /** Auto-generated from package.json do not edit manually. */
2
+ export const VERSION = '0.5.6';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sh3-core",
3
- "version": "0.5.4",
3
+ "version": "0.5.6",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist"
@@ -29,7 +29,7 @@
29
29
  }
30
30
  },
31
31
  "scripts": {
32
- "build": "svelte-package -i src -o dist && node --import tsx scripts/generate-api-docs.ts",
32
+ "build": "node --import tsx scripts/sync-version.ts && svelte-package -i src -o dist && node --import tsx scripts/generate-api-docs.ts",
33
33
  "check": "svelte-check --tsconfig ./tsconfig.json",
34
34
  "pack": "npm run build && npm pack"
35
35
  },