Prepare 1.0.0 release

This commit is contained in:
Ronan Berder
2026-06-27 18:07:58 +08:00
parent f254b92bd3
commit a9e1fe7b91
56 changed files with 5595 additions and 9121 deletions
+10 -5
View File
@@ -18,6 +18,11 @@
hidden_input_attrs={}
) %}
{% set id = id or ("combobox-" + (range(100000, 999999) | random | string)) %}
{% set main_attrs = main_attrs or {} %}
{% set input_attrs = input_attrs or {} %}
{% set popover_attrs = popover_attrs or {} %}
{% set listbox_attrs = listbox_attrs or {} %}
{% set hidden_input_attrs = hidden_input_attrs or {} %}
{% set selected_entries = namespace(items=[]) %}
{% if selected is defined and selected is iterable and selected is not string %}
{% set selected_values = selected %}
@@ -43,7 +48,7 @@
<div
id="{{ id }}"
class="combobox {{ main_attrs.class }}"
class="combobox {{ main_attrs.class | default('') }}"
{% if format == "object" %}data-format="object"{% endif %}
{% if multiple and close_on_select %}data-close-on-select="true"{% endif %}
{% if auto_highlight %}data-auto-highlight="true"{% endif %}
@@ -55,7 +60,7 @@
<input
type="text"
role="combobox"
class="{{ input_attrs.class }}"
class="{{ input_attrs.class | default('') }}"
placeholder="{{ placeholder or '' }}"
autocomplete="off"
autocorrect="off"
@@ -68,7 +73,7 @@
{% endfor %}
>
{% elif clear %}
<div class="input-group {{ input_attrs.class }}">
<div class="input-group {{ input_attrs.class | default('') }}">
<input
type="text"
role="combobox"
@@ -103,7 +108,7 @@
aria-autocomplete="list"
aria-expanded="false"
aria-controls="{{ id }}-listbox"
class="{{ input_attrs.class }}"
class="{{ input_attrs.class | default('') }}"
{% for key, value in input_attrs.items() %}
{% if key != 'class' %}{{ key }}="{{ value }}"{% endif %}
{% endfor %}
@@ -127,7 +132,7 @@
{{ key }}="{{ value }}"
{% endfor %}
>
{{ caller() if caller else '' }}
{{ caller() if caller is defined else '' }}
</div>
</div>
<input
+31 -24
View File
@@ -19,9 +19,12 @@
menu_attrs={}
) %}
{% set id = id or ("command-" ~ range(100000, 999999) | random | string) %}
{% set main_attrs = main_attrs or {} %}
{% set input_attrs = input_attrs or {} %}
{% set menu_attrs = menu_attrs or {} %}
<div
id="{{ id }}"
class="command {{ main_attrs.class }}"
class="command {{ main_attrs.class | default('') }}"
aria-label="Command menu"
{% for key, value in main_attrs.items() %}
{% if key != 'class' %}{{ key }}="{{ value }}"{% endif %}
@@ -50,7 +53,7 @@
id="{{ id }}-menu"
aria-orientation="vertical"
data-empty="{{ empty_text }}"
class="{{ menu_attrs.class }}"
class="{{ menu_attrs.class | default('') }}"
{% for key, value in menu_attrs.items() %}
{% if key != 'class' %}{{ key }}="{{ value }}"{% endif %}
{% endfor %}
@@ -58,7 +61,7 @@
{% if items and items|length > 0 %}
{{ render_command_items(items, id ~ "-items" if id else "items") }}
{% else %}
{{ caller() if caller }}
{{ caller() if caller is defined }}
{% endif %}
</div>
</div>
@@ -87,9 +90,12 @@
open=False
) %}
{% set id = id or ("command-dialog-" ~ range(100000, 999999) | random | string) %}
{% set dialog_attrs = dialog_attrs or {} %}
{% set input_attrs = input_attrs or {} %}
{% set menu_attrs = menu_attrs or {} %}
<dialog
id="{{ id }}"
class="command-dialog {{ dialog_attrs.class }}"
class="command-dialog {{ dialog_attrs.class | default('') }}"
aria-label="Command menu"
{% if open %}open{% endif %}
onclick="if (event.target === this) this.close()"
@@ -121,7 +127,7 @@
id="{{ id }}-menu"
aria-orientation="vertical"
data-empty="{{ empty_text }}"
class="{{ menu_attrs.class }}"
class="{{ menu_attrs.class | default('') }}"
{% for key, value in menu_attrs.items() %}
{% if key != 'class' %}{{ key }}="{{ value }}"{% endif %}
{% endfor %}
@@ -129,7 +135,7 @@
{% if items and items|length > 0 %}
{{ render_command_items(items, id ~ "-items" if id else "items") }}
{% else %}
{{ caller() if caller }}
{{ caller() if caller is defined }}
{% endif %}
</div>
</div>
@@ -149,53 +155,54 @@
{% macro render_command_items(items, parent_id_prefix="items") %}
{% for item in items %}
{% set item_id = parent_id_prefix ~ "-" ~ loop.index %}
{% if item.type == "group" %}
{% set group_label_id = item.id if item.id else "group-label-" + item_id %}
{% set item_type = item.type | default("item") %}
{% if item_type == "group" %}
{% set group_label_id = item.id | default("group-label-" + item_id) %}
<div
role="group"
aria-labelledby="{{ group_label_id }}"
{% if item.attrs %}
{% if item.attrs is defined and item.attrs %}
{% for key, value in item.attrs.items() %}
{{ key }}="{{ value }}"
{% endfor %}
{% endif %}
>
<span role="heading" id="{{ group_label_id }}">{{ item.label | safe }}</span>
{{ render_command_items(item['items'], item_id) if item['items'] }}
<span role="heading" id="{{ group_label_id }}">{{ item.label | default('') | safe }}</span>
{{ render_command_items(item.get('items', []), item_id) if item.get('items') }}
</div>
{% elif item.type == "separator" %}
{% elif item_type == "separator" %}
<hr role="separator" />
{% elif item.type == "item" or not item.type %}
{% if item.url %}
{% elif item_type == "item" %}
{% if item.url is defined and item.url %}
<a
id="{{ item_id }}"
href="{{ item.url }}"
role="menuitem"
{% if item.keywords %}data-keywords="{{ item.keywords }}"{% endif %}
{% if item.disabled %}aria-disabled="true"{% endif %}
{% if item.attrs %}
{% if item.keywords is defined and item.keywords %}data-keywords="{{ item.keywords }}"{% endif %}
{% if item.disabled is defined and item.disabled %}aria-disabled="true"{% endif %}
{% if item.attrs is defined and item.attrs %}
{% for key, value in item.attrs.items() %}
{% if key != "href" %}{{ key }}="{{ value }}"{% endif %}
{% endfor %}
{% endif %}
>
{% if item.icon %}{{ item.icon | safe }}{% endif %}
{{ item.label | safe }}
{% if item.icon is defined and item.icon %}{{ item.icon | safe }}{% endif %}
{{ item.label | default('') | safe }}
</a>
{% else %}
<div
id="{{ item_id }}"
role="menuitem"
{% if item.keywords %}data-keywords="{{ item.keywords }}"{% endif %}
{% if item.disabled %}aria-disabled="true"{% endif %}
{% if item.attrs %}
{% if item.keywords is defined and item.keywords %}data-keywords="{{ item.keywords }}"{% endif %}
{% if item.disabled is defined and item.disabled %}aria-disabled="true"{% endif %}
{% if item.attrs is defined and item.attrs %}
{% for key, value in item.attrs.items() %}
{{ key }}="{{ value }}"
{% endfor %}
{% endif %}
>
{% if item.icon %}{{ item.icon | safe }}{% endif %}
{{ item.label | safe }}
{% if item.icon is defined and item.icon %}{{ item.icon | safe }}{% endif %}
{{ item.label | default('') | safe }}
</div>
{% endif %}
{% endif %}
+10 -5
View File
@@ -6,7 +6,6 @@
@param title {string} [optional] - Title text displayed in the dialog header.
@param description {string} [optional] - Description text displayed below the title.
@param footer {string} [optional] - HTML content for the dialog footer.
@param main_attrs {object} [optional] - Additional HTML attributes for the main container div.
@param trigger_attrs {object} [optional] - Additional HTML attributes for the trigger button.
@param dialog_attrs {object} [optional] - Additional HTML attributes for the dialog content container.
@param header_attrs {object} [optional] - Additional HTML attributes for the dialog header.
@@ -32,6 +31,11 @@
close_on_overlay_click=true
) %}
{% set id = id or ("dialog-" + (range(100000, 999999) | random | string)) %}
{% set dialog_attrs = dialog_attrs or {} %}
{% set trigger_attrs = trigger_attrs or {} %}
{% set header_attrs = header_attrs or {} %}
{% set body_attrs = body_attrs or {} %}
{% set footer_attrs = footer_attrs or {} %}
{% if trigger %}
<button
type="button"
@@ -45,9 +49,10 @@
{% endif %}
<dialog
id="{{ id }}"
class="dialog {{ dialog_attrs.class }}"
aria-labelledby="{{ id }}-title"
class="dialog {{ dialog_attrs.class | default('') }}"
{% if title %}aria-labelledby="{{ id }}-title"{% endif %}
{% if description %}aria-describedby="{{ id }}-description"{% endif %}
{% if open %}open{% endif %}
{% if close_on_overlay_click %}onclick="if (event.target === this) this.close()"{% endif %}
{% for key, value in dialog_attrs.items() %}
{% if key != 'class' %}{{ key }}="{{ value }}"{% endif %}
@@ -60,11 +65,11 @@
{{ key }}="{{ value }}"
{% endfor %}
>
<h2 id="{{ id }}-title">{{ title | safe }}</h2>
{% if title %}<h2 id="{{ id }}-title">{{ title | safe }}</h2>{% endif %}
{% if description %}<p id="{{ id }}-description">{{ description | safe }}</p>{% endif %}
</header>
{% endif %}
{% if caller %}
{% if caller is defined %}
<section
{% for key, value in body_attrs.items() %}
{{ key }}="{{ value }}"
+23 -17
View File
@@ -7,6 +7,7 @@
@param main_attrs {object} [optional] - Additional HTML attributes for the main container div.
@param trigger_attrs {object} [optional] - Additional HTML attributes for the trigger button.
@param popover_attrs {object} [optional] - Additional HTML attributes for the dropdown content div.
@param menu_attrs {object} [optional] - Additional HTML attributes for the menu div.
#}
{% macro dropdown_menu(
trigger,
@@ -18,10 +19,14 @@
menu_attrs={}
) %}
{% set id = id or ("dropdown-menu-" + (range(100000, 999999) | random | string)) %}
{% set main_attrs = main_attrs or {} %}
{% set trigger_attrs = trigger_attrs or {} %}
{% set popover_attrs = popover_attrs or {} %}
{% set menu_attrs = menu_attrs or {} %}
<div
id="{{ id }}"
class="dropdown-menu {{ main_attrs.class }}"
class="dropdown-menu {{ main_attrs.class | default('') }}"
{% for key, value in main_attrs.items() %}
{% if key != 'class' %}{{ key }}="{{ value }}"{% endif %}
{% endfor %}
@@ -57,7 +62,7 @@
{% if items %}
{{ render_dropdown_items(items, id ~ "-items" if id else "items") }}
{% else %}
{{ caller() if caller }}
{{ caller() if caller is defined }}
{% endif %}
</div>
</div>
@@ -74,49 +79,50 @@
{% for item in items %}
{% set item_id = parent_id_prefix ~ "-" ~ loop.index %}
{% if item.type == "group" %}
{% set group_label_id = item.id if item.id else "group-label-" + item_id %}
{% set item_type = item.type | default("item") %}
{% if item_type == "group" %}
{% set group_label_id = item.id | default("group-label-" + item_id) %}
<div
role="group"
aria-labelledby="{{ group_label_id }}"
{% if item.attrs %}
{% if item.attrs is defined and item.attrs %}
{% for key, value in item.attrs.items() %}
{{ key }}="{{ value }}"
{% endfor %}
{% endif %}
>
<div role="heading" id="{{ group_label_id }}">{{ item.label }}</div>
{{ render_dropdown_items(item['items'], item_id) if item['items'] }}
<div role="heading" id="{{ group_label_id }}">{{ item.label | default('') }}</div>
{{ render_dropdown_items(item.get('items', []), item_id) if item.get('items') }}
</div>
{% elif item.type == "separator" %}
{% elif item_type == "separator" %}
<hr role="separator" />
{% elif item.type == "item" or not item.type %}
{% if item.url %}
{% elif item_type == "item" %}
{% if item.url is defined and item.url %}
<a
id="{{ item_id }}"
role="menuitem"
href="{{ item.url }}"
{% if item.attrs %}
{% if item.attrs is defined and item.attrs %}
{% for key, value in item.attrs.items() %}
{% if key != "url" %} {{ key }}="{{ value }}" {% endif %}
{% if key != "href" and key != "url" %} {{ key }}="{{ value }}" {% endif %}
{% endfor %}
{% endif %}
>
{% if item.icon %}{{ item.icon | safe }}{% endif %}
{{ item.label | safe }}
{% if item.icon is defined and item.icon %}{{ item.icon | safe }}{% endif %}
{{ item.label | default('') | safe }}
</a>
{% else %}
<div
id="{{ item_id }}"
role="menuitem"
{% if item.attrs %}
{% if item.attrs is defined and item.attrs %}
{% for key, value in item.attrs.items() %}
{{ key }}="{{ value }}"
{% endfor %}
{% endif %}
>
{% if item.icon %}{{ item.icon | safe }}{% endif %}
{{ item.label | safe }}
{% if item.icon is defined and item.icon %}{{ item.icon | safe }}{% endif %}
{{ item.label | default('') | safe }}
</div>
{% endif %}
{% endif %}
+6 -3
View File
@@ -15,10 +15,13 @@
popover_attrs={}
) %}
{% set id = id or ("popover-" + (range(100000, 999999) | random | string)) %}
{% set main_attrs = main_attrs or {} %}
{% set trigger_attrs = trigger_attrs or {} %}
{% set popover_attrs = popover_attrs or {} %}
<div
id="{{ id }}"
class="popover {{ main_attrs.class }}"
class="popover {{ main_attrs.class | default('') }}"
{% for key, value in main_attrs.items() %}
{% if key != 'class' %}{{ key }}="{{ value }}"{% endif %}
{% endfor %}
@@ -42,7 +45,7 @@
{{ key }}="{{ value }}"
{% endfor %}
>
{{ caller() if caller }}
{{ caller() if caller is defined }}
</div>
</div>
{% endmacro %}
{% endmacro %}
+25 -17
View File
@@ -7,6 +7,7 @@
@param multiple {boolean} [optional] [default=false] - Enables multiple selection mode.
@param placeholder {string} [optional] - Placeholder text shown when no option is selected.
@param close_on_select {boolean} [optional] [default=false] - Closes the popover when selecting an option in multiple mode.
@param format {string} [optional] [default="value"] - Hidden input serialization format: "value" or "object".
@param main_attrs {object} [optional] - Additional HTML attributes for the main container div.
@param trigger_attrs {object} [optional] - Additional HTML attributes for the trigger button.
@param popover_attrs {object} [optional] - Additional HTML attributes for the popover content div.
@@ -29,10 +30,15 @@
input_attrs={}
) %}
{% set id = id or ("select-" + (range(100000, 999999) | random | string)) %}
{% set main_attrs = main_attrs or {} %}
{% set trigger_attrs = trigger_attrs or {} %}
{% set popover_attrs = popover_attrs or {} %}
{% set listbox_attrs = listbox_attrs or {} %}
{% set input_attrs = input_attrs or {} %}
{% if selected is defined and selected is iterable and selected is not string %}
{% if selected is defined and selected is not none and selected is iterable and selected is not string %}
{% set selectedArray = selected %}
{% elif selected is defined %}
{% elif selected is defined and selected is not none %}
{% set selectedArray = [selected] %}
{% else %}
{% set selectedArray = [] %}
@@ -42,8 +48,9 @@
{% if items %}
{% for item in items %}
{% if item.type == "group" %}
{% for sub_item in item['items'] %}
{% set item_type = item.type | default("item") %}
{% if item_type == "group" %}
{% for sub_item in item.get('items', []) %}
{% if not first_option.item %}
{% set first_option.item = sub_item %}
{% endif %}
@@ -81,7 +88,7 @@
<div
id="{{ id }}"
class="select {{ main_attrs.class }}"
class="select {{ main_attrs.class | default('') }}"
{% if format == "object" %}data-format="object"{% endif %}
{% if placeholder %}data-placeholder="{{ placeholder }}"{% endif %}
{% if multiple and close_on_select %}data-close-on-select="true"{% endif %}
@@ -91,7 +98,7 @@
>
<button
type="button"
class="{{ trigger_attrs.class }}"
class="{{ trigger_attrs.class | default('') }}"
id="{{ id }}-trigger"
aria-haspopup="listbox"
aria-expanded="false"
@@ -124,7 +131,7 @@
{% if items %}
{{ render_select_items(items, selectedArray, id ~ "-items" if id else "items") }}
{% else %}
{{ caller() if caller }}
{{ caller() if caller is defined }}
{% endif %}
</div>
</div>
@@ -148,35 +155,36 @@
{% macro render_select_items(items, selectedArray, parent_id_prefix="items") %}
{% for item in items %}
{% set item_id = parent_id_prefix ~ "-" ~ loop.index %}
{% if item.type == "group" %}
{% set group_label_id = item.id if item.id else "group-label-" + item_id %}
{% set item_type = item.type | default("item") %}
{% if item_type == "group" %}
{% set group_label_id = item.id | default("group-label-" + item_id) %}
<div
role="group"
aria-labelledby="{{ group_label_id }}"
{% if item.attrs %}
{% if item.attrs is defined and item.attrs %}
{% for key, value in item.attrs.items() %}
{{ key }}="{{ value }}"
{% endfor %}
{% endif %}
>
<div role="heading" id="{{ group_label_id }}">{{ item.label }}</div>
{{ render_select_items(item['items'], selectedArray, item_id) if item['items'] }}
<div role="heading" id="{{ group_label_id }}">{{ item.label | default('') }}</div>
{{ render_select_items(item.get('items', []), selectedArray, item_id) if item.get('items') }}
</div>
{% elif item.type == "separator" %}
{% elif item_type == "separator" %}
<hr role="separator" />
{% elif item.type == "item" or not item.type %}
{% elif item_type == "item" %}
<div
id="{{ item_id }}"
role="option"
{% if item.value is defined and item.value is not none %}data-value="{{ item.value }}"{% endif %}
{% if item.value in selectedArray %}aria-selected="true"{% endif %}
{% if item.attrs %}
{% if item.value is defined and item.value in selectedArray %}aria-selected="true"{% endif %}
{% if item.attrs is defined and item.attrs %}
{% for key, value in item.attrs.items() %}
{{ key }}="{{ value }}"
{% endfor %}
{% endif %}
>
{{ item.label | safe }}
{{ item.label | default(item.value | default('')) | safe }}
</div>
{% endif %}
{% endfor %}
+26 -21
View File
@@ -26,9 +26,13 @@
content_attrs={},
footer_attrs={}
) %}
{% set main_attrs = main_attrs or {} %}
{% set header_attrs = header_attrs or {} %}
{% set content_attrs = content_attrs or {} %}
{% set footer_attrs = footer_attrs or {} %}
<aside
{% if id %}id="{{ id }}"{% endif %}
class="sidebar {{ main_attrs.class }}"
class="sidebar {{ main_attrs.class | default('') }}"
data-side="{{ side if side else "left" }}"
aria-hidden="{{ "true" if not open else "false" }}"
{{ "inert" if not open }}
@@ -57,7 +61,7 @@
{% if menu %}
{{ render_sidebar_content(menu, id ~ "-content" if id else "content") }}
{% else %}
{{ caller() if caller }}
{{ caller() if caller is defined }}
{% endif %}
</section>
@@ -84,59 +88,60 @@
{% for item in items %}
{% set item_id = parent_id_prefix ~ "-" ~ loop.index %}
{% if item.type == "group" %}
{% set group_label_id = item.id if item.id else "group-label-" + item_id %}
{% set item_type = item.type | default("item") %}
{% if item_type == "group" %}
{% set group_label_id = item.id | default("group-label-" + item_id) %}
<div
role="group"
{% if item.label %}aria-labelledby="{{ group_label_id }}"{% endif %}
{% if item.attrs %}
{% if item.label is defined and item.label %}aria-labelledby="{{ group_label_id }}"{% endif %}
{% if item.attrs is defined and item.attrs %}
{% for key, value in item.attrs.items() %}
{{ key }}="{{ value }}"
{% endfor %}
{% endif %}
>
{% if item.label %}
{% if item.label is defined and item.label %}
<h3 id="{{ group_label_id }}">{{ item.label }}</h3>
{% endif %}
<ul>
{{ render_sidebar_content(item["items"], item_id) if item["items"] }}
{{ render_sidebar_content(item.get("items", []), item_id) if item.get("items") }}
</ul>
</div>
{% elif item.type == "separator" %}
{% elif item_type == "separator" %}
<hr role="separator"/>
{% elif item.type == "submenu" %}
{% elif item_type == "submenu" %}
<li>
<details
id="submenu-{{ item_id }}"
{{ "open" if item.open }}
{% if item.attrs %}
{{ "open" if item.open is defined and item.open }}
{% if item.attrs is defined and item.attrs %}
{% for key, value in item.attrs.items() %}
{% if key != "open" %}{{ key }}="{{ value }}"{% endif %}
{% endfor %}
{% endif %}
>
<summary aria-controls="submenu-{{ item_id }}-content">
{% if item.icon %}{{ item.icon | safe }}{% endif %}
<span>{{ item.label | safe }}</span>
{% if item.icon is defined and item.icon %}{{ item.icon | safe }}{% endif %}
<span>{{ item.label | default('') | safe }}</span>
</summary>
<ul id="submenu-{{ item_id }}-content">
{{ render_sidebar_content(item["items"], item_id) if item["items"] }}
{{ render_sidebar_content(item.get("items", []), item_id) if item.get("items") }}
</ul>
</details>
</li>
{% elif item.type == "item" or not item.type %}
{% elif item_type == "item" %}
<li>
<a
href="{{ item.url }}"
{% if item.current %}aria-current="page"{% endif %}
{% if item.attrs %}
href="{{ item.url | default('#') }}"
{% if item.current is defined and item.current %}aria-current="page"{% endif %}
{% if item.attrs is defined and item.attrs %}
{% for key, value in item.attrs.items() %}
{% if key != "href" and key != "aria-current" %}{{ key }}="{{ value }}"{% endif %}
{% endfor %}
{% endif %}
>
{% if item.icon %}{{ item.icon | safe }}{% endif %}
<span>{{ item.label | safe }}</span>
{% if item.icon is defined and item.icon %}{{ item.icon | safe }}{% endif %}
<span>{{ item.label | default('') | safe }}</span>
</a>
</li>
{% endif %}
+10 -8
View File
@@ -4,7 +4,6 @@
@param id {string} - Unique identifier for the tabs component.
@param tabsets {array} - An array of objects, each representing a tab and its panel.
Each object should have:
- id {string}: Unique identifier prefix for the tab and panel.
- tab {string}: HTML content for the tab button.
- panel {string} [optional]: HTML content for the tab panel.
- tab_attrs {object} [optional]: Additional HTML attributes for the tab button.
@@ -23,9 +22,11 @@
)
%}
{% set id = id or ("tabs-" + (range(100000, 999999) | random | string)) %}
{% set orientation = tablist_attrs['aria-orientation'] or 'horizontal' %}
{% set main_attrs = main_attrs or {} %}
{% set tablist_attrs = tablist_attrs or {} %}
{% set orientation = tablist_attrs.get('aria-orientation', 'horizontal') %}
<div
class="tabs {{ main_attrs.class }}"
class="tabs {{ main_attrs.class | default('') }}"
id="{{ id }}"
{% for key, value in main_attrs.items() %}
{% if key != 'class' %}{{ key }}="{{ value }}"{% endif %}
@@ -39,15 +40,16 @@
{% endfor %}
>
{% for tabset in tabsets %}
{% set tab_attrs = tabset.tab_attrs | default({}) %}
<button
type="button"
role="tab"
id="{{ id }}-tab-{{ loop.index }}"
aria-controls="{{ id }}-panel-{{ loop.index }}"
aria-selected="{{ 'true' if loop.index == default_tab_index else 'false' }}"
tabindex="{{ '0' if loop.index == default_tab_index and not tabset.tab_attrs.disabled and tabset.tab_attrs['aria-disabled'] != 'true' else '-1' }}"
{% if tabset.tab_attrs %}
{% for key, value in tabset.tab_attrs.items() %}
tabindex="{{ '0' if loop.index == default_tab_index and not (tab_attrs.disabled | default(false)) and (tab_attrs['aria-disabled'] | default('false')) != 'true' else '-1' }}"
{% if tab_attrs %}
{% for key, value in tab_attrs.items() %}
{{ key }}="{{ value }}"
{% endfor %}
{% endif %}
@@ -58,7 +60,7 @@
</nav>
{% for tabset in tabsets %}
{% if tabset.panel %}
{% if tabset.panel is defined and tabset.panel %}
<div
role="tabpanel"
id="{{ id }}-panel-{{ loop.index }}"
@@ -66,7 +68,7 @@
tabindex="-1"
aria-selected="{{ 'true' if loop.index == default_tab_index else 'false' }}"
{% if loop.index != default_tab_index %}hidden{% endif %}
{% if tabset.panel_attrs %}
{% if tabset.panel_attrs is defined and tabset.panel_attrs %}
{% for key, value in tabset.panel_attrs.items() %}
{{ key }}="{{ value }}"
{% endfor %}
+46 -24
View File
@@ -13,24 +13,27 @@
toasts=[],
attrs={}
) %}
{% set attrs = attrs or {} %}
<div
id="{{ id }}"
class="toaster {{ attrs.class }}"
class="toaster {{ attrs.class | default('') }}"
{% for key, value in attrs.items() %}
{% if key != 'class' %}{{ key }}="{{ value }}"{% endif %}
{% endfor %}
>
{% for item in toasts %}
{{ toast(
category=item.category,
title=item.title,
description=item.description,
action=item.action,
cancel=item.cancel,
attrs=item.attrs
category=item.category | default("success"),
title=item.title | default(""),
description=item.description | default(""),
action=item.action | default(None),
cancel=item.cancel | default(None),
duration=item.duration | default(None),
icon=item.icon | default(None),
attrs=item.attrs | default({})
) }}
{% endfor %}
{{ caller() if caller }}
{{ caller() if caller is defined }}
</div>
{% endmacro %}
@@ -40,14 +43,16 @@
@param category {string} [optional] [default="success"] - Type of toast ('success', 'error', 'info', 'warning'). Determines icon and ARIA role.
@param title {string} [optional] - The main title text of the toast.
@param description {string} [optional] - The secondary description text.
@param duration {number} [optional] - Timeout in milliseconds. Use -1 to keep the toast open.
@param icon {string} [optional] - Custom icon HTML. Defaults to the category icon.
@param action {object} [optional] - Defines an action button.
- label {string}: Button text.
- onclick {string}: JavaScript code to execute on click.
- url {string}: URL for an anchor link button.
- href {string}: URL for an anchor link button.
@param cancel {object} [optional] - Defines a cancel/dismiss button (similar structure to action).
- label {string}: Button text.
- onclick {string}: JavaScript code to execute on click.
- url {string}: URL for an anchor link button.
- href {string}: URL for an anchor link button.
@param attrs {object} [optional] - Additional HTML attributes for the toast div.
#}
{% macro toast(
@@ -56,20 +61,28 @@
description="",
action=None,
cancel=None,
duration=None,
icon=None,
attrs={}
) %}
{% set attrs = attrs or {} %}
{% set action_href = action.href if action and action.href is defined and action.href else (action.url if action and action.url is defined and action.url else None) %}
{% set cancel_href = cancel.href if cancel and cancel.href is defined and cancel.href else (cancel.url if cancel and cancel.url is defined and cancel.url else None) %}
<div
class="toast {{ attrs.class }}"
class="toast {{ attrs.class | default('') }}"
role="{{ 'alert' if category == 'error' else 'status' }}"
aria-atomic="true"
aria-hidden="false"
{% if category %}data-category="{{ category }}"{% endif %}
{% if duration is not none %}data-duration="{{ duration }}"{% endif %}
{% for key, value in attrs.items() %}
{% if key != 'class' %}{{ key }}="{{ value }}"{% endif %}
{% endfor %}
>
<div class="toast-content">
{% if category in ["error", "success", "info", "warning"] %}
{% if icon %}
{{ icon | safe }}
{% elif category in ["error", "success", "info", "warning"] %}
{% if category == "success" %}
<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/></svg>
{% elif category == "error" %}
@@ -87,31 +100,40 @@
{% if action or cancel %}
<footer>
{% if action %}
{% if action.href %}
{% if action_href %}
<a
href="{{ action.href }}"
href="{{ action_href }}"
class="btn" data-size="sm"
data-toast-action
>{{ action.label }}</a>
>{{ action.label | default('') }}</a>
{% else %}
<button
type="button"
class="btn"
data-size="sm"
data-toast-action
{% if action.onclick %}onclick="{{ action.onclick }}"{% endif %}
>{{ action.label }}</button>
{% if action.onclick is defined and action.onclick %}onclick="{{ action.onclick }}"{% endif %}
>{{ action.label | default('') }}</button>
{% endif %}
{% endif %}
{% if cancel %}
<button
type="button"
class="btn" data-variant="outline" data-size="sm"
data-toast-cancel
{% if cancel.onclick %}onclick="{{ cancel.onclick }}"{% endif %}
>{{ cancel.label }}</button>
{% if cancel_href %}
<a
href="{{ cancel_href }}"
class="btn" data-variant="outline" data-size="sm"
data-toast-cancel
>{{ cancel.label | default('') }}</a>
{% else %}
<button
type="button"
class="btn" data-variant="outline" data-size="sm"
data-toast-cancel
{% if cancel.onclick is defined and cancel.onclick %}onclick="{{ cancel.onclick }}"{% endif %}
>{{ cancel.label | default('') }}</button>
{% endif %}
{% endif %}
</footer>
{% endif %}
</div>
</div>
{% endmacro %}
{% endmacro %}
+3 -3
View File
@@ -6,7 +6,6 @@
@param title {string} [optional] - Title text displayed in the dialog header.
@param description {string} [optional] - Description text displayed below the title.
@param footer {string} [optional] - HTML content for the dialog footer.
@param main_attrs {object} [optional] - Additional HTML attributes for the main container div.
@param trigger_attrs {object} [optional] - Additional HTML attributes for the trigger button.
@param dialog_attrs {object} [optional] - Additional HTML attributes for the dialog content container.
@param header_attrs {object} [optional] - Additional HTML attributes for the dialog header.
@@ -46,8 +45,9 @@
<dialog
id="{{ id }}"
class="dialog {{ dialog_attrs.class }}"
aria-labelledby="{{ id }}-title"
{% if title %}aria-labelledby="{{ id }}-title"{% endif %}
{% if description %}aria-describedby="{{ id }}-description"{% endif %}
{% if open %}open{% endif %}
{% if close_on_overlay_click %}onclick="if (event.target === this) this.close()"{% endif %}
{% for key, value in dialog_attrs %}
{% if key != 'class' %}{{ key }}="{{ value }}"{% endif %}
@@ -60,7 +60,7 @@
{{ key }}="{{ value }}"
{% endfor %}
>
<h2 id="{{ id }}-title">{{ title | safe }}</h2>
{% if title %}<h2 id="{{ id }}-title">{{ title | safe }}</h2>{% endif %}
{% if description %}<p id="{{ id }}-description">{{ description | safe }}</p>{% endif %}
</header>
{% endif %}
+2 -1
View File
@@ -7,6 +7,7 @@
@param main_attrs {object} [optional] - Additional HTML attributes for the main container div.
@param trigger_attrs {object} [optional] - Additional HTML attributes for the trigger button.
@param popover_attrs {object} [optional] - Additional HTML attributes for the dropdown content div.
@param menu_attrs {object} [optional] - Additional HTML attributes for the menu div.
#}
{% macro dropdown_menu(
trigger,
@@ -98,7 +99,7 @@
href="{{ item.url }}"
{% if item.attrs %}
{% for key, value in item.attrs %}
{% if key != "url" %} {{ key }}="{{ value }}" {% endif %}
{% if key != "href" and key != "url" %} {{ key }}="{{ value }}" {% endif %}
{% endfor %}
{% endif %}
>
+2 -2
View File
@@ -31,9 +31,9 @@
) %}
{% set id = id or ("select-" + (range(100000, 999999) | random | string)) %}
{% if selected is defined and selected is iterable and selected is not string %}
{% if selected is defined and selected is not none and selected is iterable and selected is not string %}
{% set selectedArray = selected %}
{% elif selected is defined %}
{% elif selected is defined and selected is not none %}
{% set selectedArray = [selected] %}
{% else %}
{% set selectedArray = [] %}
+1 -1
View File
@@ -7,7 +7,7 @@
@param side {string} [optional] - Side of the sidebar to display.
@param header {string} [optional] - Header content for the sidebar.
@param footer {string} [optional] - Footer content for the sidebar.
@param items {array} [optional] - Array of menu items for the sidebar.
@param menu {array} [optional] - Array of menu items for the sidebar.
@param main_attrs {object} [optional] - Additional HTML attributes for the main container div.
@param header_attrs {object} [optional] - Additional HTML attributes for the header element.
@param content_attrs {object} [optional] - Additional HTML attributes for the content section.
+13 -1
View File
@@ -23,5 +23,17 @@
-%}
{%- set id = id or ("tabs-" + (range(100000, 999999) | random | string)) -%}
{%- set orientation = tablist_attrs['aria-orientation'] or 'horizontal' -%}
<div class="tabs {{ main_attrs.class }}" id="{{ id }}"{% for key, value in main_attrs %}{% if key != 'class' %} {{ key }}="{{ value }}"{% endif %}{% endfor %}><nav role="tablist" aria-orientation="{{ orientation }}"{% for key, value in tablist_attrs %}{% if key != 'aria-orientation' %} {{ key }}="{{ value }}"{% endif %}{% endfor %}>{% for tabset in tabsets %}<button type="button" role="tab" id="{{ id }}-tab-{{ loop.index }}" aria-controls="{{ id }}-panel-{{ loop.index }}" aria-selected="{{ 'true' if loop.index == default_tab_index else 'false' }}" tabindex="{{ '0' if loop.index == default_tab_index and not tabset.tab_attrs.disabled and tabset.tab_attrs['aria-disabled'] != 'true' else '-1' }}"{% if tabset.tab_attrs %}{% for key, value in tabset.tab_attrs %} {{ key }}="{{ value }}"{% endfor %}{% endif %}>{{ tabset.tab | safe }}</button>{% endfor %}</nav>{% for tabset in tabsets %}{% if tabset.panel %}<div role="tabpanel" id="{{ id }}-panel-{{ loop.index }}" aria-labelledby="{{ id }}-tab-{{ loop.index }}" tabindex="-1" aria-selected="{{ 'true' if loop.index == default_tab_index else 'false' }}"{% if loop.index != default_tab_index %} hidden{% endif %}{% if tabset.panel_attrs %}{% for key, value in tabset.panel_attrs %} {{ key }}="{{ value }}"{% endfor %}{% endif %}>{{ tabset.panel | safe }}</div>{% endif %}{% endfor %}</div>
<div class="tabs {{ main_attrs.class }}" id="{{ id }}"{% for key, value in main_attrs %}{% if key != 'class' %} {{ key }}="{{ value }}"{% endif %}{% endfor %}>
<nav role="tablist" aria-orientation="{{ orientation }}"{% for key, value in tablist_attrs %}{% if key != 'aria-orientation' %} {{ key }}="{{ value }}"{% endif %}{% endfor %}>
{% for tabset in tabsets %}
{%- set tab_attrs = tabset.tab_attrs or {} -%}
<button type="button" role="tab" id="{{ id }}-tab-{{ loop.index }}" aria-controls="{{ id }}-panel-{{ loop.index }}" aria-selected="{{ 'true' if loop.index == default_tab_index else 'false' }}" tabindex="{{ '0' if loop.index == default_tab_index and not tab_attrs.disabled and tab_attrs['aria-disabled'] != 'true' else '-1' }}"{% if tab_attrs %}{% for key, value in tab_attrs %} {{ key }}="{{ value }}"{% endfor %}{% endif %}>{{ tabset.tab | safe }}</button>
{% endfor %}
</nav>
{% for tabset in tabsets %}
{% if tabset.panel %}
<div role="tabpanel" id="{{ id }}-panel-{{ loop.index }}" aria-labelledby="{{ id }}-tab-{{ loop.index }}" tabindex="-1" aria-selected="{{ 'true' if loop.index == default_tab_index else 'false' }}"{% if loop.index != default_tab_index %} hidden{% endif %}{% if tabset.panel_attrs %}{% for key, value in tabset.panel_attrs %} {{ key }}="{{ value }}"{% endfor %}{% endif %}>{{ tabset.panel | safe }}</div>
{% endif %}
{% endfor %}
</div>
{%- endmacro -%}
+33 -13
View File
@@ -27,7 +27,9 @@
description=item.description,
action=item.action,
cancel=item.cancel,
attrs=item.attrs
duration=item.duration,
icon=item.icon,
attrs=item.attrs or {}
) }}
{% endfor %}
{{ caller() if caller }}
@@ -40,14 +42,16 @@
@param category {string} [optional] [default="success"] - Type of toast ('success', 'error', 'info', 'warning'). Determines icon and ARIA role.
@param title {string} [optional] - The main title text of the toast.
@param description {string} [optional] - The secondary description text.
@param duration {number} [optional] - Timeout in milliseconds. Use -1 to keep the toast open.
@param icon {string} [optional] - Custom icon HTML. Defaults to the category icon.
@param action {object} [optional] - Defines an action button.
- label {string}: Button text.
- onclick {string}: JavaScript code to execute on click.
- url {string}: URL for an anchor link button.
- href {string}: URL for an anchor link button.
@param cancel {object} [optional] - Defines a cancel/dismiss button (similar structure to action).
- label {string}: Button text.
- onclick {string}: JavaScript code to execute on click.
- url {string}: URL for an anchor link button.
- href {string}: URL for an anchor link button.
@param attrs {object} [optional] - Additional HTML attributes for the toast div.
#}
{% macro toast(
@@ -56,20 +60,27 @@
description="",
action=None,
cancel=None,
duration=None,
icon=None,
attrs={}
) %}
{% set action_href = action.href if action and action.href else (action.url if action and action.url else None) %}
{% set cancel_href = cancel.href if cancel and cancel.href else (cancel.url if cancel and cancel.url else None) %}
<div
class="toast {{ attrs.class }}"
role="{{ 'alert' if category == 'error' else 'status' }}"
aria-atomic="true"
aria-hidden="false"
{% if category %}data-category="{{ category }}"{% endif %}
{% if duration is not none %}data-duration="{{ duration }}"{% endif %}
{% for key, value in attrs %}
{% if key != 'class' %}{{ key }}="{{ value }}"{% endif %}
{% endfor %}
>
<div class="toast-content">
{% if category in ["error", "success", "info", "warning"] %}
{% if icon %}
{{ icon | safe }}
{% elif category in ["error", "success", "info", "warning"] %}
{% if category == "success" %}
<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/></svg>
{% elif category == "error" %}
@@ -87,9 +98,9 @@
{% if action or cancel %}
<footer>
{% if action %}
{% if action.href %}
{% if action_href %}
<a
href="{{ action.href }}"
href="{{ action_href }}"
class="btn" data-size="sm"
data-toast-action
>{{ action.label }}</a>
@@ -97,21 +108,30 @@
<button
type="button"
class="btn"
data-size="sm"
data-toast-action
{% if action.onclick %}onclick="{{ action.onclick }}"{% endif %}
>{{ action.label }}</button>
{% endif %}
{% endif %}
{% if cancel %}
<button
type="button"
class="btn" data-variant="outline" data-size="sm"
data-toast-cancel
{% if cancel.onclick %}onclick="{{ cancel.onclick }}"{% endif %}
>{{ cancel.label }}</button>
{% if cancel_href %}
<a
href="{{ cancel_href }}"
class="btn" data-variant="outline" data-size="sm"
data-toast-cancel
>{{ cancel.label }}</a>
{% else %}
<button
type="button"
class="btn" data-variant="outline" data-size="sm"
data-toast-cancel
{% if cancel.onclick %}onclick="{{ cancel.onclick }}"{% endif %}
>{{ cancel.label }}</button>
{% endif %}
{% endif %}
</footer>
{% endif %}
</div>
</div>
{% endmacro %}
{% endmacro %}