django-unfold 0.37.0__py3-none-any.whl → 0.39.0__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. django_unfold-0.39.0.dist-info/METADATA +70 -0
  2. {django_unfold-0.37.0.dist-info → django_unfold-0.39.0.dist-info}/RECORD +59 -57
  3. unfold/admin.py +4 -1
  4. unfold/contrib/filters/templates/unfold/filters/filters_date_range.html +1 -1
  5. unfold/contrib/filters/templates/unfold/filters/filters_datetime_range.html +1 -1
  6. unfold/contrib/filters/templates/unfold/filters/filters_numeric_range.html +1 -1
  7. unfold/contrib/filters/templates/unfold/filters/filters_numeric_single.html +1 -1
  8. unfold/contrib/filters/templates/unfold/filters/filters_numeric_slider.html +4 -4
  9. unfold/contrib/forms/templates/unfold/forms/helpers/toolbar.html +6 -6
  10. unfold/contrib/guardian/templates/unfold/guardian/group_form.html +5 -5
  11. unfold/contrib/guardian/templates/unfold/guardian/user_form.html +5 -5
  12. unfold/contrib/import_export/templates/admin/import_export/change_form.html +1 -1
  13. unfold/contrib/import_export/templates/admin/import_export/import_errors.html +1 -1
  14. unfold/contrib/simple_history/templates/simple_history/object_history.html +1 -1
  15. unfold/contrib/simple_history/templates/simple_history/object_history_list.html +8 -8
  16. unfold/contrib/simple_history/templates/simple_history/submit_line.html +1 -1
  17. unfold/forms.py +5 -1
  18. unfold/settings.py +26 -1
  19. unfold/static/admin/js/admin/RelatedObjectLookups.js +295 -0
  20. unfold/static/unfold/css/styles.css +1 -1
  21. unfold/static/unfold/js/app.js +3 -1
  22. unfold/styles.css +1 -1
  23. unfold/templates/admin/app_list.html +2 -2
  24. unfold/templates/admin/change_form.html +8 -1
  25. unfold/templates/admin/change_list.html +1 -6
  26. unfold/templates/admin/change_list_results.html +2 -2
  27. unfold/templates/admin/delete_confirmation.html +5 -5
  28. unfold/templates/admin/delete_selected_confirmation.html +5 -5
  29. unfold/templates/admin/edit_inline/stacked.html +2 -2
  30. unfold/templates/admin/edit_inline/tabular.html +3 -3
  31. unfold/templates/admin/filter.html +1 -1
  32. unfold/templates/admin/includes/fieldset.html +1 -1
  33. unfold/templates/admin/includes/object_delete_summary.html +1 -1
  34. unfold/templates/admin/login.html +2 -2
  35. unfold/templates/admin/search_form.html +1 -1
  36. unfold/templates/auth/widgets/read_only_password_hash.html +2 -2
  37. unfold/templates/registration/logged_out.html +1 -1
  38. unfold/templates/unfold/change_list_filter.html +19 -3
  39. unfold/templates/unfold/components/button.html +1 -1
  40. unfold/templates/unfold/components/card.html +1 -1
  41. unfold/templates/unfold/components/navigation.html +1 -1
  42. unfold/templates/unfold/components/title.html +1 -1
  43. unfold/templates/unfold/helpers/actions_row.html +1 -1
  44. unfold/templates/unfold/helpers/app_list.html +7 -7
  45. unfold/templates/unfold/helpers/fieldsets_tabs.html +2 -2
  46. unfold/templates/unfold/helpers/form_label.html +1 -1
  47. unfold/templates/unfold/helpers/messages.html +1 -1
  48. unfold/templates/unfold/helpers/navigation.html +1 -1
  49. unfold/templates/unfold/helpers/search.html +1 -1
  50. unfold/templates/unfold/helpers/tab_action.html +1 -1
  51. unfold/templates/unfold/helpers/welcomemsg.html +3 -3
  52. unfold/templates/unfold/layouts/skeleton.html +1 -1
  53. unfold/templates/unfold/widgets/clearable_file_input.html +2 -2
  54. unfold/templates/unfold/widgets/clearable_file_input_small.html +1 -1
  55. unfold/templates/unfold/widgets/url.html +7 -0
  56. unfold/templatetags/unfold_list.py +0 -7
  57. unfold/widgets.py +26 -6
  58. django_unfold-0.37.0.dist-info/METADATA +0 -1455
  59. {django_unfold-0.37.0.dist-info → django_unfold-0.39.0.dist-info}/LICENSE.md +0 -0
  60. {django_unfold-0.37.0.dist-info → django_unfold-0.39.0.dist-info}/WHEEL +0 -0
@@ -33,7 +33,7 @@
33
33
  {% block content %}
34
34
  {% if perms_lacking %}
35
35
  <div class="border border-gray-200 rounded-md shadow-sm dark:border-gray-800">
36
- <p class="font-semibold p-4 text-gray-900 dark:text-gray-100">
36
+ <p class="font-semibold p-4 text-font-important-light dark:text-font-important-dark">
37
37
  {% blocktranslate with escaped_object=object %}Deleting the {{ object_name }} '{{ escaped_object }}' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:{% endblocktranslate %}
38
38
  </p>
39
39
 
@@ -49,7 +49,7 @@
49
49
  </div>
50
50
  {% elif protected %}
51
51
  <div class="border border-gray-200 rounded-md shadow-sm dark:border-gray-800">
52
- <p class="font-semibold p-4 text-gray-900 dark:text-gray-100">
52
+ <p class="font-semibold p-4 text-font-important-light dark:text-font-important-dark">
53
53
  {% blocktranslate with escaped_object=object %}Deleting the {{ object_name }} '{{ escaped_object }}' would require deleting the following protected related objects:{% endblocktranslate %}
54
54
  </p>
55
55
 
@@ -65,14 +65,14 @@
65
65
  </div>
66
66
  {% else %}
67
67
  <div class="border border-gray-200 rounded-md shadow-sm dark:border-gray-800">
