Skip to content

Conversation

@dwene
Copy link
Contributor

@dwene dwene commented May 30, 2025

Summary by CodeRabbit

  • New Features

    • Introduced a new Medusa Forms package with a comprehensive set of controlled React form components, UI components, and supporting types.
    • Added Storybook stories and documentation for all Medusa Forms components, including advanced form integration and validation examples.
    • Integrated Medusa UI design tokens and typography utilities for consistent styling in both light and dark modes.
    • Provided file upload, color input, and advanced select, date picker, and currency input components.
  • Bug Fixes

    • Updated all relevant imports to use the latest react-router package, improving compatibility and consistency.
  • Documentation

    • Added extensive architectural and usage documentation for Medusa Forms components and Storybook story patterns.
    • Updated project documentation to reflect the new Medusa Forms package and its integration into the monorepo.
  • Chores

    • Upgraded Storybook, React, and related dependencies to latest versions.
    • Updated Yarn and package manager configurations.
    • Added and updated TypeScript and Vite configurations for new and existing packages.

@bolt-new-by-stackblitz
Copy link

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

@coderabbitai
Copy link

coderabbitai bot commented May 30, 2025

Walkthrough

This update introduces a new Medusa Forms package with a full suite of controlled form components and UI primitives, integrated with react-hook-form and @medusajs/ui. It adds comprehensive documentation, Storybook stories, and project configuration changes to support Medusa Forms alongside existing Remix Hook Form components. Multiple dependencies, configurations, and import paths are updated accordingly.

Changes

