Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ComponentCard } from "@/components/component-card";
import { ComponentCard } from "@/components/example/component-card";
import { HelloWorld } from "@/registry/new-york/blocks/hello-world/hello-world";
import { ExampleForm } from "@/registry/new-york/blocks/example-form/example-form";
import PokemonPage from "@/registry/new-york/blocks/complex-component/page";
Expand Down
File renamed without changes.
34 changes: 34 additions & 0 deletions components/example/form.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { GitRepository } from "mobx-github";

import { i18n, topicStore } from "@/models/example";
import { Field } from "@/registry/new-york/blocks/rest-form/rest-form";
import { SearchableInput } from "@/registry/new-york/blocks/searchable-input/searchable-input";

export const fields: Field<GitRepository>[] = [
{
key: "full_name",
renderLabel: "Repository Name",
required: true,
minLength: 3,
invalidMessage: "Input 3 characters at least",
},
{ key: "homepage", type: "url", renderLabel: "Home Page" },
{ key: "language", renderLabel: "Programming Language" },
{
key: "topics",
renderLabel: "Topic",
renderInput: ({ topics }) => (
<SearchableInput
translator={i18n}
store={topicStore}
labelKey="name"
valueKey="name"
placeholder="search GitHub topics"
multiple
defaultValue={topics?.map((value) => ({ value, label: value }))}
/>
),
},
{ key: "stargazers_count", type: "number", renderLabel: "Star Count" },
{ key: "description", renderLabel: "Description", rows: 3 },
];
49 changes: 49 additions & 0 deletions models/example.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { components, operations } from "@octokit/openapi-types";
import { githubClient, RepositoryModel } from "mobx-github";
import { TranslationModel } from "mobx-i18n";
import { ListModel, Filter } from "mobx-restful";
import { buildURLData } from "web-utility";

export const i18n = new TranslationModel({
en_US: {
load_more: "Load more",
no_more: "No more",
submit: "Submit",
cancel: "Cancel",
},
});

type Topic = components["schemas"]["topic-search-result-item"];

type TopicSearchResponse =
operations["search/topics"]["responses"]["200"]["content"]["application/json"];

const GITHUB_TOKEN = process.env.GITHUB_TOKEN;

githubClient.use(({ request }, next) => {
if (GITHUB_TOKEN)
request.headers = {
...request.headers,
Authorization: `Bearer ${GITHUB_TOKEN}`,
};
return next();
});

class GitHubTopicModel extends ListModel<Topic> {
baseURI = "search/topics";
client = githubClient;

async loadPage(pageIndex: number, pageSize: number, { name }: Filter<Topic>) {
const { body } = await this.client.get<TopicSearchResponse>(
`${this.baseURI}?${buildURLData({
q: name,
page: pageIndex,
per_page: pageSize,
})}`
);
return { pageData: body!.items, totalCount: body!.total_count };
}
}

export const repositoryStore = new RepositoryModel("idea2app"),
topicStore = new GitHubTopicModel();
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"@babel/plugin-transform-typescript": "^7.28.5",
"@babel/preset-react": "^7.28.5",
"@eslint/eslintrc": "^3.3.3",
"@octokit/openapi-types": "^27.0.0",
"@tailwindcss/postcss": "^4.1.18",
"@types/lodash.debounce": "^4.0.9",
"@types/node": "^22.19.3",
Expand Down
8 changes: 8 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

89 changes: 89 additions & 0 deletions registry.json
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,95 @@
"type": "registry:component"
}
]
},
{
"name": "file-uploader",
"type": "registry:component",
"title": "File Uploader",
"description": "A file uploader component with drag-and-drop support for managing multiple files using MobX.",
"registryDependencies": ["file-picker"],
"dependencies": [
"mobx",
"mobx-react",
"mobx-react-helper",
"mobx-restful"
],
"files": [
{
"path": "registry/new-york/blocks/file-uploader/file-uploader.tsx",
"type": "registry:component"
}
]
},
{
"name": "rest-form",
"type": "registry:component",
"title": "REST Form",
"description": "A comprehensive form component for CRUD operations with MobX RESTful integration, supporting various field types and validation.",
"registryDependencies": [
"button",
"label",
"badge-input",
"file-preview",
"file-uploader",
"form-field"
],
"dependencies": [
"mobx",
"mobx-i18n",
"mobx-react",
"mobx-react-helper",
"mobx-restful",
"web-utility"
],
"files": [
{
"path": "registry/new-york/blocks/rest-form/rest-form.tsx",
"type": "registry:component"
}
]
},
{
"name": "rest-form-modal",
"type": "registry:component",
"title": "REST Form Modal",
"description": "A modal wrapper for REST Form component, displaying forms in a dialog for editing data.",
"registryDependencies": ["dialog", "rest-form"],
"dependencies": ["mobx-react", "mobx-restful", "web-utility"],
"files": [
{
"path": "registry/new-york/blocks/rest-form-modal/rest-form-modal.tsx",
"type": "registry:component"
}
]
},
{
"name": "searchable-input",
"type": "registry:component",
"title": "Searchable Input",
"description": "A searchable input component with autocomplete, supporting multiple selections and inline creation of new items.",
"registryDependencies": [
"button",
"input",
"badge-bar",
"badge-input",
"rest-form-modal",
"scroll-list"
],
"dependencies": [
"lodash.debounce",
"mobx",
"mobx-react",
"mobx-react-helper",
"mobx-restful",
"web-utility"
],
"files": [
{
"path": "registry/new-york/blocks/searchable-input/searchable-input.tsx",
"type": "registry:component"
}
]
}
]
}
45 changes: 45 additions & 0 deletions registry/new-york/blocks/file-uploader/example.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"use client";

import { FileModel, FileUploader } from "./file-uploader";

class MyFileModel extends FileModel {}

const store = new MyFileModel();

export const FileUploaderExample = () => (
<div className="w-full space-y-8">
<div>
<h3 className="text-lg font-semibold mb-4">Single File Upload</h3>
<FileUploader
store={store}
name="single-file"
accept="image/*"
defaultValue={[]}
/>
<p className="text-sm text-muted-foreground mt-2">
Upload a single image file
</p>
</div>

<div>
<h3 className="text-lg font-semibold mb-4">Multiple Files Upload</h3>
<FileUploader
store={store}
name="multiple-files"
accept="image/*"
multiple
defaultValue={[]}
/>
<p className="text-sm text-muted-foreground mt-2">
Upload multiple image files (drag to reorder)
</p>
</div>

<div>
<h3 className="text-lg font-semibold mb-4">Uploaded Files</h3>
<pre className="p-4 bg-muted rounded-md text-xs overflow-auto">
{JSON.stringify(store.files, null, 2)}
</pre>
</div>
</div>
);
Loading