django-admin-react 1.10.1__tar.gz → 1.11.1__tar.gz

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_admin_react-1.10.1 → django_admin_react-1.11.1}/PKG-INFO +60 -9
  2. {django_admin_react-1.10.1 → django_admin_react-1.11.1}/README.md +59 -8
  3. {django_admin_react-1.10.1 → django_admin_react-1.11.1}/django_admin_react/apps.py +13 -0
  4. django_admin_react-1.11.1/django_admin_react/checks.py +161 -0
  5. django_admin_react-1.11.1/django_admin_react/static/admin_react/.vite/manifest.json +53 -0
  6. django_admin_react-1.10.1/django_admin_react/static/admin_react/assets/ColumnLayoutModal-DHJDtlNp.js → django_admin_react-1.11.1/django_admin_react/static/admin_react/assets/ColumnLayoutModal-C7cJc5k4.js +1 -1
  7. django_admin_react-1.11.1/django_admin_react/static/admin_react/assets/CreatePage-DxqO6NwY.js +1 -0
  8. django_admin_react-1.10.1/django_admin_react/static/admin_react/assets/JsonViewer-Ckt1Ej0Y.js → django_admin_react-1.11.1/django_admin_react/static/admin_react/assets/JsonViewer-BJ2b9AYj.js +1 -1
  9. django_admin_react-1.11.1/django_admin_react/static/admin_react/assets/LoginPage-C7QsuBkV.js +1 -0
  10. django_admin_react-1.11.1/django_admin_react/static/admin_react/assets/index-BnM42yhL.css +1 -0
  11. django_admin_react-1.11.1/django_admin_react/static/admin_react/assets/index-CF3q3aV_.js +8 -0
  12. {django_admin_react-1.10.1 → django_admin_react-1.11.1}/django_admin_react/static/admin_react/index.html +2 -2
  13. {django_admin_react-1.10.1 → django_admin_react-1.11.1}/pyproject.toml +1 -1
  14. django_admin_react-1.10.1/django_admin_react/static/admin_react/.vite/manifest.json +0 -33
  15. django_admin_react-1.10.1/django_admin_react/static/admin_react/assets/index-C521uvP8.css +0 -1
  16. django_admin_react-1.10.1/django_admin_react/static/admin_react/assets/index-C9TH5IEG.js +0 -8
  17. {django_admin_react-1.10.1 → django_admin_react-1.11.1}/LICENSE +0 -0
  18. {django_admin_react-1.10.1 → django_admin_react-1.11.1}/django_admin_react/README.md +0 -0
  19. {django_admin_react-1.10.1 → django_admin_react-1.11.1}/django_admin_react/__init__.py +0 -0
  20. {django_admin_react-1.10.1 → django_admin_react-1.11.1}/django_admin_react/conf.py +0 -0
  21. {django_admin_react-1.10.1 → django_admin_react-1.11.1}/django_admin_react/pwa.py +0 -0
  22. {django_admin_react-1.10.1 → django_admin_react-1.11.1}/django_admin_react/templates/README.md +0 -0
  23. {django_admin_react-1.10.1 → django_admin_react-1.11.1}/django_admin_react/templates/admin/base_site.html +0 -0
  24. {django_admin_react-1.10.1 → django_admin_react-1.11.1}/django_admin_react/templates/admin_react/README.md +0 -0
  25. {django_admin_react-1.10.1 → django_admin_react-1.11.1}/django_admin_react/templates/admin_react/index.html +0 -0
  26. {django_admin_react-1.10.1 → django_admin_react-1.11.1}/django_admin_react/templates/admin_react/login.html +0 -0
  27. {django_admin_react-1.10.1 → django_admin_react-1.11.1}/django_admin_react/templates/admin_react/sw.js +0 -0
  28. {django_admin_react-1.10.1 → django_admin_react-1.11.1}/django_admin_react/templates/django_admin_react/_experience_toggle_strip.html +0 -0
  29. {django_admin_react-1.10.1 → django_admin_react-1.11.1}/django_admin_react/templatetags/__init__.py +0 -0
  30. {django_admin_react-1.10.1 → django_admin_react-1.11.1}/django_admin_react/templatetags/experience_toggle.py +0 -0
  31. {django_admin_react-1.10.1 → django_admin_react-1.11.1}/django_admin_react/urls.py +0 -0
  32. {django_admin_react-1.10.1 → django_admin_react-1.11.1}/django_admin_react/views.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-admin-react
3
- Version: 1.10.1
3
+ Version: 1.11.1
4
4
  Summary: A drop-in React single-page admin for Django, driven entirely by ModelAdmin.
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -654,8 +654,9 @@ all share the v1 wire contract. Per-feature live status below.
654
654
  | `list_editable` + bulk PATCH | ✅ |
655
655
  | `actions` — batch + detail (signature-classified) | ✅ |
656
656
  | `autocomplete_fields` | ✅ |