68
- <p class="font-semibold p-4 text-gray-900 dark:text-gray-100">
68
+ <p class="font-semibold p-4 text-font-important-light dark:text-font-important-dark">
69
69
  {% blocktranslate with escaped_object=object %}Are you sure you want to delete the {{ object_name }} "{{ escaped_object }}"? All of the following related items will be deleted:{% endblocktranslate %}
70
70
  </p>
71
71
 
72
72
  {% include "admin/includes/object_delete_summary.html" %}
73
73
 
74
74
  <div class="border-gray-200 border-t p-4 dark:border-gray-800">
75
- <h2 class="font-semibold mb-2 text-gray-900 dark:text-gray-100">
75
+ <h2 class="font-semibold mb-2 text-font-important-light dark:text-font-important-dark">
76
76
  {% translate "Objects" %}
77
77
  </h2>
78
78
 
@@ -96,7 +96,7 @@
96
96
  {% endif %}
97
97
 
98
98
 
99
- <a href="#" class="border cancel-link font-medium hidden mb-3 px-3 py-2 rounded-md w-full hover:bg-gray-50 lg:block lg:mb-0 lg:mr-3 lg:w-auto dark:border-gray-700 dark:text-gray-300 dark:hover:text-gray-200 dark:hover:bg-gray-900">
99
+ <a href="#" class="border cancel-link font-medium hidden mb-3 px-3 py-2 rounded-md w-full hover:bg-gray-50 lg:block lg:mb-0 lg:mr-3 lg:w-auto dark:border-gray-700 dark:text-font-default-dark dark:hover:text-gray-200 dark:hover:bg-gray-900">
100
100
  {% translate "No, take me back" %}
101
101
  </a>
102
102
 
@@ -33,7 +33,7 @@
33
33
 
34
34
  {% block content %}
35
35
  {% if perms_lacking %}
36
- <p class="font-semibold p-4 text-gray-900 dark:text-gray-100">
36
+ <p class="font-semibold p-4 text-font-important-light dark:text-font-important-dark">
37
37
  {% blocktranslate %}Deleting the selected {{ objects_name }} would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:{% endblocktranslate %}
38
38
  </p>
39
39
 
@@ -46,7 +46,7 @@
46
46
  </div>
47
47
  {% elif protected %}
48
48
  <div class="border border-gray-200 rounded-md shadow-sm dark:border-gray-800">
49
- <p class="font-semibold p-4 text-gray-900 dark:text-gray-100">
49
+ <p class="font-semibold p-4 text-font-important-light dark:text-font-important-dark">
50
50
  {% blocktranslate %}Deleting the selected {{ objects_name }} would require deleting the following protected related objects:{% endblocktranslate %}
51
51
  </p>
52
52
 
@@ -60,14 +60,14 @@
60
60
  </div>
61
61
  {% else %}
62
62
  <div class="border border-gray-200 rounded-md shadow-sm dark:border-gray-800">
63
- <p class="font-semibold p-4 text-gray-900 dark:text-gray-100">
63
+ <p class="font-semibold p-4 text-font-important-light dark:text-font-important-dark">
64
64
  {% blocktranslate %}Are you sure you want to delete the selected {{ objects_name }}? All of the following objects and their related items will be deleted:{% endblocktranslate %}
65
65
  </p>
66
66
 
67
67
  {% include "admin/includes/object_delete_summary.html" %}
68
68
 
69
69
  <div class="border-t border-gray-200 p-4 dark:border-gray-800">
70
- <h2 class="font-semibold mb-2 text-gray-900 dark:text-gray-100">
70
+ <h2 class="font-semibold mb-2 text-font-important-light dark:text-font-important-dark">
71
71
  {% translate "Objects" %}
72
72
  </h2>
73
73
 
@@ -89,7 +89,7 @@
89
89
  <input type="hidden" name="action" value="delete_selected">
90
90
  <input type="hidden" name="post" value="yes">
91
91
 
92
- <a href="#" class="border cancel-link font-medium hidden mb-3 px-3 py-2 rounded-md transition-all w-full hover:bg-gray-50 lg:block lg:mb-0 lg:mr-3 lg:w-auto dark:border-gray-700 dark:text-gray-300 dark:hover:text-gray-200 dark:hover:bg-gray-900">
92
+ <a href="#" class="border cancel-link font-medium hidden mb-3 px-3 py-2 rounded-md transition-all w-full hover:bg-gray-50 lg:block lg:mb-0 lg:mr-3 lg:w-auto dark:border-gray-700 dark:text-font-default-dark dark:hover:text-gray-200 dark:hover:bg-gray-900">
93
93
  {% translate "No, take me back" %}
94
94
  </a>
95
95
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  <div class="js-inline-admin-formset inline-group" id="{{ inline_admin_formset.formset.prefix }}-group" data-inline-type="stacked" data-inline-formset="{{ inline_admin_formset.inline_formset_data }}" {% if inline_admin_formset.opts.tab %}x-show="activeTab == '{{ inline_admin_formset.opts.verbose_name|slugify }}'"{% else %}x-show="activeTab == 'general'"{% endif %}>
4
4
  <fieldset class="module {{ inline_admin_formset.classes }}">
5
- <h2 class="bg-gray-100 border border-transparent font-semibold mb-6 px-4 py-3 rounded-md text-gray-900 text-sm lg:-mx-4 dark:bg-white/[.02] dark:border dark:border-gray-800 dark:text-gray-200 {% if inline_admin_formset.opts.tab %}hidden{% endif %}">
5
+ <h2 class="bg-gray-100 border border-transparent font-semibold mb-6 px-4 py-3 rounded-md text-font-important-light text-sm lg:-mx-4 dark:bg-white/[.02] dark:border dark:border-gray-800 dark:text-font-important-dark {% if inline_admin_formset.opts.tab %}hidden{% endif %}">
6
6
  {% if inline_admin_formset.formset.max_num == 1 %}
7
7
  {{ inline_admin_formset.opts.verbose_name|capfirst }}
8
8
  {% else %}
@@ -29,7 +29,7 @@
29
29
  {{ inline_admin_formset.opts.verbose_name|capfirst }}:
30
30
  </span>
31
31
 
