---
title: "Reference"
description: "Attributes, headers, events, and configuration."
---

import { getFolder } from '../../lib/content';

export const folder = await getFolder('reference');

export const ATTRIBUTE_GROUPS = [
    { label: 'Requests', titles: ['hx-get', 'hx-post', 'hx-put', 'hx-patch', 'hx-delete'] },
    { label: 'Request Control', titles: ['hx-trigger', 'hx-swap', 'hx-target', 'hx-select', 'hx-swap-oob', 'hx-select-oob', 'hx-confirm'] },
    { label: 'Scripting', titles: ['hx-on'] },
    { label: 'Data', titles: ['hx-vals', 'hx-include', 'hx-headers', 'hx-encoding'] },
    { label: 'History', titles: ['hx-push-url', 'hx-replace-url', 'hx-history-elt'] },
    { label: 'Enhancements', titles: ['hx-boost', 'hx-preload', 'hx-optimistic'] },
    { label: 'Advanced', titles: ['hx-indicator', 'hx-status', 'hx-sync', 'hx-validate', 'hx-disable', 'hx-ignore', 'hx-preserve', 'hx-action', 'hx-method', 'hx-config'] },
];
export const REQUEST_HEADERS = ['HX-Request', 'HX-Request-Type', 'HX-Current-URL', 'HX-Source', 'HX-Target', 'HX-Boosted', 'HX-History-Restore-Request', 'Accept', 'Last-Event-ID'];

export const groups = folder.folders.map(sub => {
    const items = sub.files.map(f => ({
        title: f.frontmatter.title,
        url: f.url,
        description: f.frontmatter.description,
    }));

    if (sub.slug === 'attributes') {
        const subgroups = ATTRIBUTE_GROUPS.map(g => ({
            label: g.label,
            items: g.titles.map(t => items.find(i => i.title === t)).filter(Boolean),
        }));
        return { slug: sub.slug, label: sub.frontmatter.title, subgroups };
    }
    if (sub.slug === 'headers') {
        const request = items.filter(i => REQUEST_HEADERS.includes(i.title));
        const response = items.filter(i => !REQUEST_HEADERS.includes(i.title));
        return { slug: sub.slug, label: sub.frontmatter.title, subgroups: [
            { label: 'Request', items: request },
            { label: 'Response', items: response },
        ]};
    }
    return { slug: sub.slug, label: sub.frontmatter.title, subgroups: [{ label: null, items }] };
});

<div class="not-prose mb-6">
    <input
        id="filter-input"
        type="text"
        placeholder="Search reference..."
        autocomplete="off"
        class="w-full px-3 py-2 text-sm border border-neutral-200 dark:border-neutral-800 rounded-md bg-white dark:bg-neutral-900 text-neutral-800 dark:text-neutral-200 placeholder:text-neutral-400 dark:placeholder:text-neutral-500 focus:outline-none focus:ring-2 focus:ring-neutral-300/50 dark:focus:ring-neutral-600/50 focus:border-neutral-300 dark:focus:border-neutral-600"
        _="on input
            set q to my.value.toLowerCase()
            if q is ''
                for s in <.filter-group/> remove @hidden from s end
                for sg in <.filter-subgroup/> remove @hidden from sg end
                for i in <.filter-item/> remove @hidden from i end
                for ct in <.filter-count/>
                    set parts to ct.dataset.total
                    put parts into ct
                end
            else
                for section in <.filter-group/>
                    set sectionTotal to 0
                    for subgroup in <.filter-subgroup/> in section
                        set subgroupTotal to 0
                        for item in <.filter-item/> in subgroup
                            if item.dataset.filter contains q
                                remove @hidden from item
                                increment subgroupTotal
                            else
                                add @hidden to item
                            end
                        end
                        set sectionTotal to sectionTotal + subgroupTotal
                        if subgroupTotal is 0 then add @hidden to subgroup else remove @hidden from subgroup
                    end
                    put sectionTotal into first <.filter-count/> in section
                    if sectionTotal is 0 then add @hidden to section else remove @hidden from section
                end
            end"
    />
</div>

{groups.map(group => {
    const totalItems = group.subgroups.reduce((n, sg) => n + sg.items.length, 0);
    return (
        <section class="filter-group">
            <h2 id={group.slug}>
                <a href={`#${group.slug}`} class="no-underline interact:underline">
                    {group.label}
                </a>
                {' '}<span class="filter-count text-xs font-normal text-neutral-400 dark:text-neutral-500 tabular-nums inline-block -translate-y-px" data-total={totalItems}>{totalItems}</span>
            </h2>
            {group.subgroups.map(sg => (
                <div class="filter-subgroup">
                    {sg.label && <h4 id={`${group.slug}-${sg.label.toLowerCase()}`} class="font-sans text-[0.625rem] font-normal uppercase tracking-widest text-neutral-600 dark:text-neutral-400">{sg.label}</h4>}
                    <table>
                        <tbody>
                            {sg.items.map(item => (
                                <tr class="filter-item stretch-link" data-filter={`${item.title} ${item.description || ''}`.toLowerCase()}>
                                    <td>
                                        <a href={item.url}><code>{item.title}</code></a>
                                        {item.description && <span class="block sm:hidden text-[0.8125em] text-neutral-650 dark:text-neutral-350 mt-0.5 pl-[6px]">{item.description}</span>}
                                    </td>
                                    <td class="hidden sm:table-cell">{item.description || ''}</td>
                                </tr>
                            ))}
                        </tbody>
                    </table>
                </div>
            ))}
        </section>
    );
})}