657
- | `raw_id_fields` (pk text input + lookup popup) | 🟡 [#626](https://github.com/MartinCastroAlvarez/django-admin-react/issues/626) (API emits the hint; SPA still renders autocomplete) |
658
- | `radio_fields` (inline radio buttons vs `<select>`) | 🟡 [#626](https://github.com/MartinCastroAlvarez/django-admin-react/issues/626) (API emits the hint; SPA still renders dropdown) |
657
+ | `raw_id_fields` (pk text input + lookup popup) | |
658
+ | `radio_fields` (inline radio buttons vs `<select>`) | |
659
+ | `filter_horizontal` / `filter_vertical` (M2M shuttle) | ✅ |
659
660
  | `ManyToManyField` read + write | ✅ |
660
661
  | `inlines` (TabularInline / StackedInline) — read + write | ✅ |
661
662
  | `FileField` / `ImageField` — read | ✅ |
@@ -684,14 +685,13 @@ issues link the work to close each gap.
684
685
  |---|---|---|
685
686
  | `change_form_template` / `add_form_template` overrides | **Embedded in an iframe** (since 1.9.0, #659): the change/add form-spec endpoint returns a `legacy-iframe` pointer and the SPA embeds the legacy admin page inside the SPA shell (breadcrumb / sidebar / toolbar stay SPA-rendered). Port the form to documented ModelAdmin hooks at your own pace. | [#624](https://github.com/MartinCastroAlvarez/django-admin-react/issues/624) |
686
687
  | `change_list_template` / `change_password_template` / `object_history_template` overrides | Silently ignored — those surfaces render entirely from the JSON wire. | [#624](https://github.com/MartinCastroAlvarez/django-admin-react/issues/624) |
687
- | `formfield_overrides = {Field: {"widget": CustomWidget}}` | Custom widget invisible the SPA picks its own control from the field's `type`. No React-side widget-registration API yet. | [#625](https://github.com/MartinCastroAlvarez/django-admin-react/issues/625) |
688
- | `raw_id_fields` | Falls back to the autocomplete picker (same as `autocomplete_fields`). Defeats the purpose for FKs with 10M+ rows where autocomplete `get_search_results` is too expensive. | [#626](https://github.com/MartinCastroAlvarez/django-admin-react/issues/626) |
689
- | `radio_fields = {"status": admin.HORIZONTAL}` | Renders a `<select>` (default choice control) instead of inline radio buttons. | [#626](https://github.com/MartinCastroAlvarez/django-admin-react/issues/626) |
690
- | `filter_horizontal` / `filter_vertical` (M2M shuttle widget) | Renders the generic multi-select checkbox list, not Django's two-pane shuttle. Switch the field to `autocomplete_fields` for a workable SPA UX. | [#627](https://github.com/MartinCastroAlvarez/django-admin-react/issues/627) |
688
+ | `formfield_overrides = {Field: {"widget": CustomWidget}}` | Custom widget rendered via the React widget-registration API (`registerFieldWidget`, #625) when the consumer registers a renderer for the widget class; otherwise falls back to the default control + an operator-visible "not registered" note. | [#625](https://github.com/MartinCastroAlvarez/django-admin-react/issues/625) |
689
+ | `empty_value_display` | **Hard-coded to `—`.** A per-`ModelAdmin` / per-field `empty_value_display` override is **not** surfaced — the SPA renders the literal em-dash for every empty value, regardless of the consumer's chosen placeholder. | [#629](https://github.com/MartinCastroAlvarez/django-admin-react/issues/629) |
690
+ | Custom `AdminSite.each_context(request)` extra keys | Not surfaced. Only a fixed set of site attributes (`site_header` / `site_title` / `site_logo` / `site_primary_color`) reaches the SPA; any extra keys a consumer adds in a custom `each_context` are dropped. | [#629](https://github.com/MartinCastroAlvarez/django-admin-react/issues/629) |
691
+ | `list_select_related` | A backend query-optimisation concern, applied server-side by the REST API's queryset; it changes query efficiency, **not** the wire shape, so it is intentionally invisible to the SPA (no client-visible effect to surface). | [#629](https://github.com/MartinCastroAlvarez/django-admin-react/issues/629) |
691
692
  | `GenericForeignKey` / `GenericInlineModelAdmin` | Support gap — verify per-model before relying on the SPA. | [#628](https://github.com/MartinCastroAlvarez/django-admin-react/issues/628) |
692
- | `LANGUAGE_CODE` / `gettext` / `Accept-Language` | The SPA chrome stays English; translated `verbose_name` / `help_text` / `@admin.action(description=_("..."))` are not surfaced per-request. | [#630](https://github.com/MartinCastroAlvarez/django-admin-react/issues/630) |
693
+ | `LANGUAGE_CODE` / `gettext` / `Accept-Language` | SPA chrome strings translate via the bundled catalogs (es / fr / pt; #630); translated `verbose_name` / `help_text` / `@admin.action(description=_("..."))` flow through when `LocaleMiddleware` is installed. | [#630](https://github.com/MartinCastroAlvarez/django-admin-react/issues/630) |
693
694
  | `ModelAdmin.get_urls()` custom views | Opens as a popout (`<a target="_blank">`) into the Django-rendered HTML page — no SPA chrome, no breadcrumb. The link IS surfaced; the UX is just outside the SPA. | [#623](https://github.com/MartinCastroAlvarez/django-admin-react/issues/623) |
694
- | Django 4.2 LTS support | Not yet — the package pins `django >= 5.0,<7.0`. | [#622](https://github.com/MartinCastroAlvarez/django-admin-react/issues/622) |
695
695
 
696
696
  If your admin relies on any "silently ignored" hook above, the
697
697
  typical workaround is to keep that model on the legacy
@@ -699,6 +699,57 @@ typical workaround is to keep that model on the legacy
699
699
  [experience-toggle strip](#experience-toggle-strip-optional) — the
700
700
  SPA + legacy admin happily coexist.
701
701
 
702
+ #### Embedding the legacy admin in an iframe — required backend headers
703
+
704
+ When a `ModelAdmin` overrides `change_form_template` / `add_form_template`,
705
+ the SPA embeds the legacy admin page in an `<iframe>` (the row above). For
706
+ the browser to actually render that frame, the **legacy admin responses must
707
+ allow being framed by the SPA's origin** — otherwise the embed is refused and
708
+ the SPA shows a "Embedding refused by the legacy admin — open in new tab"
709
+ fallback (never a broken-image icon, #673).
710
+
711
+ Most projects mount `django.middleware.clickjacking.XFrameOptionsMiddleware`,
712
+ which by default sets `X-Frame-Options: DENY` on **every** response and blocks
713
+ the iframe. Configure the legacy responses as follows:
714
+
715
+ **Same origin (SPA and legacy admin under one host — the common case):**
716
+
717
+ ```python
718
+ # settings.py
719
+ X_FRAME_OPTIONS = "SAMEORIGIN" # was the implicit "DENY"
720
+ # …or drop XFrameOptionsMiddleware entirely if you don't need clickjacking
721
+ # protection on the legacy surface.
722
+ ```
723
+
724
+ `SAMEORIGIN` lets the same-origin SPA frame the legacy page while still
725
+ blocking cross-site framing.
726
+
727
+ **Cross-origin (SPA and legacy admin on different origins):**
728
+
729
+ ```python
730
+ # On the legacy admin responses (e.g. via a middleware or
731
+ # django-csp), allow ONLY the SPA origin to frame them:
732
+ # Content-Security-Policy: frame-ancestors https://admin.example.com
733
+ #
734
+ # And, because the iframe is a cross-site context, the legacy session
735
+ # cookie must be sent in it:
736
+ # settings.py
737
+ SESSION_COOKIE_SAMESITE = "None" # send the cookie in the cross-site frame
738
+ SESSION_COOKIE_SECURE = True # required whenever SameSite=None
739
+ ```
740
+
741
+ Without these, the framed legacy page either refuses to load (`frame-ancestors`
742
+ block) or loads unauthenticated (cookie dropped) and bounces through a login
743
+ redirect the browser then refuses to display. The
744
+ [`examples/jobs`](examples/jobs) `JobAdmin` (the `?run_custom=1` variant)
745
+ exercises this path end-to-end against the example backend.
746
+
747
+ > The SPA detects a refused frame client-side (a `loading → loaded → refused`
748
+ > state machine: a ~4s window with no iframe `load` event ⇒ refused) and
749
+ > renders the fallback. A future server-side `legacy_iframeable` flag computed
750
+ > from the response middleware chain (cross-repo, rest-api) could switch to the
751
+ > "open in new tab only" UI immediately — tracked as a follow-up.
752
+
702
753
  ---
703
754
 
704
755
  ## Writing safe `list_display` callables
@@ -618,8 +618,9 @@ all share the v1 wire contract. Per-feature live status below.
618
618
  | `list_editable` + bulk PATCH | ✅ |
619
619
  | `actions` — batch + detail (signature-classified) | ✅ |
620
620
  | `autocomplete_fields` | ✅ |
621
- | `raw_id_fields` (pk text input + lookup popup) | 🟡 [#626](https://github.com/MartinCastroAlvarez/django-admin-react/issues/626) (API emits the hint; SPA still renders autocomplete) |
622
- | `radio_fields` (inline radio buttons vs `<select>`) | 🟡 [#626](https://github.com/MartinCastroAlvarez/django-admin-react/issues/626) (API emits the hint; SPA still renders dropdown) |
621
+ | `raw_id_fields` (pk text input + lookup popup) | |
622
+ | `radio_fields` (inline radio buttons vs `<select>`) | |
623
+ | `filter_horizontal` / `filter_vertical` (M2M shuttle) | ✅ |
623
624
  | `ManyToManyField` read + write | ✅ |
624
625
  | `inlines` (TabularInline / StackedInline) — read + write | ✅ |
625
626
  | `FileField` / `ImageField` — read | ✅ |
@@ -648,14 +649,13 @@ issues link the work to close each gap.
648
649
  |---|---|---|
649
650
  | `change_form_template` / `add_form_template` overrides | **Embedded in an iframe** (since 1.9.0, #659): the change/add form-spec endpoint returns a `legacy-iframe` pointer and the SPA embeds the legacy admin page inside the SPA shell (breadcrumb / sidebar / toolbar stay SPA-rendered). Port the form to documented ModelAdmin hooks at your own pace. | [#624](https://github.com/MartinCastroAlvarez/django-admin-react/issues/624) |
650
651
  | `change_list_template` / `change_password_template` / `object_history_template` overrides | Silently ignored — those surfaces render entirely from the JSON wire. | [#624](https://github.com/MartinCastroAlvarez/django-admin-react/issues/624) |
651
- | `formfield_overrides = {Field: {"widget": CustomWidget}}` | Custom widget invisible the SPA picks its own control from the field's `type`. No React-side widget-registration API yet. | [#625](https://github.com/MartinCastroAlvarez/django-admin-react/issues/625) |
652
- | `raw_id_fields` | Falls back to the autocomplete picker (same as `autocomplete_fields`). Defeats the purpose for FKs with 10M+ rows where autocomplete `get_search_results` is too expensive. | [#626](https://github.com/MartinCastroAlvarez/django-admin-react/issues/626) |
653
- | `radio_fields = {"status": admin.HORIZONTAL}` | Renders a `<select>` (default choice control) instead of inline radio buttons. | [#626](https://github.com/MartinCastroAlvarez/django-admin-react/issues/626) |
654
- | `filter_horizontal` / `filter_vertical` (M2M shuttle widget) | Renders the generic multi-select checkbox list, not Django's two-pane shuttle. Switch the field to `autocomplete_fields` for a workable SPA UX. | [#627](https://github.com/MartinCastroAlvarez/django-admin-react/issues/627) |
652
+ | `formfield_overrides = {Field: {"widget": CustomWidget}}` | Custom widget rendered via the React widget-registration API (`registerFieldWidget`, #625) when the consumer registers a renderer for the widget class; otherwise falls back to the default control + an operator-visible "not registered" note. | [#625](https://github.com/MartinCastroAlvarez/django-admin-react/issues/625) |
653
+ | `empty_value_display` | **Hard-coded to `—`.** A per-`ModelAdmin` / per-field `empty_value_display` override is **not** surfaced — the SPA renders the literal em-dash for every empty value, regardless of the consumer's chosen placeholder. | [#629](https://github.com/MartinCastroAlvarez/django-admin-react/issues/629) |
654
+ | Custom `AdminSite.each_context(request)` extra keys | Not surfaced. Only a fixed set of site attributes (`site_header` / `site_title` / `site_logo` / `site_primary_color`) reaches the SPA; any extra keys a consumer adds in a custom `each_context` are dropped. | [#629](https://github.com/MartinCastroAlvarez/django-admin-react/issues/629) |
655
+ | `list_select_related` | A backend query-optimisation concern, applied server-side by the REST API's queryset; it changes query efficiency, **not** the wire shape, so it is intentionally invisible to the SPA (no client-visible effect to surface). | [#629](https://github.com/MartinCastroAlvarez/django-admin-react/issues/629) |
655
656
  | `GenericForeignKey` / `GenericInlineModelAdmin` | Support gap — verify per-model before relying on the SPA. | [#628](https://github.com/MartinCastroAlvarez/django-admin-react/issues/628) |
656
- | `LANGUAGE_CODE` / `gettext` / `Accept-Language` | The SPA chrome stays English; translated `verbose_name` / `help_text` / `@admin.action(description=_("..."))` are not surfaced per-request. | [#630](https://github.com/MartinCastroAlvarez/django-admin-react/issues/630) |
657
+ | `LANGUAGE_CODE` / `gettext` / `Accept-Language` | SPA chrome strings translate via the bundled catalogs (es / fr / pt; #630); translated `verbose_name` / `help_text` / `@admin.action(description=_("..."))` flow through when `LocaleMiddleware` is installed. | [#630](https://github.com/MartinCastroAlvarez/django-admin-react/issues/630) |
657
658
  | `ModelAdmin.get_urls()` custom views | Opens as a popout (`<a target="_blank">`) into the Django-rendered HTML page — no SPA chrome, no breadcrumb. The link IS surfaced; the UX is just outside the SPA. | [#623](https://github.com/MartinCastroAlvarez/django-admin-react/issues/623) |
658
- | Django 4.2 LTS support | Not yet — the package pins `django >= 5.0,<7.0`. | [#622](https://github.com/MartinCastroAlvarez/django-admin-react/issues/622) |
659
659
 
660
660
  If your admin relies on any "silently ignored" hook above, the
661
661
  typical workaround is to keep that model on the legacy
@@ -663,6 +663,57 @@ typical workaround is to keep that model on the legacy
663
663
  [experience-toggle strip](#experience-toggle-strip-optional) — the
664
664
  SPA + legacy admin happily coexist.
665
665
 
666
+ #### Embedding the legacy admin in an iframe — required backend headers
667
+
668
+ When a `ModelAdmin` overrides `change_form_template` / `add_form_template`,
669
+ the SPA embeds the legacy admin page in an `<iframe>` (the row above). For
670
+ the browser to actually render that frame, the **legacy admin responses must
671
+ allow being framed by the SPA's origin** — otherwise the embed is refused and
672
+ the SPA shows a "Embedding refused by the legacy admin — open in new tab"
673
+ fallback (never a broken-image icon, #673).
674
+
675
+ Most projects mount `django.middleware.clickjacking.XFrameOptionsMiddleware`,
676
+ which by default sets `X-Frame-Options: DENY` on **every** response and blocks
677
+ the iframe. Configure the legacy responses as follows:
678
+
679
+ **Same origin (SPA and legacy admin under one host — the common case):**
680
+
681
+ ```python
682
+ # settings.py
683
+ X_FRAME_OPTIONS = "SAMEORIGIN" # was the implicit "DENY"
684
+ # …or drop XFrameOptionsMiddleware entirely if you don't need clickjacking
685
+ # protection on the legacy surface.
686
+ ```
687
+
688
+ `SAMEORIGIN` lets the same-origin SPA frame the legacy page while still
689
+ blocking cross-site framing.
690
+
691
+ **Cross-origin (SPA and legacy admin on different origins):**
692
+
693
+ ```python
694
+ # On the legacy admin responses (e.g. via a middleware or
695
+ # django-csp), allow ONLY the SPA origin to frame them:
696
+ # Content-Security-Policy: frame-ancestors https://admin.example.com
697
+ #
698
+ # And, because the iframe is a cross-site context, the legacy session
699
+ # cookie must be sent in it:
700
+ # settings.py
701
+ SESSION_COOKIE_SAMESITE = "None" # send the cookie in the cross-site frame
702
+ SESSION_COOKIE_SECURE = True # required whenever SameSite=None
703
+ ```
704
+
705
+ Without these, the framed legacy page either refuses to load (`frame-ancestors`
706
+ block) or loads unauthenticated (cookie dropped) and bounces through a login
707
+ redirect the browser then refuses to display. The
708
+ [`examples/jobs`](examples/jobs) `JobAdmin` (the `?run_custom=1` variant)
709
+ exercises this path end-to-end against the example backend.
710
+
711
+ > The SPA detects a refused frame client-side (a `loading → loaded → refused`
712
+ > state machine: a ~4s window with no iframe `load` event ⇒ refused) and
713
+ > renders the fallback. A future server-side `legacy_iframeable` flag computed
714
+ > from the response middleware chain (cross-repo, rest-api) could switch to the
715
+ > "open in new tab only" UI immediately — tracked as a follow-up.
716
+
666
717
  ---
667
718
 
668
719
  ## Writing safe `list_display` callables
@@ -6,6 +6,7 @@ templates, static assets) is opt-in via the consumer's own `urls.py`.
6
6
  """
7
7
 
8
8
  from django.apps import AppConfig
9
+ from django.core.checks import register
9
10
 
10
11
 
11
12
  class DjangoAdminReactConfig(AppConfig):
@@ -25,3 +26,15 @@ class DjangoAdminReactConfig(AppConfig):
25
26
  label = "django_admin_react"
26
27
  verbose_name = "Django Admin React"
27
28
  default_auto_field = "django.db.models.BigAutoField"
29
+
30
+ def ready(self) -> None:
31
+ """Register the package's system checks at app-load (#667).
32
+
33
+ Importing + registering here (not at module import time) keeps the
34
+ checks tied to the app registry being ready, matching Django's
35
+ documented pattern. The import is local so adding the app has no
36
+ eager import cost beyond the AppConfig itself.
37
+ """
38
+ from django_admin_react.checks import check_django_admin_react
39
+
40
+ register(check_django_admin_react)
@@ -0,0 +1,161 @@
1
+ """System checks for django_admin_react (#667).
2
+
3
+ Registered against ``django.core.checks`` so common misconfigurations
4
+ surface at ``manage.py check`` (and on every ``runserver`` boot) with an
5
+ actionable hint — instead of a lazy ``ValueError`` on first settings
6
+ access, a runtime 500, or a silent template fallback.
7
+
8
+ What we validate:
9
+
10
+ - ``django_admin_rest_api`` is installed (the package implements no API of
11
+ its own — every JSON endpoint lives in that sibling package).
12
+ - ``DJANGO_ADMIN_REACT["ADMIN_SITE"]`` (dotted path) actually imports.
13
+ - ``DJANGO_ADMIN_REACT`` has no unknown keys (the same guard ``conf._load``
14
+ enforces lazily — surfaced here at startup as a clean check error).
15
+ - ``API_URL_PREFIX`` mounting is coherent: when it is set, the package
16
+ skips its inline ``api/v1/`` include, so the consumer must mount
17
+ ``django_admin_rest_api.urls`` themselves — a Warning reminds them.
18
+ - The built SPA bundle / Vite manifest exists (a Warning, not an Error —
19
+ the package serves a friendly "not built" shell, and the manifest is
20
+ absent in a source checkout / before ``pnpm build``).
21
+
22
+ Severities follow Django's convention: an ``Error`` blocks (the package
23
+ cannot work); a ``Warning`` is a likely-misconfiguration heads-up that
24
+ does not hard-block.
25
+ """
26
+
27
+ from __future__ import annotations
28
+
29
+ from typing import Any
30
+
31
+ from django.core.checks import Error
32
+ from django.core.checks import Warning as CheckWarning
33
+
34
+ # Stable check IDs (Django convention ``<app_label>.E/W###``) so a consumer
35
+ # can silence a specific one via ``SILENCED_SYSTEM_CHECKS`` if they must.
36
+ ID_REST_API_MISSING = "django_admin_react.E001"
37
+ ID_ADMIN_SITE_IMPORT = "django_admin_react.E002"
38
+ ID_UNKNOWN_SETTINGS = "django_admin_react.E003"
39
+ ID_API_PREFIX_MOUNT = "django_admin_react.W001"
40
+ ID_BUNDLE_MISSING = "django_admin_react.W002"
41
+
42
+
43
+ def check_django_admin_react(app_configs: Any, **kwargs: Any) -> list[Any]:
44
+ """Run every package configuration check.
45
+
46
+ Registered as a single callable (rather than many) so the import
47
+ surface stays small and the ordering is explicit. ``app_configs`` /
48
+ ``kwargs`` are the Django check-framework signature; unused here
49
+ because the checks are global to the package, not per-app.
50
+ """
51
+ errors: list[Any] = []
52
+ errors.extend(_check_rest_api_installed())
53
+ errors.extend(_check_admin_site_imports())
54
+ errors.extend(_check_settings_keys())
55
+ errors.extend(_check_api_prefix_coherence())
56
+ errors.extend(_check_bundle_built())
57
+ return errors
58
+
59
+
60
+ def _check_rest_api_installed() -> list[Any]:
61
+ from django.apps import apps as django_apps
62
+
63
+ if django_apps.is_installed("django_admin_rest_api"):
64
+ return []
65
+ return [
66
+ Error(
67
+ "'django_admin_rest_api' is not in INSTALLED_APPS.",
68
+ hint=(
69
+ "django-admin-react is a React SPA over django-admin-rest-api "
70
+ "and implements no API of its own. Add 'django_admin_rest_api' "
71
+ "to INSTALLED_APPS (it ships as a dependency)."
72
+ ),
73
+ id=ID_REST_API_MISSING,
74
+ )
75
+ ]
76
+
77
+
78
+ def _check_admin_site_imports() -> list[Any]:
79
+ from django.utils.module_loading import import_string
80
+
81
+ from django_admin_react import conf as dar_conf
82
+
83
+ dotted = dar_conf.ADMIN_SITE
84
+ try:
85
+ import_string(dotted)
86
+ except ImportError as exc:
87
+ return [
88
+ Error(
89
+ f"DJANGO_ADMIN_REACT['ADMIN_SITE'] = {dotted!r} could not be imported " f"({exc}).",
90
+ hint=(
91
+ "Point ADMIN_SITE at the dotted path of your AdminSite "
92
+ "instance (e.g. 'myproject.admin.site' or the default "
93
+ "'django.contrib.admin.site')."
94
+ ),
95
+ id=ID_ADMIN_SITE_IMPORT,
96
+ )
97
+ ]
98
+ return []
99
+
100
+
101
+ def _check_settings_keys() -> list[Any]:
102
+ from django.conf import settings as django_settings
103
+
104
+ from django_admin_react.conf import DEFAULTS
105
+
106
+ overrides = getattr(django_settings, "DJANGO_ADMIN_REACT", {}) or {}
107
+ unknown = sorted(set(overrides) - set(DEFAULTS))
108
+ if not unknown:
109
+ return []
110
+ return [
111
+ Error(
112
+ "Unknown DJANGO_ADMIN_REACT key(s): " + ", ".join(unknown) + ".",
113
+ hint=("Remove the typo'd key(s). Valid keys are: " + ", ".join(sorted(DEFAULTS)) + "."),
114
+ id=ID_UNKNOWN_SETTINGS,
115
+ )
116
+ ]
117
+
118
+
119
+ def _check_api_prefix_coherence() -> list[Any]:
120
+ from django_admin_react import conf as dar_conf
121
+
122
+ prefix = dar_conf.API_URL_PREFIX
123
+ if prefix is None:
124
+ # Inline mount is active; the package mounts the API itself. Nothing
125
+ # the consumer must do.
126
+ return []
127
+ # The override is set, so `django_admin_react.urls` skips the inline
128
+ # `api/v1/` include — the consumer MUST mount the REST API themselves at
129
+ # that prefix or every SPA data call 404s.
130
+ return [
131
+ CheckWarning(
132
+ f"DJANGO_ADMIN_REACT['API_URL_PREFIX'] = {prefix!r} is set, so this "
133
+ "package does NOT mount the REST API inline.",
134
+ hint=(
135
+ "Mount the sibling API yourself at that prefix, e.g.\n"
136
+ f" path({prefix!r}, include('django_admin_rest_api.api.urls'))\n"
137
+ "or unset API_URL_PREFIX to use the package's inline 'api/v1/' mount."
138
+ ),
139
+ id=ID_API_PREFIX_MOUNT,
140
+ )
141
+ ]
142
+
143
+
144
+ def _check_bundle_built() -> list[Any]:
145
+ # Imported lazily so the check module has no import-time dependency on
146
+ # the view layer.
147
+ from django_admin_react.views import _MANIFEST_PATH
148
+
149
+ if _MANIFEST_PATH.is_file():
150
+ return []
151
+ return [
152
+ CheckWarning(
153
+ "The built SPA bundle / Vite manifest was not found at " f"{_MANIFEST_PATH}.",
154
+ hint=(
155
+ "Install the published wheel (which ships the built bundle), or "
156
+ "build the frontend from source with 'pnpm --dir frontend build'. "
157
+ "Until then the SPA shell renders a 'not built yet' page."
158
+ ),
159
+ id=ID_BUNDLE_MISSING,
160
+ )
161
+ ]
@@ -0,0 +1,53 @@
1
+ {
2
+ "../../packages/details/src/JsonViewer.tsx": {
3
+ "file": "assets/JsonViewer-BJ2b9AYj.js",
4
+ "name": "JsonViewer",
5
+ "src": "../../packages/details/src/JsonViewer.tsx",
6
+ "isDynamicEntry": true,
7
+ "imports": [
8
+ "index.html"
9
+ ]
10
+ },
11
+ "index.html": {
12
+ "file": "assets/index-CF3q3aV_.js",
13
+ "name": "index",
14
+ "src": "index.html",
15
+ "isEntry": true,
16
+ "dynamicImports": [
17
+ "../../packages/details/src/JsonViewer.tsx",
18
+ "src/ColumnLayoutModal.tsx",
19
+ "src/pages/LoginPage.tsx",
20
+ "src/pages/CreatePage.tsx"
21
+ ],
22
+ "css": [
23
+ "assets/index-BnM42yhL.css"
24
+ ]
25
+ },
26
+ "src/ColumnLayoutModal.tsx": {
27
+ "file": "assets/ColumnLayoutModal-C7cJc5k4.js",
28
+ "name": "ColumnLayoutModal",
29
+ "src": "src/ColumnLayoutModal.tsx",
30
+ "isDynamicEntry": true,
31
+ "imports": [
32
+ "index.html"
33
+ ]
34
+ },
35
+ "src/pages/CreatePage.tsx": {
36
+ "file": "assets/CreatePage-DxqO6NwY.js",
37
+ "name": "CreatePage",
38
+ "src": "src/pages/CreatePage.tsx",
39
+ "isDynamicEntry": true,
40
+ "imports": [
41
+ "index.html"
42
+ ]
43
+ },
44
+ "src/pages/LoginPage.tsx": {
45
+ "file": "assets/LoginPage-C7QsuBkV.js",
46
+ "name": "LoginPage",
47
+ "src": "src/pages/LoginPage.tsx",
48
+ "isDynamicEntry": true,
49
+ "imports": [
50
+ "index.html"
51
+ ]
52
+ }
53
+ }
@@ -1,4 +1,4 @@
1
- import{c as tt,d as c,R as $,r as ke,j as I,M as kn,b as On,a as Jt}from"./index-C9TH5IEG.js";const Tn=[["circle",{cx:"9",cy:"12",r:"1",key:"1vctgf"}],["circle",{cx:"9",cy:"5",r:"1",key:"hp0tcf"}],["circle",{cx:"9",cy:"19",r:"1",key:"fkjjf6"}],["circle",{cx:"15",cy:"12",r:"1",key:"1tmaij"}],["circle",{cx:"15",cy:"5",r:"1",key:"19l28e"}],["circle",{cx:"15",cy:"19",r:"1",key:"f4zoj3"}]],Qt=tt("grip-vertical",Tn);const Ln=[["rect",{width:"18",height:"11",x:"3",y:"11",rx:"2",ry:"2",key:"1w4ew1"}],["path",{d:"M7 11V7a5 5 0 0 1 9.9-1",key:"1mm8w8"}]],jn=tt("lock-open",Ln);const zn=[["rect",{width:"18",height:"11",x:"3",y:"11",rx:"2",ry:"2",key:"1w4ew1"}],["path",{d:"M7 11V7a5 5 0 0 1 10 0v4",key:"fwvmzm"}]],jt=tt("lock",zn);const $n=[["path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"1357e3"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}]],Bn=tt("rotate-ccw",$n);function Pn(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return c.useMemo(()=>r=>{t.forEach(o=>o(r))},t)}const nt=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";function xe(e){const t=Object.prototype.toString.call(e);return t==="[object Window]"||t==="[object global]"}function mt(e){return"nodeType"in e}function B(e){var t,n;return e?xe(e)?e:mt(e)&&(t=(n=e.ownerDocument)==null?void 0:n.defaultView)!=null?t:window:window}function yt(e){const{Document:t}=B(e);return e instanceof t}function Pe(e){return xe(e)?!1:e instanceof B(e).HTMLElement}function Zt(e){return e instanceof B(e).SVGElement}function we(e){return e?xe(e)?e.document:mt(e)?yt(e)?e:Pe(e)||Zt(e)?e.ownerDocument:document:document:document}const Z=nt?c.useLayoutEffect:c.useEffect;function xt(e){const t=c.useRef(e);return Z(()=>{t.current=e}),c.useCallback(function(){for(var n=arguments.length,r=new Array(n),o=0;o<n;o++)r[o]=arguments[o];return t.current==null?void 0:t.current(...r)},[])}function Fn(){const e=c.useRef(null),t=c.useCallback((r,o)=>{e.current=setInterval(r,o)},[]),n=c.useCallback(()=>{e.current!==null&&(clearInterval(e.current),e.current=null)},[]);return[t,n]}function je(e,t){t===void 0&&(t=[e]);const n=c.useRef(e);return Z(()=>{n.current!==e&&(n.current=e)},t),n}function Fe(e,t){const n=c.useRef();return c.useMemo(()=>{const r=e(n.current);return n.current=r,r},[...t])}function Je(e){const t=xt(e),n=c.useRef(null),r=c.useCallback(o=>{o!==n.current&&t?.(o,n.current),n.current=o},[]);return[n,r]}function ht(e){const t=c.useRef();return c.useEffect(()=>{t.current=e},[e]),t.current}let lt={};function Xe(e,t){return c.useMemo(()=>{if(t)return t;const n=lt[e]==null?0:lt[e]+1;return lt[e]=n,e+"-"+n},[e,t])}function en(e){return function(t){for(var n=arguments.length,r=new Array(n>1?n-1:0),o=1;o<n;o++)r[o-1]=arguments[o];return r.reduce((i,s)=>{const a=Object.entries(s);for(const[l,u]of a){const f=i[l];f!=null&&(i[l]=f+e*u)}return i},{...t})}}const ye=en(1),ze=en(-1);function Xn(e){return"clientX"in e&&"clientY"in e}function wt(e){if(!e)return!1;const{KeyboardEvent:t}=B(e.target);return t&&e instanceof t}function Un(e){if(!e)return!1;const{TouchEvent:t}=B(e.target);return t&&e instanceof t}function gt(e){if(Un(e)){if(e.touches&&e.touches.length){const{clientX:t,clientY:n}=e.touches[0];return{x:t,y:n}}else if(e.changedTouches&&e.changedTouches.length){const{clientX:t,clientY:n}=e.changedTouches[0];return{x:t,y:n}}}return Xn(e)?{x:e.clientX,y:e.clientY}:null}const $e=Object.freeze({Translate:{toString(e){if(!e)return;const{x:t,y:n}=e;return"translate3d("+(t?Math.round(t):0)+"px, "+(n?Math.round(n):0)+"px, 0)"}},Scale:{toString(e){if(!e)return;const{scaleX:t,scaleY:n}=e;return"scaleX("+t+") scaleY("+n+")"}},Transform:{toString(e){if(e)return[$e.Translate.toString(e),$e.Scale.toString(e)].join(" ")}},Transition:{toString(e){let{property:t,duration:n,easing:r}=e;return t+" "+n+"ms "+r}}}),zt="a,frame,iframe,input:not([type=hidden]):not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),*[tabindex]";function Yn(e){return e.matches(zt)?e:e.querySelector(zt)}const Wn={display:"none"};function Vn(e){let{id:t,value:n}=e;return $.createElement("div",{id:t,style:Wn},n)}function Hn(e){let{id:t,announcement:n,ariaLiveType:r="assertive"}=e;const o={position:"fixed",top:0,left:0,width:1,height:1,margin:-1,border:0,padding:0,overflow:"hidden",clip:"rect(0 0 0 0)",clipPath:"inset(100%)",whiteSpace:"nowrap"};return $.createElement("div",{id:t,style:o,role:"status","aria-live":r,"aria-atomic":!0},n)}function Kn(){const[e,t]=c.useState("");return{announce:c.useCallback(r=>{r!=null&&t(r)},[]),announcement:e}}const tn=c.createContext(null);function _n(e){const t=c.useContext(tn);c.useEffect(()=>{if(!t)throw new Error("useDndMonitor must be used within a children of <DndContext>");return t(e)},[e,t])}function qn(){const[e]=c.useState(()=>new Set),t=c.useCallback(r=>(e.add(r),()=>e.delete(r)),[e]);return[c.useCallback(r=>{let{type:o,event:i}=r;e.forEach(s=>{var a;return(a=s[o])==null?void 0:a.call(s,i)})},[e]),t]}const Gn={draggable:`
1
+ import{g as tt,i as c,R as $,r as ke,j as I,M as kn,e as On,c as Jt}from"./index-CF3q3aV_.js";const Tn=[["circle",{cx:"9",cy:"12",r:"1",key:"1vctgf"}],["circle",{cx:"9",cy:"5",r:"1",key:"hp0tcf"}],["circle",{cx:"9",cy:"19",r:"1",key:"fkjjf6"}],["circle",{cx:"15",cy:"12",r:"1",key:"1tmaij"}],["circle",{cx:"15",cy:"5",r:"1",key:"19l28e"}],["circle",{cx:"15",cy:"19",r:"1",key:"f4zoj3"}]],Qt=tt("grip-vertical",Tn);const Ln=[["rect",{width:"18",height:"11",x:"3",y:"11",rx:"2",ry:"2",key:"1w4ew1"}],["path",{d:"M7 11V7a5 5 0 0 1 9.9-1",key:"1mm8w8"}]],jn=tt("lock-open",Ln);const zn=[["rect",{width:"18",height:"11",x:"3",y:"11",rx:"2",ry:"2",key:"1w4ew1"}],["path",{d:"M7 11V7a5 5 0 0 1 10 0v4",key:"fwvmzm"}]],jt=tt("lock",zn);const $n=[["path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"1357e3"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}]],Bn=tt("rotate-ccw",$n);function Pn(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return c.useMemo(()=>r=>{t.forEach(o=>o(r))},t)}const nt=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";function xe(e){const t=Object.prototype.toString.call(e);return t==="[object Window]"||t==="[object global]"}function mt(e){return"nodeType"in e}function B(e){var t,n;return e?xe(e)?e:mt(e)&&(t=(n=e.ownerDocument)==null?void 0:n.defaultView)!=null?t:window:window}function yt(e){const{Document:t}=B(e);return e instanceof t}function Pe(e){return xe(e)?!1:e instanceof B(e).HTMLElement}function Zt(e){return e instanceof B(e).SVGElement}function we(e){return e?xe(e)?e.document:mt(e)?yt(e)?e:Pe(e)||Zt(e)?e.ownerDocument:document:document:document}const Z=nt?c.useLayoutEffect:c.useEffect;function xt(e){const t=c.useRef(e);return Z(()=>{t.current=e}),c.useCallback(function(){for(var n=arguments.length,r=new Array(n),o=0;o<n;o++)r[o]=arguments[o];return t.current==null?void 0:t.current(...r)},[])}function Fn(){const e=c.useRef(null),t=c.useCallback((r,o)=>{e.current=setInterval(r,o)},[]),n=c.useCallback(()=>{e.current!==null&&(clearInterval(e.current),e.current=null)},[]);return[t,n]}function je(e,t){t===void 0&&(t=[e]);const n=c.useRef(e);return Z(()=>{n.current!==e&&(n.current=e)},t),n}function Fe(e,t){const n=c.useRef();return c.useMemo(()=>{const r=e(n.current);return n.current=r,r},[...t])}function Je(e){const t=xt(e),n=c.useRef(null),r=c.useCallback(o=>{o!==n.current&&t?.(o,n.current),n.current=o},[]);return[n,r]}function ht(e){const t=c.useRef();return c.useEffect(()=>{t.current=e},[e]),t.current}let lt={};function Xe(e,t){return c.useMemo(()=>{if(t)return t;const n=lt[e]==null?0:lt[e]+1;return lt[e]=n,e+"-"+n},[e,t])}function en(e){return function(t){for(var n=arguments.length,r=new Array(n>1?n-1:0),o=1;o<n;o++)r[o-1]=arguments[o];return r.reduce((i,s)=>{const a=Object.entries(s);for(const[l,u]of a){const f=i[l];f!=null&&(i[l]=f+e*u)}return i},{...t})}}const ye=en(1),ze=en(-1);function Xn(e){return"clientX"in e&&"clientY"in e}function wt(e){if(!e)return!1;const{KeyboardEvent:t}=B(e.target);return t&&e instanceof t}function Un(e){if(!e)return!1;const{TouchEvent:t}=B(e.target);return t&&e instanceof t}function gt(e){if(Un(e)){if(e.touches&&e.touches.length){const{clientX:t,clientY:n}=e.touches[0];return{x:t,y:n}}else if(e.changedTouches&&e.changedTouches.length){const{clientX:t,clientY:n}=e.changedTouches[0];return{x:t,y:n}}}return Xn(e)?{x:e.clientX,y:e.clientY}:null}const $e=Object.freeze({Translate:{toString(e){if(!e)return;const{x:t,y:n}=e;return"translate3d("+(t?Math.round(t):0)+"px, "+(n?Math.round(n):0)+"px, 0)"}},Scale:{toString(e){if(!e)return;const{scaleX:t,scaleY:n}=e;return"scaleX("+t+") scaleY("+n+")"}},Transform:{toString(e){if(e)return[$e.Translate.toString(e),$e.Scale.toString(e)].join(" ")}},Transition:{toString(e){let{property:t,duration:n,easing:r}=e;return t+" "+n+"ms "+r}}}),zt="a,frame,iframe,input:not([type=hidden]):not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),*[tabindex]";function Yn(e){return e.matches(zt)?e:e.querySelector(zt)}const Wn={display:"none"};function Vn(e){let{id:t,value:n}=e;return $.createElement("div",{id:t,style:Wn},n)}function Hn(e){let{id:t,announcement:n,ariaLiveType:r="assertive"}=e;const o={position:"fixed",top:0,left:0,width:1,height:1,margin:-1,border:0,padding:0,overflow:"hidden",clip:"rect(0 0 0 0)",clipPath:"inset(100%)",whiteSpace:"nowrap"};return $.createElement("div",{id:t,style:o,role:"status","aria-live":r,"aria-atomic":!0},n)}function Kn(){const[e,t]=c.useState("");return{announce:c.useCallback(r=>{r!=null&&t(r)},[]),announcement:e}}const tn=c.createContext(null);function _n(e){const t=c.useContext(tn);c.useEffect(()=>{if(!t)throw new Error("useDndMonitor must be used within a children of <DndContext>");return t(e)},[e,t])}function qn(){const[e]=c.useState(()=>new Set),t=c.useCallback(r=>(e.add(r),()=>e.delete(r)),[e]);return[c.useCallback(r=>{let{type:o,event:i}=r;e.forEach(s=>{var a;return(a=s[o])==null?void 0:a.call(s,i)})},[e]),t]}const Gn={draggable:`
2
2
  To pick up a draggable item, press the space bar.
3
3
  While dragging, use the arrow keys to move the item.
4
4
  Press space again to drop the item in its new position, or press escape to cancel.
@@ -0,0 +1 @@
1
+ import{n as $,u as O,m as L,p as T,o as J,l as R,k as B,i as u,j as t,E as K,d as z,B as D,L as I,h as M,f as q,q as G,C as H,a as F,F as U,A as V}from"./index-CF3q3aV_.js";function W(i){return i.normalize("NFKD").replace(/[̀-ͯ]/g,"").toLowerCase().trim().replace(/[^a-z0-9\s-]/g,"").replace(/[\s-]+/g,"-").replace(/^-+|-+$/g,"")}function Q({values:i,prepopulated:c,editedTargets:d}){const a={...i};for(const[y,b]of Object.entries(c)){if(d.has(y))continue;const h=b.map(p=>a[p]==null?"":String(a[p])).join(" ");a[y]=W(h)}return a}function Z(){const i=$(),c=i.appLabel??"",d=i.modelName??"",a=O(),y=L(),b=T(),[h]=J(),p=R(`/${c}/${d}`,h),{singular:g,plural:v}=B(c,d),[S,C]=u.useState(null),[A,N]=u.useState(null),[k,j]=u.useState(0);return u.useEffect(()=>{let f=!0;return C(null),N(null),a.addForm(c,d).then(o=>{f&&C(o)}).catch(o=>{f&&N(o instanceof Error?o.message:"Could not load the add form.")}),()=>{f=!1}},[a,c,d]),A?t.jsx(K,{title:"Couldn't open the add form",description:A}):S?t.jsxs("div",{className:"space-y-4",children:[t.jsxs("header",{className:"space-y-1",children:[t.jsx(D,{items:[{label:"Home",to:"/"},{label:v,to:p},{label:`Add ${g}`}],renderLink:(f,o,E)=>t.jsx(I,{to:f,className:o,children:E})}),t.jsxs("h1",{className:"text-2xl font-semibold",children:["Add ",g]})]}),t.jsx(X,{schema:S,onCreate:async(f,o)=>{const E=await M({client:a,appLabel:c,modelName:d,payload:f});if(b.success("Added."),o==="addAnother"){j(x=>x+1);return}if(o==="continue"){y(q(`/${c}/${d}/${E.pk}?edit=1`,h));return}y(p)},onCancel:()=>y(p)},k)]}):t.jsx(z,{})}function X({schema:i,onCreate:c,onCancel:d}){const[a,y]=u.useState(()=>{const e={};for(const[n,r]of Object.entries(i.fields)){if(r.readonly)continue;if(r.type==="manytomany"){e[n]=[];continue}const s=r.value;if(r.type==="json"){e[n]=s==null?null:JSON.stringify(s,null,2);continue}if(r.type==="array"){e[n]=Array.isArray(s)?s.join(","):null;continue}if(r.type==="range"){if(s&&typeof s=="object"&&"value"in s){const m=s.value;if(m&&typeof m=="object"){const l=m.lower,_=m.upper;e[n]=[l==null?"":String(l),_==null?"":String(_)];continue}}e[n]=["",""];continue}e[n]=s!==null&&typeof s!="object"?s:null}return e}),[b,h]=u.useState({}),[p,g]=u.useState(null),[v,S]=u.useState(!1),C=i.prepopulated_fields??{},A=new Set(Object.keys(C)),N=u.useRef(new Set);function k(e,n){y(r=>(A.has(e)&&N.current.add(e),Q({values:{...r,[e]:n},prepopulated:C,editedTargets:N.current})))}const j=u.useRef(null);j.current===null&&(j.current=JSON.stringify(a));const f=JSON.stringify(a)!==j.current;G(f&&!v);async function o(e){S(!0),h({}),g(null);try{await c(a,e),j.current=JSON.stringify(a)}catch(n){if(n instanceof V&&n.envelope?.error){const{[""]:r,...s}=n.envelope.error.fields??{};h(s);const m=r?.join(" ")||(Object.keys(s).length===0?n.envelope.error.message:"");g(m||null)}else g(n instanceof Error?n.message:"Create failed.")}finally{S(!1)}}async function E(e){e.preventDefault(),await o("save")}const x=i.save_options,w=()=>t.jsxs("div",{className:"flex flex-wrap gap-2",children:[(x?.show_save??!0)&&t.jsx(F,{type:"submit",variant:"primary",disabled:v,children:v?"Saving…":"Add"}),x?.show_save_and_add_another&&t.jsx(F,{type:"button",variant:"secondary",disabled:v,onClick:()=>{o("addAnother")},children:"Save and add another"}),x?.show_save_and_continue&&t.jsx(F,{type:"button",variant:"secondary",disabled:v,onClick:()=>{o("continue")},children:"Save and continue editing"}),t.jsx(F,{type:"button",variant:"ghost",onClick:d,disabled:v,children:"Cancel"})]});return t.jsxs("form",{onSubmit:E,className:"space-y-4",children:[p&&t.jsx("div",{className:"rounded border border-red-300 bg-red-50 px-3 py-2 text-sm text-red-700",children:p}),x?.save_on_top&&w(),i.fieldsets.map((e,n)=>t.jsx(H,{title:e.title??void 0,children:t.jsx("div",{className:"divide-y divide-gray-100",children:(e.field_rows??e.fields.map(r=>[r])).map((r,s)=>{const m=l=>{const _=i.fields[l];return _?t.jsx(U,{name:l,field:_,value:a[l]??null,error:b[l],onChange:P=>k(l,P)},l):null};return r.length===1?m(r[0]):t.jsx("div",{className:"grid gap-4 py-1",style:{gridTemplateColumns:`repeat(${r.length}, minmax(0, 1fr))`},children:r.map(l=>m(l))},s)})})},`cfs-${n}-${e.title??"default"}`)),w()]})}export{Z as CreatePage};
@@ -1 +1 @@
1
- import{c as d,d as l,j as e,C as h}from"./index-C9TH5IEG.js";const p=[["path",{d:"m9 18 6-6-6-6",key:"mthhwq"}]],g=d("chevron-right",p);const y=[["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2",key:"17jyea"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2",key:"zix9uf"}]],j=d("copy",y);function N({raw:t,parsed:r}){const[s,c]=l.useState(!1);async function a(){try{await navigator.clipboard.writeText(t),c(!0),setTimeout(()=>c(!1),2e3)}catch{}}return e.jsxs("div",{className:"relative w-full overflow-x-auto rounded border border-gray-200 bg-gray-50 p-3 font-mono text-xs leading-relaxed text-gray-800 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-200",children:[e.jsx("button",{type:"button",onClick:a,"aria-label":"Copy JSON",title:s?"Copied":"Copy",className:"absolute right-2 top-2 inline-flex h-6 w-6 items-center justify-center rounded border border-gray-300 bg-white text-gray-600 hover:bg-gray-100 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-300 dark:hover:bg-gray-700",children:s?e.jsx(h,{className:"h-3.5 w-3.5 text-green-600","aria-hidden":!0}):e.jsx(j,{className:"h-3.5 w-3.5","aria-hidden":!0})}),e.jsx(o,{value:r,depth:0})]})}function o({value:t,depth:r}){return t===null?e.jsx("span",{className:"text-purple-600 dark:text-purple-400",children:"null"}):typeof t=="boolean"?e.jsx("span",{className:"text-purple-600 dark:text-purple-400",children:t?"true":"false"}):typeof t=="number"?e.jsx("span",{className:"text-blue-700",children:String(t)}):typeof t=="string"?e.jsxs("span",{className:"text-green-700 dark:text-green-400",children:['"',t,'"']}):Array.isArray(t)?e.jsx(u,{value:t,depth:r}):typeof t=="object"?e.jsx(m,{value:t,depth:r}):e.jsx("span",{className:"text-gray-500",children:String(t)})}function m({value:t,depth:r}){const s=Object.keys(t),[c,a]=l.useState(r<2);return s.length===0?e.jsx("span",{className:"text-gray-500",children:"{}"}):e.jsx(x,{open:c,onToggle:()=>a(n=>!n),collapsedLabel:`{…} ${s.length} ${s.length===1?"key":"keys"}`,openBracket:"{",closeBracket:"}",depth:r,children:s.map((n,i)=>e.jsxs("div",{className:"pl-4",children:[e.jsxs("span",{className:"text-rose-700 dark:text-rose-400",children:['"',n,'"']}),e.jsx("span",{className:"text-gray-500",children:": "}),e.jsx(o,{value:t[n],depth:r+1}),i<s.length-1?e.jsx("span",{className:"text-gray-500",children:","}):null]},n))})}function u({value:t,depth:r}){const[s,c]=l.useState(r<2);return t.length===0?e.jsx("span",{className:"text-gray-500",children:"[]"}):e.jsx(x,{open:s,onToggle:()=>c(a=>!a),collapsedLabel:`[…] ${t.length} ${t.length===1?"item":"items"}`,openBracket:"[",closeBracket:"]",depth:r,children:t.map((a,n)=>e.jsxs("div",{className:"pl-4",children:[e.jsx(o,{value:a,depth:r+1}),n<t.length-1?e.jsx("span",{className:"text-gray-500",children:","}):null]},n))})}function x({open:t,onToggle:r,collapsedLabel:s,openBracket:c,closeBracket:a,depth:n,children:i}){return e.jsxs("span",{children:[e.jsx("button",{type:"button",onClick:r,"aria-expanded":t,className:"inline-flex items-center align-baseline text-gray-500 hover:text-gray-800 dark:hover:text-gray-200",children:e.jsx(g,{className:`h-3 w-3 shrink-0 transition-transform ${t?"rotate-90":""}`,"aria-hidden":!0})}),e.jsx("span",{className:"text-gray-500",children:c}),t?e.jsxs(e.Fragment,{children:[i,e.jsx("div",{className:n===0?"":"pl-0",children:e.jsx("span",{className:"text-gray-500",children:a})})]}):e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"px-1 text-gray-500",children:s}),e.jsx("span",{className:"text-gray-500",children:a})]})]})}export{N as default};
1
+ import{g as x,i as l,j as e,b as g}from"./index-CF3q3aV_.js";const h=[["path",{d:"m9 18 6-6-6-6",key:"mthhwq"}]],p=x("chevron-right",h);const y=[["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2",key:"17jyea"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2",key:"zix9uf"}]],j=x("copy",y);function N({raw:t,parsed:r}){const[s,c]=l.useState(!1);async function a(){try{await navigator.clipboard.writeText(t),c(!0),setTimeout(()=>c(!1),2e3)}catch{}}return e.jsxs("div",{className:"relative w-full overflow-x-auto rounded border border-gray-200 bg-gray-50 p-3 font-mono text-xs leading-relaxed text-gray-800 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-200",children:[e.jsx("button",{type:"button",onClick:a,"aria-label":"Copy JSON",title:s?"Copied":"Copy",className:"absolute right-2 top-2 inline-flex h-6 w-6 items-center justify-center rounded border border-gray-300 bg-white text-gray-600 hover:bg-gray-100 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-300 dark:hover:bg-gray-700",children:s?e.jsx(g,{className:"h-3.5 w-3.5 text-green-600","aria-hidden":!0}):e.jsx(j,{className:"h-3.5 w-3.5","aria-hidden":!0})}),e.jsx(o,{value:r,depth:0})]})}function o({value:t,depth:r}){return t===null?e.jsx("span",{className:"text-purple-600 dark:text-purple-400",children:"null"}):typeof t=="boolean"?e.jsx("span",{className:"text-purple-600 dark:text-purple-400",children:t?"true":"false"}):typeof t=="number"?e.jsx("span",{className:"text-blue-700",children:String(t)}):typeof t=="string"?e.jsxs("span",{className:"text-green-700 dark:text-green-400",children:['"',t,'"']}):Array.isArray(t)?e.jsx(u,{value:t,depth:r}):typeof t=="object"?e.jsx(m,{value:t,depth:r}):e.jsx("span",{className:"text-gray-500",children:String(t)})}function m({value:t,depth:r}){const s=Object.keys(t),[c,a]=l.useState(r<2);return s.length===0?e.jsx("span",{className:"text-gray-500",children:"{}"}):e.jsx(d,{open:c,onToggle:()=>a(n=>!n),collapsedLabel:`{…} ${s.length} ${s.length===1?"key":"keys"}`,openBracket:"{",closeBracket:"}",depth:r,children:s.map((n,i)=>e.jsxs("div",{className:"pl-4",children:[e.jsxs("span",{className:"text-rose-700 dark:text-rose-400",children:['"',n,'"']}),e.jsx("span",{className:"text-gray-500",children:": "}),e.jsx(o,{value:t[n],depth:r+1}),i<s.length-1?e.jsx("span",{className:"text-gray-500",children:","}):null]},n))})}function u({value:t,depth:r}){const[s,c]=l.useState(r<2);return t.length===0?e.jsx("span",{className:"text-gray-500",children:"[]"}):e.jsx(d,{open:s,onToggle:()=>c(a=>!a),collapsedLabel:`[…] ${t.length} ${t.length===1?"item":"items"}`,openBracket:"[",closeBracket:"]",depth:r,children:t.map((a,n)=>e.jsxs("div",{className:"pl-4",children:[e.jsx(o,{value:a,depth:r+1}),n<t.length-1?e.jsx("span",{className:"text-gray-500",children:","}):null]},n))})}function d({open:t,onToggle:r,collapsedLabel:s,openBracket:c,closeBracket:a,depth:n,children:i}){return e.jsxs("span",{children:[e.jsx("button",{type:"button",onClick:r,"aria-expanded":t,className:"inline-flex items-center align-baseline text-gray-500 hover:text-gray-800 dark:hover:text-gray-200",children:e.jsx(p,{className:`h-3 w-3 shrink-0 transition-transform ${t?"rotate-90":""}`,"aria-hidden":!0})}),e.jsx("span",{className:"text-gray-500",children:c}),t?e.jsxs(e.Fragment,{children:[i,e.jsx("div",{className:n===0?"":"pl-0",children:e.jsx("span",{className:"text-gray-500",children:a})})]}):e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"px-1 text-gray-500",children:s}),e.jsx("span",{className:"text-gray-500",children:a})]})]})}export{N as default};
@@ -0,0 +1 @@
1
+ import{u as j,i as r,j as e,C as v,I as u,a as w,A as c}from"./index-CF3q3aV_.js";function b({onSuccess:m,brandTitle:d}){const p=j(),[n,f]=r.useState(""),[i,x]=r.useState(""),[g,a]=r.useState(null),[o,l]=r.useState(!1);async function h(s){s.preventDefault(),a(null),l(!0);try{await p.login(n,i),m()}catch(t){t instanceof c&&t.status===403?a("Invalid credentials or insufficient permissions."):t instanceof c?a(t.message):a("Could not reach the server. Please try again."),l(!1)}}return e.jsx("div",{className:"flex min-h-screen items-center justify-center bg-gray-50 px-4",children:e.jsx(v,{className:"w-full max-w-sm",children:e.jsxs("form",{onSubmit:h,className:"flex flex-col gap-4 p-2",children:[e.jsx("h1",{className:"text-center text-lg font-semibold text-gray-900",children:d??"Sign in"}),e.jsx(u,{label:"Username",name:"username",autoComplete:"username",autoFocus:!0,required:!0,value:n,onChange:s=>f(s.target.value)}),e.jsx(u,{label:"Password",name:"password",type:"password",autoComplete:"current-password",required:!0,value:i,onChange:s=>x(s.target.value),error:g??void 0}),e.jsx(w,{type:"submit",variant:"primary",loading:o,disabled:o,children:"Sign in"})]})})})}export{b as LoginPage};
@@ -0,0 +1 @@
1
+ *,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.container{width:100%}@media(min-width:640px){.container{max-width:640px}}@media(min-width:768px){.container{max-width:768px}}@media(min-width:1024px){.container{max-width:1024px}}@media(min-width:1280px){.container{max-width:1280px}}@media(min-width:1536px){.container{max-width:1536px}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.collapse{visibility:collapse}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.inset-x-0{left:0;right:0}.inset-y-0{top:0;bottom:0}.bottom-4{bottom:1rem}.left-0{left:0}.right-0{right:0}.right-2{right:.5rem}.right-4{right:1rem}.top-0{top:0}.top-2{top:.5rem}.isolate{isolation:isolate}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.z-\[100\]{z-index:100}.z-\[200\]{z-index:200}.col-span-2{grid-column:span 2 / span 2}.m-6{margin:1.5rem}.m-auto{margin:auto}.-mx-6{margin-left:-1.5rem;margin-right:-1.5rem}.-ml-2{margin-left:-.5rem}.-mt-6{margin-top:-1.5rem}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.ml-auto{margin-left:auto}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-1\.5{margin-top:.375rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.block{display:block}.inline-block{display:inline-block}.\!inline{display:inline!important}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.contents{display:contents}.hidden{display:none}.h-10{height:2.5rem}.h-14{height:3.5rem}.h-2{height:.5rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-48{height:12rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-7{height:1.75rem}.h-9{height:2.25rem}.h-\[70vh\]{height:70vh}.h-auto{height:auto}.h-full{height:100%}.max-h-48{max-height:12rem}.max-h-60{max-height:15rem}.max-h-72{max-height:18rem}.max-h-\[85vh\]{max-height:85vh}.min-h-\[6rem\]{min-height:6rem}.min-h-screen{min-height:100vh}.w-1\.5{width:.375rem}.w-1\/3{width:33.333333%}.w-10{width:2.5rem}.w-2{width:.5rem}.w-2\/3{width:66.666667%}.w-20{width:5rem}.w-24{width:6rem}.w-28{width:7rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-3\/4{width:75%}.w-32{width:8rem}.w-4{width:1rem}.w-40{width:10rem}.w-48{width:12rem}.w-5{width:1.25rem}.w-56{width:14rem}.w-6{width:1.5rem}.w-64{width:16rem}.w-72{width:18rem}.w-80{width:20rem}.w-full{width:100%}.min-w-0{min-width:0px}.min-w-56{min-width:14rem}.min-w-\[12rem\]{min-width:12rem}.min-w-\[14rem\]{min-width:14rem}.min-w-full{min-width:100%}.max-w-\[12rem\]{max-width:12rem}.max-w-\[16rem\]{max-width:16rem}.max-w-\[calc\(100vw-2rem\)\]{max-width:calc(100vw - 2rem)}.max-w-full{max-width:100%}.max-w-md{max-width:28rem}.max-w-prose{max-width:65ch}.max-w-sm{max-width:24rem}.flex-1{flex:1 1 0%}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.table-fixed{table-layout:fixed}.-translate-x-full{--tw-translate-x: -100%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-0{--tw-translate-x: 0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-rotate-90{--tw-rotate: -90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-180{--tw-rotate: 180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-90{--tw-rotate: 90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.cursor-col-resize{cursor:col-resize}.cursor-grab{cursor:grab}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.cursor-wait{cursor:wait}.touch-none{touch-action:none}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize{resize:both}.list-disc{list-style-type:disc}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-x-4{-moz-column-gap:1rem;column-gap:1rem}.gap-y-2{row-gap:.5rem}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.space-y-8>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(2rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2rem * var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.divide-gray-100>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:rgb(243 244 246 / var(--tw-divide-opacity, 1))}.divide-gray-200>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:rgb(229 231 235 / var(--tw-divide-opacity, 1))}.divide-gray-700>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:rgb(55 65 81 / var(--tw-divide-opacity, 1))}.self-start{align-self:flex-start}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-normal{white-space:normal}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-balance{text-wrap:balance}.break-words{overflow-wrap:break-word}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-t-xl{border-top-left-radius:.75rem;border-top-right-radius:.75rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-t{border-top-width:1px}.border-amber-300{--tw-border-opacity: 1;border-color:rgb(252 211 77 / var(--tw-border-opacity, 1))}.border-blue-300{--tw-border-opacity: 1;border-color:rgb(147 197 253 / var(--tw-border-opacity, 1))}.border-blue-600{--tw-border-opacity: 1;border-color:rgb(37 99 235 / var(--tw-border-opacity, 1))}.border-gray-200{--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity, 1))}.border-gray-300{--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1))}.border-gray-600{--tw-border-opacity: 1;border-color:rgb(75 85 99 / var(--tw-border-opacity, 1))}.border-gray-700{--tw-border-opacity: 1;border-color:rgb(55 65 81 / var(--tw-border-opacity, 1))}.border-green-300{--tw-border-opacity: 1;border-color:rgb(134 239 172 / var(--tw-border-opacity, 1))}.border-primary{border-color:var(--dar-primary, #2563eb)}.border-red-300{--tw-border-opacity: 1;border-color:rgb(252 165 165 / var(--tw-border-opacity, 1))}.border-red-400{--tw-border-opacity: 1;border-color:rgb(248 113 113 / var(--tw-border-opacity, 1))}.border-red-500{--tw-border-opacity: 1;border-color:rgb(239 68 68 / var(--tw-border-opacity, 1))}.border-red-600{--tw-border-opacity: 1;border-color:rgb(220 38 38 / var(--tw-border-opacity, 1))}.border-transparent{border-color:transparent}.bg-amber-50{--tw-bg-opacity: 1;background-color:rgb(255 251 235 / var(--tw-bg-opacity, 1))}.bg-black\/50{background-color:#00000080}.bg-blue-50{--tw-bg-opacity: 1;background-color:rgb(239 246 255 / var(--tw-bg-opacity, 1))}.bg-blue-500{--tw-bg-opacity: 1;background-color:rgb(59 130 246 / var(--tw-bg-opacity, 1))}.bg-blue-600{--tw-bg-opacity: 1;background-color:rgb(37 99 235 / var(--tw-bg-opacity, 1))}.bg-gray-100{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}.bg-gray-200{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}.bg-gray-400{--tw-bg-opacity: 1;background-color:rgb(156 163 175 / var(--tw-bg-opacity, 1))}.bg-gray-50{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.bg-gray-700{--tw-bg-opacity: 1;background-color:rgb(55 65 81 / var(--tw-bg-opacity, 1))}.bg-gray-800{--tw-bg-opacity: 1;background-color:rgb(31 41 55 / var(--tw-bg-opacity, 1))}.bg-gray-900{--tw-bg-opacity: 1;background-color:rgb(17 24 39 / var(--tw-bg-opacity, 1))}.bg-green-50{--tw-bg-opacity: 1;background-color:rgb(240 253 244 / var(--tw-bg-opacity, 1))}.bg-green-500{--tw-bg-opacity: 1;background-color:rgb(34 197 94 / var(--tw-bg-opacity, 1))}.bg-primary{background-color:var(--dar-primary, #2563eb)}.bg-red-50{--tw-bg-opacity: 1;background-color:rgb(254 242 242 / var(--tw-bg-opacity, 1))}.bg-red-500{--tw-bg-opacity: 1;background-color:rgb(239 68 68 / var(--tw-bg-opacity, 1))}.bg-red-600{--tw-bg-opacity: 1;background-color:rgb(220 38 38 / var(--tw-bg-opacity, 1))}.bg-transparent{background-color:transparent}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.fill-amber-400{fill:#fbbf24}.p-0\.5{padding:.125rem}.p-1{padding:.25rem}.p-1\.5{padding:.375rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pl-0{padding-left:0}.pl-4{padding-left:1rem}.pl-5{padding-left:1.25rem}.pr-3{padding-right:.75rem}.pt-1{padding-top:.25rem}.pt-20{padding-top:5rem}.pt-3{padding-top:.75rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-baseline{vertical-align:baseline}.align-top{vertical-align:top}.align-middle{vertical-align:middle}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-2xl{font-size:1.5rem;line-height:2rem}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.capitalize{text-transform:capitalize}.italic{font-style:italic}.leading-relaxed{line-height:1.625}.tracking-wide{letter-spacing:.025em}.text-amber-400{--tw-text-opacity: 1;color:rgb(251 191 36 / var(--tw-text-opacity, 1))}.text-amber-700{--tw-text-opacity: 1;color:rgb(180 83 9 / var(--tw-text-opacity, 1))}.text-amber-800{--tw-text-opacity: 1;color:rgb(146 64 14 / var(--tw-text-opacity, 1))}.text-blue-700{--tw-text-opacity: 1;color:rgb(29 78 216 / var(--tw-text-opacity, 1))}.text-gray-100{--tw-text-opacity: 1;color:rgb(243 244 246 / var(--tw-text-opacity, 1))}.text-gray-200{--tw-text-opacity: 1;color:rgb(229 231 235 / var(--tw-text-opacity, 1))}.text-gray-300{--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity, 1))}.text-gray-400{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.text-gray-500{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.text-gray-600{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.text-gray-700{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity, 1))}.text-gray-800{--tw-text-opacity: 1;color:rgb(31 41 55 / var(--tw-text-opacity, 1))}.text-gray-900{--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity, 1))}.text-green-600{--tw-text-opacity: 1;color:rgb(22 163 74 / var(--tw-text-opacity, 1))}.text-green-700{--tw-text-opacity: 1;color:rgb(21 128 61 / var(--tw-text-opacity, 1))}.text-inherit{color:inherit}.text-primary{color:var(--dar-primary, #2563eb)}.text-purple-600{--tw-text-opacity: 1;color:rgb(147 51 234 / var(--tw-text-opacity, 1))}.text-red-500{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.text-red-600{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.text-red-700{--tw-text-opacity: 1;color:rgb(185 28 28 / var(--tw-text-opacity, 1))}.text-rose-700{--tw-text-opacity: 1;color:rgb(190 18 60 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.underline{text-decoration-line:underline}.no-underline{text-decoration-line:none}.decoration-amber-500{text-decoration-color:#f59e0b}.underline-offset-2{text-underline-offset:2px}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.placeholder-gray-400::-moz-placeholder{--tw-placeholder-opacity: 1;color:rgb(156 163 175 / var(--tw-placeholder-opacity, 1))}.placeholder-gray-400::placeholder{--tw-placeholder-opacity: 1;color:rgb(156 163 175 / var(--tw-placeholder-opacity, 1))}.opacity-0{opacity:0}.opacity-25{opacity:.25}.opacity-40{opacity:.4}.opacity-75{opacity:.75}.shadow{--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / .1), 0 1px 2px -1px rgb(0 0 0 / .1);--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[2px_0_0_-1px_rgba\(0\,0\,0\,0\.06\)\]{--tw-shadow: 2px 0 0 -1px rgba(0,0,0,.06);--tw-shadow-colored: 2px 0 0 -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.ring{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.blur{--tw-blur: blur(8px);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.invert{--tw-invert: invert(100%);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}html,body,#root{height:100%}*{scrollbar-width:none;-ms-overflow-style:none}*::-webkit-scrollbar{display:none}.dark body{background-color:#0b1020;color:#e5e7eb}.dark .bg-white{background-color:#111827!important}.dark .bg-gray-50{background-color:#0b1020!important}.dark .bg-gray-200{background-color:#1f2937!important}.dark .text-gray-900,.dark .text-gray-800{color:#f3f4f6!important}.dark .text-gray-700,.dark .text-gray-600,.dark .text-gray-500{color:#9ca3af!important}.border-gray-200,.border-gray-300{border-color:#e5e7eb}.dark .border-gray-200,.dark .border-gray-300,.dark .border-gray-100{border-color:#2b3544!important}.dark .divide-gray-100>:not([hidden])~:not([hidden]),.dark .divide-gray-200>:not([hidden])~:not([hidden]){border-color:#1f2937!important}.dark .hover\:bg-gray-50:hover,.dark .hover\:bg-gray-100:hover{background-color:#1f2937!important}.dark .hover\:text-gray-900:hover,.dark .hover\:text-gray-800:hover,.dark .hover\:text-gray-700:hover{color:#f9fafb!important}.dark .hover\:text-gray-200:hover,.dark .hover\:text-gray-100:hover{color:#fff!important}.dar-table tbody tr{--dar-row-bg: #fff}.dar-table tbody tr:hover{--dar-row-bg: #f9fafb}.dar-table tbody tr[data-selected=true]{--dar-row-bg: #eff6ff;background-color:var(--dar-row-bg)}.dar-sticky-cell{background-color:var(--dar-row-bg)}.dark .dar-table tbody tr{--dar-row-bg: #111827}.dark .dar-table tbody tr:hover{--dar-row-bg: #1f2937}.dark .dar-table tbody tr[data-selected=true]{--dar-row-bg: #1e3a8a}.dark input:not([type=checkbox],[type=radio],[type=range]),.dark select,.dark textarea{background-color:#111827!important;color:#e5e7eb!important;border-color:#2b3544!important}.dark input::-moz-placeholder,.dark textarea::-moz-placeholder{color:#6b7280!important}.dark input::placeholder,.dark textarea::placeholder{color:#6b7280!important}.dark .bg-blue-50{background-color:#1e293b!important}.dark .text-blue-700{color:#93c5fd!important}.dark .bg-red-50{background-color:#3f1d1d!important}.dark .border-red-300,.dark .border-red-400{border-color:#7f1d1d!important}.dark .text-red-700,.dark .text-red-600{color:#fca5a5!important}.dark .bg-green-50{background-color:#14321f!important}.dark .text-green-700,.dark .text-green-600{color:#86efac!important}.dark .bg-amber-50{background-color:#3a2e12!important}.dark .border-amber-300{border-color:#92400e!important}.dark .text-amber-800,.dark .text-amber-700,.dark .text-amber-600{color:#fcd34d!important}.dark .bg-gray-100{background-color:#1f2937!important}table td>div>span,dl dd>span{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;color:#6b7280}.dark table td>div>span,.dark dl dd>span{color:#9ca3af}table td>div>span a,dl dd>span a{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;color:var(--dar-primary, #4f46e5)}table td>div>span a:hover,dl dd>span a:hover{text-decoration:underline}.dark table td>div>span a,.dark dl dd>span a{color:color-mix(in srgb,var(--dar-primary, #4f46e5) 65%,white)}.dark .text-primary{color:color-mix(in srgb,var(--dar-primary, #2563eb) 65%,white)}.checked\:border-primary:checked{border-color:var(--dar-primary, #2563eb)}.checked\:bg-primary:checked{background-color:var(--dar-primary, #2563eb)}.hover\:border-gray-200:hover{--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity, 1))}.hover\:bg-blue-400\/60:hover{background-color:#60a5fa99}.hover\:bg-blue-50:hover{--tw-bg-opacity: 1;background-color:rgb(239 246 255 / var(--tw-bg-opacity, 1))}.hover\:bg-blue-700:hover{--tw-bg-opacity: 1;background-color:rgb(29 78 216 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-100:hover{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-200:hover{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-50:hover{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-700:hover{--tw-bg-opacity: 1;background-color:rgb(55 65 81 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-800:hover{--tw-bg-opacity: 1;background-color:rgb(31 41 55 / var(--tw-bg-opacity, 1))}.hover\:bg-red-700:hover{--tw-bg-opacity: 1;background-color:rgb(185 28 28 / var(--tw-bg-opacity, 1))}.hover\:text-amber-500:hover{--tw-text-opacity: 1;color:rgb(245 158 11 / var(--tw-text-opacity, 1))}.hover\:text-gray-200:hover{--tw-text-opacity: 1;color:rgb(229 231 235 / var(--tw-text-opacity, 1))}.hover\:text-gray-600:hover{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.hover\:text-gray-700:hover{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity, 1))}.hover\:text-gray-800:hover{--tw-text-opacity: 1;color:rgb(31 41 55 / var(--tw-text-opacity, 1))}.hover\:text-gray-900:hover{--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity, 1))}.hover\:text-red-600:hover{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.hover\:text-white:hover{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.hover\:underline:hover{text-decoration-line:underline}.hover\:no-underline:hover{text-decoration-line:none}.hover\:decoration-amber-700:hover{text-decoration-color:#b45309}.hover\:opacity-90:hover{opacity:.9}.focus\:bg-gray-100:focus{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-1:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-gray-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(107 114 128 / var(--tw-ring-opacity, 1))}.focus\:ring-red-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(239 68 68 / var(--tw-ring-opacity, 1))}.focus-visible\:border-blue-500:focus-visible{--tw-border-opacity: 1;border-color:rgb(59 130 246 / var(--tw-border-opacity, 1))}.focus-visible\:outline-none:focus-visible{outline:2px solid transparent;outline-offset:2px}.focus-visible\:ring-1:focus-visible{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus-visible\:ring-2:focus-visible{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus-visible\:ring-inset:focus-visible{--tw-ring-inset: inset}.focus-visible\:ring-blue-500:focus-visible{--tw-ring-opacity: 1;--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1))}.focus-visible\:ring-gray-400:focus-visible{--tw-ring-opacity: 1;--tw-ring-color: rgb(156 163 175 / var(--tw-ring-opacity, 1))}.focus-visible\:ring-gray-500:focus-visible{--tw-ring-opacity: 1;--tw-ring-color: rgb(107 114 128 / var(--tw-ring-opacity, 1))}.focus-visible\:ring-offset-1:focus-visible{--tw-ring-offset-width: 1px}.active\:cursor-grabbing:active{cursor:grabbing}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:text-gray-400:disabled{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}.group:hover .group-hover\:opacity-100{opacity:1}.peer:checked~.peer-checked\:block{display:block}.dark\:border-gray-600:is(.dark *){--tw-border-opacity: 1;border-color:rgb(75 85 99 / var(--tw-border-opacity, 1))}.dark\:border-gray-700:is(.dark *){--tw-border-opacity: 1;border-color:rgb(55 65 81 / var(--tw-border-opacity, 1))}.dark\:bg-gray-800:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(31 41 55 / var(--tw-bg-opacity, 1))}.dark\:bg-gray-900:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(17 24 39 / var(--tw-bg-opacity, 1))}.dark\:text-gray-200:is(.dark *){--tw-text-opacity: 1;color:rgb(229 231 235 / var(--tw-text-opacity, 1))}.dark\:text-gray-300:is(.dark *){--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity, 1))}.dark\:text-green-400:is(.dark *){--tw-text-opacity: 1;color:rgb(74 222 128 / var(--tw-text-opacity, 1))}.dark\:text-purple-400:is(.dark *){--tw-text-opacity: 1;color:rgb(192 132 252 / var(--tw-text-opacity, 1))}.dark\:text-rose-400:is(.dark *){--tw-text-opacity: 1;color:rgb(251 113 133 / var(--tw-text-opacity, 1))}.dark\:hover\:bg-gray-700:hover:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(55 65 81 / var(--tw-bg-opacity, 1))}.dark\:hover\:text-gray-200:hover:is(.dark *){--tw-text-opacity: 1;color:rgb(229 231 235 / var(--tw-text-opacity, 1))}@media(min-width:640px){.sm\:max-w-md{max-width:28rem}.sm\:max-w-xs{max-width:20rem}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:grid-cols-\[1fr_1fr\]{grid-template-columns:1fr 1fr}.sm\:flex-row{flex-direction:row}.sm\:items-center{align-items:center}.sm\:justify-between{justify-content:space-between}.sm\:rounded-xl{border-radius:.75rem}}@media(min-width:768px){.md\:block{display:block}}@media(min-width:1024px){.lg\:static{position:static}.lg\:z-auto{z-index:auto}.lg\:-mx-6{margin-left:-1.5rem;margin-right:-1.5rem}.lg\:-mt-6{margin-top:-1.5rem}.lg\:hidden{display:none}.lg\:translate-x-0{--tw-translate-x: 0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:pt-6{padding-top:1.5rem}}