sunpeak 0.14.3 → 0.15.1
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 +32 -28
- package/bin/commands/build.mjs +2 -1
- package/bin/commands/dev.mjs +72 -2
- package/dist/chatgpt/{conversation.d.ts → chatgpt-conversation.d.ts} +1 -1
- package/dist/chatgpt/chatgpt-host.d.ts +1 -0
- package/dist/chatgpt/globals.css +618 -6156
- package/dist/chatgpt/index.cjs +11 -8
- package/dist/chatgpt/index.cjs.map +1 -1
- package/dist/chatgpt/index.d.ts +10 -32
- package/dist/chatgpt/index.js +15 -12
- package/dist/chatgpt/index.js.map +1 -1
- package/dist/claude/claude-conversation.d.ts +23 -0
- package/dist/claude/claude-host.d.ts +1 -0
- package/dist/claude/index.cjs +6 -0
- package/dist/claude/index.cjs.map +1 -0
- package/dist/claude/index.d.ts +1 -0
- package/dist/claude/index.js +6 -0
- package/dist/claude/index.js.map +1 -0
- package/dist/claude-host-C7KPfOM8.cjs +284 -0
- package/dist/claude-host-C7KPfOM8.cjs.map +1 -0
- package/dist/claude-host-CaD7ptbt.js +283 -0
- package/dist/claude-host-CaD7ptbt.js.map +1 -0
- package/dist/{discovery-COZUnY6a.js → discovery-DzV3HLXs.js} +5 -5
- package/dist/{discovery-COZUnY6a.js.map → discovery-DzV3HLXs.js.map} +1 -1
- package/dist/hooks/index.d.ts +4 -0
- package/dist/hooks/use-app-tools.d.ts +44 -0
- package/dist/hooks/use-update-model-context.d.ts +29 -0
- package/dist/index-BKrboRah.js +44 -0
- package/dist/index-BKrboRah.js.map +1 -0
- package/dist/index-BSKuY-oH.cjs +527 -0
- package/dist/index-BSKuY-oH.cjs.map +1 -0
- package/dist/index-CiqvXo8n.js +512 -0
- package/dist/index-CiqvXo8n.js.map +1 -0
- package/dist/index-Dr-L0Nb3.cjs +43 -0
- package/dist/index-Dr-L0Nb3.cjs.map +1 -0
- package/dist/index.cjs +1705 -1647
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2732 -2675
- package/dist/index.js.map +1 -1
- package/dist/lib/default-style-variables.d.ts +2 -0
- package/dist/lib/discovery-cli.js +1 -1
- package/dist/mcp/index.cjs +86 -27
- package/dist/mcp/index.cjs.map +1 -1
- package/dist/mcp/index.d.ts +3 -1
- package/dist/mcp/index.js +85 -26
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/server.d.ts +4 -3
- package/dist/mcp/types.d.ts +11 -0
- package/dist/platform/chatgpt/index.cjs +1 -1
- package/dist/platform/chatgpt/index.js +1 -1
- package/dist/platform/index.cjs +3 -0
- package/dist/platform/index.cjs.map +1 -1
- package/dist/platform/index.d.ts +3 -1
- package/dist/platform/index.js +3 -0
- package/dist/platform/index.js.map +1 -1
- package/dist/{protocol-BQCnIrc9.js → protocol-DFbsCx7E.js} +29 -29
- package/dist/{protocol-BQCnIrc9.js.map → protocol-DFbsCx7E.js.map} +1 -1
- package/dist/simulator/host-styles.d.ts +5 -0
- package/dist/simulator/hosts.d.ts +73 -0
- package/dist/{chatgpt → simulator}/iframe-resource.d.ts +27 -3
- package/dist/simulator/index.cjs +40 -0
- package/dist/simulator/index.cjs.map +1 -0
- package/dist/simulator/index.d.ts +18 -0
- package/dist/simulator/index.js +40 -0
- package/dist/simulator/index.js.map +1 -0
- package/dist/{chatgpt → simulator}/mcp-app-host.d.ts +8 -1
- package/dist/simulator/mock-openai-runtime.d.ts +20 -0
- package/dist/{chatgpt → simulator}/simulator-url.d.ts +8 -1
- package/dist/simulator/simulator.d.ts +12 -0
- package/dist/{chatgpt → simulator}/theme-provider.d.ts +3 -1
- package/dist/simulator/use-simulator-state.d.ts +91 -0
- package/dist/simulator-BqZmzFVR.cjs +8214 -0
- package/dist/simulator-BqZmzFVR.cjs.map +1 -0
- package/dist/simulator-CMgCGNuD.js +8199 -0
- package/dist/simulator-CMgCGNuD.js.map +1 -0
- package/dist/simulator-url-BQ-7SMht.js +335 -0
- package/dist/simulator-url-BQ-7SMht.js.map +1 -0
- package/dist/simulator-url-uNqOCaPJ.cjs +334 -0
- package/dist/simulator-url-uNqOCaPJ.cjs.map +1 -0
- package/dist/style.css +558 -6143
- package/dist/types/runtime.d.ts +1 -1
- package/dist/{use-app-D7kRAPSG.cjs → use-app-BnoSPiUT.cjs} +2 -1
- package/dist/{use-app-D7kRAPSG.cjs.map → use-app-BnoSPiUT.cjs.map} +1 -1
- package/dist/{use-app-Dvr4LKs2.js → use-app-D_TeaMFG.js} +4 -3
- package/dist/{use-app-Dvr4LKs2.js.map → use-app-D_TeaMFG.js.map} +1 -1
- package/package.json +18 -3
- package/template/.sunpeak/dev.tsx +4 -4
- package/template/.sunpeak/resource-loader.html +1 -1
- package/template/node_modules/.bin/nodemon +2 -2
- package/template/node_modules/.bin/playwright +2 -2
- package/template/node_modules/.bin/sunpeak +2 -2
- package/template/node_modules/.bin/tsc +2 -2
- package/template/node_modules/.bin/tsserver +2 -2
- package/template/node_modules/.bin/tsx +2 -2
- package/template/node_modules/.bin/vite +2 -2
- package/template/src/components/avatar.tsx +4 -1
- package/template/src/components/button.tsx +17 -20
- package/template/src/resources/albums/albums-resource.tsx +2 -3
- package/template/src/resources/albums/components/album-card.tsx +4 -2
- package/template/src/resources/albums/components/film-strip.test.tsx +2 -2
- package/template/src/resources/albums/components/film-strip.tsx +2 -2
- package/template/src/resources/albums/components/fullscreen-viewer.tsx +7 -5
- package/template/src/resources/carousel/carousel-resource.tsx +2 -3
- package/template/src/resources/carousel/components/card.test.tsx +3 -2
- package/template/src/resources/carousel/components/card.tsx +8 -4
- package/template/src/resources/map/components/map-view.tsx +1 -1
- package/template/src/resources/map/components/map.tsx +1 -1
- package/template/src/resources/map/components/place-card.tsx +8 -4
- package/template/src/resources/map/components/place-carousel.tsx +1 -1
- package/template/src/resources/map/components/place-inspector.tsx +15 -7
- package/template/src/resources/map/components/place-list.tsx +7 -4
- package/template/src/resources/map/map-resource.tsx +0 -2
- package/template/src/resources/review/review-resource.tsx +61 -27
- package/template/tests/e2e/albums.spec.ts +118 -102
- package/template/tests/e2e/carousel.spec.ts +103 -100
- package/template/tests/e2e/map.spec.ts +220 -181
- package/template/tests/e2e/review.spec.ts +224 -198
- package/dist/_commonjsHelpers-Bc2YnDe1.cjs +0 -8
- package/dist/_commonjsHelpers-Bc2YnDe1.cjs.map +0 -1
- package/dist/_commonjsHelpers-DWwsNxpa.js +0 -9
- package/dist/_commonjsHelpers-DWwsNxpa.js.map +0 -1
- package/dist/index-CJ3jfcjj.js +0 -15131
- package/dist/index-CJ3jfcjj.js.map +0 -1
- package/dist/index-Cdeg96So.cjs +0 -15147
- package/dist/index-Cdeg96So.cjs.map +0 -1
- /package/dist/{chatgpt → simulator}/simple-sidebar.d.ts +0 -0
- /package/dist/{chatgpt/chatgpt-simulator-types.d.ts → simulator/simulator-types.d.ts} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sunpeak",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.1",
|
|
4
4
|
"description": "Local-first MCP Apps framework. Quickstart, build, test, and ship your Claude or ChatGPT App!",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -17,12 +17,24 @@
|
|
|
17
17
|
"default": "./dist/index.cjs"
|
|
18
18
|
}
|
|
19
19
|
},
|
|
20
|
+
"./simulator": {
|
|
21
|
+
"import": {
|
|
22
|
+
"types": "./dist/simulator/index.d.ts",
|
|
23
|
+
"default": "./dist/simulator/index.js"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
20
26
|
"./chatgpt": {
|
|
21
27
|
"import": {
|
|
22
28
|
"types": "./dist/chatgpt/index.d.ts",
|
|
23
29
|
"default": "./dist/chatgpt/index.js"
|
|
24
30
|
}
|
|
25
31
|
},
|
|
32
|
+
"./claude": {
|
|
33
|
+
"import": {
|
|
34
|
+
"types": "./dist/claude/index.d.ts",
|
|
35
|
+
"default": "./dist/claude/index.js"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
26
38
|
"./style.css": "./dist/style.css",
|
|
27
39
|
"./chatgpt/globals.css": "./dist/chatgpt/globals.css",
|
|
28
40
|
"./mcp": {
|
|
@@ -55,7 +67,9 @@
|
|
|
55
67
|
"README.md"
|
|
56
68
|
],
|
|
57
69
|
"sideEffects": [
|
|
58
|
-
"**/*.css"
|
|
70
|
+
"**/*.css",
|
|
71
|
+
"**/chatgpt-host.*",
|
|
72
|
+
"**/claude-host.*"
|
|
59
73
|
],
|
|
60
74
|
"keywords": [
|
|
61
75
|
"openai-app",
|
|
@@ -64,6 +78,8 @@
|
|
|
64
78
|
"mcp-ui",
|
|
65
79
|
"mcp",
|
|
66
80
|
"chatgpt-simulator",
|
|
81
|
+
"claude",
|
|
82
|
+
"claude-simulator",
|
|
67
83
|
"testing",
|
|
68
84
|
"multi-platform",
|
|
69
85
|
"react",
|
|
@@ -73,7 +89,6 @@
|
|
|
73
89
|
"author": "Sunpeak AI",
|
|
74
90
|
"license": "MIT",
|
|
75
91
|
"peerDependencies": {
|
|
76
|
-
"@openai/apps-sdk-ui": "^0.2.1",
|
|
77
92
|
"react": "^18.0.0 || ^19.0.0",
|
|
78
93
|
"react-dom": "^18.0.0 || ^19.0.0"
|
|
79
94
|
},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/// <reference types="vite/client" />
|
|
2
2
|
/**
|
|
3
3
|
* Bootstrap file for Sunpeak dev server
|
|
4
|
-
* This file bootstraps the
|
|
4
|
+
* This file bootstraps the multi-host simulator for development.
|
|
5
5
|
*
|
|
6
6
|
* Auto-discovers simulations and resources by file naming convention:
|
|
7
7
|
* - tests/simulations/{resource}/{resource}-{scenario}-simulation.json
|
|
@@ -10,11 +10,11 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import { StrictMode } from 'react';
|
|
12
12
|
import { createRoot } from 'react-dom/client';
|
|
13
|
-
import {
|
|
13
|
+
import { simulator } from 'sunpeak';
|
|
14
14
|
import '../src/styles/globals.css';
|
|
15
15
|
import resourceComponents from '../src/resources';
|
|
16
16
|
|
|
17
|
-
const {
|
|
17
|
+
const { Simulator, buildDevSimulations } = simulator;
|
|
18
18
|
|
|
19
19
|
// Build simulations from discovered files
|
|
20
20
|
const simulations = buildDevSimulations({
|
|
@@ -34,7 +34,7 @@ if (import.meta.hot) import.meta.hot.data.root = root;
|
|
|
34
34
|
|
|
35
35
|
root.render(
|
|
36
36
|
<StrictMode>
|
|
37
|
-
<
|
|
37
|
+
<Simulator simulations={simulations} appName={appName} appIcon={appIcon} />
|
|
38
38
|
</StrictMode>
|
|
39
39
|
);
|
|
40
40
|
|
|
@@ -10,9 +10,9 @@ case `uname` in
|
|
|
10
10
|
esac
|
|
11
11
|
|
|
12
12
|
if [ -z "$NODE_PATH" ]; then
|
|
13
|
-
export NODE_PATH="/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/nodemon@3.1.11/node_modules/nodemon/
|
|
13
|
+
export NODE_PATH="/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/nodemon@3.1.11/node_modules/nodemon/node_modules:/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/nodemon@3.1.11/node_modules:/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/node_modules"
|
|
14
14
|
else
|
|
15
|
-
export NODE_PATH="/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/nodemon@3.1.11/node_modules/nodemon/
|
|
15
|
+
export NODE_PATH="/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/nodemon@3.1.11/node_modules/nodemon/node_modules:/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/nodemon@3.1.11/node_modules:/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/node_modules:$NODE_PATH"
|
|
16
16
|
fi
|
|
17
17
|
if [ -x "$basedir/node" ]; then
|
|
18
18
|
exec "$basedir/node" "$basedir/../nodemon/bin/nodemon.js" "$@"
|
|
@@ -10,9 +10,9 @@ case `uname` in
|
|
|
10
10
|
esac
|
|
11
11
|
|
|
12
12
|
if [ -z "$NODE_PATH" ]; then
|
|
13
|
-
export NODE_PATH="/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/@playwright+test@1.57.0/node_modules/@playwright/test/node_modules:/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/@playwright+test@1.57.0/node_modules
|
|
13
|
+
export NODE_PATH="/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/@playwright+test@1.57.0/node_modules/@playwright/test/node_modules:/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/@playwright+test@1.57.0/node_modules:/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/node_modules"
|
|
14
14
|
else
|
|
15
|
-
export NODE_PATH="/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/@playwright+test@1.57.0/node_modules/@playwright/test/node_modules:/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/@playwright+test@1.57.0/node_modules
|
|
15
|
+
export NODE_PATH="/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/@playwright+test@1.57.0/node_modules/@playwright/test/node_modules:/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/@playwright+test@1.57.0/node_modules:/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/node_modules:$NODE_PATH"
|
|
16
16
|
fi
|
|
17
17
|
if [ -x "$basedir/node" ]; then
|
|
18
18
|
exec "$basedir/node" "$basedir/../@playwright/test/cli.js" "$@"
|
|
@@ -10,9 +10,9 @@ case `uname` in
|
|
|
10
10
|
esac
|
|
11
11
|
|
|
12
12
|
if [ -z "$NODE_PATH" ]; then
|
|
13
|
-
export NODE_PATH="/home/runner/work/sunpeak/sunpeak/
|
|
13
|
+
export NODE_PATH="/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/node_modules"
|
|
14
14
|
else
|
|
15
|
-
export NODE_PATH="/home/runner/work/sunpeak/sunpeak/
|
|
15
|
+
export NODE_PATH="/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/node_modules:$NODE_PATH"
|
|
16
16
|
fi
|
|
17
17
|
if [ -x "$basedir/node" ]; then
|
|
18
18
|
exec "$basedir/node" "$basedir/../sunpeak/bin/sunpeak.js" "$@"
|
|
@@ -10,9 +10,9 @@ case `uname` in
|
|
|
10
10
|
esac
|
|
11
11
|
|
|
12
12
|
if [ -z "$NODE_PATH" ]; then
|
|
13
|
-
export NODE_PATH="/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/
|
|
13
|
+
export NODE_PATH="/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/typescript@5.9.3/node_modules:/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/node_modules"
|
|
14
14
|
else
|
|
15
|
-
export NODE_PATH="/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/
|
|
15
|
+
export NODE_PATH="/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/typescript@5.9.3/node_modules:/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/node_modules:$NODE_PATH"
|
|
16
16
|
fi
|
|
17
17
|
if [ -x "$basedir/node" ]; then
|
|
18
18
|
exec "$basedir/node" "$basedir/../typescript/bin/tsc" "$@"
|
|
@@ -10,9 +10,9 @@ case `uname` in
|
|
|
10
10
|
esac
|
|
11
11
|
|
|
12
12
|
if [ -z "$NODE_PATH" ]; then
|
|
13
|
-
export NODE_PATH="/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/
|
|
13
|
+
export NODE_PATH="/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/typescript@5.9.3/node_modules:/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/node_modules"
|
|
14
14
|
else
|
|
15
|
-
export NODE_PATH="/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/
|
|
15
|
+
export NODE_PATH="/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/typescript@5.9.3/node_modules:/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/node_modules:$NODE_PATH"
|
|
16
16
|
fi
|
|
17
17
|
if [ -x "$basedir/node" ]; then
|
|
18
18
|
exec "$basedir/node" "$basedir/../typescript/bin/tsserver" "$@"
|
|
@@ -10,9 +10,9 @@ case `uname` in
|
|
|
10
10
|
esac
|
|
11
11
|
|
|
12
12
|
if [ -z "$NODE_PATH" ]; then
|
|
13
|
-
export NODE_PATH="/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/tsx@4.21.0/node_modules/tsx/
|
|
13
|
+
export NODE_PATH="/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/tsx@4.21.0/node_modules/tsx/node_modules:/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/tsx@4.21.0/node_modules:/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/node_modules"
|
|
14
14
|
else
|
|
15
|
-
export NODE_PATH="/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/tsx@4.21.0/node_modules/tsx/
|
|
15
|
+
export NODE_PATH="/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/tsx@4.21.0/node_modules/tsx/node_modules:/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/tsx@4.21.0/node_modules:/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/node_modules:$NODE_PATH"
|
|
16
16
|
fi
|
|
17
17
|
if [ -x "$basedir/node" ]; then
|
|
18
18
|
exec "$basedir/node" "$basedir/../tsx/dist/cli.mjs" "$@"
|
|
@@ -10,9 +10,9 @@ case `uname` in
|
|
|
10
10
|
esac
|
|
11
11
|
|
|
12
12
|
if [ -z "$NODE_PATH" ]; then
|
|
13
|
-
export NODE_PATH="/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/vite@5.4.21_@types+node@22.19.6_lightningcss@1.30.2/node_modules/vite/
|
|
13
|
+
export NODE_PATH="/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/vite@5.4.21_@types+node@22.19.6_lightningcss@1.30.2/node_modules/vite/node_modules:/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/vite@5.4.21_@types+node@22.19.6_lightningcss@1.30.2/node_modules:/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/node_modules"
|
|
14
14
|
else
|
|
15
|
-
export NODE_PATH="/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/vite@5.4.21_@types+node@22.19.6_lightningcss@1.30.2/node_modules/vite/
|
|
15
|
+
export NODE_PATH="/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/vite@5.4.21_@types+node@22.19.6_lightningcss@1.30.2/node_modules/vite/node_modules:/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/vite@5.4.21_@types+node@22.19.6_lightningcss@1.30.2/node_modules:/home/runner/work/sunpeak/sunpeak/node_modules/.pnpm/node_modules:$NODE_PATH"
|
|
16
16
|
fi
|
|
17
17
|
if [ -x "$basedir/node" ]; then
|
|
18
18
|
exec "$basedir/node" "$basedir/../vite/bin/vite.js" "$@"
|
|
@@ -24,7 +24,10 @@ export function Avatar({ imageUrl, name, size = 32, className }: AvatarProps) {
|
|
|
24
24
|
onError={() => setImgError(true)}
|
|
25
25
|
/>
|
|
26
26
|
) : (
|
|
27
|
-
<span
|
|
27
|
+
<span
|
|
28
|
+
className="text-[var(--color-text-secondary)] font-medium leading-none"
|
|
29
|
+
style={{ fontSize: size * 0.4 }}
|
|
30
|
+
>
|
|
28
31
|
{initial}
|
|
29
32
|
</span>
|
|
30
33
|
)}
|
|
@@ -19,48 +19,45 @@ const sizeClasses: Record<ButtonSize, string> = {
|
|
|
19
19
|
lg: 'h-10 px-4 text-base gap-2',
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
-
// Colors
|
|
23
|
-
// which are available in the template's iframe via sunpeak/chatgpt/globals.css.
|
|
22
|
+
// Colors use MCP standard CSS variables (--color-*) provided by the host.
|
|
24
23
|
const variantColorClasses: Record<ButtonVariant, Record<ButtonColor, string>> = {
|
|
25
24
|
solid: {
|
|
26
25
|
primary:
|
|
27
|
-
'bg-[var(--color-background-
|
|
26
|
+
'bg-[var(--color-background-inverse)] text-[var(--color-text-inverse)] hover:opacity-85 active:opacity-75',
|
|
28
27
|
secondary:
|
|
29
|
-
'bg-[var(--color-background-
|
|
30
|
-
warning:
|
|
31
|
-
|
|
32
|
-
danger:
|
|
33
|
-
'bg-[var(--color-background-danger-solid)] hover:bg-[var(--color-background-danger-solid-hover)] active:bg-[var(--color-background-danger-solid-active)] text-[var(--color-text-danger-solid)]',
|
|
28
|
+
'bg-[var(--color-background-tertiary)] text-[var(--color-text-primary)] hover:opacity-80 active:opacity-70',
|
|
29
|
+
warning: 'bg-[var(--color-text-warning)] text-white hover:opacity-85 active:opacity-75',
|
|
30
|
+
danger: 'bg-[var(--color-text-danger)] text-white hover:opacity-85 active:opacity-75',
|
|
34
31
|
},
|
|
35
32
|
soft: {
|
|
36
33
|
primary:
|
|
37
|
-
'bg-[var(--color-background-
|
|
34
|
+
'bg-[var(--color-background-info)] text-[var(--color-text-info)] hover:opacity-75 active:opacity-65',
|
|
38
35
|
secondary:
|
|
39
|
-
'bg-[var(--color-background-secondary
|
|
36
|
+
'bg-[var(--color-background-secondary)] text-[var(--color-text-primary)] hover:opacity-80 active:opacity-70',
|
|
40
37
|
warning:
|
|
41
|
-
'bg-[var(--color-background-warning
|
|
38
|
+
'bg-[var(--color-background-warning)] text-[var(--color-text-warning)] hover:opacity-75 active:opacity-65',
|
|
42
39
|
danger:
|
|
43
|
-
'bg-[var(--color-background-danger
|
|
40
|
+
'bg-[var(--color-background-danger)] text-[var(--color-text-danger)] hover:opacity-75 active:opacity-65',
|
|
44
41
|
},
|
|
45
42
|
ghost: {
|
|
46
43
|
primary:
|
|
47
|
-
'bg-transparent
|
|
44
|
+
'bg-transparent text-[var(--color-text-info)] hover:bg-[var(--color-background-secondary)] active:bg-[var(--color-background-tertiary)]',
|
|
48
45
|
secondary:
|
|
49
|
-
'bg-transparent
|
|
46
|
+
'bg-transparent text-[var(--color-text-secondary)] hover:bg-[var(--color-background-secondary)] active:bg-[var(--color-background-tertiary)]',
|
|
50
47
|
warning:
|
|
51
|
-
'bg-transparent
|
|
48
|
+
'bg-transparent text-[var(--color-text-warning)] hover:bg-[var(--color-background-warning)] active:bg-[var(--color-background-tertiary)]',
|
|
52
49
|
danger:
|
|
53
|
-
'bg-transparent
|
|
50
|
+
'bg-transparent text-[var(--color-text-danger)] hover:bg-[var(--color-background-danger)] active:bg-[var(--color-background-tertiary)]',
|
|
54
51
|
},
|
|
55
52
|
outline: {
|
|
56
53
|
primary:
|
|
57
|
-
'bg-transparent border border-[var(--color-border-primary
|
|
54
|
+
'bg-transparent border border-[var(--color-border-primary)] text-[var(--color-text-info)] hover:bg-[var(--color-background-secondary)]',
|
|
58
55
|
secondary:
|
|
59
|
-
'bg-transparent border border-[var(--color-border-
|
|
56
|
+
'bg-transparent border border-[var(--color-border-primary)] text-[var(--color-text-secondary)] hover:bg-[var(--color-background-secondary)]',
|
|
60
57
|
warning:
|
|
61
|
-
'bg-transparent border border-[var(--color-border-warning
|
|
58
|
+
'bg-transparent border border-[var(--color-border-warning)] text-[var(--color-text-warning)] hover:bg-[var(--color-background-warning)]',
|
|
62
59
|
danger:
|
|
63
|
-
'bg-transparent border border-[var(--color-border-danger
|
|
60
|
+
'bg-transparent border border-[var(--color-border-danger)] text-[var(--color-text-danger)] hover:bg-[var(--color-background-danger)]',
|
|
64
61
|
},
|
|
65
62
|
};
|
|
66
63
|
|
|
@@ -9,9 +9,8 @@ export const resource: ResourceConfig = {
|
|
|
9
9
|
mimeType: 'text/html;profile=mcp-app',
|
|
10
10
|
_meta: {
|
|
11
11
|
ui: {
|
|
12
|
-
domain: 'https://sunpeak.ai',
|
|
13
12
|
csp: {
|
|
14
|
-
resourceDomains: ['https://cdn.sunpeak.ai'
|
|
13
|
+
resourceDomains: ['https://cdn.sunpeak.ai'],
|
|
15
14
|
},
|
|
16
15
|
},
|
|
17
16
|
},
|
|
@@ -25,7 +24,7 @@ export const resource: ResourceConfig = {
|
|
|
25
24
|
*/
|
|
26
25
|
export function AlbumsResource() {
|
|
27
26
|
return (
|
|
28
|
-
<SafeArea>
|
|
27
|
+
<SafeArea className="p-4">
|
|
29
28
|
<Albums />
|
|
30
29
|
</SafeArea>
|
|
31
30
|
);
|
|
@@ -33,8 +33,10 @@ export const AlbumCard = React.forwardRef<HTMLButtonElement, AlbumCardProps>(
|
|
|
33
33
|
/>
|
|
34
34
|
</div>
|
|
35
35
|
<div className="flex-shrink-0 w-full p-2">
|
|
36
|
-
<div className="text-base font-normal text-primary">
|
|
37
|
-
|
|
36
|
+
<div className="text-base font-normal text-[var(--color-text-primary)]">
|
|
37
|
+
{album.title}
|
|
38
|
+
</div>
|
|
39
|
+
<div className="text-sm text-[var(--color-text-secondary)]">
|
|
38
40
|
{album.photos.length} {album.photos.length === 1 ? 'photo' : 'photos'}
|
|
39
41
|
</div>
|
|
40
42
|
</div>
|
|
@@ -20,8 +20,8 @@ describe('FilmStrip', () => {
|
|
|
20
20
|
|
|
21
21
|
const buttons = container.querySelectorAll('button');
|
|
22
22
|
|
|
23
|
-
// Selected photo (index 1) should have border
|
|
24
|
-
expect(buttons[1].className).toContain('border-primary');
|
|
23
|
+
// Selected photo (index 1) should have accent border
|
|
24
|
+
expect(buttons[1].className).toContain('border-[var(--color-ring-primary)]');
|
|
25
25
|
expect(buttons[1].className).toContain('shadow-md');
|
|
26
26
|
|
|
27
27
|
// Non-selected photos should have border-transparent
|
|
@@ -29,8 +29,8 @@ export const FilmStrip = React.forwardRef<HTMLDivElement, FilmStripProps>(
|
|
|
29
29
|
className={cn(
|
|
30
30
|
'block w-full h-auto p-[1px] pointer-events-auto rounded-[10px] border transition-all',
|
|
31
31
|
idx === selectedIndex
|
|
32
|
-
? 'border-primary shadow-md'
|
|
33
|
-
: 'border-transparent hover:border-primary/30 opacity-60 hover:opacity-100'
|
|
32
|
+
? 'border-[var(--color-ring-primary)] shadow-md'
|
|
33
|
+
: 'border-transparent hover:border-[var(--color-ring-primary)]/30 opacity-60 hover:opacity-100'
|
|
34
34
|
)}
|
|
35
35
|
>
|
|
36
36
|
<div className="aspect-[5/3] rounded-lg overflow-hidden w-full">
|
|
@@ -44,16 +44,18 @@ export function FullscreenViewer({ album, className }: FullscreenViewerProps) {
|
|
|
44
44
|
<SafeArea
|
|
45
45
|
ref={containerRef}
|
|
46
46
|
className={cn(
|
|
47
|
-
'
|
|
47
|
+
'h-full flex w-full bg-[var(--color-background-primary)]',
|
|
48
48
|
isMobile ? 'flex-col' : 'flex-row',
|
|
49
49
|
className
|
|
50
50
|
)}
|
|
51
51
|
>
|
|
52
52
|
{/* Album header - mobile only */}
|
|
53
53
|
{isMobile && (
|
|
54
|
-
<div className="border-b border-
|
|
55
|
-
<h2 className="text-base font-semibold text-primary">
|
|
56
|
-
|
|
54
|
+
<div className="border-b border-[var(--color-border-tertiary)] bg-[var(--color-background-primary)]/95 backdrop-blur-sm px-4 py-3">
|
|
55
|
+
<h2 className="text-base font-semibold text-[var(--color-text-primary)]">
|
|
56
|
+
{album.title}
|
|
57
|
+
</h2>
|
|
58
|
+
<p className="text-sm text-[var(--color-text-secondary)]">
|
|
57
59
|
{selectedIndex + 1} / {album.photos.length}
|
|
58
60
|
</p>
|
|
59
61
|
</div>
|
|
@@ -72,7 +74,7 @@ export function FullscreenViewer({ album, className }: FullscreenViewerProps) {
|
|
|
72
74
|
<img
|
|
73
75
|
src={selectedPhoto.url}
|
|
74
76
|
alt={selectedPhoto.title || album.title}
|
|
75
|
-
className="rounded-3xl shadow-sm border border-primary/10 max-w-full max-h-full object-contain"
|
|
77
|
+
className="rounded-3xl shadow-sm border border-[var(--color-ring-primary)]/10 max-w-full max-h-full object-contain"
|
|
76
78
|
/>
|
|
77
79
|
) : null}
|
|
78
80
|
</div>
|
|
@@ -9,9 +9,8 @@ export const resource: ResourceConfig = {
|
|
|
9
9
|
mimeType: 'text/html;profile=mcp-app',
|
|
10
10
|
_meta: {
|
|
11
11
|
ui: {
|
|
12
|
-
domain: 'https://sunpeak.ai',
|
|
13
12
|
csp: {
|
|
14
|
-
resourceDomains: ['https://cdn.sunpeak.ai'
|
|
13
|
+
resourceDomains: ['https://cdn.sunpeak.ai'],
|
|
15
14
|
},
|
|
16
15
|
},
|
|
17
16
|
},
|
|
@@ -47,7 +46,7 @@ export function CarouselResource() {
|
|
|
47
46
|
const places = output?.places ?? [];
|
|
48
47
|
|
|
49
48
|
return (
|
|
50
|
-
<SafeArea>
|
|
49
|
+
<SafeArea className="p-4">
|
|
51
50
|
<Carousel
|
|
52
51
|
gap={16}
|
|
53
52
|
showArrows={true}
|
|
@@ -11,14 +11,15 @@ describe('Card', () => {
|
|
|
11
11
|
);
|
|
12
12
|
|
|
13
13
|
const card = container.firstChild as HTMLElement;
|
|
14
|
-
expect(card.className).toContain('border border-
|
|
14
|
+
expect(card.className).toContain('border border-[var(--color-border-tertiary)]');
|
|
15
|
+
expect(card.className).toContain('bg-[var(--color-background-primary)]');
|
|
15
16
|
|
|
16
17
|
rerender(
|
|
17
18
|
<Card variant="bordered" data-testid="card">
|
|
18
19
|
Content
|
|
19
20
|
</Card>
|
|
20
21
|
);
|
|
21
|
-
expect(card.className).toContain('border-2 border-
|
|
22
|
+
expect(card.className).toContain('border-2 border-[var(--color-border-primary)]');
|
|
22
23
|
|
|
23
24
|
rerender(
|
|
24
25
|
<Card variant="elevated" data-testid="card">
|
|
@@ -43,9 +43,11 @@ export const Card = React.forwardRef<HTMLDivElement, CardProps>(
|
|
|
43
43
|
ref
|
|
44
44
|
) => {
|
|
45
45
|
const variantClasses = {
|
|
46
|
-
default: 'border border-
|
|
47
|
-
bordered:
|
|
48
|
-
|
|
46
|
+
default: 'border border-[var(--color-border-tertiary)] bg-[var(--color-background-primary)]',
|
|
47
|
+
bordered:
|
|
48
|
+
'border-2 border-[var(--color-border-primary)] bg-[var(--color-background-primary)]',
|
|
49
|
+
elevated:
|
|
50
|
+
'border border-[var(--color-border-tertiary)] bg-[var(--color-background-primary)] shadow-lg',
|
|
49
51
|
};
|
|
50
52
|
|
|
51
53
|
const handleCardClick = (e: React.MouseEvent<HTMLDivElement>) => {
|
|
@@ -109,7 +111,9 @@ export const Card = React.forwardRef<HTMLDivElement, CardProps>(
|
|
|
109
111
|
{header}
|
|
110
112
|
</h2>
|
|
111
113
|
)}
|
|
112
|
-
{metadata &&
|
|
114
|
+
{metadata && (
|
|
115
|
+
<p className="text-[var(--color-text-secondary)] text-xs mb-1">{metadata}</p>
|
|
116
|
+
)}
|
|
113
117
|
{children && <div className="text-sm leading-normal line-clamp-2 mb-3">{children}</div>}
|
|
114
118
|
{hasButtons && (
|
|
115
119
|
<div className="flex gap-2 flex-wrap mt-auto">
|
|
@@ -195,7 +195,7 @@ export function MapView({
|
|
|
195
195
|
className={cn(
|
|
196
196
|
'absolute inset-0 overflow-hidden',
|
|
197
197
|
isFullscreen &&
|
|
198
|
-
'left-[340px] right-2 top-2 bottom-4 border border-
|
|
198
|
+
'left-[340px] right-2 top-2 bottom-4 border border-[var(--color-border-tertiary)] rounded-3xl',
|
|
199
199
|
className
|
|
200
200
|
)}
|
|
201
201
|
>
|
|
@@ -66,7 +66,7 @@ export function Map({ className }: MapProps) {
|
|
|
66
66
|
'relative w-full h-full',
|
|
67
67
|
isFullscreen
|
|
68
68
|
? 'rounded-none border-0'
|
|
69
|
-
: 'border border-
|
|
69
|
+
: 'border border-[var(--color-border-tertiary)] rounded-2xl sm:rounded-3xl'
|
|
70
70
|
)}
|
|
71
71
|
>
|
|
72
72
|
{/* Fullscreen button - only show in embedded mode */}
|
|
@@ -24,7 +24,7 @@ export const PlaceCard = React.forwardRef<HTMLDivElement, PlaceCardProps>(
|
|
|
24
24
|
<div
|
|
25
25
|
className={cn(
|
|
26
26
|
'border-b hover:border-transparent',
|
|
27
|
-
isSelected ? 'border-transparent' : 'border-
|
|
27
|
+
isSelected ? 'border-transparent' : 'border-[var(--color-border-tertiary)]'
|
|
28
28
|
)}
|
|
29
29
|
>
|
|
30
30
|
<button
|
|
@@ -38,9 +38,13 @@ export const PlaceCard = React.forwardRef<HTMLDivElement, PlaceCardProps>(
|
|
|
38
38
|
loading="lazy"
|
|
39
39
|
/>
|
|
40
40
|
<div className="min-w-0">
|
|
41
|
-
<div className="font-medium truncate text-primary">
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
<div className="font-medium truncate text-[var(--color-text-primary)]">
|
|
42
|
+
{place.name}
|
|
43
|
+
</div>
|
|
44
|
+
<div className="text-xs text-[var(--color-text-secondary)] truncate">
|
|
45
|
+
{place.description}
|
|
46
|
+
</div>
|
|
47
|
+
<div className="text-xs mt-1 text-[var(--color-text-secondary)] flex items-center gap-1">
|
|
44
48
|
<Star className="h-3 w-3" aria-hidden="true" />
|
|
45
49
|
{place.rating.toFixed(1)}
|
|
46
50
|
{place.price && <span>· {place.price}</span>}
|
|
@@ -26,7 +26,7 @@ export const PlaceCarousel = React.forwardRef<HTMLDivElement, PlaceCarouselProps
|
|
|
26
26
|
{places.map((place) => (
|
|
27
27
|
<div
|
|
28
28
|
key={place.id}
|
|
29
|
-
className="ring ring-black/10 dark:ring-white/10 max-w-[330px] w-full shadow-xl rounded-2xl bg-
|
|
29
|
+
className="ring ring-black/10 dark:ring-white/10 max-w-[330px] w-full shadow-xl rounded-2xl bg-[var(--color-background-primary)] flex-shrink-0"
|
|
30
30
|
>
|
|
31
31
|
<PlaceCard
|
|
32
32
|
place={place}
|
|
@@ -54,7 +54,7 @@ export const PlaceInspector = React.forwardRef<HTMLDivElement, PlaceInspectorPro
|
|
|
54
54
|
<X className="h-[18px] w-[18px]" aria-hidden="true" />
|
|
55
55
|
</Button>
|
|
56
56
|
|
|
57
|
-
<div className="relative h-full overflow-y-auto rounded-none xl:rounded-3xl bg-
|
|
57
|
+
<div className="relative h-full overflow-y-auto rounded-none xl:rounded-3xl bg-[var(--color-background-primary)] xl:shadow-xl xl:ring ring-black/10 dark:ring-white/10">
|
|
58
58
|
{/* Thumbnail */}
|
|
59
59
|
<div className="relative mt-2 xl:mt-0 px-2 xl:px-0">
|
|
60
60
|
<img
|
|
@@ -68,8 +68,10 @@ export const PlaceInspector = React.forwardRef<HTMLDivElement, PlaceInspectorPro
|
|
|
68
68
|
<div className="h-[calc(100%-11rem)] sm:h-[calc(100%-14rem)]">
|
|
69
69
|
{/* Place info */}
|
|
70
70
|
<div className="p-4 sm:p-5">
|
|
71
|
-
<div className="text-2xl font-medium truncate text-primary">
|
|
72
|
-
|
|
71
|
+
<div className="text-2xl font-medium truncate text-[var(--color-text-primary)]">
|
|
72
|
+
{place.name}
|
|
73
|
+
</div>
|
|
74
|
+
<div className="text-sm mt-1 text-[var(--color-text-secondary)] flex items-center gap-1">
|
|
73
75
|
<Star className="h-3.5 w-3.5" aria-hidden="true" />
|
|
74
76
|
{place.rating.toFixed(1)}
|
|
75
77
|
{place.price && <span>· {place.price}</span>}
|
|
@@ -100,7 +102,7 @@ export const PlaceInspector = React.forwardRef<HTMLDivElement, PlaceInspectorPro
|
|
|
100
102
|
</div>
|
|
101
103
|
|
|
102
104
|
{/* Description */}
|
|
103
|
-
<div className="text-sm mt-5 text-primary">
|
|
105
|
+
<div className="text-sm mt-5 text-[var(--color-text-primary)]">
|
|
104
106
|
{place.description} Enjoy a slice at one of SF's favorites. Fresh ingredients,
|
|
105
107
|
great crust, and cozy vibes.
|
|
106
108
|
</div>
|
|
@@ -108,15 +110,21 @@ export const PlaceInspector = React.forwardRef<HTMLDivElement, PlaceInspectorPro
|
|
|
108
110
|
|
|
109
111
|
{/* Reviews */}
|
|
110
112
|
<div className="px-4 sm:px-5 pb-4">
|
|
111
|
-
<div className="text-lg font-medium mb-2 text-primary">
|
|
113
|
+
<div className="text-lg font-medium mb-2 text-[var(--color-text-primary)]">
|
|
114
|
+
Reviews
|
|
115
|
+
</div>
|
|
112
116
|
<ul className="space-y-3 divide-y divide-black/5 dark:divide-white/5">
|
|
113
117
|
{REVIEWS.map((review, idx) => (
|
|
114
118
|
<li key={idx} className="py-3">
|
|
115
119
|
<div className="flex items-start gap-3">
|
|
116
120
|
<Avatar imageUrl={review.avatar} name={review.user} size={32} />
|
|
117
121
|
<div className="min-w-0 gap-1 flex flex-col">
|
|
118
|
-
<div className="text-xs font-medium text-secondary">
|
|
119
|
-
|
|
122
|
+
<div className="text-xs font-medium text-[var(--color-text-secondary)]">
|
|
123
|
+
{review.user}
|
|
124
|
+
</div>
|
|
125
|
+
<div className="text-sm text-[var(--color-text-primary)]">
|
|
126
|
+
{review.text}
|
|
127
|
+
</div>
|
|
120
128
|
</div>
|
|
121
129
|
</div>
|
|
122
130
|
</li>
|
|
@@ -46,11 +46,14 @@ export const PlaceList = React.forwardRef<HTMLDivElement, PlaceListProps>(
|
|
|
46
46
|
className
|
|
47
47
|
)}
|
|
48
48
|
>
|
|
49
|
-
<div
|
|
49
|
+
<div
|
|
50
|
+
ref={scrollRef}
|
|
51
|
+
className="relative px-2 h-full overflow-y-auto bg-[var(--color-background-primary)]"
|
|
52
|
+
>
|
|
50
53
|
{/* Header */}
|
|
51
|
-
<div className="flex justify-between flex-row items-center px-3 sticky bg-
|
|
52
|
-
<span className="text-primary">{places.length} results</span>
|
|
53
|
-
<Settings className="h-5 w-5 text-secondary" aria-hidden="true" />
|
|
54
|
+
<div className="flex justify-between flex-row items-center px-3 sticky bg-[var(--color-background-primary)] top-0 py-4 text-md font-medium">
|
|
55
|
+
<span className="text-[var(--color-text-primary)]">{places.length} results</span>
|
|
56
|
+
<Settings className="h-5 w-5 text-[var(--color-text-secondary)]" aria-hidden="true" />
|
|
54
57
|
</div>
|
|
55
58
|
|
|
56
59
|
{/* Place list */}
|
|
@@ -9,12 +9,10 @@ export const resource: ResourceConfig = {
|
|
|
9
9
|
mimeType: 'text/html;profile=mcp-app',
|
|
10
10
|
_meta: {
|
|
11
11
|
ui: {
|
|
12
|
-
domain: 'https://sunpeak.ai',
|
|
13
12
|
csp: {
|
|
14
13
|
connectDomains: ['https://api.mapbox.com', 'https://events.mapbox.com'],
|
|
15
14
|
resourceDomains: [
|
|
16
15
|
'https://cdn.sunpeak.ai',
|
|
17
|
-
'https://cdn.openai.com',
|
|
18
16
|
'https://api.mapbox.com',
|
|
19
17
|
'https://events.mapbox.com',
|
|
20
18
|
],
|