# Installation and usage

Install and start building powerful multi-step forms and surveys.

**Forms.md** (formerly Blocks.md) lets you build powerful multi-step forms and surveys with minimal code. Create production-ready forms that are privacy-focused, accessible, localizable, and themeable. Perfect for user onboarding, data collection, customer feedback, and much more.

***

## Installation

### Install via npm

```
npm install formsmd
```

### Use in browser

Download the distribution files from [the GitHub repo](https://github.com/formsmd/formsmd). Include the files using `<link>` and `<script>` tags in your template.

```html
<!-- Forms.md CSS -->
<link rel="stylesheet" type="text/css" href="path/to/formsmd/dist/css/formsmd.min.css" />
<!--
Or RTL version:
<link rel="stylesheet" type="text/css" href="path/to/formsmd/dist/css/formsmd.rtl.min.css" />
-->

<!-- Forms.md JS bundle -->
<script src="path/to/formsmd/dist/js/formsmd.bundle.min.js"></script>

<!--
Use Composer in the browser:
<script src="path/to/formsmd/dist/js/composer.bundle.min.js"></script>
-->
```

***

## Usage

Create forms programmatically using the `Composer` class, then initialize them with the `Formsmd` class by passing in the template.

{% tabs %}
{% tab title="With composer" %}

```javascript
import "formsmd/dist/css/formsmd.min.css"; // Or import formsmd.rtl.min.css in case of RTL
import { Composer, Formsmd } from "formsmd";
 
// Create form with ID and submission endpoint
const composer = new Composer({
  id: "onboarding-form",
  postUrl: "/api/onboard"
});
 
// Choice input for position
composer.choiceInput("position", {
  question: "What's your position?",
  choices: ["Product Manager", "Software Engineer", "Founder", "Other"],
  required: true
});
 
// Text input if user selects "Other" position
composer.textInput("positionOther", {
  question: "Other",
  required: true,
  labelStyle: "classic",
  displayCondition: {
    dependencies: ["position"],
    condition: "position == 'Other'"
  }
});
 
// Start new slide, progress indicator at 50%
composer.slide({
  pageProgress: "50%"
});
 
// Choice input for how user discovered the product
composer.choiceInput("referralSource", {
  question: "How did you hear about us?",
  choices: ["News", "Search Engine", "Social Media", "Recommendation"],
  required: true
});
 
// Start new slide, show only if user was recommended, progress indicator at 75%
composer.slide({
  jumpCondition: "referralSource == 'Recommendation'",
  pageProgress: "75%"
});
 
// Email input for recommender email address
composer.emailInput("recommender", {
  question: "Who recommended you?",
  description: "We may be able to reach out to them and provide a discount for helping us out."
});
 
// Initialize with template, container, and options
const formsmd = new Formsmd(
  composer.template,
  document.getElementById("onboarding-form-container"),
  {
    postHeaders: {
      Authorization: `Bearer ${localStorage.getItem("token")}`
    }
  }
);
formsmd.init();
```

{% endtab %}

{% tab title="Markdown-like" %}

```javascript
import "formsmd/dist/css/formsmd.min.css"; // Or import formsmd.rtl.min.css in case of RTL
import { Formsmd } from "formsmd";
 
// Create template
const template = `
#! id = onboarding-form
#! post-url = /api/onboard
 
position* = ChoiceInput(
  | question = What's your position?
  | choices = Product Manager, Software Engineer, Founder, Other
)
 
::: [{$ position $}]
{% if position == "Other" %}
positionOther* = TextInput(
  | question = Other
  | labelStyle = classic
)
{% endif %}
:::
 
---
|> 50%
 
referralSource* = ChoiceInput(
  | question = How did you hear about us?
  | choices = News, Search Engine, Social Media, Recommendation
)
 
---
-> referralSource == "Recommendation"
|> 75%
 
recommender = EmailInput(
  | question = Who recommended you?
  | description = We may be able to reach out to them and provide a discount for helping us out.
)
`;
 
// Initialize with template, container, and options
const formsmd = new Formsmd(
  template,
  document.getElementById("onboarding-form-container"),
  {
    postHeaders: {
      Authorization: `Bearer ${localStorage.getItem("token")}`
    }
  }
);
formsmd.init();
```

{% endtab %}
{% endtabs %}

<div><figure><img src="/files/im9UaqOshxjBiVg4QXFo" alt=""><figcaption><p>Slide 1 when "Other" is picked</p></figcaption></figure> <figure><img src="/files/Id3iSEYbwZh43vliO6tS" alt=""><figcaption><p>Slide 2</p></figcaption></figure> <figure><img src="/files/QPzxI086oZw7z0lIK4lc" alt=""><figcaption><p>Slide 3 (only shown if the user was recommended)</p></figcaption></figure></div>

***

## Form settings

The `Composer` constructor accepts an object called `settings` as the argument. These are called form settings, and they can be used to configure various aspects of the form.

```typescript
constructor(settings: object)
```

### Example

```javascript
const composer = new Composer({
  formStyle: "classic",
  id: "my-form",
  postUrl: "/api/endpoint",
});
```

Generates the following Markdown-like syntax:

```
#! form-style = classic
#! id = my-form
#! post-url = /api/endpoint
```

### Arguments

| Name       | Type     | Description                                            |
| ---------- | -------- | ------------------------------------------------------ |
| `settings` | `object` | Object containing configuration settings for the form. |

### Settings parameters

{% tabs %}
{% tab title="With composer" %}
{% hint style="warning" %}
The `formsmdBranding` and/or `footer` parameters can only be set to `"hide"` if your site has a [Pro subscription](https://forms.md/pricing/) (or above).
{% endhint %}

The `settings` argument can contain the following parameters:

| Name                | Type                                        | Description                                                                                                                                              |
| ------------------- | ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `autofocus`         | `"all-slides"`                              | If set to `"all-slides"`, when a new slide becomes active (including first slide on page load), the first form field will be auto-focused.               |
| `buttonAlignment`   | `"center"` \| `"end"` \| `"stretch"`        | Sets the alignment of the CTA buttons on each slide.                                                                                                     |
| `cssPrefix`         | `string`                                    | Prefix added to all CSS classes. Default is `"fmd-"`. If set to `"none"`, the prefix is removed altogether.                                              |
| `dir`               | `"ltr"` \| `"rtl"`                          | Direction of the form's text. Default is `"ltr"`.                                                                                                        |
| `fieldSize`         | `"sm"`                                      | If set to `"sm"`, the size of form fields will be made smaller.                                                                                          |
| `fontSize`          | `"sm"` \| `"lg"`                            | Makes the font size of everything on the form smaller or larger.                                                                                         |
| `formDelimiter`     | `string`                                    | Used to separate parameters when creating form fields. Default is `"\|"`.                                                                                |
| `formsmdBranding`   | `"hide"` \| `"show"`                        | Controls visibility of the Forms.md branding. **Please note**, you need a [Pro subscription](https://forms.md/pricing/) (or above) to hide the branding. |
| `formStyle`         | `"classic"`                                 | If set to `"classic"`, the form fields will have a classic appearance.                                                                                   |
| `footer`            | `"hide"` \| `"show"`                        | Controls visibility of the footer. **Please note**, you need a [Pro subscription](https://forms.md/pricing/) (or above) to hide the footer.              |
| `header`            | `"hide"` \| `"show"` \| `"align"`           | Controls header visibility and alignment.                                                                                                                |
| `headings`          | `"anchored"`                                | If set to `"anchored"`, all headings will contain an anchor link.                                                                                        |
| `id`                | `string`                                    | Identifier for the form. It is highly recommended that every form is given a unique `id`.                                                                |
| `labelStyle`        | `"classic"`                                 | If set to `"classic"`, the question and description of form fields will be made smaller.                                                                 |
| `localization`      | `string`                                    | Sets the language for automatic translation. Default is `"en"`.                                                                                          |
| `page`              | `"form-slides"` \| `"slides"` \| `"single"` | Determines the layout of the form. Default is `"form-slides"`.                                                                                           |
| `pageProgress`      | `"hide"` \| `"show"` \| `"decorative"`      | Controls visibility and function of the page progress.                                                                                                   |
| `placeholders`      | `"hide"` \| `"show"`                        | Controls visibility of input placeholders.                                                                                                               |
| `postSheetName`     | `string`                                    | When sending responses directly to Google Sheets, specifies which sheet to save responses to.                                                            |
| `postUrl`           | `string`                                    | URL to send form responses to using POST request.                                                                                                        |
| `restartButton`     | `"show"`                                    | If set to `"show"`, a restart button will be visible on the end slide.                                                                                   |
| `rounded`           | `"none"` \| `"pill"`                        | Controls rounding of buttons and UI elements.                                                                                                            |
| `slideControls`     | `"hide"` \| `"show"`                        | Controls visibility of next and previous buttons.                                                                                                        |
| `slideDelimiter`    | `string`                                    | Specifies where new slides are created. Default is `"---"`.                                                                                              |
| `submitButtonText`  | `string`                                    | Custom text for all submit buttons.                                                                                                                      |
| `verticalAlignment` | `"start"`                                   | If set to `"start"`, content is aligned to the top of the container vertically.                                                                          |
| {% endtab %}        |                                             |                                                                                                                                                          |

{% tab title="Markdown-like" %}
{% hint style="warning" %}
The `formsmd-branding` and/or `footer` parameters can only be set to `hide` if your site has a [Pro subscription](https://forms.md/pricing/) (or above).
{% endhint %}

A setting is a line in the format `#! {name} = {value}` added anywhere (but usually at the very start). For example, `#! button-alignment = center`. The following settings are available:

| Name                 | Value                                 | Description                                                                                                                                              |
| -------------------- | ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `autofocus`          | `all-slides`                          | If set to `all-slides`, when a new slide becomes active (including first slide on page load), the first form field will be auto-focused.                 |
| `button-alignment`   | `center` \| `end` \| `stretch`        | Sets the alignment of the CTA buttons on each slide.                                                                                                     |
| `css-prefix`         | `string`                              | Prefix added to all CSS classes. Default is `fmd-`. If set to `none`, the prefix is removed altogether.                                                  |
| `dir`                | `ltr` \| `rtl`                        | Direction of the form's text. Default is `ltr`.                                                                                                          |
| `field-size`         | `sm`                                  | If set to `sm`, the size of form fields will be made smaller.                                                                                            |
| `font-size`          | `sm` \| `lg`                          | Makes the font size of everything on the form smaller or larger.                                                                                         |
| `form-delimiter`     | `string`                              | Used to separate parameters when creating form fields. Default is `\|`.                                                                                  |
| `formsmd-branding`   | `hide` \| `show`                      | Controls visibility of the Forms.md branding. **Please note**, you need a [Pro subscription](https://forms.md/pricing/) (or above) to hide the branding. |
| `form-style`         | `classic`                             | If set to `classic`, the form fields will have a classic appearance.                                                                                     |
| `footer`             | `hide` \| `show`                      | Controls visibility of the footer. **Please note**, you need a [Pro subscription](https://forms.md/pricing/) (or above) to hide the footer.              |
| `header`             | `hide` \| `show` \| `align`           | Controls header visibility and alignment.                                                                                                                |
| `headings`           | `anchored`                            | If set to `anchored`, all headings will contain an anchor link.                                                                                          |
| `id`                 | `string`                              | Identifier for the form. It is highly recommended that every form is given a unique `id`.                                                                |
| `label-style`        | `classic`                             | If set to `classic`, the question and description of form fields will be made smaller.                                                                   |
| `localization`       | `string`                              | Sets the language for automatic translation. Default is `"en"`.                                                                                          |
| `page`               | `form-slides` \| `slides` \| `single` | Determines the layout of the form. Default is `form-slides`.                                                                                             |
| `page-progress`      | `hide` \| `show` \| `decorative`      | Controls visibility and function of the page progress.                                                                                                   |
| `placeholders`       | `hide` \| `show`                      | Controls visibility of input placeholders.                                                                                                               |
| `post-sheet-name`    | `string`                              | When sending responses directly to Google Sheets, specifies which sheet to save responses to.                                                            |
| `post-url`           | `string`                              | URL to send form responses to using POST request.                                                                                                        |
| `restart-button`     | `show`                                | If set to `show`, a restart button will be visible on the end slide.                                                                                     |
| `rounded`            | `none` \| `pill`                      | Controls rounding of buttons and UI elements.                                                                                                            |
| `slide-controls`     | `hide` \| `show`                      | Controls visibility of next and previous buttons.                                                                                                        |
| `slide-delimiter`    | `string`                              | Specifies where new slides are created. Default is `---`.                                                                                                |
| `submit-button-text` | `string`                              | Custom text for all submit buttons.                                                                                                                      |
| `vertical-alignment` | `start`                               | If set to `start`, content is aligned to the top of the container vertically.                                                                            |
| {% endtab %}         |                                       |                                                                                                                                                          |
| {% endtabs %}        |                                       |                                                                                                                                                          |

{% hint style="info" %}
More settings are available, but they are mainly relevant for full page forms. See the actual code and test cases to learn more.
{% endhint %}

***

## Options

The `Formsmd` constructor accepts the template of the form, the container where the form will be rendered, and the options to configure form behavior and appearance.

```typescript
constructor(template: string, container: HTMLElement, options: object)
```

### Example

```javascript
const formsmd = new Formsmd(
  composer.template,
  document.getElementById("my-form-container"),
  {
    postHeaders: {
      Authorization: `Bearer ${localStorage.getItem("token")}`,
    },
    themeLight: {
      accent: "#353148",
      accentForeground: "#e2d2b6",
      backgroundColor: "#e2d2b6",
      color: "#353148"
    }
  }
);
formsmd.init();
```

### Arguments

| Name        | Type          | Description                                                     |
| ----------- | ------------- | --------------------------------------------------------------- |
| `template`  | `string`      | The form template string.                                       |
| `container` | `HTMLElement` | The container element where the form will be rendered.          |
| `options`   | `object`      | Object containing configuration options for form functionality. |

### Options parameters

{% hint style="warning" %}
The `formsmdBranding` and/or `footer` parameters can only be set to `"hide"` if your site has a [Pro subscription](https://forms.md/pricing/) (or above).
{% endhint %}

The `options` argument can contain the following parameters:

| Name                       | Type                                   | Description                                                                                                                                              |
| -------------------------- | -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `colorScheme`              | `"light"` \| `"dark"`                  | Default or initial color scheme of the form. Default is `"light"`.                                                                                       |
| `errorFieldKey`            | `string`                               | Key used to identify the field in error objects. Default is `"field"`.                                                                                   |
| `errorMessageKey`          | `string`                               | Key used to identify the error message in error objects. Default is `"message"`.                                                                         |
| `footer`                   | `"hide"` \| `"show"`                   | Controls visibility of the footer. **Please note**, you need a [Pro subscription](https://forms.md/pricing/) (or above) to hide the footer.              |
| `formsmdBranding`          | `"hide"` \| `"show"`                   | Controls visibility of the Forms.md branding. **Please note**, you need a [Pro subscription](https://forms.md/pricing/) (or above) to hide the branding. |
| `getHeaders`               | `object`                               | Headers for GET requests.                                                                                                                                |
| `isFullPage`               | `boolean`                              | Whether to render in full page mode. Default is `false`.                                                                                                 |
| `paddingInlineBottom`      | `number`                               | Padding bottom for inline forms. Default is `20`.                                                                                                        |
| `paddingInlineHorizontal`  | `number`                               | Horizontal padding for inline forms. Default is `0`.                                                                                                     |
| `paddingInlineTop`         | `number`                               | Padding top for inline forms. Default is `20`.                                                                                                           |
| `pageProgress`             | `"hide"` \| `"show"` \| `"decorative"` | Controls visibility and function of the page progress.                                                                                                   |
| `postData`                 | `object`                               | Extra data sent with POST requests.                                                                                                                      |
| `postHeaders`              | `object`                               | Headers for POST requests.                                                                                                                               |
| `prioritizeURLFormData`    | `boolean`                              | Whether to prioritize URL form data. Default is `false`.                                                                                                 |
| `recaptcha`                | `object`                               | Option for setting up Google reCAPTCHA for spam protection. [Learn more](/getting-started/spam-protection).                                              |
| `sanitize`                 | `boolean`                              | Whether to sanitize template. Default is `true`.                                                                                                         |
| `saveState`                | `boolean`                              | Whether to save form data in local storage. Default is `true`.                                                                                           |
| `sendFilesAsBase64`        | `boolean`                              | Whether to send files as base64. Default is `false`.                                                                                                     |
| `setColorSchemeAttrsAgain` | `boolean`                              | Whether to set color scheme attributes again.                                                                                                            |
| `slideControls`            | `"hide"` \| `"show"`                   | Controls visibility of next and previous buttons.                                                                                                        |
| `startSlide`               | `number`                               | The index of the first slide to make active. Default is `0`.                                                                                             |
| `themeDark`                | `object`                               | Dark theme colors. [Learn more](/customization/theming).                                                                                                 |
| `themeLight`               | `object`                               | Light theme colors. [Learn more](/customization/theming).                                                                                                |

***

## Difference between form settings and options

There is quite a bit of overlap between form settings and options. Generally speaking, form settings are configuration that is unique to that specific form. Options on the other hand, are meant to be shared among multiple or all forms on your website or app. However, this is a soft rule, and it should always come down to convenience and ease of use.

## FAQs

### [How do I run a function after form submission?](/getting-started/frequently-asked-questions#how-do-i-run-a-function-after-form-submission) <a href="#how-do-i-run-a-function-after-form-submission" id="how-do-i-run-a-function-after-form-submission"></a>

### [How do get my server's submission errors to work?](/getting-started/frequently-asked-questions#how-do-get-my-servers-submission-errors-to-work) <a href="#how-do-get-my-servers-submission-errors-to-work" id="how-do-get-my-servers-submission-errors-to-work"></a>


# Form settings

Configure various aspects of your forms.

## Overview

The `Composer` constructor accepts an object called `settings` as the argument. These are called form settings, and they can be used to configure various aspects of the form.

```typescript
constructor(settings: object)
```

### Example

```javascript
const composer = new Composer({
  formStyle: "classic",
  id: "my-form",
  postUrl: "/api/endpoint",
});
```

Generates the following Markdown-like syntax:

```
#! form-style = classic
#! id = my-form
#! post-url = /api/endpoint
```

### Arguments

| Name       | Type     | Description                                            |
| ---------- | -------- | ------------------------------------------------------ |
| `settings` | `object` | Object containing configuration settings for the form. |

### Settings parameters

{% tabs %}
{% tab title="With composer" %}
{% hint style="warning" %}
The `formsmdBranding` and/or `footer` parameters can only be set to `"hide"` if your site has a [Pro subscription](https://forms.md/pricing/) (or above).
{% endhint %}

The `settings` argument can contain the following parameters:

| Name                | Type                                        | Description                                                                                                                                              |
| ------------------- | ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `autofocus`         | `"all-slides"`                              | If set to `"all-slides"`, when a new slide becomes active (including first slide on page load), the first form field will be auto-focused.               |
| `buttonAlignment`   | `"center"` \| `"end"` \| `"stretch"`        | Sets the alignment of the CTA buttons on each slide.                                                                                                     |
| `cssPrefix`         | `string`                                    | Prefix added to all CSS classes. Default is `"fmd-"`. If set to `"none"`, the prefix is removed altogether.                                              |
| `dir`               | `"ltr"` \| `"rtl"`                          | Direction of the form's text. Default is `"ltr"`.                                                                                                        |
| `fieldSize`         | `"sm"`                                      | If set to `"sm"`, the size of form fields will be made smaller.                                                                                          |
| `fontSize`          | `"sm"` \| `"lg"`                            | Makes the font size of everything on the form smaller or larger.                                                                                         |
| `formDelimiter`     | `string`                                    | Used to separate parameters when creating form fields. Default is `"\|"`.                                                                                |
| `formsmdBranding`   | `"hide"` \| `"show"`                        | Controls visibility of the Forms.md branding. **Please note**, you need a [Pro subscription](https://forms.md/pricing/) (or above) to hide the branding. |
| `formStyle`         | `"classic"`                                 | If set to `"classic"`, the form fields will have a classic appearance.                                                                                   |
| `footer`            | `"hide"` \| `"show"`                        | Controls visibility of the footer. **Please note**, you need a [Pro subscription](https://forms.md/pricing/) (or above) to hide the footer.              |
| `header`            | `"hide"` \| `"show"` \| `"align"`           | Controls header visibility and alignment.                                                                                                                |
| `headings`          | `"anchored"`                                | If set to `"anchored"`, all headings will contain an anchor link.                                                                                        |
| `id`                | `string`                                    | Identifier for the form. It is highly recommended that every form is given a unique `id`.                                                                |
| `labelStyle`        | `"classic"`                                 | If set to `"classic"`, the question and description of form fields will be made smaller.                                                                 |
| `localization`      | `string`                                    | Sets the language for automatic translation. Default is `"en"`.                                                                                          |
| `page`              | `"form-slides"` \| `"slides"` \| `"single"` | Determines the layout of the form. Default is `"form-slides"`.                                                                                           |
| `pageProgress`      | `"hide"` \| `"show"` \| `"decorative"`      | Controls visibility and function of the page progress.                                                                                                   |
| `placeholders`      | `"hide"` \| `"show"`                        | Controls visibility of input placeholders.                                                                                                               |
| `postSheetName`     | `string`                                    | When sending responses directly to Google Sheets, specifies which sheet to save responses to.                                                            |
| `postUrl`           | `string`                                    | URL to send form responses to using POST request.                                                                                                        |
| `restartButton`     | `"show"`                                    | If set to `"show"`, a restart button will be visible on the end slide.                                                                                   |
| `rounded`           | `"none"` \| `"pill"`                        | Controls rounding of buttons and UI elements.                                                                                                            |
| `slideControls`     | `"hide"` \| `"show"`                        | Controls visibility of next and previous buttons.                                                                                                        |
| `slideDelimiter`    | `string`                                    | Specifies where new slides are created. Default is `"---"`.                                                                                              |
| `submitButtonText`  | `string`                                    | Custom text for all submit buttons.                                                                                                                      |
| `verticalAlignment` | `"start"`                                   | If set to `"start"`, content is aligned to the top of the container vertically.                                                                          |
| {% endtab %}        |                                             |                                                                                                                                                          |

{% tab title="Markdown-like" %}
{% hint style="warning" %}
The `formsmd-branding` and/or `footer` parameters can only be set to `hide` if your site has a [Pro subscription](https://forms.md/pricing/) (or above).
{% endhint %}

A setting is a line in the format `#! {name} = {value}` added anywhere (but usually at the very start). For example, `#! button-alignment = center`. The following settings are available:

| Name                 | Value                                 | Description                                                                                                                                              |
| -------------------- | ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `autofocus`          | `all-slides`                          | If set to `all-slides`, when a new slide becomes active (including first slide on page load), the first form field will be auto-focused.                 |
| `button-alignment`   | `center` \| `end` \| `stretch`        | Sets the alignment of the CTA buttons on each slide.                                                                                                     |
| `css-prefix`         | `string`                              | Prefix added to all CSS classes. Default is `fmd-`. If set to `none`, the prefix is removed altogether.                                                  |
| `dir`                | `ltr` \| `rtl`                        | Direction of the form's text. Default is `ltr`.                                                                                                          |
| `field-size`         | `sm`                                  | If set to `sm`, the size of form fields will be made smaller.                                                                                            |
| `font-size`          | `sm` \| `lg`                          | Makes the font size of everything on the form smaller or larger.                                                                                         |
| `form-delimiter`     | `string`                              | Used to separate parameters when creating form fields. Default is `\|`.                                                                                  |
| `formsmd-branding`   | `hide` \| `show`                      | Controls visibility of the Forms.md branding. **Please note**, you need a [Pro subscription](https://forms.md/pricing/) (or above) to hide the branding. |
| `form-style`         | `classic`                             | If set to `classic`, the form fields will have a classic appearance.                                                                                     |
| `footer`             | `hide` \| `show`                      | Controls visibility of the footer. **Please note**, you need a [Pro subscription](https://forms.md/pricing/) (or above) to hide the footer.              |
| `header`             | `hide` \| `show` \| `align`           | Controls header visibility and alignment.                                                                                                                |
| `headings`           | `anchored`                            | If set to `anchored`, all headings will contain an anchor link.                                                                                          |
| `id`                 | `string`                              | Identifier for the form. It is highly recommended that every form is given a unique `id`.                                                                |
| `label-style`        | `classic`                             | If set to `classic`, the question and description of form fields will be made smaller.                                                                   |
| `localization`       | `string`                              | Sets the language for automatic translation. Default is `"en"`.                                                                                          |
| `page`               | `form-slides` \| `slides` \| `single` | Determines the layout of the form. Default is `form-slides`.                                                                                             |
| `page-progress`      | `hide` \| `show` \| `decorative`      | Controls visibility and function of the page progress.                                                                                                   |
| `placeholders`       | `hide` \| `show`                      | Controls visibility of input placeholders.                                                                                                               |
| `post-sheet-name`    | `string`                              | When sending responses directly to Google Sheets, specifies which sheet to save responses to.                                                            |
| `post-url`           | `string`                              | URL to send form responses to using POST request.                                                                                                        |
| `restart-button`     | `show`                                | If set to `show`, a restart button will be visible on the end slide.                                                                                     |
| `rounded`            | `none` \| `pill`                      | Controls rounding of buttons and UI elements.                                                                                                            |
| `slide-controls`     | `hide` \| `show`                      | Controls visibility of next and previous buttons.                                                                                                        |
| `slide-delimiter`    | `string`                              | Specifies where new slides are created. Default is `---`.                                                                                                |
| `submit-button-text` | `string`                              | Custom text for all submit buttons.                                                                                                                      |
| `vertical-alignment` | `start`                               | If set to `start`, content is aligned to the top of the container vertically.                                                                            |
| {% endtab %}         |                                       |                                                                                                                                                          |
| {% endtabs %}        |                                       |                                                                                                                                                          |

{% hint style="info" %}
More settings are available, but they are mainly relevant for full page forms. See the actual code and test cases to learn more.
{% endhint %}

***

## Difference between form settings and options

There is quite a bit of overlap between form settings and [options](/getting-started/options). Generally speaking, form settings are configuration that is unique to that specific form. Options on the other hand, are meant to be shared among multiple or all forms on your website or app. However, this is a soft rule, and it should always come down to convenience and ease of use.


# Options

Configure form behavior and appearance

## Overview

The `Formsmd` constructor accepts the template of the form, the container where the form will be rendered, and the options to configure form behavior and appearance.

```typescript
constructor(template: string, container: HTMLElement, options: object)
```

### Example

```javascript
const formsmd = new Formsmd(
  composer.template,
  document.getElementById("my-form-container"),
  {
    postHeaders: {
      Authorization: `Bearer ${localStorage.getItem("token")}`,
    },
    themeLight: {
      accent: "#353148",
      accentForeground: "#e2d2b6",
      backgroundColor: "#e2d2b6",
      color: "#353148"
    }
  }
);
formsmd.init();
```

### Arguments

| Name        | Type          | Description                                                     |
| ----------- | ------------- | --------------------------------------------------------------- |
| `template`  | `string`      | The form template string.                                       |
| `container` | `HTMLElement` | The container element where the form will be rendered.          |
| `options`   | `object`      | Object containing configuration options for form functionality. |

### Options parameters

{% hint style="warning" %}
The `formsmdBranding` and/or `footer` parameters can only be set to `"hide"` if your site has a [Pro subscription](https://forms.md/pricing/) (or above).
{% endhint %}

The `options` argument can contain the following parameters:

| Name                       | Type                                   | Description                                                                                                                                              |
| -------------------------- | -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `colorScheme`              | `"light"` \| `"dark"`                  | Default or initial color scheme of the form. Default is `"light"`.                                                                                       |
| `errorFieldKey`            | `string`                               | Key used to identify the field in error objects. Default is `"field"`.                                                                                   |
| `errorMessageKey`          | `string`                               | Key used to identify the error message in error objects. Default is `"message"`.                                                                         |
| `footer`                   | `"hide"` \| `"show"`                   | Controls visibility of the footer. **Please note**, you need a [Pro subscription](https://forms.md/pricing/) (or above) to hide the footer.              |
| `formsmdBranding`          | `"hide"` \| `"show"`                   | Controls visibility of the Forms.md branding. **Please note**, you need a [Pro subscription](https://forms.md/pricing/) (or above) to hide the branding. |
| `getHeaders`               | `object`                               | Headers for GET requests.                                                                                                                                |
| `isFullPage`               | `boolean`                              | Whether to render in full page mode. Default is `false`.                                                                                                 |
| `paddingInlineBottom`      | `number`                               | Padding bottom for inline forms. Default is `20`.                                                                                                        |
| `paddingInlineHorizontal`  | `number`                               | Horizontal padding for inline forms. Default is `0`.                                                                                                     |
| `paddingInlineTop`         | `number`                               | Padding top for inline forms. Default is `20`.                                                                                                           |
| `pageProgress`             | `"hide"` \| `"show"` \| `"decorative"` | Controls visibility and function of the page progress.                                                                                                   |
| `postData`                 | `object`                               | Extra data sent with POST requests.                                                                                                                      |
| `postHeaders`              | `object`                               | Headers for POST requests.                                                                                                                               |
| `prioritizeURLFormData`    | `boolean`                              | Whether to prioritize URL form data. Default is `false`.                                                                                                 |
| `recaptcha`                | `object`                               | Option for setting up Google reCAPTCHA for spam protection. [Learn more](/getting-started/spam-protection).                                              |
| `sanitize`                 | `boolean`                              | Whether to sanitize template. Default is `true`.                                                                                                         |
| `saveState`                | `boolean`                              | Whether to save form data in local storage. Default is `true`.                                                                                           |
| `sendFilesAsBase64`        | `boolean`                              | Whether to send files as base64. Default is `false`.                                                                                                     |
| `setColorSchemeAttrsAgain` | `boolean`                              | Whether to set color scheme attributes again.                                                                                                            |
| `slideControls`            | `"hide"` \| `"show"`                   | Controls visibility of next and previous buttons.                                                                                                        |
| `startSlide`               | `number`                               | The index of the first slide to make active. Default is `0`.                                                                                             |
| `themeDark`                | `object`                               | Dark theme colors. [Learn more](/customization/theming).                                                                                                 |
| `themeLight`               | `object`                               | Light theme colors. [Learn more](/customization/theming).                                                                                                |

***

## Difference between form settings and options

There is quite a bit of overlap between [form settings](/getting-started/settings) and options. Generally speaking, form settings are configuration that is unique to that specific form. Options on the other hand, are meant to be shared among multiple or all forms on your website or app. However, this is a soft rule, and it should always come down to convenience and ease of use.


# Frequently asked questions

Get answers to commonly asked questions.

## How do I run a function after form submission?

In many cases, you may want to do something after the user has submitted a form. To do this, override the `onCompletion()` function of the `Formsmd` class after instantiation. This function has the `json` argument, which is the result returned from hitting the `postURL` endpoint.

```javascript
import { Composer, Formsmd } from "formsmd";

const composer = new Composer({
  id: "my-form",
  postUrl: "/api/endpoint"
});

const formsmd = new Formsmd(
  composer.template,
  document.getElementById("my-form-container"),
  {}
);

// Override to log the result
formsmd.onCompletion = function(json) {
  console.log(json);
}

formsmd.init();
```

***

## How do get my server's submission errors to work?

By default, server error responses are expected to follow the OpenAPI format. However, you can customize error handling to work with your server's error format in two ways:

### 1. Configure the error field and message keys

If your server returns errors with different field names than the OpenAPI standard, you can configure the keys using the `errorFieldKey` and `errorMessageKey` options:

```javascript
const formsmd = new Formsmd(
  composer.template,
  document.getElementById("my-form-container"),
  {
    errorFieldKey: "attr",
    errorMessageKey: "detail"
  }
);
```

### 2. Override the error parsing function

For more complex error formats, override the `getSubmissionErrors()` function. This function receives the JSON response from your server and should return an array of error message strings:

```javascript
const formsmd = new Formsmd(
  composer.template,
  document.getElementById("my-form-container"),
  {}
);

// Override to handle errors
formsmd.getSubmissionErrors = function(json) {
  const messages = [];
  
  // Parse nested validation errors
  if (json.validation && json.validation.errors) {
    for (const error of json.validation.errors) {
      messages.push(`${error.attr}: ${error.detail}`);
    }
  }
  
  // Add general error message
  if (json.error) {
    messages.push(json.error);
  }
  
  return messages;
};

formsmd.init();
```


# Spam protection

Protect against spam responses using Google reCAPTCHA.

## Set up Google reCAPTCHA

Use the built-in Google reCAPTCHA integration to protect against spam and fraudulent responses. To set up spam protection, use the `recaptcha` [option](/getting-started/options) and set your `siteKey` during instantiation. [Learn how to create the site key](https://cloud.google.com/recaptcha/docs/create-key-website) (also known as a reCAPTCHA key). Once this is done, your forms will be protected.

{% hint style="info" %}
Only reCAPTCHA `v3` is supported.
{% endhint %}

```javascript
import { Composer, Formsmd } from "formsmd";

const composer = new Composer({
  id: "my-form"
});
 
composer.choiceInput("position", {
  question: "What's your position?",
  choices: ["Product Manager", "Software Engineer", "Founder", "Other"],
  required: true
});
 
// Set the site key during instantiation
const formsmd = new Formsmd(
  composer.template,
  document.getElementById("my-form-container"),
  {
    recaptcha: {
      siteKey: "<YOUR_RECAPTCHA_KEY>"
    }
  }
);
formsmd.init();
```

***

## The `recaptcha` option

The `recaptcha` option has the following parameters:

| Name            | Type                                            | Description                                                     |
| --------------- | ----------------------------------------------- | --------------------------------------------------------------- |
| `siteKey`       | `string`                                        | Google reCAPTCHA site key.                                      |
| `action`        | `string`                                        | The action name. Default is `"submit"`.                         |
| `badgePosition` | `"bottomleft"` \| `"bottomright"` \| `"inline"` | The position of the reCAPTCHA badge. Default is `"bottomleft"`. |
| `hideBadge`     | `boolean`                                       | Whether to hide the reCAPTCHA badge. Default is `false`.        |

### Hide the badge

Set the `hideBadge` parameter to `true` to hide the reCAPTCHA badge.

```javascript
const formsmd = new Formsmd(
  composer.template,
  document.getElementById("my-form-container"),
  {
    recaptcha: {
      siteKey: "<YOUR_RECAPTCHA_KEY>",
      hideBadge: true
    }
  }
);
formsmd.init();
```

{% hint style="warning" %}
You need to manually include links to Google's privacy policy and terms of service if you decide to hide the reCAPTCHA badge. [Learn more](https://developers.google.com/recaptcha/docs/faq#id-like-to-hide-the-recaptcha-badge.-what-is-allowed).
{% endhint %}

***

## Server-side validation

{% hint style="info" %}
Reference: <https://developers.google.com/recaptcha/docs/verify>
{% endhint %}

Once Google reCAPTCHA has been set up, each form submission will contain an extra field called `_captcha`. This is the token that needs to be verified by sending the following request:

* **URL:** `https://www.google.com/recaptcha/api/siteverify`
* **Method:** `POST`&#x20;

| POST Parameter        | Description                                                                                                           |
| --------------------- | --------------------------------------------------------------------------------------------------------------------- |
| `secret` (required)   | The shared key between your site and reCAPTCHA.                                                                       |
| `response` (required) | The user response token provided by the reCAPTCHA client-side integration on your site. This is the `_captcha` token. |
| `remoteip`            | Optional. The user's IP address.                                                                                      |

The response is a JSON object:

```json
{
  "success": true|false,
  "challenge_ts": timestamp,  // timestamp of the challenge load (ISO format yyyy-MM-dd'T'HH:mm:ssZZ)
  "hostname": string,         // the hostname of the site where the reCAPTCHA was solved
  "error-codes": [...]        // optional
}
```


# React

Build powerful multi-step forms and surveys in your React app.

**Forms.md** is a pure JavaScript library with minimal dependencies. All it requires is an input (form template) as a plain string, and a container to render the form in. This means that it is very easy to use with React, Angular, Vue, Svelte, etc. The only "catch" is that the forms only work on the client side, that is, where `window` and `document` are available.

***

## Use with React

{% hint style="warning" %}
React is declarative, while the `Composer` is imperative. This may be slightly off-putting at first. For an easy fix, you may choose to create the form template in another file and just export the template (maybe even keep all the form template files in a separate directory).
{% endhint %}

Given below is an example of a form working inside a React app:

#### MailingListForm.tsx

In the component below, the form template is created using the `Composer`. The actual component only returns an empty `<div>` element. Once the component has mounted, the form is then initialized and rendered.

{% tabs %}
{% tab title="With composer" %}

```tsx
// "use client";

import "formsmd/dist/css/formsmd.min.css";
import { useEffect, useRef } from "react";
import { Composer, Formsmd } from "formsmd";

const composer = new Composer({
  id: "mailing-list-form",
  postUrl: "/api/mailing-list",
});

composer.emailInput("email", {
  question: "Join our mailing list",
  description:
    "Stay informed of every update that matters - we'll deliver the latest news straight to your inbox.",
  required: true,
});

export default function MailingListForm() {
  const containerRef = useRef(null);

  useEffect(() => {
    if (containerRef.current) {
      const formsmd = new Formsmd(composer.template, containerRef.current, {
        postHeaders: {
          Authorization: `Basic ${process.env.PUBLIC_API_KEY}`,
        },
      });
      formsmd.init();
    }
  }, []);

  return (
    <div ref={containerRef} style={{ width: "500px", height: "500px" }}></div>
  );
}
```

{% endtab %}

{% tab title="Markdown-like" %}

```tsx
// "use client";

import "formsmd/dist/css/formsmd.min.css";
import { useEffect, useRef } from "react";
import { Formsmd } from "formsmd";

const template = `
#! id = mailing-list-form
#! post-url = /api/mailing-list

email* = EmailInput(
  | question = Join our mailing list
  | description = Stay informed of every update that matters - we'll deliver the latest news straight to your inbox.
)
`;

export default function MailingListForm() {
  const containerRef = useRef(null);

  useEffect(() => {
    if (containerRef.current) {
      const formsmd = new Formsmd(template, containerRef.current, {
        postHeaders: {
          Authorization: `Basic ${process.env.PUBLIC_API_KEY}`,
        },
      });
      formsmd.init();
    }
  }, []);

  return (
    <div ref={containerRef} style={{ width: "500px", height: "500px" }}></div>
  );
}
```

{% endtab %}
{% endtabs %}

#### page.tsx

```jsx
import MailingListForm from "./MailingListForm";

export default function Home() {
  return (
    <MailingListForm />
  );
}
```

***

## Next.js, Remix, Astro, etc., and SSR

As mentioned above, the forms only work on the client-side. If you're using a framework which uses SSR, you'll need to make sure the components that use **Forms.md** are rendered only on the client-side. How you do this will vary from framework to framework. For example, in Next.js, this can be done with the [`"use client"`](https://nextjs.org/docs/app/building-your-application/rendering/client-components) directive.


# Theming

Customize your forms to perfectly match your brand.

## Set up custom themes

Set the `themeLight` and `themeDark` [options](/getting-started/options) during instantiation to create custom themes that perfectly match your brand. The options correspond to the theme used for light mode or dark mode.

```javascript
import { Composer, Formsmd } from "formsmd";

const composer = new Composer({
  id: "my-form"
});

composer.opinionScale("nps", {
  question: "How likely are you to recommend our product to a friend or colleague?",
  required: true
});

// Set the themes during instantiation
const formsmd = new Formsmd(
  composer.template,
  document.getElementById("my-form-container"),
  {
    themeLight: {
      accent: "#353148",
      accentForeground: "#e2d2b6",
      backgroundColor: "#e2d2b6",
      color: "#353148"
    },
    themeDark: {
      accent: "#e2d2b6",
      accentForeground: "#353148",
      backgroundColor: "#353148",
      color: "#e2d2b6"
    }
  }
);
formsmd.init();
```

<div><figure><img src="/files/pNIDloX7k6abEZ4hQM3Q" alt=""><figcaption><p>Theming - light mode</p></figcaption></figure> <figure><img src="/files/JsjuWWK6pal3MxnLUcFm" alt=""><figcaption><p>Theming - dark mode</p></figcaption></figure></div>

***

## The `themeLight` and `themeDark` options

{% hint style="info" %}
The colors must be HTML names, hex codes, or RGB values.
{% endhint %}

Both the theme options have the following parameters:

| Name               | Type     | Description                                                                   |
| ------------------ | -------- | ----------------------------------------------------------------------------- |
| `accent`           | `string` | The primary color used on buttons, form fields, etc.                          |
| `accentForeground` | `string` | The text color used on `accent` background, for example, the text on buttons. |
| `backgroundColor`  | `string` | The `background-color` of the page.                                           |
| `color`            | `string` | The `color` of the text on the page.                                          |

***

## Light and dark modes

The color scheme is set using the `colorScheme` [option](/getting-started/options), which is set to `"light"` by default. Of course, this can be changed during instantiation. For example, the form below would start off in dark mode.

```javascript
const formsmd = new Formsmd(
  composer.template,
  document.getElementById("my-form-container"),
  {
    colorScheme: "dark"
  }
);
formsmd.init();
```

### Toggle

If you have a toggle on your website that lets users select light mode or dark mode (or system), you will need to dynamically update the color scheme of the forms when the user changes their preference. This is easy to do because the color scheme is handled using the `data-fmd-color-scheme` attribute on the `.fmd-root` container:

* For light mode, the `data-fmd-color-scheme` has the `"light"` value.
* For dark mode, the `data-fmd-color-scheme` has the `"dark"` value.

For example, here's a snippet the handles dynamic color schemes on a Bootstrap/[Halfmoon](https://www.gethalfmoon.com/) website:

```javascript
function toggleColorScheme() {
  const colorSchemeToSet =
    document.documentElement.getAttribute("data-bs-theme") === "light"
      ? "dark"
      : "light";
  document.documentElement.setAttribute("data-bs-theme", colorSchemeToSet);
  setCookie("halfmoon:color-scheme", colorSchemeToSet, 365);
    
  // Set color scheme of all Forms.md root elements
  document.querySelectorAll(".fmd-root").forEach((div) => {
    div.setAttribute("data-fmd-color-scheme", colorSchemeToSet);
  });
}
```


# Localization

Localize and translate your forms to other languages.

<figure><img src="/files/lo9Dl8Vnnrh1OifAEurm" alt=""><figcaption><p>Localized to Japanese</p></figcaption></figure>

## Localize to another language <a href="#localizable-to-any-language" id="localizable-to-any-language"></a>

Set the `localization` [form setting](/getting-started/settings) to a supported language code and write your questions, descriptions, etc., in that language—everything will be automatically translated. Here's an example form in Japanese:

```javascript
import { Composer } from "formsmd";

const composer = new Composer({
  id: "my-form",
  localization: "ja"
});
 
composer.opinionScale("nps", {
  question: "当社の製品を友人や同僚に推薦する可能性はどの程度ありますか？",
  required: true
});
```

Generates the following Markdown-like syntax:

```
#! id = my-form
#! localization = ja
 
nps* = OpinionScale(
  | question = 当社の製品を友人や同僚に推薦する可能性はどの程度ありますか？
)
```

***

## Supported language codes

The following language codes are supported:

| Language                                                                                | Code   |
| --------------------------------------------------------------------------------------- | ------ |
| English (default)                                                                       | `"en"` |
| Arabic (please also set the `dir` [form setting](/getting-started/settings) to `"rtl"`) | `"ar"` |
| Bengali                                                                                 | `"bn"` |
| German                                                                                  | `"de"` |
| Spanish                                                                                 | `"es"` |
| French                                                                                  | `"fr"` |
| Japanese                                                                                | `"ja"` |
| Portuguese                                                                              | `"pt"` |
| Mandarin Chinese                                                                        | `"zh"` |

***

## Dynamic translations

Use the handy `translate()` function to define all of the translation strings as you create the form. Here's the function overview:

```
translate(localization: string, translations: object)
```

It takes the ISO alpha-2 language code as the first argument (`localization`) and an object of `translations` as the second argument. In the example below, the form will be in English or Japanese depending on the language code in the user's local storage (so user preference).

```javascript
import { translate, Composer, Formsmd } from "formsmd";

function getFeedbackFormTemplate(localization) {
  // Pass the localization as a form setting
  const composer = new Composer({
    id: "my-form",
    localization: localization
  });

  // Define the translations in the opinion scale function
  composer.opinionScale("nps", {
    question: translate(localization, {
      en: "How likely are you to recommend our company's products to friends and colleagues?",
      ja: "当社の製品を友人や同僚に推薦する可能性はどの程度ありますか？"
    }),
    required: true
  });

  return composer.template;
}

// Pass the localization from local storage
const formsmd = new Formsmd(
  getFeedbackFormTemplate(localStorage.getItem("localization")),
  document.getElementById("my-form-container"),
  {}
);
formsmd.init();

```

<div><figure><img src="/files/TxX1WJUfNNfGI0LcYRqe" alt=""><figcaption><p>Form in English</p></figcaption></figure> <figure><img src="/files/lo9Dl8Vnnrh1OifAEurm" alt=""><figcaption><p>Same form in Japanese</p></figcaption></figure></div>

***

## Adding support for a new language <a href="#adding-support-for-a-new-language" id="adding-support-for-a-new-language"></a>

In order to add support for a new language, the language needs to be added to the `translations` object in the [`src/translations.js`](https://github.com/formsmd/formsmd/blob/main/src/translations.js) file. The key for this entry would be the language code, and the value would be a JSON object containing translations required for creating the forms.

Once this entry is in place, the language would be supported after the project is rebuilt using `npm run build`.

{% hint style="info" %}
If you want a specific language to be supported, please create a PR by adding an entry in [`src/translations.js`](https://github.com/formsmd/formsmd/blob/main/src/translations.js), or just create an issue containing all of the relevant translations.
{% endhint %}


# Text input

Create text inputs in your forms.

<figure><img src="/files/aoHXNkFWtmXwfK32eyVZ" alt=""><figcaption><p>Text input</p></figcaption></figure>

Use the `textInput()` function to create text inputs in your forms. It can be used for single-line or multi-line text inputs. The multi-line ones use the `<textarea>` element instead of the regular `<input type="text">`.

***

## Basic usage

```javascript
import { Composer } from "formsmd";

const composer = new Composer({
  id: "my-form"
});

composer.textInput("fullName", {
  question: "What is your name?"
});
```

Generates the following Markdown-like syntax:

```
#! id = my-form

fullName = TextInput(
  | question = What is your name?
)
```

### Required

Add the `required` parameter to make the field mandatory:

```javascript
composer.textInput("fullName", {
  question: "What is your name?",
  required: true
});
```

Generates the following Markdown-like syntax:

```
fullName* = TextInput(
  | question = What is your name?
)
```

***

## Function overview

The following is the overview of the function:

```typescript
textInput(name: string, params: object)
```

### Arguments

| Name     | Type     | Description                                                                                                                                                     |
| -------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`   | `string` | A unique name for your form field that you'll use to identify the user's response.<mark style="color:red;">\*</mark>                                            |
| `params` | `object` | An object containing all the configuration parameters for your text input field (see the [parameters section](#parameters) below for the full list of options). |

{% hint style="danger" %} <mark style="color:red;">\*</mark>Avoid values for the `name` argument which may be the names of HTML attributes, such as `"name"`, `"role"`, `"id"`, etc. This is because by default, the form's template string is first sanitized using [DOMPurify](https://github.com/cure53/DOMPurify), and these values may be removed to prevent DOM clobbering.
{% endhint %}

***

## Parameters

### Shared parameters

These parameters are common to all form fields:

| Name                  | Type                                            | Description                                                                                                                                                                                                                                                                             |
| --------------------- | ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `question` (required) | `string`                                        | The main question or label of the form field.                                                                                                                                                                                                                                           |
| `required`            | `true` (`boolean`)                              | When set, the field becomes required.                                                                                                                                                                                                                                                   |
| `description`         | `string`                                        | Any extra information that the user may need to fill out the form. Appears right below the question.                                                                                                                                                                                    |
| `fieldSize`           | `"sm"`                                          | When set to `"sm"`, the font sizes of the question, description, and answer are made smaller.                                                                                                                                                                                           |
| `labelStyle`          | `"classic"`                                     | When set to `"classic"`, the question and description of the form field are made smaller.                                                                                                                                                                                               |
| `subfield`            | `true` (`boolean`)                              | When set, the question and description of the form field are made smaller. Functionally the same as setting `labelStyle` to `"classic"`.                                                                                                                                                |
| `disabled`            | `true` (`boolean`)                              | When set, the input is disabled.                                                                                                                                                                                                                                                        |
| `autofocus`           | `true` (`boolean`)                              | When set, the input will be automatically focused when the parent slide becomes active, or immediately after page load.                                                                                                                                                                 |
| `id`                  | `string`                                        | The `id` attribute of the form field container.                                                                                                                                                                                                                                         |
| `classNames`          | `string[]`                                      | The CSS class names of the form field. [See the available CSS utility classes](/content/css-utility-classes).                                                                                                                                                                           |
| `attrs`               | `Array<{ name: string, value: string }>`        | Other HTML attributes of the form field. Each attribute has a `name` and `value` property.                                                                                                                                                                                              |
| `displayCondition`    | `{ dependencies: string[], condition: string }` | Controls when the field is shown. The `dependencies` lists the fields to watch, and `condition` is the expression that must be true to show the field. The `condition` must be a valid [Nunjucks](https://mozilla.github.io/nunjucks/) expression. [See example](#conditional-display). |

### Text input specific parameters

| Name          | Type               | Description                                                                                         |
| ------------- | ------------------ | --------------------------------------------------------------------------------------------------- |
| `placeholder` | `string`           | Sets the `placeholder` attribute of the input.                                                      |
| `multiline`   | `true` (`boolean`) | When set, the input accepts values with one or more lines because the `<textarea>` element is used. |
| `maxlength`   | `number`           | If set, this becomes the maximum number of allowed characters in the input.                         |
| `pattern`     | `string`           | If set, the input value must match the given pattern.                                               |
| `value`       | `string`           | If set, this becomes the default value of the input.                                                |

***

## Examples

### Multi-line input with character limit

```javascript
composer.textInput("comments", {
  question: "Please share your feedback",
  description: "Your feedback helps us improve our service",
  multiline: true,
  maxlength: 500,
  placeholder: "Type your feedback here..."
});
```

Generates the following Markdown-like syntax:

```
comments = TextInput(
  | question = Please share your feedback
  | description = Your feedback helps us improve our service
  | multiline
  | maxlength = 500
  | placeholder = Type your feedback here...
)
```

### Input with pattern validation

```javascript
composer.textInput("username", {
  question: "Choose a username",
  description: "Letters and numbers only, 3-20 characters",
  pattern: "^[a-zA-Z0-9]{3,20}$",
  required: true
});
```

Generates the following Markdown-like syntax:

```
username* = TextInput(
  | question = Choose a username
  | description = Letters and numbers only, 3-20 characters
  | pattern = ^[a-zA-Z0-9]{3,20}$
)
```

### Styled input with custom attributes

Add CSS classes and other HTML attributes using the `classNames` and `attrs` parameters. Please note, these class names and attributes are added to the `<div>` or `<fieldset>` container that contains the actual input field(s).

```javascript
composer.textInput("fullName", {
  question: "What is your full name?",
  classNames: ["col-6", "xs:col-6"],
  attrs: [
    { name: "style", value: "font-size: 18px;" }
  ]
});
```

Generates the following Markdown-like syntax:

```
[.col-6 .xs:col-6 style="font-size: 18px;"]
fullName = TextInput(
  | question = What is your full name?
)
```

Please [see the available CSS utility classes](/content/css-utility-classes).

### Conditional display

Conditionally show or hide an input field using the `displayCondition` parameter. It works as follows:

* `dependencies` lists the fields to watch.
* `condition` is the expression that must be true to show the field. This must be a valid [Nunjucks](https://mozilla.github.io/nunjucks/) expression.

For instance, in the example below, the `otherReason` text input will only show up if the user picks the `"Other"` option in the first choice input.

```javascript
composer.choiceInput("reason", {
  question: "What is your reason?",
  required: true,
  choices: ["A", "B", "C", "Other"]
})

composer.textInput("otherReason", {
  question: "Please specify other reason",
  displayCondition: {
    dependencies: ["reason"],
    condition: "reason == 'Other'"
  }
});
```

Generates the following Markdown-like syntax:

```
reason* = ChoiceInput(
  | question = What is your reason?
  | choices = A, B, C, Other
)

::: [{$ reason $}]
{% if reason == "Other" %}
otherReason = TextInput(
  | question = Please specify other reason
)
{% endif %}
:::
```


# Email input

Create email inputs in your forms.

<figure><img src="/files/h9p4yGv2EUYxnlh1Eddq" alt=""><figcaption><p>Email input</p></figcaption></figure>

Use the `emailInput()` function to create email inputs in your forms. It uses the HTML `<input type="email">` element which provides built-in email validation.

***

## Basic usage

```javascript
import { Composer } from "formsmd";

const composer = new Composer({
  id: "my-form"
});

composer.emailInput("email", {
  question: "What is your email address?"
});
```

Generates the following Markdown-like syntax:

```
#! id = my-form

email = EmailInput(
  | question = What is your email address?
)
```

### Required

Add the `required` parameter to make the field mandatory:

```javascript
composer.emailInput("email", {
  question: "What is your email address?",
  required: true
});
```

Generates the following Markdown-like syntax:

```
email* = EmailInput(
  | question = What is your email address?
)
```

***

## Function overview

The following is the overview of the function:

```typescript
emailInput(name: string, params: object)
```

### Arguments

| Name     | Type     | Description                                                                                                                                                      |
| -------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`   | `string` | A unique name for your form field that you'll use to identify the user's response.<mark style="color:red;">\*</mark>                                             |
| `params` | `object` | An object containing all the configuration parameters for your email input field (see the [parameters section](#parameters) below for the full list of options). |

{% hint style="danger" %} <mark style="color:red;">\*</mark>Avoid values for the `name` argument which may be the names of HTML attributes, such as `"name"`, `"role"`, `"id"`, etc. This is because by default, the form's template string is first sanitized using [DOMPurify](https://github.com/cure53/DOMPurify), and these values may be removed to prevent DOM clobbering.
{% endhint %}

***

## Parameters

### Shared parameters

These parameters are common to all form fields:

| Name                  | Type                                            | Description                                                                                                                                                                                                                                                                             |
| --------------------- | ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `question` (required) | `string`                                        | The main question or label of the form field.                                                                                                                                                                                                                                           |
| `required`            | `true` (`boolean`)                              | When set, the field becomes required.                                                                                                                                                                                                                                                   |
| `description`         | `string`                                        | Any extra information that the user may need to fill out the form. Appears right below the question.                                                                                                                                                                                    |
| `fieldSize`           | `"sm"`                                          | When set to `"sm"`, the font sizes of the question, description, and answer are made smaller.                                                                                                                                                                                           |
| `labelStyle`          | `"classic"`                                     | When set to `"classic"`, the question and description of the form field are made smaller.                                                                                                                                                                                               |
| `subfield`            | `true` (`boolean`)                              | When set, the question and description of the form field are made smaller. Functionally the same as setting `labelStyle` to `"classic"`.                                                                                                                                                |
| `disabled`            | `true` (`boolean`)                              | When set, the input is disabled.                                                                                                                                                                                                                                                        |
| `autofocus`           | `true` (`boolean`)                              | When set, the input will be automatically focused when the parent slide becomes active, or immediately after page load.                                                                                                                                                                 |
| `id`                  | `string`                                        | The `id` attribute of the form field container.                                                                                                                                                                                                                                         |
| `classNames`          | `string[]`                                      | The CSS class names of the form field. [See the available CSS utility classes](/content/css-utility-classes).                                                                                                                                                                           |
| `attrs`               | `Array<{ name: string, value: string }>`        | Other HTML attributes of the form field. Each attribute has a `name` and `value` property.                                                                                                                                                                                              |
| `displayCondition`    | `{ dependencies: string[], condition: string }` | Controls when the field is shown. The `dependencies` lists the fields to watch, and `condition` is the expression that must be true to show the field. The `condition` must be a valid [Nunjucks](https://mozilla.github.io/nunjucks/) expression. [See example](#conditional-display). |

### Email input specific parameters

| Name          | Type     | Description                                                                 |
| ------------- | -------- | --------------------------------------------------------------------------- |
| `placeholder` | `string` | Sets the `placeholder` attribute of the input.                              |
| `maxlength`   | `number` | If set, this becomes the maximum number of allowed characters in the input. |
| `pattern`     | `string` | If set, the input value must match the given pattern.                       |
| `value`       | `string` | If set, this becomes the default value of the input.                        |

***

## Examples

### Email input with custom placeholder

```javascript
composer.emailInput("contactEmail", {
  question: "What's your email address?",
  description: "We'll send the confirmation to this email",
  placeholder: "you@example.com",
  required: true
});
```

Generates the following Markdown-like syntax:

```
contactEmail* = EmailInput(
  | question = What's your email address?
  | description = We'll send the confirmation to this email
  | placeholder = you@example.com
)
```

### Email input with pattern validation

```javascript
composer.emailInput("workEmail", {
  question: "Work email address",
  description: "Please use your company email",
  pattern: ".*@company\\.com$",
  required: true
});
```

Generates the following Markdown-like syntax:

```
workEmail* = EmailInput(
  | question = Work email address
  | description = Please use your company email
  | pattern = .*@company\.com$
)
```

### Styled email input with custom attributes

Add CSS classes and other HTML attributes using the `classNames` and `attrs` parameters. Please note, these class names and attributes are added to the `<div>` or `<fieldset>` container that contains the actual input field(s).

```javascript
composer.emailInput("emailAddress", {
  question: "Email address",
  classNames: ["col-6", "xs:col-6"],
  attrs: [
    { name: "style", value: "font-size: 18px;" }
  ]
});
```

Generates the following Markdown-like syntax:

```
[.col-6 .xs:col-6 style="font-size: 18px;"]
emailAddress = EmailInput(
  | question = Email address
)
```

Please [see the available CSS utility classes](/content/css-utility-classes).

### Conditional display

Conditionally show or hide an email input field using the `displayCondition` parameter. It works as follows:

* `dependencies` lists the fields to watch.
* `condition` is the expression that must be true to show the field. This must be a valid [Nunjucks](https://mozilla.github.io/nunjucks/) expression.

For instance, in the example below, the alternate email input will only show up if the user indicates they want to provide one.

```javascript
composer.choiceInput("wantAlternateEmail", {
  question: "Would you like to provide an alternate email?",
  required: true,
  choices: ["Yes", "No"]
})

composer.emailInput("alternateEmail", {
  question: "Alternate email address",
  displayCondition: {
    dependencies: ["wantAlternateEmail"],
    condition: "wantAlternateEmail == 'Yes'"
  }
});
```

Generates the following Markdown-like syntax:

```
wantAlternateEmail* = ChoiceInput(
  | question = Would you like to provide an alternate email?
  | choices = Yes, No
)

::: [{$ wantAlternateEmail $}]
{% if wantAlternateEmail == "Yes" %}
alternateEmail = EmailInput(
  | question = Alternate email address
)
{% endif %}
:::
```


# URL input

Create URL inputs in your forms.

<figure><img src="/files/uMlAHlCTcEg5wsYqyaL8" alt=""><figcaption><p>URL input</p></figcaption></figure>

Use the `urlInput()` function to create URL inputs in your forms. It uses the HTML `<input type="url">` element which provides built-in URL validation.

***

## Basic usage

```javascript
import { Composer } from "formsmd";

const composer = new Composer({
  id: "my-form"
});

composer.urlInput("website", {
  question: "What is your website's URL?"
});
```

Generates the following Markdown-like syntax:

```
#! id = my-form

website = URLInput(
  | question = What is your website's URL?
)
```

### Required

Add the `required` parameter to make the field mandatory:

```javascript
composer.urlInput("website", {
  question: "What is your website's URL?",
  required: true
});
```

Generates the following Markdown-like syntax:

```
website* = URLInput(
  | question = What is your website's URL?
)
```

***

## Function overview

The following is the overview of the function:

```typescript
urlInput(name: string, params: object)
```

### Arguments

| Name     | Type     | Description                                                                                                                                                    |
| -------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`   | `string` | A unique name for your form field that you'll use to identify the user's response.<mark style="color:red;">\*</mark>                                           |
| `params` | `object` | An object containing all the configuration parameters for your URL input field (see the [parameters section](#parameters) below for the full list of options). |

{% hint style="danger" %} <mark style="color:red;">\*</mark>Avoid values for the `name` argument which may be the names of HTML attributes, such as `"name"`, `"role"`, `"id"`, etc. This is because by default, the form's template string is first sanitized using [DOMPurify](https://github.com/cure53/DOMPurify), and these values may be removed to prevent DOM clobbering.
{% endhint %}

***

## Parameters

### Shared parameters

These parameters are common to all form fields:

| Name                  | Type                                            | Description                                                                                                                                                                                                                                                                             |
| --------------------- | ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `question` (required) | `string`                                        | The main question or label of the form field.                                                                                                                                                                                                                                           |
| `required`            | `true` (`boolean`)                              | When set, the field becomes required.                                                                                                                                                                                                                                                   |
| `description`         | `string`                                        | Any extra information that the user may need to fill out the form. Appears right below the question.                                                                                                                                                                                    |
| `fieldSize`           | `"sm"`                                          | When set to `"sm"`, the font sizes of the question, description, and answer are made smaller.                                                                                                                                                                                           |
| `labelStyle`          | `"classic"`                                     | When set to `"classic"`, the question and description of the form field are made smaller.                                                                                                                                                                                               |
| `subfield`            | `true` (`boolean`)                              | When set, the question and description of the form field are made smaller. Functionally the same as setting `labelStyle` to `"classic"`.                                                                                                                                                |
| `disabled`            | `true` (`boolean`)                              | When set, the input is disabled.                                                                                                                                                                                                                                                        |
| `autofocus`           | `true` (`boolean`)                              | When set, the input will be automatically focused when the parent slide becomes active, or immediately after page load.                                                                                                                                                                 |
| `id`                  | `string`                                        | The `id` attribute of the form field container.                                                                                                                                                                                                                                         |
| `classNames`          | `string[]`                                      | The CSS class names of the form field. [See the available CSS utility classes](/content/css-utility-classes).                                                                                                                                                                           |
| `attrs`               | `Array<{ name: string, value: string }>`        | Other HTML attributes of the form field. Each attribute has a `name` and `value` property.                                                                                                                                                                                              |
| `displayCondition`    | `{ dependencies: string[], condition: string }` | Controls when the field is shown. The `dependencies` lists the fields to watch, and `condition` is the expression that must be true to show the field. The `condition` must be a valid [Nunjucks](https://mozilla.github.io/nunjucks/) expression. [See example](#conditional-display). |

### URL input specific parameters

| Name          | Type     | Description                                                                 |
| ------------- | -------- | --------------------------------------------------------------------------- |
| `placeholder` | `string` | Sets the `placeholder` attribute of the input.                              |
| `maxlength`   | `number` | If set, this becomes the maximum number of allowed characters in the input. |
| `pattern`     | `string` | If set, the input value must match the given pattern.                       |
| `value`       | `string` | If set, this becomes the default value of the input.                        |

***

## Examples

### URL input with custom placeholder

```javascript
composer.urlInput("blogUrl", {
  question: "What's your blog URL?",
  description: "Enter the full URL including https://",
  placeholder: "https://myblog.com",
  required: true
});
```

Generates the following Markdown-like syntax:

```
blogUrl* = URLInput(
  | question = What's your blog URL?
  | description = Enter the full URL including https://
  | placeholder = https://myblog.com
)
```

### URL input with pattern validation

```javascript
composer.urlInput("githubProfile", {
  question: "GitHub profile URL",
  description: "Please enter your GitHub profile URL",
  pattern: "https://github\\.com/[\\w-]+",
  required: true
});
```

Generates the following Markdown-like syntax:

```
githubProfile* = URLInput(
  | question = GitHub profile URL
  | description = Please enter your GitHub profile URL
  | pattern = https://github\.com/[\w-]+
)
```

### Styled URL input with custom attributes

Add CSS classes and other HTML attributes using the `classNames` and `attrs` parameters. Please note, these class names and attributes are added to the `<div>` or `<fieldset>` container that contains the actual input field(s).

```javascript
composer.urlInput("portfolioUrl", {
  question: "Portfolio URL",
  classNames: ["col-6", "xs:col-6"],
  attrs: [
    { name: "style", value: "font-size: 18px;" }
  ]
});
```

Generates the following Markdown-like syntax:

```
[.col-6 .xs:col-6 style="font-size: 18px;"]
portfolioUrl = URLInput(
  | question = Portfolio URL
)
```

Please [see the available CSS utility classes](/content/css-utility-classes).

### Conditional display

Conditionally show or hide a URL input field using the `displayCondition` parameter. It works as follows:

* `dependencies` lists the fields to watch.
* `condition` is the expression that must be true to show the field. This must be a valid [Nunjucks](https://mozilla.github.io/nunjucks/) expression.

For instance, in the example below, the portfolio URL input will only show up if the user indicates they have a portfolio website.

```javascript
composer.choiceInput("hasPortfolio", {
  question: "Do you have a portfolio website?",
  required: true,
  choices: ["Yes", "No"]
})

composer.urlInput("portfolioUrl", {
  question: "Portfolio website URL",
  displayCondition: {
    dependencies: ["hasPortfolio"],
    condition: "hasPortfolio == 'Yes'"
  }
});
```

Generates the following Markdown-like syntax:

```
hasPortfolio* = ChoiceInput(
  | question = Do you have a portfolio website?
  | choices = Yes, No
)

::: [{$ hasPortfolio $}]
{% if hasPortfolio == "Yes" %}
portfolioUrl = URLInput(
  | question = Portfolio website URL
)
{% endif %}
:::
```


# Telephone input

Create telephone inputs in your forms.

<figure><img src="/files/rfvYfAT1uALSFeot6Eof" alt=""><figcaption><p>Telephone input</p></figcaption></figure>

Use the `telInput()` function to create telephone inputs in your forms. It uses the HTML `<input type="tel">` element which provides built-in telephone format validation.

***

## Basic usage

```javascript
import { Composer } from "formsmd";

const composer = new Composer({
  id: "my-form"
});

composer.telInput("phone", {
  question: "What is your phone number?"
});
```

Generates the following Markdown-like syntax:

```
#! id = my-form

phone = TelInput(
  | question = What is your phone number?
)
```

### Required

Add the `required` parameter to make the field mandatory:

```javascript
composer.telInput("phone", {
  question: "What is your phone number?",
  required: true
});
```

Generates the following Markdown-like syntax:

```
phone* = TelInput(
  | question = What is your phone number?
)
```

***

## Function overview

The following is the overview of the function:

```typescript
telInput(name: string, params: object)
```

### Arguments

| Name     | Type     | Description                                                                                                                                                          |
| -------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`   | `string` | A unique name for your form field that you'll use to identify the user's response.<mark style="color:red;">\*</mark>                                                 |
| `params` | `object` | An object containing all the configuration parameters for your telephone input field (see the [parameters section](#parameters) below for the full list of options). |

{% hint style="danger" %} <mark style="color:red;">\*</mark>Avoid values for the `name` argument which may be the names of HTML attributes, such as `"name"`, `"role"`, `"id"`, etc. This is because by default, the form's template string is first sanitized using [DOMPurify](https://github.com/cure53/DOMPurify), and these values may be removed to prevent DOM clobbering.
{% endhint %}

***

## Parameters

### Shared parameters

These parameters are common to all form fields:

| Name                  | Type                                            | Description                                                                                                                                                                                                                                                                             |
| --------------------- | ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `question` (required) | `string`                                        | The main question or label of the form field.                                                                                                                                                                                                                                           |
| `required`            | `true` (`boolean`)                              | When set, the field becomes required.                                                                                                                                                                                                                                                   |
| `description`         | `string`                                        | Any extra information that the user may need to fill out the form. Appears right below the question.                                                                                                                                                                                    |
| `fieldSize`           | `"sm"`                                          | When set to `"sm"`, the font sizes of the question, description, and answer are made smaller.                                                                                                                                                                                           |
| `labelStyle`          | `"classic"`                                     | When set to `"classic"`, the question and description of the form field are made smaller.                                                                                                                                                                                               |
| `subfield`            | `true` (`boolean`)                              | When set, the question and description of the form field are made smaller. Functionally the same as setting `labelStyle` to `"classic"`.                                                                                                                                                |
| `disabled`            | `true` (`boolean`)                              | When set, the input is disabled.                                                                                                                                                                                                                                                        |
| `autofocus`           | `true` (`boolean`)                              | When set, the input will be automatically focused when the parent slide becomes active, or immediately after page load.                                                                                                                                                                 |
| `id`                  | `string`                                        | The `id` attribute of the form field container.                                                                                                                                                                                                                                         |
| `classNames`          | `string[]`                                      | The CSS class names of the form field. [See the available CSS utility classes](/content/css-utility-classes).                                                                                                                                                                           |
| `attrs`               | `Array<{ name: string, value: string }>`        | Other HTML attributes of the form field. Each attribute has a `name` and `value` property.                                                                                                                                                                                              |
| `displayCondition`    | `{ dependencies: string[], condition: string }` | Controls when the field is shown. The `dependencies` lists the fields to watch, and `condition` is the expression that must be true to show the field. The `condition` must be a valid [Nunjucks](https://mozilla.github.io/nunjucks/) expression. [See example](#conditional-display). |

### Telephone input specific parameters

| Name                 | Type       | Description                                                                                                           |
| -------------------- | ---------- | --------------------------------------------------------------------------------------------------------------------- |
| `placeholder`        | `string`   | Sets the `placeholder` attribute of the input.                                                                        |
| `maxlength`          | `number`   | If set, this becomes the maximum number of allowed characters in the input.                                           |
| `pattern`            | `string`   | If set, the input value must match the given pattern.                                                                 |
| `value`              | `string`   | If set, this becomes the default value of the input.                                                                  |
| `country`            | `string`   | The default country code (e.g., `"US"`, `"CA"`, `"GB"`, etc. Defaults to `"US"` if not specified. ISO alpha-2 format. |
| `availableCountries` | `string[]` | Array of available country codes (e.g., `["US", "CA", "GB"]`).                                                        |

***

## Examples

### Telephone input with custom placeholder

```javascript
composer.telInput("contactPhone", {
  question: "What's your phone number?",
  description: "We'll use this number to contact you if needed",
  placeholder: "(555) 123-4567",
  required: true
});
```

Generates the following Markdown-like syntax:

```
contactPhone* = TelInput(
  | question = What's your phone number?
  | description = We'll use this number to contact you if needed
  | placeholder = (555) 123-4567
)
```

### Telephone input with specific country and available countries

```javascript
composer.telInput("phoneNumber", {
  question: "Phone number",
  description: "Please provide a UK phone number",
  country: "GB",
  availableCountries: ["GB", "IE"],
  required: true
});
```

Generates the following Markdown-like syntax:

```
phoneNumber* = TelInput(
  | question = Phone number
  | description = Please provide a UK phone number
  | country = GB
  | availableCountries = GB, IE
)
```

### Styled telephone input with custom attributes

Add CSS classes and other HTML attributes using the `classNames` and `attrs` parameters. Please note, these class names and attributes are added to the `<div>` or `<fieldset>` container that contains the actual input field(s).

```javascript
composer.telInput("phoneNumber", {
  question: "Phone number",
  classNames: ["col-6", "xs:col-6"],
  attrs: [
    { name: "style", value: "font-size: 18px;" }
  ]
});
```

Generates the following Markdown-like syntax:

```
[.col-6 .xs:col-6 style="font-size: 18px;"]
phoneNumber = TelInput(
  | question = Phone number
)
```

Please [see the available CSS utility classes](/content/css-utility-classes).

### Conditional display

Conditionally show or hide a telephone input field using the `displayCondition` parameter. It works as follows:

* `dependencies` lists the fields to watch.
* `condition` is the expression that must be true to show the field. This must be a valid [Nunjucks](https://mozilla.github.io/nunjucks/) expression.

For instance, in the example below, the mobile phone input will only show up if the user indicates they want to receive SMS notifications.

```javascript
composer.choiceInput("wantSMS", {
  question: "Would you like to receive SMS notifications?",
  required: true,
  choices: ["Yes", "No"]
})

composer.telInput("mobilePhone", {
  question: "Mobile phone number",
  displayCondition: {
    dependencies: ["wantSMS"],
    condition: "wantSMS == 'Yes'"
  }
});
```

Generates the following Markdown-like syntax:

```
wantSMS* = ChoiceInput(
  | question = Would you like to receive SMS notifications?
  | choices = Yes, No
)

::: [{$ wantSMS $}]
{% if wantSMS == "Yes" %}
mobilePhone = TelInput(
  | question = Mobile phone number
)
{% endif %}
:::
```

## Notes

* The selected country code is sent separately from the actual phone number during form submission. For example, if we had an input with the name `contactNumber`, the actual number would be sent under the `contactNumber` key, while the selected country code would be sent under the `contactNumberCountryCode`.


# Password input

Create password inputs in your forms.

<figure><img src="/files/1vls1huBk1RZ8gVS2SWc" alt=""><figcaption><p>Password input</p></figcaption></figure>

Use the `passwordInput()` function to create password inputs in your forms. It uses the HTML `<input type="password">` element which masks the input value for security.

***

## Basic usage

```javascript
import { Composer } from "formsmd";

const composer = new Composer({
  id: "my-form"
});

composer.passwordInput("password", {
  question: "Create a password"
});
```

Generates the following Markdown-like syntax:

```
#! id = my-form

password = PasswordInput(
  | question = Create a password
)
```

### Required

Add the `required` parameter to make the field mandatory:

```javascript
composer.passwordInput("password", {
  question: "Create a password",
  required: true
});
```

Generates the following Markdown-like syntax:

```
password* = PasswordInput(
  | question = Create a password
)
```

***

## Function overview

The following is the overview of the function:

```typescript
passwordInput(name: string, params: object)
```

### Arguments

| Name     | Type     | Description                                                                                                                                                         |
| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`   | `string` | A unique name for your form field that you'll use to identify the user's response.<mark style="color:red;">\*</mark>                                                |
| `params` | `object` | An object containing all the configuration parameters for your password input field (see the [parameters section](#parameters) below for the full list of options). |

{% hint style="danger" %} <mark style="color:red;">\*</mark>Avoid values for the `name` argument which may be the names of HTML attributes, such as `"name"`, `"role"`, `"id"`, etc. This is because by default, the form's template string is first sanitized using [DOMPurify](https://github.com/cure53/DOMPurify), and these values may be removed to prevent DOM clobbering.
{% endhint %}

***

## Parameters

### Shared parameters

These parameters are common to all form fields:

| Name                  | Type                                            | Description                                                                                                                                                                                                                                                                             |
| --------------------- | ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `question` (required) | `string`                                        | The main question or label of the form field.                                                                                                                                                                                                                                           |
| `required`            | `true` (`boolean`)                              | When set, the field becomes required.                                                                                                                                                                                                                                                   |
| `description`         | `string`                                        | Any extra information that the user may need to fill out the form. Appears right below the question.                                                                                                                                                                                    |
| `fieldSize`           | `"sm"`                                          | When set to `"sm"`, the font sizes of the question, description, and answer are made smaller.                                                                                                                                                                                           |
| `labelStyle`          | `"classic"`                                     | When set to `"classic"`, the question and description of the form field are made smaller.                                                                                                                                                                                               |
| `subfield`            | `true` (`boolean`)                              | When set, the question and description of the form field are made smaller. Functionally the same as setting `labelStyle` to `"classic"`.                                                                                                                                                |
| `disabled`            | `true` (`boolean`)                              | When set, the input is disabled.                                                                                                                                                                                                                                                        |
| `autofocus`           | `true` (`boolean`)                              | When set, the input will be automatically focused when the parent slide becomes active, or immediately after page load.                                                                                                                                                                 |
| `id`                  | `string`                                        | The `id` attribute of the form field container.                                                                                                                                                                                                                                         |
| `classNames`          | `string[]`                                      | The CSS class names of the form field. [See the available CSS utility classes](/content/css-utility-classes).                                                                                                                                                                           |
| `attrs`               | `Array<{ name: string, value: string }>`        | Other HTML attributes of the form field. Each attribute has a `name` and `value` property.                                                                                                                                                                                              |
| `displayCondition`    | `{ dependencies: string[], condition: string }` | Controls when the field is shown. The `dependencies` lists the fields to watch, and `condition` is the expression that must be true to show the field. The `condition` must be a valid [Nunjucks](https://mozilla.github.io/nunjucks/) expression. [See example](#conditional-display). |

### Password input specific parameters

| Name          | Type     | Description                                                                 |
| ------------- | -------- | --------------------------------------------------------------------------- |
| `placeholder` | `string` | Sets the `placeholder` attribute of the input.                              |
| `maxlength`   | `number` | If set, this becomes the maximum number of allowed characters in the input. |
| `pattern`     | `string` | If set, the input value must match the given pattern.                       |
| `value`       | `string` | If set, this becomes the default value of the input.                        |

***

## Examples

### Password input with custom placeholder

```javascript
composer.passwordInput("newPassword", {
  question: "Create a new password",
  description: "Must be at least 8 characters long",
  placeholder: "Enter your password",
  required: true
});
```

Generates the following Markdown-like syntax:

```
newPassword* = PasswordInput(
  | question = Create a new password
  | description = Must be at least 8 characters long
  | placeholder = Enter your password
)
```

### Password input with pattern validation

```javascript
composer.passwordInput("password", {
  question: "Create a password",
  description: "Must contain at least one uppercase letter, one lowercase letter, and one number",
  pattern: "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d).{8,}$",
  required: true
});
```

Generates the following Markdown-like syntax:

```
password* = PasswordInput(
  | question = Create a password
  | description = Must contain at least one uppercase letter, one lowercase letter, and one number
  | pattern = ^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$
)
```

### Styled password input with custom attributes

Add CSS classes and other HTML attributes using the `classNames` and `attrs` parameters. Please note, these class names and attributes are added to the `<div>` or `<fieldset>` container that contains the actual input field(s).

```javascript
composer.passwordInput("accountPassword", {
  question: "Account password",
  classNames: ["col-6", "xs:col-6"],
  attrs: [
    { name: "style", value: "font-size: 18px;" }
  ]
});
```

Generates the following Markdown-like syntax:

```
[.col-6 .xs:col-6 style="font-size: 18px;"]
accountPassword = PasswordInput(
  | question = Account password
)
```

Please [see the available CSS utility classes](/content/css-utility-classes).

### Conditional display

Conditionally show or hide a password input field using the `displayCondition` parameter. It works as follows:

* `dependencies` lists the fields to watch.
* `condition` is the expression that must be true to show the field. This must be a valid [Nunjucks](https://mozilla.github.io/nunjucks/) expression.

For instance, in the example below, the password input will only show up if the user chooses to create an account.

```javascript
composer.choiceInput("createAccount", {
  question: "Would you like to create an account?",
  required: true,
  choices: ["Yes", "No"]
})

composer.passwordInput("accountPassword", {
  question: "Create a password",
  description: "Must be at least 8 characters long",
  displayCondition: {
    dependencies: ["createAccount"],
    condition: "createAccount == 'Yes'"
  }
});
```

Generates the following Markdown-like syntax:

```
createAccount* = ChoiceInput(
  | question = Would you like to create an account?
  | choices = Yes, No
)

::: [{$ createAccount $}]
{% if createAccount == "Yes" %}
accountPassword = PasswordInput(
  | question = Create a password
  | description = Must be at least 8 characters long
)
{% endif %}
:::
```


# Number input

Create number inputs in your forms.

<figure><img src="/files/yhzVhvplcDDdocTZenSv" alt=""><figcaption><p>Number input</p></figcaption></figure>

Use the `numberInput()` function to create number inputs in your forms. It uses the HTML `<input type="number">` element which provides built-in number validation.

***

## Basic usage

```javascript
import { Composer } from "formsmd";

const composer = new Composer({
  id: "my-form"
});

composer.numberInput("quantity", {
  question: "How many items would you like?"
});
```

Generates the following Markdown-like syntax:

```
#! id = my-form

quantity = NumberInput(
  | question = How many items would you like?
)
```

### Required

Add the `required` parameter to make the field mandatory:

```javascript
composer.numberInput("quantity", {
  question: "How many items would you like?",
  required: true
});
```

Generates the following Markdown-like syntax:

```
quantity* = NumberInput(
  | question = How many items would you like?
)
```

***

## Function overview

The following is the overview of the function:

```typescript
numberInput(name: string, params: object)
```

### Arguments

| Name     | Type     | Description                                                                                                                                                       |
| -------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`   | `string` | A unique name for your form field that you'll use to identify the user's response.<mark style="color:red;">\*</mark>                                              |
| `params` | `object` | An object containing all the configuration parameters for your number input field (see the [parameters section](#parameters) below for the full list of options). |

{% hint style="danger" %} <mark style="color:red;">\*</mark>Avoid values for the `name` argument which may be the names of HTML attributes, such as `"name"`, `"role"`, `"id"`, etc. This is because by default, the form's template string is first sanitized using [DOMPurify](https://github.com/cure53/DOMPurify), and these values may be removed to prevent DOM clobbering.
{% endhint %}

***

## Parameters

### Shared parameters

These parameters are common to all form fields:

| Name                  | Type                                            | Description                                                                                                                                                                                                                                                                             |
| --------------------- | ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `question` (required) | `string`                                        | The main question or label of the form field.                                                                                                                                                                                                                                           |
| `required`            | `true` (`boolean`)                              | When set, the field becomes required.                                                                                                                                                                                                                                                   |
| `description`         | `string`                                        | Any extra information that the user may need to fill out the form. Appears right below the question.                                                                                                                                                                                    |
| `fieldSize`           | `"sm"`                                          | When set to `"sm"`, the font sizes of the question, description, and answer are made smaller.                                                                                                                                                                                           |
| `labelStyle`          | `"classic"`                                     | When set to `"classic"`, the question and description of the form field are made smaller.                                                                                                                                                                                               |
| `subfield`            | `true` (`boolean`)                              | When set, the question and description of the form field are made smaller. Functionally the same as setting `labelStyle` to `"classic"`.                                                                                                                                                |
| `disabled`            | `true` (`boolean`)                              | When set, the input is disabled.                                                                                                                                                                                                                                                        |
| `autofocus`           | `true` (`boolean`)                              | When set, the input will be automatically focused when the parent slide becomes active, or immediately after page load.                                                                                                                                                                 |
| `id`                  | `string`                                        | The `id` attribute of the form field container.                                                                                                                                                                                                                                         |
| `classNames`          | `string[]`                                      | The CSS class names of the form field. [See the available CSS utility classes](/content/css-utility-classes).                                                                                                                                                                           |
| `attrs`               | `Array<{ name: string, value: string }>`        | Other HTML attributes of the form field. Each attribute has a `name` and `value` property.                                                                                                                                                                                              |
| `displayCondition`    | `{ dependencies: string[], condition: string }` | Controls when the field is shown. The `dependencies` lists the fields to watch, and `condition` is the expression that must be true to show the field. The `condition` must be a valid [Nunjucks](https://mozilla.github.io/nunjucks/) expression. [See example](#conditional-display). |

### Number input specific parameters

| Name          | Type     | Description                                                                         |
| ------------- | -------- | ----------------------------------------------------------------------------------- |
| `placeholder` | `string` | Sets the `placeholder` attribute of the input.                                      |
| `min`         | `number` | Sets the minimum allowed value.                                                     |
| `max`         | `number` | Sets the maximum allowed value.                                                     |
| `step`        | `number` | Sets the stepping interval.                                                         |
| `unit`        | `string` | Text to display before the input as a unit (e.g., `"$"`, `"€"`). Purely decorative. |
| `unitEnd`     | `string` | Text to display after the input as a unit (e.g., `"kg"`, `"%"`). Purely decorative. |
| `value`       | `number` | If set, this becomes the default value of the input.                                |

***

## Examples

### Number input with range limits

```javascript
composer.numberInput("age", {
  question: "What is your age?",
  description: "Must be 18 or older to participate",
  min: 18,
  max: 120,
  required: true
});
```

Generates the following Markdown-like syntax:

```
age* = NumberInput(
  | question = What is your age?
  | description = Must be 18 or older to participate
  | min = 18
  | max = 120
)
```

### Number input with unit

```javascript
composer.numberInput("price", {
  question: "Enter the price",
  unit: "$",
  step: 0.01,
  min: 0,
  required: true
});
```

Generates the following Markdown-like syntax:

```
price* = NumberInput(
  | question = Enter the price
  | unit = $
  | step = 0.01
  | min = 0
)
```

### Styled number input with custom attributes

Add CSS classes and other HTML attributes using the `classNames` and `attrs` parameters. Please note, these class names and attributes are added to the `<div>` or `<fieldset>` container that contains the actual input field(s).

```javascript
composer.numberInput("quantity", {
  question: "Quantity",
  classNames: ["col-4", "xs:col-6"],
  attrs: [
    { name: "style", value: "font-size: 18px;" }
  ]
});
```

Generates the following Markdown-like syntax:

```
[.col-4 .xs:col-6 style="font-size: 18px;"]
quantity = NumberInput(
  | question = Quantity
)
```

Please [see the available CSS utility classes](/content/css-utility-classes).

### Conditional display

Conditionally show or hide a number input field using the `displayCondition` parameter. It works as follows:

* `dependencies` lists the fields to watch.
* `condition` is the expression that must be true to show the field. This must be a valid [Nunjucks](https://mozilla.github.io/nunjucks/) expression.

For instance, in the example below, the quantity field will only show up if the user wants to make a purchase.

```javascript
composer.choiceInput("wantToPurchase", {
  question: "Would you like to make a purchase?",
  required: true,
  choices: ["Yes", "No"]
})

composer.numberInput("quantity", {
  question: "How many would you like to purchase?",
  min: 1,
  displayCondition: {
    dependencies: ["wantToPurchase"],
    condition: "wantToPurchase == 'Yes'"
  }
});
```

Generates the following Markdown-like syntax:

```
wantToPurchase* = ChoiceInput(
  | question = Would you like to make a purchase?
  | choices = Yes, No
)

::: [{$ wantToPurchase $}]
{% if wantToPurchase == "Yes" %}
quantity = NumberInput(
  | question = How many would you like to purchase?
  | min = 1
)
{% endif %}
:::
```

## Notes

* The `unit` and `unitEnd` parameters are purely decorative. They have no effect on the actual value of the input sent during form submission.


# Select box

Create select boxes in your forms.

<figure><img src="/files/7D3dws7EqWbfDBEn7mGj" alt=""><figcaption><p>Select box</p></figcaption></figure>

Use the `selectBox()` function to create select boxes in your forms. It uses the HTML `<select>` element which provides a dropdown list of options.

***

## Basic usage

```javascript
import { Composer } from "formsmd";

const composer = new Composer({
  id: "my-form"
});

composer.selectBox("country", {
  question: "Which country are you from?",
  options: ["United States", "Canada", "United Kingdom"]
});
```

Generates the following Markdown-like syntax:

```
#! id = my-form

country = SelectBox(
  | question = Which country are you from?
  | options = United States, Canada, United Kingdom
)
```

### Required

Add the `required` parameter to make the field mandatory:

```javascript
composer.selectBox("country", {
  question: "Which country are you from?",
  options: ["United States", "Canada", "United Kingdom"],
  required: true
});
```

Generates the following Markdown-like syntax:

```
country* = SelectBox(
  | question = Which country are you from?
  | options = United States, Canada, United Kingdom
)
```

***

## Function overview

The following is the overview of the function:

```typescript
selectBox(name: string, params: object)
```

### Arguments

| Name     | Type     | Description                                                                                                                                                     |
| -------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`   | `string` | A unique name for your form field that you'll use to identify the user's response.<mark style="color:red;">\*</mark>                                            |
| `params` | `object` | An object containing all the configuration parameters for your select box field (see the [parameters section](#parameters) below for the full list of options). |

{% hint style="danger" %} <mark style="color:red;">\*</mark>Avoid values for the `name` argument which may be the names of HTML attributes, such as `"name"`, `"role"`, `"id"`, etc. This is because by default, the form's template string is first sanitized using [DOMPurify](https://github.com/cure53/DOMPurify), and these values may be removed to prevent DOM clobbering.
{% endhint %}

***

## Parameters

### Shared parameters

These parameters are common to all form fields:

| Name                  | Type                                            | Description                                                                                                                                                                                                                                                                             |
| --------------------- | ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `question` (required) | `string`                                        | The main question or label of the form field.                                                                                                                                                                                                                                           |
| `required`            | `true` (`boolean`)                              | When set, the field becomes required.                                                                                                                                                                                                                                                   |
| `description`         | `string`                                        | Any extra information that the user may need to fill out the form. Appears right below the question.                                                                                                                                                                                    |
| `fieldSize`           | `"sm"`                                          | When set to `"sm"`, the font sizes of the question, description, and answer are made smaller.                                                                                                                                                                                           |
| `labelStyle`          | `"classic"`                                     | When set to `"classic"`, the question and description of the form field are made smaller.                                                                                                                                                                                               |
| `subfield`            | `true` (`boolean`)                              | When set, the question and description of the form field are made smaller. Functionally the same as setting `labelStyle` to `"classic"`.                                                                                                                                                |
| `disabled`            | `true` (`boolean`)                              | When set, the input is disabled.                                                                                                                                                                                                                                                        |
| `autofocus`           | `true` (`boolean`)                              | When set, the input will be automatically focused when the parent slide becomes active, or immediately after page load.                                                                                                                                                                 |
| `id`                  | `string`                                        | The `id` attribute of the form field container.                                                                                                                                                                                                                                         |
| `classNames`          | `string[]`                                      | The CSS class names of the form field. [See the available CSS utility classes](/content/css-utility-classes).                                                                                                                                                                           |
| `attrs`               | `Array<{ name: string, value: string }>`        | Other HTML attributes of the form field. Each attribute has a `name` and `value` property.                                                                                                                                                                                              |
| `displayCondition`    | `{ dependencies: string[], condition: string }` | Controls when the field is shown. The `dependencies` lists the fields to watch, and `condition` is the expression that must be true to show the field. The `condition` must be a valid [Nunjucks](https://mozilla.github.io/nunjucks/) expression. [See example](#conditional-display). |

### Select box specific parameters

| Name                 | Type                                                 | Description                                                                                                                                                                                                                                                                       |
| -------------------- | ---------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `options` (required) | `Array<string \| { label: string, value?: string }>` | Array of options that can be either strings (e.g., `["Option 1", "Option 2"]`) or objects with a `label` for display text and an optional `value` (e.g., `[{ label: "Option 1", value: "opt1" }]`). When using objects, if `value` is not provided, `label` is used as the value. |
| `selected`           | `string`                                             | Pre-selected option value.                                                                                                                                                                                                                                                        |
| `placeholder`        | `string`                                             | Sets the placeholder option of the select.                                                                                                                                                                                                                                        |

***

## Examples

### Select box with value-label pairs

Value-label pairs allow different values to be stored than what's shown to users. The `label` appears in the dropdown for users to select, while the `value` is stored in the form data. This pattern is particularly useful for storing concise identifiers in a database while displaying more descriptive text in the interface.\
\
Please note, for `selected` to work with value-label pairs, it must contain the `value`, not the `label`.&#x20;

```javascript
composer.selectBox("experience", {
  question: "Years of experience",
  options: [
    { label: "Junior (0-2 years)", value: "junior" },
    { label: "Mid-level (3-5 years)", value: "mid" },
    { label: "Senior (6+ years)", value: "senior" }
  ],
  selected: "mid",
  required: true
});
```

Generates the following Markdown-like syntax:

```
experience* = SelectBox(
  | question = Years of experience
  | options = "junior" Junior (0-2 years), "mid" Mid-level (3-5 years), "senior" Senior (6+ years)
  | selected = mid
)
```

### Select box with custom placeholder

```javascript
composer.selectBox("language", {
  question: "What's your preferred programming language?",
  description: "Choose the language you're most comfortable with",
  placeholder: "Select a language",
  options: ["JavaScript", "Python", "Java", "C++"],
  required: true
});
```

Generates the following Markdown-like syntax:

```
language* = SelectBox(
  | question = What's your preferred programming language?
  | description = Choose the language you're most comfortable with
  | placeholder = Select a language
  | options = JavaScript, Python, Java, C++
)
```

### Styled select box with custom attributes

Add CSS classes and other HTML attributes using the `classNames` and `attrs` parameters. Please note, these class names and attributes are added to the `<div>` or `<fieldset>` container that contains the actual select field.

```javascript
composer.selectBox("jobRole", {
  question: "Select your role",
  options: ["Developer", "Designer", "Manager"],
  classNames: ["col-6", "xs:col-6"],
  attrs: [
    { name: "style", value: "font-size: 18px;" }
  ]
});
```

Generates the following Markdown-like syntax:

```
[.col-6 .xs:col-6 style="font-size: 18px;"]
jobRole = SelectBox(
  | question = Select your role
  | options = Developer, Designer, Manager
)
```

Please [see the available CSS utility classes](/content/css-utility-classes).

### Conditional display

Conditionally show or hide a select box using the `displayCondition` parameter. It works as follows:

* `dependencies` lists the fields to watch.
* `condition` is the expression that must be true to show the field. This must be a valid [Nunjucks](https://mozilla.github.io/nunjucks/) expression.

For instance, in the example below, the framework select will only show up if the user indicates they are a developer.

```javascript
composer.selectBox("jobTitle", {
  question: "What is your job title?",
  required: true,
  options: ["Developer", "Designer", "Manager"]
});

composer.selectBox("framework", {
  question: "Which framework do you primarily use?",
  options: ["React", "Vue", "Angular"],
  displayCondition: {
    dependencies: ["jobTitle"],
    condition: "jobTitle == 'Developer'"
  }
});
```

Generates the following Markdown-like syntax:

```
jobTitle* = SelectBox(
  | question = What is your job title?
  | options = Developer, Designer, Manager
)

::: [{$ jobTitle $}]
{% if jobTitle == "Developer" %}
framework = SelectBox(
  | question = Which framework do you primarily use?
  | options = React, Vue, Angular
)
{% endif %}
:::
```


# Choice input

Create choice inputs in your forms.

<figure><img src="/files/oBySOJx6txkcpweHM6Yn" alt=""><figcaption><p>Choice input</p></figcaption></figure>

Use the `choiceInput()` function to create choice inputs in your forms. It allows users to select one or more options from a list of choices.

***

## Basic usage

```javascript
import { Composer } from "formsmd";

const composer = new Composer({
  id: "my-form"
});

composer.choiceInput("interest", {
  question: "What is your interest?",
  choices: ["Programming", "Design", "Marketing"]
});
```

Generates the following Markdown-like syntax:

```
#! id = my-form

interest = ChoiceInput(
  | question = What is your interest?
  | choices = Programming, Design, Marketing
)
```

### Required

Add the `required` parameter to make the field mandatory:

```javascript
composer.choiceInput("interest", {
  question: "What is your interest?",
  choices: ["Programming", "Design", "Marketing"],
  required: true
});
```

Generates the following Markdown-like syntax:

```
interest* = ChoiceInput(
  | question = What is your interest?
  | choices = Programming, Design, Marketing
  | required
)
```

***

## Function overview

The following is the overview of the function:

```typescript
choiceInput(name: string, params: object)
```

### Arguments

| Name     | Type     | Description                                                                                                                                                       |
| -------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`   | `string` | A unique name for your form field that you'll use to identify the user's response.<mark style="color:red;">\*</mark>                                              |
| `params` | `object` | An object containing all the configuration parameters for your choice input field (see the [parameters section](#parameters) below for the full list of options). |

{% hint style="danger" %} <mark style="color:red;">\*</mark>Avoid values for the `name` argument which may be the names of HTML attributes, such as `"name"`, `"role"`, `"id"`, etc. This is because by default, the form's template string is first sanitized using [DOMPurify](https://github.com/cure53/DOMPurify), and these values may be removed to prevent DOM clobbering.
{% endhint %}

***

## Parameters

### Shared parameters

These parameters are common to all form fields:

| Name                  | Type                                            | Description                                                                                                                                                                                                                                                                             |
| --------------------- | ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `question` (required) | `string`                                        | The main question or label of the form field.                                                                                                                                                                                                                                           |
| `required`            | `true` (`boolean`)                              | When set, the field becomes required.                                                                                                                                                                                                                                                   |
| `description`         | `string`                                        | Any extra information that the user may need to fill out the form. Appears right below the question.                                                                                                                                                                                    |
| `fieldSize`           | `"sm"`                                          | When set to `"sm"`, the font sizes of the question, description, and answer are made smaller.                                                                                                                                                                                           |
| `labelStyle`          | `"classic"`                                     | When set to `"classic"`, the question and description of the form field are made smaller.                                                                                                                                                                                               |
| `subfield`            | `true` (`boolean`)                              | When set, the question and description of the form field are made smaller. Functionally the same as setting `labelStyle` to `"classic"`.                                                                                                                                                |
| `disabled`            | `true` (`boolean`)                              | When set, the input is disabled.                                                                                                                                                                                                                                                        |
| `autofocus`           | `true` (`boolean`)                              | When set, the input will be automatically focused when the parent slide becomes active, or immediately after page load.                                                                                                                                                                 |
| `id`                  | `string`                                        | The `id` attribute of the form field container.                                                                                                                                                                                                                                         |
| `classNames`          | `string[]`                                      | The CSS class names of the form field. [See the available CSS utility classes](/content/css-utility-classes).                                                                                                                                                                           |
| `attrs`               | `Array<{ name: string, value: string }>`        | Other HTML attributes of the form field. Each attribute has a `name` and `value` property.                                                                                                                                                                                              |
| `displayCondition`    | `{ dependencies: string[], condition: string }` | Controls when the field is shown. The `dependencies` lists the fields to watch, and `condition` is the expression that must be true to show the field. The `condition` must be a valid [Nunjucks](https://mozilla.github.io/nunjucks/) expression. [See example](#conditional-display). |

### Choice input specific parameters

| Name                 | Type                                                 | Description                                                                                                                                                                                                                                                                     |
| -------------------- | ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `choices` (required) | `Array<string \| { label: string, value?: string }>` | Array of choices that can be either strings (e.g., `["Choice 1", "Choice 2"]`) or objects with a `label` for display text and an optional `value` (e.g., `[{ label: "Choice 1", value: "c1" }]`). When using objects, if `value` is not provided, `label` is used as the value. |
| `multiple`           | `true` (`boolean`)                                   | Allow multiple selections.                                                                                                                                                                                                                                                      |
| `horizontal`         | `true` (`boolean`)                                   | Display choices horizontally.                                                                                                                                                                                                                                                   |
| `hideFormText`       | `true` (`boolean`)                                   | For multiple selections, when set, the form text **"Choose as many as you like"** is hidden.                                                                                                                                                                                    |
| `checked`            | `string[]`                                           | Array of pre-checked choice values.                                                                                                                                                                                                                                             |

***

## Examples

### Choice input with value-label pairs

Value-label pairs allow different values to be stored than what's shown to users. The `label` appears for users to select, while the `value` is stored in the form data. This pattern is particularly useful for storing concise identifiers in a database while displaying more descriptive text in the interface.\
\
Please note, for `checked` to work with value-label pairs, it must contain the `value`, not the `label`.

```javascript
composer.choiceInput("experience", {
  question: "Select levels you've completed",
  choices: [
    { label: "Beginner (0-1 years)", value: "beginner" },
    { label: "Intermediate (2-4 years)", value: "intermediate" },
    { label: "Advanced (5+ years)", value: "advanced" }
  ],
  checked: ["beginner", "intermediate"],
  multiple: true,
  required: true
});
```

Generates the following Markdown-like syntax:

```
experience* = ChoiceInput(
  | question = Select levels you've completed
  | choices = "beginner" Beginner (0-1 years), "intermediate" Intermediate (2-4 years), "advanced" Advanced (5+ years)
  | checked = begineer, intermediate
  | multiple
)
```

### Horizontal choice input

Create a horizontally aligned choice input using the `horizontal` parameter:

```javascript
composer.choiceInput("subscription", {
  question: "Choose your subscription plan",
  choices: ["Basic", "Pro", "Enterprise"],
  horizontal: true
});
```

Generates the following Markdown-like syntax:

```
subscription = ChoiceInput(
  | question = Choose your subscription plan
  | choices = Basic, Pro, Enterprise
  | horizontal
)
```

### Styled choice input with custom attributes

Add CSS classes and other HTML attributes using the `classNames` and `attrs` parameters:

```javascript
composer.choiceInput("preferences", {
  question: "Select your preferences",
  choices: ["Email notifications", "SMS alerts", "Push notifications"],
  multiple: true,
  classNames: ["col-6", "xs:col-6"],
  attrs: [
    { name: "style", value: "margin-top: 1rem;" }
  ]
});
```

Generates the following Markdown-like syntax:

```
[.col-6 .xs:col-6 style="margin-top: 1rem;"]
preferences = ChoiceInput(
  | question = Select your preferences
  | choices = Email notifications, SMS alerts, Push notifications
  | multiple
)
```

Please [see the available CSS utility classes](/content/css-utility-classes).

### Conditional display

Conditionally show or hide a choice input using the `displayCondition` parameter. It works as follows:

* `dependencies` lists the fields to watch.
* `condition` is the expression that must be true to show the field. This must be a valid [Nunjucks](https://mozilla.github.io/nunjucks/) expression.

For instance, in the example below, the programming languages choice will only show up if the user indicates they are a developer.

```javascript
composer.choiceInput("position", {
  question: "What is your position?",
  choices: ["Developer", "Designer", "Manager"],
  required: true
});

composer.choiceInput("languages", {
  question: "Which programming languages do you use?",
  choices: ["JavaScript", "Python", "Java", "C++"],
  multiple: true,
  displayCondition: {
    dependencies: ["position"],
    condition: "position == 'Developer'"
  }
});
```

Generates the following Markdown-like syntax:

```
position* = ChoiceInput(
  | question = What is your position?
  | choices = Developer, Designer, Manager
)

::: [{$ position $}]
{% if position == "Developer" %}
languages = ChoiceInput(
  | question = Which programming languages do you use?
  | choices = JavaScript, Python, Java, C++
  | multiple
)
{% endif %}
:::
```


# Picture choice

Create picture choice inputs in your forms.

<figure><img src="/files/ZDlxCEij8apFy4hAfUqM" alt=""><figcaption><p>Picture choice</p></figcaption></figure>

Use the `pictureChoice()` function to create picture choice inputs in your forms. It allows users to select one or more options from a list of choices with associated images.

***

## Basic usage

```javascript
import { Composer } from "formsmd";

const composer = new Composer({
  id: "my-form"
});

composer.pictureChoice("style", {
  question: "Choose your preferred style",
  choices: [
    { label: "Modern", value: "modern", image: "/styles/modern.jpg" },
    { label: "Classical", value: "classical", image: "/styles/classical.jpg" },
    { label: "Minimalist", value: "minimalist", image: "/styles/minimalist.jpg" }
  ]
});
```

Generates the following Markdown-like syntax:

```
#! id = my-form

style = PictureChoice(
  | question = Choose your preferred style
  | choices = "modern" Modern && /styles/modern.jpg, "classical" Classical && /styles/classical.jpg, "minimalist" Minimalist && /styles/minimalist.jpg
)
```

### Required

Add the `required` parameter to make the field mandatory:

```javascript
composer.pictureChoice("style", {
  question: "Choose your preferred style",
  choices: [
    { label: "Modern", value: "modern", image: "/styles/modern.jpg" },
    { label: "Classical", value: "classical", image: "/styles/classical.jpg" },
    { label: "Minimalist", value: "minimalist", image: "/styles/minimalist.jpg" }
  ],
  required: true
});
```

Generates the following Markdown-like syntax:

```
style* = PictureChoice(
  | question = Choose your preferred style
  | choices = "modern" Modern && /styles/modern.jpg, "classical" Classical && /styles/classical.jpg, "minimalist" Minimalist && /styles/minimalist.jpg
  | required
)
```

***

## Function overview

The following is the overview of the function:

```typescript
pictureChoice(name: string, params: object)
```

### Arguments

| Name     | Type     | Description                                                                                                                                                         |
| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`   | `string` | A unique name for your form field that you'll use to identify the user's response.<mark style="color:red;">\*</mark>                                                |
| `params` | `object` | An object containing all the configuration parameters for your picture choice field (see the [parameters section](#parameters) below for the full list of options). |

{% hint style="danger" %} <mark style="color:red;">\*</mark>Avoid values for the `name` argument which may be the names of HTML attributes, such as `"name"`, `"role"`, `"id"`, etc. This is because by default, the form's template string is first sanitized using [DOMPurify](https://github.com/cure53/DOMPurify), and these values may be removed to prevent DOM clobbering.
{% endhint %}

***

## Parameters

### Shared parameters

These parameters are common to all form fields:

| Name                  | Type                                            | Description                                                                                                                                                                                                                                                                             |
| --------------------- | ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `question` (required) | `string`                                        | The main question or label of the form field.                                                                                                                                                                                                                                           |
| `required`            | `true` (`boolean`)                              | When set, the field becomes required.                                                                                                                                                                                                                                                   |
| `description`         | `string`                                        | Any extra information that the user may need to fill out the form. Appears right below the question.                                                                                                                                                                                    |
| `fieldSize`           | `"sm"`                                          | When set to `"sm"`, the font sizes of the question, description, and answer are made smaller.                                                                                                                                                                                           |
| `labelStyle`          | `"classic"`                                     | When set to `"classic"`, the question and description of the form field are made smaller.                                                                                                                                                                                               |
| `subfield`            | `true` (`boolean`)                              | When set, the question and description of the form field are made smaller. Functionally the same as setting `labelStyle` to `"classic"`.                                                                                                                                                |
| `disabled`            | `true` (`boolean`)                              | When set, the input is disabled.                                                                                                                                                                                                                                                        |
| `autofocus`           | `true` (`boolean`)                              | When set, the input will be automatically focused when the parent slide becomes active, or immediately after page load.                                                                                                                                                                 |
| `id`                  | `string`                                        | The `id` attribute of the form field container.                                                                                                                                                                                                                                         |
| `classNames`          | `string[]`                                      | The CSS class names of the form field. [See the available CSS utility classes](/content/css-utility-classes).                                                                                                                                                                           |
| `attrs`               | `Array<{ name: string, value: string }>`        | Other HTML attributes of the form field. Each attribute has a `name` and `value` property.                                                                                                                                                                                              |
| `displayCondition`    | `{ dependencies: string[], condition: string }` | Controls when the field is shown. The `dependencies` lists the fields to watch, and `condition` is the expression that must be true to show the field. The `condition` must be a valid [Nunjucks](https://mozilla.github.io/nunjucks/) expression. [See example](#conditional-display). |

### Picture choice specific parameters

| Name                 | Type                                                      | Description                                                                                                                                                                                        |
| -------------------- | --------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `choices` (required) | `Array<{ label: string, value?: string, image: string }>` | Array of choices that must include a `label` for display text, an optional `value` that's stored in the form data (if not provided, `label` is used as the value), and an `image` URL for display. |
| `multiple`           | `true` (`boolean`)                                        | Allow multiple selections.                                                                                                                                                                         |
| `supersize`          | `true` (`boolean`)                                        | Make the pictures larger.                                                                                                                                                                          |
| `hideLabels`         | `true` (`boolean`)                                        | Hide the text labels.                                                                                                                                                                              |
| `hideFormText`       | `true` (`boolean`)                                        | For multiple selections, when set, the form text **"Choose as many as you like"** is hidden.                                                                                                       |
| `checked`            | `string[]`                                                | Array of pre-checked choice values.                                                                                                                                                                |

***

## Examples

### Picture choice with value-label pairs and image URLs

Value-label pairs allow different values to be stored than what's shown to users. The `label` appears for users to select, while the `value` is stored in the form data. Each choice must also include an `image` URL. Please note, for `checked` to work with value-label pairs, it must contain the `value`, not the `label`.

```javascript
composer.pictureChoice("theme", {
  question: "Select your preferred theme",
  choices: [
    { 
      label: "Light and Airy",
      value: "light",
      image: "https://example.com/themes/light.jpg"
    },
    { 
      label: "Dark and Moody",
      value: "dark",
      image: "https://example.com/themes/dark.jpg"
    },
    { 
      label: "Bold and Colorful",
      value: "colorful",
      image: "https://example.com/themes/colorful.jpg"
    }
  ],
  checked: ["light"],
  multiple: true,
  required: true
});
```

Generates the following Markdown-like syntax:

```
theme* = PictureChoice(
  | question = Select your preferred theme
  | choices = "light" Light and Airy && https://example.com/themes/light.jpg, "dark" Dark and Moody && https://example.com/themes/dark.jpg, "colorful" Bold and Colorful && https://example.com/themes/colorful.jpg
  | checked = light
  | multiple
  | required
)
```

### Supersized picture choice with hidden labels

Create a picture choice with larger images and hidden text labels:

```javascript
composer.pictureChoice("avatar", {
  question: "Choose your avatar",
  choices: [
    { label: "Warrior", image: "/avatars/warrior.jpg" },
    { label: "Mage", image: "/avatars/mage.jpg" },
    { label: "Archer", image: "/avatars/archer.jpg" }
  ],
  supersize: true,
  hideLabels: true
});
```

Generates the following Markdown-like syntax:

```
avatar = PictureChoice(
  | question = Choose your avatar
  | choices = Warrior && /avatars/warrior.jpg, Mage && /avatars/mage.jpg, Archer && /avatars/archer.jpg
  | supersize
  | hidelabels
)
```

### Styled picture choice with custom attributes

Add CSS classes and other HTML attributes using the `classNames` and `attrs` parameters:

```javascript
composer.pictureChoice("layout", {
  question: "Pick your preferred layout",
  choices: [
    { label: "Grid", image: "/layouts/grid.jpg" },
    { label: "List", image: "/layouts/list.jpg" },
    { label: "Masonry", image: "/layouts/masonry.jpg" }
  ],
  classNames: ["col-6", "xs:col-6"],
  attrs: [
    { name: "style", value: "margin-top: 1rem;" }
  ]
});
```

Generates the following Markdown-like syntax:

```
[.col-6 .xs:col-6 style="margin-top: 1rem;"]
layout = PictureChoice(
  | question = Pick your preferred layout
  | choices = Grid && /layouts/grid.jpg, List && /layouts/list.jpg, Masonry && /layouts/masonry.jpg
)
```

Please [see the available CSS utility classes](/content/css-utility-classes).

### Conditional display

Conditionally show or hide a picture choice using the `displayCondition` parameter. It works as follows:

* `dependencies` lists the fields to watch.
* `condition` is the expression that must be true to show the field. This must be a valid [Nunjucks](https://mozilla.github.io/nunjucks/) expression.

For instance, in the example below, the room style choices will only show up if the user indicates they are interested in interior design.

```javascript
composer.choiceInput("interest", {
  question: "What is your interest?",
  choices: ["Interior Design", "Photography", "Cooking"],
  required: true
});

composer.pictureChoice("roomStyle", {
  question: "Which room style appeals to you most?",
  choices: [
    { label: "Contemporary", image: "/rooms/contemporary.jpg" },
    { label: "Traditional", image: "/rooms/traditional.jpg" },
    { label: "Industrial", image: "/rooms/industrial.jpg" }
  ],
  displayCondition: {
    dependencies: ["interest"],
    condition: "interest == 'Interior Design'"
  }
});
```

Generates the following Markdown-like syntax:

```
interest* = ChoiceInput(
  | question = What is your interest?
  | choices = Interior Design, Photography, Cooking
)

::: [{$ interest $}]
{% if interest == "Interior Design" %}
roomStyle = PictureChoice(
  | question = Which room style appeals to you most?
  | choices = Contemporary && /rooms/contemporary.jpg, Traditional && /rooms/traditional.jpg, Industrial && /rooms/industrial.jpg
)
{% endif %}
:::
```


# Rating input

Create rating inputs in your forms.

<figure><img src="/files/GJsVEHImRCqroYeMF1yF" alt=""><figcaption><p>Rating input</p></figcaption></figure>

Use the `ratingInput()` function to create rating inputs in your forms. It allows users to select a rating value using star or heart icons.

***

## Basic usage

```javascript
import { Composer } from "formsmd";

const composer = new Composer({
  id: "my-form"
});

composer.ratingInput("rating", {
  question: "How would you rate your experience?"
});
```

Generates the following Markdown-like syntax:

```
#! id = my-form

rating = RatingInput(
  | question = How would you rate your experience?
)
```

### Required

Add the `required` parameter to make the field mandatory:

```javascript
composer.ratingInput("rating", {
  question: "How would you rate your experience?",
  required: true
});
```

Generates the following Markdown-like syntax:

```
rating* = RatingInput(
  | question = How would you rate your experience?
)
```

***

## Function overview

The following is the overview of the function:

```typescript
ratingInput(name: string, params: object)
```

### Arguments

| Name     | Type     | Description                                                                                                                                                       |
| -------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`   | `string` | A unique name for your form field that you'll use to identify the user's response.<mark style="color:red;">\*</mark>                                              |
| `params` | `object` | An object containing all the configuration parameters for your rating input field (see the [parameters section](#parameters) below for the full list of options). |

{% hint style="danger" %} <mark style="color:red;">\*</mark>Avoid values for the `name` argument which may be the names of HTML attributes, such as `"name"`, `"role"`, `"id"`, etc. This is because by default, the form's template string is first sanitized using [DOMPurify](https://github.com/cure53/DOMPurify), and these values may be removed to prevent DOM clobbering.
{% endhint %}

***

## Parameters

### Shared parameters

These parameters are common to all form fields:

| Name                  | Type                                            | Description                                                                                                                                                                                                                                                                             |
| --------------------- | ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `question` (required) | `string`                                        | The main question or label of the form field.                                                                                                                                                                                                                                           |
| `required`            | `true` (`boolean`)                              | When set, the field becomes required.                                                                                                                                                                                                                                                   |
| `description`         | `string`                                        | Any extra information that the user may need to fill out the form. Appears right below the question.                                                                                                                                                                                    |
| `fieldSize`           | `"sm"`                                          | When set to `"sm"`, the font sizes of the question, description, and answer are made smaller.                                                                                                                                                                                           |
| `labelStyle`          | `"classic"`                                     | When set to `"classic"`, the question and description of the form field are made smaller.                                                                                                                                                                                               |
| `subfield`            | `true` (`boolean`)                              | When set, the question and description of the form field are made smaller. Functionally the same as setting `labelStyle` to `"classic"`.                                                                                                                                                |
| `disabled`            | `true` (`boolean`)                              | When set, the input is disabled.                                                                                                                                                                                                                                                        |
| `autofocus`           | `true` (`boolean`)                              | When set, the input will be automatically focused when the parent slide becomes active, or immediately after page load.                                                                                                                                                                 |
| `id`                  | `string`                                        | The `id` attribute of the form field container.                                                                                                                                                                                                                                         |
| `classNames`          | `string[]`                                      | The CSS class names of the form field. [See the available CSS utility classes](/content/css-utility-classes).                                                                                                                                                                           |
| `attrs`               | `Array<{ name: string, value: string }>`        | Other HTML attributes of the form field. Each attribute has a `name` and `value` property.                                                                                                                                                                                              |
| `displayCondition`    | `{ dependencies: string[], condition: string }` | Controls when the field is shown. The `dependencies` lists the fields to watch, and `condition` is the expression that must be true to show the field. The `condition` must be a valid [Nunjucks](https://mozilla.github.io/nunjucks/) expression. [See example](#conditional-display). |

### Rating input specific parameters

| Name         | Type                                | Description                                       |
| ------------ | ----------------------------------- | ------------------------------------------------- |
| `outOf`      | `number`                            | Number of rating options (1-10). Defaults to `5`. |
| `icon`       | `"star"` \| `"heart"` \| `"hearts"` | Icon to use for rating. Defaults to `"star"`.     |
| `value`      | `number`                            | Pre-selected rating value.                        |
| `hideLabels` | `true` (`boolean`)                  | Whether to hide the numeric labels.               |

***

## Examples

### Rating input out of 10

```javascript
composer.ratingInput("satisfaction", {
  question: "How satisfied are you with our service?",
  description: "Please rate your overall satisfaction level",
  outOf: 10,
  icon: "star",
  required: true
});
```

Generates the following Markdown-like syntax:

```
satisfaction* = RatingInput(
  | question = How satisfied are you with our service?
  | description = Please rate your overall satisfaction level
  | outOf = 10
  | icon = star
)
```

### Rating input with hearts and hidden labels

```javascript
composer.ratingInput("experience", {
  question: "Rate your experience",
  icon: "hearts",
  hideLabels: true,
  outOf: 5
});
```

Generates the following Markdown-like syntax:

```
experience = RatingInput(
  | question = Rate your experience
  | icon = hearts
  | hideLabels
  | outOf = 5
)
```

### Styled rating input with custom attributes

Add CSS classes and other HTML attributes using the `classNames` and `attrs` parameters. Please note, these class names and attributes are added to the `<div>` or `<fieldset>` container that contains the actual input field(s).

```javascript
composer.ratingInput("userRating", {
  question: "Rate this content",
  classNames: ["col-6", "xs:col-6"],
  attrs: [
    { name: "style", value: "font-size: 18px;" }
  ]
});
```

Generates the following Markdown-like syntax:

```
[.col-6 .xs:col-6 style="font-size: 18px;"]
userRating = RatingInput(
  | question = Rate this content
)
```

Please [see the available CSS utility classes](/content/css-utility-classes).

### Conditional display

Conditionally show or hide a rating input field using the `displayCondition` parameter. It works as follows:

* `dependencies` lists the fields to watch.
* `condition` is the expression that must be true to show the field. This must be a valid [Nunjucks](https://mozilla.github.io/nunjucks/) expression.

For instance, in the example below, the detailed rating will only show up if the user indicates they want to provide one.

```javascript
composer.choiceInput("wantToRate", {
  question: "Would you like to rate our service?",
  required: true,
  choices: ["Yes", "No"]
})

composer.ratingInput("serviceRating", {
  question: "Rate our service",
  displayCondition: {
    dependencies: ["wantToRate"],
    condition: "wantToRate == 'Yes'"
  }
});
```

Generates the following Markdown-like syntax:

```
wantToRate* = ChoiceInput(
  | question = Would you like to rate our service?
  | choices = Yes, No
)

::: [{$ wantToRate $}]
{% if wantToRate == "Yes" %}
serviceRating = RatingInput(
  | question = Rate our service
)
{% endif %}
:::
```


# Opinion scale / Net Promoter Score®

Create opinion scale inputs in your forms.

<figure><img src="/files/iTo6SqQOcA9iQMryWFZq" alt=""><figcaption><p>Opinion scale</p></figcaption></figure>

Use the `opinionScale()` function to create opinion scale inputs in your forms. It allows users to provide ratings or opinions on a numeric scale with optional labels at the start and end points. When using the default parameter values, the opinion scale is a [Net Promoter Score®](https://en.wikipedia.org/wiki/Net_promoter_score).

***

## Basic usage

```javascript
import { Composer } from "formsmd";

const composer = new Composer({
  id: "my-form"
});

composer.opinionScale("agreement", {
  question: "How much do you agree with this statement?"
});
```

Generates the following Markdown-like syntax:

```
#! id = my-form

agreement = OpinionScale(
  | question = How much do you agree with this statement?
)
```

### Required

Add the `required` parameter to make the field mandatory:

```javascript
composer.opinionScale("agreement", {
  question: "How much do you agree with this statement?",
  required: true
});
```

Generates the following Markdown-like syntax:

```
agreement* = OpinionScale(
  | question = How much do you agree with this statement?
)
```

***

## Function overview

The following is the overview of the function:

```typescript
opinionScale(name: string, params: object)
```

### Arguments

| Name     | Type     | Description                                                                                                                                                        |
| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `name`   | `string` | A unique name for your form field that you'll use to identify the user's response.<mark style="color:red;">\*</mark>                                               |
| `params` | `object` | An object containing all the configuration parameters for your opinion scale field (see the [parameters section](#parameters) below for the full list of options). |

{% hint style="danger" %} <mark style="color:red;">\*</mark>Avoid values for the `name` argument which may be the names of HTML attributes, such as `"name"`, `"role"`, `"id"`, etc. This is because by default, the form's template string is first sanitized using [DOMPurify](https://github.com/cure53/DOMPurify), and these values may be removed to prevent DOM clobbering.
{% endhint %}

***

## Parameters

### Shared parameters

These parameters are common to all form fields:

| Name                  | Type                                            | Description                                                                                                                                                                                                                                                                             |
| --------------------- | ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `question` (required) | `string`                                        | The main question or label of the form field.                                                                                                                                                                                                                                           |
| `required`            | `true` (`boolean`)                              | When set, the field becomes required.                                                                                                                                                                                                                                                   |
| `description`         | `string`                                        | Any extra information that the user may need to fill out the form. Appears right below the question.                                                                                                                                                                                    |
| `fieldSize`           | `"sm"`                                          | When set to `"sm"`, the font sizes of the question, description, and answer are made smaller.                                                                                                                                                                                           |
| `labelStyle`          | `"classic"`                                     | When set to `"classic"`, the question and description of the form field are made smaller.                                                                                                                                                                                               |
| `subfield`            | `true` (`boolean`)                              | When set, the question and description of the form field are made smaller. Functionally the same as setting `labelStyle` to `"classic"`.                                                                                                                                                |
| `disabled`            | `true` (`boolean`)                              | When set, the input is disabled.                                                                                                                                                                                                                                                        |
| `autofocus`           | `true` (`boolean`)                              | When set, the input will be automatically focused when the parent slide becomes active, or immediately after page load.                                                                                                                                                                 |
| `id`                  | `string`                                        | The `id` attribute of the form field container.                                                                                                                                                                                                                                         |
| `classNames`          | `string[]`                                      | The CSS class names of the form field. [See the available CSS utility classes](/content/css-utility-classes).                                                                                                                                                                           |
| `attrs`               | `Array<{ name: string, value: string }>`        | Other HTML attributes of the form field. Each attribute has a `name` and `value` property.                                                                                                                                                                                              |
| `displayCondition`    | `{ dependencies: string[], condition: string }` | Controls when the field is shown. The `dependencies` lists the fields to watch, and `condition` is the expression that must be true to show the field. The `condition` must be a valid [Nunjucks](https://mozilla.github.io/nunjucks/) expression. [See example](#conditional-display). |

### Opinion scale specific parameters

| Name             | Type               | Description                                    |
| ---------------- | ------------------ | ---------------------------------------------- |
| `startAt`        | `number`           | Starting number (`0` or `1`). Defaults to `0`. |
| `outOf`          | `number`           | Maximum scale value (5-10). Defaults to `10`.  |
| `labelStart`     | `string`           | Label for the start of the scale.              |
| `labelEnd`       | `string`           | Label for the end of the scale.                |
| `hideLabelStart` | `true` (`boolean`) | Whether to hide the start label.               |
| `hideLabelEnd`   | `true` (`boolean`) | Whether to hide the end label.                 |
| `value`          | `number`           | Pre-selected value.                            |

***

## Examples

### Opinion scale with custom range and labels

```javascript
composer.opinionScale("satisfaction", {
  question: "How likely are you to recommend our product?",
  description: "0 means not likely, 5 means very likely",
  startAt: 0,
  outOf: 5,
  labelStart: "Not likely",
  labelEnd: "Very likely",
  required: true
});
```

Generates the following Markdown-like syntax:

```
satisfaction* = OpinionScale(
  | question = How likely are you to recommend our product?
  | description = 0 means not likely, 5 means very likely
  | startAt = 0
  | outOf = 5
  | labelStart = Not likely
  | labelEnd = Very likely
)
```

### Opinion scale with hidden labels

```javascript
composer.opinionScale("rating", {
  question: "Rate your experience",
  outOf: 5,
  startAt: 1,
  hideLabelStart: true,
  hideLabelEnd: true
});
```

Generates the following Markdown-like syntax:

```
rating = OpinionScale(
  | question = Rate your experience
  | outOf = 5
  | startAt = 1
  | hideLabelStart
  | hideLabelEnd
)
```

### Styled opinion scale with custom attributes

Add CSS classes and other HTML attributes using the `classNames` and `attrs` parameters. Please note, these class names and attributes are added to the `<div>` or `<fieldset>` container that contains the actual input field(s).

```javascript
composer.opinionScale("feedback", {
  question: "Rate this content",
  classNames: ["col-6", "xs:col-6"],
  attrs: [
    { name: "style", value: "font-size: 18px;" }
  ]
});
```

Generates the following Markdown-like syntax:

```
[.col-6 .xs:col-6 style="font-size: 18px;"]
feedback = OpinionScale(
  | question = Rate this content
)
```

Please [see the available CSS utility classes](/content/css-utility-classes).

### Conditional display

Conditionally show or hide an opinion scale field using the `displayCondition` parameter. It works as follows:

* `dependencies` lists the fields to watch.
* `condition` is the expression that must be true to show the field. This must be a valid [Nunjucks](https://mozilla.github.io/nunjucks/) expression.

For instance, in the example below, the detailed scale will only show up if the user indicates they want to provide feedback.

```javascript
composer.choiceInput("wantFeedback", {
  question: "Would you like to provide detailed feedback?",
  required: true,
  choices: ["Yes", "No"]
})

composer.opinionScale("detailedFeedback", {
  question: "Rate your overall satisfaction",
  displayCondition: {
    dependencies: ["wantFeedback"],
    condition: "wantFeedback == 'Yes'"
  }
});
```

Generates the following Markdown-like syntax:

```
wantFeedback* = ChoiceInput(
  | question = Would you like to provide detailed feedback?
  | choices = Yes, No
)

::: [{$ wantFeedback $}]
{% if wantFeedback == "Yes" %}
detailedFeedback = OpinionScale(
  | question = Rate your overall satisfaction
)
{% endif %}
:::
```


# Datetime input

Create datetime inputs in your forms.

<figure><img src="/files/lfL3aTjavXkJs5Ns169o" alt=""><figcaption><p>Datetime input</p></figcaption></figure>

Use the `datetimeInput()` function to create datetime inputs in your forms. It uses the HTML `<input type="datetime-local">` element which provides a built-in datetime picker.

***

## Basic usage

```javascript
import { Composer } from "formsmd";

const composer = new Composer({
  id: "my-form"
});

composer.datetimeInput("appointment", {
  question: "When would you like to schedule your appointment?"
});
```

Generates the following Markdown-like syntax:

```
#! id = my-form

appointment = DatetimeInput(
  | question = When would you like to schedule your appointment?
)
```

### Required

Add the `required` parameter to make the field mandatory:

```javascript
composer.datetimeInput("appointment", {
  question: "When would you like to schedule your appointment?",
  required: true
});
```

Generates the following Markdown-like syntax:

```
appointment* = DatetimeInput(
  | question = When would you like to schedule your appointment?
)
```

***

## Function overview

The following is the overview of the function:

```typescript
datetimeInput(name: string, params: object)
```

### Arguments

| Name     | Type     | Description                                                                                                                                                         |
| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`   | `string` | A unique name for your form field that you'll use to identify the user's response.<mark style="color:red;">\*</mark>                                                |
| `params` | `object` | An object containing all the configuration parameters for your datetime input field (see the [parameters section](#parameters) below for the full list of options). |

{% hint style="danger" %} <mark style="color:red;">\*</mark>Avoid values for the `name` argument which may be the names of HTML attributes, such as `"name"`, `"role"`, `"id"`, etc. This is because by default, the form's template string is first sanitized using [DOMPurify](https://github.com/cure53/DOMPurify), and these values may be removed to prevent DOM clobbering.
{% endhint %}

***

## Parameters

### Shared parameters

These parameters are common to all form fields:

| Name                  | Type                                            | Description                                                                                                                                                                                                                                                                             |
| --------------------- | ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `question` (required) | `string`                                        | The main question or label of the form field.                                                                                                                                                                                                                                           |
| `required`            | `true` (`boolean`)                              | When set, the field becomes required.                                                                                                                                                                                                                                                   |
| `description`         | `string`                                        | Any extra information that the user may need to fill out the form. Appears right below the question.                                                                                                                                                                                    |
| `fieldSize`           | `"sm"`                                          | When set to `"sm"`, the font sizes of the question, description, and answer are made smaller.                                                                                                                                                                                           |
| `labelStyle`          | `"classic"`                                     | When set to `"classic"`, the question and description of the form field are made smaller.                                                                                                                                                                                               |
| `subfield`            | `true` (`boolean`)                              | When set, the question and description of the form field are made smaller. Functionally the same as setting `labelStyle` to `"classic"`.                                                                                                                                                |
| `disabled`            | `true` (`boolean`)                              | When set, the input is disabled.                                                                                                                                                                                                                                                        |
| `autofocus`           | `true` (`boolean`)                              | When set, the input will be automatically focused when the parent slide becomes active, or immediately after page load.                                                                                                                                                                 |
| `id`                  | `string`                                        | The `id` attribute of the form field container.                                                                                                                                                                                                                                         |
| `classNames`          | `string[]`                                      | The CSS class names of the form field. [See the available CSS utility classes](/content/css-utility-classes).                                                                                                                                                                           |
| `attrs`               | `Array<{ name: string, value: string }>`        | Other HTML attributes of the form field. Each attribute has a `name` and `value` property.                                                                                                                                                                                              |
| `displayCondition`    | `{ dependencies: string[], condition: string }` | Controls when the field is shown. The `dependencies` lists the fields to watch, and `condition` is the expression that must be true to show the field. The `condition` must be a valid [Nunjucks](https://mozilla.github.io/nunjucks/) expression. [See example](#conditional-display). |

### Datetime input specific parameters

| Name          | Type     | Description                                                                                      |
| ------------- | -------- | ------------------------------------------------------------------------------------------------ |
| `placeholder` | `string` | Sets the `placeholder` attribute of the input.                                                   |
| `min`         | `string` | Sets the minimum allowed datetime value. Must be in the format `"YYYY-MM-DDTHH:mm"`.             |
| `max`         | `string` | Sets the maximum allowed datetime value. Must be in the format `"YYYY-MM-DDTHH:mm"`.             |
| `step`        | `string` | Sets the stepping interval.                                                                      |
| `value`       | `string` | If set, this becomes the default value of the input. Must be in the format `"YYYY-MM-DDTHH:mm"`. |

***

## Examples

### Datetime input with min and max values

```javascript
composer.datetimeInput("meetingTime", {
  question: "When would you like to schedule the meeting?",
  description: "Please choose a time between 9 AM and 5 PM next week",
  min: "2024-01-15T09:00",
  max: "2024-01-19T17:00",
  required: true
});
```

Generates the following Markdown-like syntax:

```
meetingTime* = DatetimeInput(
  | question = When would you like to schedule the meeting?
  | description = Please choose a time between 9 AM and 5 PM next week
  | min = 2024-01-15T09:00
  | max = 2024-01-19T17:00
)
```

### Datetime input with custom step interval

```javascript
composer.datetimeInput("appointmentTime", {
  question: "Select your preferred appointment time",
  description: "Appointments are available in 30-minute slots",
  step: "1800",
  required: true
});
```

Generates the following Markdown-like syntax:

```
appointmentTime* = DatetimeInput(
  | question = Select your preferred appointment time
  | description = Appointments are available in 30-minute slots
  | step = 1800
)
```

### Styled datetime input with custom attributes

Add CSS classes and other HTML attributes using the `classNames` and `attrs` parameters. Please note, these class names and attributes are added to the `<div>` or `<fieldset>` container that contains the actual input field(s).

```javascript
composer.datetimeInput("eventDateTime", {
  question: "Event date and time",
  classNames: ["col-6", "xs:col-6"],
  attrs: [
    { name: "style", value: "font-size: 18px;" }
  ]
});
```

Generates the following Markdown-like syntax:

```
[.col-6 .xs:col-6 style="font-size: 18px;"]
eventDateTime = DatetimeInput(
  | question = Event date and time
)
```

Please [see the available CSS utility classes](/content/css-utility-classes).

### Conditional display

Conditionally show or hide a datetime input field using the `displayCondition` parameter. It works as follows:

* `dependencies` lists the fields to watch.
* `condition` is the expression that must be true to show the field. This must be a valid [Nunjucks](https://mozilla.github.io/nunjucks/) expression.

For instance, in the example below, the return flight datetime input will only show up if the user selects a round trip.

```javascript
composer.choiceInput("tripType", {
  question: "What type of trip would you like to book?",
  required: true,
  choices: ["One way", "Round trip"]
})

composer.datetimeInput("returnFlight", {
  question: "Return flight date and time",
  displayCondition: {
    dependencies: ["tripType"],
    condition: "tripType == 'Round trip'"
  }
});
```

Generates the following Markdown-like syntax:

```
tripType* = ChoiceInput(
  | question = What type of trip would you like to book?
  | choices = One way, Round trip
)

::: [{$ tripType $}]
{% if tripType == "Round trip" %}
returnFlight = DatetimeInput(
  | question = Return flight date and time
)
{% endif %}
:::
```

## Notes

* During form submission, the user's local timezone will get added to the end of the datetime input value, for example: `2024-06-01T08:30+06:00`.


# Date input

Create date inputs in your forms.

<figure><img src="/files/xDnAXNiVnrxXT9YaV2Xg" alt=""><figcaption><p>Date input</p></figcaption></figure>

Use the `dateInput()` function to create date inputs in your forms. It uses the HTML `<input type="date">` element which provides built-in date selection and validation.

***

## Basic usage

```javascript
import { Composer } from "formsmd";

const composer = new Composer({
  id: "my-form"
});

composer.dateInput("birthdate", {
  question: "What is your birth date?"
});
```

Generates the following Markdown-like syntax:

```
#! id = my-form

birthdate = DateInput(
  | question = What is your birth date?
)
```

### Required

Add the `required` parameter to make the field mandatory:

```javascript
composer.dateInput("birthdate", {
  question: "What is your birth date?",
  required: true
});
```

Generates the following Markdown-like syntax:

```
birthdate* = DateInput(
  | question = What is your birth date?
)
```

***

## Function overview

The following is the overview of the function:

```typescript
dateInput(name: string, params: object)
```

### Arguments

| Name     | Type     | Description                                                                                                                                                     |
| -------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`   | `string` | A unique name for your form field that you'll use to identify the user's response.<mark style="color:red;">\*</mark>                                            |
| `params` | `object` | An object containing all the configuration parameters for your date input field (see the [parameters section](#parameters) below for the full list of options). |

{% hint style="danger" %} <mark style="color:red;">\*</mark>Avoid values for the `name` argument which may be the names of HTML attributes, such as `"name"`, `"role"`, `"id"`, etc. This is because by default, the form's template string is first sanitized using [DOMPurify](https://github.com/cure53/DOMPurify), and these values may be removed to prevent DOM clobbering.
{% endhint %}

***

## Parameters

### Shared parameters

These parameters are common to all form fields:

| Name                  | Type                                            | Description                                                                                                                                                                                                                                                                             |
| --------------------- | ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `question` (required) | `string`                                        | The main question or label of the form field.                                                                                                                                                                                                                                           |
| `required`            | `true` (`boolean`)                              | When set, the field becomes required.                                                                                                                                                                                                                                                   |
| `description`         | `string`                                        | Any extra information that the user may need to fill out the form. Appears right below the question.                                                                                                                                                                                    |
| `fieldSize`           | `"sm"`                                          | When set to `"sm"`, the font sizes of the question, description, and answer are made smaller.                                                                                                                                                                                           |
| `labelStyle`          | `"classic"`                                     | When set to `"classic"`, the question and description of the form field are made smaller.                                                                                                                                                                                               |
| `subfield`            | `true` (`boolean`)                              | When set, the question and description of the form field are made smaller. Functionally the same as setting `labelStyle` to `"classic"`.                                                                                                                                                |
| `disabled`            | `true` (`boolean`)                              | When set, the input is disabled.                                                                                                                                                                                                                                                        |
| `autofocus`           | `true` (`boolean`)                              | When set, the input will be automatically focused when the parent slide becomes active, or immediately after page load.                                                                                                                                                                 |
| `id`                  | `string`                                        | The `id` attribute of the form field container.                                                                                                                                                                                                                                         |
| `classNames`          | `string[]`                                      | The CSS class names of the form field. [See the available CSS utility classes](/content/css-utility-classes).                                                                                                                                                                           |
| `attrs`               | `Array<{ name: string, value: string }>`        | Other HTML attributes of the form field. Each attribute has a `name` and `value` property.                                                                                                                                                                                              |
| `displayCondition`    | `{ dependencies: string[], condition: string }` | Controls when the field is shown. The `dependencies` lists the fields to watch, and `condition` is the expression that must be true to show the field. The `condition` must be a valid [Nunjucks](https://mozilla.github.io/nunjucks/) expression. [See example](#conditional-display). |

### Date input specific parameters

| Name          | Type     | Description                                           |
| ------------- | -------- | ----------------------------------------------------- |
| `placeholder` | `string` | Sets the `placeholder` attribute of the input.        |
| `min`         | `string` | Sets the minimum allowed date value (`"YYYY-MM-DD"`). |
| `max`         | `string` | Sets the maximum allowed date value (`"YYYY-MM-DD"`). |
| `step`        | `string` | Sets the stepping interval.                           |
| `value`       | `string` | Pre-selected date value (`"YYYY-MM-DD"`).             |

***

## Examples

### Date input with validation

```javascript
composer.dateInput("appointmentDate", {
  question: "When would you like to schedule your appointment?",
  description: "Please select a date within the next 30 days",
  min: "2024-01-12",
  max: "2024-02-12",
  required: true
});
```

Generates the following Markdown-like syntax:

```
appointmentDate* = DateInput(
  | question = When would you like to schedule your appointment?
  | description = Please select a date within the next 30 days
  | min = 2024-01-12
  | max = 2024-02-12
)
```

### Date input with default value

```javascript
composer.dateInput("startDate", {
  question: "Start date",
  description: "When would you like to begin?",
  value: "2024-01-12"
});
```

Generates the following Markdown-like syntax:

```
startDate = DateInput(
  | question = Start date
  | description = When would you like to begin?
  | value = 2024-01-12
)
```

### Styled date input with custom attributes

Add CSS classes and other HTML attributes using the `classNames` and `attrs` parameters. Please note, these class names and attributes are added to the `<div>` or `<fieldset>` container that contains the actual input field(s).

```javascript
composer.dateInput("eventDate", {
  question: "Event date",
  classNames: ["col-6", "xs:col-6"],
  attrs: [
    { name: "style", value: "font-size: 18px;" }
  ]
});
```

Generates the following Markdown-like syntax:

```
[.col-6 .xs:col-6 style="font-size: 18px;"]
eventDate = DateInput(
  | question = Event date
)
```

Please [see the available CSS utility classes](/content/css-utility-classes).

### Conditional display

Conditionally show or hide a date input field using the `displayCondition` parameter. It works as follows:

* `dependencies` lists the fields to watch.
* `condition` is the expression that must be true to show the field. This must be a valid [Nunjucks](https://mozilla.github.io/nunjucks/) expression.

For instance, in the example below, the return date input will only show up if the user indicates they want to book a round trip.

```javascript
composer.choiceInput("tripType", {
  question: "What type of trip would you like to book?",
  required: true,
  choices: ["One-way", "Round trip"]
})

composer.dateInput("returnDate", {
  question: "Return date",
  displayCondition: {
    dependencies: ["tripType"],
    condition: "tripType == 'Round trip'"
  }
});
```

Generates the following Markdown-like syntax:

```
tripType* = ChoiceInput(
  | question = What type of trip would you like to book?
  | choices = One-way, Round trip
)

::: [{$ tripType $}]
{% if tripType == "Round trip" %}
returnDate = DateInput(
  | question = Return date
)
{% endif %}
:::
```


# Time input

Create time inputs in your forms.

<figure><img src="/files/qYYGx4O3Sgvi1OHqXpJl" alt=""><figcaption><p>Time input</p></figcaption></figure>

Use the `timeInput()` function to create time inputs in your forms. It uses the HTML `<input type="time">` element which provides built-in time validation.

***

## Basic usage

```javascript
import { Composer } from "formsmd";

const composer = new Composer({
  id: "my-form"
});

composer.timeInput("appointmentTime", {
  question: "What time would you like to schedule your appointment?"
});
```

Generates the following Markdown-like syntax:

```
#! id = my-form

appointmentTime = TimeInput(
  | question = What time would you like to schedule your appointment?
)
```

### Required

Add the `required` parameter to make the field mandatory:

```javascript
composer.timeInput("appointmentTime", {
  question: "What time would you like to schedule your appointment?",
  required: true
});
```

Generates the following Markdown-like syntax:

```
appointmentTime* = TimeInput(
  | question = What time would you like to schedule your appointment?
)
```

***

## Function overview

The following is the overview of the function:

```typescript
timeInput(name: string, params: object)
```

### Arguments

| Name     | Type     | Description                                                                                                                                                     |
| -------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`   | `string` | A unique name for your form field that you'll use to identify the user's response.<mark style="color:red;">\*</mark>                                            |
| `params` | `object` | An object containing all the configuration parameters for your time input field (see the [parameters section](#parameters) below for the full list of options). |

{% hint style="danger" %} <mark style="color:red;">\*</mark>Avoid values for the `name` argument which may be the names of HTML attributes, such as `"name"`, `"role"`, `"id"`, etc. This is because by default, the form's template string is first sanitized using [DOMPurify](https://github.com/cure53/DOMPurify), and these values may be removed to prevent DOM clobbering.
{% endhint %}

***

## Parameters

### Shared parameters

These parameters are common to all form fields:

| Name                  | Type                                            | Description                                                                                                                                                                                                                                                                             |
| --------------------- | ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `question` (required) | `string`                                        | The main question or label of the form field.                                                                                                                                                                                                                                           |
| `required`            | `true` (`boolean`)                              | When set, the field becomes required.                                                                                                                                                                                                                                                   |
| `description`         | `string`                                        | Any extra information that the user may need to fill out the form. Appears right below the question.                                                                                                                                                                                    |
| `fieldSize`           | `"sm"`                                          | When set to `"sm"`, the font sizes of the question, description, and answer are made smaller.                                                                                                                                                                                           |
| `labelStyle`          | `"classic"`                                     | When set to `"classic"`, the question and description of the form field are made smaller.                                                                                                                                                                                               |
| `subfield`            | `true` (`boolean`)                              | When set, the question and description of the form field are made smaller. Functionally the same as setting `labelStyle` to `"classic"`.                                                                                                                                                |
| `disabled`            | `true` (`boolean`)                              | When set, the input is disabled.                                                                                                                                                                                                                                                        |
| `autofocus`           | `true` (`boolean`)                              | When set, the input will be automatically focused when the parent slide becomes active, or immediately after page load.                                                                                                                                                                 |
| `id`                  | `string`                                        | The `id` attribute of the form field container.                                                                                                                                                                                                                                         |
| `classNames`          | `string[]`                                      | The CSS class names of the form field. [See the available CSS utility classes](/content/css-utility-classes).                                                                                                                                                                           |
| `attrs`               | `Array<{ name: string, value: string }>`        | Other HTML attributes of the form field. Each attribute has a `name` and `value` property.                                                                                                                                                                                              |
| `displayCondition`    | `{ dependencies: string[], condition: string }` | Controls when the field is shown. The `dependencies` lists the fields to watch, and `condition` is the expression that must be true to show the field. The `condition` must be a valid [Nunjucks](https://mozilla.github.io/nunjucks/) expression. [See example](#conditional-display). |

### Time input specific parameters

| Name          | Type     | Description                                      |
| ------------- | -------- | ------------------------------------------------ |
| `placeholder` | `string` | Sets the `placeholder` attribute of the input.   |
| `min`         | `string` | Sets the minimum allowed time value (`"HH:mm"`). |
| `max`         | `string` | Sets the maximum allowed time value (`"HH:mm"`). |
| `step`        | `string` | Sets the stepping interval.                      |
| `value`       | `string` | Pre-selected time value (`"HH:mm"`).             |

***

## Examples

### Time input with min and max values

```javascript
composer.timeInput("meetingTime", {
  question: "What time would you like to schedule the meeting?",
  description: "Business hours are from 9 AM to 5 PM",
  min: "09:00",
  max: "17:00",
  required: true
});
```

Generates the following Markdown-like syntax:

```
meetingTime* = TimeInput(
  | question = What time would you like to schedule the meeting?
  | description = Business hours are from 9 AM to 5 PM
  | min = 09:00
  | max = 17:00
)
```

### Time input with step interval

```javascript
composer.timeInput("appointmentTime", {
  question: "Select an appointment time",
  description: "Appointments are available in 30-minute slots",
  step: "1800",
  required: true
});
```

Generates the following Markdown-like syntax:

```
appointmentTime* = TimeInput(
  | question = Select an appointment time
  | description = Appointments are available in 30-minute slots
  | step = 1800
)
```

### Styled time input with custom attributes

Add CSS classes and other HTML attributes using the `classNames` and `attrs` parameters. Please note, these class names and attributes are added to the `<div>` or `<fieldset>` container that contains the actual input field(s).

```javascript
composer.timeInput("preferredTime", {
  question: "Preferred time",
  classNames: ["col-6", "xs:col-6"],
  attrs: [
    { name: "style", value: "font-size: 18px;" }
  ]
});
```

Generates the following Markdown-like syntax:

```
[.col-6 .xs:col-6 style="font-size: 18px;"]
preferredTime = TimeInput(
  | question = Preferred time
)
```

Please [see the available CSS utility classes](/content/css-utility-classes).

### Conditional display

Conditionally show or hide a time input field using the `displayCondition` parameter. It works as follows:

* `dependencies` lists the fields to watch.
* `condition` is the expression that must be true to show the field. This must be a valid [Nunjucks](https://mozilla.github.io/nunjucks/) expression.

For instance, in the example below, the preferred meeting time input will only show up if the user indicates they want to schedule a meeting.

```javascript
composer.choiceInput("wantMeeting", {
  question: "Would you like to schedule a meeting?",
  required: true,
  choices: ["Yes", "No"]
})

composer.timeInput("meetingTime", {
  question: "Preferred meeting time",
  displayCondition: {
    dependencies: ["wantMeeting"],
    condition: "wantMeeting == 'Yes'"
  }
});
```

Generates the following Markdown-like syntax:

```
wantMeeting* = ChoiceInput(
  | question = Would you like to schedule a meeting?
  | choices = Yes, No
)

::: [{$ wantMeeting $}]
{% if wantMeeting == "Yes" %}
meetingTime = TimeInput(
  | question = Preferred meeting time
)
{% endif %}
:::
```


# File input

Create file upload inputs in your forms.

<figure><img src="/files/b4sUAGE0u7OvLDIBojVE" alt=""><figcaption><p>File input</p></figcaption></figure>

Use the `fileInput()` function to create file upload inputs in your forms. It uses the HTML `<input type="file">` element which allows users to upload files from their device.

***

## Basic usage

```javascript
import { Composer } from "formsmd";

const composer = new Composer({
  id: "my-form"
});

composer.fileInput("document", {
  question: "Upload your document"
});
```

Generates the following Markdown-like syntax:

```
#! id = my-form

document = FileInput(
  | question = Upload your document
)
```

### Required

Add the `required` parameter to make the field mandatory:

```javascript
composer.fileInput("document", {
  question: "Upload your document",
  required: true
});
```

Generates the following Markdown-like syntax:

```
document* = FileInput(
  | question = Upload your document
)
```

***

## Function overview

The following is the overview of the function:

```typescript
fileInput(name: string, params: object)
```

### Arguments

| Name     | Type     | Description                                                                                                                                                     |
| -------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`   | `string` | A unique name for your form field that you'll use to identify the user's response.<mark style="color:red;">\*</mark>                                            |
| `params` | `object` | An object containing all the configuration parameters for your file input field (see the [parameters section](#parameters) below for the full list of options). |

{% hint style="danger" %} <mark style="color:red;">\*</mark>Avoid values for the `name` argument which may be the names of HTML attributes, such as `"name"`, `"role"`, `"id"`, etc. This is because by default, the form's template string is first sanitized using [DOMPurify](https://github.com/cure53/DOMPurify), and these values may be removed to prevent DOM clobbering.
{% endhint %}

***

## Parameters

### Shared parameters

These parameters are common to all form fields:

| Name                  | Type                                            | Description                                                                                                                                                                                                                                                                             |
| --------------------- | ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `question` (required) | `string`                                        | The main question or label of the form field.                                                                                                                                                                                                                                           |
| `required`            | `true` (`boolean`)                              | When set, the field becomes required.                                                                                                                                                                                                                                                   |
| `description`         | `string`                                        | Any extra information that the user may need to fill out the form. Appears right below the question.                                                                                                                                                                                    |
| `fieldSize`           | `"sm"`                                          | When set to `"sm"`, the font sizes of the question, description, and answer are made smaller.                                                                                                                                                                                           |
| `labelStyle`          | `"classic"`                                     | When set to `"classic"`, the question and description of the form field are made smaller.                                                                                                                                                                                               |
| `subfield`            | `true` (`boolean`)                              | When set, the question and description of the form field are made smaller. Functionally the same as setting `labelStyle` to `"classic"`.                                                                                                                                                |
| `disabled`            | `true` (`boolean`)                              | When set, the input is disabled.                                                                                                                                                                                                                                                        |
| `autofocus`           | `true` (`boolean`)                              | When set, the input will be automatically focused when the parent slide becomes active, or immediately after page load.                                                                                                                                                                 |
| `id`                  | `string`                                        | The `id` attribute of the form field container.                                                                                                                                                                                                                                         |
| `classNames`          | `string[]`                                      | The CSS class names of the form field. [See the available CSS utility classes](/content/css-utility-classes).                                                                                                                                                                           |
| `attrs`               | `Array<{ name: string, value: string }>`        | Other HTML attributes of the form field. Each attribute has a `name` and `value` property.                                                                                                                                                                                              |
| `displayCondition`    | `{ dependencies: string[], condition: string }` | Controls when the field is shown. The `dependencies` lists the fields to watch, and `condition` is the expression that must be true to show the field. The `condition` must be a valid [Nunjucks](https://mozilla.github.io/nunjucks/) expression. [See example](#conditional-display). |

### File input specific parameters

| Name          | Type     | Description                                                                                                                  |
| ------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `sizeLimit`   | `number` | Maximum file size in MB. Defaults to `10`. Client-side check only, make sure to also validate on the server.                 |
| `imageOnly`   | `true`   | When set, only image files are accepted. Client-side check only, make sure to also validate on the server.                   |
| `currentFile` | `string` | The current file that exists in the database. Use a URL for best results, for example, `"https://example.s3.com/image.png"`. |

***

## Examples

### File input with size limit

```javascript
composer.fileInput("resume", {
  question: "Upload your resume",
  description: "PDF format preferred",
  sizeLimit: 5,
  required: true
});
```

Generates the following Markdown-like syntax:

```
resume* = FileInput(
  | question = Upload your resume
  | description = PDF format preferred
  | sizelimit = 5
)
```

### Image-only file input

```javascript
composer.fileInput("profilePicture", {
  question: "Profile picture",
  description: "Upload a clear photo of yourself",
  imageOnly: true,
  sizeLimit: 2,
  required: true
});
```

Generates the following Markdown-like syntax:

```
profilePicture* = FileInput(
  | question = Profile picture
  | description = Upload a clear photo of yourself
  | imageonly
  | sizelimit = 2
)
```

### File input with existing file

```javascript
composer.fileInput("document", {
  question: "Update your document",
  currentFile: "https://example.s3.com/previous-doc.pdf"
});
```

Generates the following Markdown-like syntax:

```
document = FileInput(
  | question = Update your document
  | currentfile = https://example.s3.com/previous-doc.pdf
)
```

### Styled file input with custom attributes

Add CSS classes and other HTML attributes using the `classNames` and `attrs` parameters. Please note, these class names and attributes are added to the `<div>` or `<fieldset>` container that contains the actual input field(s).

```javascript
composer.fileInput("attachment", {
  question: "Upload attachment",
  classNames: ["col-6", "xs:col-6"],
  attrs: [
    { name: "style", value: "font-size: 18px;" }
  ]
});
```

Generates the following Markdown-like syntax:

```
[.col-6 .xs:col-6 style="font-size: 18px;"]
attachment = FileInput(
  | question = Upload attachment
)
```

Please [see the available CSS utility classes](/content/css-utility-classes).

### Conditional display

Conditionally show or hide a file input field using the `displayCondition` parameter. It works as follows:

* `dependencies` lists the fields to watch.
* `condition` is the expression that must be true to show the field. This must be a valid [Nunjucks](https://mozilla.github.io/nunjucks/) expression.

For instance, in the example below, the document upload field will only show up if the user indicates they have additional documents.

```javascript
composer.choiceInput("hasDocument", {
  question: "Do you have any supporting document?",
  required: true,
  choices: ["Yes", "No"]
})

composer.fileInput("supportingDoc", {
  question: "Upload supporting document",
  description: "You can upload PDF, image, or a Word document",
  displayCondition: {
    dependencies: ["hasDocument"],
    condition: "hasDocument == 'Yes'"
  }
});
```

Generates the following Markdown-like syntax:

```
hasDocument* = ChoiceInput(
  | question = Do you have any supporting document?
  | choices = Yes, No
)

::: [{$ hasDocument $}]
{% if hasDocument == "Yes" %}
supportingDoc = FileInput(
  | question = Upload supporting document
  | description = You can upload PDF, image, or a Word document
)
{% endif %}
:::
```


# Slide

Add slides to easily create multi-step forms.

## Basic usage

The `slide()` function creates a new slide at the point where it is called. This means that anything after this function will be placed automatically within a new slide, until another `slide()` function is called (which would create another new slide), and so on. Each slide can contain form fields, content, and custom settings like logic jumps, progress indicators, etc.

In the example below, the second slide will contain the `referralSource` and have the progress indicator set to half-complete (or `50%`). The third slide will contain the `recommender`, but it will only be shown to the user if they pick `"Recommendation"` in the second slide. An end slide with a thank you message is automatically added to every form, [though this can be customized](/content/end-slide).

<div><figure><img src="/files/lqPiqI6V5uQ62FSkzjFq" alt=""><figcaption><p>Slide 1</p></figcaption></figure> <figure><img src="/files/Wkm4C9jtLwve9ND054yo" alt=""><figcaption><p>Slide 2</p></figcaption></figure> <figure><img src="/files/PHbgWWAh6GCkGDtAoHGr" alt=""><figcaption><p>Slide 3 (only shown if the user was recommended)</p></figcaption></figure></div>

```javascript
import { Composer } from "formsmd";

const composer = new Composer({
  id: "my-form"
});
 
composer.choiceInput("position", {
  question: "What's your position?",
  choices: ["Product Manager", "Software Engineer", "Founder", "Other"],
  required: true
});

// Start new slide, progress indicator at 50%
composer.slide({
  pageProgress: "50%"
});

composer.choiceInput("referralSource", {
  question: "How did you hear about us?",
  choices: ["News", "Search Engine", "Social Media", "Recommendation"],
  required: true
});

// Start new slide, show only if user was recommended, progress indicator at 75%
composer.slide({
  jumpCondition: "referralSource == 'Recommendation'",
  pageProgress: "75%"
});

composer.emailInput("recommender", {
  question: "Who recommended you?"
});
```

Generates the following Markdown-like syntax:

```
#! id = my-form

position* = ChoiceInput(
  | question = What's your position?
  | choices = Product Manager, Software Engineer, Founder, Other
)

---
|> 50%

referralSource* = ChoiceInput(
  | question = How did you hear about us?
  | choices = News, Search Engine, Social Media, Recommendation
)

---
-> referralSource == "Recommendation"
|> 75%

recommender = EmailInput(
  | question = Who recommended you?
)
```

***

## Function overview

The following is the overview of the function:

```typescript
slide(params: object)
```

### Arguments

| Name     | Type     | Description                                                                                                                                          |
| -------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `params` | `object` | An object containing all the configuration parameters for your slide (see the [parameters section](#parameters) below for the full list of options). |

***

## Parameters

| Name              | Type                                              | Description                                                                                                                                                                   |
| ----------------- | ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `jumpCondition`   | `string`                                          | Logic jump condition that must be `true` for slide to be shown. This must be a valid [Nunjucks](https://mozilla.github.io/nunjucks/) expression.                              |
| `pageProgress`    | `string`                                          | Progress indicator shown on top (e.g. `"50%"` or `"1/2"`). Format is percentage or fraction.                                                                                  |
| `buttonAlignment` | `"start"` \| `"center"` \| `"end"` \| `"stretch"` | Set the alignment of this slide's CTA button.                                                                                                                                 |
| `post`            | `true` (`boolean`)                                | Can be used for slide-level or partial submissions. When set, posts form data up to this slide when going to the next one. [See example](#slide-level-or-partial-submission). |
| `disablePrevious` | `true` (`boolean`)                                | When set, disables the previous button.                                                                                                                                       |

***

## Examples

### Slide with logic jump

In the example below, the second slide will only be shown to the user if they are older than 18. Please note, the `jumpCondition` parameter must be a valid [Nunjucks](https://mozilla.github.io/nunjucks/) expression.

```javascript
composer.numberInput("age", {
  question: "What is your age?",
  required: true,
  min: 0,
  max: 120
});

composer.slide({
  jumpCondition: "age > 18"
});

composer.textInput("drivingLicense", {
  question: "What is your driving license number?",
  required: true
});
```

Generates the following Markdown-like syntax:

```
age* = NumberInput(
  | question = What is your age?
  | min = 0
  | max = 120
)

---
-> age > 18

drivingLicense* = TextInput(
  | question = What is your driving license number?
)
```

### Slide with progress indicator

In the example below, the progress indicator will be set to half-complete (or `50%`) within the second slide because of the `pageProgress` parameter.

```javascript
composer.textInput("name", {
  question: "What is your full name?",
  required: true
});

composer.slide({
  pageProgress: "50%"
});

composer.telInput("phone", {
  question: "What is your phone number?"
});
```

Generates the following Markdown-like syntax:

```
name* = TextInput(
  | question = What is your full name?
)

---
|> 50%

phone = TelInput(
  | question = What is your phone number?
)
```

### Slide with button alignment

In the example below, the submit button will be centered within the second slide because of the `buttonAlignment` parameter.

```javascript
composer.textInput("companyName", {
  question: "What is your company name?",
  required: true
});

composer.slide({
  buttonAlignment: "center"
});

composer.numberInput("employees", {
  question: "How many employees work at your company?",
  min: 1
});
```

Generates the following Markdown-like syntax:

```
companyName* = TextInput(
  | question = What is your company name?
)

---
=| center

employees = NumberInput(
  | question = How many employees work at your company?
  | min = 1
)
```

Please note, this slide-level `buttonAlignment` parameter will take precedence over the `buttonAligment` [form setting](/getting-started/settings) (which can be used to set the button alignment of every single slide globally).

### Slide-level or partial submission

A slide-level or partial submission is when the user completes a slide and goes to the next one, all the form data up to that slide will be sent to the POST URL. Use the `post` parameter to do slide-level submissions. In the example below, when the user enters their email and goes to the next slide,  their `accountEmail` will be sent to `/api/verify-email`. Once they enter the `verificationCode`, the form data will again be sent to `/api/verify-email`.

```javascript
import { Composer } from "formsmd";

const composer = new Composer({
  id: "my-form",
  postUrl: "/api/verify-email",
});

composer.slide({
  post: true
});

composer.emailInput("accountEmail", {
  question: "Enter your account email",
  required: true
});

composer.slide({});

composer.numberInput("verificationCode", {
  question: "Enter the verification code sent to your email",
  required: true,
  min: 100000,
  max: 999999
});
```

Generates the following Markdown-like syntax:

```
#! id = my-form
#! post-url = /api/verify-email

>> post

accountEmail* = EmailInput(
  | question = Enter your account email
)

---
verificationCode* = NumberInput(
  | question = Enter the verification code sent to your email
  | min = 100000
  | max = 999999
)
```

### Slide with disabled previous button

In the example below, the previous button (in the footer) will be disabled within the second slide because of the `disablePrevious` parameter.

```javascript
composer.choiceInput("acceptTerms", {
  question: "Do you accept the terms of service?",
  required: true,
  choices: ["Yes", "No"]
});

composer.slide({
  disablePrevious: true
});

composer.textInput("signature", {
  question: "Please type your full name as signature",
  required: true
});
```

Generates the following Markdown-like syntax:

```
acceptTerms* = ChoiceInput(
  | question = Do you accept the terms of service?
  | choices = Yes, No
)

---
<< disable

signature* = TextInput(
  | question = Please type your full name as signature
)
```

### Slide with multiple parameters

```javascript
composer.choiceInput("accountType", {
  question: "What type of account would you like to create?",
  required: true,
  choices: ["personal", "business"]
});

composer.slide({
  jumpCondition: "accountType == 'business'",
  pageProgress: "75%",
  buttonAlignment: "end"
});

composer.textInput("businessName", {
  question: "What is your business name?",
  required: true
});
```

Generates the following Markdown-like syntax:

```
accountType* = ChoiceInput(
  | question = What type of account would you like to create?
  | choices = personal, business
)

---
-> accountType == "business"
|> 75%
=| end

businessName* = TextInput(
  | question = What is your business name?
)
```


# Start slide

Add a start slide to create a landing page for your form.

## Basic usage

The `startSlide()` function creates a special slide type that acts as an entry point for your form. This slide will show a start button that users must click to begin filling out the form. You can customize the button text and alignment to match your form's design.

In the example below, the start slide contains a welcome message. The start button is centered on the page, as well as the rest of the content.

<div><figure><img src="/files/2aZScbzIPGPUeDyo79vG" alt=""><figcaption><p>Start slide</p></figcaption></figure> <figure><img src="/files/hFx5OYTcPusAg0rX52OA" alt=""><figcaption><p>Slide containing the input</p></figcaption></figure></div>

```javascript
import { Composer } from "formsmd";

const composer = new Composer({
  id: "my-form"
});

composer.startSlide({
  buttonAlignment: "center"
});

composer.h1("Welcome to our survey!", {
  classNames: ["text-center"]
});
composer.p("We appreciate you taking the time to share your feedback with us.", {
  classNames: ["text-center"]
});

composer.slide({});

composer.choiceInput("experience", {
  question: "How was your experience with our product?",
  choices: ["Excellent", "Good", "Fair", "Poor"],
  required: true
});
```

Generates the following Markdown-like syntax:

```
#! id = my-form

-> start
=| center

# [.text-center] Welcome to our survey!

[.text-center]
We appreciate you taking the time to share your feedback with us.

---
experience* = ChoiceInput(
  | question = How was your experience with our product?
  | choices = Excellent, Good, Fair, Poor
)
```

***

## Function overview

The following is the overview of the function:

```typescript
startSlide(params: object)
```

### Arguments

| Name     | Type     | Description                                                                                                                                                |
| -------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `params` | `object` | An object containing all the configuration parameters for your start slide (see the [parameters section](#parameters) below for the full list of options). |

***

## Parameters

| Name              | Type                                              | Description                                             |
| ----------------- | ------------------------------------------------- | ------------------------------------------------------- |
| `buttonText`      | `string`                                          | Custom text for the start button. Default is `"Start"`. |
| `buttonAlignment` | `"start"` \| `"center"` \| `"end"` \| `"stretch"` | Set the alignment of this slide's start button.         |

***

## Examples

### Start slide with custom button text

In the example below, the start button will have the `"Start feedback"` text because of the `buttonText` parameter.

```javascript
composer.startSlide({
  buttonText: "Start feedback"
});

composer.h1("Welcome!");
composer.p("Please take a moment to complete this feedback form.");

composer.slide({});

composer.textInput("fullName", {
  question: "What is your name?",
  required: true
});
```

Generates the following Markdown-like syntax:

```
-> start -> Start feedback

# Welcome!

Please take a moment to complete this feedback form.

---
fullName* = TextInput(
  | question = What is your name?
)
```

### Start slide with button alignment

In the example below, the start button will be aligned to the end of the slide because of the `buttonAlignment` parameter.

```javascript
composer.startSlide({
  buttonAlignment: "end"
});

composer.h1("Product survey");
composer.p("Share your thoughts about our latest product.");

composer.slide({});

composer.textInput("feedback", {
  question: "What do you think about our product?",
  multiline: true
});
```

Generates the following Markdown-like syntax:

```
-> start
=| end

# Product survey

Share your thoughts about our latest product.

---
feedback = TextInput(
  | question = What do you think about our product?
  | multiline
)
```

### Start slide with multiple parameters

```javascript
composer.startSlide({
  buttonText: "Start survey",
  buttonAlignment: "center"
});

composer.h1("Customer feedback");
composer.p("Your feedback helps us improve our services.");

composer.slide({});

composer.choiceInput("satisfaction", {
  question: "How satisfied are you with our service?",
  choices: ["Very Satisfied", "Satisfied", "Neutral", "Dissatisfied"]
});
```

Generates the following Markdown-like syntax:

```
-> start -> Start survey
=| center

# Customer feedback

Your feedback helps us improve our services.

---
satisfaction = ChoiceInput(
  | question = How satisfied are you with our service?
  | choices = Very Satisfied, Satisfied, Neutral, Dissatisfied
)
```


# End slide

Add an end slide to create a completion page after form submission.

## Basic usage

{% hint style="info" %}
An end slide with a thank you message is automatically added to every form, however, the `endSlide()` function can be used to customize this slide.
{% endhint %}

The `endSlide()` function creates a special slide type that acts as the final destination for your form. This slide will be shown after users complete and submit the form. You can also customize the slide to include a redirect URL that users will be taken to after form completion.

In the example below, the end slide contains a custom message (with some data binding).

<div><figure><img src="/files/RfspFI75ImX9FqVeQcbd" alt=""><figcaption><p>Slide containing the input</p></figcaption></figure> <figure><img src="/files/UA7UpCb89brN17bZxS1z" alt=""><figcaption><p>End slide</p></figcaption></figure></div>

```javascript
import { Composer } from "formsmd";

const composer = new Composer({
  id: "my-form"
});

composer.emailInput("email", {
  question: "Join our mailing list",
  required: true
});

composer.endSlide({});

composer.h1("Thank you", {
  classNames: ["text-center"]
});
composer.p("Subscribed to mailing list with {$ email $}.", {
  classNames: ["text-center"]
});
```

Generates the following Markdown-like syntax:

```
#! id = my-form

email* = EmailInput(
  | question = Join our mailing list
)

---
-> end

# [.text-center] Thank you

[.text-center]
Subscribed to mailing list with {$ email $}.
```

***

## Function overview

The following is the overview of the function:

```typescript
endSlide(params: object)
```

### Arguments

| Name     | Type     | Description                                                                                                                                              |
| -------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `params` | `object` | An object containing all the configuration parameters for your end slide (see the [parameters section](#parameters) below for the full list of options). |

***

## Parameters

| Name          | Type     | Description                                                                              |
| ------------- | -------- | ---------------------------------------------------------------------------------------- |
| `redirectUrl` | `string` | URL to redirect to from the end slide after form submission. This redirect is automatic. |

***

## Examples

### End slide with redirect

In the example below, users will be automatically redirected to `https://example.com/confirmation` after form submission because of the `redirectUrl`.

```javascript
composer.textInput("feedback", {
  question: "Any additional comments?",
  multiline: true
});

composer.endSlide({
  redirectUrl: "https://example.com/confirmation"
});

composer.h1("Submission complete");
composer.p("Thank you for taking the time to provide feedback.");
```

Generates the following Markdown-like syntax:

```
feedback = TextInput(
  | question = Any additional comments?
  | multiline
)

---
-> end -> https://example.com/confirmation

# Submission complete

Thank you for taking the time to provide feedback.
```

### Basic end slide

In the example below, the end slide simply displays a completion message without redirecting.

```javascript
composer.ratingInput("rating", {
  question: "How would you rate our service?",
  outOf: 5,
  required: true
});

composer.endSlide({});

composer.h1("Thanks for your rating!");
composer.p("We appreciate your feedback and will use it to improve our service.");
```

Generates the following Markdown-like syntax:

```
rating* = RatingInput(
  | question = How would you rate our service?
  | outOf = 5
)

---
-> end

# Thanks for your rating!

We appreciate your feedback and will use it to improve our service.
```

### End slide with restart button

Set the `restartButton` [form setting](/getting-started/settings) to `"show"` to add a restart button to the end slide. When clicked, this button will restart the form from the very beginning.

<figure><img src="/files/Vmf1WbnbTGjqh4VfmwWN" alt=""><figcaption><p>End slide with restart button</p></figcaption></figure>

```javascript
import { Composer } from "formsmd";

const composer = new Composer({
  id: "my-form",
  restartButton: "show"
});

composer.emailInput("email", {
  question: "Join our mailing list",
  required: true
});
```

Generates the following Markdown-like syntax:

```
#! id = my-form
#! restart-button = show

email* = EmailInput(
  | question = Join our mailing list
)
```

## FAQs

### [How do I run a function after form submission?](/getting-started/frequently-asked-questions#how-do-i-run-a-function-after-form-submission) <a href="#how-do-i-run-a-function-after-form-submission" id="how-do-i-run-a-function-after-form-submission"></a>


# Markdown

Use Markdown to add content to your forms.

Use the Markdown functions to create formatted text content in your forms. These functions help you create common elements like paragraphs, headings, lists, and more.

{% hint style="info" %}
`<div>` elements are also supported. [See block-level data binding](/content/data-binding#block-level-data-binding).
{% endhint %}

## Basic usage

```javascript
import { Composer } from "formsmd";

const composer = new Composer({
  id: "my-form"
});

composer.h1("Heading");
composer.p("This is a **paragraph**.");
composer.hr();
composer.ul([
  "Item 1",
  "Item 2",
  "Item 3"
]);
composer.blockquote("Quote");
composer.code("var a = 5;", {
  language: "javascript"
});
```

Generates the following Markdown:

````
#! id = my-form

# Heading

This is a **paragraph**.

***

- Item 1
- Item 2
- Item 3

> Quote

```javascript
var a = 5;
```
````

***

## Parameters

These parameters are common to all Markdown functions (except for the horizontal rule):

| Name         | Type                                     | Description                                                                                                |
| ------------ | ---------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `id`         | `string`                                 | The `id` attribute of the element.                                                                         |
| `classNames` | `string[]`                               | The CSS class names of the element. [See the available CSS utility classes](/content/css-utility-classes). |
| `attrs`      | `Array<{ name: string, value: string }>` | Other HTML attributes of the element. Each attribute has a `name` and `value` property.                    |

### Code parameter

Additional parameter for the code element:

| Name       | Type     | Description               |
| ---------- | -------- | ------------------------- |
| `language` | `string` | The language of the code. |

***

## Headings

Create heading elements from level 1 (largest) to level 6 (smallest).

### Function overview

```typescript
h1(content: string, params?: object)
h2(content: string, params?: object)
h3(content: string, params?: object)
h4(content: string, params?: object)
h5(content: string, params?: object)
h6(content: string, params?: object)
```

### Example

```javascript
composer.h1("Main title", {
  classNames: ["text-center", "anchored"]
});

composer.h2("Section overview", {
  classNames: ["fw-bold"]
});

composer.h3("Subsection", {
  id: "sub-1"
});
```

Generates the following Markdown:

```
# [.text-center .anchored] Main title

## [.fw-bold] Section overview

### [#sub-1] Subsection
```

***

## Paragraph

Create paragraph elements for body text.

### Function overview

```typescript
p(content: string, params?: object)
```

### Example

```javascript
composer.p("This is a paragraph with custom styling.", {
  classNames: ["fs-lead", "text-accent", "col-6"],
  attrs: [{ name: "data-test", value: "intro-text" }]
});
```

Generates the following Markdown:

```
[.fs-lead .text-accent .col-6 data-test="intro-text"]
This is a paragraph with custom styling.
```

***

## Lists (unordered, ordered, task)

Create unordered (bulleted) and ordered (numbered) lists.

### Function overview

```typescript
ul(items: string[], params?: object)
ol(items: string[], params?: object)
```

### **Unordered list example**

```javascript
composer.ul([
  "First unordered item",
  "Second unordered item",
  "Third unordered item"
], {
  classNames: ["col-6"]
});
```

Generates the following Markdown:

```
- [.col-6]
- First unordered item
- Second unordered item
- Third unordered item
```

### **Ordered list example**

```javascript
composer.ol([
  "First ordered item",
  "Second ordered item",
  "Third ordered item"
], {
  classNames: ["col-4", "xs:col-8"]
});
```

Generates the following Markdown:

```
0. [.col-4 .xs:col-8]
1. First ordered item
2. Second ordered item
3. Third ordered item
```

### **Task list example**

Add the `.list-unstyled` class and use `[ ]` or `[x]` in the `items` to create task lists:

```
composer.ul([
  "[x] Python",
  "[x] JavaScript/TypeScript",
  "[ ] Go"
], {
  classNames: ["list-unstyled"]
});
```

Generates the following Markdown:

```
- [.list-unstyled]
- [x] Python
- [x] JavaScript/TypeScript
- [ ] Go
```

***

## Blockquote

Create blockquote elements for quoted or highlighted content.

### Function overview

```typescript
blockquote(content: string, params?: object)
```

### Example

```javascript
composer.blockquote("Important notice about the survey.", {
  classNames: ["col-4", "xs:col-6"],
  attrs: [{ name: "role", value: "alert" }]
});
```

Generates the following Markdown:

```
> [.col-4 .xs:col-6 role="alert"]
> Important notice about the survey.
```

***

## Code

Create code blocks with optional language specification.

### Function overview

```typescript
code(content: string, params?: object)
```

### Example

```javascript
composer.code(`function greeting() {
  console.log("Hello!");
}`, {
  language: "javascript",
  classNames: ["col-6"]
});
```

Generates the following Markdown:

````
```javascript [.col-6]
function greeting() {
  console.log("Hello!");
}
```
````

***

## Horizontal rule

Create horizontal line dividers.

### Function overview

```typescript
hr()
```

### Example

```javascript
composer.h2("Section 1");
composer.p("First section content");
composer.hr();
composer.h2("Section 2");
```

Generates the following Markdown:

```
## Section 1

First section content

***

## Section 2
```

{% hint style="info" %}
If the slide delimiter is set to `"***"`, horizontal rules will automatically use `"---"` instead to avoid confusion with slide breaks.
{% endhint %}

***

## Free-form content

Add arbitrary content that will be included exactly as written.

### Function overview

```typescript
free(content: string)
```

### Example

```javascript
composer.free(`# Hello world

This is some free-form content that will be included exactly as written, *including* 
any Markdown formatting.`);
```

Generates the following Markdown:

```
# Hello world

This is some free-form content that will be included exactly as written, *including* 
any Markdown formatting.
```


# Data binding

Bind form field data to content.

Use data binding to create dynamic content in your forms. These functions help you bind form field data to Markdown elements and create conditional content blocks.

## Inline data binding

Bind form field data directly within Markdown elements using the `{$ field $}` syntax.

### Example

```javascript
import { Composer } from "formsmd";

const composer = new Composer({
  id: "my-form"
});

composer.emailInput("email", {
  question: "What's your email address?",
  required: true
});

composer.slide({});

composer.h1("Welcome, {$ email $}!");
composer.p("Order confirmation will be sent to {$ email $}.");
```

Generates the following Markdown-like syntax:

```
#! id = my-form

email* = EmailInput(
  | question = What's your email address?
)

---
# Welcome, {$ email $}!

Order confirmation will be sent to {$ email $}.
```

<div><figure><img src="/files/gz14YGd425VyYxWrRivo" alt=""><figcaption><p>Slide 1 with input</p></figcaption></figure> <figure><img src="/files/M7W3UjBOapXeTJDBOMc7" alt=""><figcaption><p>Slide 2 with inline data binding</p></figcaption></figure></div>

{% hint style="info" %}
Inline data binding will also work in the same slide (where the input is). The example above just shows a common use case where the next slide greets the user with their own information.
{% endhint %}

***

## Block-level data binding

Create dynamic content blocks that respond to multiple form field values. Use the `div()` function with the `bind` parameter to specify which form fields to watch.

### Function overview <a href="#function-overview" id="function-overview"></a>

The following is the overview of the function:

```
div(content: string, params?: object)
```

### Parameters

| Name         | Type                                     | Description                                                                                                                                                 |
| ------------ | ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `bind`       | `Array<string>`                          | The names of the form fields to bind to the division (e.g., `["name", "email"]`). Any changes to these fields will trigger updates to the division content. |
| `id`         | `string`                                 | The `id` attribute of the division element.                                                                                                                 |
| `classNames` | `string[]`                               | The CSS class names of the division element. [See the available CSS utility classes](/content/css-utility-classes).                                         |
| `attrs`      | `Array<{ name: string, value: string }>` | Other HTML attributes of the division element. Each attribute has a `name` and `value` property.                                                            |

### Example

Please note, the content inside the `<div>` elements uses [Nunjucks](https://mozilla.github.io/nunjucks/), so its entire list of features such as if-else statements, loops, filters, etc. are fully supported. Of course, Markdown is also supported within the content.

```javascript
composer.numberInput("price", {
  question: "Price",
  required: true,
  unitEnd: "$",
  subfield: true,
  min: 1
});

composer.numberInput("quantity", {
  question: "Quantity",
  required: true,
  subfield: true,
  min: 1
});

composer.div(`
{% if price and quantity -%}
  Total: \${{ price }} × {{ quantity }} = \${{ price * quantity }}
{% else -%}
  Total: Set price and quantity
{% endif %}
`, {
  classNames: ["fs-lead", "col-8"],
  bind: ["price", "quantity"]
});
```

Generates the following Markdown-like syntax:

```
price* = NumberInput(
  | question = Price
  | subfield
  | min = 1
  | unitend = $
)

quantity* = NumberInput(
  | question = Quantity
  | subfield
  | min = 1
)

::: [.fs-lead .col-8 {$ price quantity $}]

{% if price and quantity -%}
  Total: ${{ price }} × {{ quantity }} = ${{ price * quantity }}
{% else -%}
  Total: Set price and quantity
{% endif %}

:::
```

<figure><img src="/files/SJTi4pwxjx3owHHki8RD" alt=""><figcaption><p>Block-level data binding</p></figcaption></figure>

***

## Group together inputs and content using `<div>`

Use `divStart()` and `divEnd()` functions to create content groups with shared data bindings or styling.

### Function overview

```typescript
divStart(params?: object)
divEnd()
```

The parameters for `divStart()` are the same as the `div()` function.

### Example

```javascript
// Start a new <div>
composer.divStart({
  classNames: ["col-6"]
});

composer.p("Contact information:");

composer.textInput("name", {
  question: "Full name",
  required: true
});

composer.emailInput("email", {
  question: "Email address",
  required: true
});

// End the <div>
composer.divEnd();
```

Generates the following Markdown-like syntax:

```
::: [.col-6]

Contact information:

name* = TextInput(
  | question = Full name
)

email* = EmailInput(
  | question = Email address
)

:::
```


# CSS utility classes

Add CSS utility classes to inputs and content.

## Add class names to inputs and content

Use the `classNames` parameter to add CSS utility classes to inputs and other content. In the example below, the available classes are used to create a composite address input.

{% hint style="info" %}
An `fmd-` prefix is added to all class names. However, this can be changed. [See the prefix section](#prefix) to learn more.
{% endhint %}

<figure><img src="/files/6uzzAZoehcBdRPb0xU9X" alt=""><figcaption><p>Composite address input using CSS utility classes</p></figcaption></figure>

```javascript
import { Composer } from "formsmd";

const composer = new Composer({
  id: "my-form"
});

composer.h1("Enter your address", {
  classNames: ["form-question"]
})

composer.numberInput("house", {
  question: "House #",
  required: true,
  subfield: true,
  classNames: ["col-6"]
})

composer.numberInput("road", {
  question: "Road #",
  required: true,
  subfield: true,
  classNames: ["col-6"]
})

composer.textInput("city", {
  question: "City",
  required: true,
  subfield: true
})
```

Generates the following Markdown-like syntax:

```
#! id = my-form

# [.form-question] Enter your address

[.col-6]
house* = NumberInput(
  | question = House #
  | subfield
)

[.col-6]
road* = NumberInput(
  | question = Road #
  | subfield
)

city* = TextInput(
  | question = City
  | subfield
)
```

***

## Available CSS utility classes

The following CSS utility classes are available by default:

### Layout

All of the content uses a grid based, 12-column system. Add a `.col-{value}` class to any block-level element to have it occupy only a portion of the full width of the row. The layout class names come in the following formats:

* `.col-{value}` (only for tablets and desktops, `≥ 576px`)
* `.xs:col-{value}` (only for phones, `< 576px`)

The `{value}` can be any integer between `1` to `12` (included) or `auto`. For example, `.col-4` would span 4 columns.

```javascript
composer.numberInput("price", {
  question: "Price",
  labelStyle: "classic",
  classNames: ["col-4", "xs:col-6"],
  attrs: [
    {
      "name": "style",
      "value": "border: 1px solid;"
    }
  ]
})

composer.numberInput("quantity", {
  question: "Quantity",
  labelStyle: "classic",
  classNames: ["col-4", "xs:col-6"],
  attrs: [
    {
      "name": "style",
      "value": "border: 1px solid;"
    }
  ]
})
```

Generates the following Markdown-like syntax:

```
[.col-4 .xs:col-6 style="border: 1px solid;"]
price = NumberInput(
  | question = Price
  | labelStyle = classic
)

[.col-4 .xs:col-6 style="border: 1px solid;"]
quantity = NumberInput(
  | question = Quantity
  | labelStyle = classic
)
```

<figure><img src="/files/CciDpAb7udYfZca8ecrC" alt=""><figcaption><p>CSS utility classes for layout</p></figcaption></figure>

Push and pull each column using the following classes:

* `.col-start-{value}`/`.xs:col-start-{value}` (sets `grid-column-start: {value}`)
* `.col-end-{value}`/`.xs:col-end-{value}` (sets `grid-column-end: {value}`)

Here, the `{value}` can be any integer between `1` to `13` (included) or `auto`.

```javascript
composer.numberInput("price", {
  question: "Price",
  labelStyle: "classic",
  classNames: ["col-4", "xs:col-6"],
  attrs: [
    {
      "name": "style",
      "value": "border: 1px solid;"
    }
  ]
})

composer.numberInput("quantity", {
  question: "Quantity",
  labelStyle: "classic",
  classNames: ["col-4", "col-start-9", "xs:col-6"],
  attrs: [
    {
      "name": "style",
      "value": "border: 1px solid;"
    }
  ]
})
```

Generates the following Markdown-like syntax:

```
[.col-4 .xs:col-6 style="border: 1px solid;"]
price = NumberInput(
  | question = Price
  | labelStyle = classic
)

[.col-4 .col-start-9 .xs:col-6 style="border: 1px solid;"]
quantity = NumberInput(
  | question = Quantity
  | labelStyle = classic
)
```

<figure><img src="/files/fYcFd1HCglhjbJJPZlmy" alt=""><figcaption><p>CSS utility classes for layout</p></figcaption></figure>

{% hint style="info" %}
The layout class names will also work in the exact same way for content inside `<div>` containers.
{% endhint %}

### Color

| Class            | Description                                                                      |
| ---------------- | -------------------------------------------------------------------------------- |
| `.text-emphasis` | `color: var(--fmd-emphasis-color)` (`black` in light mode, `white` in dark mode) |
| `.text-accent`   | Sets `color` to `accent`                                                         |

### Display and flex

| Class                      | Description                   |
| -------------------------- | ----------------------------- |
| `.d-inline`                | `display: inline`             |
| `.d-inline-block`          | `display: inline-block`       |
| `.d-block`                 | `display: block`              |
| `.d-inline-flex`           | `display: inline-flex`        |
| `.d-flex`                  | `display: flex`               |
| `.align-items-center`      | `align-items: center`         |
| `.justify-content-start`   | `justify-content: flex-start` |
| `.justify-content-center`  | `justify-content: center`     |
| `.justify-content-end`     | `justify-content: flex-end`   |
| `.justify-content-stretch` | `justify-content: stretch`    |
| `.d-none`                  | `display: none`               |

{% hint style="info" %}
The above classes also have phone-only (`< 576px`) variants available using the `.xs:` prefix. For example: `.xs:d-flex`, `.xs:align-items-center`, etc.
{% endhint %}

### Heading

| Class       | Description                        |
| ----------- | ---------------------------------- |
| `.h1`       | Matches the appearance of `<h1>`   |
| `.h2`       | Matches the appearance of `<h2>`   |
| `.h3`       | Matches the appearance of `<h3>`   |
| `.h4`       | Matches the appearance of `<h4>`   |
| `.h5`       | Matches the appearance of `<h5>`   |
| `.h6`       | Matches the appearance of `<h6>`   |
| `.anchored` | Adds an anchor link to the heading |

### Font size

| Class             | Description                                              |
| ----------------- | -------------------------------------------------------- |
| `.fs-lead`        | `font-size: var(--fmd-font-size-lg)` (`18px` by default) |
| `.specific-fs-12` | `font-size: 12px`                                        |
| `.specific-fs-14` | `font-size: 14px`                                        |
| `.specific-fs-16` | `font-size: 16px`                                        |
| `.specific-fs-18` | `font-size: 18px`                                        |
| `.specific-fs-20` | `font-size: 20px`                                        |

### Font weight

| Class          | Description            |
| -------------- | ---------------------- |
| `.fw-lighter`  | `font-weight: lighter` |
| `.fw-light`    | `font-weight: 300`     |
| `.fw-normal`   | `font-weight: 400`     |
| `.fw-medium`   | `font-weight: 500`     |
| `.fw-semibold` | `font-weight: 600`     |
| `.fw-bold`     | `font-weight: 700`     |
| `.fw-bolder`   | `font-weight: bolder`  |

### Form

| Class               | Description                                        |
| ------------------- | -------------------------------------------------- |
| `.form-question`    | Matches the appearance of a form field question    |
| `.form-description` | Matches the appearance of a form field description |

### Light/dark mode

| Class      | Description                        |
| ---------- | ---------------------------------- |
| `.hide-lm` | `display: none` only in light mode |
| `.hide-dm` | `display: none` only in dark mode  |

### List

| Class            | Description                                         |
| ---------------- | --------------------------------------------------- |
| `.list-inside`   | `padding-left: 0` and `list-style-position: inside` |
| `.list-unstyled` | `padding-left: 0` and `list-style: none`            |

### LTR/RTL

| Class       | Description                 |
| ----------- | --------------------------- |
| `.hide-ltr` | `display: none` only in LTR |
| `.hide-rtl` | `display: none` only in RTL |

### Spacing

The class names for the `margin` and `padding` utilities come in the following formats:

* `.m{sides}-{size}` for `margin`&#x20;
* `.p{sides}-{size}` for `padding`

#### {sides}

| {sides}     | Description                                              |
| ----------- | -------------------------------------------------------- |
| `t`         | Sets `margin-top` or `padding-top`                       |
| `b`         | Sets `margin-bottom` or `padding-bottom`                 |
| `s` (start) | Sets `margin-left` or `padding-left` (inverted in RTL)   |
| `e` (end)   | Sets `margin-right` or `padding-right` (inverted in RTL) |

#### {size}

| {size} | Description                                    |
| ------ | ---------------------------------------------- |
| `0`    | Sets `margin` or `padding` to `0`              |
| `1`    | Sets `margin` or `padding` to `4px`            |
| `2`    | Sets `margin` or `padding` to `8px`            |
| `3`    | Sets `margin` or `padding` to `16px`           |
| `auto` | Sets `margin-left` or `margin-right` to `auto` |

### Text alignment

| Class             | Description                                          |
| ----------------- | ---------------------------------------------------- |
| `.text-start`     | `text-align: left` (inverted in RTL)                 |
| `.text-center`    | `text-align: center`                                 |
| `.text-end`       | `text-align: right` (inverted in RTL)                |
| `.xs:text-start`  | `text-align: left` only on phones (inverted in RTL)  |
| `.xs:text-center` | `text-align: center` only on phones                  |
| `.xs:text-end`    | `text-align: right` only on phones (inverted in RTL) |

### Visibility

| Class        | Description          |
| ------------ | -------------------- |
| `.invisible` | `visibility: hidden` |

***

## Prefix

By default, an `fmd-` prefix is added to all class names when the `classNames` parameter is used. This is mainly used for scoping and avoiding collisions with other CSS that may be present. However, this can be changed using the `cssPrefix` [form setting](/getting-started/settings). For example, setting `cssPrefix` to `"none"` would remove the prefix altogether. This means that you can use your own CSS utility classes, even the ones available in frameworks like Tailwind.

```javascript
const composer = new Composer({
  cssPrefix: "none",
  id: "my-form"
});

composer.emailInput("email", {
  question: "Join our mailing list",
  required: true,
  classNames: ["text-blue-500"]
});
```

Generates the following Markdown-like syntax:

```
#! css-prefix = none
#! id = my-form

[.text-blue-500]
email* = EmailInput(
  | question = Join our mailing list
)
```


# Google Sheets integration

Save form submissions directly in Google Sheets.

{% embed url="<https://youtu.be/vFTiRejsKG4>" %}
Google Sheets integration
{% endembed %}

{% hint style="info" %}
Please watch the video above to learn how to get started with the Google Sheets integration.
{% endhint %}

## Apps script code

The following is the script for the integration:

```javascript
const scriptProp = PropertiesService.getScriptProperties();
scriptProp.setProperty("uploadFolderId", "");
scriptProp.setProperty("recaptchaSecret", "");

function intialSetup() {
  const activeSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  scriptProp.setProperty("key", activeSpreadsheet.getId());
}

function getSpreadsheetColRef(num) {
  const quotient = Math.floor(num / 26);
  const remainder = num % 26;
  const letter = String.fromCharCode(65 + remainder);
  if (quotient > 0) {
    return getSpreadsheetColRef(quotient - 1) + letter;
  } else {
    return letter;
  }
}

function doPost(e) {
  const lock = LockService.getScriptLock();
  lock.tryLock(10000);

  try {
    // Parse form data fields
    const data = {};
    Object.keys(e.parameter).forEach((key) => {
      data[key] = e.parameter[key];
    });

    // Handle reCAPTCHA
    if (scriptProp.getProperty("recaptchaSecret")) {
      const response = UrlFetchApp.fetch(
        "https://www.google.com/recaptcha/api/siteverify",
        {
          method: "post",
          payload: {
            secret: scriptProp.getProperty("recaptchaSecret"),
            response: data._captcha,
          },
        },
      );
      const responseJSON = JSON.parse(response.getContentText());
      if (!responseJSON.success) {
        throw new Error("CAPTCHA verification failed.");
      }
    }

    // Handle file uploads
    if (e.parameter._fileFields) {
      const fileFields = e.parameter._fileFields.split(",");
      fileFields.forEach((field) => {
        const base64Data = data[field].replace(/^data:.*,/, "");
        const blob = Utilities.newBlob(
          Utilities.base64Decode(base64Data),
          data[`${field}Type`],
          data[`${field}Filename`],
        );
        const folder = DriveApp.getFolderById(
          scriptProp.getProperty("uploadFolderId") ||
            DriveApp.getRootFolder().getId(),
        );
        const uploadedFile = folder.createFile(blob);
        uploadedFile.setSharing(
          DriveApp.Access.PRIVATE,
          DriveApp.Permission.EDIT,
        );
        data[field] = uploadedFile.getUrl();
      });
    }

    // Get the sheet using the name
    // If the sheet name is not provided, get the first sheet of the document
    const doc = SpreadsheetApp.openById(scriptProp.getProperty("key"));
    const sheet = doc.getSheetByName(data._sheetName) || doc.getSheets()[0];

    // Set up the column references
    // This contains the column numbers for the headers (first row)
    const colRefs = {};
    const firstRow = sheet
      .getRange(1, 1, 1, sheet.getLastColumn())
      .getValues()[0];
    for (let i = 0; i < firstRow.length; i++) {
      const colName = firstRow[i];
      colRefs[colName] = i + 1;
    }

    // Get the row number to insert the request data
    // By default, this is the last row
    // If the incoming request has an "_rid" that matches an existing row,
    // then that row is used for the insert
    let rowToInsert = sheet.getLastRow() + 1;
    const _ridCol = colRefs._rid || false;
    if (_ridCol) {
      const _ridColLetter = getSpreadsheetColRef(_ridCol - 1);
      const _ridValues = sheet
        .getRange(`${_ridColLetter}:${_ridColLetter}`)
        .getValues();
      for (let i = 0; i < _ridValues.length; i++) {
        if (data._rid === String(_ridValues[i])) {
          rowToInsert = i + 1;
        }
      }
    }

    // Insert
    // Make sure to remove all formulae (starts with "=")
    for (let [key, value] of Object.entries(data)) {
      const colRef = colRefs[key] || false;
      if (colRef) {
        if (typeof value === "string") {
          value = value.trim();
          if (value.startsWith("=")) {
            value = `[${value}]`;
          }
        }
        sheet.getRange(rowToInsert, colRef).setValue(value);
      }
    }

    // Return ok
    lock.releaseLock();
    return ContentService.createTextOutput(
      JSON.stringify({ ok: true }),
    ).setMimeType(ContentService.MimeType.JSON);
  } catch (e) {
    // Throw error
    lock.releaseLock();
    throw e;
  }
}
```

## Spam protection with Google reCAPTCHA

To use Google reCAPTCHA with the apps script, add your site's reCAPTCHA secret key in this line:

```javascript
scriptProp.setProperty("recaptchaSecret", "<YOUR_SECRET_KEY>");
```

After that, save and deploy again to add spam protection.

## File uploads

For file uploads, set the `sendFilesAsBase64` [option](/getting-started/options) to `true` during instantiation:

```javascript
const formsmd = new Formsmd(
  composer.template,
  document.getElementById("my-form-container"),
  {
    sendFilesAsBase64: true
  }
);
```

## Save in a different sheet

Set the `postSheetName` [form setting](/getting-started/settings) to the name of the sheet where you want to save the submissions:

```javascript
const composer = new Composer({
  postSheetName: "sheet4"
});
```

Generates the following Markdown-like syntax:

```
#! post-sheet-name = sheet4
```


# WordPress Plugin

Easily create elegant, Typeform-style forms on your WordPress site.

{% hint style="info" %}
The Forms.md WordPress plugin is very simple to use, in a way where it's actually self-documenting. You'll find short hints on what to do directly on your WP Admin after installing the plugin.
{% endhint %}

The Forms.md WordPress plugin allows you to use the software inside WP, making it easy to create elegant, Typeform-style forms on your site.

## AI Form Builder

Use the AI Form Builder to create or edit forms from the **Add New Form** and **Edit Form** pages in your WP Admin.

You can also set up ChatGPT for form generation:\
<https://wp.forms.md/ai-form-builder-chatgpt-setup/>

## Theming

Customize your forms from the **Settings** page to match your design preferences. Both light mode and dark mode are supported.

You can also set a form's container height, padding, custom CSS (like borders) from the **Add New Form**/**Edit Form** page, under **Layout Options**.

## Google reCAPTCHA

Protect your site from spam by configuring Google reCAPTCHA in the **Settings** page.

## Permissions

Control which WP admin users can access forms and responses from the **Settings** page.

## Form Content

The plugin uses Forms.md under the hood, so you can refer to the documentation to add text inputs, email inputs, opinion scales, slides, and more. If you run into syntax issues, you can use the AI Form Builder or set up ChatGPT to generate your forms automatically.&#x20;

That said, here are some relevant docs for the form fields, slides, settings, etc., just make sure to use the **Markdown-like** text in the **Content** field when creating/editing forms on your WP site:

{% content-ref url="/pages/Dd1abEtAkeVRZ0bAOqxe" %}
[Form settings](/getting-started/settings)
{% endcontent-ref %}

{% content-ref url="/pages/1BdhNeAEereqEk1OCIjW" %}
[Localization](/customization/localization)
{% endcontent-ref %}

{% content-ref url="/pages/jrrP6C2FlSxXiKqn8tBw" %}
[Text input](/input-types/text-input)
{% endcontent-ref %}

{% content-ref url="/pages/caw8GoyjmU20CSl4OGtH" %}
[Email input](/input-types/email-input)
{% endcontent-ref %}

{% content-ref url="/pages/auemgys5xDmpbulqnUXI" %}
[URL input](/input-types/url-input)
{% endcontent-ref %}

{% content-ref url="/pages/WWzNGBtQPCY9WrQ6GzHw" %}
[Telephone input](/input-types/tel-input)
{% endcontent-ref %}

{% content-ref url="/pages/w83TaSL0Va226CwtT0u8" %}
[Password input](/input-types/password-input)
{% endcontent-ref %}

{% content-ref url="/pages/o3BAJNzkg7u8tCbOp8MG" %}
[Number input](/input-types/number-input)
{% endcontent-ref %}

{% content-ref url="/pages/M1zFFQmdwvSX95CluTHC" %}
[Select box](/input-types/select-box)
{% endcontent-ref %}

{% content-ref url="/pages/3pMMv1tGJhGh7ccW7x23" %}
[Choice input](/input-types/choice-input)
{% endcontent-ref %}

{% content-ref url="/pages/IIXH26duircLbbnVA2mg" %}
[Picture choice](/input-types/picture-choice)
{% endcontent-ref %}

{% content-ref url="/pages/Mf0teoKAvnW6CSONKG7O" %}
[Rating input](/input-types/rating-input)
{% endcontent-ref %}

{% content-ref url="/pages/Wq7EIYuitupm9tpbn6zq" %}
[Opinion scale / Net Promoter Score®](/input-types/opinion-scale)
{% endcontent-ref %}

{% content-ref url="/pages/RPdxIKBkAwU01Yux4QVV" %}
[Datetime input](/input-types/datetime-input)
{% endcontent-ref %}

{% content-ref url="/pages/91tKVOEEaEBLQB3HCSWp" %}
[Date input](/input-types/date-input)
{% endcontent-ref %}

{% content-ref url="/pages/3ufW4dhv5m7OmLjJwa0M" %}
[Time input](/input-types/time-input)
{% endcontent-ref %}

{% content-ref url="/pages/9c7M21NPk81agaaCvJ9i" %}
[File input](/input-types/file-input)
{% endcontent-ref %}

{% content-ref url="/pages/DYZsSIYnJZaBymUwBo00" %}
[Slide](/content/slide)
{% endcontent-ref %}

{% content-ref url="/pages/a7RrFprnSoKE3NnVbeBX" %}
[Start slide](/content/start-slide)
{% endcontent-ref %}

{% content-ref url="/pages/tQP1rFGkfwblgKJbP3Ia" %}
[End slide](/content/end-slide)
{% endcontent-ref %}

{% content-ref url="/pages/6ODthy2SEEi2G6sFCAPM" %}
[Markdown](/content/markdown)
{% endcontent-ref %}

{% content-ref url="/pages/u94Ct2sMKy7Yhxx0tsqq" %}
[Data binding](/content/data-binding)
{% endcontent-ref %}

{% content-ref url="/pages/aqWV44WzbBfLbIFA31qv" %}
[CSS utility classes](/content/css-utility-classes)
{% endcontent-ref %}


# AI Form Builder ChatGPT Setup

Learn how to use ChatGPT to create/edit forms.

The **Forms.md** WordPress plugin comes with an AI form builder that lets you create or edit forms directly from your WordPress admin using prompts.

If you prefer to use your own ChatGPT (instead of **Forms.md** servers), follow this guide to set it up in about 2 minutes. Using your own ChatGPT typically produces better form output—and it’s completely free.

***

### 1. Create a ChatGPT Project

From ChatGPT’s sidebar:

**Projects** → **New Project** → **Add a name** → **Save**

***

### 2. Download Project Files

[Download the instructions zip file](https://drive.google.com/file/d/1PKFj8N50N1spBtNKhAjdqQ3ukzh4blwS/view?usp=sharing) and extract it. You will find:

* `instructions.md`
* `docs.md`

***

### 3. Set Up the ChatGPT Project

1. Click the **Add files** button on the project page.
2. Paste the contents of `instructions.md` into the **Instructions** field.
3. Upload the `docs.md` file into the **Files** field.

***

### 4. Start Generating Forms

You’re now set up.

Start chats within this project and ChatGPT will create or edit forms for you. Copy the Markdown-like text output and paste it into your form’s WordPress admin content field.

<div data-with-frame="true"><figure><img src="/files/BTbr3IRjAbrkTqUsniqf" alt=""><figcaption><p>ChatGPT creating/editing forms</p></figcaption></figure></div>


