# Interface API

Honestly, this is mostly just for our own purposes so that we can refer back to how it works, but you can definitely use this in your own projects.

## Forms

The form system provides a way to open modal dialogs with dynamic input fields from Lua. Forms are blocking -- the calling thread yields until the player submits or cancels. The return value is a table of input values keyed by name, or `nil` if cancelled.

### Usage

```lua
local result = Z.openForm(title, inputs, options)
```

* `title` (string, required) -- text displayed in the modal header.
* `inputs` (table\[], required) -- array of input definitions.
* `options` (table, optional) -- modal-level configuration.

Returns a `table` of values keyed by each input's `name`, or `nil` if cancelled.

### Helpers

```lua
Z.isFormOpen()          -- returns true if a form is currently open
Z.getOpenFormId()       -- returns the active form's ID, or nil
Z.closeForm()           -- close the active form (resolves as nil)
Z.closeFormById(formId) -- close a specific form by ID (resolves as nil)
```

***

### Options

The third parameter controls the modal itself. All fields are optional.

* `icon` (string) -- icon shown in the header next to the title.
* `width` (string, default `"30rem"`) -- CSS width of the modal.
* `submitText` (string, default `"Confirm"`) -- label on the submit button.
* `submitIcon` (string) -- icon on the submit button.
* `submitColor` (string, default `"var(--blue1)"`) -- CSS color for the submit button.
* `showCancel` (boolean, default `true`) -- whether to show a cancel button.
* `disableClickOutside` (boolean, default `false`) -- prevent closing by clicking the backdrop.

Pressing Enter submits the form. Pressing Escape cancels it.

***

### Input Types

Each entry in the `inputs` array is a table with a `type` field and additional properties depending on the type.

#### Common Properties

These apply to all input types.

* `type` (string, required) -- one of: `text`, `number`, `select`, `select-player`, `checkbox`, `slider`, `textarea`.
* `name` (string, required) -- key used in the returned values table.
* `label` (string) -- label shown above the input.
* `description` (string) -- secondary text below the label.
* `icon` (string) -- icon displayed in the input (select and text types).
* `disabled` (boolean) -- prevent interaction.
* `defaultValue` (any) -- initial value.

***

#### text

Standard single-line text input.

* `placeholder` (string) -- placeholder text when empty.

```lua
{ type = "text", name = "plate", label = "License Plate", placeholder = "ABC 123", icon = "label" }
```

Returns `string`.

***

#### number

Numeric input.

* `placeholder` (string) -- placeholder text.
* `min` (number) -- minimum allowed value.
* `max` (number) -- maximum allowed value.

```lua
{ type = "number", name = "amount", label = "Amount", min = 1, max = 100, icon = "money" }
```

Returns `number`.

***

#### select

Dropdown selection with optional search filtering.

* `content` (table\[]) -- array of `{ label = "...", value = "..." }` options.
* `searchable` (boolean) -- enable search filtering.
* `multiselect` (boolean) -- allow multiple selections.
* `placeholder` (string) -- placeholder text.

```lua
{
    type = "select",
    name = "garage",
    label = "Garage",
    icon = "garage",
    searchable = true,
    content = {
        { label = "Legion Square", value = "legion" },
        { label = "Pillbox", value = "pillbox" },
    },
    defaultValue = "legion",
}
```

Returns `string` (selected value) or `table` (array of values if multiselect).

***

#### select-player

A select dropdown automatically populated with all connected players. Each entry renders as `(id) Firstname Lastname` with the player's identifier as the value. Searchable by default. Defaults to the `person` icon if none is specified.

All standard select properties (`searchable`, `multiselect`, `placeholder`, `defaultValue`) are supported.

```lua
{ type = "select-player", name = "target", label = "Target Player" }
```

Returns `string` (player identifier).

***

#### checkbox

Boolean toggle with a label.

```lua
{ type = "checkbox", name = "agree", label = "I agree to the terms" }
```

Returns `boolean`.

***

#### slider

Range slider with optional step marks.

* `min` (number) -- minimum value.
* `max` (number) -- maximum value.
* `step` (number) -- step increment.
* `marks` (table\[]) -- array of `{ value = n, label = "..." }` tick marks.

```lua
{ type = "slider", name = "rating", label = "Rating", min = 0, max = 10, step = 1 }
```

Returns `number`.

***

#### textarea

Multi-line text input with auto-resize.

* `placeholder` (string) -- placeholder text.
* `minRows` (number, default `3`) -- minimum visible rows.
* `maxRows` (number, default `6`) -- maximum visible rows.
* `maxLength` (number) -- character limit.