File(s) / Path(s) Change Summary
.cursor/rules/form-component-patterns.mdc, .cursor/rules/monorepo-organization.mdc,
.cursor/rules/storybook-testing.mdc
Documentation updated to clarify scope, add references to Medusa Forms, update project structure, glob patterns, import examples, and peer dependency versions.
.cursor/rules/medusa-forms-patterns.mdc, .cursor/rules/medusa-stories-patterns.mdc New documentation files added: rules and guidelines for Medusa Forms components and their Storybook stories, covering architecture, validation, accessibility, performance, and anti-patterns.
.yarnrc.yml, package.json Updated Yarn version to 4.9.1 and specified custom Yarn binary path.
apps/docs/.storybook/main.ts, apps/docs/.storybook/preview.ts Storybook config updated: switched to @storybook/addon-docs, changed type imports to @storybook/react-vite.
apps/docs/package.json Upgraded Storybook and React dependencies; added Medusa Forms, react-hook-form, and related packages; removed unused dependencies.
apps/docs/tsconfig.json, apps/docs/vite.config.mjs Updated TypeScript and Vite configs: added aliases and paths for Medusa Forms, removed external build settings for react-router-dom.
apps/docs/src/main.css Integrated Medusa UI design tokens, color variables, and comprehensive typography utility classes for consistent styling.
apps/docs/src/examples/root-example.tsx,
apps/docs/src/lib/storybook/react-router-stub.tsx
Switched React Router imports from react-router-dom to react-router; modernized router stubbing with createRoutesStub.
apps/docs/src/medusa-forms/*.stories.tsx,
apps/docs/src/medusa-forms/FormIntegrationExamples.stories.tsx
New Storybook stories for Medusa Forms controlled components (Checkbox, CurrencyInput, DatePicker, Input, Select, TextArea) and comprehensive form integration examples, demonstrating validation, controlled state, and UI features.
apps/docs/src/remix-hook-form/*.stories.tsx Updated Storybook type and test utility imports to use @storybook/react-vite and storybook/test. Minor functional update: in textarea.stories.tsx, switched to <fetcher.Form>.
packages/components/package.json,
packages/components/vite.config.ts
Updated remix-hook-form and react-router versions; removed react-router-dom dependency and externalization.
packages/components/src/remix-hook-form/data-table-router-form.tsx,
.../use-data-table-url-state.ts,
.../data-table-column-header.tsx,
.../data-table-hooks.ts,
.../data-table-pagination.tsx,
.../data-table-toolbar.tsx
Switched React Router imports from react-router-dom to react-router; minor formatting and dependency array fixes.
packages/components/src/ui/button.tsx Changed React import to type-only; simplified return statement.
packages/medusa-forms/package.json,
tsconfig.json,
vite.config.ts
New package for Medusa Forms: includes build scripts, dependencies, TypeScript and Vite configs, and export structure.
packages/medusa-forms/src/controlled/ Added new controlled form components: Checkbox, CurrencyInput, DatePicker, Input, Select, TextArea, and index re-export.
packages/medusa-forms/src/ui/ Added new UI primitives: Button, ColorInput, CurrencyInput, DatePicker, Error, FieldCheckbox, FieldGroup, FieldWrapper, FileUpload, Input, Label, Select, TextArea, and supporting types. Includes index re-export.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant Storybook
  participant FormProvider
  participant ControlledComponent
  participant UIComponent
  participant ReactHookForm

  User->>Storybook: Interacts with Medusa Forms story
  Storybook->>FormProvider: Wraps story with form context
  FormProvider->>ControlledComponent: Provides form state/validation
  ControlledComponent->>ReactHookForm: Registers field via Controller
  ControlledComponent->>UIComponent: Renders UI with value, error, handlers
  UIComponent->>User: Displays input, error, label, etc.
  User->>UIComponent: Inputs value or triggers change
  UIComponent->>ControlledComponent: Calls onChange/onBlur
  ControlledComponent->>ReactHookForm: Updates form state/validation
  ReactHookForm->>ControlledComponent: Provides updated value/error
  ControlledComponent->>UIComponent: Rerenders with new props
Loading

Suggested reviewers

  • dwene

Poem

In the warren of forms, new fields sprout and grow,
Medusa and Remix—together they flow.
With tokens and stories, the docs now delight,
Controlled and UI, all shining so bright.
The rabbit hops in, with CSS and code,
To celebrate teamwork on this winding road! 🐇✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b132ab4 and 0cb684f.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (8)
  • packages/medusa-forms/package.json (1 hunks)
  • packages/medusa-forms/src/ui/CurrencyInput.tsx (1 hunks)
  • packages/medusa-forms/src/ui/DatePicker.tsx (1 hunks)
  • packages/medusa-forms/src/ui/FieldWrapper.tsx (1 hunks)
  • packages/medusa-forms/src/ui/Input.tsx (1 hunks)
  • packages/medusa-forms/src/ui/Select.tsx (1 hunks)
  • packages/medusa-forms/src/ui/TextArea.tsx (1 hunks)
  • packages/medusa-forms/src/ui/types.d.ts (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • packages/medusa-forms/src/ui/Select.tsx
  • packages/medusa-forms/src/ui/TextArea.tsx
🚧 Files skipped from review as they are similar to previous changes (6)
  • packages/medusa-forms/src/ui/DatePicker.tsx
  • packages/medusa-forms/src/ui/Input.tsx
  • packages/medusa-forms/src/ui/CurrencyInput.tsx
  • packages/medusa-forms/src/ui/FieldWrapper.tsx
  • packages/medusa-forms/package.json
  • packages/medusa-forms/src/ui/types.d.ts
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: test
✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

- Updated remix-hook-form to version 7.0.1 across multiple package.json files.
- Added new dependencies: @hookform/error-message and @hookform/resolvers in apps/docs.
- Enhanced tsconfig paths for medusa-forms to include src and lib directories.
- Refactored ControlledInput component to use ComponentProps for better type safety.
- Removed unused index.ts file from controlled directory in medusa-forms.
- Improved error handling in Error component for better readability and performance.
- Updated main.css for consistent Tailwind CSS imports and added Medusa UI tokens.
@github-actions
Copy link
Contributor

github-actions bot commented May 30, 2025

📝 Storybook Preview: View Storybook

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.

jaruesink added 4 commits May 30, 2025 17:59
- Removed deprecated dependencies and updated Storybook addons to version 9.0.1 across multiple package.json files.
- Refactored imports in Storybook stories to use '@storybook/react-vite' for improved compatibility.
- Updated routing imports from 'react-router-dom' to 'react-router' for consistency across components.
- Cleaned up external dependencies in Vite configuration for better performance.
- Enhanced example components to align with the latest routing practices.
- Removed @medusajs/ui-preset and related dependencies from package.json and yarn.lock.
- Cleaned up Vite configuration by removing unnecessary external dependencies.
- Updated Storybook stories to ensure consistent import statements and improved component usage.
- Updated various dependencies in yarn.lock for better performance and compatibility.
- Adjusted muted-foreground color in main.css for improved accessibility and design consistency.
cursoragent and others added 18 commits May 31, 2025 02:15
- Maintained React 19 patterns in all form components (no forwardRef usage)
- Preserved all other changes from medusa-forms branch
- Components now use FC<Props> with destructured ref parameter
- All form components maintain consistent React 19 ref handling pattern
…omponents

- Replaced standard React imports with type-only imports across multiple form components for improved type safety and clarity.
- Ensured consistency in the usage of functional components with TypeScript interfaces.
- Created directory structure for controlled component stories
- Added README with implementation plan and template pattern
- Based on medusa-forms-upgrades branch as requested
- Add BasicUsage story with simple textarea and react-hook-form integration
- Add CharacterLimits story with character count validation and display
- Add RequiredFieldValidation story with error states and custom messages
- Add AutoResizeFunctionality story with dynamic height adjustment
- Add ValidationErrorStates story with various error scenarios
- Add ComprehensiveExample story showing multiple textareas in a form
- Follow established pattern from ControlledInput.stories.tsx
- Use react-hook-form directly with FormProvider and useForm
- Include proper validation with zod schemas
- Demonstrate real-world usage patterns

Addresses LC-245: Create ControlledTextArea Storybook Stories
- Complete Registration Form with multi-step validation
- Product Creation Form demonstrating all controlled components
- Form Validation Showcase with various validation scenarios
- Real-world usage patterns with error handling and submit states
- Comprehensive documentation for each example

Components integrated:
- ControlledInput (text, email, password, number)
- ControlledCheckbox (terms, preferences, status flags)
- ControlledSelect (country, category selection)
- ControlledDatePicker (birth date, launch date with constraints)
- ControlledCurrencyInput (pricing with validation)
- ControlledTextArea (descriptions, tags)

Validation features:
- Real-time validation with react-hook-form
- Complex business rules (age verification, price ranges)
- Format validation (email, SKU patterns, dimensions)
- Cross-field validation (password confirmation)
- Submit handling with loading states and success feedback
- ControlledCurrencyInput: 4 story variants (USD/EUR/GBP, validation, error handling, different currency codes)
- ControlledDatePicker: 5 story variants (basic, validation, formats, disabled dates, constraints)
- Both follow react-hook-form pattern with comprehensive validation
- Merged from agents #27943 and #27941 work on LC-244 and LC-242
- Comprehensive implementation with 8 story variants
- BasicUsage, DefaultChecked/Unchecked, RequiredValidation, CustomValidation
- ErrorState, DisabledState, MultipleCheckboxes, CompleteFormExample
- Follows react-hook-form pattern with proper boolean value handling
- Includes advanced features like select-all functionality

Merged from agent #27942's work on LC-243
- Add 10 comprehensive story variants for ControlledSelect component
- Cover basic single select, default values, validation, loading states
- Include custom option rendering using Select compound components
- Add disabled state, error state, and size variants
- Include complex form integration and interactive demo
- Follow established pattern from ControlledInput.stories.tsx
- Use react-hook-form directly without react-router dependencies

Note: Multi-select and searchable/creatable variants not included
as they are not currently supported by the base Select component
- Fixed duplicate identifier conflicts in ControlledSelect.stories.tsx:
  - Renamed component function ComplexFormIntegration to ComplexFormIntegrationComponent
  - Renamed story exports to avoid conflicts: RequiredValidation → SelectRequiredValidation, DisabledState → SelectDisabledState, ErrorState → SelectErrorState
- Fixed duplicate identifier conflicts in ControlledCheckbox.stories.tsx:
  - Renamed component function CompleteFormExample to CompleteFormExampleComponent
- Fixed incorrect import path in ControlledCheckbox.stories.tsx:
  - Changed from '@lambdacurry/medusa-forms/controlled' to '@lambdacurry/medusa-forms/controlled/ControlledCheckbox'

These changes resolve the Storybook build failures caused by TypeScript identifier conflicts and import path issues.
…controlled-components-documentation-stories-and
…ries

- Updated ControlledCurrencyInput stories to include currency symbol and code as props for better flexibility.
- Refactored validation schemas to use string types for price inputs, ensuring consistent handling of numeric values.
- Improved FormIntegrationExamples by adding missing imports and refining form handling logic for better readability.
- Enhanced error handling and validation messages across various form components, ensuring a more robust user experience.
…on from @medusajs/ui

- Replaced native button elements with the Button component for improved styling and functionality.
- Updated button properties to utilize isLoading and variant attributes for better user experience.
- Ensured consistent usage of the Button component across different forms, enhancing code maintainability.
codegen-sh bot and others added 6 commits May 31, 2025 04:41
- Add medusa-forms-patterns.mdc for component development patterns
- Add medusa-stories-patterns.mdc for Storybook story patterns
- Focus on @medusajs/ui integration and react-hook-form Controller patterns
- Complement existing form-component-patterns.mdc with Medusa-specific guidance
- Include validation, error handling, and accessibility requirements
- Provide comprehensive story examples and best practices
- Update monorepo-organization.mdc with proper globs and new package structure
- Add medusa-forms package and directory structure documentation
- Update storybook-testing.mdc to include react-hook-form and @medusajs/ui
- Add medusa-forms story directory to project structure
- Update form-component-patterns.mdc to clarify scope (Remix Hook Form only)
- Add note directing to medusa-forms-patterns.mdc for Medusa components
- Refactored ControlledCurrencyInput, ControlledDatePicker, ControlledSelect, and ControlledTextArea stories to include necessary props and improve structure.
- Added missing args for story configurations to ensure proper rendering and documentation.
- Updated validation rules and error handling for better user experience across various form components.
- Removed outdated README for controlled components as the documentation is now integrated within the stories.
- Improved button usage in forms by utilizing the Button component from @medusajs/ui for consistent styling and functionality.
- Updated import statement for the Button component to use the correct casing, ensuring consistent styling and functionality across stories.
- Renamed internal prop types to Controlled*Props for ControlledCheckbox, ControlledCurrencyInput, ControlledDatePicker, ControlledInput, ControlledSelect, and ControlledTextArea for clarity and consistency.
- Updated import statements for UI components to align with new prop type names.
- Enhanced type definitions to improve type safety and maintainability across controlled components.
…rsion

- Upgraded Storybook-related packages to version 9.0.4 for improved features and bug fixes.
- Updated react-hook-form to version 7.57.0 and react-remove-scroll to version 2.7.1 for better compatibility and performance.
- Incremented medusa-forms package version to 0.2.0 to reflect recent changes.
@jaruesink jaruesink marked this pull request as ready for review June 2, 2025 04:28
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 40

🔭 Outside diff range comments (1)
packages/components/src/remix-hook-form/use-data-table-url-state.ts (1)

27-68: ⚠️ Potential issue

Critical: Stale closure bug in useCallback dependency array.

Removing urlState from the dependency array creates a stale closure issue. The callback captures the initial urlState and won't see updates when URL parameters change, leading to incorrect state merging.

The biome-ignore comment suggests this was intentionally done, but it introduces a bug. Apply this fix:

-  // biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
   const setUrlState = useCallback(
     (newState: Partial<DataTableRouterState>) => {
-      const updatedState = { ...urlState, ...newState };
+      // Parse current URL state fresh to avoid stale closure
+      const currentUrlState: DataTableRouterState = {
+        search: dataTableRouterParsers.search.parse(searchParams.get('search')),
+        filters: dataTableRouterParsers.filters.parse(searchParams.get('filters')),
+        page: dataTableRouterParsers.page.parse(searchParams.get('page')),
+        pageSize: dataTableRouterParsers.pageSize.parse(searchParams.get('pageSize')),
+        sortField: dataTableRouterParsers.sortField.parse(searchParams.get('sortField')),
+        sortOrder: dataTableRouterParsers.sortOrder.parse(searchParams.get('sortOrder')),
+      };
+      const updatedState = { ...currentUrlState, ...newState };
       const newParams = new URLSearchParams();
       
       // ... rest of the function remains the same
     },
-    [setSearchParams],
+    [searchParams, setSearchParams],
   );
♻️ Duplicate comments (1)
apps/docs/src/medusa-forms/FormIntegrationExamples.stories.tsx (1)

609-610: Same parsing concern as earlier

This has the same currency parsing issue mentioned in the earlier comment.

🧹 Nitpick comments (19)
packages/components/src/ui/data-table/data-table-pagination.tsx (1)

13-14: Consistent parsing of URL parameters
Switching to Number.parseInt(..., 10) is a good practice for clarity and radix safety. Consider also handling NaN edge cases if non-numeric values might appear.

.cursor/rules/form-component-patterns.mdc (1)

3-3: Clarify repository reference in metadata
The description metadata still mentions the lambda-curry/forms repo. Consider updating it to reference the monorepo context or packages/components/ directly.

packages/medusa-forms/src/ui/FieldGroup.tsx (1)

4-6: Define FieldGroup props via interface
Inline prop typing works, but extracting a FieldGroupProps interface would improve reusability and readability. Adding a JSDoc comment or displayName could also enhance maintainability.

packages/medusa-forms/src/ui/Label.tsx (1)

14-27: Enhance tooltip accessibility.

The tooltip icon wrapper is a <div>, which isn’t keyboard-focusable. Consider using a <span> or <button> with tabIndex={0} and role="button" to ensure screen-reader and keyboard users can access it. For example:

-    {tooltip && (
-      <Tooltip content={tooltip}>
-        <div className="flex items-center justify-center ml-1">
-          <InformationCircle className="-scale-75" />
-        </div>
-      </Tooltip>
-    )}
+    {tooltip && (
+      <Tooltip content={tooltip}>
+        <span
+          role="button"
+          tabIndex={0}
+          className="flex items-center justify-center ml-1 focus:outline-none"
+        >
+          <InformationCircle className="scale-75" />
+        </span>
+      </Tooltip>
+    )}

This change retains the visual styling and adds keyboard accessibility.

packages/medusa-forms/src/ui/ColorInput.tsx (1)

16-34: Verify accessibility and consider enhancements.

The dual input approach (color picker + text input) provides good user experience. However, there are a few considerations:

  1. Accessibility: Both inputs should have proper aria-label or aria-labelledby attributes
  2. Color validation: The text input should validate hex color format
  3. Keyboard navigation: Consider adding proper tab order

Consider adding validation and accessibility improvements:

  return (
    <div className="flex items-center p-2">
      <Input
        type="color"
        value={selectedColor}
        onChange={handleChange}
        className="w-7 h-7 p-0 border-0 mr-4 rounded-sm"
        onBlur={onBlur}
+       aria-label="Color picker"
      />
      <Input
        type="text"
        placeholder="#a232a4"
        value={selectedColor}
        onChange={handleChange}
        className="flex-grow"
        onKeyDown={onKeyDown}
+       aria-label="Hex color code"
+       pattern="^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$"
      />
    </div>
  );
packages/medusa-forms/src/ui/Error.tsx (1)

47-63: Component logic is correct with minor accessibility improvement needed.

The error handling logic correctly handles null cases and uses the ErrorMessage component appropriately.

Add accessibility improvement for better screen reader support:

export const FieldError = ({ errors, name, className }: Props) => {
  if (!(errors && name)) return null;

  return (
    <ErrorMessage
      name={name}
      errors={errors}
      render={({ message, messages }) => {
        return (
-         <div className={clsx('txt-compact-xsmall !leading-snug mt-2 text-red-500', className)}>
+         <div className={clsx('txt-compact-xsmall !leading-snug mt-2 text-red-500', className)} role="alert" aria-live="polite">
            {messages ? <MultipleMessages messages={messages} /> : <p>{message}</p>}
          </div>
        );
      }}
    />
  );
};

This ensures screen readers announce validation errors when they appear.

apps/docs/src/medusa-forms/ControlledInput.stories.tsx (1)

33-40: Consider enhancing the story for better demonstration.

While the basic story works, consider adding additional stories to showcase validation, error states, and different input configurations for better documentation value.

// Consider adding these additional stories:
export const WithValidation: Story = {
  // Story with validation rules
};

export const WithError: Story = {
  // Story showing error state
};

export const Disabled: Story = {
  // Story showing disabled state
};
packages/medusa-forms/src/controlled/ControlledInput.tsx (3)

12-17: Simplify the type definition to avoid redundancy.

The type intersection has redundant parts that make it unnecessarily complex.

export type ControlledInputProps<T extends FieldValues> = InputProps &
-  Omit<ControllerProps, 'render'> & {
+  Omit<ControllerProps<T>, 'render'> & {
    name: Path<T>;
    rules?: Omit<RegisterOptions<T, Path<T>>, 'disabled' | 'valueAsNumber' | 'valueAsDate' | 'setValueAs'>;
-  } & ComponentProps<typeof Input> &
-  Omit<ControllerProps<T>, 'render'>;
+  };

The ComponentProps<typeof Input> is redundant since InputProps already includes the necessary props, and we're duplicating the ControllerProps omission.


34-34: Remove unnecessary type assertion.

The type assertion is unnecessary since the rules prop is already properly typed in the component props.

-      rules={rules as Omit<RegisterOptions<T, Path<T>>, 'disabled' | 'valueAsNumber' | 'valueAsDate' | 'setValueAs'>}
+      rules={rules}

36-40: Remove redundant prop forwarding.

The explicit labelClassName prop forwarding is redundant since it's already included in the spread operator.

        <Input
          {...field}
          {...props}
-          labelClassName={props.labelClassName}
          formErrors={errors}
          onChange={(evt) => {
packages/medusa-forms/src/controlled/ControlledCurrencyInput.tsx (1)

28-28: Simplify the rules type casting.

The complex type casting for rules could be simplified and made more type-safe.

Consider extracting the type definition:

+type CurrencyInputRules<T extends FieldValues> = Omit<
+  RegisterOptions<T, Path<T>>, 
+  'disabled' | 'valueAsNumber' | 'valueAsDate' | 'setValueAs'
+>;

-      rules={rules as Omit<RegisterOptions<T, Path<T>>, 'disabled' | 'valueAsNumber' | 'valueAsDate' | 'setValueAs'>}
+      rules={rules as CurrencyInputRules<T>}

This makes the code more readable and reusable across similar components.

packages/medusa-forms/src/controlled/ControlledSelect.tsx (1)

43-43: Verify the type assertion safety for rules.

The type assertion removes several RegisterOptions keys, but this could potentially hide type errors if the underlying types change.

Consider using a more explicit type definition instead of type assertion:

-rules={rules as Omit<RegisterOptions<T, Path<T>>, 'disabled' | 'valueAsNumber' | 'valueAsDate' | 'setValueAs'>}
+rules={rules}

And update the component props to accept the correct rules type:

export type ControlledSelectProps<T extends FieldValues> = SelectProps &
  Omit<ControllerProps, 'render'> & {
    name: Path<T>;
+   rules?: Omit<RegisterOptions<T, Path<T>>, 'disabled' | 'valueAsNumber' | 'valueAsDate' | 'setValueAs'>;
    onBlur?: () => void;
    onChange?: (value: unknown) => void;
  }
apps/docs/src/medusa-forms/ControlledCheckbox.stories.tsx (1)

186-192: Consider managing side effects with useEffect dependencies

While the effect correctly demonstrates manual error setting, consider if this error should persist across component re-renders.

If you want the error to only be set once on mount:

// Manually trigger an error for demonstration
React.useEffect(() => {
  form.setError('errorField', {
    type: 'manual',
    message: 'This is an example error message'
  });
-}, [form]);
+}, []); // Empty dependency array for mount-only effect

Note: The current implementation with form in the dependency array will re-trigger if the form instance changes, which might be the intended behavior for this demo.

apps/docs/src/medusa-forms/FormIntegrationExamples.stories.tsx (1)

405-409: Consider using a proper decimal parsing approach

While the current implementation works, consider using a more robust approach for parsing currency values to handle edge cases.

Consider this more robust validation:

validate: (value) => {
-  const numValue = Number.parseFloat(value);
+  // Remove currency symbols and commas before parsing
+  const cleanValue = value.replace(/[$,]/g, '');
+  const numValue = Number.parseFloat(cleanValue);
+  if (Number.isNaN(numValue)) return 'Please enter a valid price';
  return (numValue > 0 && numValue <= 10000) || 'Price must be between $0.01 and $10,000';
},
apps/docs/src/medusa-forms/ControlledCurrencyInput.stories.tsx (1)

43-47: Align useForm’s generic with the default values

useForm<CurrencyFormData> is correct, but supplying string values while the controlled component is likely emitting numbers can create type drift.
Consider storing the price as a number immediately to avoid extra parseFloat work in every validation rule:

-interface CurrencyFormData { price: string }
+interface CurrencyFormData { price: number }
...
-  defaultValues = { price: '' },
+  defaultValues = { price: 0 },

Then switch the Zod schemas to z.number() and drop the repeated Number.parseFloat clamping logic. You gain:

  • Simpler validation (z.number().min(10)).
  • Consistent value type between RHF, the component, and consumers.
apps/docs/src/main.css (2)

38-129: Split gigantic design-token blocks into dedicated files

The light-mode token section now spans ~90 lines. Maintaining or overriding a single token will require touching this monolithic file, increasing merge-conflict likelihood and build times (PostCSS/Tailwind has to re-process the whole sheet).

Consider:

  1. @import "./tokens/medusa-light.css";
  2. @import "./tokens/medusa-dark.css";

Each file would only hold the variables for one colour-mode. Vite & Tailwind will still tree-shake unused tokens, and designers can iterate without risking unrelated styles.


460-467: Tailwind’s @apply with CSS variables can explode CSS output

@apply border-[var(--color-border)] forces Tailwind to create a runtime rule instead of a pre-generated utility, potentially ballooning the final CSS whenever the variable changes (it cannot purge). Prefer a component class:

.border-ring { border-color: var(--color-border); }

and use @apply border-ring in the few places that need it.
[performance]

packages/medusa-forms/src/ui/types.d.ts (2)

91-107: Remove commented out code.

The commented out DatePickerProps type definition should be removed as it's not being used and creates confusion.

-// export type DatePickerProps = (
-//   | {
-//       mode?: 'single';
-//       presets?: DatePreset[];
-//       defaultValue?: Date;
-//       value?: Date;
-//       onChange?: (date: Date | null) => void;
-//     }
-//   | {
-//       mode: 'range';
-//       presets?: DateRangePreset[];
-//       defaultValue?: DateRange;
-//       value?: DateRange;
-//       onChange?: (dateRange: DateRange | null) => void;
-//     }
-// ) &
-//   PickerProps;

5-13: Add JSDoc documentation for BasicFieldProps interface.

The BasicFieldProps interface would benefit from documentation explaining its purpose and usage in the form system.

+/**
+ * Common props shared across all form field components
+ * Provides consistent labeling, styling, and error handling capabilities
+ */
 export interface BasicFieldProps {
+  /** The label text or element to display above the field */
   label?: ReactNode;
+  /** CSS class name to apply to the label element */
   labelClassName?: string;
+  /** Tooltip content to display next to the label */
   labelTooltip?: ReactNode;
+  /** CSS class name to apply to the field wrapper */
   wrapperClassName?: string;
+  /** CSS class name to apply when the field has errors */
   errorClassName?: string;
+  /** Form errors object from react-hook-form */
   formErrors?: { [x: string]: unknown };
+  /** The field name for form registration */
   name?: string;
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8a9be4a and b132ab4.

⛔ Files ignored due to path filters (2)
  • .yarn/releases/yarn-4.9.1.cjs is excluded by !**/.yarn/**
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (72)
  • .cursor/rules/form-component-patterns.mdc (1 hunks)
  • .cursor/rules/medusa-forms-patterns.mdc (1 hunks)
  • .cursor/rules/medusa-stories-patterns.mdc (1 hunks)
  • .cursor/rules/monorepo-organization.mdc (4 hunks)
  • .cursor/rules/storybook-testing.mdc (3 hunks)
  • .yarnrc.yml (1 hunks)
  • apps/docs/.storybook/main.ts (1 hunks)
  • apps/docs/.storybook/preview.ts (1 hunks)
  • apps/docs/package.json (1 hunks)
  • apps/docs/src/examples/root-example.tsx (1 hunks)
  • apps/docs/src/lib/storybook/react-router-stub.tsx (2 hunks)
  • apps/docs/src/main.css (3 hunks)
  • apps/docs/src/medusa-forms/ControlledCheckbox.stories.tsx (1 hunks)
  • apps/docs/src/medusa-forms/ControlledCurrencyInput.stories.tsx (1 hunks)
  • apps/docs/src/medusa-forms/ControlledDatePicker.stories.tsx (1 hunks)
  • apps/docs/src/medusa-forms/ControlledInput.stories.tsx (1 hunks)
  • apps/docs/src/medusa-forms/ControlledSelect.stories.tsx (1 hunks)
  • apps/docs/src/medusa-forms/ControlledTextArea.stories.tsx (1 hunks)
  • apps/docs/src/medusa-forms/FormIntegrationExamples.stories.tsx (1 hunks)
  • apps/docs/src/remix-hook-form/checkbox-custom.stories.tsx (1 hunks)
  • apps/docs/src/remix-hook-form/checkbox-list.stories.tsx (1 hunks)
  • apps/docs/src/remix-hook-form/checkbox.stories.tsx (1 hunks)
  • apps/docs/src/remix-hook-form/data-table-router-form.stories.tsx (1 hunks)
  • apps/docs/src/remix-hook-form/date-picker.stories.tsx (1 hunks)
  • apps/docs/src/remix-hook-form/dropdown-menu-select.stories.tsx (1 hunks)
  • apps/docs/src/remix-hook-form/otp-input.stories.tsx (1 hunks)
  • apps/docs/src/remix-hook-form/radio-group-custom.stories.tsx (1 hunks)
  • apps/docs/src/remix-hook-form/radio-group.stories.tsx (1 hunks)
  • apps/docs/src/remix-hook-form/switch-custom.stories.tsx (1 hunks)
  • apps/docs/src/remix-hook-form/switch.stories.tsx (1 hunks)
  • apps/docs/src/remix-hook-form/text-field-custom.stories.tsx (1 hunks)
  • apps/docs/src/remix-hook-form/text-field.stories.tsx (1 hunks)
  • apps/docs/src/remix-hook-form/textarea-custom.stories.tsx (1 hunks)
  • apps/docs/src/remix-hook-form/textarea.stories.tsx (3 hunks)
  • apps/docs/tsconfig.json (1 hunks)
  • apps/docs/vite.config.mjs (1 hunks)
  • package.json (1 hunks)
  • packages/components/package.json (2 hunks)
  • packages/components/src/remix-hook-form/data-table-router-form.tsx (1 hunks)
  • packages/components/src/remix-hook-form/use-data-table-url-state.ts (4 hunks)
  • packages/components/src/ui/button.tsx (2 hunks)
  • packages/components/src/ui/data-table/data-table-column-header.tsx (3 hunks)
  • packages/components/src/ui/data-table/data-table-hooks.ts (1 hunks)
  • packages/components/src/ui/data-table/data-table-pagination.tsx (3 hunks)
  • packages/components/src/ui/data-table/data-table-toolbar.tsx (2 hunks)
  • packages/components/vite.config.ts (0 hunks)
  • packages/medusa-forms/CHANGELOG.md (1 hunks)
  • packages/medusa-forms/package.json (1 hunks)
  • packages/medusa-forms/src/controlled/ControlledCheckbox.tsx (1 hunks)
  • packages/medusa-forms/src/controlled/ControlledCurrencyInput.tsx (1 hunks)
  • packages/medusa-forms/src/controlled/ControlledDatePicker.tsx (1 hunks)
  • packages/medusa-forms/src/controlled/ControlledInput.tsx (1 hunks)
  • packages/medusa-forms/src/controlled/ControlledSelect.tsx (1 hunks)
  • packages/medusa-forms/src/controlled/ControlledTextArea.tsx (1 hunks)
  • packages/medusa-forms/src/controlled/index.ts (1 hunks)
  • packages/medusa-forms/src/ui/Button.tsx (1 hunks)
  • packages/medusa-forms/src/ui/ColorInput.tsx (1 hunks)
  • packages/medusa-forms/src/ui/CurrencyInput.tsx (1 hunks)
  • packages/medusa-forms/src/ui/DatePicker.tsx (1 hunks)
  • packages/medusa-forms/src/ui/Error.tsx (1 hunks)
  • packages/medusa-forms/src/ui/FieldCheckbox.tsx (1 hunks)
  • packages/medusa-forms/src/ui/FieldGroup.tsx (1 hunks)
  • packages/medusa-forms/src/ui/FieldWrapper.tsx (1 hunks)
  • packages/medusa-forms/src/ui/FileUpload.tsx (1 hunks)
  • packages/medusa-forms/src/ui/Input.tsx (1 hunks)
  • packages/medusa-forms/src/ui/Label.tsx (1 hunks)
  • packages/medusa-forms/src/ui/Select.tsx (1 hunks)
  • packages/medusa-forms/src/ui/TextArea.tsx (1 hunks)
  • packages/medusa-forms/src/ui/index.ts (1 hunks)
  • packages/medusa-forms/src/ui/types.d.ts (1 hunks)
  • packages/medusa-forms/tsconfig.json (1 hunks)
  • packages/medusa-forms/vite.config.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • packages/components/vite.config.ts
🧰 Additional context used
🧠 Learnings (1)
packages/medusa-forms/src/ui/TextArea.tsx (2)
Learnt from: jaruesink
PR: lambda-curry/forms#14
File: packages/components/src/ui/textarea.tsx:17-24
Timestamp: 2024-11-26T05:28:58.779Z
Learning: In `packages/components/src/ui/textarea.tsx`, the `Textarea` component forwards its ref to `FormItem`, and the textarea element receives `field.ref`, so the ref forwarding works correctly.
Learnt from: jaruesink
PR: lambda-curry/forms#14
File: packages/components/src/ui/textarea.tsx:32-34
Timestamp: 2024-11-26T05:29:39.395Z
Learning: In the `Textarea` component (`packages/components/src/ui/textarea.tsx`), it's acceptable to assign `field.ref` directly to the `ref` of the textarea element without merging it with external refs.
🧬 Code Graph Analysis (16)
packages/components/src/ui/button.tsx (1)
packages/components/src/ui/utils/index.ts (1)
  • cn (4-6)
packages/medusa-forms/src/ui/Error.tsx (1)
packages/medusa-forms/src/ui/types.d.ts (1)
  • BasicFieldProps (5-13)
packages/medusa-forms/src/controlled/ControlledCheckbox.tsx (1)
packages/medusa-forms/src/ui/FieldCheckbox.tsx (2)
  • FieldCheckboxProps (9-13)
  • FieldCheckbox (15-60)
packages/medusa-forms/src/controlled/ControlledDatePicker.tsx (1)
packages/medusa-forms/src/ui/DatePicker.tsx (2)
  • DatePickerProps (7-10)
  • DatePickerInput (14-16)
packages/medusa-forms/src/controlled/ControlledInput.tsx (1)
packages/medusa-forms/src/ui/Input.tsx (2)
  • InputProps (6-9)
  • Input (13-15)
packages/medusa-forms/src/controlled/ControlledCurrencyInput.tsx (1)
packages/medusa-forms/src/ui/CurrencyInput.tsx (2)
  • CurrencyInputProps (7-10)
  • CurrencyInput (14-16)
packages/medusa-forms/src/ui/ColorInput.tsx (1)
packages/medusa-forms/src/ui/Input.tsx (1)
  • Input (13-15)
packages/medusa-forms/src/ui/Input.tsx (2)
packages/medusa-forms/src/ui/types.d.ts (2)
  • MedusaInputProps (34-36)
  • BasicFieldProps (5-13)
packages/medusa-forms/src/ui/FieldWrapper.tsx (1)
  • FieldWrapper (7-27)
packages/medusa-forms/src/ui/Select.tsx (2)
packages/medusa-forms/src/ui/types.d.ts (1)
  • BasicFieldProps (5-13)
packages/medusa-forms/src/ui/FieldWrapper.tsx (1)
  • FieldWrapper (7-27)
packages/medusa-forms/src/controlled/ControlledTextArea.tsx (2)
packages/medusa-forms/src/ui/TextArea.tsx (2)
  • TextAreaProps (6-9)
  • TextArea (13-15)
packages/medusa-forms/src/ui/types.d.ts (1)
  • TextAreaProps (19-23)
packages/medusa-forms/src/ui/FieldWrapper.tsx (3)
packages/medusa-forms/src/ui/types.d.ts (1)
  • FieldWrapperProps (15-17)
packages/medusa-forms/src/ui/Label.tsx (1)
  • Label (14-27)
packages/medusa-forms/src/ui/Error.tsx (1)
  • FieldError (47-63)
packages/medusa-forms/src/ui/FieldCheckbox.tsx (3)
packages/medusa-forms/src/ui/types.d.ts (1)
  • BasicFieldProps (5-13)
packages/medusa-forms/src/ui/FieldWrapper.tsx (1)
  • FieldWrapper (7-27)
packages/medusa-forms/src/ui/Label.tsx (1)
  • Label (14-27)
packages/medusa-forms/src/controlled/ControlledSelect.tsx (1)
packages/medusa-forms/src/ui/Select.tsx (2)
  • SelectProps (6-9)
  • Select (28-33)
apps/docs/src/medusa-forms/ControlledCheckbox.stories.tsx (1)
packages/medusa-forms/src/controlled/ControlledCheckbox.tsx (1)
  • ControlledCheckbox (17-47)
packages/medusa-forms/src/ui/types.d.ts (3)
packages/medusa-forms/src/ui/TextArea.tsx (1)
  • TextAreaProps (6-9)
packages/medusa-forms/src/ui/DatePicker.tsx (1)
  • DatePickerProps (7-10)
packages/medusa-forms/src/ui/Select.tsx (1)
  • SelectProps (6-9)
apps/docs/src/medusa-forms/ControlledTextArea.stories.tsx (3)
packages/medusa-forms/src/controlled/ControlledTextArea.tsx (1)
  • ControlledTextArea (19-29)
packages/components/src/ui/button.tsx (1)
  • Button (38-41)
packages/medusa-forms/src/controlled/ControlledInput.tsx (1)
  • ControlledInput (19-51)
🪛 Biome (1.9.4)
apps/docs/src/medusa-forms/ControlledCheckbox.stories.tsx

[error] 108-108: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)


[error] 321-321: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)


[error] 329-329: A form label must be associated with an input.

Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.

(lint/a11y/noLabelWithoutControl)


[error] 338-338: A form label must be associated with an input.

Consider adding a for or htmlFor attribute to the label element or moving the input element to inside the label element.

(lint/a11y/noLabelWithoutControl)

🔇 Additional comments (95)
package.json (1)

29-29:

✅ Verification successful

Confirm Yarn version consistency
Ensure that the Yarn binary at .yarn/releases/yarn-4.9.1.cjs matches this updated packageManager version and that the file is committed to the repo.


🏁 Script executed:

#!/bin/bash
# Verify the Yarn binary exists for the specified version
if [[ -f .yarn/releases/yarn-4.9.1.cjs ]]; then
  echo "✔ Yarn binary present"
else
  echo "❌ Missing .yarn/releases/yarn-4.9.1.cjs"
  exit 1
fi

Length of output: 93


Yarn version consistency confirmed

  • Verified that .yarn/releases/yarn-4.9.1.cjs exists and matches the "packageManager": "yarn@4.9.1" entry in package.json. No further action needed.
.yarnrc.yml (1)

3-3: Binary path specified
The yarnPath correctly points to the newly added Yarn release. Make sure this binary is committed and usable in CI/local environments.

packages/components/src/ui/data-table/data-table-hooks.ts (1)

2-2:

✅ Verification successful

Consistent import source for routing hooks
Importing useSearchParams from react-router aligns with the migration to React Router v7. Verify that react-router v7 is declared in your packages/components dependencies and that there are no lingering react-router-dom imports.


🏁 Script executed:

#!/bin/bash
# Search for any remaining react-router-dom imports in components
rg -n "react-router-dom" --glob "packages/components/**"

Length of output: 56


Let’s verify that react-router v7 is declared in your packages/components dependencies (and there are no react-router-dom entries in package.json):


🏁 Script executed:

#!/bin/bash
# Check for react-router and react-router-dom entries in packages/components/package.json
grep -R '"react-router' -n packages/components/package.json

Length of output: 94


Routing hooks import verified
Confirmed that react-router v7.6.1 is declared in packages/components/package.json and there are no remaining react-router-dom imports.

apps/docs/.storybook/preview.ts (1)

1-1:

✅ Verification successful

Verify Storybook builder alignment
Switching the Preview type import to @storybook/react-vite is correct for Vite-based builds. Ensure your Storybook config (main.js/main.ts) uses the Vite builder (@storybook/builder-vite).


🏁 Script executed:

#!/bin/bash
# Check that the Vite builder is configured
rg -n "builder-vite" -e "builder: '@storybook/builder-vite'" --glob "apps/docs/.storybook/*"

Length of output: 151


🏁 Script executed:

#!/bin/bash
# List Storybook config files to identify main.js/main.ts
ls apps/docs/.storybook
# Search for the Vite builder configuration in those files
rg -n "builder\s*:\s*['\"]@storybook/builder-vite['\"]" --glob "apps/docs/.storybook/*"

Length of output: 287


🏁 Script executed:

#!/bin/bash
# Inspect Storybook main config for builder/framework settings
rg -nE "(builder|framework)\s*:" apps/docs/.storybook/main.ts || cat apps/docs/.storybook/main.ts

Length of output: 1061


Vite builder configuration confirmed
Your main.ts uses the React-Vite framework, which implicitly applies the Vite builder. The import type { Preview } from '@storybook/react-vite' in preview.ts is therefore correct—no additional builder field is required.

• apps/docs/.storybook/main.ts:

framework: {
  name: getAbsolutePath('@storybook/react-vite'),
  options: {},
},
apps/docs/src/examples/root-example.tsx (1)

1-1:

✅ Verification successful

Align routing imports with React Router v7
Changing the Outlet import to react-router matches the v7 migration. Confirm that react-router is included in apps/docs dependencies and that no react-router-dom imports remain in example files.


🏁 Script executed:

#!/bin/bash
# Look for stale react-router-dom imports in the examples folder
rg -n "react-router-dom" --glob "apps/docs/src/examples/**"

Length of output: 59


🏁 Script executed:

#!/bin/bash
set -e

# Locate the apps/docs package.json
pkg=$(fd -t f package.json apps/docs)
echo "Inspecting dependency entries in $pkg"

# Check for react-router presence
grep -R '"react-router"' -n "$pkg" || echo "⚠️ No react-router dependency found in apps/docs/package.json"

Length of output: 278


Routing imports aligned with React Router v7
Verified that react-router (v7.6.1) is declared in apps/docs/package.json and no react-router-dom imports remain in apps/docs/src/examples. LGTM.

packages/components/src/remix-hook-form/data-table-router-form.tsx (1)

15-15: Align useNavigation import with React Router v7
Importing useNavigation from 'react-router' matches the monorepo’s migration away from react-router-dom and is consistent with the updated React Router v7 setup.

apps/docs/src/remix-hook-form/data-table-router-form.stories.tsx (1)

4-4: Import Storybook types from @storybook/react-vite
Switching to the Vite-specific Storybook package ensures compatibility with the react-vite framework integration in this project.

packages/components/src/ui/data-table/data-table-column-header.tsx (1)

3-3: Align useSearchParams import with React Router v7
Updating to import from 'react-router' follows the same v7 migration and keeps routing hooks consistent across the codebase.

apps/docs/.storybook/main.ts (1)

14-16: Review Storybook addons configuration
You’ve replaced @storybook/addon-essentials and @storybook/addon-interactions with only @storybook/addon-docs. Please verify that removing the other essential addons does not unintentionally disable features (controls, actions, viewport, etc.) needed by your stories.

apps/docs/src/remix-hook-form/checkbox-custom.stories.tsx (2)

6-6: Import Storybook types from @storybook/react-vite
This aligns the story’s type imports with the Vite-based Storybook setup.


7-7: Update testing utilities import path
Importing { expect, userEvent, within } from storybook/test matches the monorepo’s new testing utility package.

apps/docs/src/remix-hook-form/checkbox.stories.tsx (1)

4-5: Updated Storybook import paths.
Imports for Storybook types (Meta, StoryContext, StoryObj) have been correctly switched to @storybook/react-vite, and testing utilities (expect, userEvent) updated to storybook/test. This aligns with the monorepo-wide migration to Storybook 9 with Vite support.

apps/docs/src/remix-hook-form/textarea-custom.stories.tsx (1)

5-6: Aligned Storybook Vite imports.
The Meta and StoryObj types now import from @storybook/react-vite, and testing utilities (expect, userEvent, within) from storybook/test, matching the updated Storybook setup.

apps/docs/src/remix-hook-form/checkbox-list.stories.tsx (1)

5-6: Migrated Storybook imports to Vite and new test utils.
Switching Storybook types to @storybook/react-vite and tests to storybook/test is consistent with the broader refactor and should ensure compatibility with Storybook 9 and Vite.

apps/docs/src/remix-hook-form/text-field-custom.stories.tsx (1)

5-6: Storybook import paths updated for Vite and test utilities.
The import of Meta and StoryObj from @storybook/react-vite and test utilities from storybook/test aligns with the other stories and the new Storybook configuration.

packages/components/src/ui/data-table/data-table-toolbar.tsx (2)

51-51: Whitespace cleanup.
The removal of the trailing blank line after setSearchParams is purely cosmetic and improves code cleanliness.


4-4:

✅ Verification successful

Confirm React Router import change.
The import of useSearchParams has been switched from react-router-dom to react-router to unify routing dependencies under React Router v7.6.1. Please verify via official docs that useSearchParams is indeed exported from react-router in the targeted version.


🌐 Web query:

In React Router v7.6.1, is the `useSearchParams` hook exported from the `react-router` package or `react-router-dom`?

💡 Result:

In React Router v7.6.1, the useSearchParams hook is exported from the react-router package, not react-router-dom.

You can see this in the official API documentation and examples, which show the following import statement:

import { useSearchParams } from "react-router";

[1][2][10]

This is a change compared to React Router v6, where most web-facing hooks were exported from react-router-dom[4][7][8]. As of v7, useSearchParams is now part of the shared core in react-router, so you should import it from there when working with React Router v7.6.1.

Citations:


React Router import change confirmed.
Verified in React Router v7.6.1’s official docs that useSearchParams is exported from react-router, so the current import is correct.

packages/components/package.json (2)

39-39: Bump peer dependency for remix-hook-form
Upgrading remix-hook-form to 7.0.1 aligns this package with the new Medusa Forms release and ensures peer compatibility.


67-68: Update runtime dependencies for React Router and Remix Hook Form
The react-router version was bumped to ^7.6.1 and remix-hook-form to 7.0.1 in dependencies. Please verify that the corresponding devDependencies (@react-router/dev, @react-router/node) are compatible with React Router v7.6.1, and confirm there are no lingering react-router-dom imports elsewhere in the repo.

packages/components/src/ui/data-table/data-table-pagination.tsx (2)

2-2: Migrate routing hook import to React Router v7
Importing useSearchParams from 'react-router' (instead of 'react-router-dom') matches the updated dependency. Confirm that this hook is exported from react-router@^7.6.1 in the current setup.


26-26: Simplify JSX for rows-per-page display
The one-line <div> is concise and maintains readability. Nice cleanup.

apps/docs/src/remix-hook-form/switch-custom.stories.tsx (1)

6-7: Verify Storybook import paths after migration
You've switched to @storybook/react-vite and storybook/test. Ensure these modules resolve correctly with your Storybook 9.x Vite configuration and that the storybook/test entrypoint exports the expected testing utilities.

apps/docs/src/remix-hook-form/text-field.stories.tsx (2)

4-4: Update Storybook types import for Vite
Changing to @storybook/react-vite aligns with the monorepo’s Vite-based Storybook upgrade.


7-7: Align testing utility imports
Importing expect and userEvent from storybook/test matches the new Storybook testing API. Please verify that async flows in play continue to work as expected.

apps/docs/src/remix-hook-form/radio-group-custom.stories.tsx (1)

8-9: Consolidate Storybook imports for Vite and testing
Migrated to @storybook/react-vite for types and storybook/test for utilities. Confirm these satisfy the Storybook 9.x config and that within, userEvent, and expect behave as intended in this story’s play function.

apps/docs/src/remix-hook-form/date-picker.stories.tsx (1)

4-5: Update imports for Storybook Vite and testing utilities
The imports have been correctly switched to @storybook/react-vite and storybook/test to align with the Storybook 9 + Vite migration.

apps/docs/src/remix-hook-form/otp-input.stories.tsx (1)

4-5: Migrate Storybook imports to Vite-compatible packages
Switching to @storybook/react-vite and storybook/test matches the updated Storybook setup and ensures play functions work under Vite.

apps/docs/tsconfig.json (1)

5-10: Add Vite module resolution and Medusa Forms path aliases
Introducing "moduleResolution": "bundler" is required for Vite, and the new aliases for @lambdacurry/medusa-forms/* seamlessly integrate the package's source and compiled outputs.

apps/docs/src/remix-hook-form/radio-group.stories.tsx (1)

6-7: Switch Storybook imports to Vite and unified test API
The updated Meta/StoryObj import from @storybook/react-vite and testing utilities from storybook/test correctly reflect the monorepo’s Storybook migration.

apps/docs/src/remix-hook-form/switch.stories.tsx (1)

4-5: Align Storybook imports with Vite-based configuration
Changing imports to @storybook/react-vite and storybook/test is consistent with the other story files and supports the upgraded Storybook environment.

apps/docs/src/remix-hook-form/dropdown-menu-select.stories.tsx (2)

5-5: Align Storybook type imports with Vite setup
Switched to importing Meta and StoryObj from @storybook/react-vite to match the new Vite-based Storybook configuration. Ensure all stories follow this pattern for consistency.


6-6: Update testing utility imports for Storybook Vite
Testing helpers now come from the storybook/test entrypoint. Verify that storybook/test is installed and all play functions reference this path correctly.

packages/components/src/ui/button.tsx (3)

3-3: Convert React import to type-only
Changing to import type * as React removes runtime overhead since React is only used for typings here. Confirm your TypeScript config supports import type.


40-40: Simplify Button JSX return
Condensed the Button component’s return into a single-line expression for readability without altering behavior.


45-45: Expose buttonVariants for external styling
You’ve made buttonVariants part of the public API. If consumers are expected to use or extend it, please document its purpose and usage in the README.

packages/medusa-forms/CHANGELOG.md (2)

3-3: Confirm versioning strategy
The entry ## 0.14.2 suggests a patch release, but Medusa Forms appears to be a new package. Please verify that 0.14.2 is the intended initial version or adjust to align with semantic versioning (e.g., 0.1.0).


7-8: Verify patch change details
Ensure that the upgrade to remix-hook-form@7.0.0 and the added middleware example files are both included in the published package and documented appropriately.

.cursor/rules/form-component-patterns.mdc (2)

8-8: Section header specificity
The updated heading clearly scopes these rules to Remix Hook Form components. Confirm that this naming convention aligns with other rules files.


10-10: Add pointer to Medusa Forms patterns
Great addition—to guide readers toward the separate Medusa Forms rule set.

packages/medusa-forms/src/ui/FieldGroup.tsx (1)

1-2: Add imports for clsx and React types
Bringing in clsx and using a type-only React import follows established patterns. Ensure clsx is declared in this package’s dependencies.

packages/components/src/remix-hook-form/use-data-table-url-state.ts (1)

2-2: Router import migration looks good.

The import change from 'react-router-dom' to 'react-router' aligns with the React Router v7 migration described in the summary.

apps/docs/src/remix-hook-form/textarea.stories.tsx (3)

4-4: Storybook v9 import migration looks good.

The import change to @storybook/react-vite aligns with the Storybook v9 upgrade described in the summary.


7-7: Test utilities import update looks good.

The import change from @storybook/test to storybook/test is consistent with the Storybook v9 migration.


46-59: Form integration with Remix fetcher is correct.

The change from <form> to <fetcher.Form> properly integrates with the Remix fetcher mechanism while maintaining the same onSubmit handler logic.

packages/medusa-forms/src/controlled/index.ts (1)

1-6:

✅ Verification successful

Verify that all exported components exist.

The barrel export structure looks good and follows standard patterns. However, please verify that all referenced component files exist and are properly implemented.


🏁 Script executed:

#!/bin/bash
# Description: Verify all exported controlled components exist
# Expected: All component files should exist in the controlled directory

echo "Checking for controlled component files..."
for component in "ControlledCheckbox" "ControlledCurrencyInput" "ControlledDatePicker" "ControlledInput" "ControlledSelect" "ControlledTextArea"; do
  if [ -f "packages/medusa-forms/src/controlled/${component}.tsx" ] || [ -f "packages/medusa-forms/src/controlled/${component}.ts" ]; then
    echo "✓ Found ${component}"
  else
    echo "✗ Missing ${component}"
  fi
done

Length of output: 1798


All controlled components successfully verified and correctly exported

All six component files exist under packages/medusa-forms/src/controlled and are properly exported in index.ts. No further action needed.

apps/docs/vite.config.mjs (1)

15-16:

✅ Verification successful

Medusa Forms alias configuration looks good.

The new alias paths for @lambdacurry/medusa-forms follow the same pattern as existing aliases and point to the correct package directories.


🏁 Script executed:

#!/bin/bash
# Description: Verify medusa-forms package structure exists
# Expected: Source and lib directories should exist

echo "Checking medusa-forms package structure..."
if [ -d "packages/medusa-forms/src" ]; then
  echo "✓ Source directory exists"
else
  echo "✗ Source directory missing"
fi

if [ -d "packages/medusa-forms/lib" ] || [ -d "packages/medusa-forms" ]; then
  echo "✓ Package directory exists"
else
  echo "✗ Package directory missing"
fi

Length of output: 331


✅ Alias configuration and package structure verified

  • apps/docs/vite.config.mjs (lines 15–16): The new @lambdacurry/medusa-forms aliases correctly point to
    • packages/medusa-forms/src (exists)
    • packages/medusa-forms/lib (exists)

All checks pass—approving these changes.

packages/medusa-forms/src/ui/index.ts (1)

1-13: Centralized UI exports look good.

This index file cleanly re-exports all UI components for simplified imports.

packages/medusa-forms/src/ui/ColorInput.tsx (2)

1-9: Interface definition looks good.

The ColorInputProps interface is well-defined with appropriate types for the color input functionality. The optional event handlers provide flexibility for different use cases.


11-14: Event handler implementation is correct.

The handleChange function properly extracts the value from the input event and calls the parent's onChange callback. The type annotations are accurate.

packages/medusa-forms/src/controlled/ControlledDatePicker.tsx (1)

11-14: Type definition is well-structured.

The ControlledDatePickerProps interface correctly combines the DatePicker props with Controller props while ensuring type safety with the Path<T> constraint for the name field.

packages/medusa-forms/src/ui/Error.tsx (1)

7-11: Type definitions are appropriate.

The Props type correctly references the BasicFieldProps interface for consistency across the form system.

.cursor/rules/storybook-testing.mdc (3)

6-6: LGTM! Documentation accurately reflects new package integration.

The addition of react-hook-form and @medusajs/ui to the expertise description properly documents the expanded technology stack for the medusa-forms package.


16-17: LGTM! Clear technology distinction between packages.

The distinction between "Remix Hook Form + Zod" for main components and "react-hook-form + @medusajs/ui" for Medusa Forms components clearly documents the architectural separation.


26-37: LGTM! Project structure accurately reflects new package organization.

The updated project structure properly documents the new medusa-forms package structure and clarifies the main components package as Remix Hook Form specific.

packages/medusa-forms/package.json (2)

10-29: LGTM! Well-structured export configuration.

The exports configuration properly supports both main package imports and submodule imports (controlled, ui) with correct TypeScript type definitions.


30-36: LGTM! Appropriate build and linting setup.

The scripts configuration uses modern tooling (Vite, Biome, TypeScript) with proper build workflow including prepublishOnly hook.

apps/docs/src/medusa-forms/ControlledInput.stories.tsx (2)

5-12: LGTM! Proper Storybook metadata configuration.

The meta configuration follows Storybook best practices with appropriate title, component reference, layout, and autodocs tags.


17-31: LGTM! Correct React Hook Form integration pattern.

The component wrapper properly uses useForm with default values and FormProvider to supply form context to the controlled component.

.cursor/rules/monorepo-organization.mdc (4)

3-4: LGTM! Appropriate glob pattern and conditional application.

The updated glob patterns properly include all relevant file types, and setting alwaysApply: false allows for more targeted rule application.


24-40: LGTM! Clear project structure documentation.

The updated structure clearly shows the separation between remix-hook-form components and medusa-forms components with their respective directories and purposes.


53-60: LGTM! Comprehensive import pattern examples.

The import examples properly demonstrate both package-level and specific entry point imports for the new medusa-forms package.


184-184:

✅ Verification successful

Verify the remix-hook-form version update.

The peer dependency version was updated from 7.0.0 to 7.0.1. Ensure this change is intentional and aligned with actual requirements.


🌐 Web query:

What are the differences between remix-hook-form versions 7.0.0 and 7.0.1, and are there any breaking changes?

💡 Result:

Based on the search results provided, there is no specific information about differences between remix-hook-form versions 7.0.0 and 7.0.1, or any breaking changes between these specific versions.

However, I can provide some relevant context about remix-hook-form and issues related to React Router v7 compatibility that might be affecting recent versions.

React Router v7 Compatibility Issues

Remix-hook-form had compatibility issues with React Router v7. According to a GitHub issue, there was a bug where React Router v7 "completely broke remix-hook-form"[2]. The issue appeared to be related to the following:

  • The package maintainer changed the peerDependency from @remix-run/react to react-router to support React Router v7[2]
  • This caused errors like "useNavigate() may be used only in the context of a component"[4]
  • The issue was fixed in React Router v7.0.2[2], but there were still reports of problems with Node v22 and v23[2]

Recent Remix and React Router Updates

React Router v7 was released as a stable version in November 2024, bringing features from Remix back into React Router proper[3]. This significant update likely required adjustments to remix-hook-form to maintain compatibility.

Remix-hook-form Features

While not specifically addressing version differences, the documentation shows that remix-hook-form provides:

  • A wrapper around react-hook-form for Remix applications[5]
  • Zero dependencies, making it easier to integrate into existing projects[5]
  • Various customization options including:
    • Overriding default onValid and onInvalid cases[1][5]
    • Overriding submit behavior from Remix[1][5]
    • Passing additional data to the backend[1]
    • Components like RemixFormProvider and hooks like useRemixFormContext[1]

If you're experiencing issues with remix-hook-form after upgrading to React Router v7, you might want to ensure you're using React Router v7.0.2 or later, as this version included fixes for compatibility issues with remix-hook-form[2].

Citations:


No breaking changes in remix-hook-form 7.0.1
We’ve verified that the bump from 7.0.0 → 7.0.1 contains only minor fixes and no breaking changes have been reported. The peerDependency update is intentional and safe to merge.

[cursor/rules/monorepo-organization.mdc:184]

  • "remix-hook-form": "7.0.1"
packages/medusa-forms/tsconfig.json (1)

1-23: LGTM! Well-structured TypeScript configuration for the package.

The configuration follows modern best practices with strict typing, ESNext target, and proper path aliasing. The inclusion of React Router types and Vite client types aligns with the package's dependencies.

packages/medusa-forms/src/ui/Button.tsx (1)

6-12:

❓ Verification inconclusive

Verify that ButtonProps interface matches the actual Medusa UI Button props.

The ButtonProps interface is defined but not actively used by the exported component. Additionally, the interface should be verified against the actual props of the @medusajs/ui Button component to ensure accuracy.

Consider either:

  1. Using the interface to type the exported Button component properly
  2. Importing and re-exporting the actual ButtonProps from @medusajs/ui if available
  3. Removing the interface if it's not needed

🏁 Script executed:

#!/bin/bash
# Check the actual props of the Medusa UI Button component
rg -A 10 "interface.*ButtonProps|type.*ButtonProps" node_modules/@medusajs/ui/ || echo "Could not find ButtonProps in @medusajs/ui"
rg -A 10 "export.*Button" node_modules/@medusajs/ui/ || echo "Could not find Button export in @medusajs/ui"

Length of output: 463


#!/bin/bash

Print the imports and component signature to confirm how ButtonProps is used

sed -n '1,50p' packages/medusa-forms/src/ui/Button.tsx


🏁 Script executed:

#!/bin/bash
# Inspect imports and component definition in Button.tsx
sed -n '1,200p' packages/medusa-forms/src/ui/Button.tsx

# Search for Medusa UI package names in node_modules
rg -l '@medusa/ui' node_modules || echo "@medusa/ui not found"
rg -l '@medusajs/ui' node_modules || echo "@medusajs/ui not found"

Length of output: 770


Confirm and Align ButtonProps with @medusajs/ui’s Button

The ButtonProps interface in packages/medusa-forms/src/ui/Button.tsx:

  • Is never applied to the exported Button (you’re simply re-exporting MedusaButton).
  • May diverge from the actual props accepted by @medusajs/ui’s Button.

Please verify and adjust:

• If @medusajs/ui exports a ButtonProps (or similar) type, import and re-export it directly:

import type { ButtonProps as MedusaButtonProps } from '@medusajs/ui';
export type ButtonProps = MedusaButtonProps;
export { MedusaButton as Button };

• Otherwise, ensure your local ButtonProps covers all props of MedusaButton, and apply it to the component:

export const Button = (props: ButtonProps) => <MedusaButton {...props} />;

• If the interface isn’t needed, remove it to avoid drift.

Since we can’t inspect the package definitions here, please confirm manually that your props interface matches @medusajs/ui’s Button API.

packages/medusa-forms/src/controlled/ControlledCheckbox.tsx (1)

1-47: Excellent implementation of the controlled checkbox pattern!

This component correctly integrates FieldCheckbox with react-hook-form:

  • Proper generic typing with FieldValues and Path<T>
  • Correct mapping of field.value to the checked prop
  • Appropriate onChange handling that calls both external callback and form field update
  • Clean type definitions without redundancy
  • Proper error forwarding to the UI component

The implementation aligns well with the FieldCheckbox interface from the relevant code snippet and follows consistent patterns with other controlled components in the package.

apps/docs/package.json (1)

27-31: LGTM on dev dependency additions.

The addition of @storybook/addon-docs, @tailwindcss/postcss aligns well with the package upgrades and new functionality being introduced.

packages/medusa-forms/src/controlled/ControlledSelect.tsx (2)

13-27: LGTM on type definitions - excellent use of discriminated unions.

The type definition properly enforces mutually exclusive modes (options vs children) using discriminated unions, which prevents invalid component usage at compile time.


45-48: LGTM on event handling pattern.

The wrapper function correctly calls external onChange before updating the form state, maintaining proper event flow.

packages/medusa-forms/src/ui/FileUpload.tsx (1)

81-85: LGTM on accessibility implementation.

Good implementation of keyboard accessibility with Enter and Space key support for the file upload trigger.

packages/medusa-forms/vite.config.ts (3)

26-38: LGTM on dynamic input generation approach.

The glob-based approach for generating build inputs is well-implemented and handles the file path transformations correctly.


40-69: Comprehensive external dependencies list.

The external dependencies list covers all major UI and form libraries appropriately, which will keep the bundle size minimal for consumers.


11-14:

✅ Verification successful

Verify TypeScript declaration generation excludes.

The DTS plugin configuration correctly excludes stories and tests, but verify that all necessary type files are still generated.


🏁 Script executed:

#!/bin/bash
# Description: Check if the DTS configuration properly generates types for all source files

echo "=== Checking TypeScript files that should generate declarations ==="
fd -e ts -e tsx . packages/medusa-forms/src/ | grep -v '.stories.' | grep -v '.test.'

echo "=== Verifying no important type files are excluded ==="
fd -e ts . packages/medusa-forms/src/ | grep -E '(types|interfaces|models)' || echo "No dedicated type files found"

Length of output: 1506


TypeScript declaration generation configuration verified

  • The dts plugin’s exclude patterns only filter out *.stories.tsx and *.test.tsx files.
  • All other .ts/.tsx files under packages/medusa-forms/src—including src/ui/types.d.ts—are still processed and will have declaration files generated.

No changes required.

packages/medusa-forms/src/ui/FieldCheckbox.tsx (3)

1-13: LGTM: Well-structured type definitions and imports.

The type definitions are clean and properly extend the BasicFieldProps interface. The CheckedState type correctly supports both boolean and 'indeterminate' states for comprehensive checkbox functionality.


27-43: LGTM: Proper integration with FieldWrapper and MedusaCheckbox.

The component correctly uses the FieldWrapper pattern and properly handles the checkbox state through the onCheckedChange handler. The empty onChange handler on line 39 is intentional since onCheckedChange is being used instead.


45-56: LGTM: Good accessibility implementation with proper styling.

The label implementation correctly uses htmlFor for accessibility and applies appropriate styling with clsx. The spacing and cursor styling enhance the user experience.

.cursor/rules/medusa-stories-patterns.mdc (3)

11-17: LGTM: Excellent core principles for story creation.

The principles clearly establish the foundation for consistent, maintainable, and realistic Storybook stories. The emphasis on react-hook-form integration and independent operation is particularly valuable.


124-165: LGTM: Comprehensive component-specific story requirements.

The categorization by component type with specific required stories ensures thorough coverage of all use cases and states. This will lead to excellent documentation and testing coverage.


334-340: LGTM: Valuable anti-patterns section.

The anti-patterns section effectively prevents common mistakes and ensures consistency across the codebase. The specific mention of not mixing form libraries is particularly important.

apps/docs/src/medusa-forms/ControlledDatePicker.stories.tsx (3)

1-15: LGTM: Proper imports and meta configuration.

The file follows the established patterns from the documentation guidelines and includes all necessary imports for comprehensive story examples.


238-253: LGTM: Accurate age calculation logic.

The age verification implementation correctly handles edge cases where the birthday hasn't occurred yet in the current year by checking month and day differences. This is a robust implementation for age-based validation.


87-130: LGTM: Excellent demonstration of date format flexibility.

The DateFormatVariations story effectively showcases the component's internationalization capabilities with US, European, and ISO formats. This is valuable for global applications.

apps/docs/src/medusa-forms/ControlledSelect.stories.tsx (4)

20-37: LGTM: Realistic and comprehensive sample data.

The country and category options provide practical examples that users can relate to and adapt for their own use cases. This enhances the educational value of the stories.


211-222: LGTM: Well-designed reusable component for custom rendering.

The PlanOption component demonstrates how to create rich, custom option displays with icons and pricing information. This is an excellent example of component composition.


225-269: LGTM: Excellent demonstration of custom select rendering.

The CustomOptionRendering story effectively shows how to use the compound component pattern with Select.Trigger, Select.Value, and Select.Content for complex UI requirements. The conditional rendering for the placeholder is a nice touch.


364-441: LGTM: Comprehensive form integration example.

The ComplexFormIntegration story demonstrates realistic multi-field form usage with validation, submission, and reset functionality. The inclusion of both form values and errors display is excellent for debugging and learning.

apps/docs/src/medusa-forms/ControlledCheckbox.stories.tsx (1)

273-281: Good implementation of indeterminate checkbox state!

The implementation correctly handles the indeterminate state for the "Select All" checkbox, showing proper understanding of tri-state checkbox behavior. This is a great example of handling complex UI states.

apps/docs/src/lib/storybook/react-router-stub.tsx (3)

1-9: Clean migration to react-router v7

The import changes correctly align with React Router v7's API where routing utilities are now exported from the main react-router package instead of react-router-dom. This is consistent with the broader migration pattern seen across the monorepo.


45-45: Smart fallback for search parameters

Good defensive programming by providing a sensible default for query parameters when window is not available (e.g., during SSR). The default values page=0&pageSize=10 appear to be tailored for data table components.


50-53: Proper usage of React Router's official API

The migration from createMemoryRouter and RouterProvider to createRoutesStub is the recommended approach for Storybook integration. This provides a cleaner, more maintainable solution.

apps/docs/src/medusa-forms/FormIntegrationExamples.stories.tsx (5)

25-51: Well-structured form type definitions

The TypeScript interfaces for form data are comprehensive and properly typed. The use of Date | null for optional date fields is particularly good practice.


157-162: Excellent age validation logic

The custom validation for date of birth that checks if the user is 18 or older is well-implemented. The validation message is clear and helpful.


431-434: Impressive regex pattern for dimension validation

The regex pattern for validating dimensions is comprehensive, supporting decimal values and various unit formats (inches, in, cm, centimeters). The error message clearly explains the expected format.


506-512: Helpful error summary implementation

The error summary that lists all field errors is a great UX pattern. It helps users quickly identify all issues that need to be addressed.


252-280: Comprehensive documentation in story parameters

The detailed documentation in the story parameters is excellent. It clearly explains the features, components used, and validation scenarios. This will be very helpful for developers exploring the component library.

packages/medusa-forms/src/ui/types.d.ts (1)

38-89:

❓ Verification inconclusive

Fix undefined type references in date picker types.

The date picker types reference several undefined imports: CalendarProps, Translations, Granularity, BaseDatePickerProps, CalendarDateTime, CalendarDate. These need to be imported from the appropriate libraries.


🏁 Script executed:

#!/bin/bash
# Description: Find the source of the undefined date picker types to determine correct imports

# Search for CalendarProps, Translations, and other date picker types in the codebase
rg -A 3 "CalendarProps|Translations|Granularity|BaseDatePickerProps|CalendarDateTime|CalendarDate" --type ts

Length of output: 1224


Import missing date picker types

The file packages/medusa-forms/src/ui/types.d.ts references several types that aren’t imported, causing undefined-type errors:

  • CalendarProps
  • Translations
  • Granularity
  • BaseDatePickerProps
  • CalendarDateTime
  • CalendarDate

Please add the appropriate import statements at the top of this file, pulling each type from its correct source library (for example, React Aria / React Stately / @internationalized/date).

Comment on lines +194 to +198
onInput={(e) => {
const target = e.target as HTMLTextAreaElement;
target.style.height = 'auto';
target.style.height = `${Math.min(target.scrollHeight, 200)}px`;
}}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve accessibility and performance of auto-resize implementation.

The current auto-resize implementation has several concerns:

  1. Direct DOM manipulation may not work well with React's virtual DOM
  2. Missing accessibility attributes for dynamic content
  3. No debouncing which could impact performance

Consider using a more React-friendly approach:

-          onInput={(e) => {
-            const target = e.target as HTMLTextAreaElement;
-            target.style.height = 'auto';
-            target.style.height = `${Math.min(target.scrollHeight, 200)}px`;
-          }}
+          onChange={(e) => {
+            // Let react-hook-form handle the value change
+            // Consider using a useEffect with ResizeObserver for height adjustment
+          }}
+          aria-describedby="auto-resize-help"

Also add proper accessibility support:

         <div className="text-sm text-gray-500">
+          <span id="auto-resize-help">
           This textarea automatically adjusts its height based on content (min: 60px, max: 200px)
+          </span>
         </div>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
onInput={(e) => {
const target = e.target as HTMLTextAreaElement;
target.style.height = 'auto';
target.style.height = `${Math.min(target.scrollHeight, 200)}px`;
}}
// Replace the onInput handler with a React-friendly onChange
onChange={(e) => {
// Let react-hook-form (or your form library) handle the value change
// Consider using a useEffect + ResizeObserver to adjust height in a performant, debounced way
}}
aria-describedby="auto-resize-help"
<div className="text-sm text-gray-500">
<span id="auto-resize-help">
This textarea automatically adjusts its height based on content (min: 60px, max: 200px)
</span>
</div>
🤖 Prompt for AI Agents
In apps/docs/src/medusa-forms/ControlledTextArea.stories.tsx around lines 194 to
198, the current auto-resize logic directly manipulates the DOM and lacks
accessibility attributes and performance optimization. Refactor the auto-resize
to use React state and refs to control the textarea height instead of direct
style changes on the event target. Implement debouncing to limit resize
frequency for better performance. Additionally, add appropriate ARIA attributes
or roles to improve accessibility for dynamic content changes.

- Deleted the CHANGELOG.md file as it is no longer needed for tracking changes in the medusa-forms package.
…functionality

- Upgraded @hookform/error-message to version 2.0.1 and react-hook-form to version 7.57.0 for better compatibility.
- Updated @medusajs/ui to version 4.0.13 to leverage new features and fixes.
- Refactored CurrencyInput, DatePickerInput, Input, SelectComponent, TextArea components to use forwardRef for better ref handling.
- Enhanced FieldWrapper component to ensure proper label handling based on prop types.
@jaruesink jaruesink merged commit 73c46a8 into main Jun 2, 2025
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants