Skip to content

Commit 5f61638

Browse files
committed
Add Project Templates to Gallery
1 parent 74c7dca commit 5f61638

File tree

2 files changed

+119
-7
lines changed

2 files changed

+119
-7
lines changed

src/gallery/components/GalleryLayout.tsx

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,6 @@ export default function GalleryLayout({ children, title }: GalleryLayoutProps) {
2828
<a href="/gallery" className="text-xl font-bold text-gray-900 dark:text-gray-100">
2929
React Component Gallery
3030
</a>
31-
<nav className="hidden md:flex gap-6">
32-
<a href="/" className="text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100">
33-
← Back to Demo
34-
</a>
35-
</nav>
3631
</div>
3732
<DarkModeToggle />
3833
</div>

src/gallery/pages/Install.tsx

Lines changed: 119 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,127 @@
1-
import React from 'react'
1+
import React, { useState, useMemo } from 'react'
22
import GalleryLayout from '../components/GalleryLayout'
33
import CodeBlock from '../components/CodeBlock'
44

5+
function ProjectTemplateSelector() {
6+
const [project, setProject] = useState('MyApp')
7+
8+
const projectZip = useMemo(() => (project || 'MyApp') + '.zip', [project])
9+
10+
const zipUrl = (template: string) =>
11+
`https://account.servicestack.net/archive/${template}?Name=${project || 'MyApp'}`
12+
13+
const isAlphaNumeric = (e: React.KeyboardEvent<HTMLInputElement>) => {
14+
const key = e.key
15+
// Allow alphanumeric characters and underscore
16+
if (key.length === 1 && !/^[A-Za-z0-9_]$/.test(key)) {
17+
e.preventDefault()
18+
}
19+
}
20+
21+
return (
22+
<section className="not-prose w-full flex flex-col justify-center text-center">
23+
<div id="empty" className="mt-4 mb-2">
24+
<div className="flex justify-center mb-16">
25+
<div className="w-70">
26+
<input
27+
value={project}
28+
onChange={(e) => setProject(e.target.value)}
29+
type="text"
30+
placeholder="Project Name"
31+
autoCorrect="off"
32+
spellCheck={false}
33+
onKeyDown={isAlphaNumeric}
34+
className="mt-1 text-lg block w-full px-3 py-2 bg-white dark:bg-black border border-slate-300 dark:border-slate-700 rounded-md text-sm shadow-sm placeholder-slate-400
35+
focus:outline-none focus:border-sky-500 focus:ring-1 focus:ring-sky-500"
36+
/>
37+
</div>
38+
</div>
39+
<div id="ssg" className="mt-4 mb-2">
40+
<h3 className="text-gray-400 text-xl mb-2">React Templates</h3>
41+
<div className="flex flex-wrap justify-center">
42+
<div>
43+
<a className="archive-url hover:no-underline" href={zipUrl('NetCoreTemplates/react-vite')}>
44+
<div className="bg-white dark:bg-gray-800 px-4 py-4 mr-4 mb-4 rounded-lg shadow-lg text-center items-center justify-center hover:shadow-2xl dark:border-2 dark:border-pink-600 dark:hover:border-blue-600" style={{ minWidth: '150px' }}>
45+
<div className="text-center font-extrabold flex items-center justify-center mb-2">
46+
<div className="text-4xl text-blue-400 my-3">
47+
<svg className="w-14 h-14" xmlns="http://www.w3.org/2000/svg" viewBox="-10.5 -9.45 21 18.9" fill="none">
48+
<circle cx="0" cy="0" r="2" fill="currentColor"></circle>
49+
<g stroke="currentColor" strokeWidth="1" fill="none">
50+
<ellipse rx="10" ry="4.5"></ellipse>
51+
<ellipse rx="10" ry="4.5" transform="rotate(60)"></ellipse>
52+
<ellipse rx="10" ry="4.5" transform="rotate(120)"></ellipse>
53+
</g>
54+
</svg>
55+
</div>
56+
</div>
57+
<div className="text-xl font-medium text-gray-700 dark:text-gray-200">React Vite</div>
58+
<div className="flex justify-center h-8"></div>
59+
<span className="archive-name px-4 pb-2 text-blue-600 dark:text-indigo-400">{projectZip}</span>
60+
<div className="count mt-1 text-gray-400 text-sm"></div>
61+
</div>
62+
</a>
63+
<a className="text-sm text-center mr-4" href="https://react-vite.web-templates.io">react-vite.web-templates.io</a>
64+
</div>
65+
<div>
66+
<a className="archive-url hover:no-underline" href={zipUrl('NetCoreTemplates/nextjs')}>
67+
<div className="bg-white dark:bg-gray-800 px-4 py-4 mr-4 mb-4 rounded-lg shadow-lg text-center items-center justify-center hover:shadow-2xl dark:border-2 dark:border-pink-600 dark:hover:border-blue-600" style={{ minWidth: '150px' }}>
68+
<div className="text-center font-extrabold flex items-center justify-center mb-2">
69+
<div className="text-4xl text-blue-400 my-3">
70+
<svg className="w-14 h-14 bg-white text-gray-900 rounded-full" xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512">
71+
<path fill="currentColor" d="M386.399 35.508C217.06-64.061 1.885 57.55.012 253.882c-1.828 191.716 201.063 315.545 370.02 231.163L185.56 213.636v167.997c0 18.614-35.619 18.614-35.619 0V156.421c0-14.776 27.448-15.989 35.226-3.145L395.43 470.572c157.95-101.737 155.817-338.136-9.031-435.064zm-23.756 317.939L326.91 298.87V149.458c0-13.932 35.732-13.932 35.732 0v203.989z"/>
72+
</svg>
73+
</div>
74+
</div>
75+
<div className="text-xl font-medium text-gray-700 dark:text-gray-200">Next.js</div>
76+
<div className="flex justify-center h-8"></div>
77+
<span className="archive-name px-4 pb-2 text-blue-600 dark:text-indigo-400">{projectZip}</span>
78+
<div className="count mt-1 text-gray-400 text-sm"></div>
79+
</div>
80+
</a>
81+
<a className="text-sm text-center mr-4" href="https://nextjs.web-templates.io">nextjs.web-templates.io</a>
82+
</div>
83+
<div>
84+
<a className="archive-url hover:no-underline" href={zipUrl('NetCoreTemplates/react-spa')}>
85+
<div className="bg-white dark:bg-gray-800 px-4 py-4 mr-4 mb-4 rounded-lg shadow-lg text-center items-center justify-center hover:shadow-2xl dark:border-2 dark:border-pink-600 dark:hover:border-blue-600" style={{ minWidth: '150px' }}>
86+
<div className="text-center font-extrabold flex items-center justify-center mb-2">
87+
<div className="text-4xl text-blue-400 my-3">
88+
<svg className="w-14 h-14" xmlns="http://www.w3.org/2000/svg" viewBox="-10.5 -9.45 21 18.9" fill="none">
89+
<circle cx="0" cy="0" r="2" fill="currentColor"></circle>
90+
<g stroke="currentColor" strokeWidth="1" fill="none">
91+
<ellipse rx="10" ry="4.5"></ellipse>
92+
<ellipse rx="10" ry="4.5" transform="rotate(60)"></ellipse>
93+
<ellipse rx="10" ry="4.5" transform="rotate(120)"></ellipse>
94+
</g>
95+
</svg>
96+
</div>
97+
</div>
98+
<div className="text-xl font-medium text-gray-700 dark:text-gray-200">React SPA</div>
99+
<div className="flex justify-center h-8"></div>
100+
<span className="archive-name px-4 pb-2 text-blue-600 dark:text-indigo-400">{projectZip}</span>
101+
<div className="count mt-1 text-gray-400 text-sm"></div>
102+
</div>
103+
</a>
104+
<a className="text-sm text-center mr-4" href="https://react-spa.web-templates.io">react-spa.web-templates.io</a>
105+
</div>
106+
</div>
107+
</div>
108+
</div>
109+
</section>
110+
)
111+
}
112+
5113
export default function InstallPage() {
6114
return (
7115
<GalleryLayout title="Installation">
116+
<h2>Starting Project Templates</h2>
117+
<p>
118+
The fastest way to get started is to use one of our pre-configured project templates.
119+
These templates come with ServiceStack and <code>@servicestack/react</code> already configured with
120+
best practices, authentication, and example components to help you hit the ground running.
121+
</p>
122+
123+
<ProjectTemplateSelector />
124+
8125
<h2>NPM Installation</h2>
9126
<p>
10127
<strong>@servicestack/react</strong> can be added to existing React Apps by installing via npm:
@@ -89,7 +206,7 @@ export default {
89206
import { JsonServiceClient } from '@servicestack/client'
90207
import { ClientContext, AutoQueryGrid } from '@servicestack/react'
91208
92-
const client = new JsonServiceClient('https://blazor-gallery.jamstacks.net')
209+
const client = new JsonServiceClient('https://blazor-gallery.web-templates.io')
93210
94211
function App() {
95212
return (

0 commit comments

Comments
 (0)