django-unfold 0.12.0__py3-none-any.whl → 0.13.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. {django_unfold-0.12.0.dist-info → django_unfold-0.13.0.dist-info}/METADATA +209 -102
  2. {django_unfold-0.12.0.dist-info → django_unfold-0.13.0.dist-info}/RECORD +32 -13
  3. unfold/admin.py +26 -6
  4. unfold/contrib/guardian/__init__.py +0 -0
  5. unfold/contrib/guardian/apps.py +6 -0
  6. unfold/contrib/guardian/templates/admin/guardian/model/change_form.html +13 -0
  7. unfold/contrib/guardian/templates/admin/guardian/model/field.html +11 -0
  8. unfold/contrib/guardian/templates/admin/guardian/model/obj_perms_manage.html +35 -0
  9. unfold/contrib/guardian/templates/admin/guardian/model/obj_perms_manage_group.html +55 -0
  10. unfold/contrib/guardian/templates/admin/guardian/model/obj_perms_manage_user.html +56 -0
  11. unfold/contrib/guardian/templates/unfold/guardian/group_form.html +72 -0
  12. unfold/contrib/guardian/templates/unfold/guardian/user_form.html +72 -0
  13. unfold/contrib/simple_history/__init__.py +0 -0
  14. unfold/contrib/simple_history/apps.py +6 -0
  15. unfold/contrib/simple_history/templates/simple_history/_object_history_list.html +80 -0
  16. unfold/contrib/simple_history/templates/simple_history/object_history.html +21 -0
  17. unfold/contrib/simple_history/templates/simple_history/object_history_form.html +55 -0
  18. unfold/contrib/simple_history/templates/simple_history/submit_line.html +25 -0
  19. unfold/settings.py +1 -0
  20. unfold/sites.py +4 -0
  21. unfold/static/unfold/css/styles.css +1 -1
  22. unfold/styles.css +134 -66
  23. unfold/templates/admin/edit_inline/tabular.html +1 -1
  24. unfold/templates/admin/includes/fieldset.html +3 -7
  25. unfold/templates/admin/widgets/radio.html +20 -0
  26. unfold/templates/admin/widgets/radio_option.html +12 -0
  27. unfold/templates/unfold/helpers/field_readonly.html +9 -0
  28. unfold/templates/unfold/helpers/submit.html +3 -0
  29. unfold/templatetags/unfold.py +14 -0
  30. unfold/widgets.py +19 -0
  31. /django_unfold-0.12.0.dist-info/LICENSE → /django_unfold-0.13.0.dist-info/LICENSE.md +0 -0
  32. {django_unfold-0.12.0.dist-info → django_unfold-0.13.0.dist-info}/WHEEL +0 -0
unfold/styles.css CHANGED
@@ -5,16 +5,17 @@
5
5
  @tailwind utilities;
6
6
 
7
7
  html {
8
- --color-primary-50: theme('colors.purple.50');
9
- --color-primary-100: theme('colors.purple.100');
10
- --color-primary-200: theme('colors.purple.200');
11
- --color-primary-300: theme('colors.purple.300');
12
- --color-primary-400: theme('colors.purple.400');
13
- --color-primary-500: theme('colors.purple.500');
14
- --color-primary-600: theme('colors.purple.600');
15
- --color-primary-700: theme('colors.purple.700');
16
- --color-primary-800: theme('colors.purple.800');
17
- --color-primary-900: theme('colors.purple.900');
8
+ --color-primary-50: theme("colors.purple.50");
9
+ --color-primary-100: theme("colors.purple.100");
10
+ --color-primary-200: theme("colors.purple.200");
11
+ --color-primary-300: theme("colors.purple.300");
12
+ --color-primary-400: theme("colors.purple.400");
13
+ --color-primary-500: theme("colors.purple.500");
14
+ --color-primary-600: theme("colors.purple.600");
15
+ --color-primary-700: theme("colors.purple.700");
16
+ --color-primary-800: theme("colors.purple.800");
17
+ --color-primary-900: theme("colors.purple.900");
18
+ --color-primary-950: theme("colors.purple.950");
18
19
  }
19
20
 
