Skip to content

Commit 1ddf1d2

Browse files
authored
Merge pull request #37 from lambda-curry/gen/85446350-51fe-4d9e-8972-3edc10a9b2cd
(BETA) LC-173: Migrate LambdaCurry/forms to ShadCN tailwind V4
2 parents 95944f5 + 4085523 commit 1ddf1d2

File tree

87 files changed

+6933
-21598
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

87 files changed

+6933
-21598
lines changed

.github/workflows/test.yml

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,6 @@ jobs:
3434
- name: Install Playwright Chromium
3535
run: npx playwright install chromium
3636

37-
- name: Build Storybook
38-
run: yarn build-storybook
39-
40-
- name: Start Storybook server
41-
run: yarn workspace @lambdacurry/forms-docs storybook --ci --port 6006 &
42-
env:
43-
NODE_OPTIONS: --max-old-space-size=4096
44-
45-
- name: Wait for Storybook to be ready
46-
run: npx wait-on http://localhost:6006
47-
4837
- name: Run tests
4938
run: yarn test
5039

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,4 +179,7 @@ dist
179179
.turbo
180180
*storybook.log
181181

182-
storybook-static
182+
storybook-static
183+
184+
# React Router v7
185+
.react-router/

.vscode/settings.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"hookform",
88
"isbot",
99
"lucide",
10+
"Nuqs",
1011
"shadcn",
1112
"sonner"
1213
],
@@ -20,5 +21,6 @@
2021
"editor.codeActionsOnSave": {
2122
"source.fixAll.biome": "explicit",
2223
"source.organizeImports.biome": "explicit"
23-
}
24+
},
25+
"tailwindCSS.classAttributes": ["class", "className", "ngClass", "class:list", "wrapperClassName"]
2426
}

.yarnrc.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
nodeLinker: node-modules
1+
nodeLinker: node-modules

ai/CustomInputsProject.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,8 @@ import { expect, userEvent } from '@storybook/test';
484484
import * as React from 'react';
485485
import { RemixFormProvider, getValidatedFormData, useRemixForm } from 'remix-hook-form';
486486
import { z } from 'zod';
487-
import { withRemixStubDecorator } from '../lib/storybook/remix-stub';
487+
488+
import { withReactRouterStubDecorator } from '../lib/storybook/react-router-stub';
488489

