{"_id":"@alexandregerault/react-dynamic-form","name":"@alexandregerault/react-dynamic-form","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@alexandregerault/react-dynamic-form","version":"0.1.0","type":"module","scripts":{"dev":"vite","build":"tsc && vite build","preview":"vite preview"},"dependencies":{"react":"^18.2.0","react-dom":"^18.2.0"},"devDependencies":{"@rollup/plugin-typescript":"^9.0.2","@testing-library/jest-dom":"^5.16.5","@testing-library/react":"^13.4.0","@testing-library/user-event":"^14.4.3","@types/jest":"^29.0.3","@types/react":"^18.0.17","@types/react-dom":"^18.0.6","@typescript-eslint/eslint-plugin":"^5.42.0","@typescript-eslint/parser":"^5.42.0","@vitejs/plugin-react":"^2.1.0","autoprefixer":"^10.4.13","eslint":"^8.26.0","eslint-config-prettier":"^8.5.0","eslint-plugin-import":"^2.26.0","eslint-plugin-jsx-a11y":"^6.6.1","eslint-plugin-prettier":"^4.2.1","eslint-plugin-react":"^7.31.10","eslint-plugin-simple-import-sort":"^8.0.0","jest-environment-jsdom":"^29.0.3","postcss":"^8.4.18","prettier":"^2.7.1","tailwindcss":"^3.2.2","ts-node":"^10.9.1","typescript":"^4.6.4","vite":"^3.1.0","vite-tsconfig-paths":"^3.5.0","vitest":"^0.24.4"},"main":"./dist/react-dynamic-form.umd.cjs","module":"./dist/react-dynamic-form.js","exports":{".":{"import":"./dist/react-dynamic-form.js","require":"./dist/react-dynamic-form.umd.cjs"}},"repository":{"url":"git://github.com/AlexandreGerault/react-dynamic-form.git"},"author":{"name":"Alexandre Gérault","email":"gerault-alexandre@orange.fr"},"license":"MIT","gitHead":"9be7c8216bebfe3e05b561d8be6ca4a59e1b99a4","description":"A react library to build dynamic step forms. Create an object describing your form and be ready to go!\r ## Features","bugs":{"url":"https://github.com/AlexandreGerault/react-dynamic-form/issues"},"homepage":"https://github.com/AlexandreGerault/react-dynamic-form#readme","_id":"@alexandregerault/react-dynamic-form@0.1.0","_nodeVersion":"16.14.0","_npmVersion":"8.3.1","dist":{"integrity":"sha512-5MUa1Hz8en2cxUGHdMXd8T5gMUQ49p0qhnIMqOxAAMFIOD5/oiApGdWKSkbBIv7TN8HsVR6d7q3ad7KMGCF0NA==","shasum":"8feab4191e3aee520fb5aa2d3d458b57129ef1bd","tarball":"https://registry.npmjs.org/@alexandregerault/react-dynamic-form/-/react-dynamic-form-0.1.0.tgz","fileCount":11,"unpackedSize":12430,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICQxWltqUlTObwP2PblhXWCMJRMOrvcuAjdBFbH0fyiXAiEA3N05AcxIhYz3A9xWrPERCOIZzaD5PpWh94ns5VrojeI="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjbCwQACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoD5A/+KCgdE6OFI/ItgPOw6sBvDLkXEILwCaiRs4yJvL7JqFrAucu2\r\n6PLk9T7dp3A9UxYdBJpQfA2gMqunLM4OukOWKhIQbO2njDKEYBxEyiqxXUt+\r\n4ysRLU+RAzcnwJ+oriCcRPgqvHk7uSaGwCmJoY2G5Mil/wO2EqItngqq5hjj\r\n+rY6AifLFEj0JSahNuHwycA7YntqdL8zmMdAzE5NgcgQTPw0cT5EjVA9ELvG\r\nS0LYctlSG+LQWxZ+ys2J0BvRLHtcfIEaboXSCMtC/xu14K/BYaI+65FI3OSW\r\nq7rtXCohlmTqwj4C0sNRmtAwRYC4InfV87tF8NFadU1XUYyUJROQaZ2Pjbln\r\nmwAJ0GO1sgG7wThlOsc3+aJ/Uury6BLmtbsXMOw3+I6x+1N3RouxjrQt92eq\r\nvGQX8Hi54sWrAuysTWgFbF2tIjyb/YjKdB0blMKaaYeUbmqP8tg6Alj2csBu\r\nQKSD8Q6PmAajFzstcidkzsl7g1AhseRUBW9nVEAjwcG8/ua0OzCt9B9ydwPP\r\nCH1eJ5g6yfO0Vbm3OZkqg1/cgWp+k+tmrVcRDsRfYuNY7XL0XEtRSguNMzz9\r\nC+fmq5rH1yQWkLGBwADWPOuogJOJmbjp00iUeF7wO8gjfD/L2h/jiL6dnOW8\r\nzwC/NaXBE4RpEjjWK9Jer+CUHmnP09+2FPU=\r\n=62Is\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"alexandre_gerault","email":"gerault-alexandre@orange.fr"},"directories":{},"maintainers":[{"name":"alexandre_gerault","email":"gerault-alexandre@orange.fr"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/react-dynamic-form_0.1.0_1668033552416_0.6605769671032562"},"_hasShrinkwrap":false}},"time":{"created":"2022-11-09T22:39:12.341Z","0.1.0":"2022-11-09T22:39:12.600Z","modified":"2022-11-09T22:39:12.753Z"},"maintainers":[{"name":"alexandre_gerault","email":"gerault-alexandre@orange.fr"}],"description":"A react library to build dynamic step forms. Create an object describing your form and be ready to go!\r ## Features","homepage":"https://github.com/AlexandreGerault/react-dynamic-form#readme","repository":{"url":"git://github.com/AlexandreGerault/react-dynamic-form.git"},"author":{"name":"Alexandre Gérault","email":"gerault-alexandre@orange.fr"},"bugs":{"url":"https://github.com/AlexandreGerault/react-dynamic-form/issues"},"license":"MIT","readme":"# React dynamic form\r\n\r\nA react library to build dynamic step forms. Create an object describing your form and be ready to go!\r\n## Features\r\n\r\n- Create a step by step form\r\n- Allow dynamic form path\r\n\r\n\r\n## Documentation\r\n\r\n[Documentation](docs/)\r\n\r\n### Simple example\r\n\r\nTo create a dynamic step by step form, you have to:\r\n\r\n1. Create an object representing your form;\r\n2. Create a handler function that will execute when the form ends;\r\n3. Create a component to render your form.\r\n\r\nTo create an object representing the steps, you can write a plain Javascript \r\nobject or use the factory functions.\r\n\r\n```javascript\r\n// Factory functions\r\nconst questionRoute = createQuestion(\r\n  'Quelle fillière ?',\r\n  [\r\n    createAnswer('PCSI', { value: 'pcsi' }),\r\n    createAnswer('MPSI', { value: 'mpsi' }),\r\n    createAnswer('PC', { value: 'pc' }),\r\n    createAnswer('PSI', { value: 'psi' }),\r\n  ],\r\n  { key: 'route' },\r\n);\r\n\r\nconst tree = createQuestion(\r\n  'Vous êtes ?',\r\n  [\r\n    createAnswer('En CPGE', { nextQuestion: questionRoute, value: 'cpge' }),\r\n    createAnswer('Lycéen', {\r\n      value: 'highschool',\r\n      nextQuestion: createQuestion(\r\n        'Envisagez-vous de faire une prépa ?',\r\n        [\r\n          createAnswer('Oui', { value: 'yes', nextQuestion: questionRoute }),\r\n          createAnswer('Non', { value: 'no' }),\r\n        ],\r\n        { key: 'do-prepa' },\r\n      ),\r\n    }),\r\n  ],\r\n  { key: 'level' },\r\n);\r\n\r\n// Plain object\r\nconst tree = {\r\n  label: 'Vous êtes ?',\r\n  answers: [\r\n    {\r\n      label: 'En CPGE',\r\n      options: {\r\n        value: 'cpge',\r\n        nextQuestion: {\r\n          label: 'Quelle fillière ?',\r\n          answers: [\r\n            { label: 'PCSI', options: { value: 'pcsi' } },\r\n            { label: 'MPSI', options: { value: 'mpsi' } },\r\n            { label: 'PC', options: { value: 'pc' } },\r\n            { label: 'PSI', options: { value: 'psi' } },\r\n          ],\r\n        },\r\n      },\r\n    },\r\n    {\r\n      label: 'Lycéen',\r\n      options: {\r\n        nextQuestion: {\r\n          label: 'Envisagez-vous de faire une prépa ?',\r\n          answers: [\r\n            { label: 'Oui', options: { value: 'yes' } },\r\n            { label: 'Non', options: { value: 'no' } },\r\n          ],\r\n          options: {\r\n            key: 'do-prepa',\r\n          },\r\n        },\r\n        value: 'highschool',\r\n      },\r\n    },\r\n  ],\r\n  options: {\r\n    key: 'level',\r\n  },\r\n};\r\n```\r\n\r\nAs you can read above, the factory functions allow you to avoid repeating yourself when repeating the same question.\r\n\r\nThen you can create a component that will create a form with the given questions, using the `useStepForm` hook. You can look at the `DynamicForm` component as an example:\r\n\r\n```tsx\r\nimport { Question } from '@/core/questions';\r\n\r\nimport useStepForm from './hooks/step-form';\r\n\r\ninterface DynamicFormProps {\r\n  questionsTree: Question;\r\n  onSubmit: (values: Record<string, string>) => void;\r\n}\r\n\r\nexport function DynamicForm({ questionsTree, onSubmit }: DynamicFormProps) {\r\n  const {\r\n    submit,\r\n    back,\r\n    selectAnswer,\r\n    currentQuestion,\r\n    shouldDisableBackButton,\r\n    selectedAnswer,\r\n  } = useStepForm(questionsTree, onSubmit);\r\n\r\n  return (\r\n    <form\r\n      onSubmit={(e) => {\r\n        e.preventDefault();\r\n        submit();\r\n      }}\r\n      className=\"max-w-xs bg-white rounded shadow px-6 py-4 w-full space-y-4\">\r\n      <p className=\"text-2xl\">{currentQuestion.label}</p>\r\n      <div className=\"space-y-2\">\r\n        {currentQuestion.answers.map((answer) => (\r\n          <div key={answer.label} className=\"flex gap-2 items-center\">\r\n            <input\r\n              type=\"radio\"\r\n              name=\"answer\"\r\n              value={answer.label}\r\n              id={answer.label}\r\n              onChange={() => selectAnswer(answer)}\r\n              checked={answer.label === selectedAnswer?.label}\r\n            />\r\n\r\n            <label htmlFor={answer.label}>{answer.label}</label>\r\n          </div>\r\n        ))}\r\n      </div>\r\n      <div className=\"flex justify-between\">\r\n        <button\r\n          type=\"button\"\r\n          onClick={back}\r\n          disabled={shouldDisableBackButton}\r\n          className=\"rounded outline-purple-500 text-purple-500 px-3 py-2\">\r\n          Back\r\n        </button>\r\n        <button type=\"submit\" className=\"rounded bg-purple-500 text-white px-3 py-2\">\r\n          Submit\r\n        </button>\r\n      </div>\r\n    </form>\r\n  );\r\n}\r\n\r\n```\r\n\r\nThen, the last thing you have to do is to use this component with a submit handler function, like so\r\n\r\n```tsx\r\nfunction App() {\r\n  return (\r\n    <div className=\"flex items-center justify-center mx-auto min-h-screen bg-blue-200\">\r\n      <DynamicForm\r\n        questionsTree={tree}\r\n        onSubmit={(values) => {\r\n          fetch('http://localhost?' + new UrlSearchParams(values))\r\n        }}\r\n      />\r\n    </div>\r\n  );\r\n}\r\n```\r\n\r\n## Installation\r\n\r\nJust type\r\n```sh\r\nnpm install  @alexandregerault/react-dynamic-form@0.1.0\r\n```\r\nOr if you use yarn\r\n```sh\r\nyarn add  @alexandregerault/react-dynamic-form@0.1.0\r\n```\r\n## Running Tests\r\n\r\nTo run tests, run the following command (you must have cloned the project)\r\n\r\n```bash\r\n  yarn vitest\r\n```\r\n\r\n\r\n## Run Locally\r\n\r\nClone the project\r\n\r\n```bash\r\ngit clone https://github.com/AlexandreGerault/react-dynamic-form\r\n```\r\n\r\nInstall the dependencies\r\n\r\n```bash\r\ncd react-dynamic-form\r\nyarn\r\n```\r\n\r\nAnd then you can start the dev environment with\r\n```bash\r\n yarn dev\r\n```\r\n## License\r\n\r\n[MIT](https://choosealicense.com/licenses/mit/)\r\n\r\n","readmeFilename":"README.md"}