Skip to content

Commit 5a38481

Browse files
committed
[optimize] simplify Copilot's source codes
[remove] complex Searchable Input component
1 parent 74e9332 commit 5a38481

File tree

13 files changed

+141
-527
lines changed

13 files changed

+141
-527
lines changed

app/layout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export default function RootLayout({
1414
children: React.ReactNode;
1515
}>) {
1616
return (
17-
<html lang="en">
17+
<html lang="en-US">
1818
<head>
1919
<link rel="preconnect" href="https://fonts.googleapis.com" />
2020
<link

app/page.tsx

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import { ReactNode } from "react";
2-
import { OpenInV0Button } from "@/components/open-in-v0-button";
1+
import { ComponentCard } from "@/components/component-card";
32
import { HelloWorld } from "@/registry/new-york/blocks/hello-world/hello-world";
43
import { ExampleForm } from "@/registry/new-york/blocks/example-form/example-form";
54
import PokemonPage from "@/registry/new-york/blocks/complex-component/page";
@@ -15,31 +14,6 @@ import { BadgeInputExample } from "@/registry/new-york/blocks/badge-input/exampl
1514
import { RangeInputExample } from "@/registry/new-york/blocks/range-input/example";
1615
import { FilePickerExample } from "@/registry/new-york/blocks/file-picker/example";
1716
import { FormFieldExample } from "@/registry/new-york/blocks/form-field/example";
18-
import { SearchableInputExample } from "@/registry/new-york/blocks/searchable-input/example";
19-
// This page displays items from the custom registry.
20-
// You are free to implement this with your own design as needed.
21-
22-
const ComponentCard = ({
23-
name,
24-
description,
25-
children,
26-
minHeight = "min-h-[400px]",
27-
}: {
28-
name: string;
29-
description: string;
30-
children: ReactNode;
31-
minHeight?: string;
32-
}) => (
33-
<div className="flex flex-col gap-4 border rounded-lg p-4 min-h-[450px] relative">
34-
<div className="flex items-center justify-between">
35-
<h2 className="text-sm text-muted-foreground sm:pl-3">{description}</h2>
36-
<OpenInV0Button name={name} className="w-fit" />
37-
</div>
38-
<div className={`flex items-center justify-center ${minHeight} relative`}>
39-
{children}
40-
</div>
41-
</div>
42-
);
4317

4418
export default function Home() {
4519
return (
@@ -156,13 +130,6 @@ export default function Home() {
156130
>
157131
<FormFieldExample />
158132
</ComponentCard>
159-
160-
<ComponentCard
161-
name="searchable-input"
162-
description="A searchable select input with badge display, supporting single or multiple selection."
163-
>
164-
<SearchableInputExample />
165-
</ComponentCard>
166133
</main>
167134
</div>
168135
);

components/component-card.tsx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { FC, PropsWithChildren } from "react";
2+
3+
import { OpenInV0Button } from "./open-in-v0-button";
4+
5+
export type ComponentCardProps = PropsWithChildren<{
6+
name: string;
7+
description: string;
8+
minHeight?: string;
9+
}>;
10+
11+
export const ComponentCard: FC<ComponentCardProps> = ({
12+
name,
13+
description,
14+
children,
15+
minHeight = "min-h-[400px]",
16+
}) => (
17+
<div className="flex flex-col gap-4 border rounded-lg p-4 min-h-[450px] relative">
18+
<div className="flex items-center justify-between">
19+
<h2 className="text-sm text-muted-foreground sm:pl-3">{description}</h2>
20+
<OpenInV0Button name={name} className="w-fit" />
21+
</div>
22+
<div className={`flex items-center justify-center ${minHeight} relative`}>
23+
{children}
24+
</div>
25+
</div>
26+
);

components/index.ini

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
badge
22
button
33
dialog
4-
input
4+
input
5+
label

registry.json

Lines changed: 3 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -3,33 +3,6 @@
33
"name": "acme",
44
"homepage": "https://acme.com",
55
"items": [
6-
{
7-
"name": "hello-world",
8-
"type": "registry:component",
9-
"title": "Hello World",
10-
"description": "A simple hello world component",
11-
"registryDependencies": ["button"],
12-
"files": [
13-
{
14-
"path": "registry/new-york/blocks/hello-world/hello-world.tsx",
15-
"type": "registry:component"
16-
}
17-
]
18-
},
19-
{
20-
"name": "example-form",
21-
"type": "registry:component",
22-
"title": "Example Form",
23-
"description": "A contact form with Zod validation.",
24-
"dependencies": ["zod"],
25-
"registryDependencies": ["button", "input", "label", "textarea", "card"],
26-
"files": [
27-
{
28-
"path": "registry/new-york/blocks/example-form/example-form.tsx",
29-
"type": "registry:component"
30-
}
31-
]
32-
},
336
{
347
"name": "complex-component",
358
"type": "registry:component",
@@ -195,12 +168,7 @@
195168
"title": "Badge Input",
196169
"description": "An input component that displays values as removable badges, supporting multiple entries.",
197170
"registryDependencies": ["badge"],
198-
"dependencies": [
199-
"mobx",
200-
"mobx-react",
201-
"mobx-react-helper",
202-
"web-utility"
203-
],
171+
"dependencies": ["mobx-react", "mobx-react-helper", "web-utility"],
204172
"files": [
205173
{
206174
"path": "registry/new-york/blocks/badge-input/badge-input.tsx",
@@ -213,12 +181,7 @@
213181
"type": "registry:component",
214182
"title": "Range Input",
215183
"description": "A range slider input with optional custom icon display for each step.",
216-
"dependencies": [
217-
"lucide-react",
218-
"mobx",
219-
"mobx-react",
220-
"mobx-react-helper"
221-
],
184+
"dependencies": ["mobx-react", "mobx-react-helper"],
222185
"files": [
223186
{
224187
"path": "registry/new-york/blocks/range-input/range-input.tsx",
@@ -252,33 +215,13 @@
252215
"title": "Form Field",
253216
"description": "A unified form field component supporting input, textarea, and select elements with labels.",
254217
"registryDependencies": ["input", "label"],
218+
"dependencies": ["web-utility"],
255219
"files": [
256220
{
257221
"path": "registry/new-york/blocks/form-field/form-field.tsx",
258222
"type": "registry:component"
259223
}
260224
]
261-
},
262-
{
263-
"name": "searchable-input",
264-
"type": "registry:component",
265-
"title": "Searchable Input",
266-
"description": "A searchable select input with badge display, supporting single or multiple selection.",
267-
"registryDependencies": ["button", "input"],
268-
"dependencies": [
269-
"lodash.debounce",
270-
"mobx",
271-
"mobx-react",
272-
"mobx-react-helper",
273-
"mobx-restful",
274-
"web-utility"
275-
],
276-
"files": [
277-
{
278-
"path": "registry/new-york/blocks/searchable-input/searchable-input.tsx",
279-
"type": "registry:component"
280-
}
281-
]
282225
}
283226
]
284227
}

registry/new-york/blocks/array-field/array-field.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export class ArrayField<
4747
item,
4848
...innerValue!.slice(index + 1),
4949
].map((item) => toJS(item));
50+
5051
this.props.onChange?.(list);
5152
};
5253

Lines changed: 15 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
"use client";
22

3-
import { useState } from "react";
43
import { DataObject } from "mobx-restful";
54

65
import { Input } from "@/components/ui/input";
@@ -11,35 +10,19 @@ interface TodoItem extends DataObject {
1110
completed?: boolean;
1211
}
1312

14-
export const ArrayFieldExample = () => {
15-
const [items, setItems] = useState<TodoItem[]>([
16-
{ title: "First task" },
17-
{ title: "Second task" },
18-
]);
19-
20-
return (
21-
<div className="w-full space-y-8">
22-
<div>
23-
<h3 className="text-lg font-semibold mb-4">Array Field with Inputs</h3>
24-
<ArrayField<TodoItem>
25-
value={items}
26-
onChange={setItems}
27-
renderItem={(item, index) => (
28-
<Input
29-
name="title"
30-
defaultValue={item.title}
31-
placeholder={`Task ${index + 1}`}
32-
/>
33-
)}
34-
/>
35-
</div>
36-
37-
<div>
38-
<h3 className="text-lg font-semibold mb-4">Current Values</h3>
39-
<pre className="p-4 bg-muted rounded-md">
40-
{JSON.stringify(items, null, 2)}
41-
</pre>
42-
</div>
13+
export const ArrayFieldExample = () => (
14+
<div className="w-full space-y-8">
15+
<div>
16+
<h3 className="text-lg font-semibold mb-4">Array Field with Inputs</h3>
17+
<ArrayField<TodoItem>
18+
renderItem={({ title }, index) => (
19+
<Input
20+
name="title"
21+
defaultValue={title}
22+
placeholder={`Task ${index + 1}`}
23+
/>
24+
)}
25+
/>
4326
</div>
44-
);
45-
};
27+
</div>
28+
);

registry/new-york/blocks/badge-input/badge-input.tsx

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,34 @@ import { KeyboardEvent } from "react";
66
import { isEmpty } from "web-utility";
77

88
import { cn } from "@/lib/utils";
9-
import { BadgeBar } from "@/registry/new-york/blocks/badge-bar/badge-bar";
9+
import { BadgeBar } from "../badge-bar/badge-bar";
1010

11-
export const TextInputTypes = ["text", "number", "tel", "email", "url"] as const;
11+
export const TextInputTypes = [
12+
"text",
13+
"number",
14+
"tel",
15+
"email",
16+
"url",
17+
] as const;
18+
19+
export type TextInputType = (typeof TextInputTypes)[number];
1220

1321
export interface BadgeInputProps extends FormComponentProps<string[]> {
14-
type?: (typeof TextInputTypes)[number];
22+
type?: TextInputType;
1523
}
1624

1725
@observer
1826
export class BadgeInput extends FormComponent<BadgeInputProps> {
1927
static readonly displayName = "BadgeInput";
2028

21-
static match(type: string): type is (typeof TextInputTypes)[number] {
22-
return TextInputTypes.includes(type as (typeof TextInputTypes)[number]);
29+
static match(type: string): type is TextInputType {
30+
return TextInputTypes.includes(type as TextInputType);
2331
}
2432

2533
handleInput = (event: KeyboardEvent<HTMLInputElement>) => {
2634
const input = event.currentTarget;
27-
const { value } = input;
28-
const innerValue = this.innerValue || [];
35+
const { value } = input,
36+
innerValue = this.innerValue || [];
2937

3038
switch (event.key) {
3139
case "Enter": {
@@ -52,9 +60,8 @@ export class BadgeInput extends FormComponent<BadgeInputProps> {
5260
}
5361

5462
render() {
55-
const { value } = this;
56-
const { className = "", style, type, name, required, placeholder } =
57-
this.props;
63+
const { value } = this,
64+
{ className, style, type, name, required, placeholder } = this.props;
5865

5966
return (
6067
<div

registry/new-york/blocks/file-picker/file-picker.tsx

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { blobOf } from "web-utility";
88

99
import { cn } from "@/lib/utils";
1010
import { Button } from "@/components/ui/button";
11-
import { FilePreview } from "@/registry/new-york/blocks/file-preview/file-preview";
11+
import { FilePreview } from "../file-preview/file-preview";
1212

1313
export type FilePickerProps = FormComponentProps<string | File>;
1414

@@ -23,8 +23,8 @@ export class FilePicker extends FormComponent<FilePickerProps> {
2323

2424
@computed
2525
get fileType() {
26-
const { accept } = this.observedProps;
27-
const { file } = this;
26+
const { accept } = this.observedProps,
27+
{ file } = this;
2828

2929
return file?.type || file?.name.match(/\.\w+$/)?.[0] || accept;
3030
}
@@ -33,15 +33,15 @@ export class FilePicker extends FormComponent<FilePickerProps> {
3333
get filePath() {
3434
const { value } = this;
3535

36-
return typeof value === "string" ? value : value ? blobCache.get(value) : undefined;
36+
return typeof value === "string" ? value : value && blobCache.get(value);
3737
}
3838

3939
@reaction(({ value }) => value)
4040
protected async restoreFile(data: FilePickerProps["value"]) {
4141
if (typeof data === "string")
4242
try {
43-
const blob = await blobOf(data);
44-
const name = data.split("/").at(-1);
43+
const blob = await blobOf(data),
44+
name = data.split("/").at(-1);
4545
const file = new File([blob], name!, { type: blob.type });
4646

4747
blobCache.set(file, data);
@@ -105,19 +105,20 @@ export class FilePicker extends FormComponent<FilePickerProps> {
105105
}
106106

107107
render() {
108-
const { filePath, fileType } = this;
109-
const { className = "", style } = this.props;
108+
const { filePath, fileType } = this,
109+
{ className = "", style } = this.props;
110110

111111
return (
112112
<div
113-
className={cn(
114-
"inline-block border rounded-md relative",
115-
className
116-
)}
113+
className={cn("inline-block border rounded-md relative", className)}
117114
style={{ width: "10rem", height: "10rem", ...style }}
118115
>
119116
{filePath ? (
120-
<FilePreview className="w-full h-full" type={fileType} path={filePath} />
117+
<FilePreview
118+
className="w-full h-full"
119+
type={fileType}
120+
path={filePath}
121+
/>
121122
) : (
122123
<div className="w-full h-full flex justify-center items-center text-6xl text-muted-foreground">
123124
+

0 commit comments

Comments
 (0)