create-skybridge 0.0.0-dev.ddd9ae4 → 0.0.0-dev.fd05cd0

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.
Files changed (36) hide show
  1. package/dist/index.js +17 -28
  2. package/package.json +10 -8
  3. package/template/.cursor/mcp.json +7 -0
  4. package/template/.nvmrc +1 -0
  5. package/template/.vscode/launch.json +16 -0
  6. package/template/.vscode/settings.json +3 -0
  7. package/template/.vscode/tasks.json +14 -0
  8. package/template/README.md +116 -0
  9. package/template/_gitignore +194 -0
  10. package/template/alpic.json +4 -0
  11. package/template/docs/demo.gif +0 -0
  12. package/template/package.json +21 -0
  13. package/template/pnpm-lock.yaml +317 -0
  14. package/template/pnpm-workspace.yaml +7 -0
  15. package/template/server/nodemon.json +5 -0
  16. package/template/server/package.json +36 -0
  17. package/template/server/pnpm-lock.yaml +3796 -0
  18. package/template/server/src/env.ts +12 -0
  19. package/template/server/src/index.ts +34 -0
  20. package/template/server/src/middleware.ts +54 -0
  21. package/template/server/src/pokedex.ts +148 -0
  22. package/template/server/src/server.ts +76 -0
  23. package/template/server/tsconfig.json +17 -0
  24. package/template/web/components.json +22 -0
  25. package/template/web/package.json +32 -0
  26. package/template/web/pnpm-lock.yaml +2629 -0
  27. package/template/web/src/components/ui/shadcn-io/spinner/index.tsx +272 -0
  28. package/template/web/src/helpers.ts +4 -0
  29. package/template/web/src/index.css +120 -0
  30. package/template/web/src/utils.ts +6 -0
  31. package/template/web/src/widgets/pokemon.tsx +203 -0
  32. package/template/web/tsconfig.app.json +34 -0
  33. package/template/web/tsconfig.json +13 -0
  34. package/template/web/tsconfig.node.json +26 -0
  35. package/template/web/vite.config.ts +16 -0
  36. package/LICENSE +0 -21