32
- <span class="inline_label font-semibold text-gray-900 dark:text-gray-200">
32
+ <span class="inline_label font-semibold text-font-important-light dark:text-font-important-dark">
33
33
  {% if inline_admin_form.original and inline_admin_form.model_admin.show_change_link and inline_admin_form.model_admin.has_registered_model %}
34
34
  <a href="{% url inline_admin_form.model_admin.opts|admin_urlname:'change' inline_admin_form.original.pk|admin_urlquote %}" class="{% if inline_admin_formset.has_change_permission %}inlinechangelink{% else %}inlineviewlink{% endif %} font-medium text-primary-600 dark:text-primary-500">
35
35
  {{ inline_admin_form.original }}
@@ -5,7 +5,7 @@
5
5
  {{ inline_admin_formset.formset.management_form }}
6
6
 
7
7
  <fieldset class="module {{ inline_admin_formset.classes }} min-w-0">
8
- <h2 class="bg-gray-100 border border-transparent font-semibold mb-6 px-4 py-3 rounded-md text-gray-900 text-sm lg:-mx-4 dark:bg-white/[.02] dark:border dark:border-gray-800 dark:text-gray-200 {% if inline_admin_formset.opts.tab %}hidden{% endif %}">
8
+ <h2 class="bg-gray-100 border border-transparent font-semibold mb-6 px-4 py-3 rounded-md text-font-important-light text-sm lg:-mx-4 dark:bg-white/[.02] dark:border dark:border-gray-800 dark:text-font-important-dark {% if inline_admin_formset.opts.tab %}hidden{% endif %}">
9
9
  {% if inline_admin_formset.formset.max_num == 1 %}
10
10
  {{ inline_admin_formset.opts.verbose_name|capfirst }}
11
11
  {% else %}
@@ -27,7 +27,7 @@
27
27
  <tr>
28
28
  {% for field in inline_admin_formset.fields %}
29
29
  {% if not field.widget.is_hidden %}
30
- <th class="column-{{ field.name }}{% if field.required %} required{% endif %} align-middle border-b border-gray-200 font-medium px-3 py-2 text-left text-gray-900 text-sm whitespace-nowrap dark:text-gray-200 dark:border-gray-800">
30
+ <th class="column-{{ field.name }}{% if field.required %} required{% endif %} align-middle border-b border-gray-200 font-semibold px-3 py-2 text-left text-font-important-light text-sm whitespace-nowrap dark:text-font-important-dark dark:border-gray-800">
31
31
  <span class="flex flex-row items-center">
32
32
  {{ field.label|capfirst }}
33
33
 
@@ -40,7 +40,7 @@
40
40
  {% endfor %}
41
41
 
42
42
  {% if inline_admin_formset.formset.can_delete and inline_admin_formset.has_delete_permission %}
43
- <th class="align-middle border-b border-gray-200 font-medium px-3 py-2 text-left text-gray-900 text-sm whitespace-nowrap lg:w-px dark:border-gray-800 dark:text-gray-200">
43
+ <th class="align-middle border-b border-gray-200 font-semibold px-3 py-2 text-left text-font-important-light text-sm whitespace-nowrap lg:w-px dark:border-gray-800 dark:text-font-important-dark">
44
44
  {% translate "Delete?" %}
45
45
  </th>
46
46
  {% endif %}
@@ -1,7 +1,7 @@
1
1
  {% load i18n unfold %}
2
2
 
3
3
  <div class="mb-6">
4
- <h3 class="font-semibold mb-2 text-gray-900 dark:text-gray-100">
4
+ <h3 class="font-semibold mb-2 text-font-important-light dark:text-font-important-dark">
5
5
  {% blocktranslate with filter_title=title %} By {{ filter_title }} {% endblocktranslate %}
6
6
  </h3>
7
7
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  <fieldset class="module{% if fieldset.classes %} {{ fieldset.classes }}{% endif %}" {% if stacked != 1 %}x-show="activeTab == 'general'"{% endif %}>
4
4
  {% if fieldset.name and "tab" not in fieldset.classes %}
5
- <h2 class="bg-gray-100 border border-transparent font-semibold mb-6 px-4 py-3 rounded-md text-gray-700 text-sm lg:-mx-4 dark:bg-white/[.02] dark:border dark:border-gray-800 dark:text-gray-200">
5
+ <h2 class="bg-gray-100 border border-transparent font-semibold mb-6 px-4 py-3 rounded-md text-font-important-light text-sm lg:-mx-4 dark:bg-white/[.02] dark:border dark:border-gray-800 dark:text-font-important-dark">
6
6
  {{ fieldset.name }}
7
7
  </h2>
8
8
  {% endif %}
@@ -1,7 +1,7 @@
1
1
  {% load i18n %}
2
2
 
3
3
  <div class="border-gray-200 border-t p-4 dark:border-gray-800">
4
- <h2 class="font-semibold mb-2 text-gray-900 dark:text-gray-100">
4
+ <h2 class="font-semibold mb-2 text-font-important-light dark:text-font-important-dark">
5
5
  {% translate "Summary" %}
6
6
  </h2>
7
7
 
@@ -28,7 +28,7 @@
28
28
  <div class="flex flex-grow items-center justify-center mx-auto px-4 relative">
29
29
  <div class="w-full sm:w-96">
30
30
  <h1 class="font-semibold mb-10">
31
- <span class="block text-gray-700 dark:text-gray-200">{% trans 'Welcome back to' %}</span>
31
+ <span class="block text-font-important-light dark:text-font-important-dark">{% trans 'Welcome back to' %}</span>
32
32
  <span class="block text-primary-600 text-xl dark:text-primary-500">{{ site_title }}</span>
33
33
  </h1>
34
34
 
@@ -66,7 +66,7 @@
66
66
 
67
67
  {% if password_reset_url %}
68
68
  <div class="password-reset-link">
