diff --git a/README.md b/README.md index 485eda9..a8e86d0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,8 @@ # WhizFlow +![npm bundle size](https://img.shields.io/bundlephobia/minzip/whizflow) +![npm](https://img.shields.io/npm/dm/whizflow) +![npm](https://img.shields.io/npm/v/whizflow) +![node-current](https://img.shields.io/node/v/whizflow) WhizFlow is a lightweight, headless and extensible React library for building dynamic multi-step forms or troubleshooting workflows. @@ -120,8 +124,10 @@ export default YourComponent; - `step`: The current step object. - `answers`: An object containing the answers for each question in the workflow. +- `loading`: A boolean to mark when `handleNext` is waiting to resolve. - `setAnswers`: A function to update the `answers` object. - `handleNext`: A function to handle navigation to the next step in the workflow. +- `handlePrev`: A function to handle navigation to the previous step. - `renderQuestion`: A function to render the correct question type based on the provided dictionary. ### Step @@ -172,14 +178,17 @@ const questionTypes = { | | `onComplete` | `(answers: Answers) => void` |A callback function to be called when the workflow reaches the `done` step. (Optional) | | | `questionTypes` | `{ [key: string]: QuestionRenderFunction }` | An object with keys representing the question type and values as the corresponding render functions. (Optional) | | | `step` | `Step` | The current step object. (Render prop) | +| | `loading` | `boolean` | Whether `handleNext` is running asyncly. (Render prop) | | | `answers` | `Record` | An object containing the answers for each question in the workflow. (Render prop) | | | `setAnswers` | `(updatedAnswers: Record) => void` | A function to update the `answers` object. (Render prop) | | | `handleNext` | `(submitterAnswers?: Record) => void` | A function to handle navigation to the next step in the workflow, allows the submitter to update the answers. (Render prop) | +| | `handlePrev` | `() => void` | A function to handle navigation to the previous step in the workflow. (Render prop) | | | `renderQuestion` | `(questionId: string) => React.ReactNode` | A function to render the correct question type based on the provided dictionary. (Render prop) | | **Step** | | | An object defining a single step in the workflow. | | | `id` | `string` | A unique identifier for the step. | | | `questions` | `Question[]` | An array of `Question` objects. | -| | `next` | `(answers: Record) => string \| 'done'` | A function that determines the next step in the workflow based on the current answers. It should return the next step's ID or 'done' if the workflow is complete. | +| | `next` | `string \| { nextStepId: string; updatedAnswers?: Answers } ֿֿֿ\| Promise \| Promise<{ nextStepId: string; updatedAnswers?: Answers }>` | A function that determines the next step in the workflow based on the current answers. It should return the next step's ID or 'done' if the workflow is complete. | +| | `context?` | `any` | An optional context object for the question to pass (to be used later when rendering). | | **Question** | | | An object defining a single question within a step. | | | `id` | `string` | A unique identifier for the question. | | | `prompt` | `string` | The question's text. | diff --git a/dist/WhizFlow.d.ts.map b/dist/WhizFlow.d.ts.map index 696d49b..28fae86 100644 --- a/dist/WhizFlow.d.ts.map +++ b/dist/WhizFlow.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"WhizFlow.d.ts","sourceRoot":"","sources":["../src/WhizFlow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAGxC,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CAsC5C,CAAC"} \ No newline at end of file +{"version":3,"file":"WhizFlow.d.ts","sourceRoot":"","sources":["../src/WhizFlow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAGxC,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CA4C5C,CAAC"} \ No newline at end of file diff --git a/dist/WhizFlow.js b/dist/WhizFlow.js index 46e16dd..007b977 100644 --- a/dist/WhizFlow.js +++ b/dist/WhizFlow.js @@ -2,7 +2,7 @@ import { useWhizFlow } from './useWhizFlow'; export var WhizFlow = function (_a) { var workflow = _a.workflow, questionTypes = _a.questionTypes, children = _a.children, onComplete = _a.onComplete; var defaultOnComplete = function () { }; - var _b = useWhizFlow(workflow, onComplete !== null && onComplete !== void 0 ? onComplete : defaultOnComplete), step = _b.step, answers = _b.answers, setAnswers = _b.setAnswers, handleNext = _b.handleNext; + var _b = useWhizFlow(workflow, onComplete !== null && onComplete !== void 0 ? onComplete : defaultOnComplete), step = _b.step, answers = _b.answers, setAnswers = _b.setAnswers, handleNext = _b.handleNext, handlePrev = _b.handlePrev, loading = _b.loading; var renderQuestion = function (questionId) { var question = step.questions.find(function (q) { return q.id === questionId; }); if (!question) { @@ -20,6 +20,14 @@ export var WhizFlow = function (_a) { } return renderFunc(question, answers, setAnswers); }; - return children({ step: step, answers: answers, setAnswers: setAnswers, handleNext: handleNext, renderQuestion: renderQuestion }); + return children({ + step: step, + answers: answers, + loading: loading, + setAnswers: setAnswers, + handleNext: handleNext, + renderQuestion: renderQuestion, + handlePrev: handlePrev, + }); }; //# sourceMappingURL=WhizFlow.js.map \ No newline at end of file diff --git a/dist/WhizFlow.js.map b/dist/WhizFlow.js.map index 727f8dc..f0322d4 100644 --- a/dist/WhizFlow.js.map +++ b/dist/WhizFlow.js.map @@ -1 +1 @@ -{"version":3,"file":"WhizFlow.js","sourceRoot":"","sources":["../src/WhizFlow.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,CAAC,IAAM,QAAQ,GAA4B,UAAC,EAKjD;QAJC,QAAQ,cAAA,EACR,aAAa,mBAAA,EACb,QAAQ,cAAA,EACR,UAAU,gBAAA;IAEV,IAAM,iBAAiB,GAAG,cAAO,CAAC,CAAC;IAC7B,IAAA,KAA4C,WAAW,CAC3D,QAAQ,EACR,UAAU,aAAV,UAAU,cAAV,UAAU,GAAI,iBAAiB,CAChC,EAHO,IAAI,UAAA,EAAE,OAAO,aAAA,EAAE,UAAU,gBAAA,EAAE,UAAU,gBAG5C,CAAC;IAEF,IAAM,cAAc,GAAG,UAAC,UAAkB;QACxC,IAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,UAAC,CAAC,IAAK,OAAA,CAAC,CAAC,EAAE,KAAK,UAAU,EAAnB,CAAmB,CAAC,CAAC;QAEjE,IAAI,CAAC,QAAQ,EAAE;YACb,OAAO,CAAC,KAAK,CAAC,6BAAqB,UAAU,kBAAc,CAAC,CAAC;YAC7D,OAAO,IAAI,CAAC;SACb;QAED,IAAI,CAAC,aAAa,EAAE;YAClB,OAAO,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;YAC5C,OAAO,IAAI,CAAC;SACb;QAED,IAAM,UAAU,GAAG,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QAErD,IAAI,CAAC,UAAU,EAAE;YACf,OAAO,CAAC,KAAK,CACX,0BAAkB,QAAQ,CAAC,SAAS,gDAA4C,CACjF,CAAC;YACF,OAAO,IAAI,CAAC;SACb;QAED,OAAO,UAAU,CAAC,QAAQ,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;IACnD,CAAC,CAAC;IAEF,OAAO,QAAQ,CAAC,EAAE,IAAI,MAAA,EAAE,OAAO,SAAA,EAAE,UAAU,YAAA,EAAE,UAAU,YAAA,EAAE,cAAc,gBAAA,EAAE,CAAC,CAAC;AAC7E,CAAC,CAAC"} \ No newline at end of file +{"version":3,"file":"WhizFlow.js","sourceRoot":"","sources":["../src/WhizFlow.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,CAAC,IAAM,QAAQ,GAA4B,UAAC,EAKjD;QAJC,QAAQ,cAAA,EACR,aAAa,mBAAA,EACb,QAAQ,cAAA,EACR,UAAU,gBAAA;IAEV,IAAM,iBAAiB,GAAG,cAAO,CAAC,CAAC;IAC7B,IAAA,KACJ,WAAW,CAAC,QAAQ,EAAE,UAAU,aAAV,UAAU,cAAV,UAAU,GAAI,iBAAiB,CAAC,EADhD,IAAI,UAAA,EAAE,OAAO,aAAA,EAAE,UAAU,gBAAA,EAAE,UAAU,gBAAA,EAAE,UAAU,gBAAA,EAAE,OAAO,aACV,CAAC;IAEzD,IAAM,cAAc,GAAG,UAAC,UAAkB;QACxC,IAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,UAAC,CAAC,IAAK,OAAA,CAAC,CAAC,EAAE,KAAK,UAAU,EAAnB,CAAmB,CAAC,CAAC;QAEjE,IAAI,CAAC,QAAQ,EAAE;YACb,OAAO,CAAC,KAAK,CAAC,6BAAqB,UAAU,kBAAc,CAAC,CAAC;YAC7D,OAAO,IAAI,CAAC;SACb;QAED,IAAI,CAAC,aAAa,EAAE;YAClB,OAAO,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;YAC5C,OAAO,IAAI,CAAC;SACb;QAED,IAAM,UAAU,GAAG,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QAErD,IAAI,CAAC,UAAU,EAAE;YACf,OAAO,CAAC,KAAK,CACX,0BAAkB,QAAQ,CAAC,SAAS,gDAA4C,CACjF,CAAC;YACF,OAAO,IAAI,CAAC;SACb;QAED,OAAO,UAAU,CAAC,QAAQ,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;IACnD,CAAC,CAAC;IAEF,OAAO,QAAQ,CAAC;QACd,IAAI,MAAA;QACJ,OAAO,SAAA;QACP,OAAO,SAAA;QACP,UAAU,YAAA;QACV,UAAU,YAAA;QACV,cAAc,gBAAA;QACd,UAAU,YAAA;KACX,CAAC,CAAC;AACL,CAAC,CAAC"} \ No newline at end of file diff --git a/dist/index.es.js b/dist/index.es.js index 72834be..7ca90b4 100644 --- a/dist/index.es.js +++ b/dist/index.es.js @@ -1,2 +1,2 @@ -import{useState as e}from"react";var n=function(n){var t=n.workflow,r=n.questionTypes,o=n.children,s=n.onComplete,i=function(n,t){var r=e(0),o=r[0],s=r[1],i=e({}),u=i[0],d=i[1],l=n[o];return{step:l,answers:u,setAnswers:d,handleNext:function(e){var r=null!=e?e:u,o=l.next(r),i="string"==typeof o?o:o.nextStepId,a="string"!=typeof o&&o.updatedAnswers?o.updatedAnswers:r;if("done"===i)t(a);else{d(a);var f=n.findIndex((function(e){return e.id===i}));if(-1===f)return void console.error('Error: Non-existent step "'.concat(i,'"'));s(f)}}}}(t,null!=s?s:function(){}),u=i.step,d=i.answers,l=i.setAnswers,a=i.handleNext;return o({step:u,answers:d,setAnswers:l,handleNext:a,renderQuestion:function(e){var n=u.questions.find((function(n){return n.id===e}));if(!n)return console.error('Question with ID "'.concat(e,'" not found.')),null;if(!r)return console.error("No question types defined."),null;var t=r[n.inputType];return t?t(n,d,l):(console.error('Question type "'.concat(n.inputType,'" not found in the provided questionTypes.')),null)}})};export{n as default}; +import{useState as e}from"react";function n(e,n,t,r){return new(t||(t=Promise))((function(o,i){function u(e){try{a(r.next(e))}catch(e){i(e)}}function l(e){try{a(r.throw(e))}catch(e){i(e)}}function a(e){var n;e.done?o(e.value):(n=e.value,n instanceof t?n:new t((function(e){e(n)}))).then(u,l)}a((r=r.apply(e,n||[])).next())}))}function t(e,n){var t,r,o,i,u={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:l(0),throw:l(1),return:l(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function l(l){return function(a){return function(l){if(t)throw new TypeError("Generator is already executing.");for(;i&&(i=0,l[0]&&(u=0)),u;)try{if(t=1,r&&(o=2&l[0]?r.return:l[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,l[1])).done)return o;switch(r=0,o&&(l=[2&l[0],o.value]),l[0]){case 0:case 1:o=l;break;case 4:return u.label++,{value:l[1],done:!1};case 5:u.label++,r=l[1],l=[0];continue;case 7:l=u.ops.pop(),u.trys.pop();continue;default:if(!(o=u.trys,(o=o.length>0&&o[o.length-1])||6!==l[0]&&2!==l[0])){u=0;continue}if(3===l[0]&&(!o||l[1]>o[0]&&l[1]=0&&(w(r([],y,!0)),a(e)),[2]}))}))}}}(i,null!=a?a:function(){}),c=s.step,f=s.answers,d=s.setAnswers,p=s.handleNext,v=s.handlePrev,h=s.loading;return l({step:c,answers:f,loading:h,setAnswers:d,handleNext:p,renderQuestion:function(e){var n=c.questions.find((function(n){return n.id===e}));if(!n)return console.error('Question with ID "'.concat(e,'" not found.')),null;if(!u)return console.error("No question types defined."),null;var t=u[n.inputType];return t?t(n,f,d):(console.error('Question type "'.concat(n.inputType,'" not found in the provided questionTypes.')),null)},handlePrev:v})};export{o as default}; //# sourceMappingURL=index.es.js.map diff --git a/dist/index.es.js.map b/dist/index.es.js.map index 26e4288..3fe0abf 100644 --- a/dist/index.es.js.map +++ b/dist/index.es.js.map @@ -1 +1 @@ -{"version":3,"file":"index.es.js","sources":["../src/useWhizFlow.ts","../src/WhizFlow.tsx"],"sourcesContent":["// src/useWhizFlow.ts\nimport { useState } from 'react';\nimport { Step, Answers } from './types';\n\nexport const useWhizFlow = (\n workflow: Step[],\n onComplete: (answers: Answers) => void\n) => {\n const [currentStep, setCurrentStep] = useState(0);\n const [answers, setAnswers] = useState({});\n\n const step = workflow[currentStep];\n\n const handleNext = (submitterAnswers?: Answers) => {\n const currAnswers = submitterAnswers ?? answers;\n const result = step.next(currAnswers);\n\n const nextStepId = typeof result === 'string' ? result : result.nextStepId;\n const updatedAnswers =\n typeof result !== 'string' && result.updatedAnswers\n ? result.updatedAnswers\n : currAnswers;\n\n if (nextStepId === 'done') {\n onComplete(updatedAnswers);\n } else {\n setAnswers(updatedAnswers);\n const nextStepIndex = workflow.findIndex(\n (step) => step.id === nextStepId\n );\n\n if (nextStepIndex === -1) {\n console.error(`Error: Non-existent step \"${nextStepId}\"`);\n return;\n }\n\n setCurrentStep(nextStepIndex);\n }\n };\n\n return {\n step,\n answers,\n setAnswers,\n handleNext,\n };\n};\n","import React from 'react';\nimport { WhizFlowProps } from './types';\nimport { useWhizFlow } from './useWhizFlow';\n\nexport const WhizFlow: React.FC = ({\n workflow,\n questionTypes,\n children,\n onComplete,\n}) => {\n const defaultOnComplete = () => {};\n const { step, answers, setAnswers, handleNext } = useWhizFlow(\n workflow,\n onComplete ?? defaultOnComplete\n );\n\n const renderQuestion = (questionId: string) => {\n const question = step.questions.find((q) => q.id === questionId);\n\n if (!question) {\n console.error(`Question with ID \"${questionId}\" not found.`);\n return null;\n }\n\n if (!questionTypes) {\n console.error(`No question types defined.`);\n return null;\n }\n\n const renderFunc = questionTypes[question.inputType];\n\n if (!renderFunc) {\n console.error(\n `Question type \"${question.inputType}\" not found in the provided questionTypes.`\n );\n return null;\n }\n\n return renderFunc(question, answers, setAnswers);\n };\n\n return children({ step, answers, setAnswers, handleNext, renderQuestion });\n};\n"],"names":["WhizFlow","_a","workflow","questionTypes","children","onComplete","_b","useState","currentStep","setCurrentStep","answers","setAnswers","step","handleNext","submitterAnswers","currAnswers","result","next","nextStepId","updatedAnswers","nextStepIndex","findIndex","id","console","error","useWhizFlow","renderQuestion","questionId","question","questions","find","q","renderFunc","inputType","concat"],"mappings":"iCAIO,ICAMA,EAAoC,SAACC,OAChDC,EAAQD,EAAAC,SACRC,EAAaF,EAAAE,cACbC,EAAQH,EAAAG,SACRC,EAAUJ,EAAAI,WAGJC,EDPmB,SACzBJ,EACAG,GAEM,IAAAJ,EAAgCM,EAAiB,GAAhDC,EAAWP,EAAA,GAAEQ,EAAcR,EAAA,GAC5BK,EAAwBC,EAAkB,CAAE,GAA3CG,EAAOJ,EAAA,GAAEK,EAAUL,EAAA,GAEpBM,EAAOV,EAASM,GA6BtB,MAAO,CACLI,KAAIA,EACJF,QAAOA,EACPC,WAAUA,EACVE,WA/BiB,SAACC,GAClB,IAAMC,EAAcD,QAAAA,EAAoBJ,EAClCM,EAASJ,EAAKK,KAAKF,GAEnBG,EAA+B,iBAAXF,EAAsBA,EAASA,EAAOE,WAC1DC,EACc,iBAAXH,GAAuBA,EAAOG,eACjCH,EAAOG,eACPJ,EAEN,GAAmB,SAAfG,EACFb,EAAWc,OACN,CACLR,EAAWQ,GACX,IAAMC,EAAgBlB,EAASmB,WAC7B,SAACT,GAAS,OAAAA,EAAKU,KAAOJ,CAAZ,IAGZ,IAAuB,IAAnBE,EAEF,YADAG,QAAQC,MAAM,oCAA6BN,EAAU,MAIvDT,EAAeW,EAChB,CACH,EAQF,CCnCoDK,CAChDvB,EACAG,QAAAA,EAHwB,cAClBO,EAAIN,EAAAM,KAAEF,EAAOJ,EAAAI,QAAEC,EAAUL,EAAAK,WAAEE,EAAUP,EAAAO,WA8B7C,OAAOT,EAAS,CAAEQ,KAAIA,EAAEF,QAAOA,EAAEC,WAAUA,EAAEE,WAAUA,EAAEa,eAzBlC,SAACC,GACtB,IAAMC,EAAWhB,EAAKiB,UAAUC,MAAK,SAACC,GAAM,OAAAA,EAAET,KAAOK,CAAU,IAE/D,IAAKC,EAEH,OADAL,QAAQC,MAAM,4BAAqBG,EAAU,iBACtC,KAGT,IAAKxB,EAEH,OADAoB,QAAQC,MAAM,8BACP,KAGT,IAAMQ,EAAa7B,EAAcyB,EAASK,WAE1C,OAAKD,EAOEA,EAAWJ,EAAUlB,EAASC,IANnCY,QAAQC,MACN,kBAAAU,OAAkBN,EAASK,UAAqD,+CAE3E,KAIX,GAGF"} \ No newline at end of file +{"version":3,"file":"index.es.js","sources":["../src/useWhizFlow.ts","../src/WhizFlow.tsx"],"sourcesContent":["// src/useWhizFlow.ts\nimport { useState } from 'react';\nimport { Step, Answers } from './types';\n\nexport const useWhizFlow = (\n workflow: Step[],\n onComplete: (answers: Answers) => void\n) => {\n const [currentStep, setCurrentStep] = useState(0);\n const [answers, setAnswers] = useState({});\n const [loading, setLoading] = useState(false);\n const [trail, setTrail] = useState([]);\n\n const step = workflow[currentStep];\n\n const handlePrev = async () => {\n const prevStep = trail.pop();\n if (prevStep !== undefined && prevStep >= 0) {\n setTrail([...trail]);\n setCurrentStep(prevStep);\n }\n };\n\n const handleNext = async (submitterAnswers?: Answers) => {\n const currAnswers = submitterAnswers ?? answers;\n const result = step.next(currAnswers);\n\n let nextStepId = '';\n let updatedAnswers = currAnswers;\n if (typeof result === 'string') {\n nextStepId = result;\n updatedAnswers = currAnswers;\n } else if (typeof (result as Promise)?.then === 'function') {\n try {\n setLoading(true);\n const awaitedResult = await result;\n setLoading(false);\n if (typeof awaitedResult === 'string') {\n nextStepId = awaitedResult;\n } else {\n nextStepId = awaitedResult.nextStepId;\n updatedAnswers = awaitedResult.updatedAnswers ?? currAnswers;\n }\n } catch (ex) {\n console.error(`Error: Next step eval failed \"${ex}\"`);\n return;\n }\n } else if ((result as any)?.nextStepId) {\n nextStepId = (result as any).nextStepId;\n updatedAnswers = (result as any).updatedAnswers ?? currAnswers;\n }\n\n if (nextStepId === 'done') {\n onComplete(updatedAnswers);\n } else {\n setAnswers(updatedAnswers);\n const nextStepIndex = workflow.findIndex(\n (step) => step.id === nextStepId\n );\n\n if (nextStepIndex === -1) {\n console.error(`Error: Non-existent step \"${nextStepId}\"`);\n return;\n }\n\n setTrail([...trail, currentStep]);\n setCurrentStep(nextStepIndex);\n }\n };\n\n return {\n step,\n answers,\n loading,\n setAnswers,\n handleNext,\n handlePrev,\n };\n};\n","import React from 'react';\nimport { WhizFlowProps } from './types';\nimport { useWhizFlow } from './useWhizFlow';\n\nexport const WhizFlow: React.FC = ({\n workflow,\n questionTypes,\n children,\n onComplete,\n}) => {\n const defaultOnComplete = () => {};\n const { step, answers, setAnswers, handleNext, handlePrev, loading } =\n useWhizFlow(workflow, onComplete ?? defaultOnComplete);\n\n const renderQuestion = (questionId: string) => {\n const question = step.questions.find((q) => q.id === questionId);\n\n if (!question) {\n console.error(`Question with ID \"${questionId}\" not found.`);\n return null;\n }\n\n if (!questionTypes) {\n console.error(`No question types defined.`);\n return null;\n }\n\n const renderFunc = questionTypes[question.inputType];\n\n if (!renderFunc) {\n console.error(\n `Question type \"${question.inputType}\" not found in the provided questionTypes.`\n );\n return null;\n }\n\n return renderFunc(question, answers, setAnswers);\n };\n\n return children({\n step,\n answers,\n loading,\n setAnswers,\n handleNext,\n renderQuestion,\n handlePrev,\n });\n};\n"],"names":["WhizFlow","_a","workflow","questionTypes","children","onComplete","_b","useState","currentStep","setCurrentStep","answers","setAnswers","_c","loading","setLoading","_d","trail","setTrail","step","handleNext","submitterAnswers","__awaiter","currAnswers","result","next","nextStepId","updatedAnswers","then","awaitedResult","sent","console","error","ex_1","nextStepIndex","findIndex","id","__spreadArray","handlePrev","undefined","prevStep","pop","useWhizFlow","renderQuestion","questionId","question","questions","find","q","renderFunc","inputType","concat"],"mappings":"kkDAIO,ICAMA,EAAoC,SAACC,OAChDC,EAAQD,EAAAC,SACRC,EAAaF,EAAAE,cACbC,EAAQH,EAAAG,SACRC,EAAUJ,EAAAI,WAGJC,EDPmB,SACzBJ,EACAG,GAEM,IAAAJ,EAAgCM,EAAiB,GAAhDC,EAAWP,EAAA,GAAEQ,EAAcR,EAAA,GAC5BK,EAAwBC,EAAkB,CAAE,GAA3CG,EAAOJ,EAAA,GAAEK,EAAUL,EAAA,GACpBM,EAAwBL,GAAkB,GAAzCM,EAAOD,EAAA,GAAEE,EAAUF,EAAA,GACpBG,EAAoBR,EAAmB,IAAtCS,EAAKD,EAAA,GAAEE,EAAQF,EAAA,GAEhBG,EAAOhB,EAASM,GAyDtB,MAAO,CACLU,KAAIA,EACJR,QAAOA,EACPG,QAAOA,EACPF,WAAUA,EACVQ,WApDiB,SAAOC,GAA0B,OAAAC,OAAA,OAAA,OAAA,GAAA,mFAM9C,OALEC,EAAcF,QAAAA,EAAoBV,EAClCa,EAASL,EAAKM,KAAKF,GAErBG,EAAa,GACbC,EAAiBJ,EACC,iBAAXC,EAAmB,CAAA,EAAA,IAC5BE,EAAaF,EACbG,EAAiBJ,gBACR,GAA0C,mBAAlCC,aAAA,EAAAA,EAAyBI,MAAjC,MAAoD,CAAA,EAAA,oBAGrC,6BADtBb,GAAW,GACW,CAAA,EAAMS,iBAAtBK,EAAgBhB,EAAYiB,OAClCf,GAAW,GACkB,iBAAlBc,EACTH,EAAaG,GAEbH,EAAaG,EAAcH,WAC3BC,EAA6C,QAA5BzB,EAAA2B,EAAcF,sBAAc,IAAAzB,EAAAA,EAAIqB,gBAInD,kBADAQ,QAAQC,MAAM,wCAAiCC,EAAE,MAC1C,CAAA,8BAECT,eAAAA,EAAgBE,cAC1BA,EAAcF,EAAeE,WAC7BC,EAA+C,QAA7BpB,EAAAiB,EAAeG,sBAAc,IAAApB,EAAAA,EAAIgB,oBAGrD,GAAmB,SAAfG,EACFpB,EAAWqB,OACN,CAML,GALAf,EAAWe,GACLO,EAAgB/B,EAASgC,WAC7B,SAAChB,GAAS,OAAAA,EAAKiB,KAAOV,CAAZ,KAGW,IAAnBQ,EAEF,OADAH,QAAQC,MAAM,oCAA6BN,EAAU,MAC9C,CAAA,GAGTR,EAAamB,EAAAA,EAAA,GAAApB,GAAO,GAAA,CAAAR,QACpBC,EAAewB,EAChB,mBASDI,WA7DiB,WAAA,OAAAhB,OAAA,OAAA,OAAA,GAAA,wDAEAiB,KADXC,EAAWvB,EAAMwB,QACOD,GAAY,IACxCtB,EAAQmB,EAAA,GAAKpB,GAAK,IAClBP,EAAe8B,eA2DrB,CClEIE,CAAYvC,EAAUG,QAAAA,EAFE,cAClBa,EAAIZ,EAAAY,KAAER,EAAOJ,EAAAI,QAAEC,eAAYQ,EAAUb,EAAAa,WAAEkB,EAAU/B,EAAA+B,WAAExB,YA4B3D,OAAOT,EAAS,CACdc,KAAIA,EACJR,QAAOA,EACPG,QAAOA,EACPF,WAAUA,EACVQ,WAAUA,EACVuB,eA/BqB,SAACC,GACtB,IAAMC,EAAW1B,EAAK2B,UAAUC,MAAK,SAACC,GAAM,OAAAA,EAAEZ,KAAOQ,CAAU,IAE/D,IAAKC,EAEH,OADAd,QAAQC,MAAM,4BAAqBY,EAAU,iBACtC,KAGT,IAAKxC,EAEH,OADA2B,QAAQC,MAAM,8BACP,KAGT,IAAMiB,EAAa7C,EAAcyC,EAASK,WAE1C,OAAKD,EAOEA,EAAWJ,EAAUlC,EAASC,IANnCmB,QAAQC,MACN,kBAAAmB,OAAkBN,EAASK,UAAqD,+CAE3E,KAIX,EASEZ,WAAUA,GAEd"} \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index 3727577..1c4bee1 100644 --- a/dist/index.js +++ b/dist/index.js @@ -2,43 +2,161 @@ var react = require('react'); -// src/useWhizFlow.ts +/****************************************************************************** +Copyright (c) Microsoft Corporation. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +***************************************************************************** */ + +function __awaiter(thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +} + +function __generator(thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (g && (g = 0, op[0] && (_ = 0)), _) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +} + +function __spreadArray(to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); +} + var useWhizFlow = function (workflow, onComplete) { var _a = react.useState(0), currentStep = _a[0], setCurrentStep = _a[1]; var _b = react.useState({}), answers = _b[0], setAnswers = _b[1]; + var _c = react.useState(false), loading = _c[0], setLoading = _c[1]; + var _d = react.useState([]), trail = _d[0], setTrail = _d[1]; var step = workflow[currentStep]; - var handleNext = function (submitterAnswers) { - var currAnswers = submitterAnswers !== null && submitterAnswers !== void 0 ? submitterAnswers : answers; - var result = step.next(currAnswers); - var nextStepId = typeof result === 'string' ? result : result.nextStepId; - var updatedAnswers = typeof result !== 'string' && result.updatedAnswers - ? result.updatedAnswers - : currAnswers; - if (nextStepId === 'done') { - onComplete(updatedAnswers); - } - else { - setAnswers(updatedAnswers); - var nextStepIndex = workflow.findIndex(function (step) { return step.id === nextStepId; }); - if (nextStepIndex === -1) { - console.error("Error: Non-existent step \"".concat(nextStepId, "\"")); - return; + var handlePrev = function () { return __awaiter(void 0, void 0, void 0, function () { + var prevStep; + return __generator(this, function (_a) { + prevStep = trail.pop(); + if (prevStep !== undefined && prevStep >= 0) { + setTrail(__spreadArray([], trail, true)); + setCurrentStep(prevStep); } - setCurrentStep(nextStepIndex); - } - }; + return [2 /*return*/]; + }); + }); }; + var handleNext = function (submitterAnswers) { return __awaiter(void 0, void 0, void 0, function () { + var currAnswers, result, nextStepId, updatedAnswers, awaitedResult, ex_1, nextStepIndex; + var _a, _b; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + currAnswers = submitterAnswers !== null && submitterAnswers !== void 0 ? submitterAnswers : answers; + result = step.next(currAnswers); + nextStepId = ''; + updatedAnswers = currAnswers; + if (!(typeof result === 'string')) return [3 /*break*/, 1]; + nextStepId = result; + updatedAnswers = currAnswers; + return [3 /*break*/, 7]; + case 1: + if (!(typeof (result === null || result === void 0 ? void 0 : result.then) === 'function')) return [3 /*break*/, 6]; + _c.label = 2; + case 2: + _c.trys.push([2, 4, , 5]); + setLoading(true); + return [4 /*yield*/, result]; + case 3: + awaitedResult = _c.sent(); + setLoading(false); + if (typeof awaitedResult === 'string') { + nextStepId = awaitedResult; + } + else { + nextStepId = awaitedResult.nextStepId; + updatedAnswers = (_a = awaitedResult.updatedAnswers) !== null && _a !== void 0 ? _a : currAnswers; + } + return [3 /*break*/, 5]; + case 4: + ex_1 = _c.sent(); + console.error("Error: Next step eval failed \"".concat(ex_1, "\"")); + return [2 /*return*/]; + case 5: return [3 /*break*/, 7]; + case 6: + if (result === null || result === void 0 ? void 0 : result.nextStepId) { + nextStepId = result.nextStepId; + updatedAnswers = (_b = result.updatedAnswers) !== null && _b !== void 0 ? _b : currAnswers; + } + _c.label = 7; + case 7: + if (nextStepId === 'done') { + onComplete(updatedAnswers); + } + else { + setAnswers(updatedAnswers); + nextStepIndex = workflow.findIndex(function (step) { return step.id === nextStepId; }); + if (nextStepIndex === -1) { + console.error("Error: Non-existent step \"".concat(nextStepId, "\"")); + return [2 /*return*/]; + } + setTrail(__spreadArray(__spreadArray([], trail, true), [currentStep], false)); + setCurrentStep(nextStepIndex); + } + return [2 /*return*/]; + } + }); + }); }; return { step: step, answers: answers, + loading: loading, setAnswers: setAnswers, handleNext: handleNext, + handlePrev: handlePrev, }; }; var WhizFlow = function (_a) { var workflow = _a.workflow, questionTypes = _a.questionTypes, children = _a.children, onComplete = _a.onComplete; var defaultOnComplete = function () { }; - var _b = useWhizFlow(workflow, onComplete !== null && onComplete !== void 0 ? onComplete : defaultOnComplete), step = _b.step, answers = _b.answers, setAnswers = _b.setAnswers, handleNext = _b.handleNext; + var _b = useWhizFlow(workflow, onComplete !== null && onComplete !== void 0 ? onComplete : defaultOnComplete), step = _b.step, answers = _b.answers, setAnswers = _b.setAnswers, handleNext = _b.handleNext, handlePrev = _b.handlePrev, loading = _b.loading; var renderQuestion = function (questionId) { var question = step.questions.find(function (q) { return q.id === questionId; }); if (!question) { @@ -56,7 +174,15 @@ var WhizFlow = function (_a) { } return renderFunc(question, answers, setAnswers); }; - return children({ step: step, answers: answers, setAnswers: setAnswers, handleNext: handleNext, renderQuestion: renderQuestion }); + return children({ + step: step, + answers: answers, + loading: loading, + setAnswers: setAnswers, + handleNext: handleNext, + renderQuestion: renderQuestion, + handlePrev: handlePrev, + }); }; module.exports = WhizFlow; diff --git a/dist/index.js.map b/dist/index.js.map index b6ec1c1..25273df 100644 --- a/dist/index.js.map +++ b/dist/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","sources":["../src/useWhizFlow.ts","../src/WhizFlow.tsx"],"sourcesContent":["// src/useWhizFlow.ts\nimport { useState } from 'react';\nimport { Step, Answers } from './types';\n\nexport const useWhizFlow = (\n workflow: Step[],\n onComplete: (answers: Answers) => void\n) => {\n const [currentStep, setCurrentStep] = useState(0);\n const [answers, setAnswers] = useState({});\n\n const step = workflow[currentStep];\n\n const handleNext = (submitterAnswers?: Answers) => {\n const currAnswers = submitterAnswers ?? answers;\n const result = step.next(currAnswers);\n\n const nextStepId = typeof result === 'string' ? result : result.nextStepId;\n const updatedAnswers =\n typeof result !== 'string' && result.updatedAnswers\n ? result.updatedAnswers\n : currAnswers;\n\n if (nextStepId === 'done') {\n onComplete(updatedAnswers);\n } else {\n setAnswers(updatedAnswers);\n const nextStepIndex = workflow.findIndex(\n (step) => step.id === nextStepId\n );\n\n if (nextStepIndex === -1) {\n console.error(`Error: Non-existent step \"${nextStepId}\"`);\n return;\n }\n\n setCurrentStep(nextStepIndex);\n }\n };\n\n return {\n step,\n answers,\n setAnswers,\n handleNext,\n };\n};\n","import React from 'react';\nimport { WhizFlowProps } from './types';\nimport { useWhizFlow } from './useWhizFlow';\n\nexport const WhizFlow: React.FC = ({\n workflow,\n questionTypes,\n children,\n onComplete,\n}) => {\n const defaultOnComplete = () => {};\n const { step, answers, setAnswers, handleNext } = useWhizFlow(\n workflow,\n onComplete ?? defaultOnComplete\n );\n\n const renderQuestion = (questionId: string) => {\n const question = step.questions.find((q) => q.id === questionId);\n\n if (!question) {\n console.error(`Question with ID \"${questionId}\" not found.`);\n return null;\n }\n\n if (!questionTypes) {\n console.error(`No question types defined.`);\n return null;\n }\n\n const renderFunc = questionTypes[question.inputType];\n\n if (!renderFunc) {\n console.error(\n `Question type \"${question.inputType}\" not found in the provided questionTypes.`\n );\n return null;\n }\n\n return renderFunc(question, answers, setAnswers);\n };\n\n return children({ step, answers, setAnswers, handleNext, renderQuestion });\n};\n"],"names":["useState"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"index.js","sources":["../src/useWhizFlow.ts","../src/WhizFlow.tsx"],"sourcesContent":["// src/useWhizFlow.ts\nimport { useState } from 'react';\nimport { Step, Answers } from './types';\n\nexport const useWhizFlow = (\n workflow: Step[],\n onComplete: (answers: Answers) => void\n) => {\n const [currentStep, setCurrentStep] = useState(0);\n const [answers, setAnswers] = useState({});\n const [loading, setLoading] = useState(false);\n const [trail, setTrail] = useState([]);\n\n const step = workflow[currentStep];\n\n const handlePrev = async () => {\n const prevStep = trail.pop();\n if (prevStep !== undefined && prevStep >= 0) {\n setTrail([...trail]);\n setCurrentStep(prevStep);\n }\n };\n\n const handleNext = async (submitterAnswers?: Answers) => {\n const currAnswers = submitterAnswers ?? answers;\n const result = step.next(currAnswers);\n\n let nextStepId = '';\n let updatedAnswers = currAnswers;\n if (typeof result === 'string') {\n nextStepId = result;\n updatedAnswers = currAnswers;\n } else if (typeof (result as Promise)?.then === 'function') {\n try {\n setLoading(true);\n const awaitedResult = await result;\n setLoading(false);\n if (typeof awaitedResult === 'string') {\n nextStepId = awaitedResult;\n } else {\n nextStepId = awaitedResult.nextStepId;\n updatedAnswers = awaitedResult.updatedAnswers ?? currAnswers;\n }\n } catch (ex) {\n console.error(`Error: Next step eval failed \"${ex}\"`);\n return;\n }\n } else if ((result as any)?.nextStepId) {\n nextStepId = (result as any).nextStepId;\n updatedAnswers = (result as any).updatedAnswers ?? currAnswers;\n }\n\n if (nextStepId === 'done') {\n onComplete(updatedAnswers);\n } else {\n setAnswers(updatedAnswers);\n const nextStepIndex = workflow.findIndex(\n (step) => step.id === nextStepId\n );\n\n if (nextStepIndex === -1) {\n console.error(`Error: Non-existent step \"${nextStepId}\"`);\n return;\n }\n\n setTrail([...trail, currentStep]);\n setCurrentStep(nextStepIndex);\n }\n };\n\n return {\n step,\n answers,\n loading,\n setAnswers,\n handleNext,\n handlePrev,\n };\n};\n","import React from 'react';\nimport { WhizFlowProps } from './types';\nimport { useWhizFlow } from './useWhizFlow';\n\nexport const WhizFlow: React.FC = ({\n workflow,\n questionTypes,\n children,\n onComplete,\n}) => {\n const defaultOnComplete = () => {};\n const { step, answers, setAnswers, handleNext, handlePrev, loading } =\n useWhizFlow(workflow, onComplete ?? defaultOnComplete);\n\n const renderQuestion = (questionId: string) => {\n const question = step.questions.find((q) => q.id === questionId);\n\n if (!question) {\n console.error(`Question with ID \"${questionId}\" not found.`);\n return null;\n }\n\n if (!questionTypes) {\n console.error(`No question types defined.`);\n return null;\n }\n\n const renderFunc = questionTypes[question.inputType];\n\n if (!renderFunc) {\n console.error(\n `Question type \"${question.inputType}\" not found in the provided questionTypes.`\n );\n return null;\n }\n\n return renderFunc(question, answers, setAnswers);\n };\n\n return children({\n step,\n answers,\n loading,\n setAnswers,\n handleNext,\n renderQuestion,\n handlePrev,\n });\n};\n"],"names":["useState"],"mappings":"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"} \ No newline at end of file diff --git a/dist/index.min.js b/dist/index.min.js index 381915d..615fc7a 100644 --- a/dist/index.min.js +++ b/dist/index.min.js @@ -1,2 +1,2 @@ -"use strict";var e=require("react");module.exports=function(n){var t=n.workflow,r=n.questionTypes,o=n.children,s=n.onComplete,u=function(n,t){var r=e.useState(0),o=r[0],s=r[1],u=e.useState({}),i=u[0],d=u[1],l=n[o];return{step:l,answers:i,setAnswers:d,handleNext:function(e){var r=null!=e?e:i,o=l.next(r),u="string"==typeof o?o:o.nextStepId,a="string"!=typeof o&&o.updatedAnswers?o.updatedAnswers:r;if("done"===u)t(a);else{d(a);var c=n.findIndex((function(e){return e.id===u}));if(-1===c)return void console.error('Error: Non-existent step "'.concat(u,'"'));s(c)}}}}(t,null!=s?s:function(){}),i=u.step,d=u.answers,l=u.setAnswers,a=u.handleNext;return o({step:i,answers:d,setAnswers:l,handleNext:a,renderQuestion:function(e){var n=i.questions.find((function(n){return n.id===e}));if(!n)return console.error('Question with ID "'.concat(e,'" not found.')),null;if(!r)return console.error("No question types defined."),null;var t=r[n.inputType];return t?t(n,d,l):(console.error('Question type "'.concat(n.inputType,'" not found in the provided questionTypes.')),null)}})}; +"use strict";var e=require("react");function n(e,n,t,r){return new(t||(t=Promise))((function(o,u){function i(e){try{s(r.next(e))}catch(e){u(e)}}function l(e){try{s(r.throw(e))}catch(e){u(e)}}function s(e){var n;e.done?o(e.value):(n=e.value,n instanceof t?n:new t((function(e){e(n)}))).then(i,l)}s((r=r.apply(e,n||[])).next())}))}function t(e,n){var t,r,o,u,i={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return u={next:l(0),throw:l(1),return:l(2)},"function"==typeof Symbol&&(u[Symbol.iterator]=function(){return this}),u;function l(l){return function(s){return function(l){if(t)throw new TypeError("Generator is already executing.");for(;u&&(u=0,l[0]&&(i=0)),i;)try{if(t=1,r&&(o=2&l[0]?r.return:l[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,l[1])).done)return o;switch(r=0,o&&(l=[2&l[0],o.value]),l[0]){case 0:case 1:o=l;break;case 4:return i.label++,{value:l[1],done:!1};case 5:i.label++,r=l[1],l=[0];continue;case 7:l=i.ops.pop(),i.trys.pop();continue;default:if(!(o=i.trys,(o=o.length>0&&o[o.length-1])||6!==l[0]&&2!==l[0])){i=0;continue}if(3===l[0]&&(!o||l[1]>o[0]&&l[1]=0&&(w(r([],y,!0)),s(e)),[2]}))}))}}}(u,null!=s?s:function(){}),c=a.step,f=a.answers,d=a.setAnswers,p=a.handleNext,v=a.handlePrev,h=a.loading;return l({step:c,answers:f,loading:h,setAnswers:d,handleNext:p,renderQuestion:function(e){var n=c.questions.find((function(n){return n.id===e}));if(!n)return console.error('Question with ID "'.concat(e,'" not found.')),null;if(!i)return console.error("No question types defined."),null;var t=i[n.inputType];return t?t(n,f,d):(console.error('Question type "'.concat(n.inputType,'" not found in the provided questionTypes.')),null)},handlePrev:v})}; //# sourceMappingURL=index.min.js.map diff --git a/dist/index.min.js.map b/dist/index.min.js.map index 0f7b7fe..699f78c 100644 --- a/dist/index.min.js.map +++ b/dist/index.min.js.map @@ -1 +1 @@ -{"version":3,"file":"index.min.js","sources":["../src/WhizFlow.tsx","../src/useWhizFlow.ts"],"sourcesContent":["import React from 'react';\nimport { WhizFlowProps } from './types';\nimport { useWhizFlow } from './useWhizFlow';\n\nexport const WhizFlow: React.FC = ({\n workflow,\n questionTypes,\n children,\n onComplete,\n}) => {\n const defaultOnComplete = () => {};\n const { step, answers, setAnswers, handleNext } = useWhizFlow(\n workflow,\n onComplete ?? defaultOnComplete\n );\n\n const renderQuestion = (questionId: string) => {\n const question = step.questions.find((q) => q.id === questionId);\n\n if (!question) {\n console.error(`Question with ID \"${questionId}\" not found.`);\n return null;\n }\n\n if (!questionTypes) {\n console.error(`No question types defined.`);\n return null;\n }\n\n const renderFunc = questionTypes[question.inputType];\n\n if (!renderFunc) {\n console.error(\n `Question type \"${question.inputType}\" not found in the provided questionTypes.`\n );\n return null;\n }\n\n return renderFunc(question, answers, setAnswers);\n };\n\n return children({ step, answers, setAnswers, handleNext, renderQuestion });\n};\n","// src/useWhizFlow.ts\nimport { useState } from 'react';\nimport { Step, Answers } from './types';\n\nexport const useWhizFlow = (\n workflow: Step[],\n onComplete: (answers: Answers) => void\n) => {\n const [currentStep, setCurrentStep] = useState(0);\n const [answers, setAnswers] = useState({});\n\n const step = workflow[currentStep];\n\n const handleNext = (submitterAnswers?: Answers) => {\n const currAnswers = submitterAnswers ?? answers;\n const result = step.next(currAnswers);\n\n const nextStepId = typeof result === 'string' ? result : result.nextStepId;\n const updatedAnswers =\n typeof result !== 'string' && result.updatedAnswers\n ? result.updatedAnswers\n : currAnswers;\n\n if (nextStepId === 'done') {\n onComplete(updatedAnswers);\n } else {\n setAnswers(updatedAnswers);\n const nextStepIndex = workflow.findIndex(\n (step) => step.id === nextStepId\n );\n\n if (nextStepIndex === -1) {\n console.error(`Error: Non-existent step \"${nextStepId}\"`);\n return;\n }\n\n setCurrentStep(nextStepIndex);\n }\n };\n\n return {\n step,\n answers,\n setAnswers,\n handleNext,\n };\n};\n"],"names":["_a","workflow","questionTypes","children","onComplete","_b","useState","currentStep","setCurrentStep","answers","setAnswers","step","handleNext","submitterAnswers","currAnswers","result","next","nextStepId","updatedAnswers","nextStepIndex","findIndex","id","console","error","useWhizFlow","renderQuestion","questionId","question","questions","find","q","renderFunc","inputType","concat"],"mappings":"mDAIiD,SAACA,OAChDC,EAAQD,EAAAC,SACRC,EAAaF,EAAAE,cACbC,EAAQH,EAAAG,SACRC,EAAUJ,EAAAI,WAGJC,ECPmB,SACzBJ,EACAG,GAEM,IAAAJ,EAAgCM,EAAAA,SAAiB,GAAhDC,EAAWP,EAAA,GAAEQ,EAAcR,EAAA,GAC5BK,EAAwBC,EAAAA,SAAkB,CAAE,GAA3CG,EAAOJ,EAAA,GAAEK,EAAUL,EAAA,GAEpBM,EAAOV,EAASM,GA6BtB,MAAO,CACLI,KAAIA,EACJF,QAAOA,EACPC,WAAUA,EACVE,WA/BiB,SAACC,GAClB,IAAMC,EAAcD,QAAAA,EAAoBJ,EAClCM,EAASJ,EAAKK,KAAKF,GAEnBG,EAA+B,iBAAXF,EAAsBA,EAASA,EAAOE,WAC1DC,EACc,iBAAXH,GAAuBA,EAAOG,eACjCH,EAAOG,eACPJ,EAEN,GAAmB,SAAfG,EACFb,EAAWc,OACN,CACLR,EAAWQ,GACX,IAAMC,EAAgBlB,EAASmB,WAC7B,SAACT,GAAS,OAAAA,EAAKU,KAAOJ,CAAZ,IAGZ,IAAuB,IAAnBE,EAEF,YADAG,QAAQC,MAAM,oCAA6BN,EAAU,MAIvDT,EAAeW,EAChB,CACH,EAQF,CDnCoDK,CAChDvB,EACAG,QAAAA,EAHwB,cAClBO,EAAIN,EAAAM,KAAEF,EAAOJ,EAAAI,QAAEC,EAAUL,EAAAK,WAAEE,EAAUP,EAAAO,WA8B7C,OAAOT,EAAS,CAAEQ,KAAIA,EAAEF,QAAOA,EAAEC,WAAUA,EAAEE,WAAUA,EAAEa,eAzBlC,SAACC,GACtB,IAAMC,EAAWhB,EAAKiB,UAAUC,MAAK,SAACC,GAAM,OAAAA,EAAET,KAAOK,CAAU,IAE/D,IAAKC,EAEH,OADAL,QAAQC,MAAM,4BAAqBG,EAAU,iBACtC,KAGT,IAAKxB,EAEH,OADAoB,QAAQC,MAAM,8BACP,KAGT,IAAMQ,EAAa7B,EAAcyB,EAASK,WAE1C,OAAKD,EAOEA,EAAWJ,EAAUlB,EAASC,IANnCY,QAAQC,MACN,kBAAAU,OAAkBN,EAASK,UAAqD,+CAE3E,KAIX,GAGF"} \ No newline at end of file +{"version":3,"file":"index.min.js","sources":["../src/WhizFlow.tsx","../src/useWhizFlow.ts"],"sourcesContent":["import React from 'react';\nimport { WhizFlowProps } from './types';\nimport { useWhizFlow } from './useWhizFlow';\n\nexport const WhizFlow: React.FC = ({\n workflow,\n questionTypes,\n children,\n onComplete,\n}) => {\n const defaultOnComplete = () => {};\n const { step, answers, setAnswers, handleNext, handlePrev, loading } =\n useWhizFlow(workflow, onComplete ?? defaultOnComplete);\n\n const renderQuestion = (questionId: string) => {\n const question = step.questions.find((q) => q.id === questionId);\n\n if (!question) {\n console.error(`Question with ID \"${questionId}\" not found.`);\n return null;\n }\n\n if (!questionTypes) {\n console.error(`No question types defined.`);\n return null;\n }\n\n const renderFunc = questionTypes[question.inputType];\n\n if (!renderFunc) {\n console.error(\n `Question type \"${question.inputType}\" not found in the provided questionTypes.`\n );\n return null;\n }\n\n return renderFunc(question, answers, setAnswers);\n };\n\n return children({\n step,\n answers,\n loading,\n setAnswers,\n handleNext,\n renderQuestion,\n handlePrev,\n });\n};\n","// src/useWhizFlow.ts\nimport { useState } from 'react';\nimport { Step, Answers } from './types';\n\nexport const useWhizFlow = (\n workflow: Step[],\n onComplete: (answers: Answers) => void\n) => {\n const [currentStep, setCurrentStep] = useState(0);\n const [answers, setAnswers] = useState({});\n const [loading, setLoading] = useState(false);\n const [trail, setTrail] = useState([]);\n\n const step = workflow[currentStep];\n\n const handlePrev = async () => {\n const prevStep = trail.pop();\n if (prevStep !== undefined && prevStep >= 0) {\n setTrail([...trail]);\n setCurrentStep(prevStep);\n }\n };\n\n const handleNext = async (submitterAnswers?: Answers) => {\n const currAnswers = submitterAnswers ?? answers;\n const result = step.next(currAnswers);\n\n let nextStepId = '';\n let updatedAnswers = currAnswers;\n if (typeof result === 'string') {\n nextStepId = result;\n updatedAnswers = currAnswers;\n } else if (typeof (result as Promise)?.then === 'function') {\n try {\n setLoading(true);\n const awaitedResult = await result;\n setLoading(false);\n if (typeof awaitedResult === 'string') {\n nextStepId = awaitedResult;\n } else {\n nextStepId = awaitedResult.nextStepId;\n updatedAnswers = awaitedResult.updatedAnswers ?? currAnswers;\n }\n } catch (ex) {\n console.error(`Error: Next step eval failed \"${ex}\"`);\n return;\n }\n } else if ((result as any)?.nextStepId) {\n nextStepId = (result as any).nextStepId;\n updatedAnswers = (result as any).updatedAnswers ?? currAnswers;\n }\n\n if (nextStepId === 'done') {\n onComplete(updatedAnswers);\n } else {\n setAnswers(updatedAnswers);\n const nextStepIndex = workflow.findIndex(\n (step) => step.id === nextStepId\n );\n\n if (nextStepIndex === -1) {\n console.error(`Error: Non-existent step \"${nextStepId}\"`);\n return;\n }\n\n setTrail([...trail, currentStep]);\n setCurrentStep(nextStepIndex);\n }\n };\n\n return {\n step,\n answers,\n loading,\n setAnswers,\n handleNext,\n handlePrev,\n };\n};\n"],"names":["_a","workflow","questionTypes","children","onComplete","_b","useState","currentStep","setCurrentStep","answers","setAnswers","_c","loading","setLoading","_d","trail","setTrail","step","handleNext","submitterAnswers","__awaiter","currAnswers","result","next","nextStepId","updatedAnswers","then","awaitedResult","sent","console","error","ex_1","nextStepIndex","findIndex","id","__spreadArray","handlePrev","undefined","prevStep","pop","useWhizFlow","renderQuestion","questionId","question","questions","find","q","renderFunc","inputType","concat"],"mappings":"olDAIiD,SAACA,OAChDC,EAAQD,EAAAC,SACRC,EAAaF,EAAAE,cACbC,EAAQH,EAAAG,SACRC,EAAUJ,EAAAI,WAGJC,ECPmB,SACzBJ,EACAG,GAEM,IAAAJ,EAAgCM,EAAAA,SAAiB,GAAhDC,EAAWP,EAAA,GAAEQ,EAAcR,EAAA,GAC5BK,EAAwBC,EAAAA,SAAkB,CAAE,GAA3CG,EAAOJ,EAAA,GAAEK,EAAUL,EAAA,GACpBM,EAAwBL,EAAAA,UAAkB,GAAzCM,EAAOD,EAAA,GAAEE,EAAUF,EAAA,GACpBG,EAAoBR,EAAAA,SAAmB,IAAtCS,EAAKD,EAAA,GAAEE,EAAQF,EAAA,GAEhBG,EAAOhB,EAASM,GAyDtB,MAAO,CACLU,KAAIA,EACJR,QAAOA,EACPG,QAAOA,EACPF,WAAUA,EACVQ,WApDiB,SAAOC,GAA0B,OAAAC,OAAA,OAAA,OAAA,GAAA,mFAM9C,OALEC,EAAcF,QAAAA,EAAoBV,EAClCa,EAASL,EAAKM,KAAKF,GAErBG,EAAa,GACbC,EAAiBJ,EACC,iBAAXC,EAAmB,CAAA,EAAA,IAC5BE,EAAaF,EACbG,EAAiBJ,gBACR,GAA0C,mBAAlCC,aAAA,EAAAA,EAAyBI,MAAjC,MAAoD,CAAA,EAAA,oBAGrC,6BADtBb,GAAW,GACW,CAAA,EAAMS,iBAAtBK,EAAgBhB,EAAYiB,OAClCf,GAAW,GACkB,iBAAlBc,EACTH,EAAaG,GAEbH,EAAaG,EAAcH,WAC3BC,EAA6C,QAA5BzB,EAAA2B,EAAcF,sBAAc,IAAAzB,EAAAA,EAAIqB,gBAInD,kBADAQ,QAAQC,MAAM,wCAAiCC,EAAE,MAC1C,CAAA,8BAECT,eAAAA,EAAgBE,cAC1BA,EAAcF,EAAeE,WAC7BC,EAA+C,QAA7BpB,EAAAiB,EAAeG,sBAAc,IAAApB,EAAAA,EAAIgB,oBAGrD,GAAmB,SAAfG,EACFpB,EAAWqB,OACN,CAML,GALAf,EAAWe,GACLO,EAAgB/B,EAASgC,WAC7B,SAAChB,GAAS,OAAAA,EAAKiB,KAAOV,CAAZ,KAGW,IAAnBQ,EAEF,OADAH,QAAQC,MAAM,oCAA6BN,EAAU,MAC9C,CAAA,GAGTR,EAAamB,EAAAA,EAAA,GAAApB,GAAO,GAAA,CAAAR,QACpBC,EAAewB,EAChB,mBASDI,WA7DiB,WAAA,OAAAhB,OAAA,OAAA,OAAA,GAAA,wDAEAiB,KADXC,EAAWvB,EAAMwB,QACOD,GAAY,IACxCtB,EAAQmB,EAAA,GAAKpB,GAAK,IAClBP,EAAe8B,eA2DrB,CDlEIE,CAAYvC,EAAUG,QAAAA,EAFE,cAClBa,EAAIZ,EAAAY,KAAER,EAAOJ,EAAAI,QAAEC,eAAYQ,EAAUb,EAAAa,WAAEkB,EAAU/B,EAAA+B,WAAExB,YA4B3D,OAAOT,EAAS,CACdc,KAAIA,EACJR,QAAOA,EACPG,QAAOA,EACPF,WAAUA,EACVQ,WAAUA,EACVuB,eA/BqB,SAACC,GACtB,IAAMC,EAAW1B,EAAK2B,UAAUC,MAAK,SAACC,GAAM,OAAAA,EAAEZ,KAAOQ,CAAU,IAE/D,IAAKC,EAEH,OADAd,QAAQC,MAAM,4BAAqBY,EAAU,iBACtC,KAGT,IAAKxC,EAEH,OADA2B,QAAQC,MAAM,8BACP,KAGT,IAAMiB,EAAa7C,EAAcyC,EAASK,WAE1C,OAAKD,EAOEA,EAAWJ,EAAUlC,EAASC,IANnCmB,QAAQC,MACN,kBAAAmB,OAAkBN,EAASK,UAAqD,+CAE3E,KAIX,EASEZ,WAAUA,GAEd"} \ No newline at end of file diff --git a/dist/types.d.ts b/dist/types.d.ts index fa1f37b..4b2a331 100644 --- a/dist/types.d.ts +++ b/dist/types.d.ts @@ -15,10 +15,14 @@ export interface Question { export interface Step { id: string; questions: Question[]; + context?: any; next: (answers: Answers) => string | { nextStepId: string; updatedAnswers?: Answers; - }; + } | Promise | Promise<{ + nextStepId: string; + updatedAnswers?: Answers; + }>; } export type QuestionRenderFunction = (question: Question, answers: Record, setAnswers: (updatedAnswers: Record) => void) => React.ReactNode; export type QuestionTypes = { @@ -31,8 +35,10 @@ export interface WhizFlowProps { children: (props: { step: Step; answers: Answers; + loading: boolean; setAnswers: (value: Answers) => void; handleNext: (submitterAnswers?: Answers) => void; + handlePrev: () => void; renderQuestion: (questionId: string) => React.ReactNode; }) => JSX.Element; } diff --git a/dist/types.d.ts.map b/dist/types.d.ts.map index 28313cf..e2fe398 100644 --- a/dist/types.d.ts.map +++ b/dist/types.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE7C,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AACD,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,GAAG,CAAC,CAAC,OAAO,EAAE,OAAO,KAAK,MAAM,CAAC,CAAC;IAChD,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,GAAG,CAAA;CACd;AAED,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,IAAI,EAAE,CACJ,OAAO,EAAE,OAAO,KACb,MAAM,GAAG;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CAChE;AAED,MAAM,MAAM,sBAAsB,GAAG,CACnC,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC5B,UAAU,EAAE,CAAC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,KACtD,KAAK,CAAC,SAAS,CAAC;AAErB,MAAM,MAAM,aAAa,GAAG;IAC1B,CAAC,GAAG,EAAE,MAAM,GAAG,sBAAsB,CAAC;CACvC,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,IAAI,EAAE,CAAC;IACjB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACxC,QAAQ,EAAE,CAAC,KAAK,EAAE;QAChB,IAAI,EAAE,IAAI,CAAC;QACX,OAAO,EAAE,OAAO,CAAC;QACjB,UAAU,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;QACrC,UAAU,EAAE,CAAC,gBAAgB,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;QACjD,cAAc,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC;KACzD,KAAK,GAAG,CAAC,OAAO,CAAC;CACnB"} \ No newline at end of file +{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE7C,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AACD,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,GAAG,CAAC,CAAC,OAAO,EAAE,OAAO,KAAK,MAAM,CAAC,CAAC;IAChD,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,GAAG,CAAC;CACf;AAED,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,IAAI,EAAE,CACJ,OAAO,EAAE,OAAO,KAEd,MAAM,GACN;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,OAAO,CAAA;KAAE,GAChD,OAAO,CAAC,MAAM,CAAC,GACf,OAAO,CAAC;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CAC/D;AAED,MAAM,MAAM,sBAAsB,GAAG,CACnC,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC5B,UAAU,EAAE,CAAC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,KACtD,KAAK,CAAC,SAAS,CAAC;AAErB,MAAM,MAAM,aAAa,GAAG;IAC1B,CAAC,GAAG,EAAE,MAAM,GAAG,sBAAsB,CAAC;CACvC,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,IAAI,EAAE,CAAC;IACjB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACxC,QAAQ,EAAE,CAAC,KAAK,EAAE;QAChB,IAAI,EAAE,IAAI,CAAC;QACX,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,EAAE,OAAO,CAAC;QACjB,UAAU,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;QACrC,UAAU,EAAE,CAAC,gBAAgB,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;QACjD,UAAU,EAAE,MAAM,IAAI,CAAC;QACvB,cAAc,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC;KACzD,KAAK,GAAG,CAAC,OAAO,CAAC;CACnB"} \ No newline at end of file diff --git a/dist/useWhizFlow.d.ts b/dist/useWhizFlow.d.ts index ace4fc2..18e59bc 100644 --- a/dist/useWhizFlow.d.ts +++ b/dist/useWhizFlow.d.ts @@ -3,7 +3,9 @@ import { Step, Answers } from './types'; export declare const useWhizFlow: (workflow: Step[], onComplete: (answers: Answers) => void) => { step: Step; answers: Answers; + loading: boolean; setAnswers: import("react").Dispatch>; - handleNext: (submitterAnswers?: Answers) => void; + handleNext: (submitterAnswers?: Answers) => Promise; + handlePrev: () => Promise; }; //# sourceMappingURL=useWhizFlow.d.ts.map \ No newline at end of file diff --git a/dist/useWhizFlow.d.ts.map b/dist/useWhizFlow.d.ts.map index d2820e9..2b1c796 100644 --- a/dist/useWhizFlow.d.ts.map +++ b/dist/useWhizFlow.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"useWhizFlow.d.ts","sourceRoot":"","sources":["../src/useWhizFlow.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAExC,eAAO,MAAM,WAAW,aACZ,IAAI,EAAE,wBACM,OAAO,KAAK,IAAI;;;;oCAOC,OAAO;CAiC/C,CAAC"} \ No newline at end of file +{"version":3,"file":"useWhizFlow.d.ts","sourceRoot":"","sources":["../src/useWhizFlow.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAExC,eAAO,MAAM,WAAW,aACZ,IAAI,EAAE,wBACM,OAAO,KAAK,IAAI;;;;;oCAiBO,OAAO;;CAuDrD,CAAC"} \ No newline at end of file diff --git a/dist/useWhizFlow.js b/dist/useWhizFlow.js index 933bc97..1205534 100644 --- a/dist/useWhizFlow.js +++ b/dist/useWhizFlow.js @@ -1,34 +1,135 @@ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (g && (g = 0, op[0] && (_ = 0)), _) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); +}; // src/useWhizFlow.ts import { useState } from 'react'; export var useWhizFlow = function (workflow, onComplete) { var _a = useState(0), currentStep = _a[0], setCurrentStep = _a[1]; var _b = useState({}), answers = _b[0], setAnswers = _b[1]; + var _c = useState(false), loading = _c[0], setLoading = _c[1]; + var _d = useState([]), trail = _d[0], setTrail = _d[1]; var step = workflow[currentStep]; - var handleNext = function (submitterAnswers) { - var currAnswers = submitterAnswers !== null && submitterAnswers !== void 0 ? submitterAnswers : answers; - var result = step.next(currAnswers); - var nextStepId = typeof result === 'string' ? result : result.nextStepId; - var updatedAnswers = typeof result !== 'string' && result.updatedAnswers - ? result.updatedAnswers - : currAnswers; - if (nextStepId === 'done') { - onComplete(updatedAnswers); - } - else { - setAnswers(updatedAnswers); - var nextStepIndex = workflow.findIndex(function (step) { return step.id === nextStepId; }); - if (nextStepIndex === -1) { - console.error("Error: Non-existent step \"".concat(nextStepId, "\"")); - return; + var handlePrev = function () { return __awaiter(void 0, void 0, void 0, function () { + var prevStep; + return __generator(this, function (_a) { + prevStep = trail.pop(); + if (prevStep !== undefined && prevStep >= 0) { + setTrail(__spreadArray([], trail, true)); + setCurrentStep(prevStep); } - setCurrentStep(nextStepIndex); - } - }; + return [2 /*return*/]; + }); + }); }; + var handleNext = function (submitterAnswers) { return __awaiter(void 0, void 0, void 0, function () { + var currAnswers, result, nextStepId, updatedAnswers, awaitedResult, ex_1, nextStepIndex; + var _a, _b; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + currAnswers = submitterAnswers !== null && submitterAnswers !== void 0 ? submitterAnswers : answers; + result = step.next(currAnswers); + nextStepId = ''; + updatedAnswers = currAnswers; + if (!(typeof result === 'string')) return [3 /*break*/, 1]; + nextStepId = result; + updatedAnswers = currAnswers; + return [3 /*break*/, 7]; + case 1: + if (!(typeof (result === null || result === void 0 ? void 0 : result.then) === 'function')) return [3 /*break*/, 6]; + _c.label = 2; + case 2: + _c.trys.push([2, 4, , 5]); + setLoading(true); + return [4 /*yield*/, result]; + case 3: + awaitedResult = _c.sent(); + setLoading(false); + if (typeof awaitedResult === 'string') { + nextStepId = awaitedResult; + } + else { + nextStepId = awaitedResult.nextStepId; + updatedAnswers = (_a = awaitedResult.updatedAnswers) !== null && _a !== void 0 ? _a : currAnswers; + } + return [3 /*break*/, 5]; + case 4: + ex_1 = _c.sent(); + console.error("Error: Next step eval failed \"".concat(ex_1, "\"")); + return [2 /*return*/]; + case 5: return [3 /*break*/, 7]; + case 6: + if (result === null || result === void 0 ? void 0 : result.nextStepId) { + nextStepId = result.nextStepId; + updatedAnswers = (_b = result.updatedAnswers) !== null && _b !== void 0 ? _b : currAnswers; + } + _c.label = 7; + case 7: + if (nextStepId === 'done') { + onComplete(updatedAnswers); + } + else { + setAnswers(updatedAnswers); + nextStepIndex = workflow.findIndex(function (step) { return step.id === nextStepId; }); + if (nextStepIndex === -1) { + console.error("Error: Non-existent step \"".concat(nextStepId, "\"")); + return [2 /*return*/]; + } + setTrail(__spreadArray(__spreadArray([], trail, true), [currentStep], false)); + setCurrentStep(nextStepIndex); + } + return [2 /*return*/]; + } + }); + }); }; return { step: step, answers: answers, + loading: loading, setAnswers: setAnswers, handleNext: handleNext, + handlePrev: handlePrev, }; }; //# sourceMappingURL=useWhizFlow.js.map \ No newline at end of file diff --git a/dist/useWhizFlow.js.map b/dist/useWhizFlow.js.map index e14d449..747b8e1 100644 --- a/dist/useWhizFlow.js.map +++ b/dist/useWhizFlow.js.map @@ -1 +1 @@ -{"version":3,"file":"useWhizFlow.js","sourceRoot":"","sources":["../src/useWhizFlow.ts"],"names":[],"mappings":"AAAA,qBAAqB;AACrB,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAGjC,MAAM,CAAC,IAAM,WAAW,GAAG,UACzB,QAAgB,EAChB,UAAsC;IAEhC,IAAA,KAAgC,QAAQ,CAAS,CAAC,CAAC,EAAlD,WAAW,QAAA,EAAE,cAAc,QAAuB,CAAC;IACpD,IAAA,KAAwB,QAAQ,CAAU,EAAE,CAAC,EAA5C,OAAO,QAAA,EAAE,UAAU,QAAyB,CAAC;IAEpD,IAAM,IAAI,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC;IAEnC,IAAM,UAAU,GAAG,UAAC,gBAA0B;QAC5C,IAAM,WAAW,GAAG,gBAAgB,aAAhB,gBAAgB,cAAhB,gBAAgB,GAAI,OAAO,CAAC;QAChD,IAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAEtC,IAAM,UAAU,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;QAC3E,IAAM,cAAc,GAClB,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,cAAc;YACjD,CAAC,CAAC,MAAM,CAAC,cAAc;YACvB,CAAC,CAAC,WAAW,CAAC;QAElB,IAAI,UAAU,KAAK,MAAM,EAAE;YACzB,UAAU,CAAC,cAAc,CAAC,CAAC;SAC5B;aAAM;YACL,UAAU,CAAC,cAAc,CAAC,CAAC;YAC3B,IAAM,aAAa,GAAG,QAAQ,CAAC,SAAS,CACtC,UAAC,IAAI,IAAK,OAAA,IAAI,CAAC,EAAE,KAAK,UAAU,EAAtB,CAAsB,CACjC,CAAC;YAEF,IAAI,aAAa,KAAK,CAAC,CAAC,EAAE;gBACxB,OAAO,CAAC,KAAK,CAAC,qCAA6B,UAAU,OAAG,CAAC,CAAC;gBAC1D,OAAO;aACR;YAED,cAAc,CAAC,aAAa,CAAC,CAAC;SAC/B;IACH,CAAC,CAAC;IAEF,OAAO;QACL,IAAI,MAAA;QACJ,OAAO,SAAA;QACP,UAAU,YAAA;QACV,UAAU,YAAA;KACX,CAAC;AACJ,CAAC,CAAC"} \ No newline at end of file +{"version":3,"file":"useWhizFlow.js","sourceRoot":"","sources":["../src/useWhizFlow.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/docs/assets/search.js b/docs/assets/search.js index 930c060..6e21f77 100644 --- a/docs/assets/search.js +++ b/docs/assets/search.js @@ -1 +1 @@ -window.searchData = JSON.parse("{\"kinds\":{\"2\":\"Module\",\"64\":\"Function\",\"256\":\"Interface\",\"1024\":\"Property\",\"65536\":\"Type literal\",\"4194304\":\"Type alias\"},\"rows\":[{\"kind\":64,\"name\":\"default\",\"url\":\"functions/default.html\",\"classes\":\"tsd-kind-function\"},{\"kind\":2,\"name\":\"\",\"url\":\"modules/_internal_.html\",\"classes\":\"tsd-kind-module\"},{\"kind\":256,\"name\":\"WhizFlowProps\",\"url\":\"interfaces/_internal_.WhizFlowProps.html\",\"classes\":\"tsd-kind-interface tsd-parent-kind-module\",\"parent\":\"\"},{\"kind\":1024,\"name\":\"workflow\",\"url\":\"interfaces/_internal_.WhizFlowProps.html#workflow\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\".WhizFlowProps\"},{\"kind\":1024,\"name\":\"questionTypes\",\"url\":\"interfaces/_internal_.WhizFlowProps.html#questionTypes\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\".WhizFlowProps\"},{\"kind\":1024,\"name\":\"onComplete\",\"url\":\"interfaces/_internal_.WhizFlowProps.html#onComplete\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\".WhizFlowProps\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/_internal_.WhizFlowProps.html#onComplete.__type-2\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-property\",\"parent\":\".WhizFlowProps.onComplete\"},{\"kind\":1024,\"name\":\"children\",\"url\":\"interfaces/_internal_.WhizFlowProps.html#children\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\".WhizFlowProps\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/_internal_.WhizFlowProps.html#children.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-property\",\"parent\":\".WhizFlowProps.children\"},{\"kind\":256,\"name\":\"Step\",\"url\":\"interfaces/_internal_.Step.html\",\"classes\":\"tsd-kind-interface tsd-parent-kind-module\",\"parent\":\"\"},{\"kind\":1024,\"name\":\"id\",\"url\":\"interfaces/_internal_.Step.html#id\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\".Step\"},{\"kind\":1024,\"name\":\"questions\",\"url\":\"interfaces/_internal_.Step.html#questions\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\".Step\"},{\"kind\":1024,\"name\":\"next\",\"url\":\"interfaces/_internal_.Step.html#next\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\".Step\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/_internal_.Step.html#next.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-property\",\"parent\":\".Step.next\"},{\"kind\":4194304,\"name\":\"QuestionTypes\",\"url\":\"types/_internal_.QuestionTypes.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/_internal_.QuestionTypes.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\".QuestionTypes\"},{\"kind\":4194304,\"name\":\"Answers\",\"url\":\"types/_internal_.Answers.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"\"},{\"kind\":256,\"name\":\"Question\",\"url\":\"interfaces/_internal_.Question.html\",\"classes\":\"tsd-kind-interface tsd-parent-kind-module\",\"parent\":\"\"},{\"kind\":1024,\"name\":\"id\",\"url\":\"interfaces/_internal_.Question.html#id\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\".Question\"},{\"kind\":1024,\"name\":\"prompt\",\"url\":\"interfaces/_internal_.Question.html#prompt\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\".Question\"},{\"kind\":1024,\"name\":\"options\",\"url\":\"interfaces/_internal_.Question.html#options\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\".Question\"},{\"kind\":1024,\"name\":\"inputType\",\"url\":\"interfaces/_internal_.Question.html#inputType\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\".Question\"},{\"kind\":1024,\"name\":\"context\",\"url\":\"interfaces/_internal_.Question.html#context\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\".Question\"},{\"kind\":4194304,\"name\":\"QuestionRenderFunction\",\"url\":\"types/_internal_.QuestionRenderFunction.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/_internal_.QuestionRenderFunction.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\".QuestionRenderFunction\"},{\"kind\":256,\"name\":\"Option\",\"url\":\"interfaces/_internal_.Option.html\",\"classes\":\"tsd-kind-interface tsd-parent-kind-module\",\"parent\":\"\"},{\"kind\":1024,\"name\":\"id\",\"url\":\"interfaces/_internal_.Option.html#id\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\".Option\"},{\"kind\":1024,\"name\":\"value\",\"url\":\"interfaces/_internal_.Option.html#value\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\".Option\"},{\"kind\":1024,\"name\":\"label\",\"url\":\"interfaces/_internal_.Option.html#label\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\".Option\"}],\"index\":{\"version\":\"2.3.9\",\"fields\":[\"name\",\"comment\"],\"fieldVectors\":[[\"name/0\",[0,29.957]],[\"comment/0\",[]],[\"name/1\",[1,29.957]],[\"comment/1\",[]],[\"name/2\",[2,29.957]],[\"comment/2\",[]],[\"name/3\",[3,29.957]],[\"comment/3\",[]],[\"name/4\",[4,24.849]],[\"comment/4\",[]],[\"name/5\",[5,29.957]],[\"comment/5\",[]],[\"name/6\",[6,16.964]],[\"comment/6\",[]],[\"name/7\",[7,29.957]],[\"comment/7\",[]],[\"name/8\",[6,16.964]],[\"comment/8\",[]],[\"name/9\",[8,29.957]],[\"comment/9\",[]],[\"name/10\",[9,21.484]],[\"comment/10\",[]],[\"name/11\",[10,29.957]],[\"comment/11\",[]],[\"name/12\",[11,29.957]],[\"comment/12\",[]],[\"name/13\",[6,16.964]],[\"comment/13\",[]],[\"name/14\",[4,24.849]],[\"comment/14\",[]],[\"name/15\",[6,16.964]],[\"comment/15\",[]],[\"name/16\",[12,29.957]],[\"comment/16\",[]],[\"name/17\",[13,29.957]],[\"comment/17\",[]],[\"name/18\",[9,21.484]],[\"comment/18\",[]],[\"name/19\",[14,29.957]],[\"comment/19\",[]],[\"name/20\",[15,29.957]],[\"comment/20\",[]],[\"name/21\",[16,29.957]],[\"comment/21\",[]],[\"name/22\",[17,29.957]],[\"comment/22\",[]],[\"name/23\",[18,29.957]],[\"comment/23\",[]],[\"name/24\",[6,16.964]],[\"comment/24\",[]],[\"name/25\",[19,29.957]],[\"comment/25\",[]],[\"name/26\",[9,21.484]],[\"comment/26\",[]],[\"name/27\",[20,29.957]],[\"comment/27\",[]],[\"name/28\",[21,29.957]],[\"comment/28\",[]]],\"invertedIndex\":[[\"__type\",{\"_index\":6,\"name\":{\"6\":{},\"8\":{},\"13\":{},\"15\":{},\"24\":{}},\"comment\":{}}],[\"answers\",{\"_index\":12,\"name\":{\"16\":{}},\"comment\":{}}],[\"children\",{\"_index\":7,\"name\":{\"7\":{}},\"comment\":{}}],[\"context\",{\"_index\":17,\"name\":{\"22\":{}},\"comment\":{}}],[\"default\",{\"_index\":0,\"name\":{\"0\":{}},\"comment\":{}}],[\"id\",{\"_index\":9,\"name\":{\"10\":{},\"18\":{},\"26\":{}},\"comment\":{}}],[\"inputtype\",{\"_index\":16,\"name\":{\"21\":{}},\"comment\":{}}],[\"internal\",{\"_index\":1,\"name\":{\"1\":{}},\"comment\":{}}],[\"label\",{\"_index\":21,\"name\":{\"28\":{}},\"comment\":{}}],[\"next\",{\"_index\":11,\"name\":{\"12\":{}},\"comment\":{}}],[\"oncomplete\",{\"_index\":5,\"name\":{\"5\":{}},\"comment\":{}}],[\"option\",{\"_index\":19,\"name\":{\"25\":{}},\"comment\":{}}],[\"options\",{\"_index\":15,\"name\":{\"20\":{}},\"comment\":{}}],[\"prompt\",{\"_index\":14,\"name\":{\"19\":{}},\"comment\":{}}],[\"question\",{\"_index\":13,\"name\":{\"17\":{}},\"comment\":{}}],[\"questionrenderfunction\",{\"_index\":18,\"name\":{\"23\":{}},\"comment\":{}}],[\"questions\",{\"_index\":10,\"name\":{\"11\":{}},\"comment\":{}}],[\"questiontypes\",{\"_index\":4,\"name\":{\"4\":{},\"14\":{}},\"comment\":{}}],[\"step\",{\"_index\":8,\"name\":{\"9\":{}},\"comment\":{}}],[\"value\",{\"_index\":20,\"name\":{\"27\":{}},\"comment\":{}}],[\"whizflowprops\",{\"_index\":2,\"name\":{\"2\":{}},\"comment\":{}}],[\"workflow\",{\"_index\":3,\"name\":{\"3\":{}},\"comment\":{}}]],\"pipeline\":[]}}"); \ No newline at end of file +window.searchData = JSON.parse("{\"kinds\":{\"2\":\"Module\",\"64\":\"Function\",\"256\":\"Interface\",\"1024\":\"Property\",\"65536\":\"Type literal\",\"4194304\":\"Type alias\"},\"rows\":[{\"kind\":64,\"name\":\"default\",\"url\":\"functions/default.html\",\"classes\":\"tsd-kind-function\"},{\"kind\":2,\"name\":\"\",\"url\":\"modules/_internal_.html\",\"classes\":\"tsd-kind-module\"},{\"kind\":256,\"name\":\"WhizFlowProps\",\"url\":\"interfaces/_internal_.WhizFlowProps.html\",\"classes\":\"tsd-kind-interface tsd-parent-kind-module\",\"parent\":\"\"},{\"kind\":1024,\"name\":\"workflow\",\"url\":\"interfaces/_internal_.WhizFlowProps.html#workflow\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\".WhizFlowProps\"},{\"kind\":1024,\"name\":\"questionTypes\",\"url\":\"interfaces/_internal_.WhizFlowProps.html#questionTypes\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\".WhizFlowProps\"},{\"kind\":1024,\"name\":\"onComplete\",\"url\":\"interfaces/_internal_.WhizFlowProps.html#onComplete\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\".WhizFlowProps\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/_internal_.WhizFlowProps.html#onComplete.__type-2\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-property\",\"parent\":\".WhizFlowProps.onComplete\"},{\"kind\":1024,\"name\":\"children\",\"url\":\"interfaces/_internal_.WhizFlowProps.html#children\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\".WhizFlowProps\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/_internal_.WhizFlowProps.html#children.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-property\",\"parent\":\".WhizFlowProps.children\"},{\"kind\":256,\"name\":\"Step\",\"url\":\"interfaces/_internal_.Step.html\",\"classes\":\"tsd-kind-interface tsd-parent-kind-module\",\"parent\":\"\"},{\"kind\":1024,\"name\":\"id\",\"url\":\"interfaces/_internal_.Step.html#id\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\".Step\"},{\"kind\":1024,\"name\":\"questions\",\"url\":\"interfaces/_internal_.Step.html#questions\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\".Step\"},{\"kind\":1024,\"name\":\"context\",\"url\":\"interfaces/_internal_.Step.html#context\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\".Step\"},{\"kind\":1024,\"name\":\"next\",\"url\":\"interfaces/_internal_.Step.html#next\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\".Step\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/_internal_.Step.html#next.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-property\",\"parent\":\".Step.next\"},{\"kind\":4194304,\"name\":\"QuestionTypes\",\"url\":\"types/_internal_.QuestionTypes.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/_internal_.QuestionTypes.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\".QuestionTypes\"},{\"kind\":4194304,\"name\":\"Answers\",\"url\":\"types/_internal_.Answers.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"\"},{\"kind\":256,\"name\":\"Question\",\"url\":\"interfaces/_internal_.Question.html\",\"classes\":\"tsd-kind-interface tsd-parent-kind-module\",\"parent\":\"\"},{\"kind\":1024,\"name\":\"id\",\"url\":\"interfaces/_internal_.Question.html#id\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\".Question\"},{\"kind\":1024,\"name\":\"prompt\",\"url\":\"interfaces/_internal_.Question.html#prompt\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\".Question\"},{\"kind\":1024,\"name\":\"options\",\"url\":\"interfaces/_internal_.Question.html#options\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\".Question\"},{\"kind\":1024,\"name\":\"inputType\",\"url\":\"interfaces/_internal_.Question.html#inputType\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\".Question\"},{\"kind\":1024,\"name\":\"context\",\"url\":\"interfaces/_internal_.Question.html#context\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\".Question\"},{\"kind\":4194304,\"name\":\"QuestionRenderFunction\",\"url\":\"types/_internal_.QuestionRenderFunction.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/_internal_.QuestionRenderFunction.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\".QuestionRenderFunction\"},{\"kind\":256,\"name\":\"Option\",\"url\":\"interfaces/_internal_.Option.html\",\"classes\":\"tsd-kind-interface tsd-parent-kind-module\",\"parent\":\"\"},{\"kind\":1024,\"name\":\"id\",\"url\":\"interfaces/_internal_.Option.html#id\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\".Option\"},{\"kind\":1024,\"name\":\"value\",\"url\":\"interfaces/_internal_.Option.html#value\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\".Option\"},{\"kind\":1024,\"name\":\"label\",\"url\":\"interfaces/_internal_.Option.html#label\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\".Option\"}],\"index\":{\"version\":\"2.3.9\",\"fields\":[\"name\",\"comment\"],\"fieldVectors\":[[\"name/0\",[0,30.285]],[\"comment/0\",[]],[\"name/1\",[1,30.285]],[\"comment/1\",[]],[\"name/2\",[2,30.285]],[\"comment/2\",[]],[\"name/3\",[3,30.285]],[\"comment/3\",[]],[\"name/4\",[4,25.177]],[\"comment/4\",[]],[\"name/5\",[5,30.285]],[\"comment/5\",[]],[\"name/6\",[6,17.292]],[\"comment/6\",[]],[\"name/7\",[7,30.285]],[\"comment/7\",[]],[\"name/8\",[6,17.292]],[\"comment/8\",[]],[\"name/9\",[8,30.285]],[\"comment/9\",[]],[\"name/10\",[9,21.812]],[\"comment/10\",[]],[\"name/11\",[10,30.285]],[\"comment/11\",[]],[\"name/12\",[11,25.177]],[\"comment/12\",[]],[\"name/13\",[12,30.285]],[\"comment/13\",[]],[\"name/14\",[6,17.292]],[\"comment/14\",[]],[\"name/15\",[4,25.177]],[\"comment/15\",[]],[\"name/16\",[6,17.292]],[\"comment/16\",[]],[\"name/17\",[13,30.285]],[\"comment/17\",[]],[\"name/18\",[14,30.285]],[\"comment/18\",[]],[\"name/19\",[9,21.812]],[\"comment/19\",[]],[\"name/20\",[15,30.285]],[\"comment/20\",[]],[\"name/21\",[16,30.285]],[\"comment/21\",[]],[\"name/22\",[17,30.285]],[\"comment/22\",[]],[\"name/23\",[11,25.177]],[\"comment/23\",[]],[\"name/24\",[18,30.285]],[\"comment/24\",[]],[\"name/25\",[6,17.292]],[\"comment/25\",[]],[\"name/26\",[19,30.285]],[\"comment/26\",[]],[\"name/27\",[9,21.812]],[\"comment/27\",[]],[\"name/28\",[20,30.285]],[\"comment/28\",[]],[\"name/29\",[21,30.285]],[\"comment/29\",[]]],\"invertedIndex\":[[\"__type\",{\"_index\":6,\"name\":{\"6\":{},\"8\":{},\"14\":{},\"16\":{},\"25\":{}},\"comment\":{}}],[\"answers\",{\"_index\":13,\"name\":{\"17\":{}},\"comment\":{}}],[\"children\",{\"_index\":7,\"name\":{\"7\":{}},\"comment\":{}}],[\"context\",{\"_index\":11,\"name\":{\"12\":{},\"23\":{}},\"comment\":{}}],[\"default\",{\"_index\":0,\"name\":{\"0\":{}},\"comment\":{}}],[\"id\",{\"_index\":9,\"name\":{\"10\":{},\"19\":{},\"27\":{}},\"comment\":{}}],[\"inputtype\",{\"_index\":17,\"name\":{\"22\":{}},\"comment\":{}}],[\"internal\",{\"_index\":1,\"name\":{\"1\":{}},\"comment\":{}}],[\"label\",{\"_index\":21,\"name\":{\"29\":{}},\"comment\":{}}],[\"next\",{\"_index\":12,\"name\":{\"13\":{}},\"comment\":{}}],[\"oncomplete\",{\"_index\":5,\"name\":{\"5\":{}},\"comment\":{}}],[\"option\",{\"_index\":19,\"name\":{\"26\":{}},\"comment\":{}}],[\"options\",{\"_index\":16,\"name\":{\"21\":{}},\"comment\":{}}],[\"prompt\",{\"_index\":15,\"name\":{\"20\":{}},\"comment\":{}}],[\"question\",{\"_index\":14,\"name\":{\"18\":{}},\"comment\":{}}],[\"questionrenderfunction\",{\"_index\":18,\"name\":{\"24\":{}},\"comment\":{}}],[\"questions\",{\"_index\":10,\"name\":{\"11\":{}},\"comment\":{}}],[\"questiontypes\",{\"_index\":4,\"name\":{\"4\":{},\"15\":{}},\"comment\":{}}],[\"step\",{\"_index\":8,\"name\":{\"9\":{}},\"comment\":{}}],[\"value\",{\"_index\":20,\"name\":{\"28\":{}},\"comment\":{}}],[\"whizflowprops\",{\"_index\":2,\"name\":{\"2\":{}},\"comment\":{}}],[\"workflow\",{\"_index\":3,\"name\":{\"3\":{}},\"comment\":{}}]],\"pipeline\":[]}}"); \ No newline at end of file diff --git a/docs/classes/_internal_.Component.html b/docs/classes/_internal_.Component.html index b145df7..cf878f0 100644 --- a/docs/classes/_internal_.Component.html +++ b/docs/classes/_internal_.Component.html @@ -1,4 +1,4 @@ -Component | whizflow - v0.2.2
+Component | whizflow - v0.4.0
  • Preparing search index...
  • -
  • The search index is not available
