@freeappstore/sdk 0.9.0 → 0.11.0

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 CHANGED
@@ -140,6 +140,23 @@ const res = await fas.proxy.fetch('api.openweathermap.org/data/2.5/weather?q=Lon
140
140
  const data = await res.json();
141
141
  ```
142
142
 
143
+ ### User API Key Vault
144
+
145
+ Users store their own API keys on the platform (encrypted AES-256-GCM). Apps never see plaintext keys.
146
+
147
+ ```ts
148
+ // Check if user has a key configured
149
+ const hasKey = await fas.keys.has('openai');
150
+
151
+ // Redirect to platform key management page
152
+ fas.keys.manage('openai');
153
+
154
+ // Check all configured providers
155
+ const keys = await fas.keys.status();
156
+ ```
157
+
158
+ Supported providers: OpenAI, Anthropic, Google AI, OpenRouter, Replicate, Stability AI, ElevenLabs, Stripe.
159
+
143
160
  ### React Hooks
144
161
 
145
162
  Import from `@freeappstore/sdk/hooks`. Requires React 18+ as a peer dependency.
@@ -159,21 +176,52 @@ function App() {
159
176
  Drop-in React components. Import from `@freeappstore/sdk/ui`. Components use CSS custom properties (`--ink`, `--accent`, etc.) to blend into your app's theme.
160
177
 
161
178
  ```tsx
162
- import { FasShell, Avatar, SignInButton, ThemeToggle, ProfileMenu, ProfilePage } from '@freeappstore/sdk/ui';
179
+ import {
180
+ FasShell, Avatar, SignInButton, ThemeToggle, ProfileMenu, ProfilePage,
181
+ Spinner, Badge, Card, Tabs, Modal, ConfirmDialog, EmptyState,
182
+ ProgressBar, SearchInput, ListRow, ErrorBoundary, KeyPrompt,
183
+ } from '@freeappstore/sdk/ui';
163
184
 
164
185
  // Zero-config shell
165
- <FasShell app={fas} appName="My App">
166
- <MyApp />
167
- </FasShell>
168
-
169
- // Or use individual components
170
- <Avatar user={user} size={32} />
171
- <ThemeToggle />
172
- <ProfileMenu app={fas} />
173
- <ProfilePage app={fas} />
186
+ <FasShell app={fas} appName="My App"><MyApp /></FasShell>
187
+
188
+ // Building blocks
189
+ <Spinner size={24} />
190
+ <Badge variant="success">Live</Badge>
191
+ <Card onClick={fn}>content</Card>
192
+ <Tabs tabs={[{key:'a',label:'A'}]} active="a" onChange={setTab} />
193
+ <Modal open={show} onClose={close} title="Settings">content</Modal>
194
+ <ConfirmDialog open={show} onConfirm={ok} onCancel={cancel} title="Delete?" message="Sure?" variant="danger" />
195
+ <EmptyState message="Nothing here yet" />
196
+ <ProgressBar value={75} label="Progress" />
197
+ <SearchInput value={q} onChange={setQ} />
198
+ <ListRow title="Item" subtitle="details" onClick={fn} />
199
+ <ErrorBoundary>{children}</ErrorBoundary>
200
+ <KeyPrompt app={fas} provider="openai" providerName="OpenAI" />
174
201
  ```
175
202
 
176
- Full docs: [freeappstore.online/docs/ui](https://freeappstore.online/docs/ui)
203
+ Full docs: [freeappstore.online/skills.md](https://freeappstore.online/skills.md)
204
+
205
+ ## For AI Agents
206
+
207
+ Building with Claude Code, Cursor, or another AI tool? Two options:
208
+
209
+ **MCP Server (recommended)** -- your agent gets tools to check deploys, look up SDK docs, and list apps:
210
+ ```json
211
+ {
212
+ "mcpServers": {
213
+ "freeappstore": {
214
+ "command": "npx",
215
+ "args": ["mcp-remote", "https://mcp.freeappstore.online/mcp"]
216
+ }
217
+ }
218
+ }
219
+ ```
220
+
221
+ **SKILLS.md** -- full platform guide (tech stack, SDK reference, CLI, deploy flow, compliance):
222
+ ```
223
+ https://freeappstore.online/skills.md
224
+ ```
177
225
 
178
226
  ## License
179
227
 
package/dist/auth.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { Unsubscribe, User } from './types.js';
2
- export type AuthProvider = 'github' | 'google' | 'email';
2
+ export type AuthProvider = 'github' | 'google' | 'apple' | 'email';
3
3
  /** OAuth authentication — sign in, sign out, session management. */
4
4
  export declare class Auth {
5
5
  private readonly appId;
@@ -66,6 +66,8 @@ export declare class Auth {
66
66
  */
67
67
  setDateOfBirth(dateOfBirth: string): Promise<User>;
68
68
  private fetchUser;
69
+ /** Fire-and-forget: ensure the user has at least 'member' role in this app. */
70
+ private ensureMember;
69
71
  private readStorage;
70
72
  private writeStorage;
71
73
  private emit;
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEpD,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;AAazD,oEAAoE;AACpE,qBAAa,IAAI;IAKb,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAL1B,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,SAAS,CAA0C;gBAGxC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM;IAKlC,4DAA4D;IAC5D,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,CAEtB;IAED,2DAA2D;IAC3D,IAAI,KAAK,IAAI,MAAM,GAAG,IAAI,CAEzB;IAED,kGAAkG;IAClG,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,KAAK,IAAI,GAAG,WAAW;IAM5D;;;;;;;OAOG;IACH,MAAM,CAAC,QAAQ,GAAE,YAAuB,GAAG,IAAI;IAa/C;;;;;;;;;;;OAWG;IACG,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAenD,8CAA8C;IAC9C,OAAO,IAAI,IAAI;IAQf;;;;OAIG;IACH,kBAAkB,IAAI,IAAI;IAI1B;;;;;;;;;;;;OAYG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA8B3B;;;;;;OAMG;IACG,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YA4B1C,SAAS;IAQvB,OAAO,CAAC,WAAW;IAWnB,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,IAAI;CAGb"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEpD,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC;AAanE,oEAAoE;AACpE,qBAAa,IAAI;IAKb,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAL1B,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,SAAS,CAA0C;gBAGxC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM;IAMlC,4DAA4D;IAC5D,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,CAEtB;IAED,2DAA2D;IAC3D,IAAI,KAAK,IAAI,MAAM,GAAG,IAAI,CAEzB;IAED,kGAAkG;IAClG,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,KAAK,IAAI,GAAG,WAAW;IAM5D;;;;;;;OAOG;IACH,MAAM,CAAC,QAAQ,GAAE,YAAuB,GAAG,IAAI;IAa/C;;;;;;;;;;;OAWG;IACG,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAenD,8CAA8C;IAC9C,OAAO,IAAI,IAAI;IAQf;;;;OAIG;IACH,kBAAkB,IAAI,IAAI;IAI1B;;;;;;;;;;;;OAYG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA+B3B;;;;;;OAMG;IACG,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YA4B1C,SAAS;IAQvB,+EAA+E;IAC/E,OAAO,CAAC,YAAY;IAUpB,OAAO,CAAC,WAAW;IAWnB,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,IAAI;CAGb"}
package/dist/auth.js CHANGED
@@ -13,6 +13,8 @@ export class Auth {
13
13
  this.appId = appId;
14
14
  this.apiBase = apiBase;
15
15
  this.session = this.readStorage();
16
+ if (this.session)
17
+ this.ensureMember();
16
18
  }
17
19
  /** Current signed-in user, or null if not authenticated. */
18
20
  get user() {
@@ -131,6 +133,7 @@ export class Auth {
131
133
  this.session = { token, user };
132
134
  this.writeStorage(this.session);
133
135
  this.emit();
136
+ this.ensureMember();
134
137
  }
135
138
  catch {
136
139
  // Token was invalid or network failed. Hash already cleared so the user
@@ -180,6 +183,18 @@ export class Auth {
180
183
  throw new Error(`Auth failed: ${response.status}`);
181
184
  return (await response.json());
182
185
  }
186
+ /** Fire-and-forget: ensure the user has at least 'member' role in this app. */
187
+ ensureMember() {
188
+ if (typeof fetch === 'undefined')
189
+ return; // SSR / test env
190
+ const t = this.session?.token;
191
+ if (!t)
192
+ return;
193
+ fetch(`${this.apiBase}/v1/apps/${encodeURIComponent(this.appId)}/roles/ensure-member`, {
194
+ method: 'POST',
195
+ headers: { Authorization: `Bearer ${t}` },
196
+ }).catch(() => { }); // silent — non-blocking
197
+ }
183
198
  readStorage() {
184
199
  if (typeof window === 'undefined')
185
200
  return null;
package/dist/auth.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
package/dist/hooks.d.ts CHANGED
@@ -4,7 +4,7 @@ export type { User } from './types.js';
4
4
  type ThemePreference = 'light' | 'dark' | 'system';
5
5
  type ResolvedTheme = 'light' | 'dark';
6
6
  /**
7
- * Theme hook — zero-provider. Reads/writes localStorage, applies data-theme on <html>.
7
+ * Theme hook — zero-provider. Persists preference, applies data-theme on html element.
8
8
  *
9
9
  * Usage:
10
10
  * ```tsx
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,YAAY,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAIvC,KAAK,eAAe,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;AACnD,KAAK,aAAa,GAAG,OAAO,GAAG,MAAM,CAAC;AA4DtC;;;;;;;;;GASG;AACH,wBAAgB,QAAQ;;;0BAGmB,eAAe;EASzD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,YAAY;;;;;;oBAuB9B,MAAM;EAKhB"}
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,YAAY,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAIvC,KAAK,eAAe,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;AACnD,KAAK,aAAa,GAAG,OAAO,GAAG,MAAM,CAAC;AA8DtC;;;;;;;;;GASG;AACH,wBAAgB,QAAQ;;;0BAGmB,eAAe;EASzD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,YAAY;;;;;;oBAuB9B,MAAM;EAKhB"}
package/dist/hooks.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { useSyncExternalStore, useState, useEffect, useCallback } from 'react';
2
- const THEME_KEY = 'fas:theme';
2
+ const THEME_KEY = 'stores-theme';
3
3
  // Shared theme state — all useTheme() callers share this via DOM + localStorage
4
4
  const themeListeners = new Set();
5
5
  function getSystemTheme() {
@@ -21,9 +21,12 @@ function resolveTheme(pref) {
21
21
  function applyTheme(theme) {
22
22
  if (typeof document === 'undefined')
23
23
  return;
24
- document.documentElement.setAttribute('data-theme', theme);
25
- // Also toggle the 'dark' class used by the store sites' CSS
26
- document.documentElement.classList.toggle('dark', theme === 'dark');
24
+ if (theme === 'dark') {
25
+ document.documentElement.dataset.theme = 'dark';
26
+ }
27
+ else {
28
+ delete document.documentElement.dataset.theme;
29
+ }
27
30
  }
28
31
  function notifyThemeListeners() {
29
32
  for (const fn of themeListeners)
@@ -53,7 +56,7 @@ function getSnapshot() {
53
56
  return cachedSnapshot;
54
57
  }
55
58
  /**
56
- * Theme hook — zero-provider. Reads/writes localStorage, applies data-theme on <html>.
59
+ * Theme hook — zero-provider. Persists preference, applies data-theme on html element.
57
60
  *
58
61
  * Usage:
59
62
  * ```tsx
package/dist/hooks.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { Auth } from './auth.js';
2
2
  import { Counters } from './counters.js';
3
3
  import { Collections } from './db.js';
4
+ import { Keys } from './keys.js';
4
5
  import { Kv } from './kv.js';
5
6
  import { ApiProxy } from './proxy.js';
6
7
  import { Roles } from './roles.js';
@@ -22,6 +23,7 @@ export declare class FreeAppStore {
22
23
  readonly rooms: Rooms;
23
24
  readonly proxy: ApiProxy;
24
25
  readonly roles: Roles;
26
+ readonly keys: Keys;
25
27
  constructor(opts: FasInitOptions);
26
28
  }
27
29
  /** Create a new FreeAppStore SDK instance for the given app. */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,YAAY,EAAE,eAAe,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC/E,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEpE,kGAAkG;AAClG,qBAAa,YAAY;IACvB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC;IAChB,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;gBAEV,IAAI,EAAE,cAAc;CAUjC;AAED,gEAAgE;AAChE,wBAAgB,OAAO,CAAC,IAAI,EAAE,cAAc,GAAG,YAAY,CAE1D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,YAAY,EAAE,eAAe,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC/E,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEpE,kGAAkG;AAClG,qBAAa,YAAY;IACvB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC;IAChB,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;gBAER,IAAI,EAAE,cAAc;CAWjC;AAED,gEAAgE;AAChE,wBAAgB,OAAO,CAAC,IAAI,EAAE,cAAc,GAAG,YAAY,CAE1D"}
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { Auth } from './auth.js';
2
2
  import { Counters } from './counters.js';
3
3
  import { Collections } from './db.js';
4
+ import { Keys } from './keys.js';
4
5
  import { Kv } from './kv.js';
5
6
  import { ApiProxy } from './proxy.js';
6
7
  import { Roles } from './roles.js';
@@ -16,6 +17,7 @@ export class FreeAppStore {
16
17
  rooms;
17
18
  proxy;
18
19
  roles;
20
+ keys;
19
21
  constructor(opts) {
20
22
  const apiBase = opts.apiBase ?? 'https://api.freeappstore.online';
21
23
  this.auth = new Auth(opts.appId, apiBase);
@@ -25,6 +27,7 @@ export class FreeAppStore {
25
27
  this.rooms = new Rooms(opts.appId, apiBase, this.auth);
26
28
  this.proxy = new ApiProxy(opts.appId, apiBase, this.auth);
27
29
  this.roles = new Roles(opts.appId, apiBase, this.auth);
30
+ this.keys = new Keys(opts.appId, apiBase, this.auth);
28
31
  }
29
32
  }
30
33
  /** Create a new FreeAppStore SDK instance for the given app. */
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAKnC,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAGtC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAG3C,kGAAkG;AAClG,MAAM,OAAO,YAAY;IACd,IAAI,CAAO;IACX,EAAE,CAAK;IACP,WAAW,CAAc;IACzB,QAAQ,CAAW;IACnB,KAAK,CAAQ;IACb,KAAK,CAAW;IAChB,KAAK,CAAQ;IAEtB,YAAY,IAAoB;QAC9B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,iCAAiC,CAAC;QAClE,IAAI,CAAC,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC1C,IAAI,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACjD,IAAI,CAAC,WAAW,GAAG,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACnE,IAAI,CAAC,QAAQ,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7D,IAAI,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACvD,IAAI,CAAC,KAAK,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1D,IAAI,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IACzD,CAAC;CACF;AAED,gEAAgE;AAChE,MAAM,UAAU,OAAO,CAAC,IAAoB;IAC1C,OAAO,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;AAChC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAKnC,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAGtC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAG3C,kGAAkG;AAClG,MAAM,OAAO,YAAY;IACd,IAAI,CAAO;IACX,EAAE,CAAK;IACP,WAAW,CAAc;IACzB,QAAQ,CAAW;IACnB,KAAK,CAAQ;IACb,KAAK,CAAW;IAChB,KAAK,CAAQ;IACb,IAAI,CAAO;IAEpB,YAAY,IAAoB;QAC9B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,iCAAiC,CAAC;QAClE,IAAI,CAAC,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC1C,IAAI,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACjD,IAAI,CAAC,WAAW,GAAG,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACnE,IAAI,CAAC,QAAQ,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7D,IAAI,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACvD,IAAI,CAAC,KAAK,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1D,IAAI,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACvD,IAAI,CAAC,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IACvD,CAAC;CACF;AAED,gEAAgE;AAChE,MAAM,UAAU,OAAO,CAAC,IAAoB;IAC1C,OAAO,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;AAChC,CAAC"}
package/dist/keys.d.ts ADDED
@@ -0,0 +1,40 @@
1
+ import type { Auth } from './auth.js';
2
+ /**
3
+ * User API Key management. Keys are stored encrypted on the platform and
4
+ * injected server-side when apps call `fas.proxy.fetch()`. Apps never see
5
+ * the plaintext key.
6
+ *
7
+ * Key management happens on a platform-hosted page, not in the app UI.
8
+ * Apps use `fas.keys.manage()` to redirect users there.
9
+ */
10
+ export declare class Keys {
11
+ private readonly appId;
12
+ private readonly apiBase;
13
+ private readonly auth;
14
+ constructor(appId: string, apiBase: string, auth: Auth);
15
+ /**
16
+ * Open the platform's key management page. If a provider is specified,
17
+ * that provider's card will be highlighted on the page.
18
+ *
19
+ * The user manages their keys on the platform page and is redirected
20
+ * back to the app when done.
21
+ *
22
+ * @param provider - Optional provider to highlight (e.g. 'openai')
23
+ */
24
+ manage(provider?: string): void;
25
+ /**
26
+ * Check which providers the current user has keys configured for.
27
+ * Useful for showing "configure your API key" prompts in the app.
28
+ */
29
+ status(): Promise<Array<{
30
+ provider: string;
31
+ label: string | null;
32
+ createdAt: number;
33
+ lastUsedAt: number | null;
34
+ }>>;
35
+ /**
36
+ * Check if the user has a key for a specific provider.
37
+ */
38
+ has(provider: string): Promise<boolean>;
39
+ }
40
+ //# sourceMappingURL=keys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEtC;;;;;;;GAOG;AACH,qBAAa,IAAI;IAEb,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAFJ,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,IAAI;IAG7B;;;;;;;;OAQG;IACH,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IAQ/B;;;OAGG;IACG,MAAM,IAAI,OAAO,CAAC,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;IAUxH;;OAEG;IACG,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAI9C"}
package/dist/keys.js ADDED
@@ -0,0 +1,58 @@
1
+ /**
2
+ * User API Key management. Keys are stored encrypted on the platform and
3
+ * injected server-side when apps call `fas.proxy.fetch()`. Apps never see
4
+ * the plaintext key.
5
+ *
6
+ * Key management happens on a platform-hosted page, not in the app UI.
7
+ * Apps use `fas.keys.manage()` to redirect users there.
8
+ */
9
+ export class Keys {
10
+ appId;
11
+ apiBase;
12
+ auth;
13
+ constructor(appId, apiBase, auth) {
14
+ this.appId = appId;
15
+ this.apiBase = apiBase;
16
+ this.auth = auth;
17
+ }
18
+ /**
19
+ * Open the platform's key management page. If a provider is specified,
20
+ * that provider's card will be highlighted on the page.
21
+ *
22
+ * The user manages their keys on the platform page and is redirected
23
+ * back to the app when done.
24
+ *
25
+ * @param provider - Optional provider to highlight (e.g. 'openai')
26
+ */
27
+ manage(provider) {
28
+ const params = new URLSearchParams();
29
+ params.set('app', this.appId);
30
+ params.set('return', window.location.href);
31
+ if (provider)
32
+ params.set('provider', provider);
33
+ window.location.href = `${this.apiBase}/v1/keys?${params}`;
34
+ }
35
+ /**
36
+ * Check which providers the current user has keys configured for.
37
+ * Useful for showing "configure your API key" prompts in the app.
38
+ */
39
+ async status() {
40
+ if (!this.auth.token)
41
+ return [];
42
+ const res = await fetch(`${this.apiBase}/v1/keys/status`, {
43
+ headers: { Authorization: `Bearer ${this.auth.token}`, Accept: 'application/json' },
44
+ });
45
+ if (!res.ok)
46
+ return [];
47
+ const data = (await res.json());
48
+ return data.keys;
49
+ }
50
+ /**
51
+ * Check if the user has a key for a specific provider.
52
+ */
53
+ async has(provider) {
54
+ const keys = await this.status();
55
+ return keys.some((k) => k.provider === provider);
56
+ }
57
+ }
58
+ //# sourceMappingURL=keys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keys.js","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,MAAM,OAAO,IAAI;IAEI;IACA;IACA;IAHnB,YACmB,KAAa,EACb,OAAe,EACf,IAAU;QAFV,UAAK,GAAL,KAAK,CAAQ;QACb,YAAO,GAAP,OAAO,CAAQ;QACf,SAAI,GAAJ,IAAI,CAAM;IAC1B,CAAC;IAEJ;;;;;;;;OAQG;IACH,MAAM,CAAC,QAAiB;QACtB,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAC9B,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC3C,IAAI,QAAQ;YAAE,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAC/C,MAAM,CAAC,QAAQ,CAAC,IAAI,GAAG,GAAG,IAAI,CAAC,OAAO,YAAY,MAAM,EAAE,CAAC;IAC7D,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,MAAM;QACV,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAO,EAAE,CAAC;QAChC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,iBAAiB,EAAE;YACxD,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;SACpF,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA8G,CAAC;QAC7I,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,GAAG,CAAC,QAAgB;QACxB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;QACjC,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC;IACnD,CAAC;CACF"}
@@ -0,0 +1,99 @@
1
+ import { Component, type ReactNode, type CSSProperties } from 'react';
2
+ import type { FreeAppStore } from '../index.js';
3
+ export interface SpinnerProps {
4
+ size?: number;
5
+ color?: string;
6
+ }
7
+ export declare function Spinner({ size, color }: SpinnerProps): import("react/jsx-runtime").JSX.Element;
8
+ export interface BadgeProps {
9
+ children: ReactNode;
10
+ variant?: 'default' | 'accent' | 'success' | 'warning' | 'danger';
11
+ style?: CSSProperties;
12
+ }
13
+ export declare function Badge({ children, variant, style: extraStyle }: BadgeProps): import("react/jsx-runtime").JSX.Element;
14
+ export interface CardProps {
15
+ children: ReactNode;
16
+ onClick?: () => void;
17
+ padding?: string;
18
+ style?: CSSProperties;
19
+ }
20
+ export declare function Card({ children, onClick, padding, style: extraStyle }: CardProps): import("react/jsx-runtime").JSX.Element;
21
+ export interface TabsProps {
22
+ tabs: Array<{
23
+ key: string;
24
+ label: string;
25
+ }>;
26
+ active: string;
27
+ onChange: (key: string) => void;
28
+ style?: CSSProperties;
29
+ }
30
+ export declare function Tabs({ tabs, active, onChange, style: extraStyle }: TabsProps): import("react/jsx-runtime").JSX.Element;
31
+ export interface ModalProps {
32
+ open: boolean;
33
+ onClose: () => void;
34
+ children: ReactNode;
35
+ title?: string;
36
+ maxWidth?: number;
37
+ }
38
+ export declare function Modal({ open, onClose, children, title, maxWidth }: ModalProps): import("react/jsx-runtime").JSX.Element | null;
39
+ export interface ConfirmDialogProps {
40
+ open: boolean;
41
+ onConfirm: () => void;
42
+ onCancel: () => void;
43
+ title: string;
44
+ message: string;
45
+ confirmLabel?: string;
46
+ variant?: 'danger' | 'default';
47
+ }
48
+ export declare function ConfirmDialog({ open, onConfirm, onCancel, title, message, confirmLabel, variant }: ConfirmDialogProps): import("react/jsx-runtime").JSX.Element;
49
+ export interface EmptyStateProps {
50
+ icon?: ReactNode;
51
+ title?: string;
52
+ message: string;
53
+ action?: ReactNode;
54
+ }
55
+ export declare function EmptyState({ icon, title, message, action }: EmptyStateProps): import("react/jsx-runtime").JSX.Element;
56
+ export interface ProgressBarProps {
57
+ value: number;
58
+ max?: number;
59
+ color?: string;
60
+ height?: number;
61
+ label?: string;
62
+ }
63
+ export declare function ProgressBar({ value, max, color, height, label }: ProgressBarProps): import("react/jsx-runtime").JSX.Element;
64
+ export interface SearchInputProps {
65
+ value: string;
66
+ onChange: (value: string) => void;
67
+ placeholder?: string;
68
+ style?: CSSProperties;
69
+ }
70
+ export declare function SearchInput({ value, onChange, placeholder, style: extraStyle }: SearchInputProps): import("react/jsx-runtime").JSX.Element;
71
+ export interface ListRowProps {
72
+ icon?: ReactNode;
73
+ title: string;
74
+ subtitle?: string;
75
+ trailing?: ReactNode;
76
+ onClick?: () => void;
77
+ }
78
+ export declare function ListRow({ icon, title, subtitle, trailing, onClick }: ListRowProps): import("react/jsx-runtime").JSX.Element;
79
+ export interface ErrorBoundaryProps {
80
+ children: ReactNode;
81
+ fallback?: ReactNode;
82
+ }
83
+ interface ErrorBoundaryState {
84
+ error: Error | null;
85
+ }
86
+ export declare class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
87
+ state: ErrorBoundaryState;
88
+ static getDerivedStateFromError(error: Error): ErrorBoundaryState;
89
+ render(): string | number | bigint | boolean | import("react/jsx-runtime").JSX.Element | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | null | undefined;
90
+ }
91
+ export interface KeyPromptProps {
92
+ app: FreeAppStore;
93
+ provider: string;
94
+ providerName?: string;
95
+ message?: string;
96
+ }
97
+ export declare function KeyPrompt({ app, provider, providerName, message }: KeyPromptProps): import("react/jsx-runtime").JSX.Element;
98
+ export {};
99
+ //# sourceMappingURL=components.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../src/ui/components.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,78 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, Component } from 'react';
3
+ // Inject keyframes once
4
+ if (typeof document !== 'undefined' && !document.getElementById('fas-ui-keyframes')) {
5
+ const style = document.createElement('style');
6
+ style.id = 'fas-ui-keyframes';
7
+ style.textContent = '@keyframes fas-spin{to{transform:rotate(360deg)}}@keyframes fas-fade-in{from{opacity:0}to{opacity:1}}@keyframes fas-slide-up{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}';
8
+ document.head.appendChild(style);
9
+ }
10
+ export function Spinner({ size = 24, color = 'var(--accent, #2563eb)' }) {
11
+ return _jsx("div", { style: { width: size, height: size, border: '2px solid var(--border, #e2e8f0)', borderTopColor: color, borderRadius: '50%', animation: 'fas-spin 0.6s linear infinite' } });
12
+ }
13
+ const badgeColors = {
14
+ default: { bg: 'var(--surface, #f8fafc)', color: 'var(--muted, #64748b)', border: 'var(--border, #e2e8f0)' },
15
+ accent: { bg: 'var(--accent-soft, #eff6ff)', color: 'var(--accent, #2563eb)', border: 'var(--accent, #2563eb)' },
16
+ success: { bg: '#f0fdf4', color: '#16a34a', border: '#86efac' },
17
+ warning: { bg: '#fefce8', color: '#ca8a04', border: '#fde047' },
18
+ danger: { bg: '#fef2f2', color: '#dc2626', border: '#fecaca' },
19
+ };
20
+ export function Badge({ children, variant = 'default', style: extraStyle }) {
21
+ const c = badgeColors[variant] ?? badgeColors.default;
22
+ return (_jsx("span", { style: { display: 'inline-flex', alignItems: 'center', gap: '0.25rem', padding: '0.15rem 0.5rem', borderRadius: '9999px', fontSize: '0.75rem', fontWeight: 600, lineHeight: 1.4, background: c.bg, color: c.color, border: `1px solid ${c.border}`, ...extraStyle }, children: children }));
23
+ }
24
+ export function Card({ children, onClick, padding = '1rem', style: extraStyle }) {
25
+ const interactive = !!onClick;
26
+ const Tag = interactive ? 'button' : 'div';
27
+ return (_jsx(Tag, { onClick: onClick, style: { display: 'block', width: '100%', textAlign: 'left', padding, borderRadius: 'var(--radius, 0.75rem)', border: '1px solid var(--border, var(--line, #e2e8f0))', background: 'var(--surface, var(--panel, #ffffff))', cursor: interactive ? 'pointer' : undefined, fontFamily: 'inherit', fontSize: 'inherit', color: 'inherit', transition: 'border-color 0.15s', ...(interactive ? { outline: 'none' } : {}), ...extraStyle }, children: children }));
28
+ }
29
+ export function Tabs({ tabs, active, onChange, style: extraStyle }) {
30
+ return (_jsx("div", { style: { display: 'inline-flex', gap: '0.25rem', padding: '0.25rem', borderRadius: '9999px', border: '1px solid var(--border, var(--line, #e2e8f0))', background: 'var(--surface, var(--glass, #f8fafc))', ...extraStyle }, children: tabs.map((tab) => (_jsx("button", { onClick: () => onChange(tab.key), style: { padding: '0.35rem 0.85rem', borderRadius: '9999px', border: 'none', fontSize: '0.8rem', fontWeight: 600, cursor: 'pointer', fontFamily: 'inherit', transition: 'all 0.15s', background: active === tab.key ? 'var(--ink, #1e293b)' : 'transparent', color: active === tab.key ? 'var(--surface, #ffffff)' : 'var(--muted, #64748b)' }, children: tab.label }, tab.key))) }));
31
+ }
32
+ export function Modal({ open, onClose, children, title, maxWidth = 480 }) {
33
+ useEffect(() => {
34
+ if (!open)
35
+ return;
36
+ const handler = (e) => { if (e.key === 'Escape')
37
+ onClose(); };
38
+ document.addEventListener('keydown', handler);
39
+ return () => document.removeEventListener('keydown', handler);
40
+ }, [open, onClose]);
41
+ if (!open)
42
+ return null;
43
+ return (_jsx("div", { onClick: onClose, style: { position: 'fixed', inset: 0, zIndex: 999, background: 'rgba(0,0,0,0.5)', backdropFilter: 'blur(4px)', display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '1rem', animation: 'fas-fade-in 0.15s' }, children: _jsxs("div", { onClick: (e) => e.stopPropagation(), style: { background: 'var(--surface, var(--panel, #ffffff))', border: '1px solid var(--border, var(--line, #e2e8f0))', borderRadius: 'var(--radius-lg, var(--radius, 0.75rem))', maxWidth, width: '100%', maxHeight: '85dvh', overflow: 'auto', animation: 'fas-slide-up 0.2s' }, children: [title && (_jsxs("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '1rem 1.25rem', borderBottom: '1px solid var(--border, var(--line, #e2e8f0))' }, children: [_jsx("h2", { style: { margin: 0, fontSize: '1rem', fontWeight: 700, color: 'var(--ink, #1e293b)' }, children: title }), _jsx("button", { onClick: onClose, "aria-label": "Close", style: { background: 'none', border: 'none', cursor: 'pointer', padding: '0.25rem', color: 'var(--muted, #64748b)', fontSize: '1.25rem', lineHeight: 1, fontFamily: 'inherit' }, children: "\u00D7" })] })), _jsx("div", { style: { padding: '1.25rem' }, children: children })] }) }));
44
+ }
45
+ export function ConfirmDialog({ open, onConfirm, onCancel, title, message, confirmLabel = 'Confirm', variant = 'default' }) {
46
+ const isDanger = variant === 'danger';
47
+ return (_jsxs(Modal, { open: open, onClose: onCancel, title: title, maxWidth: 400, children: [_jsx("p", { style: { fontSize: '0.9rem', color: 'var(--muted, #64748b)', margin: '0 0 1.25rem' }, children: message }), _jsxs("div", { style: { display: 'flex', gap: '0.5rem', justifyContent: 'flex-end' }, children: [_jsx("button", { onClick: onCancel, style: { padding: '0.5rem 1rem', borderRadius: 'var(--radius-sm, 0.5rem)', border: '1px solid var(--border, #e2e8f0)', background: 'transparent', color: 'var(--ink, #1e293b)', fontSize: '0.85rem', fontWeight: 600, cursor: 'pointer', fontFamily: 'inherit' }, children: "Cancel" }), _jsx("button", { onClick: onConfirm, style: { padding: '0.5rem 1rem', borderRadius: 'var(--radius-sm, 0.5rem)', border: 'none', fontSize: '0.85rem', fontWeight: 600, cursor: 'pointer', fontFamily: 'inherit', background: isDanger ? '#dc2626' : 'var(--accent, #2563eb)', color: '#fff' }, children: confirmLabel })] })] }));
48
+ }
49
+ export function EmptyState({ icon, title, message, action }) {
50
+ return (_jsxs("div", { style: { textAlign: 'center', padding: '3rem 1.5rem' }, children: [icon && _jsx("div", { style: { marginBottom: '0.75rem', color: 'var(--muted, #94a3b8)', fontSize: '2rem' }, children: icon }), title && _jsx("div", { style: { fontSize: '1rem', fontWeight: 700, color: 'var(--ink, #1e293b)', marginBottom: '0.35rem' }, children: title }), _jsx("p", { style: { fontSize: '0.85rem', color: 'var(--muted, #64748b)', margin: '0 0 1rem', maxWidth: 320, marginInline: 'auto' }, children: message }), action] }));
51
+ }
52
+ export function ProgressBar({ value, max = 100, color = 'var(--accent, #2563eb)', height = 8, label }) {
53
+ const pct = Math.min(100, Math.max(0, (value / max) * 100));
54
+ return (_jsxs("div", { children: [label && _jsx("div", { style: { fontSize: '0.75rem', fontWeight: 600, color: 'var(--muted, #64748b)', marginBottom: '0.35rem' }, children: label }), _jsx("div", { style: { width: '100%', height, borderRadius: height, background: 'var(--border, var(--line, #e2e8f0))', overflow: 'hidden' }, children: _jsx("div", { style: { width: `${pct}%`, height: '100%', borderRadius: height, background: color, transition: 'width 0.3s' } }) })] }));
55
+ }
56
+ export function SearchInput({ value, onChange, placeholder = 'Search...', style: extraStyle }) {
57
+ return (_jsxs("div", { style: { position: 'relative', ...extraStyle }, children: [_jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "var(--muted, #64748b)", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", style: { position: 'absolute', left: 12, top: '50%', transform: 'translateY(-50%)', pointerEvents: 'none' }, children: [_jsx("circle", { cx: "11", cy: "11", r: "8" }), _jsx("line", { x1: "21", y1: "21", x2: "16.65", y2: "16.65" })] }), _jsx("input", { type: "text", value: value, onChange: (e) => onChange(e.currentTarget.value), placeholder: placeholder, style: { width: '100%', padding: '0.5rem 0.75rem 0.5rem 2.25rem', borderRadius: '9999px', border: '1px solid var(--border, var(--line, #e2e8f0))', background: 'var(--surface, var(--glass, #ffffff))', color: 'var(--ink, #1e293b)', fontSize: '0.85rem', fontFamily: 'inherit', outline: 'none' } })] }));
58
+ }
59
+ export function ListRow({ icon, title, subtitle, trailing, onClick }) {
60
+ const Tag = onClick ? 'button' : 'div';
61
+ return (_jsxs(Tag, { onClick: onClick, style: { display: 'flex', alignItems: 'center', gap: '0.75rem', width: '100%', padding: '0.65rem 0.75rem', background: 'none', border: 'none', borderBottom: '1px solid var(--border, var(--line, #e2e8f0))', textAlign: 'left', cursor: onClick ? 'pointer' : undefined, fontFamily: 'inherit', color: 'inherit' }, children: [icon && _jsx("div", { style: { flexShrink: 0, color: 'var(--muted, #64748b)' }, children: icon }), _jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [_jsx("div", { style: { fontSize: '0.9rem', fontWeight: 600, color: 'var(--ink, #1e293b)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }, children: title }), subtitle && _jsx("div", { style: { fontSize: '0.75rem', color: 'var(--muted, #64748b)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }, children: subtitle })] }), trailing && _jsx("div", { style: { flexShrink: 0 }, children: trailing })] }));
62
+ }
63
+ export class ErrorBoundary extends Component {
64
+ state = { error: null };
65
+ static getDerivedStateFromError(error) { return { error }; }
66
+ render() {
67
+ if (this.state.error) {
68
+ return this.props.fallback ?? (_jsxs("div", { style: { padding: '2rem', textAlign: 'center' }, children: [_jsx("p", { style: { color: '#dc2626', fontWeight: 700, marginBottom: '0.5rem' }, children: "Something went wrong" }), _jsx("p", { style: { color: 'var(--muted, #64748b)', fontSize: '0.85rem' }, children: this.state.error.message })] }));
69
+ }
70
+ return this.props.children;
71
+ }
72
+ }
73
+ export function KeyPrompt({ app, provider, providerName, message }) {
74
+ const name = providerName ?? provider;
75
+ const msg = message ?? `This app uses ${name} and needs your API key. Your key is stored securely on the FreeAppStore platform and is never visible to the app.`;
76
+ return (_jsxs("div", { style: { background: 'var(--surface, var(--panel, #f8fafc))', border: '1px solid var(--border, var(--line, #e2e8f0))', borderRadius: 'var(--radius, 0.75rem)', padding: '1.5rem', maxWidth: 420, margin: '2rem auto', textAlign: 'center' }, children: [_jsx("div", { style: { fontSize: '1.5rem', marginBottom: '0.5rem' }, children: _jsx("svg", { width: "28", height: "28", viewBox: "0 0 24 24", fill: "none", stroke: "var(--muted, #64748b)", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", style: { display: 'inline-block', verticalAlign: 'middle' }, children: _jsx("path", { d: "M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4" }) }) }), _jsxs("div", { style: { fontSize: '1rem', fontWeight: 700, color: 'var(--ink, #1e293b)', marginBottom: '0.5rem' }, children: [name, " API key required"] }), _jsx("p", { style: { fontSize: '0.85rem', color: 'var(--muted, #64748b)', margin: '0 0 1rem', lineHeight: 1.5 }, children: msg }), _jsxs("button", { onClick: () => app.keys.manage(provider), style: { background: 'var(--accent, #2563eb)', color: '#fff', border: 'none', padding: '0.6rem 1.5rem', borderRadius: 'var(--radius, 0.75rem)', fontSize: '0.9rem', fontWeight: 700, cursor: 'pointer', fontFamily: 'inherit' }, children: ["Configure ", name, " key"] })] }));
77
+ }
78
+ //# sourceMappingURL=components.js.map