489490
// Custom checkbox component
490491
const CustomCheckbox = React.forwardRef<
@@ -597,6 +598,18 @@ const handleFormSubmission = async (request: Request) => {
597598
// Story definition
598599
export const CustomComponents: Story = {
599600
render: () => <CustomCheckboxExample />,
601+
decorators: [
602+
withReactRouterStubDecorator({
603+
routes: [
604+
{
605+
path: '/',
606+
action: async ({ request }: ActionFunctionArgs) => {
607+
return handleFormSubmission(request);
608+
},
609+
},
610+
],
611+
}),
612+
],
600613
parameters: {
601614
docs: {
602615
description: {

apps/docs/.storybook/main.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import { dirname, join } from 'node:path';
22
import type { StorybookConfig } from '@storybook/react-vite';
3-
import { mergeConfig } from 'vite';
4-
import viteConfig from '../vite.config';
53

64
/**
75
* This function is used to resolve the absolute path of a package.
@@ -21,7 +19,9 @@ const config: StorybookConfig = {
2119
name: getAbsolutePath('@storybook/react-vite'),
2220
options: {},
2321
},
24-
viteFinal: (config) => {
22+
viteFinal: async (config) => {
23+
const { mergeConfig } = await import('vite');
24+
const viteConfig = await import('../vite.config.mjs');
2525
return mergeConfig(config, viteConfig);
2626
},
2727
};

apps/docs/package.json

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,35 +6,39 @@
66
"build": "storybook build",
77
"build-storybook": "storybook build",
88
"storybook": "storybook dev -p 6006",
9-
"test": "test-storybook"
9+
"serve": "http-server ./storybook-static -p 6006 -s",
10+
"test": "start-server-and-test serve http://127.0.0.1:6006 'test-storybook --url http://127.0.0.1:6006'",
11+
"test:local": "test-storybook"
1012
},
1113
"dependencies": {
1214
"@lambdacurry/forms": "*",
13-
"@storybook/addon-essentials": "^8.4.7",
14-
"@storybook/addon-interactions": "^8.4.7",
15-
"@storybook/addon-links": "^8.4.7",
16-
"@storybook/blocks": "^8.4.7",
17-
"@storybook/react": "^8.4.7",
18-
"@storybook/react-vite": "^8.4.7",
19-
"@storybook/test": "^8.4.7",
20-
"storybook": "^8.4.7"
15+
"@storybook/addon-essentials": "^8.6.7",
16+
"@storybook/addon-interactions": "^8.6.7",
17+
"@storybook/addon-links": "^8.6.7",
18+
"@storybook/blocks": "^8.6.7",
19+
"@storybook/react": "^8.6.7",
20+
"@storybook/react-vite": "^8.6.7",
21+
"@storybook/test": "^8.6.7",
22+
"storybook": "^8.6.7"
2123
},
2224
"devDependencies": {
23-
"@remix-run/dev": "^2.15.1",
24-
"@remix-run/testing": "^2.15.1",
25-
"@storybook/test-runner": "^0.20.1",
25+
"@react-router/dev": "^7.0.0",
26+
"@storybook/test-runner": "^0.22.0",
2627
"@storybook/testing-library": "^0.2.2",
27-
"@types/react": "^18.0.0",
28-
"@types/react-dom": "^18.0.0",
28+
"@tailwindcss/vite": "^4.0.0",
29+
"@types/react": "^19.0.0",
2930
"@typescript-eslint/eslint-plugin": "^6.21.0",
3031
"@typescript-eslint/parser": "^6.21.0",
3132
"autoprefixer": "^10.4.20",
32-
"postcss": "^8.4.49",
33-
"react": "^18.0.0",
34-
"react-dom": "^18.0.0",
35-
"tailwindcss": "^3.4.17",
33+
"http-server": "^14.1.1",
34+
"react": "^19.0.0",
35+
"react-router": "^7.0.0",
36+
"react-router-dom": "^7.0.0",
37+
"start-server-and-test": "^2.0.11",
38+
"tailwindcss": "^4.0.0",
3639
"typescript": "^5.7.2",
37-
"vite": "^5.4.11",
38-
"vite-tsconfig-paths": "^5.1.4"
40+
"vite": "^6.2.2",
41+
"vite-tsconfig-paths": "^5.1.4",
42+
"wait-on": "^8.0.3"
3943
}
4044
}

apps/docs/postcss.config.js

Lines changed: 0 additions & 6 deletions
This file was deleted.
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Example of using the new middleware feature in remix-hook-form v7.0.0
2+
import { Form } from 'react-router';
3+
import { RemixFormProvider, useRemixForm } from 'remix-hook-form';
4+
import { zodResolver } from '@hookform/resolvers/zod';
5+
import * as zod from 'zod';
6+
import { TextField } from '@lambdacurry/forms/remix-hook-form';
7+
import { getValidatedFormData } from 'remix-hook-form/middleware';
8+
import type { ActionFunctionArgs } from 'react-router';
9+
10+
// Define schema and types
11+
const schema = zod.object({
12+
name: zod.string().min(1, "Name is required"),
13+
email: zod.string().email("Invalid email format").min(1, "Email is required"),
14+
});
15+
16+
type FormData = zod.infer<typeof schema>;
17+
const resolver = zodResolver(schema);
18+
19+
// Action function using the new middleware
20+
export const action = async ({ context }: ActionFunctionArgs) => {
21+
// Use the middleware to extract and validate form data
22+
const { errors, data, receivedValues } = await getValidatedFormData<FormData>(
23+
context,
24+
resolver
25+
);
26+
27+
if (errors) {
28+
return { errors, defaultValues: receivedValues };
29+
}
30+
31+
// Process the validated data
32+
console.log('Processing data:', data);
33+
34+
return { success: true, data };
35+
};
36+
37+
// Component
38+
export default function MiddlewareExample() {
39+
const {
40+
handleSubmit,
41+
formState: { errors },
42+
register,
43+
} = useRemixForm<FormData>({
44+
mode: "onSubmit",
45+
resolver,
46+
});
47+
48+
return (
49+
<div className="p-4">
50+
<h1 className="text-2xl font-bold mb-4">Remix Hook Form v7 Middleware Example</h1>
51+
52+
<RemixFormProvider>
53+
<Form method="POST" onSubmit={handleSubmit}>
54+
<div className="space-y-4">
55+
<TextField
56+
label="Name"
57+
{...register("name")}
58+
error={errors.name?.message}
59+
/>
60+
61+
<TextField
62+
label="Email"
63+
type="email"
64+
{...register("email")}
65+
error={errors.email?.message}
66+
/>
67+
68+
<button
69+
type="submit"
70+
className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
71+
>
72+
Submit
73+
</button>
74+
</div>
75+
</Form>
76+
</RemixFormProvider>
77+
</div>
78+
);
79+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Example of setting up the middleware in root.tsx
2+
import { unstable_extractFormDataMiddleware } from 'remix-hook-form/middleware';
3+
import { Outlet } from 'react-router-dom';
4+
5+
// Export the middleware for React Router 7
6+
export const unstable_middleware = [unstable_extractFormDataMiddleware()];
7+
8+
export default function Root() {
9+
return (
10+
<html lang="en">
11+
<head>
12+
<meta charSet="utf-8" />
13+
<meta name="viewport" content="width=device-width, initial-scale=1" />
14+
<title>Remix Hook Form v7 Example</title>
15+
</head>
16+
<body>
17+
<div className="container mx-auto">
18+
<Outlet />
19+
</div>
20+
</body>
21+
</html>
22+
);
23+
}

0 commit comments

Comments
 (0)