@@ -0,0 +1,272 @@
1
+ import {
2
+ LoaderCircleIcon,
3
+ LoaderIcon,
4
+ LoaderPinwheelIcon,
5
+ type LucideProps,
6
+ } from "lucide-react";
7
+ import { cn } from "../../../../utils";
8
+
9
+ type SpinnerVariantProps = Omit<SpinnerProps, "variant">;
10
+
11
+ const Default = ({ className, ...props }: SpinnerVariantProps) => (
12
+ <LoaderIcon className={cn("animate-spin", className)} {...props} />
13
+ );
14
+
15
+ const Circle = ({ className, ...props }: SpinnerVariantProps) => (
16
+ <LoaderCircleIcon className={cn("animate-spin", className)} {...props} />
17
+ );
18
+
19
+ const Pinwheel = ({ className, ...props }: SpinnerVariantProps) => (
20
+ <LoaderPinwheelIcon className={cn("animate-spin", className)} {...props} />
21
+ );
22
+
23
+ const CircleFilled = ({
24
+ className,
25
+ size = 24,
26
+ ...props
27
+ }: SpinnerVariantProps) => (
28
+ <div className="relative" style={{ width: size, height: size }}>
29
+ <div className="absolute inset-0 rotate-180">
30
+ <LoaderCircleIcon
31
+ className={cn("animate-spin", className, "text-foreground opacity-20")}
32
+ size={size}
33
+ {...props}
34
+ />
35
+ </div>
36
+ <LoaderCircleIcon
37
+ className={cn("relative animate-spin", className)}
38
+ size={size}
39
+ {...props}
40
+ />
41
+ </div>
42
+ );
43
+
44
+ const Ellipsis = ({ size = 24, ...props }: SpinnerVariantProps) => {
45
+ return (
46
+ <svg
47
+ height={size}
48
+ viewBox="0 0 24 24"
49
+ width={size}
50
+ xmlns="http://www.w3.org/2000/svg"
51
+ {...props}
52
+ >
53
+ <title>Loading...</title>
54
+ <circle cx="4" cy="12" fill="currentColor" r="2">
55
+ <animate
56
+ attributeName="cy"
57
+ begin="0;ellipsis3.end+0.25s"
58
+ calcMode="spline"
59
+ dur="0.6s"
60
+ id="ellipsis1"
61
+ keySplines=".33,.66,.66,1;.33,0,.66,.33"
62
+ values="12;6;12"
63
+ />
64
+ </circle>
65
+ <circle cx="12" cy="12" fill="currentColor" r="2">
66
+ <animate
67
+ attributeName="cy"
68
+ begin="ellipsis1.begin+0.1s"
69
+ calcMode="spline"
70
+ dur="0.6s"
71
+ keySplines=".33,.66,.66,1;.33,0,.66,.33"
72
+ values="12;6;12"
73
+ />
74
+ </circle>
75
+ <circle cx="20" cy="12" fill="currentColor" r="2">
76
+ <animate
77
+ attributeName="cy"
78
+ begin="ellipsis1.begin+0.2s"
79
+ calcMode="spline"
80
+ dur="0.6s"
81
+ id="ellipsis3"
82
+ keySplines=".33,.66,.66,1;.33,0,.66,.33"
83
+ values="12;6;12"
84
+ />
85
+ </circle>
86
+ </svg>
87
+ );
88
+ };
89
+
90
+ const Ring = ({ size = 24, ...props }: SpinnerVariantProps) => (
91
+ <svg
92
+ height={size}
93
+ stroke="currentColor"
94
+ viewBox="0 0 44 44"
95
+ width={size}
96
+ xmlns="http://www.w3.org/2000/svg"
97
+ {...props}
98
+ >
99
+ <title>Loading...</title>
100
+ <g fill="none" fillRule="evenodd" strokeWidth="2">
101
+ <circle cx="22" cy="22" r="1">
102
+ <animate
103
+ attributeName="r"
104
+ begin="0s"
105
+ calcMode="spline"
106
+ dur="1.8s"
107
+ keySplines="0.165, 0.84, 0.44, 1"
108
+ keyTimes="0; 1"
109
+ repeatCount="indefinite"
110
+ values="1; 20"
111
+ />
112
+ <animate
113
+ attributeName="stroke-opacity"
114
+ begin="0s"
115
+ calcMode="spline"
116
+ dur="1.8s"
117
+ keySplines="0.3, 0.61, 0.355, 1"
118
+ keyTimes="0; 1"
119
+ repeatCount="indefinite"
120
+ values="1; 0"
121
+ />
122
+ </circle>
123
+ <circle cx="22" cy="22" r="1">
124
+ <animate
125
+ attributeName="r"
126
+ begin="-0.9s"
127
+ calcMode="spline"
128
+ dur="1.8s"
129
+ keySplines="0.165, 0.84, 0.44, 1"
130
+ keyTimes="0; 1"
131
+ repeatCount="indefinite"
132
+ values="1; 20"
133
+ />
134
+ <animate
135
+ attributeName="stroke-opacity"
136
+ begin="-0.9s"
137
+ calcMode="spline"
138
+ dur="1.8s"
139
+ keySplines="0.3, 0.61, 0.355, 1"
140
+ keyTimes="0; 1"
141
+ repeatCount="indefinite"
142
+ values="1; 0"
143
+ />
144
+ </circle>
145
+ </g>
146
+ </svg>
147
+ );
148
+
149
+ const Bars = ({ size = 24, ...props }: SpinnerVariantProps) => (
150
+ <svg
151
+ height={size}
152
+ viewBox="0 0 24 24"
153
+ width={size}
154
+ xmlns="http://www.w3.org/2000/svg"
155
+ {...props}
156
+ >
157
+ <title>Loading...</title>
158
+ <style>{`
159
+ .spinner-bar {
160
+ animation: spinner-bars-animation .8s linear infinite;
161
+ animation-delay: -.8s;
162
+ }
163
+ .spinner-bars-2 {
164
+ animation-delay: -.65s;
165
+ }
166
+ .spinner-bars-3 {
167
+ animation-delay: -0.5s;
168
+ }
169
+ @keyframes spinner-bars-animation {
170
+ 0% {
171
+ y: 1px;
172
+ height: 22px;
173
+ }
174
+ 93.75% {
175
+ y: 5px;
176
+ height: 14px;
177
+ opacity: 0.2;
178
+ }
179
+ }
180
+ `}</style>
181
+ <rect
182
+ className="spinner-bar"
183
+ fill="currentColor"
184
+ height="22"
185
+ width="6"
186
+ x="1"
187
+ y="1"
188
+ />
189
+ <rect
190
+ className="spinner-bar spinner-bars-2"
191
+ fill="currentColor"
192
+ height="22"
193
+ width="6"
194
+ x="9"
195
+ y="1"
196
+ />
197
+ <rect
198
+ className="spinner-bar spinner-bars-3"
199
+ fill="currentColor"
200
+ height="22"
201
+ width="6"
202
+ x="17"
203
+ y="1"
204
+ />
205
+ </svg>
206
+ );
207
+
208
+ const Infinite = ({ size = 24, ...props }: SpinnerVariantProps) => (
209
+ <svg
210
+ height={size}
211
+ preserveAspectRatio="xMidYMid"
212
+ viewBox="0 0 100 100"
213
+ width={size}
214
+ xmlns="http://www.w3.org/2000/svg"
215
+ {...props}
216
+ >
217
+ <title>Loading...</title>
218
+ <path
219
+ d="M24.3 30C11.4 30 5 43.3 5 50s6.4 20 19.3 20c19.3 0 32.1-40 51.4-40 C88.6 30 95 43.3 95 50s-6.4 20-19.3 20C56.4 70 43.6 30 24.3 30z"
220
+ fill="none"
221
+ stroke="currentColor"
222
+ strokeDasharray="205.271142578125 51.317785644531256"
223
+ strokeLinecap="round"
224
+ strokeWidth="10"
225
+ style={{
226
+ transform: "scale(0.8)",
227
+ transformOrigin: "50px 50px",
228
+ }}
229
+ >
230
+ <animate
231
+ attributeName="stroke-dashoffset"
232
+ dur="2s"
233
+ keyTimes="0;1"
234
+ repeatCount="indefinite"
235
+ values="0;256.58892822265625"
236
+ />
237
+ </path>
238
+ </svg>
239
+ );
240
+
241
+ export type SpinnerProps = LucideProps & {
242
+ variant?:
243
+ | "default"
244
+ | "circle"
245
+ | "pinwheel"
246
+ | "circle-filled"
247
+ | "ellipsis"
248
+ | "ring"
249
+ | "bars"
250
+ | "infinite";
251
+ };
252
+
253
+ export const Spinner = ({ variant, ...props }: SpinnerProps) => {
254
+ switch (variant) {
255
+ case "circle":
256
+ return <Circle {...props} />;
257
+ case "pinwheel":
258
+ return <Pinwheel {...props} />;
259
+ case "circle-filled":
260
+ return <CircleFilled {...props} />;
261
+ case "ellipsis":
262
+ return <Ellipsis {...props} />;
263
+ case "ring":
264
+ return <Ring {...props} />;
265
+ case "bars":
266
+ return <Bars {...props} />;
267
+ case "infinite":
268
+ return <Infinite {...props} />;
269
+ default:
270
+ return <Default {...props} />;
271
+ }
272
+ };
@@ -0,0 +1,4 @@
1
+ import { generateHelpers } from "skybridge/web";
2
+ import type { AppType } from "../../server/src/server";
3
+
4
+ export const { useCallTool, useToolInfo } = generateHelpers<AppType>();
@@ -0,0 +1,120 @@
1
+ @import "tailwindcss";
2
+ @import "tw-animate-css";
3
+
4
+ @custom-variant dark (&:is(.dark *));
5
+
6
+ @theme inline {
7
+ --radius-sm: calc(var(--radius) - 4px);
8
+ --radius-md: calc(var(--radius) - 2px);
9
+ --radius-lg: var(--radius);
10
+ --radius-xl: calc(var(--radius) + 4px);
11
+ --color-background: var(--background);
12
+ --color-foreground: var(--foreground);
13
+ --color-card: var(--card);
14
+ --color-card-foreground: var(--card-foreground);
15
+ --color-popover: var(--popover);
16
+ --color-popover-foreground: var(--popover-foreground);
17
+ --color-primary: var(--primary);
18
+ --color-primary-foreground: var(--primary-foreground);
19
+ --color-secondary: var(--secondary);
20
+ --color-secondary-foreground: var(--secondary-foreground);
21
+ --color-muted: var(--muted);
22
+ --color-muted-foreground: var(--muted-foreground);
23
+ --color-accent: var(--accent);
24
+ --color-accent-foreground: var(--accent-foreground);
25
+ --color-destructive: var(--destructive);
26
+ --color-border: var(--border);
27
+ --color-input: var(--input);
28
+ --color-ring: var(--ring);
29
+ --color-chart-1: var(--chart-1);
30
+ --color-chart-2: var(--chart-2);
31
+ --color-chart-3: var(--chart-3);
32
+ --color-chart-4: var(--chart-4);
33
+ --color-chart-5: var(--chart-5);
34
+ --color-sidebar: var(--sidebar);
35
+ --color-sidebar-foreground: var(--sidebar-foreground);
36
+ --color-sidebar-primary: var(--sidebar-primary);
37
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
38
+ --color-sidebar-accent: var(--sidebar-accent);
39
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
40
+ --color-sidebar-border: var(--sidebar-border);
41
+ --color-sidebar-ring: var(--sidebar-ring);
42
+ }
43
+
44
+ :root {
45
+ --radius: 0.625rem;
46
+ --background: oklch(1 0 0);
47
+ --foreground: oklch(0.145 0 0);
48
+ --card: oklch(1 0 0);
49
+ --card-foreground: oklch(0.145 0 0);
50
+ --popover: oklch(1 0 0);
51
+ --popover-foreground: oklch(0.145 0 0);
52
+ --primary: oklch(0.205 0 0);
53
+ --primary-foreground: oklch(0.985 0 0);
54
+ --secondary: oklch(0.97 0 0);
55
+ --secondary-foreground: oklch(0.205 0 0);
56
+ --muted: oklch(0.97 0 0);
57
+ --muted-foreground: oklch(0.556 0 0);
58
+ --accent: oklch(0.97 0 0);
59
+ --accent-foreground: oklch(0.205 0 0);
60
+ --destructive: oklch(0.577 0.245 27.325);
61
+ --border: oklch(0.922 0 0);
62
+ --input: oklch(0.922 0 0);
63
+ --ring: oklch(0.708 0 0);
64
+ --chart-1: oklch(0.646 0.222 41.116);
65
+ --chart-2: oklch(0.6 0.118 184.704);
66
+ --chart-3: oklch(0.398 0.07 227.392);
67
+ --chart-4: oklch(0.828 0.189 84.429);
68
+ --chart-5: oklch(0.769 0.188 70.08);
69
+ --sidebar: oklch(0.985 0 0);
70
+ --sidebar-foreground: oklch(0.145 0 0);
71
+ --sidebar-primary: oklch(0.205 0 0);
72
+ --sidebar-primary-foreground: oklch(0.985 0 0);
73
+ --sidebar-accent: oklch(0.97 0 0);
74
+ --sidebar-accent-foreground: oklch(0.205 0 0);
75
+ --sidebar-border: oklch(0.922 0 0);
76
+ --sidebar-ring: oklch(0.708 0 0);
77
+ }
78
+
79
+ .dark {
80
+ --background: oklch(0.145 0 0);
81
+ --foreground: oklch(0.985 0 0);
82
+ --card: oklch(0.205 0 0);
83
+ --card-foreground: oklch(0.985 0 0);
84
+ --popover: oklch(0.205 0 0);
85
+ --popover-foreground: oklch(0.985 0 0);
86
+ --primary: oklch(0.922 0 0);
87
+ --primary-foreground: oklch(0.205 0 0);
88
+ --secondary: oklch(0.269 0 0);
89
+ --secondary-foreground: oklch(0.985 0 0);
90
+ --muted: oklch(0.269 0 0);
91
+ --muted-foreground: oklch(0.708 0 0);
92
+ --accent: oklch(0.269 0 0);
93
+ --accent-foreground: oklch(0.985 0 0);
94
+ --destructive: oklch(0.704 0.191 22.216);
95
+ --border: oklch(1 0 0 / 10%);
96
+ --input: oklch(1 0 0 / 15%);
97
+ --ring: oklch(0.556 0 0);
98
+ --chart-1: oklch(0.488 0.243 264.376);
99
+ --chart-2: oklch(0.696 0.17 162.48);
100
+ --chart-3: oklch(0.769 0.188 70.08);
101
+ --chart-4: oklch(0.627 0.265 303.9);
102
+ --chart-5: oklch(0.645 0.246 16.439);
103
+ --sidebar: oklch(0.205 0 0);
104
+ --sidebar-foreground: oklch(0.985 0 0);
105
+ --sidebar-primary: oklch(0.488 0.243 264.376);
106
+ --sidebar-primary-foreground: oklch(0.985 0 0);
107
+ --sidebar-accent: oklch(0.269 0 0);
108
+ --sidebar-accent-foreground: oklch(0.985 0 0);
109
+ --sidebar-border: oklch(1 0 0 / 10%);
110
+ --sidebar-ring: oklch(0.556 0 0);
111
+ }
112
+
113
+ @layer base {
114
+ * {
115
+ @apply border-border outline-ring/50;
116
+ }
117
+ body {
118
+ @apply bg-background text-foreground;
119
+ }
120
+ }
@@ -0,0 +1,6 @@
1
+ import { type ClassValue, clsx } from "clsx";
2
+ import { twMerge } from "tailwind-merge";
3
+
4
+ export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs));
6
+ }
@@ -0,0 +1,203 @@
1
+ import { Spinner } from "@/components/ui/shadcn-io/spinner";
2
+ import "@/index.css";
3
+
4
+ import { mountWidget } from "skybridge/web";
5
+ import { useCallTool, useToolInfo } from "../helpers";
6
+
7
+ const typesSvgs = {
8
+ bug: "https://raw.githubusercontent.com/partywhale/pokemon-type-icons/refs/heads/main/icons/bug.svg",
9
+ dark: "https://raw.githubusercontent.com/partywhale/pokemon-type-icons/refs/heads/main/icons/dark.svg",
10
+ dragon:
11
+ "https://raw.githubusercontent.com/partywhale/pokemon-type-icons/refs/heads/main/icons/dragon.svg",
12
+ electric:
13
+ "https://raw.githubusercontent.com/partywhale/pokemon-type-icons/refs/heads/main/icons/electric.svg",
14
+ fairy:
15
+ "https://raw.githubusercontent.com/partywhale/pokemon-type-icons/refs/heads/main/icons/fairy.svg",
16
+ fighting:
17
+ "https://raw.githubusercontent.com/partywhale/pokemon-type-icons/refs/heads/main/icons/fighting.svg",
18
+ fire: "https://raw.githubusercontent.com/partywhale/pokemon-type-icons/refs/heads/main/icons/fire.svg",
19
+ flying:
20
+ "https://raw.githubusercontent.com/partywhale/pokemon-type-icons/refs/heads/main/icons/flying.svg",
21
+ ghost:
22
+ "https://raw.githubusercontent.com/partywhale/pokemon-type-icons/refs/heads/main/icons/ghost.svg",
23
+ grass:
24
+ "https://raw.githubusercontent.com/partywhale/pokemon-type-icons/refs/heads/main/icons/grass.svg",
25
+ ground:
26
+ "https://raw.githubusercontent.com/partywhale/pokemon-type-icons/refs/heads/main/icons/ground.svg",
27
+ ice: "https://raw.githubusercontent.com/partywhale/pokemon-type-icons/refs/heads/main/icons/ice.svg",
28
+ normal:
29
+ "https://raw.githubusercontent.com/partywhale/pokemon-type-icons/refs/heads/main/icons/normal.svg",
30
+ poison:
31
+ "https://raw.githubusercontent.com/partywhale/pokemon-type-icons/refs/heads/main/icons/poison.svg",
32
+ psychic:
33
+ "https://raw.githubusercontent.com/partywhale/pokemon-type-icons/refs/heads/main/icons/psychic.svg",
34
+ rock: "https://raw.githubusercontent.com/partywhale/pokemon-type-icons/refs/heads/main/icons/rock.svg",
35
+ steel:
36
+ "https://raw.githubusercontent.com/partywhale/pokemon-type-icons/refs/heads/main/icons/steel.svg",
37
+ water:
38
+ "https://raw.githubusercontent.com/partywhale/pokemon-type-icons/refs/heads/main/icons/water.svg",
39
+ };
40
+
41
+ const typesToClassnames: Record<
42
+ string,
43
+ {
44
+ background: {
45
+ widget: string;
46
+ tiles: string;
47
+ };
48
+ text: string;
49
+ }
50
+ > = {
51
+ bug: {
52
+ background: { widget: "bg-gray-100", tiles: "bg-gray-50" },
53
+ text: "black",
54
+ },
55
+ dark: {
56
+ background: { widget: "bg-gray-100", tiles: "bg-gray-50" },
57
+ text: "black",
58
+ },
59
+ dragon: {
60
+ background: { widget: "bg-gray-100", tiles: "bg-gray-50" },
61
+ text: "black",
62
+ },
63
+ electric: {
64
+ background: { widget: "bg-yellow-100", tiles: "bg-yellow-50" },
65
+ text: "text-yellow-600",
66
+ },
67
+ fairy: {
68
+ background: { widget: "bg-gray-100", tiles: "bg-gray-50" },
69
+ text: "black",
70
+ },
71
+ fighting: {
72
+ background: { widget: "bg-gray-100", tiles: "bg-gray-50" },
73
+ text: "black",
74
+ },
75
+ fire: {
76
+ background: { widget: "bg-orange-100", tiles: "bg-orange-50" },
77
+ text: "text-orange-600",
78
+ },
79
+ flying: {
80
+ background: { widget: "bg-gray-100", tiles: "bg-gray-50" },
81
+ text: "black",
82
+ },
83
+ ghost: {
84
+ background: { widget: "bg-gray-100", tiles: "bg-gray-50" },
85
+ text: "black",
86
+ },
87
+ grass: {
88
+ background: { widget: "bg-green-100", tiles: "bg-green-50" },
89
+ text: "text-green-600",
90
+ },
91
+ ground: {
92
+ background: { widget: "bg-[#D7CCC8]", tiles: "bg-[#EFEBE9]" },
93
+ text: "text-[#6D4C41]",
94
+ },
95
+ ice: {
96
+ background: { widget: "bg-blue-100", tiles: "bg-blue-50" },
97
+ text: "text-blue-600",
98
+ },
99
+ normal: {
100
+ background: { widget: "bg-gray-100", tiles: "bg-gray-50" },
101
+ text: "black",
102
+ },
103
+ poison: {
104
+ background: { widget: "bg-purple-100", tiles: "bg-purple-50" },
105
+ text: "text-purple-600",
106
+ },
107
+ psychic: {
108
+ background: { widget: "bg-gray-100", tiles: "bg-gray-50" },
109
+ text: "black",
110
+ },
111
+ rock: {
112
+ background: { widget: "bg-gray-100", tiles: "bg-gray-50" },
113
+ text: "black",
114
+ },
115
+ steel: {
116
+ background: { widget: "bg-gray-100", tiles: "bg-gray-50" },
117
+ text: "black",
118
+ },
119
+ water: {
120
+ background: { widget: "bg-blue-100", tiles: "bg-blue-50" },
121
+ text: "text-blue-600",
122
+ },
123
+ };
124
+
125
+ function Pokemon() {
126
+ const toolInfo = useToolInfo<"pokemon">();
127
+
128
+ const pokemon = toolInfo.output ?? null;
129
+
130
+ const { callTool: captureTool } = useCallTool("capture");
131
+
132
+ if (!pokemon) {
133
+ return (
134
+ <div className="flex justify-center items-center h-50">
135
+ <Spinner />
136
+ </div>
137
+ );
138
+ }
139
+
140
+ return (
141
+ <div
142
+ className={`p-4 rounded-xl flex flex-row gap-4 ${typesToClassnames[pokemon.types[0].id].background.widget}`}
143
+ >
144
+ <img
145
+ src={pokemon.imageUrl}
146
+ alt={pokemon.name}
147
+ className="object-contain drop-shadow-2xl"
148
+ />
149
+ <div className="flex flex-col gap-2">
150
+ <Tile color={pokemon.types[0].id}>
151
+ <div className="flex flex-row justify-between items-center">
152
+ <div>
153
+ <h2 className="text-lg font-bold uppercase">{pokemon.name}</h2>
154
+ <h2
155
+ className={`text-md font-bold ${typesToClassnames[pokemon.types[0].id].text}`}
156
+ >
157
+ {String(pokemon.order).padStart(3, "0")}
158
+ </h2>
159
+ </div>
160
+ <div className="flex flex-row gap-2">
161
+ {pokemon.types.map(({ id, name }) => (
162
+ <img
163
+ key={id}
164
+ src={typesSvgs[id as keyof typeof typesSvgs]}
165
+ alt={name}
166
+ className="w-6 h-6"
167
+ />
168
+ ))}
169
+ </div>
170
+ </div>
171
+ <p className="text-gray-500">{pokemon.description}</p>
172
+ <button
173
+ type="button"
174
+ onClick={() => captureTool({})}
175
+ className="mt-4 px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition-colors"
176
+ >
177
+ Capture Pokemon
178
+ </button>
179
+ </Tile>
180
+ </div>
181
+ </div>
182
+ );
183
+ }
184
+
185
+ const Tile = ({
186
+ children,
187
+ color,
188
+ }: {
189
+ children: React.ReactNode;
190
+ color: string;
191
+ }) => {
192
+ return (
193
+ <div
194
+ className={`p-4 rounded-xl ${typesToClassnames[color].background.tiles}`}
195
+ >
196
+ {children}
197
+ </div>
198
+ );
199
+ };
200
+
201
+ export default Pokemon;
202
+
203
+ mountWidget(<Pokemon />);
@@ -0,0 +1,34 @@
1
+ {
2
+ "compilerOptions": {
3
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
4
+ "target": "ES2022",
5
+ "useDefineForClassFields": true,
6
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
7
+ "module": "ESNext",
8
+ "types": ["vite/client"],
9
+ "skipLibCheck": true,
10
+
11
+ /* Bundler mode */
12
+ "moduleResolution": "bundler",
13
+ "allowImportingTsExtensions": true,
14
+ "verbatimModuleSyntax": true,
15
+ "moduleDetection": "force",
16
+ "noEmit": true,
17
+ "jsx": "react-jsx",
18
+
19
+ /* Linting */
20
+ "strict": true,
21
+ "noUnusedLocals": true,
22
+ "noUnusedParameters": true,
23
+ "erasableSyntaxOnly": true,
24
+ "noFallthroughCasesInSwitch": true,
25
+ "noUncheckedSideEffectImports": true,
26
+
27
+ /* Shadcn Config */
28
+ "baseUrl": ".",
29
+ "paths": {
30
+ "@/*": ["./src/*"]
31
+ }
32
+ },
33
+ "include": ["src"]
34
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "files": [],
3
+ "references": [
4
+ { "path": "./tsconfig.app.json" },
5
+ { "path": "./tsconfig.node.json" }
6
+ ],
7
+ "compilerOptions": {
8
+ "baseUrl": ".",
9
+ "paths": {
10
+ "@/*": ["./src/*"]
11
+ }
12
+ }
13
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "compilerOptions": {
3
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
4
+ "target": "ES2023",
5
+ "lib": ["ES2023"],
6
+ "module": "ESNext",
7
+ "types": ["node"],
8
+ "skipLibCheck": true,
9
+
10
+ /* Bundler mode */
11
+ "moduleResolution": "bundler",
12
+ "allowImportingTsExtensions": true,
13
+ "verbatimModuleSyntax": true,
14
+ "moduleDetection": "force",
15
+ "noEmit": true,
16
+
17
+ /* Linting */
18
+ "strict": true,
19
+ "noUnusedLocals": true,
20
+ "noUnusedParameters": true,
21
+ "erasableSyntaxOnly": true,
22
+ "noFallthroughCasesInSwitch": true,
23
+ "noUncheckedSideEffectImports": true
24
+ },
25
+ "include": ["vite.config.ts"]
26
+ }
@@ -0,0 +1,16 @@
1
+ import path from "node:path";
2
+ import tailwindcss from "@tailwindcss/vite";
3
+ import react from "@vitejs/plugin-react";
4
+ import { skybridge } from "skybridge/web";
5
+ import { defineConfig } from "vite";
6
+
7
+ // https://vite.dev/config/
8
+ export default defineConfig({
9
+ plugins: [skybridge(), react(), tailwindcss()],
10
+
11
+ resolve: {
12
+ alias: {
13
+ "@": path.resolve(__dirname, "./src"),
14
+ },
15
+ },
16
+ });