{% macro onsTable(params) %}
    {% from "components/button/_macro.njk" import onsButton %}
    {% from "components/icon/_macro.njk" import onsIcon %}
    {% from "components/figure/_macro.njk" import onsFigure %}
    {% set variants = params.variants if params.variants %}

    {%
        call onsFigure({
            "useDivForRootElement": true,
            "id": params.id,
            "headingLevel": params.headingLevel,
            "figureNumber": params.figureNumber,
            "title": params.title,
            "subtitle": params.subtitle,
            "footnotes": params.footnotes,
            "download": params.download,
            "caption": params.sourceNote
        })
    %}
        {% set tableClasses = "ons-table" %}

        {# If there is no source note, footnotes or downloads after the table, add a bottom margin to the table to match the previous spacing #}
        {# If there source note, footnotes or downloads after the table, the figure component handles the extra spacing #}
        {% if not params.sourceNote and not params.footnotes and not params.download %}
            {% set tableClasses = tableClasses + " ons-table--bottom-space" %}
        {% endif %}

        {% if params.tableClasses %}
            {% set tableClasses = tableClasses + " " + params.tableClasses %}
        {% endif %}

        <div class="ons-table-scrollable ons-table-scrollable--on">
            <div
                class="ons-table-scrollable__content"
                tabindex="0"
                role="region"
                {% if params.ariaLabel %}aria-label="{{ params.ariaLabel }}"{% endif %}
            >
                {# Uses multiple loops to set the rowspan class so that it can work in both nunjucks and jinja2 environments due to the scoping rules of each language #}
                <table
                    class="{{ tableClasses }}{% for row in params.thList %}{% for th in row.ths %}{% if th.rowspan %}{{ ' ' }}ons-table--has-rowspan{% endif %}{% endfor %}{% endfor %}{% for row in params.trs %}{% for td in row.tds %}{% if td.rowspan %}{{ ' ' }}ons-table--has-rowspan{% endif %}{% endfor %}{% endfor %}{% if variants %}{% if variants is not string %}{% for variant in variants %}{{ ' ' }}ons-table--{{ variant }}{% endfor %}{% else %}{{ ' ' }}ons-table--{{ variants }}{% endif %}{% endif %}"
                    {% if params.sortBy and 'sortable' in variants %}
                        data-aria-sort="{{ params.sortBy }}" data-aria-asc="{{ params.ariaAsc }}" data-aria-desc="{{ params.ariaDesc }}"
                    {% endif %}
                >
                    {# Note that the caption is rendered inside the table element to be semantically correct, and we deliberately do not render it with the onsFigure caption option. We also have the option to visually hide it for the table. #}
                    {% if params.caption %}
                        <caption class="ons-table__caption{{ ' ons-u-vh' if params.hideCaption }}">
                            {{ params.caption }}
                        </caption>
                    {% endif %}
                    <thead class="ons-table__head">
                        {# Uses thList if multiple-row headers, otherwise wrap single ths array into a default group #}
                        {% if params.thList %}
                            {% set thGroups = params.thList %}
                        {% else %}
                            {% set thGroups = [ { "ths": params.ths } ] %}
                        {% endif %}
                        {% for headerCols in thGroups %}
                            <tr class="ons-table__row">
                                {% for th in headerCols.ths %}
                                    <th
                                        scope="col"
                                        class="ons-table__header  ons-table__header--{{ th.valign | default('top') }}{{ ' ' + th.thClasses if th.thClasses else '' }}{{ ' ons-table__header--numeric' if th.numeric }}"
                                        {% if th.colspan %}colspan="{{ th.colspan }}"{% endif %}
                                        {% if th.rowspan %}rowspan="{{ th.rowspan }}"{% endif %}
                                        {% if 'sortable' in variants %}aria-sort="{{ th.ariaSort | default('none') }}"{% endif %}
                                        {% if th.widthPercentage %}width="{{ th.widthPercentage }}%"{% endif %}
                                    >
                                        <span class="ons-table__header-text">{{ th.value | safe }}</span>
                                        {% if 'sortable' in variants %}
                                            {{-
                                                onsIcon({
                                                    "iconType": "sort-sprite",
                                                    "id": th.value | replace(' ', '-'),
                                                    "classes": 'ons-u-d-no'
                                                })
                                            -}}
                                        {% endif %}
                                    </th>
                                {% endfor %}
                            </tr>
                        {% endfor %}
                    </thead>
                    <tbody class="ons-table__body">
                        {% for tr in params.trs %}
                            <tr
                                class="ons-table__row{{ ' ons-table__row--highlight' if tr.highlight }}"
                                {% if tr.id %}id="{{ tr.id }}"{% endif %}
                            >
                                {% for td in tr.tds %}
                                    {% if td.heading == true %}
                                        {% set openingTag = '<th' %}
                                        {% set closingTag = '</th>' %}
                                    {% else %}
                                        {% set openingTag = '<td' %}
                                        {% set closingTag = '</td>' %}
                                    {% endif %}
                                    {% set isFirstRow = loop.index == 0 and td.rowspan %}
                                    {% set rowSpan = isFirstRow and loop.index0 == rowspanCount %}
                                    {{ openingTag | safe }}
                                    class="ons-table__cell
                                    ons-table__cell--{{ td.valign | default('top') }}{{ ' ' + td.tdClasses if td.tdClasses else '' }}{{ ' ons-table__cell--numeric' if td.numeric }}"
                                    {% if td.id %}id="{{ td.id }}"{% endif %}
                                    {% if td.data %}{{ ' ' }}data-th="{{ td.data }}"{% endif %}
                                    {% if td.colspan %}colspan="{{ td.colspan }}"{% endif %}
                                    {% if td.rowspan %}rowspan="{{ td.rowspan }}"{% endif %}
                                    {% if td.dataSort %}{{ ' ' }}data-sort-value="{{ td.dataSort }}"{% endif %}
                                    {% if td.heading %}scope="row"{% endif %}
                                    >
                                    {% if td.form %}
                                        <form action="{{ td.form.action }}" method="{{ td.form.method | default('POST') }}">
                                            {{ onsButton(td.form.button) }}
                                            {% if td.form.hiddenFormField %}
                                                {% for hiddenField in td.form.hiddenFormField %}
                                                    <input
                                                        type="hidden"
                                                        {% if hiddenField.name %}name="{{ hiddenField.name }}"{% endif %}
                                                        {% if hiddenField.value %}value="{{ hiddenField.value }}"{% endif %}
                                                    />
                                                {% endfor %}
                                            {% endif %}
                                        </form>
                                    {% endif %}
                                    {% if td.value %}
                                        {{ td.value | safe }}
                                    {% endif %}
                                    {{ closingTag | safe }}
                                {% endfor %}
                            </tr>
                        {% endfor %}
                    </tbody>
                    {% if params.tfoot %}
                        <tfoot class="ons-table__foot">
                            <tr class="ons-table__row">
                                {% for tfootCell in params.tfoot %}
                                    <td class="ons-table__cell ons-table__cell--{{ tfootCell.valign | default('top') }} ons-u-fs-s">
                                        {{ tfootCell.value }}
                                    </td>
                                {% endfor %}
                            </tr>
                        </tfoot>
                    {% endif %}
                </table>
            </div>
        </div>
    {% endcall %}
{% endmacro %}
