diff --git a/docs/docs-ui/package.json b/docs/docs-ui/package.json
index cc6f669..561ec6e 100644
--- a/docs/docs-ui/package.json
+++ b/docs/docs-ui/package.json
@@ -1,7 +1,7 @@
{
"name": "docs-ui",
"description": "Your project description",
- "version": "0.1.4",
+ "version": "0.1.5",
"main": "dist/index.html",
"type": "module",
"scripts": {
@@ -41,6 +41,6 @@
"vite": "^5.1.6"
},
"peerDependencies": {
- "@chaoying/flect": "0.2.3"
+ "@chaoying/flect": "0.2.4"
}
}
diff --git a/docs/docs-ui/pnpm-lock.yaml b/docs/docs-ui/pnpm-lock.yaml
index dfcb6d8..b24e438 100644
--- a/docs/docs-ui/pnpm-lock.yaml
+++ b/docs/docs-ui/pnpm-lock.yaml
@@ -6,8 +6,8 @@ settings:
dependencies:
'@chaoying/flect':
- specifier: 0.2.3
- version: 0.2.3(@types/react-dom@18.2.22)(@types/react@18.2.66)(tailwindcss@3.4.1)
+ specifier: 0.2.4
+ version: 0.2.4(@types/react-dom@18.2.22)(@types/react@18.2.66)(tailwindcss@3.4.1)
class-variance-authority:
specifier: ^0.7.0
version: 0.7.0
@@ -331,8 +331,8 @@ packages:
to-fast-properties: 2.0.0
dev: true
- /@chaoying/flect@0.2.3(@types/react-dom@18.2.22)(@types/react@18.2.66)(tailwindcss@3.4.1):
- resolution: {integrity: sha512-u85s7jS36c1a5+uAlIGyjQuk8wgHqNglR1KkmSzyEEkVtwTrzoaHOEQzWeyTFCuq8Z1/Cc1NzOJEzUy8IeyOMA==}
+ /@chaoying/flect@0.2.4(@types/react-dom@18.2.22)(@types/react@18.2.66)(tailwindcss@3.4.1):
+ resolution: {integrity: sha512-NZt+/ZLkfJr9o47ULJ9eUZFA4+7bDkdv9axDCXR9UkFxl2WicPZ+G05MhEZzGtOurOAPcITjvYdc3onJLlBJNA==}
dependencies:
'@fengkx/react-syntax-highlighter': 15.6.1(react@18.2.0)
'@hookform/resolvers': 3.3.4(react-hook-form@7.51.1)
diff --git a/docs/docs-ui/src/components/code-block-lazy.tsx b/docs/docs-ui/src/components/code-block-lazy.tsx
deleted file mode 100644
index 0530b14..0000000
--- a/docs/docs-ui/src/components/code-block-lazy.tsx
+++ /dev/null
@@ -1,41 +0,0 @@
-import { PrismLight as SyntaxHighlighter } from "react-syntax-highlighter";
-import python from "react-syntax-highlighter/dist/esm/languages/prism/python";
-import tsx from "react-syntax-highlighter/dist/esm/languages/prism/tsx";
-import dracula from "react-syntax-highlighter/dist/esm/styles/prism/dracula";
-import { CopyButton } from "@chaoying/flect/components";
-
-import { cn } from "@/lib/utils";
-
-SyntaxHighlighter.registerLanguage("python", python);
-SyntaxHighlighter.registerLanguage("tsx", tsx);
-
-export type CodeBlockLazyProps = {
- package: "docs-ui";
- type: "code-block";
- subType: "code-block";
- className?: string;
- text: string;
- language?: string;
-};
-
-export default function CodeBlockLazy(props: CodeBlockLazyProps) {
- return (
-
-
-
- {props.text}
-
-
- );
-}
diff --git a/docs/docs-ui/src/components/code-block.tsx b/docs/docs-ui/src/components/code-block.tsx
index 5eefb4e..af5d9e6 100644
--- a/docs/docs-ui/src/components/code-block.tsx
+++ b/docs/docs-ui/src/components/code-block.tsx
@@ -1,6 +1,41 @@
-import { lazy } from "react";
-import { CodeBlockLazyProps } from "@/components/code-block-lazy";
+import { PrismLight as SyntaxHighlighter } from "react-syntax-highlighter";
+import python from "react-syntax-highlighter/dist/esm/languages/prism/python";
+import tsx from "react-syntax-highlighter/dist/esm/languages/prism/tsx";
+import dracula from "react-syntax-highlighter/dist/esm/styles/prism/dracula";
+import { CopyButton } from "@chaoying/flect/components";
-export type { CodeBlockLazyProps as CodeBlockProps };
+import { cn } from "@/lib/utils";
-export const CodeBlock = lazy(() => import("./code-block-lazy.tsx"));
+SyntaxHighlighter.registerLanguage("python", python);
+SyntaxHighlighter.registerLanguage("tsx", tsx);
+
+export type CodeBlockProps = {
+ package: "docs-ui";
+ type: "code-block";
+ subType: "code-block";
+ className?: string;
+ text: string;
+ language?: string;
+};
+
+export function CodeBlock(props: CodeBlockProps) {
+ return (
+
+
+
+ {props.text}
+
+
+ );
+}
diff --git a/docs/docs-ui/src/components/markdown-lazy.tsx b/docs/docs-ui/src/components/markdown-lazy.tsx
deleted file mode 100644
index aaab4fa..0000000
--- a/docs/docs-ui/src/components/markdown-lazy.tsx
+++ /dev/null
@@ -1,46 +0,0 @@
-import { cn } from "@/lib/utils";
-import ReactMarkdown, { Components } from "react-markdown";
-import remarkGfm from "remark-gfm";
-import { CodeBlock } from "@/components/code-block";
-
-export interface MarkdownLazyProps {
- package: "docs-ui";
- type: "markdown";
- subType: "markdown";
- className?: string;
- text: string;
-}
-
-export default function MarkdownLazy(props: MarkdownLazyProps) {
- const { text, className } = props;
- const components: Components = {
- code({ children, className }) {
- const language = /language-(\w+)/.exec(className || "");
- if (!language) {
- return {children}
;
- }
- return (
-
- );
- },
- };
-
- return (
-
- {text}
-
- );
-}
diff --git a/docs/docs-ui/src/components/markdown.tsx b/docs/docs-ui/src/components/markdown.tsx
index a3c1ff1..14934da 100644
--- a/docs/docs-ui/src/components/markdown.tsx
+++ b/docs/docs-ui/src/components/markdown.tsx
@@ -1,6 +1,46 @@
-import { lazy } from "react";
-import { MarkdownLazyProps } from "@/components/markdown-lazy";
+import { cn } from "@/lib/utils";
+import ReactMarkdown, { Components } from "react-markdown";
+import remarkGfm from "remark-gfm";
+import { CodeBlock } from "@/components/code-block";
-export type { MarkdownLazyProps as MarkdownProps };
+export interface MarkdownProps {
+ package: "docs-ui";
+ type: "markdown";
+ subType: "markdown";
+ className?: string;
+ text: string;
+}
-export const Markdown = lazy(() => import("./markdown-lazy.tsx"));
+export function Markdown(props: MarkdownProps) {
+ const { text, className } = props;
+ const components: Components = {
+ code({ children, className }) {
+ const language = /language-(\w+)/.exec(className || "");
+ if (!language) {
+ return {children}
;
+ }
+ return (
+
+ );
+ },
+ };
+
+ return (
+
+ {text}
+
+ );
+}
diff --git a/docs/docs-ui/vite.config.ts b/docs/docs-ui/vite.config.ts
index b189a52..f77ec4b 100644
--- a/docs/docs-ui/vite.config.ts
+++ b/docs/docs-ui/vite.config.ts
@@ -1,6 +1,7 @@
import path from "path";
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
+import { splitVendorChunkPlugin } from "vite";
const serverConfig = {
host: true,
@@ -10,11 +11,8 @@ const serverConfig = {
},
};
-const version = process.env.npm_package_version;
-
export default defineConfig({
- plugins: [react()],
- base: `https://unpkg.com/docs-ui@${version}/dist/`,
+ plugins: [react(), splitVendorChunkPlugin()],
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
diff --git a/docs/src/documentation/app/group__docs/actions/dynamic__action_type/page.py b/docs/src/documentation/app/group__docs/actions/dynamic__action_type/page.py
index 2f99d60..8039732 100644
--- a/docs/src/documentation/app/group__docs/actions/dynamic__action_type/page.py
+++ b/docs/src/documentation/app/group__docs/actions/dynamic__action_type/page.py
@@ -81,12 +81,12 @@
async def sitemap(dynamic_url: str) -> list[Sitemap]:
return [
Sitemap(
- url=dynamic_url.format(type=type),
+ url=dynamic_url.format(action_type=action_type),
last_modified=None,
change_frequency=None,
priority=None,
)
- for type in ACTION_DOCS_MAP
+ for action_type in ACTION_DOCS_MAP
]
diff --git a/docs/src/documentation/main.py b/docs/src/documentation/main.py
index 3ebf182..25f0e56 100644
--- a/docs/src/documentation/main.py
+++ b/docs/src/documentation/main.py
@@ -7,7 +7,5 @@
document_app,
docs_url="/documentation",
debug=settings.debug,
- prebuilt_uri="https://unpkg.com/@chaoying/flect-prebuilt@0.2.4-beta.2/dist/assets",
- # prebuilt_uri="/Users/chaoying/dev/os/flect/docs/docs-ui/dist/assets",
- # prebuilt_uri="/Users/chaoying/dev/os/flect/src/npm-flect-prebuilt/dist/assets"
+ prebuilt_uri="https://unpkg.com/docs-ui@0.1.5/dist/assets",
)
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 4db83de..358f6aa 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -51,88 +51,6 @@ importers:
specifier: ^5.3.3
version: 5.3.3
- docs/docs-ui:
- dependencies:
- class-variance-authority:
- specifier: ^0.7.0
- version: 0.7.0
- clsx:
- specifier: ^2.1.0
- version: 2.1.0
- react:
- specifier: ^18.2.0
- version: 18.2.0
- react-dom:
- specifier: ^18.2.0
- version: 18.2.0(react@18.2.0)
- react-markdown:
- specifier: ^9.0.1
- version: 9.0.1(@types/react@18.2.65)(react@18.2.0)
- react-syntax-highlighter:
- specifier: npm:@fengkx/react-syntax-highlighter@15.6.1
- version: /@fengkx/react-syntax-highlighter@15.6.1(react@18.2.0)
- remark-gfm:
- specifier: ^4.0.0
- version: 4.0.0
- tailwind-merge:
- specifier: ^2.2.1
- version: 2.2.1
- tailwindcss-animate:
- specifier: ^1.0.7
- version: 1.0.7(tailwindcss@3.4.1)
- devDependencies:
- '@types/react':
- specifier: ^18.2.64
- version: 18.2.65
- '@types/react-dom':
- specifier: ^18.2.21
- version: 18.2.22
- '@types/react-syntax-highlighter':
- specifier: ^15.5.11
- version: 15.5.11
- '@typescript-eslint/eslint-plugin':
- specifier: ^7.1.1
- version: 7.2.0(@typescript-eslint/parser@7.2.0)(eslint@8.57.0)(typescript@5.3.3)
- '@typescript-eslint/parser':
- specifier: ^7.1.1
- version: 7.2.0(eslint@8.57.0)(typescript@5.3.3)
- '@vitejs/plugin-react':
- specifier: ^4.2.1
- version: 4.2.1(vite@5.1.6)
- autoprefixer:
- specifier: ^10.4.18
- version: 10.4.18(postcss@8.4.35)
- eslint:
- specifier: ^8.57.0
- version: 8.57.0
- eslint-plugin-react-hooks:
- specifier: ^4.6.0
- version: 4.6.0(eslint@8.57.0)
- eslint-plugin-react-refresh:
- specifier: ^0.4.5
- version: 0.4.5(eslint@8.57.0)
- postcss:
- specifier: ^8.4.35
- version: 8.4.35
- prettier:
- specifier: ^3.2.5
- version: 3.2.5
- prettier-plugin-tailwindcss:
- specifier: ^0.5.12
- version: 0.5.12(prettier@3.2.5)
- rollup-plugin-base-url:
- specifier: ^0.0.2
- version: 0.0.2
- tailwindcss:
- specifier: ^3.4.1
- version: 3.4.1
- typescript:
- specifier: ^5.2.2
- version: 5.3.3
- vite:
- specifier: ^5.1.6
- version: 5.1.6
-
src/npm-flect:
dependencies:
'@fengkx/react-syntax-highlighter':
@@ -263,7 +181,7 @@ importers:
src/npm-flect-prebuilt:
dependencies:
'@chaoying/flect':
- specifier: 0.2.3
+ specifier: 0.2.4
version: link:../npm-flect
class-variance-authority:
specifier: ^0.7.0
@@ -1819,6 +1737,7 @@ packages:
'@types/prop-types': 15.7.11
'@types/scheduler': 0.16.8
csstype: 3.1.3
+ dev: true
/@types/scheduler@0.16.8:
resolution: {integrity: sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==}
@@ -2129,7 +2048,7 @@ packages:
'@babel/plugin-transform-react-jsx-source': 7.23.3(@babel/core@7.24.0)
'@types/babel__core': 7.20.5
react-refresh: 0.14.0
- vite: 5.1.6
+ vite: 5.1.6(@types/node@20.11.24)
transitivePeerDependencies:
- supports-color
dev: true
@@ -5147,28 +5066,6 @@ packages:
- supports-color
dev: false
- /react-markdown@9.0.1(@types/react@18.2.65)(react@18.2.0):
- resolution: {integrity: sha512-186Gw/vF1uRkydbsOIkcGXw7aHq0sZOCRFFjGrr7b9+nVZg4UfA4enXCaxm4fUzecU38sWfrNDitGhshuU7rdg==}
- peerDependencies:
- '@types/react': '>=18'
- react: '>=18'
- dependencies:
- '@types/hast': 3.0.4
- '@types/react': 18.2.65
- devlop: 1.1.0
- hast-util-to-jsx-runtime: 2.3.0
- html-url-attributes: 3.0.0
- mdast-util-to-hast: 13.1.0
- react: 18.2.0
- remark-parse: 11.0.0
- remark-rehype: 11.1.0
- unified: 11.0.4
- unist-util-visit: 5.0.0
- vfile: 6.0.1
- transitivePeerDependencies:
- - supports-color
- dev: false
-
/react-refresh@0.14.0:
resolution: {integrity: sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==}
engines: {node: '>=0.10.0'}
@@ -6136,41 +6033,6 @@ packages:
fsevents: 2.3.3
dev: true
- /vite@5.1.6:
- resolution: {integrity: sha512-yYIAZs9nVfRJ/AiOLCA91zzhjsHUgMjB+EigzFb6W2XTLO8JixBCKCjvhKZaye+NKYHCrkv3Oh50dH9EdLU2RA==}
- engines: {node: ^18.0.0 || >=20.0.0}
- hasBin: true
- peerDependencies:
- '@types/node': ^18.0.0 || >=20.0.0
- less: '*'
- lightningcss: ^1.21.0
- sass: '*'
- stylus: '*'
- sugarss: '*'
- terser: ^5.4.0
- peerDependenciesMeta:
- '@types/node':
- optional: true
- less:
- optional: true
- lightningcss:
- optional: true
- sass:
- optional: true
- stylus:
- optional: true
- sugarss:
- optional: true
- terser:
- optional: true
- dependencies:
- esbuild: 0.19.12
- postcss: 8.4.35
- rollup: 4.12.0
- optionalDependencies:
- fsevents: 2.3.3
- dev: true
-
/vite@5.1.6(@types/node@20.11.24):
resolution: {integrity: sha512-yYIAZs9nVfRJ/AiOLCA91zzhjsHUgMjB+EigzFb6W2XTLO8JixBCKCjvhKZaye+NKYHCrkv3Oh50dH9EdLU2RA==}
engines: {node: ^18.0.0 || >=20.0.0}
diff --git a/pyproject.toml b/pyproject.toml
index 3a8f47f..1718f8a 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "flect"
-version = "0.2.3"
+version = "0.2.4"
description = "Turning ideas into web app fast."
authors = [
{name = "Chaoying", email = "chaunceywe@gmail.com"},
diff --git a/src/npm-flect-prebuilt/package.json b/src/npm-flect-prebuilt/package.json
index a3d8882..1178f26 100644
--- a/src/npm-flect-prebuilt/package.json
+++ b/src/npm-flect-prebuilt/package.json
@@ -1,7 +1,7 @@
{
"name": "@chaoying/flect-prebuilt",
"description": "flect is a Python framework for building full-stack web applications.",
- "version": "0.2.4-beta.2",
+ "version": "0.2.4",
"type": "module",
"main": "dist/index.html",
"scripts": {
@@ -39,6 +39,6 @@
"vite": "^5.1.6"
},
"peerDependencies": {
- "@chaoying/flect": "0.2.3"
+ "@chaoying/flect": "0.2.4"
}
}
diff --git a/src/npm-flect-prebuilt/vite.config.ts b/src/npm-flect-prebuilt/vite.config.ts
index dfc6df1..f77ec4b 100644
--- a/src/npm-flect-prebuilt/vite.config.ts
+++ b/src/npm-flect-prebuilt/vite.config.ts
@@ -1,9 +1,7 @@
import path from "path";
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
-
-const pkg = process.env.npm_package_name;
-const version = process.env.npm_package_version;
+import { splitVendorChunkPlugin } from "vite";
const serverConfig = {
host: true,
@@ -14,8 +12,7 @@ const serverConfig = {
};
export default defineConfig({
- plugins: [react()],
- base: `https://unpkg.com/${pkg}@${version}/dist/`,
+ plugins: [react(), splitVendorChunkPlugin()],
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
diff --git a/src/npm-flect/package.json b/src/npm-flect/package.json
index 431ac1f..ecac6f6 100644
--- a/src/npm-flect/package.json
+++ b/src/npm-flect/package.json
@@ -4,7 +4,7 @@
"author": "chaoying",
"license": "MIT",
"private": false,
- "version": "0.2.3",
+ "version": "0.2.4",
"type": "module",
"main": "dist/index.js",
"types": "dist/index.d.ts",
@@ -21,7 +21,7 @@
},
"scripts": {
"dev": "vite",
- "build": "tsc && vite build --emptyOutDir --base=https://unpkg.com/@chaoying/flect@0.2.3/dist/",
+ "build": "tsc && vite build --emptyOutDir",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview"
},
diff --git a/src/npm-flect/src/components/flect/form-lazy.tsx b/src/npm-flect/src/components/flect/form-lazy.tsx
deleted file mode 100644
index 92db199..0000000
--- a/src/npm-flect/src/components/flect/form-lazy.tsx
+++ /dev/null
@@ -1,212 +0,0 @@
-import { useForm, FieldValues, ControllerRenderProps } from "react-hook-form";
-import { Input } from "@/components/ui/input";
-import { Button } from "@/components/ui/button";
-import { Checkbox } from "@/components/ui/checkbox";
-import {
- Form as FormUI,
- FormControl,
- FormDescription,
- FormField,
- FormItem,
- FormLabel,
- FormMessage,
-} from "@/components/ui/form";
-import { JSONSchema7 } from "json-schema";
-import { Textarea } from "@/components/ui/textarea";
-import { ajvResolver } from "@/lib/ajv-resolver";
-import {
- Select,
- SelectContent,
- SelectItem,
- SelectTrigger,
- SelectValue,
-} from "@/components/ui/select";
-import { cn } from "@/lib/utils";
-import React, { useContext } from "react";
-import { RotateCw } from "lucide-react";
-import { ActionResponse } from "@/types";
-import { resolveAction } from "@/lib/actions";
-import { ActionResolverContext } from "@/contexts/action-resolver";
-
-interface InputAttrs {
- type: "text" | "password" | "email";
- placeholder?: string;
-}
-
-interface TextAreaAttrs {
- rows?: number;
- cols?: number;
- placeholder?: string;
-}
-
-interface SelectAttrs {
- options: string[];
-}
-
-type Fieldtypes = "checkbox" | "input" | "select" | "textarea";
-type FieldAttrs = InputAttrs | TextAreaAttrs | SelectAttrs;
-
-interface Model extends JSONSchema7 {
- fieldType: Fieldtypes;
- className?: string;
- attrs?: FieldAttrs;
- properties: {
- [key: string]: Model;
- };
-}
-
-export interface FormLazyProps {
- package: "flect";
- type: "form";
- className?: string;
- model: Model;
- submitUrl: string;
- submitText?: string;
-}
-
-function getDefaultValues(schema: Model): FieldValues {
- const defaults: FieldValues = {};
- Object.keys(schema.properties).forEach((key) => {
- const prop = schema.properties[key];
- if (prop.default !== undefined && prop.default !== null) {
- defaults[key] = prop.default;
- }
- });
- return defaults;
-}
-
-export default function FormLazy(props: FormLazyProps) {
- const { resolvers } = useContext(ActionResolverContext);
- const form = useForm({
- resolver: ajvResolver(props.model),
- defaultValues: getDefaultValues(props.model),
- });
- async function onSubmit(values: FieldValues) {
- const response = await fetch(props.submitUrl, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify(values),
- });
- if (!response.ok) {
- throw new Error(response.statusText);
- }
- const responseJson = (await response.json()) as ActionResponse;
- resolveAction(resolvers, responseJson.action)();
- }
-
- return (
-
-
-
- );
-}
-
-interface FormFieldSlotProps {
- fieldType: Fieldtypes;
- attrs?: FieldAttrs;
- className?: string;
- field: ControllerRenderProps;
-}
-
-const FormFieldSlot = React.memo(
- ({ fieldType, attrs, field, className }: FormFieldSlotProps) => {
- switch (fieldType) {
- case "checkbox":
- return ;
- case "input":
- return (
-
- );
- case "select": {
- const { options } = attrs as SelectAttrs;
- return (
-
- );
- }
- case "textarea":
- return (
-
- );
- default:
- return null;
- }
- },
-);
diff --git a/src/npm-flect/src/components/flect/form.tsx b/src/npm-flect/src/components/flect/form.tsx
index a0be836..c51fef6 100644
--- a/src/npm-flect/src/components/flect/form.tsx
+++ b/src/npm-flect/src/components/flect/form.tsx
@@ -1,6 +1,212 @@
-import { lazy } from "react";
-import { FormLazyProps } from "@/components/flect/form-lazy";
+import { useForm, FieldValues, ControllerRenderProps } from "react-hook-form";
+import { Input } from "@/components/ui/input";
+import { Button } from "@/components/ui/button";
+import { Checkbox } from "@/components/ui/checkbox";
+import {
+ Form as FormUI,
+ FormControl,
+ FormDescription,
+ FormField,
+ FormItem,
+ FormLabel,
+ FormMessage,
+} from "@/components/ui/form";
+import { JSONSchema7 } from "json-schema";
+import { Textarea } from "@/components/ui/textarea";
+import { ajvResolver } from "@/lib/ajv-resolver";
+import {
+ Select,
+ SelectContent,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@/components/ui/select";
+import { cn } from "@/lib/utils";
+import React, { useContext } from "react";
+import { RotateCw } from "lucide-react";
+import { ActionResponse } from "@/types";
+import { resolveAction } from "@/lib/actions";
+import { ActionResolverContext } from "@/contexts/action-resolver";
-export type { FormLazyProps as FormProps };
+interface InputAttrs {
+ type: "text" | "password" | "email";
+ placeholder?: string;
+}
-export const Form = lazy(() => import("./form-lazy"));
+interface TextAreaAttrs {
+ rows?: number;
+ cols?: number;
+ placeholder?: string;
+}
+
+interface SelectAttrs {
+ options: string[];
+}
+
+type Fieldtypes = "checkbox" | "input" | "select" | "textarea";
+type FieldAttrs = InputAttrs | TextAreaAttrs | SelectAttrs;
+
+interface Model extends JSONSchema7 {
+ fieldType: Fieldtypes;
+ className?: string;
+ attrs?: FieldAttrs;
+ properties: {
+ [key: string]: Model;
+ };
+}
+
+export interface FormProps {
+ package: "flect";
+ type: "form";
+ className?: string;
+ model: Model;
+ submitUrl: string;
+ submitText?: string;
+}
+
+function getDefaultValues(schema: Model): FieldValues {
+ const defaults: FieldValues = {};
+ Object.keys(schema.properties).forEach((key) => {
+ const prop = schema.properties[key];
+ if (prop.default !== undefined && prop.default !== null) {
+ defaults[key] = prop.default;
+ }
+ });
+ return defaults;
+}
+
+export function Form(props: FormProps) {
+ const { resolvers } = useContext(ActionResolverContext);
+ const form = useForm({
+ resolver: ajvResolver(props.model),
+ defaultValues: getDefaultValues(props.model),
+ });
+ async function onSubmit(values: FieldValues) {
+ const response = await fetch(props.submitUrl, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify(values),
+ });
+ if (!response.ok) {
+ throw new Error(response.statusText);
+ }
+ const responseJson = (await response.json()) as ActionResponse;
+ resolveAction(resolvers, responseJson.action)();
+ }
+
+ return (
+
+
+
+ );
+}
+
+interface FormFieldSlotProps {
+ fieldType: Fieldtypes;
+ attrs?: FieldAttrs;
+ className?: string;
+ field: ControllerRenderProps;
+}
+
+const FormFieldSlot = React.memo(
+ ({ fieldType, attrs, field, className }: FormFieldSlotProps) => {
+ switch (fieldType) {
+ case "checkbox":
+ return ;
+ case "input":
+ return (
+
+ );
+ case "select": {
+ const { options } = attrs as SelectAttrs;
+ return (
+
+ );
+ }
+ case "textarea":
+ return (
+
+ );
+ default:
+ return null;
+ }
+ },
+);
diff --git a/src/npm-flect/src/components/flect/markdown-lazy.tsx b/src/npm-flect/src/components/flect/markdown-lazy.tsx
deleted file mode 100644
index 8ba6de6..0000000
--- a/src/npm-flect/src/components/flect/markdown-lazy.tsx
+++ /dev/null
@@ -1,41 +0,0 @@
-import { cn } from "@/lib/utils";
-import ReactMarkdown, { Components } from "react-markdown";
-import remarkGfm from "remark-gfm";
-import { CodeBlock } from "./code-block";
-
-export interface MarkdownLazyProps {
- package: "flect";
- type: "markdown";
- className?: string;
- text: string;
-}
-
-export default function Markdown(props: MarkdownLazyProps) {
- const { text, className } = props;
- const components: Components = {
- code({ children, className }) {
- const language = /language-(\w+)/.exec(className || "");
- if (!language) {
- return {children}
;
- }
- return (
-
- );
- },
- };
-
- return (
-
- {text}
-
- );
-}
diff --git a/src/npm-flect/src/components/flect/markdown.tsx b/src/npm-flect/src/components/flect/markdown.tsx
index 6b5880b..e86086e 100644
--- a/src/npm-flect/src/components/flect/markdown.tsx
+++ b/src/npm-flect/src/components/flect/markdown.tsx
@@ -1,6 +1,41 @@
-import { lazy } from "react";
-import { MarkdownLazyProps } from "@/components/flect/markdown-lazy";
+import { cn } from "@/lib/utils";
+import ReactMarkdown, { Components } from "react-markdown";
+import remarkGfm from "remark-gfm";
+import { CodeBlock } from "./code-block";
-export type { MarkdownLazyProps as MarkdownProps };
+export interface MarkdownProps {
+ package: "flect";
+ type: "markdown";
+ className?: string;
+ text: string;
+}
-export const Markdown = lazy(() => import("./markdown-lazy.tsx"));
+export function Markdown(props: MarkdownProps) {
+ const { text, className } = props;
+ const components: Components = {
+ code({ children, className }) {
+ const language = /language-(\w+)/.exec(className || "");
+ if (!language) {
+ return {children}
;
+ }
+ return (
+
+ );
+ },
+ };
+
+ return (
+
+ {text}
+
+ );
+}
diff --git a/src/python-flect/src/flect/render.py b/src/python-flect/src/flect/render.py
index 61606e3..fb305e4 100644
--- a/src/python-flect/src/flect/render.py
+++ b/src/python-flect/src/flect/render.py
@@ -15,7 +15,7 @@
if TYPE_CHECKING:
from flect.routing import ClientRoute
-FLECT_PREBUILT_URI = "https://unpkg.com/@chaoying/flect-prebuilt@0.2.3/dist/assets"
+FLECT_PREBUILT_URI = "https://unpkg.com/@chaoying/flect-prebuilt@0.2.4/dist/assets"
def generate_html(