whizflow - v0.2.2
+
  • The search index is not available
  • whizflow - v0.4.0
    @@ -519,7 +519,7 @@

    Theme

    @@ -6,13 +6,13 @@
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0
    @@ -48,7 +48,7 @@

    Theme

    @@ -6,16 +6,20 @@
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0
    -

    whizflow - v0.2.2

    +

    whizflow - v0.4.0

    WhizFlow

    +

    npm bundle size +npm +npm +node-current

    WhizFlow is a lightweight, headless and extensible React library for building dynamic multi-step forms or troubleshooting workflows.

    @@ -28,6 +32,14 @@

    Features

  • Agnostic: Use Formik or any other form/validation library that you want to handle the input.
  • + +

    Demo

    +
    + +

    Installation

    @@ -43,7 +55,7 @@

    Usage

    1. Import WhizFlow and required types:
    -
    import WhizFlow from 'whizflow';
    import { Step } from 'whizflow/types'; +
    import WhizFlow from 'whizflow';
    import { Step } from 'whizflow/dist/types';
    1. Define your workflow:
    2. @@ -85,8 +97,10 @@

      Render Props

      • step: The current step object.
      • answers: An object containing the answers for each question in the workflow.
      • +
      • loading: A boolean to mark when handleNext is waiting to resolve.
      • setAnswers: A function to update the answers object.
      • handleNext: A function to handle navigation to the next step in the workflow.
      • +
      • handlePrev: A function to handle navigation to the previous step.
      • renderQuestion: A function to render the correct question type based on the provided dictionary.
      @@ -161,6 +175,12 @@

      API

      +loading +boolean +Whether handleNext is running asyncly. (Render prop) + + + answers Record<string, any> An object containing the answers for each question in the workflow. (Render prop) @@ -179,6 +199,12 @@

      API

      +handlePrev +() => void +A function to handle navigation to the previous step in the workflow. (Render prop) + + + renderQuestion (questionId: string) => React.ReactNode A function to render the correct question type based on the provided dictionary. (Render prop) @@ -204,10 +230,16 @@

      API

      next -(answers: Record<string, any>) => string | 'done' +string | { nextStepId: string; updatedAnswers?: Answers } ֿֿֿ| Promise<string> | Promise<{ nextStepId: string; updatedAnswers?: Answers }> A function that determines the next step in the workflow based on the current answers. It should return the next step's ID or 'done' if the workflow is complete. + +context? +any +An optional context object for the question to pass (to be used later when rendering). + + Question @@ -305,7 +337,7 @@

      Theme

    @@ -6,13 +6,13 @@
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0

    Interface ComponentLifecycle<P, S, SS>

    @@ -348,7 +348,7 @@

    Theme

    @@ -6,13 +6,13 @@
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0
    @@ -75,7 +75,7 @@

    Theme

    @@ -6,13 +6,13 @@
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0
    @@ -74,7 +74,7 @@

    Theme

    @@ -6,13 +6,13 @@
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0

    Interface DeprecatedLifecycle<P, S>

    @@ -225,7 +225,7 @@

    Theme

    @@ -6,13 +6,13 @@
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0
    @@ -59,7 +59,7 @@

    Theme

    @@ -6,13 +6,13 @@
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0
    @@ -76,7 +76,7 @@

    Theme

    @@ -6,13 +6,13 @@
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0
    @@ -65,7 +65,7 @@

    Theme

    @@ -6,13 +6,13 @@
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0

    Interface Iterator<T, TReturn, TNext>

    @@ -102,7 +102,7 @@

    Theme

    @@ -6,13 +6,13 @@
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0

    Interface IteratorReturnResult<TReturn>

    @@ -68,7 +68,7 @@

    Theme

    @@ -6,13 +6,13 @@
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0

    Interface IteratorYieldResult<TYield>

    @@ -68,7 +68,7 @@

    Theme

    @@ -6,13 +6,13 @@
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0

    Interface NewLifecycle<P, S, SS>

    @@ -105,7 +105,7 @@

    Theme

    @@ -6,13 +6,13 @@
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0
    @@ -21,7 +21,7 @@

    Hierarchy

    • Option
    +
  • Defined in src/types.ts:3
  • @@ -39,17 +39,17 @@

    Properties

    id: string
    +
  • Defined in src/types.ts:4
  • label: string
    +
  • Defined in src/types.ts:6
  • value: string
    +
  • Defined in src/types.ts:5
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0
    @@ -83,7 +83,7 @@

    Theme

    @@ -6,13 +6,13 @@
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0
    @@ -68,7 +68,7 @@

    Theme

    @@ -6,13 +6,13 @@
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0
    @@ -21,7 +21,7 @@

    Hierarchy

    • Question
    +
  • Defined in src/types.ts:8
  • @@ -41,27 +41,27 @@

    Properties

    context?: any
    +
  • Defined in src/types.ts:13
  • id: string
    +
  • Defined in src/types.ts:9
  • inputType: string
    +
  • Defined in src/types.ts:12
  • options?: Option[]
    +
  • Defined in src/types.ts:11
  • prompt: string | ((answers: Answers) => string)
    +
  • Defined in src/types.ts:10
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0
    @@ -78,7 +78,7 @@

    Theme

    @@ -6,13 +6,13 @@
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0
    @@ -80,7 +80,7 @@

    Theme

    @@ -6,13 +6,13 @@
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0
    @@ -21,7 +21,7 @@

    Hierarchy

    • Step
    +
  • Defined in src/types.ts:16
  • @@ -29,40 +29,46 @@

    Properties

    +
    + +
    context?: any
    - +
    id: string
    +
  • Defined in src/types.ts:17
  • -
    next: ((answers: Answers) => string | {
        nextStepId: string;
        updatedAnswers?: Answers;
    })
    +
    next: ((answers: Answers) => string | {
        nextStepId: string;
        updatedAnswers?: Answers;
    } | Promise<string> | Promise<{
        nextStepId: string;
        updatedAnswers?: Answers;
    }>)

    Type declaration

      • -
      • (answers: Answers): string | {
            nextStepId: string;
            updatedAnswers?: Answers;
        }
      • +
      • (answers: Answers): string | {
            nextStepId: string;
            updatedAnswers?: Answers;
        } | Promise<string> | Promise<{
            nextStepId: string;
            updatedAnswers?: Answers;
        }>
      • Parameters

        -

        Returns string | {
            nextStepId: string;
            updatedAnswers?: Answers;
        }

    +
  • Defined in src/types.ts:20
  • questions: Question[]
    +
  • Defined in src/types.ts:18
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0
    @@ -88,7 +88,7 @@

    Theme

    @@ -6,13 +6,13 @@
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0
    @@ -21,7 +21,7 @@

    Hierarchy

    • WhizFlowProps
    +
  • Defined in src/types.ts:39
  • @@ -38,19 +38,19 @@

    Properties

    Properties

    -
    children: ((props: {
        answers: Answers;
        handleNext: ((submitterAnswers?: Answers) => void);
        renderQuestion: ((questionId: string) => ReactNode);
        setAnswers: ((value: Answers) => void);
        step: Step;
    }) => Element)
    +
    children: ((props: {
        answers: Answers;
        handleNext: ((submitterAnswers?: Answers) => void);
        handlePrev: (() => void);
        loading: boolean;
        renderQuestion: ((questionId: string) => ReactNode);
        setAnswers: ((value: Answers) => void);
        step: Step;
    }) => Element)

    Type declaration

      • -
      • (props: {
            answers: Answers;
            handleNext: ((submitterAnswers?: Answers) => void);
            renderQuestion: ((questionId: string) => ReactNode);
            setAnswers: ((value: Answers) => void);
            step: Step;
        }): Element
      • +
      • (props: {
            answers: Answers;
            handleNext: ((submitterAnswers?: Answers) => void);
            handlePrev: (() => void);
            loading: boolean;
            renderQuestion: ((questionId: string) => ReactNode);
            setAnswers: ((value: Answers) => void);
            step: Step;
        }): Element
      • Parameters

        • -
          props: {
              answers: Answers;
              handleNext: ((submitterAnswers?: Answers) => void);
              renderQuestion: ((questionId: string) => ReactNode);
              setAnswers: ((value: Answers) => void);
              step: Step;
          }
          +
          props: {
              answers: Answers;
              handleNext: ((submitterAnswers?: Answers) => void);
              handlePrev: (() => void);
              loading: boolean;
              renderQuestion: ((questionId: string) => ReactNode);
              setAnswers: ((value: Answers) => void);
              step: Step;
          }
          • answers: Answers
          • @@ -68,6 +68,16 @@

            Parameters

            Optional submitterAnswers: Answers

        Returns void

  • +
    handlePrev: (() => void)
    +
      +
    • +
        +
      • (): void
      • +
      • +

        Returns void

  • +
  • +
    loading: boolean
  • +
  • renderQuestion: ((questionId: string) => ReactNode)
    • @@ -97,7 +107,7 @@

      Returns voidstep: Step

  • Returns Element

    +
  • Defined in src/types.ts:43
  • onComplete?: ((answers: Answers) => void)
    @@ -115,17 +125,17 @@

    Parameters

    answers: Answers

    Returns void

    +
  • Defined in src/types.ts:42
  • questionTypes?: QuestionTypes
    +
  • Defined in src/types.ts:41
  • workflow: Step[]
    +
  • Defined in src/types.ts:40
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0
    -

    whizflow - v0.2.2

    +

    whizflow - v0.4.0

    Index

    @@ -42,7 +42,7 @@

    Theme

    @@ -6,13 +6,13 @@
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0
    @@ -85,7 +85,7 @@

    Theme

    @@ -6,19 +6,19 @@
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0
    Answers: Record<string, string>
    +
  • Defined in src/types.ts:1
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0
    @@ -43,7 +43,7 @@

    Theme

    @@ -6,13 +6,13 @@
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0

    Type alias IteratorResult<T, TReturn>

    @@ -45,7 +45,7 @@

    Theme

    @@ -6,13 +6,13 @@
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0
    @@ -43,7 +43,7 @@

    Theme

    @@ -6,13 +6,13 @@
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0
    @@ -38,7 +38,7 @@

    Theme

    @@ -6,13 +6,13 @@
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0
    @@ -47,7 +47,7 @@

    Theme

    @@ -6,13 +6,13 @@
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0
    @@ -43,7 +43,7 @@

    Theme

    @@ -6,13 +6,13 @@
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0
    @@ -46,7 +46,7 @@
    updatedAnswers: Returns void

    Returns ReactNode

    +
  • Defined in src/types.ts:29
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0
    @@ -23,7 +23,7 @@

    Type declaration

  • [key: string]: QuestionRenderFunction
  • +
  • Defined in src/types.ts:35
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0
    @@ -38,7 +38,7 @@

    Theme

    @@ -6,13 +6,13 @@
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0
    @@ -38,7 +38,7 @@

    Theme

    @@ -6,13 +6,13 @@
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0
    @@ -38,7 +38,7 @@

    Theme

    @@ -6,13 +6,13 @@
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0
    @@ -45,7 +45,7 @@

    Theme

    @@ -6,13 +6,13 @@
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0
    @@ -47,7 +47,7 @@

    Theme

    @@ -6,13 +6,13 @@
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0
    @@ -43,7 +43,7 @@

    Theme

    @@ -6,13 +6,13 @@
    • Preparing search index...
    • -
    • The search index is not available
    whizflow - v0.2.2 +
  • The search index is not available
  • whizflow - v0.4.0
    @@ -43,7 +43,7 @@

    Theme

    + setAnswers({ + ...answers, + [step.questions[0].id]: e.target.value, + }) + } + /> + {loading &&

    Loading...

    } + +
    + )} + + ); + + expect(queryByText('Loading...')).toBe(null); + fireEvent.change(getByLabelText('What is your name?'), { + target: { value: 'Alice' }, + }); + fireEvent.click(getByText('Next')); + + expect(getByText('Loading...')).toBeInTheDocument(); + await waitFor(() => expect(queryByText('Loading...')).toBe(null), { + timeout: 5000, + }); + + expect( + getByLabelText('Hello, Alice! What is your favorite color?') + ).toBeInTheDocument(); + }); + + const answerChangingWorkflow = [ + { + id: 'step1', + questions: [ + { + id: 'question1', + prompt: 'What is your name?', + inputType: 'text', + }, + ], + next: async (answers) => { + await delay(1000); + return { + nextStepId: 'step2', + updatedAnswers: { ...answers, question1: 'Bob' }, + }; + }, + }, + { + id: 'step2', + questions: [ + { + id: 'question2', + prompt: (answers) => + `Hello, ${answers.question1}! What is your favorite color?`, + inputType: 'text', + }, + ], + next: (answers) => 'done', + }, + ] as Step[]; + + it('should load between steps', async () => { + const { getByLabelText, getByText, queryByText } = render( + + {({ step, answers, setAnswers, handleNext, loading }) => ( +
    + + + setAnswers({ + ...answers, + [step.questions[0].id]: e.target.value, + }) + } + /> + {loading &&

    Loading...

    } + +
    + )} +
    + ); + + expect(queryByText('Loading...')).toBe(null); + fireEvent.change(getByLabelText('What is your name?'), { + target: { value: 'Alice' }, + }); + fireEvent.click(getByText('Next')); + + expect(getByText('Loading...')).toBeInTheDocument(); + await waitFor(() => expect(queryByText('Loading...')).toBe(null), { + timeout: 5000, + }); + + expect( + getByLabelText('Hello, Bob! What is your favorite color?') + ).toBeInTheDocument(); + }); + + const errorEmittingWorflow = [ + { + id: 'step1', + questions: [ + { + id: 'question1', + prompt: 'What is your name?', + inputType: 'text', + }, + ], + next: async (answers) => { + await delayFail(1000); + return { + nextStepId: 'step2', + updatedAnswers: { ...answers, question1: 'Bob' }, + }; + }, + }, + { + id: 'step2', + questions: [ + { + id: 'question2', + prompt: (answers) => + `Hello, ${answers.question1}! What is your favorite color?`, + inputType: 'text', + }, + ], + next: (answers) => 'done', + }, + ] as Step[]; + + it('should load between steps', async () => { + const { getByLabelText, getByText, queryByText } = render( + + {({ step, answers, setAnswers, handleNext, loading }) => ( +
    + + + setAnswers({ + ...answers, + [step.questions[0].id]: e.target.value, + }) + } + /> + {loading &&

    Loading...

    } + +
    + )} +
    + ); + + expect(queryByText('Loading...')).toBe(null); + fireEvent.change(getByLabelText('What is your name?'), { + target: { value: 'Alice' }, + }); + fireEvent.click(getByText('Next')); + + expect(getByText('Loading...')).toBeInTheDocument(); + fireEvent.click(getByText('Next')); + await waitFor(() => expect(errorSpy).toHaveBeenCalled(), { timeout: 5000 }); + errorSpy.mockRestore(); + }); +}); diff --git a/src/__tests__/WhizFlow_prev.test.tsx b/src/__tests__/WhizFlow_prev.test.tsx new file mode 100644 index 0000000..8dd427e --- /dev/null +++ b/src/__tests__/WhizFlow_prev.test.tsx @@ -0,0 +1,61 @@ +// src/__tests__/WhizFlow.test.tsx +import React from 'react'; +import { render, fireEvent } from '@testing-library/react'; +import '@testing-library/jest-dom/extend-expect'; +import { WhizFlow } from '../WhizFlow'; +import { Step } from '../types'; + +describe('WhizFlow', () => { + const workflow = [ + { + id: 'step1', + questions: [ + { + id: 'question1', + prompt: 'Question 1:', + inputType: 'text', + }, + ], + next: (answers) => 'step2', + }, + { + id: 'step2', + questions: [ + { + id: 'question2', + prompt: 'Question 2:', + inputType: 'text', + }, + ], + next: (answers) => 'done', + }, + ] as Step[]; + + it('transitions back to the previous step', () => { + const { getByLabelText, getByText } = render( + + {({ step, answers, handleNext, handlePrev }) => ( +
    + {step.questions.map((question) => ( + + + + + ))} + + +
    + )} +
    + ); + + fireEvent.click(getByText('Next')); + expect(getByLabelText('Question 2:')).toBeInTheDocument(); + fireEvent.click(getByText('Previous')); + expect(getByLabelText('Question 1:')).toBeInTheDocument(); + }); +}); diff --git a/src/types.ts b/src/types.ts index 295c889..f2a5ffb 100644 --- a/src/types.ts +++ b/src/types.ts @@ -16,9 +16,14 @@ export interface Question { export interface Step { id: string; questions: Question[]; + context?: any; next: ( answers: Answers - ) => string | { nextStepId: string; updatedAnswers?: Answers }; + ) => + | string + | { nextStepId: string; updatedAnswers?: Answers } + | Promise + | Promise<{ nextStepId: string; updatedAnswers?: Answers }>; } export type QuestionRenderFunction = ( @@ -38,8 +43,10 @@ export interface WhizFlowProps { children: (props: { step: Step; answers: Answers; + loading: boolean; setAnswers: (value: Answers) => void; handleNext: (submitterAnswers?: Answers) => void; + handlePrev: () => void; renderQuestion: (questionId: string) => React.ReactNode; }) => JSX.Element; } diff --git a/src/useWhizFlow.ts b/src/useWhizFlow.ts index 83296bb..d8329f4 100644 --- a/src/useWhizFlow.ts +++ b/src/useWhizFlow.ts @@ -8,18 +8,47 @@ export const useWhizFlow = ( ) => { const [currentStep, setCurrentStep] = useState(0); const [answers, setAnswers] = useState({}); + const [loading, setLoading] = useState(false); + const [trail, setTrail] = useState([]); const step = workflow[currentStep]; - const handleNext = (submitterAnswers?: Answers) => { + const handlePrev = async () => { + const prevStep = trail.pop(); + if (prevStep !== undefined && prevStep >= 0) { + setTrail([...trail]); + setCurrentStep(prevStep); + } + }; + + const handleNext = async (submitterAnswers?: Answers) => { const currAnswers = submitterAnswers ?? answers; const result = step.next(currAnswers); - const nextStepId = typeof result === 'string' ? result : result.nextStepId; - const updatedAnswers = - typeof result !== 'string' && result.updatedAnswers - ? result.updatedAnswers - : currAnswers; + let nextStepId = ''; + let updatedAnswers = currAnswers; + if (typeof result === 'string') { + nextStepId = result; + updatedAnswers = currAnswers; + } else if (typeof (result as Promise)?.then === 'function') { + try { + setLoading(true); + const awaitedResult = await result; + setLoading(false); + if (typeof awaitedResult === 'string') { + nextStepId = awaitedResult; + } else { + nextStepId = awaitedResult.nextStepId; + updatedAnswers = awaitedResult.updatedAnswers ?? currAnswers; + } + } catch (ex) { + console.error(`Error: Next step eval failed "${ex}"`); + return; + } + } else if ((result as any)?.nextStepId) { + nextStepId = (result as any).nextStepId; + updatedAnswers = (result as any).updatedAnswers ?? currAnswers; + } if (nextStepId === 'done') { onComplete(updatedAnswers); @@ -34,6 +63,7 @@ export const useWhizFlow = ( return; } + setTrail([...trail, currentStep]); setCurrentStep(nextStepIndex); } }; @@ -41,7 +71,9 @@ export const useWhizFlow = ( return { step, answers, + loading, setAnswers, handleNext, + handlePrev, }; };