@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 +59 -11
- package/dist/auth.d.ts +3 -1
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +15 -0
- package/dist/auth.js.map +1 -1
- package/dist/hooks.d.ts +1 -1
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +8 -5
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/keys.d.ts +40 -0
- package/dist/keys.d.ts.map +1 -0
- package/dist/keys.js +58 -0
- package/dist/keys.js.map +1 -0
- package/dist/ui/components.d.ts +99 -0
- package/dist/ui/components.d.ts.map +1 -0
- package/dist/ui/components.js +78 -0
- package/dist/ui/components.js.map +1 -0
- package/dist/ui/core.d.ts +19 -0
- package/dist/ui/core.d.ts.map +1 -0
- package/dist/ui/core.js +123 -0
- package/dist/ui/core.js.map +1 -0
- package/dist/ui/index.d.ts +7 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +4 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/layout.d.ts +25 -0
- package/dist/ui/layout.d.ts.map +1 -0
- package/dist/ui/layout.js +137 -0
- package/dist/ui/layout.js.map +1 -0
- package/dist/ui.d.ts +1 -42
- package/dist/ui.d.ts.map +1 -1
- package/dist/ui.js +3 -236
- package/dist/ui.js.map +1 -1
- package/package.json +2 -2
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 {
|
|
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
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
<
|
|
171
|
-
<
|
|
172
|
-
<
|
|
173
|
-
<
|
|
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/
|
|
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;
|
package/dist/auth.d.ts.map
CHANGED
|
@@ -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;
|
|
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":"AAIA;;;GAGG;AACH,MAAM,WAAW,GAAG,aAAa,CAAC;AAOlC,oEAAoE;AACpE,MAAM,OAAO,IAAI;IAKI;IACA;IALX,OAAO,GAAmB,IAAI,CAAC;IAC/B,SAAS,GAAG,IAAI,GAAG,EAA+B,CAAC;IAE3D,YACmB,KAAa,EACb,OAAe;QADf,UAAK,GAAL,KAAK,CAAQ;QACb,YAAO,GAAP,OAAO,CAAQ;QAEhC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;
|
|
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.
|
|
7
|
+
* Theme hook — zero-provider. Persists preference, applies data-theme on html element.
|
|
8
8
|
*
|
|
9
9
|
* Usage:
|
|
10
10
|
* ```tsx
|
package/dist/hooks.d.ts.map
CHANGED
|
@@ -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;
|
|
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 = '
|
|
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
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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.
|
|
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":"AAAA,OAAO,EAAE,oBAAoB,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAM/E,MAAM,SAAS,GAAG,
|
|
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. */
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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;
|
|
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;
|
|
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
|
package/dist/keys.js.map
ADDED
|
@@ -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
|