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 ( +
+ + +
+ ) +} + +export const config: RouteConfig = { + link: { + label: "Custom Product Form", + }, +} + +export default ProductForm +``` + +## Form Integration Examples + +Check out our **Form Integration Examples** story to see complete working forms with: +- Validation schemas using Zod +- Complex form layouts +- Error handling +- Real-world use cases + +## Dependencies + +- **React** ^19.0.0 +- **react-hook-form** ^7.51.0 +- **@medusajs/ui** ^4.0.0 +- **zod** ^3.23.8 (for validation examples) + +## Next Steps + +1. 📖 **Explore Components** - Browse the component stories to see all available options +2. 🎮 **Try Examples** - Check out the Form Integration Examples for complete implementations +3. 🔧 **Customize** - All components accept standard HTML props and can be styled as needed +4. 🚀 **Build** - Start building your Medusa Admin forms with confidence! + +--- + +**Ready to build better forms?** Start exploring the components in the sidebar! 👈 -- [ ] Add a few Next.js Examples -- [ ] Add more components (React Select?) -- [ ] Add some AI specific documentation - usefull for prompts and writing tests -- [ ] Rename Default stories to Test stories and provide documentation on how they are used by the test runner with the play command. -- [ ] Add documentation of base components to Storybook without tests (maybe they can have visual regression tests in the future) From 81aea27f82301eb1c39fe69b8b99e0ccfee0c723 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:58:41 +0000 Subject: [PATCH 04/16] fix: Add missing type imports and definitions - Import CalendarDateTime, CalendarDate from @internationalized/date - Import BaseDatePickerProps, Translations, Direction from @medusajs/ui - Add missing Option, IsMulti, Group type definitions - Resolve TypeScript undeclared variable errors --- packages/medusa-forms/src/ui/types.d.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/medusa-forms/src/ui/types.d.ts b/packages/medusa-forms/src/ui/types.d.ts index cafd967..62742d8 100644 --- a/packages/medusa-forms/src/ui/types.d.ts +++ b/packages/medusa-forms/src/ui/types.d.ts @@ -1,3 +1,5 @@ +import type { CalendarDate, CalendarDateTime, CalendarProps, Granularity } from '@internationalized/date'; +import type { BaseDatePickerProps, Direction, Translations } from '@medusajs/ui'; import type { ReactNode, RefAttributes } from 'react'; import type { Props, SelectInstance } from 'react-select'; import type { CreatableProps } from 'react-select/creatable'; @@ -34,6 +36,14 @@ export type MedusaInputProps = React.InputHTMLAttributes & { size?: 'small' | 'base'; }; +type Option = { + label: string; + value: string; +}; + +type IsMulti = boolean; +type Group = any; + interface PickerProps extends CalendarProps { /** * The class name to apply on the date picker. From df4ef87dbe678910e6a466d47d3b1190b90b0d61 Mon Sep 17 00:00:00 2001 From: "codegen-sh[bot]" <131295404+codegen-sh[bot]@users.noreply.github.com> Date: Wed, 4 Jun 2025 05:10:29 +0000 Subject: [PATCH 05/16] fix: Address critical linting and formatting issues - Fix Node.js import protocol warnings in simple-server.js - Move regex patterns to top level for performance optimization - Fix TypeScript type definitions and imports - Replace 'any' type with proper Group interface - Resolve undeclared React variable issues These fixes address the main issues causing test failures. --- apps/docs/.storybook/main.ts | 5 +- apps/docs/simple-server.js | 34 +-- apps/docs/src/main.css | 269 +++++++++++------- .../ControlledCheckbox.stories.tsx | 156 ++++------ .../FormIntegrationExamples.stories.tsx | 16 +- package.json | 5 +- packages/medusa-forms/package.json | 4 +- packages/medusa-forms/src/index.ts | 1 - packages/medusa-forms/src/ui/types.d.ts | 19 +- 9 files changed, 263 insertions(+), 246 deletions(-) diff --git a/apps/docs/.storybook/main.ts b/apps/docs/.storybook/main.ts index 3ecc947..c138a79 100644 --- a/apps/docs/.storybook/main.ts +++ b/apps/docs/.storybook/main.ts @@ -10,10 +10,7 @@ function getAbsolutePath(value: string): string { } const config: StorybookConfig = { stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'], - addons: [ - getAbsolutePath('@storybook/addon-links'), - getAbsolutePath("@storybook/addon-docs") - ], + addons: [getAbsolutePath('@storybook/addon-links'), getAbsolutePath('@storybook/addon-docs')], framework: { name: getAbsolutePath('@storybook/react-vite'), options: {}, diff --git a/apps/docs/simple-server.js b/apps/docs/simple-server.js index a7b12be..51aa9ba 100644 --- a/apps/docs/simple-server.js +++ b/apps/docs/simple-server.js @@ -1,6 +1,6 @@ -const http = require('http'); -const fs = require('fs'); -const path = require('path'); +const http = require('node:http'); +const fs = require('node:fs'); +const path = require('node:path'); const server = http.createServer((req, res) => { // Add CORS headers @@ -9,24 +9,25 @@ const server = http.createServer((req, res) => { res.setHeader('Access-Control-Allow-Headers', 'Content-Type'); let filePath = path.join(__dirname, 'storybook-static', req.url === '/' ? 'index.html' : req.url); - + // If file doesn't exist, serve index.html for SPA routing if (!fs.existsSync(filePath)) { filePath = path.join(__dirname, 'storybook-static', 'index.html'); } - + const ext = path.extname(filePath); - const contentType = { - '.html': 'text/html', - '.js': 'text/javascript', - '.css': 'text/css', - '.json': 'application/json', - '.png': 'image/png', - '.jpg': 'image/jpeg', - '.gif': 'image/gif', - '.svg': 'image/svg+xml' - }[ext] || 'text/plain'; - + const contentType = + { + '.html': 'text/html', + '.js': 'text/javascript', + '.css': 'text/css', + '.json': 'application/json', + '.png': 'image/png', + '.jpg': 'image/jpeg', + '.gif': 'image/gif', + '.svg': 'image/svg+xml', + }[ext] || 'text/plain'; + fs.readFile(filePath, (err, content) => { if (err) { console.error('Error reading file:', filePath, err); @@ -43,4 +44,3 @@ const PORT = 45678; server.listen(PORT, () => { console.log(`Server running on http://127.0.0.1:${PORT}`); }); - diff --git a/apps/docs/src/main.css b/apps/docs/src/main.css index c1325f7..0ca752f 100644 --- a/apps/docs/src/main.css +++ b/apps/docs/src/main.css @@ -1,4 +1,4 @@ -@import 'tailwindcss'; +@import "tailwindcss"; @source "../../../packages/components"; @source "../../../packages/medusa-forms"; @source "../../../node_modules/@medusajs/ui"; @@ -246,48 +246,66 @@ /* Medusa UI Dark Mode Shadow Effects */ --borders-interactive-with-shadow: 0px 1px 2px 0px rgba(219, 234, 254, 0.5), 0px 0px 0px 1px rgba(96, 165, 250, 1); --details-contrast-on-bg-interactive: 0px 1px 2px 0px rgba(30, 58, 138, 0.6); - --details-switch-handle: 0px 0px 2px 1px rgba(255, 255, 255, 1) inset, 0px 1px 0px 0px rgba(255, 255, 255, 1) inset, + --details-switch-handle: + 0px 0px 2px 1px rgba(255, 255, 255, 1) inset, 0px 1px 0px 0px rgba(255, 255, 255, 1) inset, 0px 0px 0px 0.5px rgba(0, 0, 0, 0.16), 0px 5px 4px 0px rgba(0, 0, 0, 0.1), 0px 3px 3px 0px rgba(0, 0, 0, 0.1), 0px 1px 2px 0px rgba(0, 0, 0, 0.1), 0px 0px 1px 0px rgba(0, 0, 0, 0.1); --borders-interactive-with-active: 0px 0px 0px 1px rgba(96, 165, 250, 1), 0px 0px 0px 4px rgba(59, 130, 246, 0.25); --borders-focus: 0px 0px 0px 1px rgba(24, 24, 27, 1), 0px 0px 0px 3px rgba(96, 165, 250, 0.8); - --borders-interactive-with-focus: 0px 1px 2px 0px rgba(219, 234, 254, 0.5), 0px 0px 0px 1px rgba(96, 165, 250, 1), + --borders-interactive-with-focus: + 0px 1px 2px 0px rgba(219, 234, 254, 0.5), 0px 0px 0px 1px rgba(96, 165, 250, 1), 0px 0px 0px 2px rgba(24, 24, 27, 1), 0px 0px 0px 4px rgba(96, 165, 250, 0.8); - --details-switch-background-focus: 0px 0px 0px 1px rgba(24, 24, 27, 1), 0px 0px 0px 3px rgba(96, 165, 250, 0.8), + --details-switch-background-focus: + 0px 0px 0px 1px rgba(24, 24, 27, 1), 0px 0px 0px 3px rgba(96, 165, 250, 0.8), 0px 1px 1px 0px rgba(0, 0, 0, 0.1) inset, 0px 2px 4px 0px rgba(0, 0, 0, 0.1) inset, 0px 0px 0px 0.75px rgba(255, 255, 255, 0.12) inset, 0px 0px 8px 0px rgba(0, 0, 0, 0.1) inset; - --buttons-danger: 0px -1px 0px 0px rgba(255, 255, 255, 0.16), 0px 0px 0px 1px rgba(255, 255, 255, 0.12), + --buttons-danger: + 0px -1px 0px 0px rgba(255, 255, 255, 0.16), 0px 0px 0px 1px rgba(255, 255, 255, 0.12), 0px 0px 0px 1px rgba(159, 18, 57, 1), 0px 0px 1px 1.5px rgba(0, 0, 0, 0.24), 0px 2px 2px 0px rgba(0, 0, 0, 0.24); - --buttons-danger-focus: 0px -1px 0px 0px rgba(255, 255, 255, 0.16), 0px 0px 0px 1px rgba(255, 255, 255, 0.12), + --buttons-danger-focus: + 0px -1px 0px 0px rgba(255, 255, 255, 0.16), 0px 0px 0px 1px rgba(255, 255, 255, 0.12), 0px 0px 0px 1px rgba(159, 18, 57, 1), 0px 0px 0px 2px rgba(24, 24, 27, 1), 0px 0px 0px 4px rgba(96, 165, 250, 0.8); - --details-switch-background: 0px 1px 1px 0px rgba(0, 0, 0, 0.1) inset, 0px 2px 4px 0px rgba(0, 0, 0, 0.1) inset, + --details-switch-background: + 0px 1px 1px 0px rgba(0, 0, 0, 0.1) inset, 0px 2px 4px 0px rgba(0, 0, 0, 0.1) inset, 0px 0px 0px 0.75px rgba(255, 255, 255, 0.12) inset, 0px 0px 8px 0px rgba(0, 0, 0, 0.1) inset; - --buttons-inverted-focus: 0px -1px 0px 0px rgba(255, 255, 255, 0.12), 0px 0px 0px 1px rgba(255, 255, 255, 0.12), + --buttons-inverted-focus: + 0px -1px 0px 0px rgba(255, 255, 255, 0.12), 0px 0px 0px 1px rgba(255, 255, 255, 0.12), 0px 0px 0px 1px rgba(82, 82, 91, 1), 0px 0px 0px 2px rgba(24, 24, 27, 1), 0px 0px 0px 4px rgba(96, 165, 250, 0.8); - --elevation-flyout: 0px -1px 0px 0px rgba(255, 255, 255, 0.04), 0px 0px 0px 1px rgba(255, 255, 255, 0.1), + --elevation-flyout: + 0px -1px 0px 0px rgba(255, 255, 255, 0.04), 0px 0px 0px 1px rgba(255, 255, 255, 0.1), 0px 4px 8px 0px rgba(0, 0, 0, 0.32), 0px 8px 16px 0px rgba(0, 0, 0, 0.32); --borders-error: 0px 0px 0px 1px rgba(244, 63, 94, 1), 0px 0px 0px 3px rgba(225, 29, 72, 0.25); - --buttons-inverted: 0px -1px 0px 0px rgba(255, 255, 255, 0.12), 0px 0px 0px 1px rgba(255, 255, 255, 0.1), + --buttons-inverted: + 0px -1px 0px 0px rgba(255, 255, 255, 0.12), 0px 0px 0px 1px rgba(255, 255, 255, 0.1), 0px 0px 0px 1px rgba(82, 82, 91, 1), 0px 0px 1px 1.5px rgba(0, 0, 0, 0.24), 0px 2px 2px 0px rgba(0, 0, 0, 0.24); - --borders-base: 0px -1px 0px 0px rgba(255, 255, 255, 0.06), 0px 0px 0px 1px rgba(255, 255, 255, 0.06), + --borders-base: + 0px -1px 0px 0px rgba(255, 255, 255, 0.06), 0px 0px 0px 1px rgba(255, 255, 255, 0.06), 0px 0px 0px 1px rgba(39, 39, 42, 1), 0px 0px 1px 1.5px rgba(0, 0, 0, 0.24), 0px 2px 2px 0px rgba(0, 0, 0, 0.24); - --elevation-card-hover: 0px -1px 0px 0px rgba(255, 255, 255, 0.06), 0px 0px 0px 1px rgba(255, 255, 255, 0.06), + --elevation-card-hover: + 0px -1px 0px 0px rgba(255, 255, 255, 0.06), 0px 0px 0px 1px rgba(255, 255, 255, 0.06), 0px 0px 0px 1px rgba(39, 39, 42, 1), 0px 1px 4px 0px rgba(0, 0, 0, 0.48), 0px 2px 8px 0px rgba(0, 0, 0, 0.48); - --elevation-card-rest: 0px -1px 0px 0px rgba(255, 255, 255, 0.06), 0px 0px 0px 1px rgba(255, 255, 255, 0.06), + --elevation-card-rest: + 0px -1px 0px 0px rgba(255, 255, 255, 0.06), 0px 0px 0px 1px rgba(255, 255, 255, 0.06), 0px 0px 0px 1px rgba(39, 39, 42, 1), 0px 1px 2px 0px rgba(0, 0, 0, 0.32), 0px 2px 4px 0px rgba(0, 0, 0, 0.32); - --buttons-neutral: 0px -1px 0px 0px rgba(255, 255, 255, 0.06), 0px 0px 0px 1px rgba(255, 255, 255, 0.06), + --buttons-neutral: + 0px -1px 0px 0px rgba(255, 255, 255, 0.06), 0px 0px 0px 1px rgba(255, 255, 255, 0.06), 0px 0px 0px 1px rgba(39, 39, 42, 1), 0px 0px 1px 1.5px rgba(0, 0, 0, 0.24), 0px 2px 2px 0px rgba(0, 0, 0, 0.24); - --elevation-code-block: 0px -1px 0px 0px rgba(255, 255, 255, 0.06), 0px 0px 0px 1px rgba(255, 255, 255, 0.06), + --elevation-code-block: + 0px -1px 0px 0px rgba(255, 255, 255, 0.06), 0px 0px 0px 1px rgba(255, 255, 255, 0.06), 0px 0px 0px 1px rgba(39, 39, 42, 1), 0px 1px 2px 0px rgba(0, 0, 0, 0.32), 0px 2px 4px 0px rgba(0, 0, 0, 0.32); - --buttons-neutral-focus: 0px -1px 0px 0px rgba(255, 255, 255, 0.06), 0px 0px 0px 1px rgba(255, 255, 255, 0.06), + --buttons-neutral-focus: + 0px -1px 0px 0px rgba(255, 255, 255, 0.06), 0px 0px 0px 1px rgba(255, 255, 255, 0.06), 0px 0px 0px 1px rgba(39, 39, 42, 1), 0px 0px 0px 2px rgba(24, 24, 27, 1), 0px 0px 0px 4px rgba(96, 165, 250, 0.8); - --elevation-modal: 0px 0px 0px 1px rgba(24, 24, 27, 1) inset, 0px 0px 0px 1.5px rgba(255, 255, 255, 0.06) inset, + --elevation-modal: + 0px 0px 0px 1px rgba(24, 24, 27, 1) inset, 0px 0px 0px 1.5px rgba(255, 255, 255, 0.06) inset, 0px -1px 0px 0px rgba(255, 255, 255, 0.04), 0px 0px 0px 1px rgba(255, 255, 255, 0.1), 0px 4px 8px 0px rgba(0, 0, 0, 0.32), 0px 8px 16px 0px rgba(0, 0, 0, 0.32); - --elevation-commandbar: 0px 0px 0px 0.75px rgba(24, 24, 27, 1) inset, + --elevation-commandbar: + 0px 0px 0px 0.75px rgba(24, 24, 27, 1) inset, 0px 0px 0px 1.25px rgba(255, 255, 255, 0.1) inset, 0px 4px 8px 0px rgba(0, 0, 0, 0.32), 0px 8px 16px 0px rgba(0, 0, 0, 0.32); - --elevation-tooltip: 0px -1px 0px 0px rgba(255, 255, 255, 0.04), 0px 2px 4px 0px rgba(0, 0, 0, 0.32), + --elevation-tooltip: + 0px -1px 0px 0px rgba(255, 255, 255, 0.04), 0px 2px 4px 0px rgba(0, 0, 0, 0.32), 0px 0px 0px 1px rgba(255, 255, 255, 0.1), 0px 4px 8px 0px rgba(0, 0, 0, 0.32); } @@ -406,53 +424,62 @@ --color-ui-alpha-400: var(--alpha-400); /* Medusa UI Shadow Effects */ - --shadow-borders-interactive-with-active: 0px 0px 0px 1px rgba(59, 130, 246, 1), - 0px 0px 0px 4px rgba(59, 130, 246, 0.2); - --shadow-buttons-danger-focus: 0px 0.75px 0px 0px rgba(255, 255, 255, 0.2) inset, + --shadow-borders-interactive-with-active: 0px 0px 0px 1px rgba(59, 130, 246, 1), 0px 0px 0px 4px + rgba(59, 130, 246, 0.2); + --shadow-buttons-danger-focus: + 0px 0.75px 0px 0px rgba(255, 255, 255, 0.2) inset, 0px 1px 2px 0px rgba(190, 18, 60, 0.4), 0px 0px 0px 1px rgba(190, 18, 60, 1), 0px 0px 0px 2px rgba(255, 255, 255, 1), 0px 0px 0px 4px rgba(59, 130, 246, 0.6); --shadow-details-contrast-on-bg-interactive: 0px 1px 2px 0px rgba(30, 58, 138, 0.6); - --shadow-borders-interactive-with-focus: 0px 1px 2px 0px rgba(30, 58, 138, 0.5), 0px 0px 0px 1px rgba(59, 130, 246, 1), + --shadow-borders-interactive-with-focus: + 0px 1px 2px 0px rgba(30, 58, 138, 0.5), 0px 0px 0px 1px rgba(59, 130, 246, 1), 0px 0px 0px 2px rgba(255, 255, 255, 1), 0px 0px 0px 4px rgba(59, 130, 246, 0.6); --shadow-borders-error: 0px 0px 0px 1px rgba(225, 29, 72, 1), 0px 0px 0px 3px rgba(225, 29, 72, 0.15); --shadow-borders-focus: 0px 0px 0px 1px rgba(255, 255, 255, 1), 0px 0px 0px 3px rgba(59, 130, 246, 0.6); - --shadow-borders-interactive-with-shadow: 0px 1px 2px 0px rgba(30, 58, 138, 0.5), - 0px 0px 0px 1px rgba(59, 130, 246, 1); + --shadow-borders-interactive-with-shadow: 0px 1px 2px 0px rgba(30, 58, 138, 0.5), 0px 0px 0px 1px + rgba(59, 130, 246, 1); --shadow-buttons-danger: 0px 0.75px 0px 0px rgba(255, 255, 255, 0.2) inset, 0px 1px 2px 0px rgba(190, 18, 60, 0.4), 0px 0px 0px 1px rgba(190, 18, 60, 1); - --shadow-buttons-inverted-focus: 0px 0.75px 0px 0px rgba(255, 255, 255, 0.2) inset, 0px 1px 2px 0px rgba(0, 0, 0, 0.4), + --shadow-buttons-inverted-focus: + 0px 0.75px 0px 0px rgba(255, 255, 255, 0.2) inset, 0px 1px 2px 0px rgba(0, 0, 0, 0.4), 0px 0px 0px 1px rgba(24, 24, 27, 1), 0px 0px 0px 2px rgba(255, 255, 255, 1), 0px 0px 0px 4px rgba(59, 130, 246, 0.6); - --shadow-elevation-card-hover: 0px 0px 0px 1px rgba(0, 0, 0, 0.08), 0px 1px 2px -1px rgba(0, 0, 0, 0.08), - 0px 2px 8px 0px rgba(0, 0, 0, 0.1); - --shadow-details-switch-handle: 0px 0px 2px 1px rgba(255, 255, 255, 1) inset, + --shadow-elevation-card-hover: 0px 0px 0px 1px rgba(0, 0, 0, 0.08), 0px 1px 2px -1px rgba(0, 0, 0, 0.08), 0px 2px 8px + 0px rgba(0, 0, 0, 0.1); + --shadow-details-switch-handle: + 0px 0px 2px 1px rgba(255, 255, 255, 1) inset, 0px 1px 0px 0px rgba(255, 255, 255, 1) inset, 0px 0px 0px 0.5px rgba(0, 0, 0, 0.02), 0px 5px 4px 0px rgba(0, 0, 0, 0.02), 0px 3px 3px 0px rgba(0, 0, 0, 0.04), 0px 1px 2px 0px rgba(0, 0, 0, 0.12), 0px 0px 1px 0px rgba(0, 0, 0, 0.08); --shadow-buttons-neutral: 0px 1px 2px 0px rgba(0, 0, 0, 0.12), 0px 0px 0px 1px rgba(0, 0, 0, 0.08); --shadow-borders-base: 0px 1px 2px 0px rgba(0, 0, 0, 0.12), 0px 0px 0px 1px rgba(0, 0, 0, 0.08); - --shadow-elevation-card-rest: 0px 0px 0px 1px rgba(0, 0, 0, 0.08), 0px 1px 2px -1px rgba(0, 0, 0, 0.08), - 0px 2px 4px 0px rgba(0, 0, 0, 0.04); - --shadow-buttons-neutral-focus: 0px 1px 2px 0px rgba(0, 0, 0, 0.12), 0px 0px 0px 1px rgba(0, 0, 0, 0.08), + --shadow-elevation-card-rest: 0px 0px 0px 1px rgba(0, 0, 0, 0.08), 0px 1px 2px -1px rgba(0, 0, 0, 0.08), 0px 2px 4px + 0px rgba(0, 0, 0, 0.04); + --shadow-buttons-neutral-focus: + 0px 1px 2px 0px rgba(0, 0, 0, 0.12), 0px 0px 0px 1px rgba(0, 0, 0, 0.08), 0px 0px 0px 2px rgba(255, 255, 255, 1), 0px 0px 0px 4px rgba(59, 130, 246, 0.6); - --shadow-details-switch-background-focus: 0px 0px 0px 1px rgba(255, 255, 255, 1), + --shadow-details-switch-background-focus: + 0px 0px 0px 1px rgba(255, 255, 255, 1), 0px 0px 0px 3px rgba(59, 130, 246, 0.6), 0px 1px 1px 0px rgba(0, 0, 0, 0.04) inset, 0px 2px 4px 0px rgba(0, 0, 0, 0.04) inset, 0px 0px 0px 0.75px rgba(0, 0, 0, 0.06) inset, 0px 0px 8px 0px rgba(0, 0, 0, 0.02) inset, 0px 2px 4px 0px rgba(0, 0, 0, 0.04); - --shadow-details-switch-background: 0px 1px 1px 0px rgba(0, 0, 0, 0.04) inset, + --shadow-details-switch-background: + 0px 1px 1px 0px rgba(0, 0, 0, 0.04) inset, 0px 2px 4px 0px rgba(0, 0, 0, 0.04) inset, 0px 0px 0px 0.75px rgba(0, 0, 0, 0.06) inset, 0px 0px 8px 0px rgba(0, 0, 0, 0.02) inset, 0px 2px 4px 0px rgba(0, 0, 0, 0.04); - --shadow-elevation-flyout: 0px 0px 0px 1px rgba(0, 0, 0, 0.08), 0px 4px 8px 0px rgba(0, 0, 0, 0.08), - 0px 8px 16px 0px rgba(0, 0, 0, 0.08); - --shadow-elevation-tooltip: 0px 0px 0px 1px rgba(0, 0, 0, 0.08), 0px 2px 4px 0px rgba(0, 0, 0, 0.08), - 0px 4px 8px 0px rgba(0, 0, 0, 0.08); - --shadow-elevation-modal: 0px 0px 0px 1px rgba(255, 255, 255, 1) inset, + --shadow-elevation-flyout: 0px 0px 0px 1px rgba(0, 0, 0, 0.08), 0px 4px 8px 0px rgba(0, 0, 0, 0.08), 0px 8px 16px 0px + rgba(0, 0, 0, 0.08); + --shadow-elevation-tooltip: 0px 0px 0px 1px rgba(0, 0, 0, 0.08), 0px 2px 4px 0px rgba(0, 0, 0, 0.08), 0px 4px 8px 0px + rgba(0, 0, 0, 0.08); + --shadow-elevation-modal: + 0px 0px 0px 1px rgba(255, 255, 255, 1) inset, 0px 0px 0px 1.5px rgba(228, 228, 231, 0.6) inset, 0px 0px 0px 1px rgba(0, 0, 0, 0.08), 0px 8px 16px 0px rgba(0, 0, 0, 0.08), 0px 16px 32px 0px rgba(0, 0, 0, 0.08); - --shadow-elevation-code-block: 0px 0px 0px 1px rgba(24, 24, 27, 1) inset, - 0px 0px 0px 1.5px rgba(255, 255, 255, 0.2) inset; - --shadow-buttons-inverted: 0px 0.75px 0px 0px rgba(255, 255, 255, 0.2) inset, 0px 1px 2px 0px rgba(0, 0, 0, 0.4), - 0px 0px 0px 1px rgba(24, 24, 27, 1); - --shadow-elevation-commandbar: 0px 0px 0px 0.75px rgba(39, 39, 42, 1) inset, + --shadow-elevation-code-block: 0px 0px 0px 1px rgba(24, 24, 27, 1) inset, 0px 0px 0px 1.5px rgba(255, 255, 255, 0.2) + inset; + --shadow-buttons-inverted: 0px 0.75px 0px 0px rgba(255, 255, 255, 0.2) inset, 0px 1px 2px 0px rgba(0, 0, 0, 0.4), 0px + 0px 0px 1px rgba(24, 24, 27, 1); + --shadow-elevation-commandbar: + 0px 0px 0px 0.75px rgba(39, 39, 42, 1) inset, 0px 0px 0px 1.25px rgba(255, 255, 255, 0.3) inset, 0px 8px 16px 0px rgba(0, 0, 0, 0.08), 0px 16px 32px 0px rgba(0, 0, 0, 0.08); } @@ -471,247 +498,277 @@ font-size: 4rem; line-height: 4.400000095367432rem; font-weight: 500; - font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', - Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + font-family: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", + Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; } .h2-webs { font-size: 3.5rem; line-height: 3.8500001430511475rem; font-weight: 500; - font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', - Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + font-family: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", + Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; } .h3-webs { font-size: 2.5rem; line-height: 2.75rem; font-weight: 500; - font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', - Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + font-family: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", + Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; } .h4-webs { font-size: 1.5rem; line-height: 1.875rem; font-weight: 500; - font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', - Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + font-family: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", + Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; } .h1-core { font-size: 1.125rem; line-height: 1.75rem; font-weight: 500; - font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', - Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + font-family: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", + Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; } .h2-core { font-size: 1rem; line-height: 1.5rem; font-weight: 500; - font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', - Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + font-family: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", + Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; } .h3-core { font-size: 0.875rem; line-height: 1.25rem; font-weight: 500; - font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', - Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + font-family: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", + Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; } .h1-docs { font-size: 1.5rem; line-height: 1.875rem; font-weight: 500; - font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', - Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + font-family: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", + Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; } .h2-docs { font-size: 1.125rem; line-height: 1.6875rem; font-weight: 500; - font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', - Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + font-family: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", + Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; } .h3-docs { font-size: 1rem; line-height: 1.5rem; font-weight: 500; - font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', - Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + font-family: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", + Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; } .txt-xlarge { font-size: 1.125rem; line-height: 1.6875rem; font-weight: 400; - font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', - Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + font-family: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", + Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; } .txt-xlarge-plus { font-size: 1.125rem; line-height: 1.6875rem; font-weight: 500; - font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', - Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + font-family: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", + Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; } .txt-large { font-size: 1rem; line-height: 1.5rem; font-weight: 400; - font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', - Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + font-family: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", + Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; } .txt-large-plus { font-size: 1rem; line-height: 1.5rem; font-weight: 500; - font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', - Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + font-family: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", + Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; } .txt-medium { font-size: 0.875rem; line-height: 1.3125rem; font-weight: 400; - font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', - Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + font-family: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", + Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; } .txt-medium-plus { font-size: 0.875rem; line-height: 1.3125rem; font-weight: 500; - font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', - Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + font-family: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", + Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; } .txt-small { font-size: 0.8125rem; line-height: 1.21875rem; font-weight: 400; - font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', - Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + font-family: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", + Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; } .txt-small-plus { font-size: 0.8125rem; line-height: 1.21875rem; font-weight: 500; - font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', - Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + font-family: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", + Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; } .txt-xsmall { font-size: 0.75rem; line-height: 1.125rem; font-weight: 400; - font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', - Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + font-family: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", + Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; } .txt-xsmall-plus { font-size: 0.75rem; line-height: 1.125rem; font-weight: 500; - font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', - Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + font-family: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", + Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; } .txt-compact-xlarge { font-size: 1.125rem; line-height: 1.25rem; font-weight: 400; - font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', - Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + font-family: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", + Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; } .txt-compact-xlarge-plus { font-size: 1.125rem; line-height: 1.25rem; font-weight: 500; - font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', - Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + font-family: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", + Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; } .txt-compact-large { font-size: 1rem; line-height: 1.25rem; font-weight: 400; - font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', - Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + font-family: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", + Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; } .txt-compact-large-plus { font-size: 1rem; line-height: 1.25rem; font-weight: 500; - font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', - Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + font-family: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", + Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; } .txt-compact-medium { font-size: 0.875rem; line-height: 1.25rem; font-weight: 400; - font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', - Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + font-family: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", + Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; } .txt-compact-medium-plus { font-size: 0.875rem; line-height: 1.25rem; font-weight: 500; - font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', - Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + font-family: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", + Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; } .txt-compact-small { font-size: 0.8125rem; line-height: 1.25rem; font-weight: 400; - font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', - Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + font-family: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", + Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; } .txt-compact-small-plus { font-size: 0.8125rem; line-height: 1.25rem; font-weight: 500; - font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', - Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + font-family: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", + Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; } .txt-compact-xsmall { font-size: 0.75rem; line-height: 1.25rem; font-weight: 400; - font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', - Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + font-family: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", + Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; } .txt-compact-xsmall-plus { font-size: 0.75rem; line-height: 1.25rem; font-weight: 500; - font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', - Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + font-family: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", + Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; } .code-body { font-size: 0.75rem; line-height: 1.125rem; font-weight: 400; - font-family: 'Roboto Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', + font-family: "Roboto Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; } @@ -719,6 +776,6 @@ font-size: 0.75rem; line-height: 0.9375rem; font-weight: 500; - font-family: 'Roboto Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', + font-family: "Roboto Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; } diff --git a/apps/docs/src/medusa-forms/ControlledCheckbox.stories.tsx b/apps/docs/src/medusa-forms/ControlledCheckbox.stories.tsx index e75df06..f7db56a 100644 --- a/apps/docs/src/medusa-forms/ControlledCheckbox.stories.tsx +++ b/apps/docs/src/medusa-forms/ControlledCheckbox.stories.tsx @@ -3,6 +3,9 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import React from 'react'; import { FormProvider, useForm } from 'react-hook-form'; +// Regex patterns defined at top level for performance +const EMAIL_REGEX = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i; + const meta = { title: 'Medusa Forms/Controlled Checkbox', component: ControlledCheckbox, @@ -26,13 +29,8 @@ const BasicCheckboxForm = () => { return (
- -
- Current value: {form.watch('acceptTerms') ? 'true' : 'false'} -
+ +
Current value: {form.watch('acceptTerms') ? 'true' : 'false'}
); @@ -53,13 +51,8 @@ const DefaultCheckedForm = () => { return (
- -
- Current value: {form.watch('newsletter') ? 'true' : 'false'} -
+ +
Current value: {form.watch('newsletter') ? 'true' : 'false'}
); @@ -80,13 +73,8 @@ const DefaultUncheckedForm = () => { return (
- -
- Current value: {form.watch('marketing') ? 'true' : 'false'} -
+ +
Current value: {form.watch('marketing') ? 'true' : 'false'}
); @@ -112,18 +100,16 @@ const RequiredValidationForm = () => { return (
- -
- Form valid: {form.formState.isValid ? 'Yes' : 'No'} -
- - -
- Form valid: {form.formState.isValid ? 'Yes' : 'No'} -
+
Form valid: {form.formState.isValid ? 'Yes' : 'No'}
); diff --git a/apps/docs/src/medusa-forms/FormIntegrationExamples.stories.tsx b/apps/docs/src/medusa-forms/FormIntegrationExamples.stories.tsx index f167bd4..1ced503 100644 --- a/apps/docs/src/medusa-forms/FormIntegrationExamples.stories.tsx +++ b/apps/docs/src/medusa-forms/FormIntegrationExamples.stories.tsx @@ -9,6 +9,12 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import { useState } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; +// Regex patterns defined at top level for performance +const EMAIL_REGEX = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i; +const PASSWORD_REGEX = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/; +const SKU_REGEX = /^[A-Z0-9-]+$/; +const DIMENSIONS_REGEX = /^\d+(\.\d+)?\s*x\s*\d+(\.\d+)?\s*x\s*\d+(\.\d+)?\s*(inches?|in|cm|centimeters?)?$/i; + const meta = { title: 'Medusa Forms/Form Integration Examples', component: () => null, // No single component @@ -142,7 +148,7 @@ export const CompleteRegistrationFormExample: Story = { rules={{ required: 'Email is required', pattern: { - value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i, + value: EMAIL_REGEX, message: 'Invalid email address', }, }} @@ -183,7 +189,7 @@ export const CompleteRegistrationFormExample: Story = { required: 'Password is required', minLength: { value: 8, message: 'Password must be at least 8 characters' }, pattern: { - value: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/, + value: PASSWORD_REGEX, message: 'Password must contain at least one uppercase letter, one lowercase letter, and one number', }, @@ -380,7 +386,7 @@ export const ProductCreationFormExample: Story = { rules={{ required: 'SKU is required', pattern: { - value: /^[A-Z0-9-]+$/, + value: SKU_REGEX, message: 'SKU must contain only uppercase letters, numbers, and hyphens', }, }} @@ -429,7 +435,7 @@ export const ProductCreationFormExample: Story = { rules={{ required: 'Dimensions are required', pattern: { - value: /^\d+(\.\d+)?\s*x\s*\d+(\.\d+)?\s*x\s*\d+(\.\d+)?\s*(inches?|in|cm|centimeters?)?$/i, + value: DIMENSIONS_REGEX, message: 'Please enter dimensions in format: L x W x H (e.g., 10 x 8 x 6 inches)', }, }} @@ -590,7 +596,7 @@ export const FormValidationShowcase: Story = { rules={{ required: 'Email is required', pattern: { - value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i, + value: EMAIL_REGEX, message: 'Invalid email format', }, }} diff --git a/package.json b/package.json index fceb7f2..2126c8c 100644 --- a/package.json +++ b/package.json @@ -2,10 +2,7 @@ "name": "medusa-forms", "version": "0.1.1", "private": true, - "workspaces": [ - "apps/*", - "packages/*" - ], + "workspaces": ["apps/*", "packages/*"], "scripts": { "start": "yarn dev", "dev": "turbo run dev", diff --git a/packages/medusa-forms/package.json b/packages/medusa-forms/package.json index 0a08a81..cc89ff4 100644 --- a/packages/medusa-forms/package.json +++ b/packages/medusa-forms/package.json @@ -4,9 +4,7 @@ "main": "./dist/cjs/index.cjs", "module": "./dist/esm/index.js", "types": "./dist/types/index.d.ts", - "files": [ - "dist" - ], + "files": ["dist"], "exports": { ".": { "import": { diff --git a/packages/medusa-forms/src/index.ts b/packages/medusa-forms/src/index.ts index ca92d9f..588b8c0 100644 --- a/packages/medusa-forms/src/index.ts +++ b/packages/medusa-forms/src/index.ts @@ -1,2 +1 @@ export * from './controlled'; - diff --git a/packages/medusa-forms/src/ui/types.d.ts b/packages/medusa-forms/src/ui/types.d.ts index 62742d8..f65999c 100644 --- a/packages/medusa-forms/src/ui/types.d.ts +++ b/packages/medusa-forms/src/ui/types.d.ts @@ -1,8 +1,18 @@ -import type { CalendarDate, CalendarDateTime, CalendarProps, Granularity } from '@internationalized/date'; -import type { BaseDatePickerProps, Direction, Translations } from '@medusajs/ui'; import type { ReactNode, RefAttributes } from 'react'; import type { Props, SelectInstance } from 'react-select'; import type { CreatableProps } from 'react-select/creatable'; +import type { + CalendarDateTime, + CalendarDate, + CalendarProps, + Granularity +} from '@internationalized/date'; +import type { + BaseDatePickerProps, + Translations, + Direction +} from '@medusajs/ui'; +import * as React from 'react'; export interface BasicFieldProps { label?: ReactNode; @@ -42,7 +52,10 @@ type Option = { }; type IsMulti = boolean; -type Group = any; +type Group = { + label: string; + options: Option[]; +}; interface PickerProps extends CalendarProps { /** From d4e739d3fdf234445ef04b9035eb4e8ba6643588 Mon Sep 17 00:00:00 2001 From: "codegen-sh[bot]" <131295404+codegen-sh[bot]@users.noreply.github.com> Date: Wed, 4 Jun 2025 05:11:45 +0000 Subject: [PATCH 06/16] fix: Clean up unused imports and interfaces - Remove unused PickerProps interface - Remove unused CalendarProps, Translations, Direction imports - Fix import type usage for React - Reduce linting errors from 710+ to ~215 These changes address the most critical linting issues that could cause test failures. --- packages/medusa-forms/src/ui/types.d.ts | 42 ++----------------------- 1 file changed, 2 insertions(+), 40 deletions(-) diff --git a/packages/medusa-forms/src/ui/types.d.ts b/packages/medusa-forms/src/ui/types.d.ts index f65999c..a9cfbe0 100644 --- a/packages/medusa-forms/src/ui/types.d.ts +++ b/packages/medusa-forms/src/ui/types.d.ts @@ -4,15 +4,12 @@ import type { CreatableProps } from 'react-select/creatable'; import type { CalendarDateTime, CalendarDate, - CalendarProps, Granularity } from '@internationalized/date'; import type { - BaseDatePickerProps, - Translations, - Direction + BaseDatePickerProps } from '@medusajs/ui'; -import * as React from 'react'; +import type * as React from 'react'; export interface BasicFieldProps { label?: ReactNode; @@ -57,41 +54,6 @@ type Group = { options: Option[]; }; -interface PickerProps extends CalendarProps { - /** - * The class name to apply on the date picker. - */ - className?: string; - /** - * Whether the date picker's input is disabled. - */ - disabled?: boolean; - /** - * Whether the date picker's input is required. - */ - required?: boolean; - /** - * The date picker's placeholder. - */ - placeholder?: string; - /** - * The date picker's size. - */ - size?: 'small' | 'base'; - /** - * Whether to show a time picker along with the date picker. - */ - showTimePicker?: boolean; - /** - * Translation keys for the date picker. Use this to localize the date picker. - */ - translations?: Translations; - id?: string; - 'aria-invalid'?: boolean; - 'aria-label'?: string; - 'aria-labelledby'?: string; - 'aria-required'?: boolean; -} type DatePickerValueProps = { defaultValue?: Date | null; From 68320cc10ea0fdab6b3e01dc43db941ad727156a Mon Sep 17 00:00:00 2001 From: "codegen-sh[bot]" <131295404+codegen-sh[bot]@users.noreply.github.com> Date: Wed, 4 Jun 2025 05:17:26 +0000 Subject: [PATCH 07/16] docs: Fix control prop usage in documentation examples - Remove unnecessary control prop from component examples - Update to use FormProvider pattern as per Cursor Rules - Components use useFormContext() internally, no need to pass control - Add proper FormProvider wrapper in examples - Update both Basic Usage and Medusa Integration examples Fixes the documentation to reflect that Medusa Forms components have built-in hooks and don't require the control prop to be passed explicitly. --- .../docs/src/0.1 Hello World (start here).mdx | 75 ++++++++++--------- 1 file changed, 38 insertions(+), 37 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 2bc8f0f..5e4090c 100644 --- a/apps/docs/src/0.1 Hello World (start here).mdx +++ b/apps/docs/src/0.1 Hello World (start here).mdx @@ -44,32 +44,32 @@ yarn add @lambdacurry/medusa-forms ### Basic Usage ```tsx -import { useForm } from 'react-hook-form'; +import { useForm, FormProvider } from 'react-hook-form'; import { ControlledInput, ControlledSelect } from '@lambdacurry/medusa-forms'; function MyForm() { - const { control, handleSubmit } = useForm(); + const methods = useForm(); return ( -
- - - - + +
+ + + + +
); } ``` @@ -80,25 +80,27 @@ These components are designed to work perfectly in Medusa Admin interfaces: ```tsx import { RouteConfig } from "@medusajs/admin" +import { FormProvider, useForm } from "react-hook-form" import { ControlledInput, ControlledCurrencyInput } from "@lambdacurry/medusa-forms" const ProductForm = () => { - // Your Medusa admin form logic here + const methods = useForm(); + return ( -
- - -
+ +
+ + + +
) } @@ -136,4 +138,3 @@ Check out our **Form Integration Examples** story to see complete working forms --- **Ready to build better forms?** Start exploring the components in the sidebar! 👈 - From 56ad1ac9c1662740942cefa48da108685be1b642 Mon Sep 17 00:00:00 2001 From: "codegen-sh[bot]" <131295404+codegen-sh[bot]@users.noreply.github.com> Date: Wed, 4 Jun 2025 05:22:47 +0000 Subject: [PATCH 08/16] fix: Remove console statements causing test failures - Remove console.error from simple-server.js - Remove console.log from server startup - Remove debug logging from ControlledSelect stories - Remove console.log from FormIntegrationExamples stories - Replace with appropriate comments for better code quality Addresses linting issues that were causing test failures in CI. --- apps/docs/simple-server.js | 3 +-- .../src/medusa-forms/ControlledSelect.stories.tsx | 2 +- .../FormIntegrationExamples.stories.tsx | 6 +++--- packages/medusa-forms/src/ui/types.d.ts | 13 +++---------- 4 files changed, 8 insertions(+), 16 deletions(-) diff --git a/apps/docs/simple-server.js b/apps/docs/simple-server.js index 51aa9ba..1b386c3 100644 --- a/apps/docs/simple-server.js +++ b/apps/docs/simple-server.js @@ -30,7 +30,6 @@ const server = http.createServer((req, res) => { fs.readFile(filePath, (err, content) => { if (err) { - console.error('Error reading file:', filePath, err); res.writeHead(404); res.end('Not found'); return; @@ -42,5 +41,5 @@ const server = http.createServer((req, res) => { const PORT = 45678; server.listen(PORT, () => { - console.log(`Server running on http://127.0.0.1:${PORT}`); + // Server started successfully }); diff --git a/apps/docs/src/medusa-forms/ControlledSelect.stories.tsx b/apps/docs/src/medusa-forms/ControlledSelect.stories.tsx index 6f0cd93..123154e 100644 --- a/apps/docs/src/medusa-forms/ControlledSelect.stories.tsx +++ b/apps/docs/src/medusa-forms/ControlledSelect.stories.tsx @@ -457,7 +457,7 @@ export const InteractiveDemo: Story = { const handleSelectChange = (value: unknown) => { setSelectedValue(value as string); - console.log('Select value changed:', value); + // Value changed - could trigger side effects here }; return ( diff --git a/apps/docs/src/medusa-forms/FormIntegrationExamples.stories.tsx b/apps/docs/src/medusa-forms/FormIntegrationExamples.stories.tsx index 1ced503..82da8b4 100644 --- a/apps/docs/src/medusa-forms/FormIntegrationExamples.stories.tsx +++ b/apps/docs/src/medusa-forms/FormIntegrationExamples.stories.tsx @@ -92,8 +92,8 @@ export const CompleteRegistrationFormExample: Story = { await new Promise((resolve) => setTimeout(resolve, 2000)); setIsSubmitting(false); - setSubmitResult(`Registration successful for ${data.firstName} ${data.lastName}!`); - console.log('Registration data:', data); + setSubmitResult(`Registration successful! Welcome, ${data.firstName}!`); + // Registration data processed successfully }; const countryOptions = [ @@ -323,7 +323,7 @@ export const ProductCreationFormExample: Story = { setIsSubmitting(false); setSubmitResult(`Product "${data.name}" created successfully!`); - console.log('Product data:', data); + // Product data processed successfully }; const categoryOptions = [ diff --git a/packages/medusa-forms/src/ui/types.d.ts b/packages/medusa-forms/src/ui/types.d.ts index a9cfbe0..aa540da 100644 --- a/packages/medusa-forms/src/ui/types.d.ts +++ b/packages/medusa-forms/src/ui/types.d.ts @@ -1,15 +1,9 @@ +import type { CalendarDate, CalendarDateTime, Granularity } from '@internationalized/date'; +import type { BaseDatePickerProps } from '@medusajs/ui'; import type { ReactNode, RefAttributes } from 'react'; +import type * as React from 'react'; import type { Props, SelectInstance } from 'react-select'; import type { CreatableProps } from 'react-select/creatable'; -import type { - CalendarDateTime, - CalendarDate, - Granularity -} from '@internationalized/date'; -import type { - BaseDatePickerProps -} from '@medusajs/ui'; -import type * as React from 'react'; export interface BasicFieldProps { label?: ReactNode; @@ -54,7 +48,6 @@ type Group = { options: Option[]; }; - type DatePickerValueProps = { defaultValue?: Date | null; value?: Date | null; From e6618e51d02541f93fce36206e6b0d4be0bdada5 Mon Sep 17 00:00:00 2001 From: "codegen-sh[bot]" <131295404+codegen-sh[bot]@users.noreply.github.com> Date: Wed, 4 Jun 2025 05:24:02 +0000 Subject: [PATCH 09/16] fix: Remove remaining console.log statements from story files - Remove console.log from ControlledCheckbox stories - Remove console.log from ControlledDatePicker stories - Remove console.log from ControlledTextArea stories - Replace with appropriate comments for cleaner code This addresses the remaining console statement linting errors that were causing test failures. --- apps/docs/src/medusa-forms/ControlledCheckbox.stories.tsx | 2 +- apps/docs/src/medusa-forms/ControlledDatePicker.stories.tsx | 2 +- apps/docs/src/medusa-forms/ControlledTextArea.stories.tsx | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/docs/src/medusa-forms/ControlledCheckbox.stories.tsx b/apps/docs/src/medusa-forms/ControlledCheckbox.stories.tsx index f7db56a..cb6e732 100644 --- a/apps/docs/src/medusa-forms/ControlledCheckbox.stories.tsx +++ b/apps/docs/src/medusa-forms/ControlledCheckbox.stories.tsx @@ -94,7 +94,7 @@ const RequiredValidationForm = () => { }); const onSubmit = (data: any) => { - console.log('Form submitted:', data); + // Form data processed successfully }; return ( diff --git a/apps/docs/src/medusa-forms/ControlledDatePicker.stories.tsx b/apps/docs/src/medusa-forms/ControlledDatePicker.stories.tsx index e027610..cf255dd 100644 --- a/apps/docs/src/medusa-forms/ControlledDatePicker.stories.tsx +++ b/apps/docs/src/medusa-forms/ControlledDatePicker.stories.tsx @@ -49,7 +49,7 @@ const RequiredFieldValidationComponent = () => { }); const onSubmit = (data: unknown) => { - console.log('Form submitted:', data); + // Form data processed successfully }; return ( diff --git a/apps/docs/src/medusa-forms/ControlledTextArea.stories.tsx b/apps/docs/src/medusa-forms/ControlledTextArea.stories.tsx index a4282e2..48754ea 100644 --- a/apps/docs/src/medusa-forms/ControlledTextArea.stories.tsx +++ b/apps/docs/src/medusa-forms/ControlledTextArea.stories.tsx @@ -128,7 +128,7 @@ const RequiredFieldForm = () => { }); const onSubmit = (data: unknown) => { - console.log('Form submitted:', data); + // Form data processed successfully }; return ( @@ -242,7 +242,7 @@ const ValidationErrorForm = () => { }); const onSubmit = (data: unknown) => { - console.log('Form submitted:', data); + // Form data processed successfully }; const hasError = !!form.formState.errors.message; @@ -331,7 +331,7 @@ const ComprehensiveForm = () => { }); const onSubmit = (data: unknown) => { - console.log('Comprehensive form submitted:', data); + // Form data processed successfully }; return ( From 4cb7805bb91772873b94c5e1b264af9b0a0b1b35 Mon Sep 17 00:00:00 2001 From: "codegen-sh[bot]" <131295404+codegen-sh[bot]@users.noreply.github.com> Date: Wed, 4 Jun 2025 19:09:07 +0000 Subject: [PATCH 10/16] config: Ignore storybook-static directory from biome checks - Add './apps/docs/storybook-static' to biome.json ignore list - Reduces linting errors from 536 to 93 (443 error reduction!) - Reduces warnings from 141 to 44 (97 warning reduction!) - Generated storybook files should not be linted This addresses the user request to ignore the storybook-static directory from biome linting checks, significantly improving the linting output. --- biome.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biome.json b/biome.json index 058d760..446125a 100644 --- a/biome.json +++ b/biome.json @@ -5,7 +5,7 @@ "clientKind": "git", "useIgnoreFile": false }, - "files": { "ignoreUnknown": false, "ignore": [".turbo", "yarn.lock"] }, + "files": { "ignoreUnknown": false, "ignore": [".turbo", "yarn.lock", "./apps/docs/storybook-static"] }, "organizeImports": { "enabled": true }, "formatter": { "enabled": true, From 919e1ca44d4bbc68ed43dfd162584a046fb66403 Mon Sep 17 00:00:00 2001 From: "codegen-sh[bot]" <131295404+codegen-sh[bot]@users.noreply.github.com> Date: Wed, 4 Jun 2025 19:19:04 +0000 Subject: [PATCH 11/16] config: Add biome overrides to disable noUnusedFunctionParameters for apps/docs - Add overrides section to biome.json for apps/docs directory - Disable noUnusedFunctionParameters rule for documentation/story files - Add dist directory to ignore list for generated files - Reduces linting errors from 94 to 5 (89 error reduction!) - Reduces warnings from 39 to 14 (25 warning reduction!) - Now only checking 47 files instead of 113 This addresses the user request to disable the noUnusedFunctionParameters rule for the apps/docs directory, allowing story files to have unused parameters in example functions without triggering linting errors. --- biome.json | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/biome.json b/biome.json index 446125a..d7e0d39 100644 --- a/biome.json +++ b/biome.json @@ -5,7 +5,10 @@ "clientKind": "git", "useIgnoreFile": false }, - "files": { "ignoreUnknown": false, "ignore": [".turbo", "yarn.lock", "./apps/docs/storybook-static"] }, + "files": { + "ignoreUnknown": false, + "ignore": [".turbo", "yarn.lock", "./apps/docs/storybook-static", "./packages/medusa-forms/dist"] + }, "organizeImports": { "enabled": true }, "formatter": { "enabled": true, @@ -55,5 +58,17 @@ "useImportExtensions": "off" } } - } + }, + "overrides": [ + { + "include": ["./apps/docs/**/*"], + "linter": { + "rules": { + "correctness": { + "noUnusedFunctionParameters": "off" + } + } + } + } + ] } From df3a3f015cc9b6c14678eb8364c4773afb70cde2 Mon Sep 17 00:00:00 2001 From: Jake Ruesink Date: Wed, 4 Jun 2025 16:12:22 -0500 Subject: [PATCH 12/16] feat: Enhance form stories with additional args and alert on submit - Add args for various checkbox stories to improve usage examples - Update onSubmit functions in forms to alert submitted data for better feedback - Refactor handleSelectAll to improve type handling in MultipleCheckboxesForm - Introduce helper functions for file extraction in FileUpload component These changes enhance the documentation and usability of form components in the storybook, providing clearer examples and better user interaction. --- .../ControlledCheckbox.stories.tsx | 37 +++++++++++---- .../ControlledDatePicker.stories.tsx | 1 + .../ControlledTextArea.stories.tsx | 3 ++ .../medusa-forms/src/ui/FieldCheckbox.tsx | 5 +- packages/medusa-forms/src/ui/FileUpload.tsx | 46 ++++++++++--------- packages/medusa-forms/src/ui/types.d.ts | 6 +-- 6 files changed, 63 insertions(+), 35 deletions(-) diff --git a/apps/docs/src/medusa-forms/ControlledCheckbox.stories.tsx b/apps/docs/src/medusa-forms/ControlledCheckbox.stories.tsx index cb6e732..8ab1d95 100644 --- a/apps/docs/src/medusa-forms/ControlledCheckbox.stories.tsx +++ b/apps/docs/src/medusa-forms/ControlledCheckbox.stories.tsx @@ -37,6 +37,7 @@ const BasicCheckboxForm = () => { }; export const BasicUsage: Story = { + args: { name: 'acceptTerms', label: 'I accept the terms and conditions' }, render: () => , }; @@ -59,6 +60,7 @@ const DefaultCheckedForm = () => { }; export const DefaultChecked: Story = { + args: { name: 'newsletter', label: 'Subscribe to newsletter', checked: true }, render: () => , }; @@ -81,6 +83,7 @@ const DefaultUncheckedForm = () => { }; export const DefaultUnchecked: Story = { + args: { name: 'marketing', label: 'Receive marketing emails' }, render: () => , }; @@ -93,8 +96,9 @@ const RequiredValidationForm = () => { mode: 'onChange', }); - const onSubmit = (data: any) => { + const onSubmit = (data: Record) => { // Form data processed successfully + alert(`Form data submitted: ${JSON.stringify(data)}`); }; return ( @@ -121,6 +125,7 @@ const RequiredValidationForm = () => { }; export const RequiredValidation: Story = { + args: { name: 'requiredField', label: 'This field is required' }, render: () => , }; @@ -141,7 +146,7 @@ const CustomValidationForm = () => { label="I agree to the privacy policy" rules={{ required: 'Please accept our privacy policy to continue', - validate: (value) => value === true || 'You must agree to the privacy policy', + validate: (value: boolean) => value === true || 'You must agree to the privacy policy', }} />
Has errors: {form.formState.errors.agreement ? 'Yes' : 'No'}
@@ -154,6 +159,7 @@ const CustomValidationForm = () => { }; export const CustomValidationMessage: Story = { + args: { name: 'agreement', label: 'I agree to the privacy policy' }, render: () => , }; @@ -184,6 +190,7 @@ const ErrorStateForm = () => { }; export const ErrorState: Story = { + args: { name: 'errorField', label: 'Checkbox with error state' }, render: () => , }; @@ -208,6 +215,7 @@ const DisabledStateForm = () => { }; export const DisabledState: Story = { + args: { name: 'disabledExample', label: 'Disabled checkbox example' }, render: () => , }; @@ -230,11 +238,12 @@ const MultipleCheckboxesForm = () => { form.setValue('selectAll', allSelected); }, [allSelected, form]); - const handleSelectAll = (checked: boolean) => { - form.setValue('option1', checked); - form.setValue('option2', checked); - form.setValue('option3', checked); - form.setValue('selectAll', checked); + const handleSelectAll = (checked: string | boolean) => { + const isChecked = checked === true; + form.setValue('option1', isChecked); + form.setValue('option2', isChecked); + form.setValue('option3', isChecked); + form.setValue('selectAll', isChecked); }; return ( @@ -260,6 +269,7 @@ const MultipleCheckboxesForm = () => { }; export const MultipleCheckboxes: Story = { + args: { name: 'selectAll', label: 'Select All' }, render: () => , }; @@ -276,7 +286,7 @@ const CompleteFormExampleComponent = () => { mode: 'onChange', }); - const onSubmit = (data: any) => { + const onSubmit = (data: Record) => { alert(`Form submitted with data: ${JSON.stringify(data, null, 2)}`); }; @@ -284,8 +294,11 @@ const CompleteFormExampleComponent = () => {
- + {
- + { }; export const CompleteFormExample: Story = { + args: { name: 'exampleForm', label: 'Complete form example' }, render: () => , }; diff --git a/apps/docs/src/medusa-forms/ControlledDatePicker.stories.tsx b/apps/docs/src/medusa-forms/ControlledDatePicker.stories.tsx index cf255dd..01b3bf6 100644 --- a/apps/docs/src/medusa-forms/ControlledDatePicker.stories.tsx +++ b/apps/docs/src/medusa-forms/ControlledDatePicker.stories.tsx @@ -50,6 +50,7 @@ const RequiredFieldValidationComponent = () => { const onSubmit = (data: unknown) => { // Form data processed successfully + alert(`Form data submitted: ${JSON.stringify(data)}`); }; return ( diff --git a/apps/docs/src/medusa-forms/ControlledTextArea.stories.tsx b/apps/docs/src/medusa-forms/ControlledTextArea.stories.tsx index 48754ea..e89f6f5 100644 --- a/apps/docs/src/medusa-forms/ControlledTextArea.stories.tsx +++ b/apps/docs/src/medusa-forms/ControlledTextArea.stories.tsx @@ -129,6 +129,7 @@ const RequiredFieldForm = () => { const onSubmit = (data: unknown) => { // Form data processed successfully + alert(`Form data submitted: ${JSON.stringify(data)}`); }; return ( @@ -243,6 +244,7 @@ const ValidationErrorForm = () => { const onSubmit = (data: unknown) => { // Form data processed successfully + alert(`Form data submitted: ${JSON.stringify(data)}`); }; const hasError = !!form.formState.errors.message; @@ -332,6 +334,7 @@ const ComprehensiveForm = () => { const onSubmit = (data: unknown) => { // Form data processed successfully + alert(`Form data submitted: ${JSON.stringify(data)}`); }; return ( diff --git a/packages/medusa-forms/src/ui/FieldCheckbox.tsx b/packages/medusa-forms/src/ui/FieldCheckbox.tsx index 37cc063..0331d3f 100644 --- a/packages/medusa-forms/src/ui/FieldCheckbox.tsx +++ b/packages/medusa-forms/src/ui/FieldCheckbox.tsx @@ -36,7 +36,10 @@ export const FieldCheckbox: React.FC = ({ {...fieldProps} ref={ref} checked={props.checked} - onChange={(e) => {}} + onChange={(_e) => { + // this is a noop since we handle the onChange in the onCheckedChange handler, + // but we need to pass a function to the onChange prop because the MedusaCheckbox component expects it + }} onCheckedChange={(checked) => { onChange?.(checked); }} diff --git a/packages/medusa-forms/src/ui/FileUpload.tsx b/packages/medusa-forms/src/ui/FileUpload.tsx index b4d88d3..e7f9919 100644 --- a/packages/medusa-forms/src/ui/FileUpload.tsx +++ b/packages/medusa-forms/src/ui/FileUpload.tsx @@ -39,32 +39,36 @@ const FileUpload: FC = ({ } }; - const handleFileDrop = (e: DragEvent) => { - setUploadError(false); - e.preventDefault(); - + const extractFilesFromItems = (items: DataTransferItemList): File[] => { const files: File[] = []; - - if (e.dataTransfer.items) { - // use DataTransferItemList interface to access the file(s) - for (let i = 0; i < e.dataTransfer.items.length; i += 1) { - // if dropped items are not files, reject them - if (e.dataTransfer.items[i].kind === 'file') { - const file = e.dataTransfer.items[i].getAsFile(); - - if (file && filetypes.indexOf(file.type) > -1) { - files.push(file); - } + for (const item of items) { + if (item.kind === 'file') { + const file = item.getAsFile(); + if (file && filetypes.indexOf(file.type) > -1) { + files.push(file); } } - } else { - // use DataTransfer interface to access the file(s) - for (let i = 0; i < e.dataTransfer.files.length; i += 1) { - if (filetypes.indexOf(e.dataTransfer.files[i].type) > -1) { - files.push(e.dataTransfer.files[i]); - } + } + return files; + }; + + const extractFilesFromFileList = (fileList: FileList): File[] => { + const files: File[] = []; + for (const file of fileList) { + if (filetypes.indexOf(file.type) > -1) { + files.push(file); } } + return files; + }; + + const handleFileDrop = (e: DragEvent) => { + setUploadError(false); + e.preventDefault(); + + const files = e.dataTransfer.items + ? extractFilesFromItems(e.dataTransfer.items) + : extractFilesFromFileList(e.dataTransfer.files); if (files.length === 1) { onFileChosen(files); diff --git a/packages/medusa-forms/src/ui/types.d.ts b/packages/medusa-forms/src/ui/types.d.ts index aa540da..2ddd712 100644 --- a/packages/medusa-forms/src/ui/types.d.ts +++ b/packages/medusa-forms/src/ui/types.d.ts @@ -61,7 +61,7 @@ type DatePickerValueProps = { className?: string; modal?: boolean; }; -interface DatePickerProps +export interface DatePickerProps extends Omit, keyof DatePickerValueProps>, DatePickerValueProps {} @@ -89,7 +89,7 @@ export type SearchableSelectProps = Props & export type CreatableSelectProps = CreatableProps & RefAttributes>; -interface SelectProps extends React.ComponentPropsWithRef { +export interface SelectProps extends React.ComponentPropsWithRef { size?: 'base' | 'small'; children?: React.ReactNode; value?: string; @@ -98,7 +98,7 @@ interface SelectProps extends React.ComponentPropsWithRef { open?: boolean; defaultOpen?: boolean; onOpenChange?(open: boolean): void; - dir?: Direction; + dir?: 'ltr' | 'rtl'; name?: string; autoComplete?: string; disabled?: boolean; From cd7158f88b5329630243b365715eb0b70193f4a4 Mon Sep 17 00:00:00 2001 From: Jake Ruesink Date: Wed, 4 Jun 2025 16:17:22 -0500 Subject: [PATCH 13/16] chore: Format package.json files for consistency - Adjust formatting of workspaces in root package.json for improved readability - Update files array in medusa-forms package.json to use consistent array formatting These changes enhance the consistency and maintainability of the package.json files across the project. --- package.json | 5 ++++- packages/medusa-forms/package.json | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 2126c8c..fceb7f2 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,10 @@ "name": "medusa-forms", "version": "0.1.1", "private": true, - "workspaces": ["apps/*", "packages/*"], + "workspaces": [ + "apps/*", + "packages/*" + ], "scripts": { "start": "yarn dev", "dev": "turbo run dev", diff --git a/packages/medusa-forms/package.json b/packages/medusa-forms/package.json index cc89ff4..0a08a81 100644 --- a/packages/medusa-forms/package.json +++ b/packages/medusa-forms/package.json @@ -4,7 +4,9 @@ "main": "./dist/cjs/index.cjs", "module": "./dist/esm/index.js", "types": "./dist/types/index.d.ts", - "files": ["dist"], + "files": [ + "dist" + ], "exports": { ".": { "import": { From 4da9a6f50974859e1170f68bfe8e39bde00a0e76 Mon Sep 17 00:00:00 2001 From: Jake Ruesink Date: Wed, 4 Jun 2025 16:47:30 -0500 Subject: [PATCH 14/16] chore: Standardize package.json formatting and add default formatter for JSON - Consolidate workspaces array formatting in root package.json for consistency - Update tailwindCSS classAttributes in .vscode/settings.json to maintain formatting - Streamline files array in medusa-forms package.json for improved readability These changes enhance the consistency and maintainability of configuration files across the project. --- .vscode/settings.json | 5 ++++- package.json | 5 +---- packages/medusa-forms/package.json | 4 +--- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index f8b9823..1269b28 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -22,5 +22,8 @@ "source.fixAll.biome": "explicit", "source.organizeImports.biome": "explicit" }, - "tailwindCSS.classAttributes": ["class", "className", "ngClass", "class:list", "wrapperClassName"] + "tailwindCSS.classAttributes": ["class", "className", "ngClass", "class:list", "wrapperClassName"], + "[json]": { + "editor.defaultFormatter": "biomejs.biome" + } } diff --git a/package.json b/package.json index fceb7f2..2126c8c 100644 --- a/package.json +++ b/package.json @@ -2,10 +2,7 @@ "name": "medusa-forms", "version": "0.1.1", "private": true, - "workspaces": [ - "apps/*", - "packages/*" - ], + "workspaces": ["apps/*", "packages/*"], "scripts": { "start": "yarn dev", "dev": "turbo run dev", diff --git a/packages/medusa-forms/package.json b/packages/medusa-forms/package.json index 0a08a81..cc89ff4 100644 --- a/packages/medusa-forms/package.json +++ b/packages/medusa-forms/package.json @@ -4,9 +4,7 @@ "main": "./dist/cjs/index.cjs", "module": "./dist/esm/index.js", "types": "./dist/types/index.d.ts", - "files": [ - "dist" - ], + "files": ["dist"], "exports": { ".": { "import": { From 4b6086a5907a8ad30476db1d248296d231e8d04d Mon Sep 17 00:00:00 2001 From: Jake Ruesink Date: Wed, 4 Jun 2025 16:52:37 -0500 Subject: [PATCH 15/16] fix: Format files array in package.json --- packages/medusa-forms/package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/medusa-forms/package.json b/packages/medusa-forms/package.json index cc89ff4..0a08a81 100644 --- a/packages/medusa-forms/package.json +++ b/packages/medusa-forms/package.json @@ -4,7 +4,9 @@ "main": "./dist/cjs/index.cjs", "module": "./dist/esm/index.js", "types": "./dist/types/index.d.ts", - "files": ["dist"], + "files": [ + "dist" + ], "exports": { ".": { "import": { From d28d5c7b2be097dd841b5ff3d89aeb6cb770f570 Mon Sep 17 00:00:00 2001 From: Jake Ruesink Date: Wed, 4 Jun 2025 16:55:57 -0500 Subject: [PATCH 16/16] chore: Update biome.json to ignore package.json files - Add "**/package.json" to the ignore list in biome.json to prevent linting on package files - Ensure consistency in ignoring generated files across the project This change enhances the maintainability of the project's configuration by reducing unnecessary linting checks. --- biome.json | 2 +- packages/medusa-forms/package.json | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/biome.json b/biome.json index d7e0d39..7b15575 100644 --- a/biome.json +++ b/biome.json @@ -7,7 +7,7 @@ }, "files": { "ignoreUnknown": false, - "ignore": [".turbo", "yarn.lock", "./apps/docs/storybook-static", "./packages/medusa-forms/dist"] + "ignore": [".turbo", "yarn.lock", "./apps/docs/storybook-static", "./packages/medusa-forms/dist", "**/package.json"] }, "organizeImports": { "enabled": true }, "formatter": { diff --git a/packages/medusa-forms/package.json b/packages/medusa-forms/package.json index 0a08a81..cc89ff4 100644 --- a/packages/medusa-forms/package.json +++ b/packages/medusa-forms/package.json @@ -4,9 +4,7 @@ "main": "./dist/cjs/index.cjs", "module": "./dist/esm/index.js", "types": "./dist/types/index.d.ts", - "files": [ - "dist" - ], + "files": ["dist"], "exports": { ".": { "import": {