diff --git a/apps/docs/src/medusa-forms/ControlledCheckbox.stories.tsx b/apps/docs/src/medusa-forms/ControlledCheckbox.stories.tsx index 2c22b898..e75df06c 100644 --- a/apps/docs/src/medusa-forms/ControlledCheckbox.stories.tsx +++ b/apps/docs/src/medusa-forms/ControlledCheckbox.stories.tsx @@ -1,4 +1,4 @@ -import { ControlledCheckbox } from '@lambdacurry/medusa-forms/controlled'; +import { ControlledCheckbox } from '@lambdacurry/medusa-forms/controlled/ControlledCheckbox'; import type { Meta, StoryObj } from '@storybook/react-vite'; import React from 'react'; import { FormProvider, useForm } from 'react-hook-form'; @@ -306,7 +306,7 @@ export const MultipleCheckboxes: Story = { }; // Form Integration Example Story -const CompleteFormExample = () => { +const CompleteFormExampleComponent = () => { const form = useForm({ defaultValues: { username: '', @@ -392,5 +392,5 @@ const CompleteFormExample = () => { }; export const CompleteFormExample: Story = { - render: () => , + render: () => , }; diff --git a/apps/docs/src/medusa-forms/ControlledSelect.stories.tsx b/apps/docs/src/medusa-forms/ControlledSelect.stories.tsx new file mode 100644 index 00000000..00893d50 --- /dev/null +++ b/apps/docs/src/medusa-forms/ControlledSelect.stories.tsx @@ -0,0 +1,475 @@ +import { ControlledSelect } from '@lambdacurry/medusa-forms/controlled/ControlledSelect'; +import { Select } from '@lambdacurry/medusa-forms/ui/Select'; +import type { Meta, StoryObj } from '@storybook/react-vite'; +import { FormProvider, useForm } from 'react-hook-form'; +import { useState } from 'react'; + +const meta = { + title: 'Medusa Forms/Controlled Select', + component: ControlledSelect, + parameters: { + layout: 'centered', + }, + tags: ['autodocs'], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +// Sample options for stories +const countryOptions = [ + { label: 'United States', value: 'us' }, + { label: 'Canada', value: 'ca' }, + { label: 'United Kingdom', value: 'uk' }, + { label: 'Germany', value: 'de' }, + { label: 'France', value: 'fr' }, + { label: 'Japan', value: 'jp' }, + { label: 'Australia', value: 'au' }, +]; + +const categoryOptions = [ + { label: 'Electronics', value: 'electronics' }, + { label: 'Clothing', value: 'clothing' }, + { label: 'Books', value: 'books' }, + { label: 'Home & Garden', value: 'home-garden' }, + { label: 'Sports', value: 'sports' }, +]; + +// 1. Basic Single Select +const BasicSingleSelectForm = () => { + const form = useForm({ + defaultValues: { + country: '', + }, + }); + + return ( + + + + + Form Value: {JSON.stringify(form.watch(), null, 2)} + + + + ); +}; + +export const BasicSingleSelect: Story = { + render: () => , +}; + +// 2. Single Select with Default Value +const DefaultValueSelectForm = () => { + const form = useForm({ + defaultValues: { + country: 'us', + }, + }); + + return ( + + + + + Form Value: {JSON.stringify(form.watch(), null, 2)} + + + + ); +}; + +export const WithDefaultValue: Story = { + render: () => , +}; + +// 3. Required Field Validation +const RequiredValidationForm = () => { + const form = useForm({ + defaultValues: { + requiredCountry: '', + }, + }); + + const onSubmit = (data: any) => { + alert(`Form submitted with: ${JSON.stringify(data)}`); + }; + + return ( + + + + + + Submit + + {form.formState.errors.requiredCountry && ( + + {form.formState.errors.requiredCountry.message} + + )} + + + Form Value: {JSON.stringify(form.watch(), null, 2)} + + + + ); +}; + +export const SelectRequiredValidation: Story = { + render: () => , +}; + +// 4. Loading States +const LoadingStateForm = () => { + const [isLoading, setIsLoading] = useState(false); + const form = useForm({ + defaultValues: { + country: '', + }, + }); + + const toggleLoading = () => { + setIsLoading(!isLoading); + }; + + return ( + + + + + + {isLoading ? 'Stop Loading' : 'Start Loading'} + + + + Form Value: {JSON.stringify(form.watch(), null, 2)} + + Loading: {isLoading.toString()} + + + + ); +}; + +export const LoadingState: Story = { + render: () => , +}; + +// 5. Custom Option Rendering (using children) +const CustomOptionRenderingForm = () => { + const form = useForm({ + defaultValues: { + customSelect: '', + }, + }); + + return ( + + + + + + + + + ⭐ + Premium Plan + ($29/mo) + + + + + 💎 + Standard Plan + ($19/mo) + + + + + 🌱 + Basic Plan + ($9/mo) + + + + + + Form Value: {JSON.stringify(form.watch(), null, 2)} + + + + ); +}; + +export const CustomOptionRendering: Story = { + render: () => , +}; + +// 6. Disabled State +const DisabledStateForm = () => { + const form = useForm({ + defaultValues: { + disabledSelect: 'us', + }, + }); + + return ( + + + + + Form Value: {JSON.stringify(form.watch(), null, 2)} + + + + ); +}; + +export const SelectDisabledState: Story = { + render: () => , +}; + +// 7. Error State +const ErrorStateForm = () => { + const form = useForm({ + defaultValues: { + errorSelect: '', + }, + }); + + // Manually set an error for demonstration + form.setError('errorSelect', { + type: 'manual', + message: 'This field has an error', + }); + + return ( + + + + {form.formState.errors.errorSelect && ( + + {form.formState.errors.errorSelect.message} + + )} + + Form Value: {JSON.stringify(form.watch(), null, 2)} + + + + ); +}; + +export const SelectErrorState: Story = { + render: () => , +}; + +// 8. Small Size Variant +const SmallSizeForm = () => { + const form = useForm({ + defaultValues: { + smallSelect: '', + }, + }); + + return ( + + + + + Form Value: {JSON.stringify(form.watch(), null, 2)} + + + + ); +}; + +export const SmallSize: Story = { + render: () => , +}; + +// 9. Complex Form Integration +const ComplexFormIntegrationComponent = () => { + const form = useForm({ + defaultValues: { + country: '', + category: '', + plan: '', + priority: '', + }, + }); + + const onSubmit = (data: any) => { + alert(`Complete form submitted: ${JSON.stringify(data, null, 2)}`); + }; + + return ( + + + + + + + + + + + + + Submit Form + + + form.reset()} + className="w-full px-4 py-2 bg-gray-500 text-white rounded hover:bg-gray-600" + > + Reset Form + + + + + Form Values: + {JSON.stringify(form.watch(), null, 2)} + + + + Form Errors: + + {JSON.stringify(form.formState.errors, null, 2)} + + + + + ); +}; + +export const ComplexFormIntegration: Story = { + render: () => , +}; + +// 10. Interactive Demo with onChange Handler +const InteractiveDemoForm = () => { + const [selectedValue, setSelectedValue] = useState(''); + const form = useForm({ + defaultValues: { + interactiveSelect: '', + }, + }); + + const handleSelectChange = (value: unknown) => { + setSelectedValue(value as string); + console.log('Select value changed:', value); + }; + + return ( + + + + + External State Value: {selectedValue || 'None'} + + + Form Value: {JSON.stringify(form.watch(), null, 2)} + + + + ); +}; + +export const InteractiveDemo: Story = { + render: () => , +}; +
{JSON.stringify(form.watch(), null, 2)}
+ {JSON.stringify(form.formState.errors, null, 2)} +