20
21
  /*******************************************************
@@ -34,7 +35,7 @@ html {
34
35
  }
35
36
 
36
37
  .material-symbols-outlined {
37
- font-family: 'Material Symbols Outlined';
38
+ font-family: "Material Symbols Outlined";
38
39
  font-weight: normal;
39
40
  font-style: normal;
40
41
  font-size: 18px;
@@ -45,13 +46,13 @@ html {
45
46
  white-space: nowrap;
46
47
  word-wrap: normal;
47
48
  direction: ltr;
48
- -moz-font-feature-settings: 'liga';
49
+ -moz-font-feature-settings: "liga";
49
50
  -moz-osx-font-smoothing: grayscale;
50
51
  }
51
52
 
52
53
  .scrollable-top:after {
53
- @apply absolute bg-gradient-to-t from-gray-100 h-4 left-0 right-0 -top-4 dark:bg-none;
54
- content: '';
54
+ @apply absolute bg-gradient-to-t from-gray-100 h-4 left-0 right-0 -top-4 dark:bg-none;
55
+ content: "";
55
56
  }
56
57
  }
57
58
 
@@ -71,41 +72,68 @@ html {
71
72
  }
72
73
 
73
74
  /*******************************************************
74
- Forms
75
+ Select
75
76
  *******************************************************/
76
77
  select:not([class*="bg-none"]):not([multiple]) {
77
78
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3e%3cpath fill='#6B7280' d='M24 31.4 11.3 18.7l2.85-2.8L24 25.8l9.85-9.85 2.85 2.8Z'/%3e%3c/svg%3e");
78
- background-position: right .70rem center;
79
+ background-position: right 0.7rem center;
79
80
  background-repeat: no-repeat;
80
81
  background-size: 1.125rem 1.125rem;
81
82
  }
82
83
 
83
84
  select:after {
84
- content: '';
85
+ content: "";
85
86
  display: block;
86
87
  }
87
88
 
88
- #page input[type=checkbox] {
89
+ /*******************************************************
90
+ Checkbox
91
+ *******************************************************/
92
+ #page input[type="checkbox"] {
89
93
  @apply appearance-none bg-white block border border-gray-300 cursor-pointer h-4 relative rounded w-4 dark:bg-gray-700 dark:border-gray-500 hover:border-gray-400;
90
- @apply focus:outline focus:outline-1 focus:outline-offset-2 focus:outline-primary-500
94
+ @apply focus:outline focus:outline-1 focus:outline-offset-2 focus:outline-primary-500;
91
95
  }
92
96
 
93
- #page input[type=checkbox]:after {
97
+ #page input[type="checkbox"]:after {
94
98
  @apply absolute flex h-4 items-center justify-center leading-none -ml-px -mt-px text-white transition-all text-sm w-4 dark:text-gray-700;
95
99
 
96
100
  content: "done";
97
101
  font-family: "Material Symbols Outlined";
98
102
  }
99
103
 
100
- #page input[type=checkbox]:checked {
104
+ #page input[type="checkbox"]:checked {
101
105
  @apply bg-primary-600 border-primary-600 transition-all;
102
106
  }
103
107
 
104
- #page input[type=checkbox]:checked:after {
108
+ #page input[type="checkbox"]:checked:after {
105
109
  @apply text-white;
106
110
  }
107
111
 
108
- #page input[type=checkbox].hidden {
112
+ #page input[type="checkbox"].hidden {
113
+ display: none;
114
+ }
115
+
116
+ /*******************************************************
117
+ Radio
118
+ *******************************************************/
119
+ #page input[type="radio"] {
120
+ @apply appearance-none bg-white block border border-gray-300 cursor-pointer h-4 relative rounded-full w-4 dark:bg-gray-700 dark:border-gray-500 hover:border-gray-400;
121
+ @apply focus:outline focus:outline-1 focus:outline-offset-2 focus:outline-primary-500;
122
+ }
123
+
124
+ #page input[type="radio"]:after {
125
+ @apply absolute bg-white content-[''] flex h-2 items-center justify-center leading-none left-1/2 rounded-full text-white top-1/2 transition-all -translate-x-1/2 -translate-y-1/2 text-sm w-2 dark:text-gray-700 dark:bg-transparent;
126
+ }
127
+
128
+ #page input[type="radio"]:checked {
129
+ @apply bg-primary-600 border-primary-600 transition-all;
130
+ }
131
+
132
+ #page input[type="radio"]:checked:after {
133
+ @apply bg-white dark:bg-gray-200;
134
+ }
135
+
136
+ #page input[type="radio"].hidden {
109
137
  display: none;