69
- <a href="{{ password_reset_url }}" class="border font-medium hidden mt-4 px-3 py-2 rounded-md text-center text-sm text-gray-500 transition-all w-full hover:bg-gray-50 lg:block lg:w-auto dark:border-gray-700 dark:text-gray-300 dark:hover:text-gray-200 dark:hover:bg-gray-900">
69
+ <a href="{{ password_reset_url }}" class="border font-medium hidden mt-4 px-3 py-2 rounded-md text-center text-sm text-gray-500 transition-all w-full hover:bg-gray-50 lg:block lg:w-auto dark:border-gray-700 dark:text-font-default-dark dark:hover:text-gray-200 dark:hover:bg-gray-900">
70
70
  {% translate 'Forgotten your password or username?' %}
71
71
  </a>
72
72
  </div>
@@ -3,7 +3,7 @@
3
3
  {% if cl.search_fields %}
4
4
  <div id="toolbar">
5
5
  <div class="bg-white border flex rounded-md overflow-hidden shadow-sm lg:w-64 focus-within:ring focus-within:ring-primary-300 focus-within:border-primary-600 dark:bg-gray-900 dark:border-gray-700 dark:focus-within:border-primary-600 dark:focus-within:ring-primary-700 dark:focus-within:ring-opacity-50">
6
- <input class="font-medium grow min-w-0 h-9 px-3 text-gray-500 text-sm focus:outline-none dark:bg-gray-900 dark:text-gray-300 placeholder-shown:truncate" type="text" name="{{ search_var }}" value="{{ cl.query }}" id="searchbar" placeholder="{% if cl.search_help_text %}{{ cl.search_help_text }}{% else %}{% trans "Type to search" %}{% endif %}" />
6
+ <input class="font-medium grow min-w-0 h-9 px-3 text-font-default-light text-sm focus:outline-none dark:bg-gray-900 dark:text-font-default-dark placeholder-shown:truncate" type="text" name="{{ search_var }}" value="{{ cl.query }}" id="searchbar" placeholder="{% if cl.search_help_text %}{{ cl.search_help_text }}{% else %}{% trans "Type to search" %}{% endif %}" />
7
7
 
8
8
  <button type="submit" class="flex items-center px-2 focus:outline-none" id="searchbar-submit">
9
9
  <span class="material-symbols-outlined md-18 text-gray-400 dark:text-gray-500">search</span>
@@ -1,8 +1,8 @@
1
1
  <div class="table table-fixed w-full">
2
- <div class="readonly bg-gray-50 border font-medium max-w-2xl px-3 py-2 rounded-md shadow-sm text-gray-500 text-sm dark:bg-gray-900 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-300{% if summary|length > 1 %} text-ellipsis overflow-hidden whitespace-nowrap w-full{% endif %}" {% include 'django/forms/widgets/attrs.html' %}>
2
+ <div class="readonly bg-gray-50 border font-medium max-w-2xl px-3 py-2 rounded-md shadow-sm dark:bg-white/[.02] dark:border-gray-700 {% if summary|length > 1 %} text-ellipsis overflow-hidden whitespace-nowrap w-full{% endif %}" {% include 'django/forms/widgets/attrs.html' %}>
3
3
  {% if summary|length > 1 %}
4
4
  {% for entry in summary %}
5
- <strong class="font-semibold text-gray-900 dark:text-gray-200">{{ entry.label }}</strong>{% if entry.value %}: {{ entry.value }}{% endif %}
5
+ <strong class="font-semibold text-font-important-light dark:text-font-important-dark">{{ entry.label }}</strong>{% if entry.value %}: {{ entry.value }}{% endif %}
6
6
  {% endfor %}
7
7
  {% else %}
8
8
  {% for entry in summary %}
@@ -12,7 +12,7 @@
12
12
  </span>
13
13
  </h1>
14
14
 
15
- <p class="mb-10 text-gray-500 dark:text-gray-300">
15
+ <p class="mb-10">
16
16
  {% translate "Thanks for spending some quality time with the web site today." %}
17
17
  </p>
18
18
 
@@ -5,12 +5,28 @@
5
5
 
6
6
  <div class="bg-white flex mx-4 my-4 overflow-hidden rounded shadow-sm w-96 dark:bg-gray-800" x-on:click.outside="filterOpen = false">
7
7
  <div class="flex-grow h-full overflow-auto relative">
8
- <h3 class="border-b flex font-semibold mb-6 px-6 py-4 text-gray-900 text-sm dark:text-gray-100 dark:border-gray-700">
9
- {% trans "Filter results" %}
8
+ <h3 class="border-b flex font-semibold mb-6 px-6 py-4 text-font-important-light text-sm dark:text-font-important-dark dark:border-gray-700">
9
+ {% trans "Filter" %}
10
+
11
+ {% if cl.is_facets_optional %}
12
+ <span id="changelist-filter-extra-actions" class="font-normal ml-3 text-primary-600 text-sm dark:text-primary-500">
13
+ {% if cl.is_facets_optional %}
14
+ {% if cl.add_facets %}
15
+ <a href="{{ cl.remove_facet_link }}" class="hidelink">
16
+ {% trans "Hide counts" %}
17
+ </a>
18
+ {% else %}
19
+ <a href="{{ cl.add_facet_link }}" class="viewlink">
20
+ {% trans "Show counts" %}
21
+ </a>
22
+ {% endif %}
23
+ {% endif %}
24
+ </span>
25
+ {% endif %}
10
26
 
11
27
  {% if cl.has_active_filters %}
12
28
  <a href="{{ cl.clear_all_filters_qs }}" class="font-normal ml-3 text-sm text-red-600 dark:text-red-500">
13
- {% translate "Clear all filters" %}
29
+ {% trans "Clear all filters" %}
14
30
  </a>
15
31
  {% endif %}
16
32
 
@@ -1,3 +1,3 @@
1
- <button {% if submit %}type="submit"{% endif%} class="bg-primary-600 border border-transparent font-medium px-3 py-2 rounded-md text-sm text-white">
1
+ <button {% if submit %}type="submit"{% endif%} {% if name %}name="{{ name }}"{% endif %} class="bg-primary-600 border border-transparent font-medium px-3 py-2 rounded-md text-sm text-white">
2
2
  {{ children }}
3
3
  </button>
@@ -1,6 +1,6 @@
1
1
  <div class="border flex flex-col flex-grow overflow-hidden p-6 relative rounded-md shadow-sm dark:border-gray-800{% if class %} {{ class }}{% endif %}">
