@alexgorbatchev/shadcn 0.0.37 → 0.0.41
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 +34 -0
- package/THIRD_PARTY_NOTICES.md +4 -0
- package/dist/{chunk-6grcm62s.js → chunk-1hj251b8.js} +1 -1
- package/dist/{chunk-r9qrb6b6.js → chunk-5bw5h08v.js} +1 -1
- package/dist/{chunk-kmvvw1vr.js → chunk-sb00e3gj.js} +1 -1
- package/dist/{chunk-f71469fs.js → chunk-v0va5w5c.js} +1 -1
- package/dist/components/data-grid/index.js +2 -2
- package/dist/components/gantt/index.js +2 -2
- package/dist/components/json-render/index.js +3 -3
- package/dist/components/virtual-data-grid/index.js +2 -2
- package/dist/index.js +3 -3
- package/dist/prototype.js +3665 -0
- package/dist/theme.css +20 -0
- package/licenses/commander-MIT.txt +22 -0
- package/llms/components/forms/NativeSelect.md +8 -0
- package/llms/setup.md +34 -0
- package/package.json +9 -3
- package/templates/prototype/AGENTS.md +23 -0
- package/templates/prototype/gitignore +5 -0
- package/templates/prototype/index.html +12 -0
- package/templates/prototype/justfile +18 -0
- package/templates/prototype/src/components/ScenarioContent.tsx +41 -0
- package/templates/prototype/src/components/Workbench.tsx +132 -0
- package/templates/prototype/src/main.tsx +12 -0
- package/templates/prototype/src/prototypes/dashboard/components/Dashboard.tsx +80 -0
- package/templates/prototype/src/prototypes/dashboard/data.ts +5 -0
- package/templates/prototype/src/prototypes/dashboard/prototype.ts +9 -0
- package/templates/prototype/src/prototypes/projects/components/Projects.tsx +151 -0
- package/templates/prototype/src/prototypes/projects/data.ts +5 -0
- package/templates/prototype/src/prototypes/projects/prototype.ts +9 -0
- package/templates/prototype/src/prototypes/settings/components/Settings.tsx +72 -0
- package/templates/prototype/src/prototypes/settings/prototype.ts +9 -0
- package/templates/prototype/src/styles.css +7 -0
- package/templates/prototype/src/types.ts +9 -0
- package/templates/prototype/tsconfig.json +13 -0
- package/templates/prototype/vite.config.ts +8 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { useState, type ReactElement } from "react";
|
|
2
|
+
import {
|
|
3
|
+
AppShell,
|
|
4
|
+
Button,
|
|
5
|
+
Card,
|
|
6
|
+
CardHeader,
|
|
7
|
+
CardTitle,
|
|
8
|
+
CardDescription,
|
|
9
|
+
CardContent,
|
|
10
|
+
Dialog,
|
|
11
|
+
DialogContent,
|
|
12
|
+
DialogHeader,
|
|
13
|
+
DialogTitle,
|
|
14
|
+
DialogDescription,
|
|
15
|
+
DialogFooter,
|
|
16
|
+
Empty,
|
|
17
|
+
EmptyHeader,
|
|
18
|
+
EmptyTitle,
|
|
19
|
+
Field,
|
|
20
|
+
FieldGroup,
|
|
21
|
+
FieldLabel,
|
|
22
|
+
Input,
|
|
23
|
+
PageHeader,
|
|
24
|
+
Table,
|
|
25
|
+
TableHeader,
|
|
26
|
+
TableHead,
|
|
27
|
+
TableBody,
|
|
28
|
+
TableRow,
|
|
29
|
+
TableCell,
|
|
30
|
+
} from "@alexgorbatchev/shadcn";
|
|
31
|
+
import type { PrototypeProps } from "../../../types";
|
|
32
|
+
import { ScenarioContent } from "../../../components/ScenarioContent";
|
|
33
|
+
import { projects } from "../data";
|
|
34
|
+
|
|
35
|
+
type Project = (typeof projects)[number];
|
|
36
|
+
|
|
37
|
+
export function Projects({ scenario }: PrototypeProps): ReactElement {
|
|
38
|
+
const [records, setRecords] = useState(projects);
|
|
39
|
+
const [search, setSearch] = useState("");
|
|
40
|
+
const [editing, setEditing] = useState<Project | null>(null);
|
|
41
|
+
const [message, setMessage] = useState("");
|
|
42
|
+
const visible = records.filter((project) =>
|
|
43
|
+
`${project.name} ${project.owner}`.toLowerCase().includes(search.toLowerCase()),
|
|
44
|
+
);
|
|
45
|
+
return (
|
|
46
|
+
<AppShell brand="Northstar" header="Projects" navigation={[]}>
|
|
47
|
+
<PageHeader title="Projects" description="Find a project and update its details." />
|
|
48
|
+
<ScenarioContent scenario={scenario}>
|
|
49
|
+
<FieldGroup>
|
|
50
|
+
<Field>
|
|
51
|
+
<FieldLabel htmlFor="search">Search projects</FieldLabel>
|
|
52
|
+
<Input id="search" value={search} onChange={(event) => setSearch(event.target.value)} />
|
|
53
|
+
</Field>
|
|
54
|
+
</FieldGroup>
|
|
55
|
+
<Card>
|
|
56
|
+
<CardHeader>
|
|
57
|
+
<CardTitle>Project directory</CardTitle>
|
|
58
|
+
<CardDescription>{visible.length} projects</CardDescription>
|
|
59
|
+
</CardHeader>
|
|
60
|
+
<CardContent>
|
|
61
|
+
{visible.length ? (
|
|
62
|
+
<Table>
|
|
63
|
+
<TableHeader>
|
|
64
|
+
<TableRow>
|
|
65
|
+
<TableHead>Project</TableHead>
|
|
66
|
+
<TableHead>Owner</TableHead>
|
|
67
|
+
<TableHead>Action</TableHead>
|
|
68
|
+
</TableRow>
|
|
69
|
+
</TableHeader>
|
|
70
|
+
<TableBody>
|
|
71
|
+
{visible.map((project) => (
|
|
72
|
+
<TableRow key={project.id}>
|
|
73
|
+
<TableCell>{project.name}</TableCell>
|
|
74
|
+
<TableCell>{project.owner}</TableCell>
|
|
75
|
+
<TableCell>
|
|
76
|
+
<Button
|
|
77
|
+
variant="outline"
|
|
78
|
+
aria-label={`Edit ${project.name}`}
|
|
79
|
+
onClick={() => setEditing({ ...project })}
|
|
80
|
+
>
|
|
81
|
+
Edit
|
|
82
|
+
</Button>
|
|
83
|
+
</TableCell>
|
|
84
|
+
</TableRow>
|
|
85
|
+
))}
|
|
86
|
+
</TableBody>
|
|
87
|
+
</Table>
|
|
88
|
+
) : (
|
|
89
|
+
<Empty>
|
|
90
|
+
<EmptyHeader>
|
|
91
|
+
<EmptyTitle>No matching projects</EmptyTitle>
|
|
92
|
+
</EmptyHeader>
|
|
93
|
+
</Empty>
|
|
94
|
+
)}
|
|
95
|
+
</CardContent>
|
|
96
|
+
</Card>
|
|
97
|
+
<p role="status">{message}</p>
|
|
98
|
+
<Dialog
|
|
99
|
+
open={editing !== null}
|
|
100
|
+
onOpenChange={(open) => {
|
|
101
|
+
if (!open) setEditing(null);
|
|
102
|
+
}}
|
|
103
|
+
>
|
|
104
|
+
<DialogContent>
|
|
105
|
+
<DialogHeader>
|
|
106
|
+
<DialogTitle>Edit project</DialogTitle>
|
|
107
|
+
<DialogDescription>Changes stay in this prototype until you reset it.</DialogDescription>
|
|
108
|
+
</DialogHeader>
|
|
109
|
+
{editing && (
|
|
110
|
+
<form
|
|
111
|
+
onSubmit={(event) => {
|
|
112
|
+
event.preventDefault();
|
|
113
|
+
setRecords((current) => current.map((project) => (project.id === editing.id ? editing : project)));
|
|
114
|
+
setMessage(`Saved ${editing.name}`);
|
|
115
|
+
setEditing(null);
|
|
116
|
+
}}
|
|
117
|
+
>
|
|
118
|
+
<FieldGroup>
|
|
119
|
+
<Field>
|
|
120
|
+
<FieldLabel htmlFor="project-name">Project name</FieldLabel>
|
|
121
|
+
<Input
|
|
122
|
+
id="project-name"
|
|
123
|
+
required
|
|
124
|
+
value={editing.name}
|
|
125
|
+
onChange={(event) => setEditing({ ...editing, name: event.target.value })}
|
|
126
|
+
/>
|
|
127
|
+
</Field>
|
|
128
|
+
<Field>
|
|
129
|
+
<FieldLabel htmlFor="project-owner">Owner</FieldLabel>
|
|
130
|
+
<Input
|
|
131
|
+
id="project-owner"
|
|
132
|
+
required
|
|
133
|
+
value={editing.owner}
|
|
134
|
+
onChange={(event) => setEditing({ ...editing, owner: event.target.value })}
|
|
135
|
+
/>
|
|
136
|
+
</Field>
|
|
137
|
+
</FieldGroup>
|
|
138
|
+
<DialogFooter>
|
|
139
|
+
<Button type="button" variant="outline" onClick={() => setEditing(null)}>
|
|
140
|
+
Cancel
|
|
141
|
+
</Button>
|
|
142
|
+
<Button type="submit">Save project</Button>
|
|
143
|
+
</DialogFooter>
|
|
144
|
+
</form>
|
|
145
|
+
)}
|
|
146
|
+
</DialogContent>
|
|
147
|
+
</Dialog>
|
|
148
|
+
</ScenarioContent>
|
|
149
|
+
</AppShell>
|
|
150
|
+
);
|
|
151
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { PrototypeDefinition } from "../../types";
|
|
2
|
+
import { Projects } from "./components/Projects";
|
|
3
|
+
|
|
4
|
+
const prototype: PrototypeDefinition = {
|
|
5
|
+
title: "Projects",
|
|
6
|
+
description: "Search projects and edit their details.",
|
|
7
|
+
component: Projects,
|
|
8
|
+
};
|
|
9
|
+
export default prototype;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { useState, type ReactElement } from "react";
|
|
2
|
+
import {
|
|
3
|
+
AppShell,
|
|
4
|
+
Button,
|
|
5
|
+
Card,
|
|
6
|
+
CardHeader,
|
|
7
|
+
CardTitle,
|
|
8
|
+
CardDescription,
|
|
9
|
+
CardContent,
|
|
10
|
+
CardFooter,
|
|
11
|
+
Field,
|
|
12
|
+
FieldGroup,
|
|
13
|
+
FieldLabel,
|
|
14
|
+
Input,
|
|
15
|
+
PageHeader,
|
|
16
|
+
Switch,
|
|
17
|
+
} from "@alexgorbatchev/shadcn";
|
|
18
|
+
import type { PrototypeProps } from "../../../types";
|
|
19
|
+
import { ScenarioContent } from "../../../components/ScenarioContent";
|
|
20
|
+
|
|
21
|
+
export function Settings({ scenario }: PrototypeProps): ReactElement {
|
|
22
|
+
const [name, setName] = useState("Northstar");
|
|
23
|
+
const [email, setEmail] = useState("team@example.com");
|
|
24
|
+
const [notifications, setNotifications] = useState(true);
|
|
25
|
+
const [message, setMessage] = useState("");
|
|
26
|
+
return (
|
|
27
|
+
<AppShell brand="Northstar" header="Settings" navigation={[]}>
|
|
28
|
+
<PageHeader title="Workspace settings" description="Manage the profile and preferences for your team." />
|
|
29
|
+
<ScenarioContent scenario={scenario}>
|
|
30
|
+
<form
|
|
31
|
+
onSubmit={(event) => {
|
|
32
|
+
event.preventDefault();
|
|
33
|
+
setMessage(`Saved ${name}. Email updates ${notifications ? "enabled" : "disabled"} for ${email}.`);
|
|
34
|
+
}}
|
|
35
|
+
>
|
|
36
|
+
<Card>
|
|
37
|
+
<CardHeader>
|
|
38
|
+
<CardTitle>Workspace profile</CardTitle>
|
|
39
|
+
<CardDescription>These settings use local sample data.</CardDescription>
|
|
40
|
+
</CardHeader>
|
|
41
|
+
<CardContent>
|
|
42
|
+
<FieldGroup>
|
|
43
|
+
<Field>
|
|
44
|
+
<FieldLabel htmlFor="workspace-name">Workspace name</FieldLabel>
|
|
45
|
+
<Input id="workspace-name" required value={name} onChange={(event) => setName(event.target.value)} />
|
|
46
|
+
</Field>
|
|
47
|
+
<Field>
|
|
48
|
+
<FieldLabel htmlFor="email">Contact email</FieldLabel>
|
|
49
|
+
<Input
|
|
50
|
+
id="email"
|
|
51
|
+
type="email"
|
|
52
|
+
required
|
|
53
|
+
value={email}
|
|
54
|
+
onChange={(event) => setEmail(event.target.value)}
|
|
55
|
+
/>
|
|
56
|
+
</Field>
|
|
57
|
+
<Field orientation="horizontal">
|
|
58
|
+
<Switch id="notifications" checked={notifications} onCheckedChange={setNotifications} />
|
|
59
|
+
<FieldLabel htmlFor="notifications">Email updates</FieldLabel>
|
|
60
|
+
</Field>
|
|
61
|
+
</FieldGroup>
|
|
62
|
+
</CardContent>
|
|
63
|
+
<CardFooter>
|
|
64
|
+
<Button type="submit">Save settings</Button>
|
|
65
|
+
</CardFooter>
|
|
66
|
+
</Card>
|
|
67
|
+
</form>
|
|
68
|
+
<p role="status">{message}</p>
|
|
69
|
+
</ScenarioContent>
|
|
70
|
+
</AppShell>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { PrototypeDefinition } from "../../types";
|
|
2
|
+
import { Settings } from "./components/Settings";
|
|
3
|
+
|
|
4
|
+
const prototype: PrototypeDefinition = {
|
|
5
|
+
title: "Settings",
|
|
6
|
+
description: "Edit a workspace profile and notification preferences.",
|
|
7
|
+
component: Settings,
|
|
8
|
+
};
|
|
9
|
+
export default prototype;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ComponentType } from "react";
|
|
2
|
+
|
|
3
|
+
export type Scenario = "populated" | "empty" | "loading" | "error";
|
|
4
|
+
export type PrototypeProps = { scenario: Scenario };
|
|
5
|
+
export type PrototypeDefinition = {
|
|
6
|
+
title: string;
|
|
7
|
+
description: string;
|
|
8
|
+
component: ComponentType<PrototypeProps>;
|
|
9
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ESNext",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "Bundler",
|
|
6
|
+
"jsx": "react-jsx",
|
|
7
|
+
"strict": true,
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
"noEmit": true,
|
|
10
|
+
"types": ["vite/client", "bun"]
|
|
11
|
+
},
|
|
12
|
+
"include": ["src", "vite.config.ts"]
|
|
13
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { defineConfig } from "vite";
|
|
2
|
+
import react from "@vitejs/plugin-react";
|
|
3
|
+
import tailwindcss from "@tailwindcss/vite";
|
|
4
|
+
|
|
5
|
+
export default defineConfig({
|
|
6
|
+
plugins: [react(), tailwindcss()],
|
|
7
|
+
server: { host: "127.0.0.1", strictPort: true, headers: { "Cache-Control": "no-store" } },
|
|
8
|
+
});
|