{"id":14156670,"url":"https://github.com/mayashavin/vurian-wizard","last_synced_at":"2025-10-10T16:15:38.352Z","repository":{"id":66182921,"uuid":"454963261","full_name":"mayashavin/vurian-wizard","owner":"mayashavin","description":"A Wizard Vue component on Vue 3 and state machine","archived":false,"fork":false,"pushed_at":"2022-02-04T13:31:47.000Z","size":506,"stargazers_count":84,"open_issues_count":4,"forks_count":0,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-01T23:34:48.976Z","etag":null,"topics":["component-library","form","tabs-management","vue","vue3","vuejs","wizard","wizard-steps","xstate"],"latest_commit_sha":null,"homepage":"","language":"Vue","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/mayashavin.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":"2022-02-02T22:59:20.000Z","updated_at":"2024-08-13T20:00:45.000Z","dependencies_parsed_at":"2023-02-26T19:30:51.996Z","dependency_job_id":null,"html_url":"https://github.com/mayashavin/vurian-wizard","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/mayashavin/vurian-wizard","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mayashavin%2Fvurian-wizard","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mayashavin%2Fvurian-wizard/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mayashavin%2Fvurian-wizard/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mayashavin%2Fvurian-wizard/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mayashavin","download_url":"https://codeload.github.com/mayashavin/vurian-wizard/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mayashavin%2Fvurian-wizard/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279004685,"owners_count":26083748,"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","status":"online","status_checked_at":"2025-10-10T02:00:06.843Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["component-library","form","tabs-management","vue","vue3","vuejs","wizard","wizard-steps","xstate"],"created_at":"2024-08-17T08:07:46.549Z","updated_at":"2025-10-10T16:15:38.304Z","avatar_url":"https://github.com/mayashavin.png","language":"Vue","funding_links":[],"categories":["vuejs"],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e@vurian/wizard - A wizard machine component for Vue 3\u003c/h1\u003e\n\n\u003c!-- badge --\u003e\n[![Netlify Status](https://api.netlify.com/api/v1/badges/86174d7f-1c39-41e4-879a-8c28809b854d/deploy-status)](https://app.netlify.com/sites/vurianjs/deploys)\n[![npm version](https://img.shields.io/npm/v/@vurian/wizard.svg)](https://www.npmjs.com/package/@vurian/wizard)\n[![npm download](https://img.shields.io/npm/dt/@vurian/wizard.svg)](https://www.npmjs.com/package/@vurian/wizard)\n\u003c!-- endbadge --\u003e\n\n![Vurian logo](./docs/static/preview.png)\n\nThe more organized and out-of-the-box for Wizard Component from the Vurian project, written in TypeScript and using [XState](https://xstate.js.org).\n\n📚 Documentation: [https://vurianjs.netlify.app](https://vurianjs.netlify.app)\n\n🎮 Playground: TBD\n\n💻 Demo: TBD\n\n## Example\n\nAn example of how to define and use the component as shown below:\n\n## 1. Define the data context for the Wizard\n\nIn the `script` we will need to define the wizard context, with any data related to the general flow of the wizard per need. However, you need to initialize at least 2 fields: `completedSteps` and `currentView`\n\nIn the example below we define a wizard with `shipping`, `paymentMethod`, `cart`, `shippingMethod`, `billing` and a flag for `agreeToTerms` as the common data needed for a checkout wizard.\n\n```vue\n\u003cscript setup\u003e\n\nconst context = {\n  completedSteps: [],\n  cart: [],\n  shipping: {\n    address: '',\n    phone: '',\n    email: '',\n    id: ''\n  },\n  shippingMethod: '',\n  billing: {\n    address: '',\n  },\n  agreeToTerms: false,\n  paymentMethod: ''\n}\n\n\u003c/script\u003e\n```\n\n## 2. Define the steps (or states) of the Wizard\n\nNow let's pass the configuration of the steps (or states) for the wizard to handle. For each step, it's essential to provide the following:\n\n* `id` - id of the state.\n* `title` - title of the state to display on the progress flow in the wizard header.\n* `stepView` - this is the component to render for the relevant state.\n* `order` - order of appearance of the state in the flow. This will be used to initialize which state to go next/prev.\n\nThe `states` is an object contains all the steps needed, following the above format, as seen below:\n\n```js\nconst states = {\n  review: {\n    title: 'Review',\n      id: 'review',\n      stepView: ReviewCart,\n      order: 0,\n      meta: {\n        description: 'Review your cart',\n      },\n  }\n}\n```\n\nIf you wish to add internal events such as updating shipping address, payment method, etc, you can create your own events by using the property `on`. However, to handle updating any context data of the wizard will require using `assign` function from `xstate`.\n\nBelow is the example of the configuration for step/state `shipping` in `states`\n\n```js\nconst states = {\n  /*...*/\n  shipping: {\n    title: 'Shipping',\n    id: 'shipping',\n    stepView: Shipping,\n    order: 1,\n    on: {\n      //event to update address to be triggered inside Shipping component\n      UPDATE_ADDRESS: {\n        actions: assign({\n          shipping: (_, event) =\u003e  event.address\n        }),\n        meta: {\n          description: 'Provide shipping address'\n        }\n      },\n      //event to update shipping method to be triggered inside Shipping component\n      SELECT_METHOD: {\n        actions: assign({\n          shippingMethod: (_, event) =\u003e event.method \n        }),\n        meta: {\n          description: 'Select shipping method'\n        }\n      },\n    },\n  },\n}\n```\n\n\u003calert type='info'\u003e\n\nIf it is the final step, and you don't wish to enable the prev button, you can set `state.type` to `final`.\n\n\u003c/alert\u003e\n\nBy default next/prev is handled automatically without being defined in the state configuration. However, in certain case you wish to add condition to enable/disable the next/prev functionality (as a step guard), such as in payment it is a must to complete the payment method and agreeing to the T\u0026C. \n\nIn this scenario you can use `on.NEXT.cond` and define the method to trigger for validation. \n\n```js\nconst states = {\n  /*...*/\n  payment: {\n    title: 'Payment',\n    id: 'payment',\n    stepView: Payment,\n    order: 3,\n    on: {\n      /*...*/\n      NEXT: {\n        cond: 'isAgreeToTerm'\n      }\n    }\n  },\n}\n```\n\nThe actual method implementation should be provide in step 3 below - define options.\n\n## 3. Define additional options (validation per step, etc)\n\nOptions are the external configurations to setup for the wizard, based on [Xstate options](https://xstate.js.org/docs/guides/machines.html#options). It can receive `guards`, `actions`, `delays`, `activities`, and `services`.\n\nIn our example we will set the guard validation for `NEXT` event in Payment Step.\n\n```js\nconst options= {\n  guards: {\n    isAgreeToTerm: (ctx) =\u003e ctx.agreeToTerms \u0026\u0026 !!ctx.paymentMethod,\n  }\n}\n```\n\nUpon user reaches to Payment step, the Next button will be disabled until user fulfills all the inputs required (`agreedToTerms` and `paymentMethod`). Out of the box!\n\n## 4. Add `onComplete` event listener\n\nWe can also pass an event handler to the wizard to trigger when all the steps is completed.\n\n```js\nconst onComplete = async() =\u003e {\n  //redirecting to home page\n}\n```\n\n## 5. Define the wizard's id and initial step\n\nTwo last configuration props we need to initialize is `id` and `initial` as `id` is required to create wizard state machine, and `initial` defines the first step for the wizard to start from. \n\n`initial` can be the key of the state defined in `states`, or the `id` of that state.\n\n```js\nconst id = \"checkout\"\nconst initial = \"review\", //start with the review step\n```\n\n## 6. Bind to `VrWizard` component\n\nAnd finally, we need to pass those variables to the `VrWizard` component.\n\n```vue\n\u003ctemplate\u003e\n  \u003cVrWizard \n    :options=\"options\" \n    :id=\"id\" \n    :context=\"context\" \n    :states=\"states\" \n    :initial=\"initial\"\n    :onComplete=\"onComplete\"\n    title=\"My Vurian Checkout Wizard\"\n    description=\"Just checking out\"\n  /\u003e\n\u003c/template\u003e\n```\n\nAnd the full code will look something similar to the below code:\n\n```vue\n\u003cscript setup\u003e\nimport VrWizard from '@vurian/wizard';\nimport ReviewCart from './components/Steps/ReviewCart.vue';\nimport Payment from './components/Steps/Payment.vue';\nimport Confirmation from './components/Steps/Confirmation.vue';\nimport Shipping from './components/Steps/Shipping.vue';\nimport Billing from './components/Steps/Billing.vue';\nimport { assign } from \"xstate\";\n\nconst config = {\n  id: \"checkout\",\n  initial: \"review\",\n  context: {\n    completedSteps: [],\n    cart: [],\n    shipping: {\n      address: '',\n      phone: '',\n      email: '',\n      id: ''\n    },\n    shippingMethod: '',\n    billing: {\n      address: '',\n    },\n    agreeToTerms: false,\n    paymentMethod: ''\n  },\n  states: {\n    review: {\n      title: 'Review',\n      id: 'review',\n      meta: {\n        description: 'Review your cart',\n      },\n      stepView: ReviewCart,\n      order: 0,\n    },\n    shipping: {\n      title: 'Shipping',\n      id: 'shipping',\n      stepView: Shipping,\n      order: 1,\n      on: {\n        UPDATE_ADDRESS: {\n          actions: assign({\n            shipping: (_, event) =\u003e  event.address\n          }),\n          meta: {\n            description: 'Provide shipping address'\n          }\n        },\n        SELECT_METHOD: {\n          actions: assign({\n            shippingMethod: (_, event) =\u003e event.method \n          }),\n          meta: {\n            description: 'Select shipping method'\n          }\n        },\n      },\n      meta: {\n        description: 'Shipping address',\n      }\n    },\n    billing: {\n      title: 'Billing',\n      id: 'billing',\n      stepView: Billing,\n      order: 2,\n      on: {\n        ADD_BILLING_ADDRESS: {\n          meta: {\n            description: 'Enter billing address'\n          },\n          actions: assign({\n            billing: (context, event) =\u003e  ({\n              ...context.billing,\n              address: event.address\n            })\n          }),\n        },\n      },\n      meta: {\n        description: 'Billing address',\n      }\n    },\n    payment: {\n      title: 'Payment',\n      id: 'payment',\n      stepView: Payment,\n      order: 3,\n      on: {\n        SELECT_METHOD: {\n          meta: {\n            description: 'Select a payment method'\n          },\n          actions: assign({\n            paymentMethod: (_, event) =\u003e event.paymentMethod\n          })\n        },\n        AGREE_TO_TERM: {\n          meta: {\n            description: 'Confirm agree to terms \u0026 conditions'\n          },\n          actions: assign({\n            agreeToTerms: (_, event) =\u003e event.agreeToTerms\n          })\n        },\n        NEXT: {\n          cond: 'isAgreeToTerm'\n        }\n      },\n      meta: {\n        description: 'Payment',\n      },\n    },\n    success: {\n      title: 'Confirmation',\n      id: 'success',\n      stepView: Confirmation,\n      order: 4,\n      meta: {\n        description: 'Order confirmed',\n      },\n    },\n  },\n} \n\nconst options = {\n  guards: {\n    isAgreeToTerm: (ctx) =\u003e ctx.agreeToTerms \u0026\u0026 !!ctx.paymentMethod,\n  }\n}\n\nconst onComplete = () =\u003e {\n    /* do something */\n}\n\u003c/script\u003e\n\u003ctemplate\u003e\n  \u003cVrWizard \n    :options=\"options\" \n    :id=\"config.id\" \n    :context=\"config.context\" \n    :states=\"config.states\" \n    :initial=\"config.initial\"\n    :onComplete=\"onComplete\"\n    title=\"My Vurian Checkout Wizard\"\n    description=\"Just checking out\"\n  /\u003e\n\u003c/template\u003e\n```\n\n## Result\n\n![How the wizard of checkout process looks](https://res.cloudinary.com/mayashavin/image/upload/v1643979140/Vurian/Screen_Shot_2022-01-27_at_12.28.31.png)\n\nA video will come soon.\n\n## Visualize the wizard's flows\n\nYou can also visualize your steps by using [the visualizer from Stately](https://stately.ai/viz) (just need to define the next/prev yourself). There is plan for component visualizer to be coming soon :)!\n\nOur example wizard's flows above can be visualized as below:\n\n![This is the example how the flows of the wizard's steps](https://res.cloudinary.com/mayashavin/image/upload/v1643979061/Vurian/state_machines_visual.png)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmayashavin%2Fvurian-wizard","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmayashavin%2Fvurian-wizard","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmayashavin%2Fvurian-wizard/lists"}