2
2
  {% if title %}
3
- <h2 class="border-b font-semibold mb-6 -mt-2 -mx-6 pb-4 px-6 text-sm text-gray-700 dark:text-gray-200 dark:border-gray-800">
3
+ <h2 class="border-b font-semibold mb-6 -mt-2 -mx-6 pb-4 px-6 text-font-important-light dark:text-font-important-dark dark:border-gray-800">
4
4
  {{ title }}
5
5
  </h2>
6
6
  {% endif %}
@@ -1,7 +1,7 @@
1
1
  {% if items %}
2
2
  <nav class="bg-gray-100 flex gap-2 mb-8 p-1 rounded text-sm dark:bg-white/[.04]{% if class %} {{ class }}{% endif %}">
3
3
  {% for item in items %}
4
- <a href="{{ item.link }}" class="flex flex-row font-medium items-center px-2.5 py-1 rounded {% if item.active %} bg-white shadow-sm text-gray-700 hover:bg-white dark:bg-gray-900 dark:hover:bg-gray-900 dark:text-white{% else %} text-gray-400 hover:bg-gray-700/[.04] hover:text-gray-700 dark:hover:bg-white/[.04] dark:hover:text-white{% endif %}">
4
+ <a href="{{ item.link }}" class="flex flex-row font-medium items-center px-2.5 py-1 rounded {% if item.active %} bg-white shadow-sm text-font-important-light hover:bg-white dark:bg-gray-900 dark:hover:bg-gray-900 dark:text-font-important-dark{% else %}text-font-subtle-light dark:text-font-subtle-dark hover:bg-gray-700/[.04] dark:hover:bg-white/[.04]{% endif %}">
5
5
  {% if item.icon %}
6
6
  <span class="material-symbols-outlined{% if item.title %} mr-2{% endif %}">{{ item.icon }}</span>
7
7
  {% endif %}
@@ -1,3 +1,3 @@
1
- <div class="font-medium text-2xl text-gray-900 dark:text-gray-100{% if class %} {{ class }}{% endif %}">
1
+ <div class="font-semibold text-2xl text-font-important-light tracking-tight dark:text-font-important-dark{% if class %} {{ class }}{% endif %}">
2
2
  {{ children }}
3
3
  </div>
@@ -4,7 +4,7 @@
4
4
  <td data-label="{% trans "More actions" %}" class="field-actions_holder align-middle flex border-t border-gray-200 font-normal px-3 py-2 text-left text-sm before:block before:capitalize before:content-[attr(data-label)] before:mr-auto before:text-gray-500 dark:before:text-gray-300 lg:before:hidden lg:py-3 lg:table-cell dark:border-gray-800 lg:w-px">
5
5
  {% with action_id=instance_pk|cut:"-" %}
6
6
  <div class="group leading-none relative" x-data="{ openActionsId{{ action_id }}: false }">
7
- <span x-ref="rowDropdown{{ action_id }}" class="cursor-pointer flex h-7 material-symbols-outlined md-18 -my-1 !leading-7 rounded text-center text-gray-400 w-7 group-hover:bg-gray-100 group-hover:text-gray-700 dark:text-gray-300 group-hover:dark:bg-gray-800 group-hover:dark:text-white" @click="openActionsId{{ action_id }} = !openActionsId{{ action_id }}">
7
+ <span x-ref="rowDropdown{{ action_id }}" class="cursor-pointer flex h-7 material-symbols-outlined md-18 -my-1 !leading-7 rounded text-center text-gray-400 w-7 group-hover:bg-gray-100 group-hover:text-gray-700 dark:text-font-default-dark group-hover:dark:bg-gray-800 group-hover:dark:text-white" @click="openActionsId{{ action_id }} = !openActionsId{{ action_id }}">
8
8
  more_horiz
9
9
  </span>
10
10
 
@@ -6,13 +6,13 @@
6
6
  {% if group.items %}
7
7
  {% has_nav_item_active group.items as has_active %}
8
8
 
9
- <div class="mb-3" {% if group.collapsible %}x-data="{navigationOpen: {% if has_active %}true{% else %}false{% endif %}}"{% endif %}>
9
+ <div class="hidden mb-3 has-[ol]:has-[li]:block" {% if group.collapsible %}x-data="{navigationOpen: {% if has_active %}true{% else %}false{% endif %}}"{% endif %}>
10
10
  {% if group.separator %}
11
11
  <hr class="border-t border-gray-200 mx-6 my-2 dark:border-gray-800" />
12
12
  {% endif %}
13
13
 
14
14
  {% if group.title %}
15
- <h2 class="font-semibold flex flex-row items-center mb-1 mx-3 py-1.5 px-3 select-none text-gray-900 text-sm dark:text-gray-100 {% if group.collapsible %}cursor-pointer{% endif %}" {% if group.collapsible %}x-on:click="navigationOpen = !navigationOpen"{% endif %}>
15
+ <h2 class="font-semibold flex flex-row items-center mb-1 mx-3 py-1.5 px-3 select-none text-font-important-light text-sm dark:text-font-important-dark {% if group.collapsible %}cursor-pointer{% endif %}" {% if group.collapsible %}x-on:click="navigationOpen = !navigationOpen"{% endif %}>
16
16
  {{ group.title }}
17
17
 
18
18
  {% if group.collapsible %}
@@ -27,7 +27,7 @@
27
27
  {% for item in group.items %}
28
28
  {% if item.has_permission %}
29
29
  <li>
30
- <a href="{% if item.link_callback %}{{ item.link_callback }}{% else %}{{ item.link }}{% endif %}" class="flex h-11 items-center -mx-3 px-3 py-2 rounded-md {% if item.active %}bg-gray-100 font-semibold text-primary-600 dark:bg-white/[.06] dark:text-primary-500{% else %} hover:text-gray-700 hover:dark:text-gray-200{% endif %}">
30
+ <a href="{% if item.link_callback %}{{ item.link_callback }}{% else %}{{ item.link }}{% endif %}" class="flex h-11 items-center -mx-3 px-3 py-2 rounded-md {% if item.active %}bg-gray-100 font-semibold text-primary-600 dark:bg-white/[.06] dark:text-primary-500{% endif %}">
31
31
  {% if item.icon %}
