@inploi/forms
v1.0.11
Published
Visual form renderer for inploi application flows.
Downloads
1,080
Readme
@inploi/forms
Visual form renderer for inploi application flows. It takes the same flow JSON that @inploi/plugin-chatbot renders sequentially and presents it as a classic, scrollable form. Forms can be rendered inline with the page or opened in a drawer, and are themed through the standard appearance options.
Architecture
- Host plugin (
forms.ts) creates and supervises an iframe, manages drawer open/close, scroll lock, theme propagation, submit transport and Talent Bank duplicate checks. It follows the same iframe scaffolding pattern as@inploi/plugin-kin. - Frame runtime (
forms.runtime.tsx) is a Preact app rendered inside the iframe. It owns form state, validation, draft persistence, user interactions and the host RPC (submit, duplicate-check and address lookuprequestIdcorrelation, inlined — no separate bridge module). - Flow projection (
form.projector.ts) walks the raw flow graph and produces renderable items plus a terminal state. It evaluatesif-block, followsjump, appliesadd-submission, collects submit chains, exposes readycheck-duplicatecandidates, and gathers post-submit text/image/link content. - Shared logic is consumed from
@inploi/flowsfor validation-adjacent flow helpers, conditions, interpolation, submit-response shapes, session keys and duplicate-check request building.
Forms is intentionally a projection-first renderer with a small forms executor, not a copy of the chatbot service interpreter.
Public API
import { formsPlugin } from '@inploi/forms';
const forms = formsPlugin({ appearance: { placement: 'drawer' } });
await forms.open({ flow, title: 'Apply now', context: { jobId: '...' } });Placement
formsPlugin({
appearance: { placement: 'embedded' },
container: '#application-form',
});drawer is the default placement. embedded mounts the iframe into the provided container and resizes it to fit the form content.
Submit
By default, the host plugin submits to /flow/submit using the SDK apiClient. Consumers can override this with onSubmit:
const forms = formsPlugin({
onSubmit: async payload => {
await submitApplication(payload);
return { success: true };
},
});FormsSubmitPayload contains only the public submit data: integrationId, optional job, and filtered submissions.
See forms.protocol.ts for the full set of types (OpenFormsParams, FormsAppearance, FormsSubmitPayload, ...).
Runtime Behaviour
- Drafts are persisted by flow identity, flow keys and context hash. Closing, minimising, failed submit and successful submit preserve the draft. The header reset action is the explicit way to start over.
- Submit is disabled while required fields are missing, values are invalid, a duplicate check is pending, or a submit is already in progress.
- Sequential
integration-application-submitnodes are executed as a chain —FormAppawaits each step in order and short-circuits on the first failure or redirect. Redirect responses show the provider message and replace the footer submit button with a redirect CTA that opens the ATS in a new tab. There is no persistent submit cursor: before a successful submit, any field edit resets submit state, and the next click reruns the whole chain from step 0 (relies on integration idempotency). - Post-submit
text,imageandlinknodes are rendered after a successful final submit. - A successful final submit locks the inputs: they are wrapped in a disabled
<fieldset>, so every control becomes non-editable and visibly muted, while labels, descriptions, informational nodes and links stay fully legible and clickable. The footer CTA and post-submit content remain interactive; the header reset clears the lock (and the draft). end-flowbefore submit is treated as a terminal dead-end and hides the submit button.check-duplicateruns through the host-side Talent Bank client and writes the result back as an integration submission for downstream conditions.question-addresssupports manual entry plus host-side Mapbox suggestions. The regular address fields stay visible; selecting a suggestion fills them and users can still edit manually.integration-workflow-getis expected to be materialized by the backend before runtime; if it reaches forms, the form fails closed instead of skipping integration-specific fields.
