Source code for django_remix_icon.widgets

"""
Django widgets for RemixIcon selection.
"""

import json
from django import forms
from django.urls import reverse
from django.utils.safestring import mark_safe

from django_remix_icon.remix_icons import REMIX_ICONS


[docs]def get_all_icon_names(): """ Get a flat list of all icon names with 'ri-' prefix. """ icon_names = [] for category, icons in REMIX_ICONS.items(): for icon_name in icons.keys(): icon_names.append(f"ri-{icon_name}") return icon_names
[docs]class IconSelectWidget(forms.Select): """ A custom widget for selecting RemixIcons with autocomplete and preview functionality. This widget provides: - Autocomplete functionality for searching icons - Icon preview in the dropdown - Clean integration with Django admin """
[docs] class Media: css = { 'all': ( 'https://cdn.jsdelivr.net/npm/remixicon@4.7.0/fonts/remixicon.css', 'django_remix_icon/css/icon_select.css', ) } js = ('django_remix_icon/js/icon_select.js',)
[docs] def __init__(self, attrs=None): super().__init__(attrs) self.choices = [(icon, icon) for icon in get_all_icon_names()]
[docs] def format_value(self, value): """ Return the value that should be displayed in the widget. """ if value is None: return '' return str(value)
[docs] def render(self, name, value, attrs=None, renderer=None): """ Render the widget as HTML. """ if attrs is None: attrs = {} field_id = attrs.get('id', f'id_{name}') preview_html = '' if value: preview_html = f''' <div class="icon-preview" id="icon-preview-{name}"> <i class="{value}"></i> <span class="icon-name">{value}</span> </div> ''' else: preview_html = f''' <div class="icon-preview" id="icon-preview-{name}" style="display: none;"> <i class=""></i> <span class="icon-name"></span> </div> ''' # Create a hidden input to store the actual value # This is what Django will use to save the data hidden_attrs = { 'type': 'hidden', 'name': name, 'id': field_id, 'value': value or '', } hidden_attrs_str = ' '.join([f'{k}="{v}"' for k, v in hidden_attrs.items()]) # Get the search URL search_url = reverse('django_remix_icon:icon_search') # Combine HTML with autocomplete container html = f''' <div class="remix-icon-widget" data-field-name="{name}"> <input {hidden_attrs_str}> <div class="icon-search-container"> <input type="text" class="icon-search-input" placeholder="Search RemixIcons..." data-target="{field_id}" data-icon-search-url="{search_url}" autocomplete="off" value="{value or ''}"> <div class="icon-search-results" id="search-results-{name}"></div> </div> {preview_html} </div> ''' return mark_safe(html)
[docs]class IconPreviewWidget(forms.TextInput): """ A simpler widget that shows icon preview without autocomplete. Useful for read-only displays or simple forms. """
[docs] class Media: css = { 'all': ( 'https://cdn.jsdelivr.net/npm/remixicon@4.7.0/fonts/remixicon.css', 'django_remix_icon/css/icon_preview.css', ) }
[docs] def render(self, name, value, attrs=None, renderer=None): """ Render the widget with icon preview. """ if attrs is None: attrs = {} attrs['class'] = attrs.get('class', '') + ' remix-icon-preview-input' input_html = super().render(name, value, attrs, renderer) preview_html = '' if value: preview_html = f''' <div class="icon-preview-simple"> <i class="{value}"></i> <span class="icon-name">{value}</span> </div> ''' html = f''' <div class="remix-icon-preview-widget"> {input_html} {preview_html} </div> ''' return mark_safe(html)