32
32
  <span class="material-symbols-outlined md-18 mr-3 w-4.5">
33
33
  {{ item.icon }}
@@ -52,14 +52,14 @@
52
52
  {% endif %}
53
53
  {% endfor %}
54
54
  </ol>
55
+ </div>
55
56
  {% endif %}
56
- </div>
57
57
  {% endfor %}
58
58
  </div>
59
59
 
60
60
  {% if sidebar_show_all_applications %}
61
61
  <div class="mt-auto" x-data="{ openAllApplications: false }">
62
- <a class="cursor-pointer flex items-center px-6 py-3 text-sm hover:text-gray-700 dark:text-gray-300 hover:dark:text-gray-200" x-on:click="openAllApplications = !openAllApplications">
62
+ <a class="cursor-pointer flex items-center px-6 py-3 text-sm dark:text-font-default-dark" x-on:click="openAllApplications = !openAllApplications">
63
63
  <span class="material-symbols-outlined md-18 mr-3">
64
64
  apps
65
65
  </span>
@@ -75,14 +75,14 @@
75
75
  <div class="bg-white flex flex-col h-full overflow-x-hidden overflow-y-auto py-5 px-8 relative text-sm w-80 z-20 dark:bg-gray-900 dark:border-r dark:border-gray-800" x-on:click.outside="openAllApplications = false" x-on:keydown.escape.window="openAllApplications = false">
76
76
  {% for app in app_list %}
77
77
  <div class="mb-6 last:mb-0">
78
- <h2 class="mb-4 font-semibold text-gray-900 truncate dark:text-gray-100">
78
+ <h2 class="mb-4 font-semibold text-font-important-light truncate dark:text-font-important-dark">
79
79
  {{ app.name }}
80
80
  </h2>
81
81
 
82
82
  <ul>
83
83
  {% for model in app.models %}
84
84
  <li class="block mb-4 last:mb-0">
85
- <a href="{{ model.admin_url }}" class="block truncate hover:text-gray-700 dark:hover:text-gray-200">
85
+ <a href="{{ model.admin_url }}" class="block truncate">
86
86
  {{ model.name }}
87
87
  </a>
88
88
  </li>
@@ -3,12 +3,12 @@
3
3
  {% with tabs=adminform|tabs %}
4
4
  {% if tabs %}
5
5
  <div x-data="{openTab: null}" x-show="activeTab == 'general'">
6
- <ul class="bg-gray-100 border border-transparent flex gap-10 mb-6 px-4 py-3 rounded-md text-gray-500 text-sm lg:-mx-4 dark:bg-white/[.02] dark:border dark:border-gray-800 dark:text-gray-300">
6
+ <ul class="bg-gray-100 border border-transparent flex gap-10 mb-6 px-4 py-3 rounded-md text-font-default-light text-sm lg:-mx-4 dark:bg-white/[.02] dark:border dark:border-gray-800 dark:text-font-default-dark">
7
7
  {% for fieldset in tabs %}
8
8
  <li>
9
9
  <a class="cursor-pointer font-semibold hover:text-gray-700 dark:hover:text-white"
10
10
  x-on:click="openTab = '{{ forloop.counter0 }}-{{ fieldset.name|slugify }}'"
11
- x-bind:class="openTab == '{{ forloop.counter0 }}-{{ fieldset.name|slugify }}'{% if forloop.first %} || openTab == null{% endif %} ? 'text-gray-700 dark:text-white' : ''">
11
+ x-bind:class="openTab == '{{ forloop.counter0 }}-{{ fieldset.name|slugify }}'{% if forloop.first %} || openTab == null{% endif %} ? 'text-font-important-light dark:text-font-important-dark' : ''">
12
12
  {{ fieldset.name }}
13
13
  </a>
14
14
  </li>
@@ -1,4 +1,4 @@
1
- <label for="{{ field.id_for_label }}" class="block text-gray-900 text-sm dark:text-gray-200{% if field.field.widget.input_type == "checkbox" %}{% else %} font-medium mb-2{% endif %}">
1
+ <label for="{{ field.id_for_label }}" class="block text-font-important-light dark:text-font-important-dark{% if field.field.widget.input_type == "checkbox" %}{% else %} font-medium mb-2{% endif %}">
2
2
  {{ field.label }}
3
3
 
4
4
  {% if field.field.required %}
@@ -1,7 +1,7 @@
1
1
  {% if messages %}
2
2
  <ul>
3
3
  {% for message in messages %}
4
- <li class="mb-3 px-3 py-3 rounded-md text-sm last:mb-8
4
+ <li class="{{ message.tags }} mb-3 px-3 py-3 rounded-md text-sm last:mb-8
5
5
  {% if message.tags == 'success' %}
6
6
  bg-green-100 text-green-700 dark:bg-green-500/20 dark:text-green-400
7
7
  {% elif message.tags == 'warning' %}
@@ -4,7 +4,7 @@
4
4
  <nav id="nav-sidebar" class="bg-gray-50 border-r border-gray-200 bottom-0 fixed max-h-screen top-0 transition-width w-sidebar dark:bg-gray-900 dark:border-gray-800">
5
5
  <div class="flex flex-col min-h-screen min-w-sidebar dark:bg-gray-950/20">
6
6
  <div class="border-b border-gray-200 mb-5 py-3 dark:border-gray-800">
7
- <div class="flex font-medium h-10 items-center px-6 text-gray-900 tracking-tight dark:text-gray-100 xl:text-base">
7
+ <div class="flex font-semibold h-10 items-center px-6 text-font-important-light tracking-tight dark:text-font-important-dark xl:text-base">
8
8
  {% if site_logo %}
9
9
  {% include "unfold/helpers/site_logo.html" %}
10
10
  {% elif branding %}
@@ -14,7 +14,7 @@
14
14
  hx-trigger="keyup changed delay:500ms, search"
15
15
  hx-target="#search-results"
16
16
  hx-indicator=".htmx-indicator"
