{"id":15527209,"url":"https://github.com/max-sym/react-booking-form","last_synced_at":"2025-04-23T12:23:07.249Z","repository":{"id":41841332,"uuid":"328135113","full_name":"max-sym/react-booking-form","owner":"max-sym","description":"🚀 Light, unstyled and flexible library to quickly create booking forms with location search (debounce), calendar, and guest fields.","archived":false,"fork":false,"pushed_at":"2023-10-16T22:24:40.000Z","size":2914,"stargazers_count":28,"open_issues_count":4,"forks_count":5,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-11T19:41:13.542Z","etag":null,"topics":["booking","booking-platform","booking-system","calendar-component","form","forms","hotel-booking","react","reactjs","tailwindcss","tourist-website"],"latest_commit_sha":null,"homepage":"https://codesandbox.io/s/react-booking-form-example-9z489","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/max-sym.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-01-09T11:04:20.000Z","updated_at":"2025-01-30T19:43:40.000Z","dependencies_parsed_at":"2024-10-02T00:00:58.540Z","dependency_job_id":"59f7c76f-667d-4661-bb9c-061cda52dc3b","html_url":"https://github.com/max-sym/react-booking-form","commit_stats":{"total_commits":153,"total_committers":4,"mean_commits":38.25,"dds":0.522875816993464,"last_synced_commit":"92651ca4ab6494256a49f47f543e30ab3731b690"},"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/max-sym%2Freact-booking-form","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/max-sym%2Freact-booking-form/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/max-sym%2Freact-booking-form/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/max-sym%2Freact-booking-form/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/max-sym","download_url":"https://codeload.github.com/max-sym/react-booking-form/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250285666,"owners_count":21405297,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["booking","booking-platform","booking-system","calendar-component","form","forms","hotel-booking","react","reactjs","tailwindcss","tourist-website"],"created_at":"2024-10-02T11:05:05.033Z","updated_at":"2025-04-23T12:23:07.220Z","avatar_url":"https://github.com/max-sym.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"![npm](https://img.shields.io/npm/dm/react-booking-form?style=flat-square)\n![GitHub last commit](https://img.shields.io/github/last-commit/MaxChu23/react-booking-form?style=flat-square)\n![npm bundle size](https://img.shields.io/bundlephobia/minzip/react-booking-form@2.0.0-alpha.1?style=flat-square)\n![npm bundle size](https://img.shields.io/bundlephobia/min/react-booking-form@2.0.0-alpha.1?style=flat-square)\n![GitHub](https://img.shields.io/github/license/MaxChu23/react-booking-form?style=flat-square)\n\n# React Booking Form 🔥\n\nLightweight, flexible library for quickly creating booking forms for websites with purposes such as hotel, restaurant, transport services booking and similar.\\\nIncludes location, calendar, and guest selectors logic (style agnostic) and much more.\n\n\u003cimg src=\"https://i.imgur.com/9JBUX53.gif\" width=\"100%\" /\u003e\n\n## Live examples\n- [CodeSandbox](https://codesandbox.io/s/react-booking-form-example-9z489)\n- [Storybook](https://611f9e606d0396003a654e41-sfznirawpt.chromatic.com/?path=/story/booking-form--basic)\n\n\n## Installation\nnpm: `npm i react-booking-form`\\\nyarn: `yarn add react-booking-form`\n\n## Features included\n### Main:\n\n✅ Style agnostic: style your components however you want. Logic is taken care of by the library\\\n✅ Debounced location search\\\n✅ Swap locations\\\n✅ Focus on the next form fields right after selections\\\n✅ Date calendar with time selector [flatpickr](https://github.com/flatpickr/flatpickr)\\\n✅ Ability to set check-out minimum date depending on the selected check-in date value.\\\n✅ Allows human readable datetime format + localization (configuration options provided by [flatpickr](https://github.com/flatpickr/flatpickr))\\\n✅ Little size\\\n✅ Guest count selection by person group\n\n### Layout \u0026 DOM:\n\n✅ Popups' position is relative to the browser window's position and size (i.e., it would try to make the popups visible even if not enough height)\\\n✅ Uses [React Portal](https://reactjs.org/docs/portals.html) under the hood 🎩\\\n✅ Accessible\\\n✅ Responsive\n\n\n### Notes\n- The library styling is very flexible, however the calendar component styling requires including a theme css file from [flatpickr](https://github.com/flatpickr/flatpickr). We made it so you can fully control it by including it yourself or creating your own theme;\n\n## Usage\n\nTo quickly catch up go to the CodeSandbox Playground first.\\\nThen read the example below + configuration docs.\n\n\u003cdetails\u003e\n\u003csummary\u003e 👉 TypeScript + TailwindCSS example (with \u003ca href=\"https://github.com/MathiasGilson/Tailwind-Styled-Component\"\u003etailwind-styled-components\u003c/a\u003e)\u003c/summary\u003e\n\t\n### Install\n\n```bash\nyarn add react-booking-form moment @react-icons/all-files tailwind-styled-components\n```\n\n### Import the libraries:\n\n```js\nimport React from \"react\"\nimport {\n  DateInput,\n  FormSchema,\n  GuestSelect,\n  GuestOption,\n  LocationSelect,\n  useReactBookingForm,\n  BookingForm as BookingFormType,\n  LocationOption,\n} from \"react-booking-form\"\nimport tw from \"tailwind-styled-components\"\nimport moment from \"moment\"\nimport \"flatpickr/dist/themes/material_green.css\"\n```\n\n### Prepare some helper functions:\n\nHere's some helpers that represent something similar to how we would fetch the city data in a real-world application for the location selector:\n\nCreate a file called `cities.ts`:\n\n```js\nexport const cities = [\n\t\"New York\",\n\t\"Alabama\",\n\t\"Los Angeles\",\n\t// ... Add more cities if you want \n]\n```\n\nThen import `cities` and add some helper functions:\t\n\n```js\nimport { cities } from \"./cities\"\n\n// This is mocking a call to API that would return location search results\n// whenever user types into the location input field.\nconst searchPlace = async (query: string) =\u003e\n  new Promise((resolve, _reject) =\u003e {\n    setTimeout(() =\u003e resolve(filterAndMapCiies(query)), 600)\n  })\n\nconst formattedCities = cities.map((city) =\u003e ({\n  value: city.toLowerCase(),\n  label: city,\n}))\n\t\n// This is what might happen on the backend in real-life application: it would search for the city.\nconst filterAndMapCiies = (query: string) =\u003e\n  formattedCities.filter((city) =\u003e city.value.includes(query.toLowerCase()))\n\n// This is the list of cities to be shown initially when user didn't start the search of location yet.\nconst defaultLocationOptions: LocationOption[] = formattedCities.slice(0, 5)\n\n```\n\n### Define your form schema:\n\n```js\nconst dateConfig = {\n  altInput: true,\n  altFormat: \"M j, Y\",\n  dateFormat: \"Y-m-d\",\n  wrap: true,\n}\n\nconst formSchema: FormSchema = {\n  from: {\n    type: \"location\",\n    options: { defaultLocationOptions, searchPlace },\n    focusOnNext: \"to\",\n  },\n  to: {\n    type: \"location\",\n    options: { defaultLocationOptions, searchPlace },\n    focusOnNext: \"checkIn\",\n  },\n  checkIn: {\n    type: \"date\",\n    focusOnNext: \"checkOut\",\n    options: { ...dateConfig, minDate: \"today\" },\n  },\n  checkOut: {\n    type: \"date\",\n    focusOnNext: \"guests\",\n    options: { ...dateConfig, minDateFrom: \"checkIn\" },\n  },\n  guests: {\n    type: \"peopleCount\",\n    defaultValue: [\n      {\n        name: \"adults\",\n        label: \"Adults\",\n        description: \"Ages 13+\",\n        value: 1,\n        min: 0,\n        max: 10,\n      },\n      {\n        name: \"children\",\n        label: \"Children\",\n        description: \"Ages 4-12\",\n        value: 0,\n        min: 0,\n        max: 10,\n      },\n      {\n        name: \"infants\",\n        label: \"Infants\",\n        description: \"Under 4 years old\",\n        value: 0,\n        min: 0,\n        max: 10,\n      },\n    ],\n  },\n}\n```\n\n### Create your booking form JSX\n\nThe form would include some of the components that we imported previously from the `react-booking-form` and your own components:\n\n```jsx\nexport const BookingForm = () =\u003e {\n  const form = useReactBookingForm({ formSchema })\n\n  const onBookButtonClick = () =\u003e {\n    const config = {\n      convertDate: (dateValue: Date) =\u003e moment(dateValue).format(\"DD-MM-YYYY\"),\n    }\n    alert(form.serializeToURLParams(config))\n  }\n\n  return (\n    \u003cContainer\u003e\n      \u003cInputContainer\u003e\n        \u003cLabel\u003e{\"From\"}\u003c/Label\u003e\n        \u003cLocationSelect\n          form={form}\n          menu={Menu}\n          menuContainer={MenuContainer}\n          option={OptionContainer}\n          inputComponent={InputComponent}\n          name=\"from\"\n          emptyOption=\"Nothing was found :(\"\n          placeholder=\"Where are you going?\"\n        /\u003e\n      \u003c/InputContainer\u003e\n      \u003cInputContainer style={{ width: \"auto\" }}\u003e\n        \u003cSwapButton\n          title=\"Swap Locations\"\n          aria-label=\"Swap Locations\"\n          onClick={() =\u003e form.swapLocations()}\n        \u003e\n          \u003cIoMdSwap className=\"w-4 h-4\" /\u003e\n        \u003c/SwapButton\u003e\n      \u003c/InputContainer\u003e\n      \u003cInputContainer\u003e\n        \u003cLabel\u003e{\"To\"}\u003c/Label\u003e\n        \u003cLocationSelect\n          form={form}\n          menu={Menu}\n          menuContainer={MenuContainer}\n          option={OptionContainer}\n          inputComponent={InputComponent}\n          name=\"to\"\n          emptyOption=\"Nothing was found :(\"\n          placeholder=\"Where are you going?\"\n        /\u003e\n      \u003c/InputContainer\u003e\n      \u003cInputContainer\u003e\n        \u003cLabel\u003e{\"Check in\"}\u003c/Label\u003e\n        \u003cDateInput\n          inputComponent={InputComponent}\n          className=\"w-full\"\n          placeholder=\"Add date\"\n          form={form}\n          name=\"checkIn\"\n        /\u003e\n      \u003c/InputContainer\u003e\n      \u003cInputContainer\u003e\n        \u003cLabel\u003e{\"Check out\"}\u003c/Label\u003e\n        \u003cDateInput\n          inputComponent={InputComponent}\n          className=\"w-full\"\n          placeholder=\"Add date\"\n          form={form}\n          name=\"checkOut\"\n        /\u003e\n      \u003c/InputContainer\u003e\n      \u003cInputContainer\u003e\n        \u003cLabel\u003e{\"Guests\"}\u003c/Label\u003e\n        \u003cGuestSelect\n          form={form}\n          menuContainer={MenuContainer}\n          menu={Menu}\n          inputComponent={InputComponent}\n          option={GuestOptionComponent}\n          okButton={GuestOkButton}\n          okText=\"Ok!\"\n          placeholder=\"Add guests\"\n          name={\"guests\"}\n        /\u003e\n      \u003c/InputContainer\u003e\n      \u003cInputContainer\u003e\n        \u003cSearchButton onClick={onBookButtonClick}\u003e{\"Search\"}\u003c/SearchButton\u003e\n      \u003c/InputContainer\u003e\n    \u003c/Container\u003e\n  )\n}\n```\n\n### Styling Components\n\t\nBelow are our own custom components (styled by tailwind-styled-components, but you can use anything for styling).\n\nImport the icons right away:\n\n```jsx\nimport { FaMapMarkerAlt } from \"@react-icons/all-files/fa/FaMapMarkerAlt\"\nimport { FaCalendarAlt } from \"@react-icons/all-files/fa/FaCalendarAlt\"\nimport { FaSpinner } from \"@react-icons/all-files/fa/FaSpinner\"\nimport { FaPlus } from \"@react-icons/all-files/fa/FaPlus\"\nimport { FaMinus } from \"@react-icons/all-files/fa/FaMinus\"\nimport { FaUser } from \"@react-icons/all-files/fa/FaUser\"\nimport { IoMdSwap } from \"@react-icons/all-files/io/IoMdSwap\"\n```\n\t\nNow start styling with `tw` from `tailwind-styled-components` package.\n\n```jsx\nconst Container = tw.div`md:rounded-full rounded-xl bg-white p-6 shadow-xl flex justify-between flex-col md:flex-row md:space-x-2 md:space-y-0 space-y-2 border border-gray-300`\nconst InputContainer = tw.div`relative w-full md:w-1/3 flex flex-col justify-center items-center pl-2`\nconst InputCore = tw.input`relative w-full peer flex h-10 focus:outline-none appearance-none border border-gray-300 rounded-full outline-none transition pl-4 pr-6 group-hover:border-green-500 focus:border-green-500 cursor-pointer`\nconst Label = tw.div`text-sm w-full font-bold mb-1 text-gray-500`\n\nconst ButtonCore = tw.button`appearance-none h-10 rounded-full flex justify-center items-center font-bold px-3`\nconst SwapButton = tw(ButtonCore)`\nmd:mt-5 border md:w-full border-gray-300 hover:border-green-500 hover:text-green-500 focus:border-green-500 focus:text-green-500 transition outline-none`\nconst PrimaryButton = tw(ButtonCore)`\nborder-0 bg-green-500 text-white uppercase`\nconst GuestOkButton = tw(PrimaryButton)`mx-auto w-5/6 mb-2`\nconst SearchButton = tw(PrimaryButton)`w-full mt-5`\n\nconst IconContainer = tw.a`z-20 absolute top-0 right-0 bottom-0 h-full flex items-center pr-2 cursor-pointer group-hover:text-green-500 peer-focus:text-green-500 text-gray-500 transition`\n\nconst MenuContainer = tw.div`z-20`\nconst Menu = tw.ul\u003c{ open: boolean }\u003e`\n  w-64 max-h-[240px] border z-20 shadow-lg transform transition ease-in-out bg-white rounded-3xl overflow-y-auto overflow-x-hidden\n  ${({ open }) =\u003e (open ? \"\" : \"opacity-0 -translate-y-4 pointer-events-none\")}\n`\nconst Text = tw.p`text-sm font-bold text-gray-700 font-title`\nconst SmallText = tw.p`text-sm text-gray-500`\n\nconst OptionBase = tw.div`transition ease-in-out relative py-2 px-4`\nconst OptionContainer = tw(OptionBase)\u003c{\n  $active?: boolean\n  $selected?: boolean\n}\u003e`cursor-pointer transition ${({ $active, $selected }) =\u003e\n  $active || $selected ? \"bg-green-100\" : \"\"}`\n\nconst GuestButton = tw.button`appearance-none rounded-full p-2 flex items-center justify-center h-full overflow-hidden border border-gray-500 text-gray-500 hover:text-white hover:bg-green-500 hover:border-transparent transition ease-in-out disabled:opacity-50`\n```\n\nAnd finally add 2 more components.\n\nThe first one would be `InputComponent` used as an `input` in the main form:\n```jsx\ntype InputProps = {\n  form?: BookingFormType\n  isLoading?: boolean\n  name?: string\n  containerRef?: React.RefObject\u003cHTMLDivElement\u003e\n}\n\nconst iconsList = {\n  location: FaMapMarkerAlt,\n  date: FaCalendarAlt,\n  peopleCount: FaUser,\n}\n\nconst InputComponent = React.forwardRef\u003cHTMLInputElement, InputProps\u003e(\n  ({ isLoading, containerRef, form, name, ...props }, ref) =\u003e {\n    const itemType = name \u0026\u0026 form?.formSchema[name].type\n    const InputIcon = isLoading ? FaSpinner : iconsList[itemType || \"location\"]\n\n    return (\n      \u003cdiv className=\"relative w-full group\" ref={containerRef}\u003e\n        \u003cInputCore data-input ref={ref} name={name} {...props} /\u003e\n        \u003cIconContainer title=\"toggle\" data-toggle\u003e\n          \u003cInputIcon className={`w-4 h-4 ${isLoading ? \"animate-spin\" : \"\"}`} /\u003e\n        \u003c/IconContainer\u003e\n      \u003c/div\u003e\n    )\n  }\n)\n```\n\nAnd `GuestOptionComponent` to be used in our guest selector menu:\n\n```jsx\nconst GuestOptionComponent = ({\n  form,\n  name,\n  option,\n}: {\n  form: BookingFormType\n  name: string\n  option: GuestOption\n}) =\u003e (\n  \u003cOptionBase className=\"flex items-center justify-between\"\u003e\n    \u003cdiv\u003e\n      \u003cText\u003e{option.label}\u003c/Text\u003e\n      \u003cSmallText\u003e{option.description}\u003c/SmallText\u003e\n    \u003c/div\u003e\n    \u003cdiv className=\"flex items-center justify-center gap-x-2\"\u003e\n      \u003cGuestButton\n        onClick={form.onPlusClick(option, name)}\n        disabled={form.getIsOptionDisabled(option, \"plus\")}\n      \u003e\n        \u003cFaPlus className=\"w-3 h-3\" /\u003e\n      \u003c/GuestButton\u003e\n      \u003cText\u003e{option.value}\u003c/Text\u003e\n      \u003cGuestButton\n        onClick={form.onMinusClick(option, name)}\n        disabled={form.getIsOptionDisabled(option, \"minus\")}\n      \u003e\n        \u003cFaMinus className=\"w-3 h-3\" /\u003e\n      \u003c/GuestButton\u003e\n    \u003c/div\u003e\n  \u003c/OptionBase\u003e\n)\n```\t\n\u003c/details\u003e\n  \n\u003cdetails\u003e\n\n\u003csummary\u003e 👉 Documentation\u003c/summary\u003e\n\n## Basic\n\nHere's the form schema object. This is the main library configuration:\n\n```js\nconst formSchema: FormSchema = {\n  location: {\n    type: \"location\",\n    focusOnNext: \"checkIn\",\n    options: { defaultLocationOptions, searchPlace },\n  },\n  checkIn: {\n    type: \"date\",\n    focusOnNext: \"checkOut\",\n    options: {\n\t// These are entirely flatpickr options\n      altInput: true,\n      altFormat: \"M j, Y\",\n      dateFormat: \"Y-m-d\",\n      minDate: \"today\",\n      wrap: true,\n    },\n  },\n  checkOut: {\n    type: \"date\",\n    focusOnNext: \"guests\",\n    options: {\n\t// These are entirely flatpickr options\n      minDateFrom: \"checkIn\",\n      altInput: true,\n      altFormat: \"M j, Y\",\n      dateFormat: \"Y-m-d\",\n      wrap: true,\n    },\n  },\n  guests: {\n    type: \"peopleCount\",\n    defaultValue: [\n      {\n        name: \"adults\",\n        label: \"Adults\",\n        description: \"Ages 13+\",\n        value: 1,\n        min: 0,\n        max: 10,\n      },\n      {\n        name: \"children\",\n        label: \"Children\",\n        description: \"Ages 4-12\",\n        value: 0,\n        min: 0,\n        max: 10,\n      },\n      {\n        name: \"infants\",\n        label: \"Infants\",\n        description: \"Under 4 years old\",\n        value: 0,\n        min: 0,\n        max: 10,\n      },\n    ],\n  },\n}\n```\n\nIt should be used by `useReactBookingForm` as:\n\n```js\nconst form = useReactBookingForm({ formSchema })\n```\n\nAnd later the `form` can be passed down to the `BookingForm` as:\n\n```jsx\nexport const BookingForm = () =\u003e {\n  const form = useReactBookingForm({ formSchema })\n\t\n  const onBookButtonClick = () =\u003e {\n    const config = {\n      convertDate: (dateValue: Date) =\u003e moment(dateValue).format(\"DD-MM-YYYY\"),\n    }\n    alert(form.serializeToURLParams(config))\n  }\n\n  return (\n    \u003cContainer\u003e\n      \u003cInputContainer\u003e\n        \u003cLabel\u003e{\"From\"}\u003c/Label\u003e\n        \u003cLocationSelect\n          form={form}\n          menu={Menu}\n          menuContainer={MenuContainer}\n          option={OptionContainer}\n          inputComponent={InputComponent}\n          name=\"from\"\n          emptyOption=\"Nothing was found :(\"\n          placeholder=\"Where are you going?\"\n        /\u003e\n      \u003c/InputContainer\u003e\n      \u003cInputContainer style={{ width: \"auto\" }}\u003e\n        \u003cSwapButton\n          title=\"Swap Locations\"\n          aria-label=\"Swap Locations\"\n          onClick={() =\u003e form.swapLocations()}\n        \u003e\n          \u003cIoMdSwap className=\"w-4 h-4\" /\u003e\n        \u003c/SwapButton\u003e\n      \u003c/InputContainer\u003e\n      \u003cInputContainer\u003e\n        \u003cLabel\u003e{\"To\"}\u003c/Label\u003e\n        \u003cLocationSelect\n          form={form}\n          menu={Menu}\n          menuContainer={MenuContainer}\n          option={OptionContainer}\n          inputComponent={InputComponent}\n          name=\"to\"\n          emptyOption=\"Nothing was found :(\"\n          placeholder=\"Where are you going?\"\n        /\u003e\n      \u003c/InputContainer\u003e\n      \u003cInputContainer\u003e\n        \u003cLabel\u003e{\"Check in\"}\u003c/Label\u003e\n        \u003cDateInput\n          inputComponent={InputComponent}\n          className=\"w-full\"\n          placeholder=\"Add date\"\n          form={form}\n          name=\"checkIn\"\n        /\u003e\n      \u003c/InputContainer\u003e\n      \u003cInputContainer\u003e\n        \u003cLabel\u003e{\"Check out\"}\u003c/Label\u003e\n        \u003cDateInput\n          inputComponent={InputComponent}\n          className=\"w-full\"\n          placeholder=\"Add date\"\n          form={form}\n          name=\"checkOut\"\n        /\u003e\n      \u003c/InputContainer\u003e\n      \u003cInputContainer\u003e\n        \u003cLabel\u003e{\"Guests\"}\u003c/Label\u003e\n        \u003cGuestSelect\n          form={form}\n          menuContainer={MenuContainer}\n          menu={Menu}\n          inputComponent={InputComponent}\n          option={GuestOptionComponent}\n          okButton={GuestOkButton}\n          okText=\"Ok!\"\n          placeholder=\"Add guests\"\n          name={\"guests\"}\n        /\u003e\n      \u003c/InputContainer\u003e\n      \u003cInputContainer\u003e\n        \u003cSearchButton onClick={onBookButtonClick}\u003e{\"Search\"}\u003c/SearchButton\u003e\n      \u003c/InputContainer\u003e\n    \u003c/Container\u003e\n  )\n}\n```\n\n## Form object\n\t\nThe `form` that's returned in the example above is an object that can be used to read current form state\n\tas well as call different callbacks on form input fields and much more.\n\nThis is the `form` type:\n\n```ts\nexport type BookingForm = {\n  /**\n   * Form schema provided by the user.\n   */\n  formSchema: FormSchema\n  /**\n   * Current form state.\n   */\n  state: FormState\n  setState: (state: FormState) =\u003e void\n  /**\n   * Helper that sets the particular field value in the form.\n   */\n  setFieldValue: (key: string, value: any) =\u003e void\n  /**\n   * Helper that sets the particular field state in the form.\n   */\n  setFieldState: (key: string, state: any) =\u003e void\n  /**\n   * An array of references to the form fields.\n   * This can be used to focus on a particular field and do other relevant actions.\n   */\n  refs: RefsType\n  /**\n   * Helper that allows to focus on a particular field just by passing field key to it.\n   */\n  focusOn: (key?: string) =\u003e void\n  /**\n   * This is a helper that allows to change a particular option item state.\n   * For example, if you want to increment the number of \"adults\", you can use this helper as:\n   * ```\n   * form.setGuestOptionValue(name, option, option.value + 1)\n   * ```\n   */\n  setGuestOptionValue: (key: string, option: any, value: any) =\u003e void\n  /**\n   * A callback to pass to the guest minus button click event.\n   */\n  onMinusClick: (option: GuestOption, name: string) =\u003e () =\u003e void\n  /**\n   * A callback to pass to the guest plus button click event.\n   */\n  onPlusClick: (option: GuestOption, name: string) =\u003e () =\u003e void\n  /**\n   * A callback to pass to the guest buttons to determine if the buttons are disabled.\n   */\n  getIsOptionDisabled: (\n    option: GuestOption,\n    optionType: \"plus\" | \"minus\"\n  ) =\u003e boolean\n  /**\n   * This can be used to swap the location fields.\n   */\n  swapLocations: (fieldKeys?: [string, string] | undefined) =\u003e void\n  /**\n   * Converts the form state to url query string.\n   * Use convertDate to convert dates to the desired format.\n   */\n  serializeToURLParams: ({\n    convertDate,\n  }: {\n    convertDate?: (dateValue: Date) =\u003e any\n  }) =\u003e string\n}\n```\n\n## Form state object\n\n```ts\nexport type FormState = {\n  [key: string]: {\n    type: FieldType\n    value: FieldValue\n    /**\n     * Used to know total number of guests in guest selector.\n     */\n    totalCount?: number\n  }\n}\n```\n\t\n## Schema object\n\t\t\n| Name         \t| Type                                        \t| Required \t| Description                                                                                                                                                                                          \t| Example                                                                                                                          \t|\n|--------------\t|---------------------------------------------\t|----------\t|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\t|----------------------------------------------------------------------------------------------------------------------------------\t|\n| type         \t| `\"location\" \\| \"date\" \\| \"peopleCount\"`     \t| ✅         | The type of the field                                                                                                                                                                                \t| \"location\"                                                                                                                       \t|\n| focusOnNext  \t| `string`                                    \t|          \t| The key of some form schema object item to focus upon after selecting this field                                                                                                                     \t| \"checkIn\" (if checkIn key exists in the `formSchema` object)                                                                     \t|\n| defaultValue \t| `LocationOption \\| GuestOption[] \\| string` \t|          \t| Default value of the field. In case of the type of the form field being \"location\", it should be of LocationOption type. Should be an array of `GuestOption`'s in case of \"peopleCount\" respectively \t| Location example: ``` {   label: \"New York\",   value: \"new-york\" } ```  Guest Example:  ``` {   value: 1,   name: \"adults\" } ``` \t|\n| options      \t| `Options`                                   \t|          \t| Options object. Refer to its schema (defined below)                                                                                                                                                  \t|                                                                                                                                  \t|\t\t\n\n## Options\n\n| Name                     \t| Type                                   \t| Description                                                                                                                                          \t|\n|--------------------------\t|----------------------------------------\t|------------------------------------------------------------------------------------------------------------------------------------------------------\t|\n| `defaultLocationOptions` \t| `LocationOption[]`                     \t| If the field type is \"location\" then it accepts these locations as default values                                                                    \t|\n| `searchPlace`            \t| `(queryString:string) =\u003e Promise\u003cany\u003e` \t| A function that fetches the location data. Refer to the TypeScript example in the repo documentation.                                                \t|\n| `[key: string]`          \t| `any`                                  \t| **Parameters that will be passed down to the flatpickr React component. [Here's a list of options you can pass](https://flatpickr.js.org/options/)** \t|\n\n\u003c/details\u003e\n\n## Contribution Guide\n- Clone the repository to your local machine;\n- Run `yarn` in the root\n- Run `yarn start`\n- Go to `localhost:6006` and see magic happen 🚀\n\nWhenever finished, create a PR on a separate branch for review.\n\nContributions are very welcome!\n\n## License\n[MIT](https://github.com/max-sym/react-booking-form/blob/main/LICENSE) \n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmax-sym%2Freact-booking-form","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmax-sym%2Freact-booking-form","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmax-sym%2Freact-booking-form/lists"}