110
138
  }
111
139
 
@@ -117,7 +145,7 @@ table select {
117
145
 
118
146
  background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="rgb(156, 163, 175)"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M7 10l5 5 5-5H7z"/></svg>');
119
147
  background-size: 1.125rem 1.125rem;
120
- background-position: right .5rem center;
148
+ background-position: right 0.5rem center;
121
149
  }
122
150
 
123
151
  table select:focus {
@@ -145,7 +173,7 @@ table tr.selected {
145
173
 
146
174
  .datetimeshortcuts a:first-child:after {
147
175
  @apply border-l flex h-9 items-center justify-center leading-none material-symbols-outlined py-2 text-base text-center w-9 hover:text-gray-700 dark:border-gray-700 dark:hover:text-white;
148
- content: 'timer';
176
+ content: "timer";
149
177
  }
150
178
 
151
179
  .datetimeshortcuts a:first-child:after {
@@ -158,7 +186,7 @@ table tr.selected {
158
186
 
159
187
  .date-icon:after {
160
188
  @apply border-l h-9 items-center justify-center leading-none material-symbols-outlined py-2 text-base text-center w-9 hover:text-gray-700 dark:border-gray-700;
161
- content: 'edit';
189
+ content: "edit";
162
190
  }
163
191
 
164
192
  .date-icon:after {
@@ -171,7 +199,7 @@ table tr.selected {
171
199
 
172
200
  .clock-icon:after {
173
201
  @apply border-l h-9 items-center justify-center material-symbols-outlined py-2 text-base text-center w-9 hover:text-gray-700 dark:border-gray-700 dark:hover:text-white;
174
- content: 'edit';
202
+ content: "edit";
175
203
  }
176
204
 
177
205
  .clock-icon:after {
@@ -241,11 +269,11 @@ table tr.selected {
241
269
  }
242
270
 
243
271
  .selector-add:after {
244
- content: 'arrow_forward';
272
+ content: "arrow_forward";
245
273
  }
246
274
 
247
275
  .selector-remove:after {
248
- content: 'arrow_back';
276
+ content: "arrow_back";
249
277
  }
250
278
 
251
279
  .related-widget-wrapper-link {
@@ -302,52 +330,73 @@ h3 span:nth-child(3) {
302
330
  @apply border-red-600;
303
331
  }
304
332
 
305
- .select2-container.select2-container--admin-autocomplete .select2-selection--single {
333
+ .select2-container.select2-container--admin-autocomplete
334
+ .select2-selection--single {
306
335
  @apply h-auto;
307
336
  }
308
337
 
309
- .select2-container.select2-container--admin-autocomplete .select2-selection--single .select2-selection__rendered {
310
- @apply font-medium h-9 px-3 py-2 text-gray-500 text-sm dark:text-gray-400;
338
+ .select2-container.select2-container--admin-autocomplete
339
+ .select2-selection--single
340
+ .select2-selection__rendered {
341
+ @apply font-medium h-9 px-3 py-2 text-gray-500 text-sm dark:text-gray-400;
311
342
  }
312
343
 
313
- .select2-container.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__clear,
314
- .select2-container.select2-container--admin-autocomplete .select2-selection--single .select2-selection__clear {
344
+ .select2-container.select2-container--admin-autocomplete
345
+ .select2-selection--multiple
346
+ .select2-selection__clear,
347
+ .select2-container.select2-container--admin-autocomplete
348
+ .select2-selection--single
349
+ .select2-selection__clear {
315
350
  @apply flex items-center mr-5 h-9 -mt-2 text-0;
316
351
  }
317
352
 
318
- .select2-container.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__clear:after,
319
- .select2-container.select2-container--admin-autocomplete .select2-selection--single .select2-selection__clear:after {
353
+ .select2-container.select2-container--admin-autocomplete
354
+ .select2-selection--multiple
355
+ .select2-selection__clear:after,
356
+ .select2-container.select2-container--admin-autocomplete
357
+ .select2-selection--single
358
+ .select2-selection__clear:after {
320
359
  @apply material-symbols-outlined text-gray-500;
321
360
  content: "close";
322
361
  font-size: 14px;
323
362
  }
324
363
 
325
- .select2-container.select2-container--admin-autocomplete .select2-selection--single .select2-selection__arrow {
364
+ .select2-container.select2-container--admin-autocomplete
365
+ .select2-selection--single
366
+ .select2-selection__arrow {
326
367
  @apply flex h-9 items-center mr-2 -mt-px;
327
368
  }
328
369
 
329
- .select2-container.select2-container--admin-autocomplete .select2-selection--single .select2-selection__arrow:after {
370
+ .select2-container.select2-container--admin-autocomplete
371
+ .select2-selection--single
372
+ .select2-selection__arrow:after {
330
373
  @apply left-0 leading-none m-0 material-symbols-outlined text-gray-500 text-lg;
331
374
  content: "expand_more";
332
375
  }
333
376
 
334
- .select2-container.select2-container--admin-autocomplete .select2-selection--single .select2-selection__arrow b {
377
+ .select2-container.select2-container--admin-autocomplete
378
+ .select2-selection--single
379
+ .select2-selection__arrow
380
+ b {
335
381
  @apply hidden;
336
382
  }
337
383
 
338
- .select2-container.select2-container--admin-autocomplete .select2-search--dropdown {
384
+ .select2-container.select2-container--admin-autocomplete
385
+ .select2-search--dropdown {
339
386
  @apply flex px-3 py-2;
340
387
  }
341
388
 
342
- .select2-container.select2-container--admin-autocomplete .select2-search--dropdown .select2-search__field {
389
+ .select2-container.select2-container--admin-autocomplete
390
+ .select2-search--dropdown
391
+ .select2-search__field {
343
392
  @apply bg-gray-50 border border-gray-200 border-solid flex-grow font-medium mx-0 outline-none px-3 py-2 rounded-md shadow-sm text-gray-500 text-sm w-auto dark:bg-gray-800 dark:border-gray-800 dark:text-gray-400;
344
393
  }
345
394
 
346
- .select2-container.select2-container--admin-autocomplete.select2-container--open.select2-container--above {
395
+ .select2-container.select2-container--admin-autocomplete.select2-container--open.select2-container--above {
347
396
  @apply rounded-t-none;
348
397
  }
349
398
 
350
- .select2-container.select2-container--admin-autocomplete.select2-container--open.select2-container--below {
399
+ .select2-container.select2-container--admin-autocomplete.select2-container--open.select2-container--below {
351
400
  @apply rounded-b-none;
352
401
  }
353
402
 
@@ -363,38 +412,55 @@ h3 span:nth-child(3) {
363
412
  @apply rounded-b-none rounded-t-md after:bottom-0 after:-mb-1 after:mt-0 after:top-auto;
364
413
  }
365
414
 
366
- .select2-container.select2-container--admin-autocomplete .select2-results__option {
415
+ .select2-container.select2-container--admin-autocomplete
416
+ .select2-results__option {
367
417
  @apply block px-3 py-2 text-gray-500 text-sm transition-all dark:text-gray-400;
368
418
  }
369
419
 
370
- .select2-container.select2-container--admin-autocomplete .select2-results__option--highlighted[aria-selected] {
420
+ .select2-container.select2-container--admin-autocomplete
421
+ .select2-results__option--highlighted[aria-selected] {
371
422
  @apply text-primary-500;
372
423
  }
373
424
 
374
- .select2-container.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__clear {
425
+ .select2-container.select2-container--admin-autocomplete
426
+ .select2-selection--multiple
427
+ .select2-selection__clear {
375
428
  @apply m-0 mr-2 top-0;
376
429
  }
377
430
 
378
- .select2-container.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__rendered {
431
+ .select2-container.select2-container--admin-autocomplete
432
+ .select2-selection--multiple
433
+ .select2-selection__rendered {
379
434
  @apply pl-1 pr-6 py-0 pt-1;
380
435
  }
381
436
 
382
- .select2-container--admin-autocomplete .select2-selection--multiple li.select2-selection__choice {
437
+ .select2-container--admin-autocomplete
438
+ .select2-selection--multiple
439
+ li.select2-selection__choice {
383
440
  @apply bg-gray-100 block font-medium h-7 leading-7 m-0 mr-1 mb-1 px-2 shadow-inner text-sm text-gray-500 truncate dark:bg-gray-800 dark:text-gray-400 dark:hover:text-gray-200;
384
441
  }
385
442
 
386
- .select2-container--admin-autocomplete .select2-selection--multiple li.select2-selection__choice .select2-selection__choice__remove {
443
+ .select2-container--admin-autocomplete
444
+ .select2-selection--multiple
445
+ li.select2-selection__choice
446
+ .select2-selection__choice__remove {
387
447
  @apply align-top text-0 hover:text-gray-600 dark:hover:text-gray-200;
388
448
  }
389
449
 
390
- .select2-container--admin-autocomplete .select2-selection--multiple li.select2-selection__choice .select2-selection__choice__remove:after {
450
+ .select2-container--admin-autocomplete
451
+ .select2-selection--multiple
452
+ li.select2-selection__choice
453
+ .select2-selection__choice__remove:after {
391
454
  @apply h-7 !leading-7 material-symbols-outlined;
392
455
 
393
456
  content: "close";
394
457
  font-size: 14px;
395
458
  }
396
459
 
397
- .select2-container--admin-autocomplete .select2-selection--multiple li.select2-search--inline .select2-search__field {
460
+ .select2-container--admin-autocomplete
461
+ .select2-selection--multiple
462
+ li.select2-search--inline
463
+ .select2-search__field {
398
464
  @apply m-0 h-7 text-gray-500 text-sm;
399
465
  }
400
466
 
@@ -406,25 +472,27 @@ h3 span:nth-child(3) {
406
472
  Collapsed
407
473
  *******************************************************/
408
474
  fieldset.collapsed > div {
409
- display: none;
475
+ display: none;
410
476
  }
411
477
 
412
478
  fieldset.collapse {
413
- @apply visible;
479
+ @apply visible;
414
480
  }
415
481
 
416
- fieldset.collapsed h2, fieldset.collapsed {
417
- @apply block;
482
+ fieldset.collapsed h2,
483
+ fieldset.collapsed {
484
+ @apply block;
418
485
  }
419
486
 
420
487
  fieldset.collapsed .collapse-toggle {
421
- @apply inline;
488
+ @apply inline;
422
489
  }
423
490
 
424
491
  /*******************************************************
425
492
  Calendar
426
493
  *******************************************************/
427
- .calendarbox, .clockbox {
494
+ .calendarbox,
495
+ .clockbox {
428
496
  @apply bg-white border rounded-md shadow-sm text-gray-500 text-sm w-80 z-50 dark:bg-gray-800 dark:border-gray-700 !fixed !left-1/2 !top-1/2 -translate-x-1/2 -translate-y-1/2;
429
497
  }
430
498
 
@@ -476,7 +544,7 @@ fieldset.collapsed .collapse-toggle {
476
544
  .calendarnav-previous:after {
477
545
  @apply border flex h-7 items-center justify-center material-symbols-outlined rounded-full text-gray-400 transition-all w-7 hover:border-primary-600 hover:text-primary-500 dark:bg-gray-800 dark:border-gray-700 dark:hover:border-gray-800;
478
546
 
479
- content: 'navigate_before';
547
+ content: "navigate_before";
480
548
  display: flex;
481
549
  }
482
550
 
@@ -490,7 +558,7 @@ fieldset.collapsed .collapse-toggle {
490
558
  }
491
559
 
492
560
  .calendarnav-next:after {
493
- content: 'navigate_next';
561
+ content: "navigate_next";
494
562
  display: flex;
495
563
  }
496
564
 
@@ -520,31 +588,31 @@ fieldset.collapsed .collapse-toggle {
520
588
  *******************************************************/
521
589
  .htmx-swapping:before {
522
590
  @apply absolute bg-white bottom-0 left-0 opacity-80 transition-all right-0 top-0;
523
- content: '';
591
+ content: "";
524
592
  }
525
593
 
526
594
  .htmx-swapping:after {
527
595
  @apply absolute animate-spin h-4 inset-1/2 material-symbols-outlined md-16 text-gray-400 w-4;
528
- content: 'sync';
596
+ content: "sync";
529
597
  }
530
598
 
531
599
  /*******************************************************
532
600
  Filters
533
601
  *******************************************************/
534
602
  #changelist-filter .admin-numeric-filter-slider .noUi-handle {
535
- @apply bg-white border border-gray-200 cursor-pointer h-4 -right-4 rounded-full shadow-sm w-4 dark:bg-gray-200 dark:border-gray-200;
603
+ @apply bg-white border border-gray-200 cursor-pointer h-4 -right-4 rounded-full shadow-sm w-4 dark:bg-gray-200 dark:border-gray-200;
536
604
  }
537
605
 
538
606
  #changelist-filter .admin-numeric-filter-slider .noUi-handle-upper {
539
- @apply right-0;
607
+ @apply right-0;
540
608
  }
541
609
 
542
610
  #changelist-filter .admin-numeric-filter-slider .noUi-handle:after {
543
- content: none;
611
+ content: none;
544
612
  }
545
613
 
546
614
  #changelist-filter .admin-numeric-filter-slider .noUi-handle:before {
547
- content: none;
615
+ content: none;
548
616
  }
549
617
 
550
618
  #changelist-filter .admin-numeric-filter-slider.noUi-target {
@@ -556,7 +624,7 @@ fieldset.collapsed .collapse-toggle {
556
624
  }
557
625
 
558
626
  #changelist-filter .admin-numeric-filter-slider-tooltips {
559
- @apply flex flex-row font-medium mb-5 space-x-4 text-gray-500 text-sm;
627
+ @apply flex flex-row font-medium mb-5 space-x-4 text-gray-500 text-sm;
560
628
  }
561
629
 
562
630
  /*******************************************************
@@ -111,7 +111,7 @@
111
111
  {% if field.is_readonly or not field.field.is_hidden %}
112
112
  <td{% if field.field.name %} class="field-{{ field.field.name }}{% if field.field.errors|length > 0 %} errors{% endif %}{% if inline_admin_form.original %} p-3 lg:py-3{% else %} py-3{% endif %}{% if field.is_checkbox %} align-middle{% else %} align-top{% endif %} {% if is_last_row and not inline_admin_formset.has_add_permission %}{% if is_last_col %}border-0 {% else %}border-b lg:border-0{% endif %}{% else %}border-b{% endif %} border-gray-200 flex items-center before:capitalize before:content-[attr(data-label)] before:mr-auto before:text-gray-500 before:w-72 lg:before:hidden font-normal px-3 text-left text-sm lg:table-cell dark:border-gray-800"{% endif %} data-label="{{ field.field.label }}">
113
113
  {% if field.is_readonly %}
114
- <p class="bg-gray-50 border font-medium px-3 py-2 rounded-md shadow-sm text-gray-500 text-sm dark:bg-gray-900 dark:border-gray-700 dark:text-gray-400 dark:bg-gray-800">
114
+ <p class="bg-gray-50 border font-medium max-w-lg px-3 py-2 rounded-md shadow-sm text-gray-500 text-sm truncate whitespace-nowrap dark:border-gray-700 dark:text-gray-400 dark:bg-gray-800">
115
115
  {{ field.contents }}
116
116
  </p>
117
117
  {% else %}
@@ -1,3 +1,5 @@
1
+ {% load unfold %}
2
+
1
3
  <fieldset class="module {{ fieldset.classes }}">
2
4
  {% if fieldset.name %}
3
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">
@@ -26,13 +28,7 @@
26
28
  </div>
27
29
 
28
30
  {% if field.is_readonly %}
29
- <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:border-gray-700 dark:text-gray-400 dark:bg-gray-800">
30
- {% if field.contents %}
31
- {{ field.contents }}
32
- {% else %}
33
- -
34
- {% endif %}
35
- </div>
31
+ <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:border-gray-700 dark:text-gray-400 dark:bg-gray-800 {% if field.is_json %}whitespace-pre{% endif %}">{% if field.contents %}{{ field.contents }}{% else %}-{% endif %}</div>
36
32
  {% else %}
37
33
  {{ field.field }}
38
34
  {% endif %}
@@ -0,0 +1,20 @@
1
+ {% with id=widget.attrs.id %}
2
+ <div{% if id %} id="{{ id }}"{% endif %} class="flex gap-2 {% if radio_style == 1 %} flex-row{% else %} flex-col{% endif %}">
3
+ {% for group, options, index in widget.optgroups %}
4
+ {% if group %}
5
+ <div>
6
+ <label>{{ group }}</label>
7
+ {% endif %}
8
+
9
+ {% for option in options %}
10
+ <div>
11
+ {% include option.template_name with widget=option %}
12
+ </div>
13
+ {% endfor %}
14
+
15
+ {% if group %}
16
+ </div>
17
+ {% endif %}
18
+ {% endfor %}
19
+ </div>
20
+ {% endwith %}
@@ -0,0 +1,12 @@
1
+ {% if widget.wrap_label %}
2
+ <label{% if widget.attrs.id %} for="{{ widget.attrs.id }}"{% endif %} class="flex flex-row items-center gap-2">
3
+ {% endif %}
4
+
5
+ {% include "django/forms/widgets/input.html" %}
6
+
7
+ {% if widget.wrap_label %}
8
+ <span class="text-sm text-gray-900 dark:text-gray-200">
9
+ {{ widget.label }}
10
+ </span>
11
+ </label>
12
+ {% endif %}
@@ -0,0 +1,9 @@
1
+ <div class="flex group mb-6 flex-col last:mb-4">
2
+ <label class="block font-medium mb-2 text-gray-900 text-sm dark:text-gray-200">
3
+ {{ title }}
4
+ </label>
5
+
6
+ <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:border-gray-700 dark:bg-gray-800 dark:text-gray-400">
7
+ {{ value }}
8
+ </div>
9
+ </div>
@@ -0,0 +1,3 @@
1
+ <button type="submit" {% if name %}name="{{ name}}"{% endif %} class="bg-primary-600 block border border-transparent font-medium px-3 py-2 rounded-md self-end text-sm text-white">
2
+ {{ title }}
3
+ </button>
@@ -1,5 +1,6 @@
1
1
  from typing import Any, Dict, Mapping, Union
2
2
 
3
+ from django.forms import Field
3
4
  from django.template import Library, Node, TemplateSyntaxError
4
5
  from django.template.base import NodeList, Parser, Token
5
6
  from django.template.loader import render_to_string
@@ -107,3 +108,16 @@ def do_capture(parser: Parser, token: Token) -> CaptureNode:
107
108
  nodelist = parser.parse(("endcapture",))
108
109
  parser.delete_first_token()
109
110
  return CaptureNode(nodelist, var, silent)
111
+
112
+
113
+ @register.filter
114
+ def add_css_class(field: Field, classes: Union[list, tuple]) -> Field:
115
+ if type(classes) in (list, tuple):
116
+ classes = " ".join(classes)
117
+
118
+ if "class" in field.field.widget.attrs:
119
+ field.field.widget.attrs["class"] += f" {classes}"
120
+ else:
121
+ field.field.widget.attrs["class"] = classes
122
+
123
+ return field
unfold/widgets.py CHANGED
@@ -1,11 +1,13 @@
1
1
  from typing import Any, Callable, Dict, Optional, Tuple, Union
2
2
 
3
+ from django.contrib.admin.options import VERTICAL
3
4
  from django.contrib.admin.widgets import (
4
5
  AdminBigIntegerFieldWidget,
5
6
  AdminDateWidget,
6
7
  AdminEmailInputWidget,
7
8
  AdminFileWidget,
8
9
  AdminIntegerFieldWidget,
10
+ AdminRadioSelect,
9
11
  AdminSplitDateTime,
10
12
  AdminTextareaWidget,
11
13
  AdminTextInputWidget,
@@ -319,6 +321,23 @@ class UnfoldAdminSelect(Select):
319
321
  super().__init__(attrs, choices)
320
322
 
321
323
 
324
+ class UnfoldAdminRadioSelectWidget(AdminRadioSelect):
325
+ option_template_name = "admin/widgets/radio_option.html"
326
+
327
+ def __init__(self, radio_style: Optional[int] = None, *args, **kwargs):
328
+ super().__init__(*args, **kwargs)
329
+
330
+ if radio_style is None:
331
+ radio_style = VERTICAL
332
+
333
+ self.radio_style = radio_style
334
+
335
+ def get_context(self, *args, **kwargs) -> Dict[str, Any]:
336
+ context = super().get_context(*args, **kwargs)
337
+ context.update({"radio_style": self.radio_style})
338
+ return context
339
+
340
+
322
341
  try:
323
342
  from djmoney.forms.widgets import MoneyWidget
324
343
  from djmoney.settings import CURRENCY_CHOICES