17
- class="flex-grow font-medium overflow-hidden pl-2 pr-3 py-2 text-gray-500 text-sm focus:outline-none dark:bg-gray-900 dark:text-gray-300"
17
+ class="flex-grow font-medium overflow-hidden pl-2 pr-3 py-2 text-font-default-light text-sm focus:outline-none dark:bg-gray-900 dark:text-font-default-dark"
18
18
  placeholder="{% translate 'Search apps and models...' %}" aria-label="{% translate 'Filter navigation items' %}" />
19
19
  <div class="absolute opacity-0 htmx-indicator mt-0.5 right-2 top-2">
20
20
  <span class="animate-spin material-symbols-outlined md-18 text-gray-300">sync</span>
@@ -1,5 +1,5 @@
1
1
  <li class="border-b flex-grow text-center md:border-b-0 md:border-r last:border-0 dark:border-gray-800">
2
- <a href="{{ link }}" class="block px-4 py-2 text-left whitespace-nowrap hover:text-gray-700 hover:dark:text-gray-200"{% if blank %} target="_blank"{% endif %} {% include "unfold/helpers/attrs.html" with attrs=action.attrs %}>
2
+ <a href="{{ link }}" class="block px-4 py-2 text-left whitespace-nowrap"{% if blank %} target="_blank"{% endif %} {% include "unfold/helpers/attrs.html" with attrs=action.attrs %}>
3
3
  {{ title }}
4
4
  </a>
5
5
  </li>
@@ -1,9 +1,9 @@
1
1
  {% load i18n %}
2
2
 
3
- <div class="flex-grow font-medium min-w-0 mr-3">
4
- <h1 class="overflow-hidden text-ellipsis text-sm whitespace-nowrap xl:text-base text-gray-700 dark:text-gray-200">
3
+ <div class="flex-grow font-semibold min-w-0 mr-3">
4
+ <h1 class="overflow-hidden text-ellipsis text-sm whitespace-nowrap xl:text-base text-font-important-light dark:text-font-important-dark">
5
5
  {% if content_title %}
6
- <span class="font-medium text-gray-900 tracking-tight dark:text-gray-100">
6
+ <span class="tracking-tight">
7
7
  {{ pretitle }}
8
8
 
9
9
  {{ content_title }}
@@ -68,7 +68,7 @@
68
68
  {% endif %}
69
69
  </head>
70
70
 
71
- <body class="antialiased bg-white font-sans text-gray-600 text-sm dark:bg-gray-900 dark:text-gray-300 {% if is_popup %}popup {% endif %}{% block bodyclass %}{% endblock %}" data-admin-utc-offset="{% now "Z" %}" x-data="{ activeTab: 'general', sidebarMobileOpen: false, sidebarDesktopOpen: {% if request.session.toggle_sidebar == False %}false{% else %}true{% endif %} }" x-init="activeTab = window.location.hash?.replace('#', '') || 'general'">
71
+ <body class="antialiased bg-white font-sans text-font-default-light text-sm dark:bg-gray-900 dark:text-font-default-dark {% if is_popup %}popup {% endif %}{% block bodyclass %}{% endblock %}" data-admin-utc-offset="{% now "Z" %}" x-data="{ activeTab: 'general', sidebarMobileOpen: false, sidebarDesktopOpen: {% if request.session.toggle_sidebar == False %}false{% else %}true{% endif %} }" x-init="activeTab = window.location.hash?.replace('#', '') || 'general'">
72
72
  {% block base %}{% endblock %}
73
73
 
74
74
  <div id="modal-overlay" class="backdrop-blur-sm bg-opacity-80 bg-gray-900 bottom-0 fixed hidden left-0 mr-1 right-0 top-0 z-50"></div>
@@ -10,7 +10,7 @@
10
10
 
11
11
  <div class="border flex items-center overflow-hidden rounded-md shadow-sm text-sm max-w-2xl dark:border-gray-700">
12
12
  {% if widget.is_initial and not widget.required %}
13
- <div class="bg-gray-50 border-r flex flex-none items-center self-stretch px-3 dark:bg-white/[.02] dark:border-gray-700 dark:text-gray-300">
13
+ <div class="bg-gray-50 border-r flex flex-none items-center self-stretch px-3 dark:bg-white/[.02] dark:border-gray-700 dark:text-font-default-dark">
14
14
  <label for="{{ widget.checkbox_id }}" class="flex items-center">
15
15
  <input type="checkbox"{% if widget.class %} class="{{ widget.class }}"{% endif %} name="{{ widget.checkbox_name }}" id="{{ widget.checkbox_id }}" />
16
16
 
@@ -21,7 +21,7 @@
21
21
  </div>
22
22
  {% endif %}
23
23
 
24
- <input type="text" aria-label="{% trans 'Choose file to upload' %}" value="{% if widget.value %}{{ widget.value.url }}{% else %}{% trans 'Choose file to upload' %}{% endif %}" disabled class="bg-white flex-grow font-medium px-3 py-2 text-ellipsis dark:bg-gray-900 {% if widget.value %}text-gray-500 dark:text-gray-300{% else %}text-gray-300 dark:text-gray-300{% endif %}">
24
+ <input type="text" aria-label="{% trans 'Choose file to upload' %}" value="{% if widget.value %}{{ widget.value.url }}{% else %}{% trans 'Choose file to upload' %}{% endif %}" disabled class="bg-white flex-grow font-medium px-3 py-2 text-ellipsis dark:bg-gray-900">
25
25
 
26
26
  <div class="flex flex-none items-center leading-none self-stretch">
27
27
  <div class="hidden">
@@ -14,7 +14,7 @@
14
14
  </div>
15
15
  {% endif %}
16
16
 
17
- <input type="text" aria-label="{% trans 'Choose file to upload' %}" value="{% if widget.value %}{{ widget.value.url }}{% else %}{% trans 'Choose file to upload' %}{% endif %}" disabled class="bg-white flex-grow font-medium px-3 py-2 text-ellipsis dark:bg-gray-900 {% if widget.value %}text-gray-500 dark:text-gray-300{% else %}text-gray-300 dark:text-gray-300{% endif %}">
17
+ <input type="text" aria-label="{% trans 'Choose file to upload' %}" value="{% if widget.value %}{{ widget.value.url }}{% else %}{% trans 'Choose file to upload' %}{% endif %}" disabled class="bg-white flex-grow font-medium px-3 py-2 text-ellipsis dark:bg-gray-900">
18
18
 