```lua
{ type = "textarea", name = "notes", label = "Notes", placeholder = "Write here...", maxLength = 500 }
```

Returns `string`.

***

### Icons

Icons can be specified by name as a string on any `icon` field (inputs and options). Resolution works in two layers:

1. **Icon Registry** -- SVG icons from MUI and react-icons. These are the same icons used throughout zyke\_garages and render as crisp vector graphics.
2. **Material Icons** (fallback) -- if the name is not found in the registry, it is treated as a [Material Icons](https://fonts.google.com/icons) font name.

#### Registry Icons

<details>

<summary>View all registry icons</summary>

| Name           | Source      | Description                            |
| -------------- | ----------- | -------------------------------------- |
| `confirm`      | react-icons | Standard confirm/submit icon (SiAuthy) |
| `check`        | MUI         | Checkmark                              |
| `save`         | MUI         | Floppy disk                            |
| `edit`         | MUI         | Pencil                                 |
| `delete`       | MUI         | Trash can                              |
| `add`          | MUI         | Plus sign                              |
| `close`        | MUI         | X mark                                 |
| `refresh`      | MUI         | Circular arrows                        |
| `restore`      | MUI         | Restore clock                          |
| `copy`         | MUI         | Clipboard copy                         |
| `search`       | MUI         | Magnifying glass                       |
| `back`         | MUI         | Left arrow                             |
| `person`       | MUI         | Person silhouette                      |
| `accounts`     | MUI         | Person with gear                       |
| `garage`       | MUI         | Garage door                            |
| `warehouse`    | MUI         | Warehouse                              |
| `car`          | MUI         | Car                                    |
| `car_alt`      | react-icons | Car (alternate)                        |
| `commute`      | MUI         | Two cars                               |
| `engine`       | react-icons | Engine block                           |
| `fuel`         | react-icons | Jerry can                              |
| `gas`          | react-icons | Gas pump                               |
| `wheel`        | react-icons | Car wheel                              |
| `suspension`   | react-icons | Spring coil                            |
| `transmission` | react-icons | Manual gearbox                         |
| `turbo`        | react-icons | Lightning bolt                         |
| `propane`      | MUI         | Propane tank                           |
| `receipt`      | MUI         | Receipt document                       |
| `label`        | MUI         | Tag label                              |
| `info`         | MUI         | Info circle                            |
| `info_alt`     | react-icons | Info circle (alternate)                |
| `warning`      | MUI         | Warning triangle                       |
| `error`        | MUI         | Error circle                           |
| `help`         | MUI         | Question mark circle                   |
| `gitbook`      | react-icons | Gitbook logo                           |
| `key`          | MUI         | Key                                    |
| `key_alt`      | react-icons | Key (alternate)                        |
| `lock`         | MUI         | Locked padlock                         |
| `unlock`       | MUI         | Open padlock                           |
| `settings`     | MUI         | Gear                                   |
| `build`        | MUI         | Wrench                                 |
| `construction` | MUI         | Construction hat                       |
| `wrench`       | react-icons | Wrench (alternate)                     |
| `work`         | MUI         | Briefcase                              |
| `gavel`        | MUI         | Judge's gavel                          |
| `keyboard`     | MUI         | Keyboard                               |
| `location`     | MUI         | Map pin                                |
| `time`         | MUI         | Clock                                  |
| `color`        | MUI         | Paint palette                          |
| `money`        | MUI         | Dollar sign                            |
| `cart`         | MUI         | Shopping cart                          |

</details>

#### Material Icons Fallback

Any string not found in the registry is treated as a Material Icons font name. Browse the available icons at [fonts.google.com/icons](https://fonts.google.com/icons).

```lua
icon = "directions_boat"  -- not in registry, renders via Material Icons font
```

***

### Full Example

```lua
local result = Z.openForm("Report Player", {
    {
        type = "select-player",
        name = "target",
        label = "Player",
    },
    {
        type = "select",
        name = "reason",
        label = "Reason",
        icon = "warning",
        searchable = true,
        content = {
            { label = "Cheating", value = "cheating" },
            { label = "Harassment", value = "harassment" },
            { label = "Bug Abuse", value = "bug_abuse" },
        },
    },
    {
        type = "textarea",
        name = "details",
        label = "Details",
        placeholder = "Describe what happened...",
        maxLength = 500,
    },
}, {
    icon = "info",
    submitText = "Submit Report",
    submitIcon = "confirm",
    submitColor = "var(--blue1)",
})

if (not result) then return end

print(result.target, result.reason, result.details)
```
