sunpeak 0.2.2 โ 0.2.4
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 +26 -9
- package/bin/sunpeak.js +5 -0
- package/package.json +1 -1
- package/template/dev/styles.css +1 -0
- package/template/src/App.tsx +1 -1
- package/template/src/components/sunpeak-card.tsx +5 -5
- package/template/vite.config.ts +3 -12
package/README.md
CHANGED
|
@@ -15,24 +15,41 @@
|
|
|
15
15
|
[](https://www.typescriptlang.org/)
|
|
16
16
|
[](https://reactjs.org/)
|
|
17
17
|
|
|
18
|
-
The ChatGPT Apps UI SDK.
|
|
18
|
+
The ChatGPT Apps UI SDK.
|
|
19
|
+
|
|
20
|
+
Build and test your ChatGPT App UI locally with approved React components.
|
|
19
21
|
|
|
20
22
|

|
|
21
23
|
|
|
22
|
-
|
|
24
|
+
## Quickstart
|
|
25
|
+
|
|
26
|
+
Requirements: Node (20+), pnpm (10+)
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pnpm dlx sunpeak init
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Key Features
|
|
23
33
|
- ๐บ ChatGPT simulator for rapid UI component development.
|
|
24
|
-
- ๐ React component library built
|
|
34
|
+
- ๐ React component library built on [shadcn](https://ui.shadcn.com/).
|
|
25
35
|
- ๐ฑ Interface for custom components that work across genAI platforms.
|
|
26
36
|
- ๐ค Styles that fit the [OpenAI design system](https://developers.openai.com/apps-sdk/build/chatgpt-ui).
|
|
27
37
|
- ๐งช Testing framework that replicates advanced ChatGPT behavior locally.
|
|
28
38
|
|
|
29
|
-
##
|
|
30
|
-
|
|
31
|
-
|
|
39
|
+
## Example Component
|
|
40
|
+
```tsx
|
|
41
|
+
import { SunpeakCard } from "sunpeak";
|
|
32
42
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
43
|
+
export default function App() {
|
|
44
|
+
return (
|
|
45
|
+
<SunpeakCard
|
|
46
|
+
image="/photo.jpg"
|
|
47
|
+
imageAlt="Product"
|
|
48
|
+
header="Summer Collection"
|
|
49
|
+
button1={{ children: "Shop Now", onClick: () => console.log("Howdy!") }}
|
|
50
|
+
/>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
36
53
|
```
|
|
37
54
|
|
|
38
55
|
## Supported Platforms
|
package/bin/sunpeak.js
CHANGED
|
@@ -25,6 +25,11 @@ async function init(projectName) {
|
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
if (projectName === 'template') {
|
|
29
|
+
console.error('Error: "template" is a reserved name. Please choose another name.');
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
|
|
28
33
|
const targetDir = join(process.cwd(), projectName);
|
|
29
34
|
|
|
30
35
|
if (existsSync(targetDir)) {
|
package/package.json
CHANGED
package/template/dev/styles.css
CHANGED
package/template/src/App.tsx
CHANGED
|
@@ -18,7 +18,7 @@ export interface AppProps {
|
|
|
18
18
|
|
|
19
19
|
export function App({ data }: AppProps) {
|
|
20
20
|
return (
|
|
21
|
-
<SunpeakCarousel gap={16} showArrows={true} showEdgeGradients={true} cardWidth={
|
|
21
|
+
<SunpeakCarousel gap={16} showArrows={true} showEdgeGradients={true} cardWidth={220}>
|
|
22
22
|
{data.map((place) => (
|
|
23
23
|
<SunpeakCard
|
|
24
24
|
key={place.id}
|
|
@@ -105,9 +105,9 @@ export const SunpeakCard = React.forwardRef<HTMLDivElement, SunpeakCardProps>(
|
|
|
105
105
|
)}
|
|
106
106
|
<div className="flex flex-col flex-1">
|
|
107
107
|
{(header || metadata) && (
|
|
108
|
-
<CardHeader className={cn(image && "pt-
|
|
108
|
+
<CardHeader className={cn("p-3", image && "pt-2")}>
|
|
109
109
|
{header && (
|
|
110
|
-
<CardTitle className="text-
|
|
110
|
+
<CardTitle className="text-sm font-medium leading-tight overflow-hidden text-ellipsis whitespace-nowrap">
|
|
111
111
|
{header}
|
|
112
112
|
</CardTitle>
|
|
113
113
|
)}
|
|
@@ -120,14 +120,14 @@ export const SunpeakCard = React.forwardRef<HTMLDivElement, SunpeakCardProps>(
|
|
|
120
120
|
)}
|
|
121
121
|
{children && (
|
|
122
122
|
<CardContent className={cn(
|
|
123
|
-
"text-sm leading-normal",
|
|
124
|
-
(header || metadata)
|
|
123
|
+
"px-3 pb-3 text-sm leading-normal",
|
|
124
|
+
(header || metadata) ? "pt-0" : "pt-3"
|
|
125
125
|
)}>
|
|
126
126
|
<div className="line-clamp-2">{children}</div>
|
|
127
127
|
</CardContent>
|
|
128
128
|
)}
|
|
129
129
|
{hasButtons && (
|
|
130
|
-
<CardFooter className="flex gap-2 flex-wrap">
|
|
130
|
+
<CardFooter className="flex gap-2 flex-wrap px-3 pb-3 pt-0">
|
|
131
131
|
{button1 && renderButton(button1)}
|
|
132
132
|
{button2 && renderButton(button2)}
|
|
133
133
|
</CardFooter>
|
package/template/vite.config.ts
CHANGED
|
@@ -2,19 +2,10 @@ import { defineConfig } from 'vite';
|
|
|
2
2
|
import react from '@vitejs/plugin-react';
|
|
3
3
|
import tailwindcss from '@tailwindcss/vite';
|
|
4
4
|
import path from 'path';
|
|
5
|
-
import fs from 'fs';
|
|
6
5
|
|
|
7
|
-
// Check if we're in the sunpeak workspace
|
|
8
|
-
const
|
|
6
|
+
// Check if we're in the sunpeak workspace (directory is named "template")
|
|
7
|
+
const isTemplate = path.basename(__dirname) === 'template';
|
|
9
8
|
const parentSrc = path.resolve(__dirname, '../src');
|
|
10
|
-
let isSunpeakWorkspace = false;
|
|
11
|
-
|
|
12
|
-
if (fs.existsSync(parentPkgPath) && fs.existsSync(parentSrc)) {
|
|
13
|
-
try {
|
|
14
|
-
const parentPkg = JSON.parse(fs.readFileSync(parentPkgPath, 'utf-8'));
|
|
15
|
-
isSunpeakWorkspace = parentPkg.name === 'sunpeak';
|
|
16
|
-
} catch {}
|
|
17
|
-
}
|
|
18
9
|
|
|
19
10
|
export default defineConfig({
|
|
20
11
|
plugins: [react(), tailwindcss()],
|
|
@@ -22,7 +13,7 @@ export default defineConfig({
|
|
|
22
13
|
alias: {
|
|
23
14
|
'@': path.resolve(__dirname, './src'),
|
|
24
15
|
// In workspace dev mode, use local sunpeak source
|
|
25
|
-
...(
|
|
16
|
+
...(isTemplate && {
|
|
26
17
|
'sunpeak': parentSrc,
|
|
27
18
|
'~': parentSrc,
|
|
28
19
|
}),
|