19
19
  <div class="flex flex-none items-center leading-none self-stretch">
20
20
  <div class="hidden">
@@ -0,0 +1,7 @@
1
+ <div class="flex flex-row gap-2 items-center">
2
+ {% include "django/forms/widgets/input.html" %}
3
+
4
+ {% if url_valid %}
5
+ {{ current_label }} <a href="{{ widget.href }}" class="text-primary-600 dark:text-primary-500">{{ widget.value }}</a>
6
+ {% endif %}
7
+ </div>
@@ -50,17 +50,13 @@ ROW_CLASSES = [
50
50
  "px-3",
51
51
  "py-2",
52
52
  "text-left",
53
- "text-sm",
54
53
  "before:flex",
55
54
  "before:capitalize",
56
55
  "before:content-[attr(data-label)]",
57
56
  "before:items-center",
58
57
  "before:font-semibold",
59
58
  "before:mr-auto",
60
- "before:text-gray-900",
61
59
  "first:border-t-0",
62
- "dark:text-gray-300",
63
- "dark:before:text-gray-100",
64
60
  "lg:before:hidden",
65
61
  "lg:first:border-t",
66
62
  "lg:py-3",
@@ -76,18 +72,15 @@ CHECKBOX_CLASSES = [
76
72
  "px-3",
77
73
  "py-2",
78
74
  "text-left",
79
- "text-sm",
80
75
  "before:block",
81
76
  "before:capitalize",
82
77
  "before:content-[attr(data-label)]",
83
78
  "before:font-semibold",
84
79
  "before:mr-auto",
85
- "before:text-gray-900",
86
80
  "lg:before:hidden",
87
81
  "lg:border-t",
88
82
  "lg:border-gray-200",
89
83
  "lg:table-cell",
90
- "dark:before:text-gray-100",
91
84
  "dark:lg:border-gray-800",
92
85
  ]
93
86
 
unfold/widgets.py CHANGED
@@ -13,6 +13,7 @@ from django.contrib.admin.widgets import (
13
13
  AdminTextareaWidget,
14
14
  AdminTextInputWidget,
15
15
  AdminTimeWidget,
16
+ AdminURLFieldWidget,
16
17
  AdminUUIDInputWidget,
17
18
  ForeignKeyRawIdWidget,
18
19
  RelatedFieldWidgetWrapper,
@@ -20,6 +21,7 @@ from django.contrib.admin.widgets import (
20
21
  from django.db.models.fields.reverse_related import ForeignObjectRel
21
22
  from django.forms import (
22
23
  CheckboxInput,
24
+ CheckboxSelectMultiple,
23
25
  MultiWidget,
24
26
  NullBooleanSelect,
25
27
  NumberInput,
@@ -35,16 +37,17 @@ LABEL_CLASSES = [
35
37
  "block",
36
38
  "font-medium",
37
39
  "mb-2",
38
- "text-gray-900",
40
+ "text-font-important-light",
39
41
  "text-sm",
40
- "dark:text-gray-100",
42
+ "dark:text-font-important-dark",
41
43
  ]
42
44
 
43
45
  CHECKBOX_LABEL_CLASSES = [
46
+ "font-medium",
44
47
  "ml-2",
45
48
  "text-sm",
46
- "text-gray-900",
47
- "dark:text-gray-100",
49
+ "text-font-important-light",
50
+ "dark:text-font-important-dark",
48
51
  ]
49
52
 
50
53
  BASE_CLASSES = [
@@ -54,7 +57,7 @@ BASE_CLASSES = [
54
57
  "min-w-20",
55
58
  "rounded-md",
56
59
  "shadow-sm",
57
- "text-gray-500",
60
+ "text-font-default-light",
58
61
  "text-sm",
59
62
  "focus:ring",
60
63
  "focus:ring-primary-300",
@@ -64,7 +67,7 @@ BASE_CLASSES = [
64
67
  "group-[.errors]:focus:ring-red-200",
65
68
  "dark:bg-gray-900",
66
69
  "dark:border-gray-700",
67
- "dark:text-gray-300",
70
+ "dark:text-font-default-dark",
68
71
  "dark:focus:border-primary-600",
69
72
  "dark:focus:ring-primary-700",
70
73
  "dark:focus:ring-opacity-50",
@@ -253,6 +256,13 @@ class UnfoldAdminTextInputWidget(AdminTextInputWidget):
253
256
  super().__init__(attrs={"class": " ".join(INPUT_CLASSES), **(attrs or {})})
254
257
 
255
258
 
259
+ class UnfoldAdminURLInputWidget(AdminURLFieldWidget):
260
+ template_name = "unfold/widgets/url.html"
261
+
262
+ def __init__(self, attrs: Optional[Dict[str, Any]] = None) -> None:
263
+ super().__init__(attrs={"class": " ".join(INPUT_CLASSES), **(attrs or {})})
264
+
265
+
256
266
  class UnfoldAdminColorInputWidget(AdminTextInputWidget):
257
267
  def __init__(self, attrs: Optional[Dict[str, Any]] = None) -> None:
258
268
  super().__init__(
@@ -513,6 +523,16 @@ class UnfoldAdminRadioSelectWidget(AdminRadioSelect):
513
523
  return context
514
524
 
515
525
 
526
+ class UnfoldAdminCheckboxSelectMultiple(CheckboxSelectMultiple):
527
+ template_name = "unfold/widgets/radio.html"
528
+ option_template_name = "unfold/widgets/radio_option.html"
529
+
530
+ def __init__(self, *args, **kwargs):
531
+ super().__init__(*args, **kwargs)
532
+
533
+ self.attrs = {"class": " ".join(CHECKBOX_CLASSES)}
534
+
535
+
516
536
  try:
517
537
  from djmoney.forms.widgets import MoneyWidget
518
538
  from djmoney.settings import CURRENCY_CHOICES