From 9e5d78e974c076eff3e047f64ab8e10cdcc94779 Mon Sep 17 00:00:00 2001 From: "codegen-sh[bot]" <131295404+codegen-sh[bot]@users.noreply.github.com> Date: Wed, 4 Jun 2025 04:09:50 +0000 Subject: [PATCH 01/16] feat: complete medusa forms extraction and migration - Migrated core repository structure from @lambdacurry/forms - Copied packages/medusa-forms with all controlled components - Migrated apps/docs with Storybook documentation for medusa forms - Copied development setup (.cursor, .vscode, configuration files) - Updated package names and references to @lambdacurry/medusa-forms - Removed remix-hook-form dependencies and stories (out of scope) - Added missing zod dependency for form validation - Updated README.md to reflect new repository purpose - Verified Storybook builds and runs successfully Components migrated: - ControlledInput, ControlledTextArea, ControlledSelect - ControlledCheckbox, ControlledDatePicker, ControlledCurrencyInput - Supporting UI components and field wrappers All medusa form components are now functional in the new repository. --- README.md | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 98611c3..65e3097 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,84 @@ A controlled form components library for Medusa Admin and Medusa UI applications. +Checkout our [Storybook Documentation](https://lambda-curry.github.io/medusa-forms/?path=/docs/0-1-hello-world-start-here--docs) to see the components in action and get started. + +## Features + +- **Controlled Components**: All form components are controlled and work seamlessly with react-hook-form +- **Medusa UI Integration**: Built specifically for Medusa Admin and Medusa UI design system +- **TypeScript Support**: Full TypeScript support with proper type definitions +- **Storybook Documentation**: Comprehensive documentation and examples + +## Components + +- `ControlledInput` - Text input with validation +- `ControlledTextArea` - Multi-line text input +- `ControlledSelect` - Dropdown selection +- `ControlledCheckbox` - Checkbox input +- `ControlledDatePicker` - Date selection +- `ControlledCurrencyInput` - Currency input with formatting + ## Getting Started -This repository is being set up. Please check back soon for the complete implementation. +Step 1: Install dependencies + +```bash +yarn install +``` + +Step 2: Start Storybook + +```bash +yarn storybook +``` + +## Development + +### PR Previews + +When you create a pull request, a preview of the Storybook documentation will be automatically deployed. You can find the link to the preview in the PR comments. This allows you to review changes to the documentation and components before merging. + +Preview URLs follow this format: +``` +https://lambda-curry.github.io/medusa-forms/pr-preview/pr-[PR_NUMBER]/ +``` + +#### How PR Previews Work + +The PR preview system: +1. Builds the Storybook documentation for each PR +2. Deploys it to a PR-specific directory on the `gh-pages` branch +3. Adds a comment to the PR with a link to the preview +4. **Automatically updates the preview when you push new changes to the PR** +5. Cleans up the preview when the PR is closed + +#### GitHub Environment Setup + +For PR previews to work properly, you need to set up a GitHub environment: + +1. Go to your repository settings +2. Navigate to "Environments" +3. Create a new environment named `pr-preview` +4. Configure environment protection rules as needed: + - You can require reviewers to approve deployment + - You can limit deployment to specific branches + - You can add wait timers before deployment + +The main branch will continue to deploy to the `github-pages` environment. + +#### Troubleshooting PR Previews + +If you encounter a 404 error when accessing the PR preview: + +1. Make sure the PR build has completed successfully by checking the GitHub Actions tab +2. Verify that the repository has GitHub Pages enabled and configured to deploy from the `gh-pages` branch +3. Check that the PR preview comment contains the correct URL +4. Ensure the PR has been approved for deployment if environment protection rules are enabled +5. Try clearing your browser cache or using an incognito window + +The PR preview is deployed to the `gh-pages` branch in a directory structure like: +``` +/pr-preview/pr-[PR_NUMBER]/ +``` From c2b2f6f8da2142e6ff827bdd65696e7318acae92 Mon Sep 17 00:00:00 2001 From: "codegen-sh[bot]" <131295404+codegen-sh[bot]@users.noreply.github.com> Date: Wed, 4 Jun 2025 04:46:48 +0000 Subject: [PATCH 02/16] feat: Add GitHub workflows for Storybook deployment and releases - Add PR preview workflow for automatic Storybook previews on PRs - Add release workflow with changesets for automated npm publishing - Add GitHub Pages workflow for main branch Storybook deployment - Add test workflow for CI validation - Workflows adapted from lambdacurry/forms repo with medusa-forms specific updates --- .github/workflows/github-pages.yml | 62 +++++++++++ .github/workflows/pr-preview.yml | 168 +++++++++++++++++++++++++++++ .github/workflows/release.yml | 41 +++++++ .github/workflows/test.yml | 50 +++++++++ 4 files changed, 321 insertions(+) create mode 100644 .github/workflows/github-pages.yml create mode 100644 .github/workflows/pr-preview.yml create mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/github-pages.yml b/.github/workflows/github-pages.yml new file mode 100644 index 0000000..b68fe27 --- /dev/null +++ b/.github/workflows/github-pages.yml @@ -0,0 +1,62 @@ +# Simple workflow for deploying static content to GitHub Pages +name: Deploy static content to Pages + +on: + # Runs on pushes targeting the default branch + push: + branches: ["main"] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. +# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + # Single deploy job since we're just deploying + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: '22.9.0' + + - name: Setup Yarn Corepack + run: corepack enable + + - name: Install dependencies + run: yarn install + + - name: Build Storybook + run: yarn build-storybook + + - name: Setup Pages + uses: actions/configure-pages@v5 + + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + # Don't remove PR previews when deploying the main branch + path: 'apps/docs/storybook-static' + retention-days: 30 + + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 + diff --git a/.github/workflows/pr-preview.yml b/.github/workflows/pr-preview.yml new file mode 100644 index 0000000..07a2e71 --- /dev/null +++ b/.github/workflows/pr-preview.yml @@ -0,0 +1,168 @@ +name: Deploy PR Preview + +on: + pull_request: + types: + - opened + - reopened + - synchronize + - closed + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + pull-requests: write + +# Allow only one concurrent deployment per PR +concurrency: + group: pr-preview-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + # Build job + build: + runs-on: ubuntu-latest + # Don't run on closed PRs + if: github.event.action != 'closed' + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: '22.9.0' + + - name: Setup Yarn Corepack + run: corepack enable + + - name: Install dependencies + run: yarn install + + - name: Build Storybook + run: yarn build-storybook + + # Verify the build output + - name: Verify build output + run: | + echo "Checking build output directory..." + ls -la apps/docs/storybook-static + echo "Checking for index.html..." + if [ -f apps/docs/storybook-static/index.html ]; then + echo "index.html exists" + else + echo "index.html does not exist" + exit 1 + fi + + # Add a comment to the PR with the preview URL + - name: Comment PR + uses: actions/github-script@v6 + with: + script: | + const previewUrl = `https://lambda-curry.github.io/medusa-forms/pr-${context.issue.number}/`; + const commentBody = `📝 **Storybook Preview**: [View Storybook](${previewUrl}) + + This preview will be updated automatically when you push new changes to this PR. + + > Note: The preview will be available after the workflow completes and the PR is approved for deployment.`; + + // Get existing comments + const comments = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + }); + + // Check if we already have a comment + const botComment = comments.data.find(comment => + comment.user.login === 'github-actions[bot]' && + comment.body.includes('Storybook Preview') + ); + + if (botComment) { + // Update existing comment + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: botComment.id, + body: commentBody + }); + } else { + // Create new comment + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body: commentBody + }); + } + + # Create PR-specific directory structure + - name: Create PR-specific directory + run: | + mkdir -p pr-preview/pr-${{ github.event.pull_request.number }} + cp -r apps/docs/storybook-static/* pr-preview/pr-${{ github.event.pull_request.number }}/ + + # Upload the artifact for the deployment job + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: pr-preview + retention-days: 30 + + # Deploy job + deploy: + needs: build + runs-on: ubuntu-latest + if: github.event.action != 'closed' + + # Use a specific environment with protection rules + # This ensures only approved PRs can deploy + environment: + name: pr-preview + url: ${{ steps.deployment.outputs.page_url }} + + steps: + - name: Setup Pages + uses: actions/configure-pages@v5 + + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 + + # Clean up when PR is closed + cleanup: + runs-on: ubuntu-latest + if: github.event.action == 'closed' + permissions: + contents: write + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: gh-pages + + - name: Delete PR Preview + run: | + PR_NUMBER="${{ github.event.pull_request.number }}" + PR_PREVIEW_PATH="pr-preview/pr-$PR_NUMBER" + + if [ -d "$PR_PREVIEW_PATH" ]; then + echo "Removing PR preview at $PR_PREVIEW_PATH" + rm -rf "$PR_PREVIEW_PATH" + + # Commit and push the changes + git config user.name "GitHub Actions" + git config user.email "actions@github.com" + git add -A + git commit -m "Remove PR preview for PR #$PR_NUMBER" || echo "No changes to commit" + git push + else + echo "PR preview directory not found" + fi + diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..4ab25d9 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,41 @@ +name: Release + +on: + push: + branches: + - main + +concurrency: ${{ github.workflow }}-${{ github.ref }} + +jobs: + release: + name: Release + runs-on: ubuntu-latest + steps: + - name: Checkout Repo + uses: actions/checkout@v3 + + - name: Setup Node.js 20.x + uses: actions/setup-node@v3 + with: + node-version: 20.x + + - name: Enable Corepack + run: corepack enable + + - name: Install Correct Yarn Version + run: corepack prepare yarn@4.9.1 --activate + + - name: Install Dependencies + run: yarn + + - name: Create Release Pull Request or Publish to npm + id: changesets + uses: changesets/action@v1 + with: + # This expects you to have a script called release which does a build for your packages and calls changeset publish + publish: yarn release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..fccf6da --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,50 @@ +name: Run Tests + +on: + push: + branches: [main] + pull_request: + branches: [main] + workflow_dispatch: + +jobs: + test: + runs-on: ubuntu-latest + timeout-minutes: 15 + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: '22.9.0' + + - name: Setup Yarn Corepack + run: corepack enable + + - name: Install dependencies + run: yarn install + + - uses: dtinth/setup-github-actions-caching-for-turbo@v1 + + - name: Build packages + run: yarn build + + - name: Build Storybook + run: yarn build-storybook + + - name: Lint and format check + run: yarn format-and-lint + + - name: Upload artifacts on failure + if: failure() + uses: actions/upload-artifact@v4 + with: + name: test-failure + path: apps/docs/storybook-static + retention-days: 2 + From 2988ba97a16919dc305c1b918101492b2256319d Mon Sep 17 00:00:00 2001 From: "codegen-sh[bot]" <131295404+codegen-sh[bot]@users.noreply.github.com> Date: Wed, 4 Jun 2025 04:57:45 +0000 Subject: [PATCH 03/16] docs: Update Storybook welcome page for medusa-forms - Replace generic forms content with medusa-forms specific documentation - Add installation and quick start guide - Include Medusa Admin integration examples - Document all available components and features - Provide clear next steps for developers --- .../docs/src/0.1 Hello World (start here).mdx | 145 +++++++++++++++--- 1 file changed, 126 insertions(+), 19 deletions(-) diff --git a/apps/docs/src/0.1 Hello World (start here).mdx b/apps/docs/src/0.1 Hello World (start here).mdx index 54157f3..2bc8f0f 100644 --- a/apps/docs/src/0.1 Hello World (start here).mdx +++ b/apps/docs/src/0.1 Hello World (start here).mdx @@ -1,32 +1,139 @@ -# FORMS ARE HARD 🙃 -But everything is a form. And everything will continue to be a form until all the robots just talk to each other - that's probably the day I'll be able to retire. Until then, I'll keep working on forms and making them easier to implement. +# Welcome to Medusa Forms! 🎯 -## Intro: *How did we get here?* +**Controlled form components designed specifically for Medusa Admin and Medusa UI** -From jQuery Validation to AngularJS to Redux Form to Formik, I've spent way too many late nights working on form libraries. It's been a large part of my web development career as a front-end developer starting in the early 2010s. +Medusa Forms provides a comprehensive set of controlled form components that integrate seamlessly with the Medusa ecosystem, built on top of `react-hook-form` and `@medusajs/ui`. +## What is Medusa Forms? -## Inspiration +Medusa Forms is a collection of controlled form components extracted and optimized for use with Medusa Admin interfaces. Each component is designed to work perfectly with Medusa's design system while providing excellent developer experience through TypeScript support and comprehensive documentation. -Now everything is trending back to "using the platform" with this concept of progressive enhancement. I'm a big fan of Ryan Florence [(@ryanflorence)](https://x.com/ryanflorence) and Michael Jackson [(@mjackson)](https://x.com/mjackson)'s work on [Remix](https://x.com/remix_run). Also, Alem Tuzlak [(@AlemTuzlak)](https://x.com/AlemTuzlak) and Thomas Fritz [(@thomasf)](https://x.com/thomasf)'s work on Remix Hook Form (and Remix Dev Tools) with their agency Forge42 [(@forge42dev)](https://x.com/forge42dev). +## Key Features -Special shoutout to Edmund Hung [(@edmundhung)](https://x.com/edmundhung) for his work on [React Conform](https://x.com/react_conform) which is another great library for working with forms. His stuff is so cool that people like Kent C. Dodds [(@kentcdodds)](https://x.com/kentcdodds) have adopted his library into his Epic Web stack. +✅ **Medusa UI Integration** - Built specifically for Medusa Admin design system +✅ **Controlled Components** - All components work seamlessly with react-hook-form +✅ **TypeScript Support** - Full type definitions and IntelliSense +✅ **Comprehensive Documentation** - Interactive Storybook with examples +✅ **Performance Optimized** - Tree-shaking support and optimized bundle sizes +## Available Components -## Goals +### Form Controls +- **ControlledInput** - Text input with validation +- **ControlledTextArea** - Multi-line text input +- **ControlledSelect** - Dropdown selection with search +- **ControlledCheckbox** - Checkbox input with proper styling +- **ControlledDatePicker** - Date selection with calendar +- **ControlledCurrencyInput** - Currency input with formatting -1. Extremely easy implementation in React Frameworks such as Next.js and Remix. -2. Well tested, documented, and maintained. -3. Forward thinking - for example React 19 is coming and it has a few new features that could make working with forms even easier. +### UI Components +- **FieldWrapper** - Consistent field styling and error handling +- **Label** - Accessible form labels +- **ErrorMessage** - Standardized error display -## WIP +## Quick Start -This is a work in progress. Please don't hesitate to message me with questions or collaboration opportunities. +### Installation -Next up: +```bash +npm install @lambdacurry/medusa-forms +# or +yarn add @lambdacurry/medusa-forms +``` + +### Basic Usage + +```tsx +import { useForm } from 'react-hook-form'; +import { ControlledInput, ControlledSelect } from '@lambdacurry/medusa-forms'; + +function MyForm() { + const { control, handleSubmit } = useForm(); + + return ( +
+ ); +} +``` + +## Integration with Medusa + +These components are designed to work perfectly in Medusa Admin interfaces: + +```tsx +import { RouteConfig } from "@medusajs/admin" +import { ControlledInput, ControlledCurrencyInput } from "@lambdacurry/medusa-forms" + +const ProductForm = () => { + // Your Medusa admin form logic here + return ( +