diff --git a/backend/news/330.feature b/backend/news/330.feature new file mode 100644 index 000000000..770d7750b --- /dev/null +++ b/backend/news/330.feature @@ -0,0 +1 @@ +Implemented content review & reminders features. @jntpk diff --git a/backend/scripts/review_reminder.py b/backend/scripts/review_reminder.py new file mode 100644 index 000000000..38862cf8c --- /dev/null +++ b/backend/scripts/review_reminder.py @@ -0,0 +1,10 @@ +from kitconcept.intranet.utils.review_due_notifier import nofity_reviewer +from plone import api +from zope.component.hooks import setSite + + +portal = app.Plone +setSite(portal) + +with api.env.adopt_roles(["Manager"]): + nofity_reviewer(portal) diff --git a/backend/src/kitconcept/intranet/behaviors/configure.zcml b/backend/src/kitconcept/intranet/behaviors/configure.zcml index 74299710a..c90cb1000 100644 --- a/backend/src/kitconcept/intranet/behaviors/configure.zcml +++ b/backend/src/kitconcept/intranet/behaviors/configure.zcml @@ -48,6 +48,13 @@ provides=".person.IPersonBehavior" /> + + str: + return api.portal.get_registry_record( + "kitconcept.intranet.content_review_default_interval" + ) + + +@provider(IFormFieldProvider) +class IContentReview(model.Schema): + """Content Review behavior""" + + model.fieldset( + "Content Review & Reminders", + label=_("label_review_fieldset", "Content Review & Reminders"), + fields=[ + "review_timeless", + "review_status", + "review_interval", + "review_assignee", + "review_due_date", + "review_completed_date", + ], + ) + + review_timeless = schema.Bool( + title=_( + "label_review_timeless", + default="Timeless content - exclude from review reminders", + ), + required=False, + default=False, + ) + + review_status = schema.Choice( + title=_("label_review_status", default="Status"), + values=("Up-to-date", "Due", "Changes requested"), + default="Up-to-date", + required=False, + readonly=True, + ) + + review_interval = schema.Choice( + title=_("label_review_interval", default="Review Interval"), + vocabulary="kitconcept.intranet.vocabularies.content_review_intervals", + required=False, + defaultFactory=default_review_interval, + ) + + review_assignee = schema.Choice( + title=_("label_review_assignee", default="Reviewer"), + description=_( + "help_review_assignee", + default="... will be notified as soon as the review is due. Unless otherwise specified, the content owner is considered the responsible person.", + ), + vocabulary="plone.app.vocabularies.Users", + required=False, + ) + + review_due_date = schema.Date( + title=_("label_review_due_date", default="Next review on"), + required=False, + defaultFactory=calc_due_date, + ) + + review_completed_date = schema.Date( + title=_("label_review_completed_date", default="Last review on"), + required=False, + readonly=True, + ) + + review_comment = schema.Text( + title=_("label_review_comment", default="Comment"), + required=False, + readonly=True, + ) + + @invariant + def validate_due_date_field(data): + is_timeless = getattr(data, "review_timeless", False) + has_due_date = getattr(data, "review_due_date", None) + if not is_timeless and not has_due_date: + raise Invalid("You have to set a due date if the content is not timeless") + elif is_timeless and has_due_date: + raise Invalid("Cannot set due date if content is timeless") diff --git a/backend/src/kitconcept/intranet/controlpanels/intranet.py b/backend/src/kitconcept/intranet/controlpanels/intranet.py index c558a0a30..196c7a4b1 100644 --- a/backend/src/kitconcept/intranet/controlpanels/intranet.py +++ b/backend/src/kitconcept/intranet/controlpanels/intranet.py @@ -87,6 +87,20 @@ class IIntranetSettings(Interface): defaultFactory=list, ) + enable_content_review = schema.Bool( + title=_("Enable Content Review"), + description=_("Enable content review reminders globally for the Intranet."), + required=False, + default=False, + ) + + content_review_default_interval = schema.Choice( + title=_("Default review interval"), + vocabulary="kitconcept.intranet.vocabularies.content_review_intervals", + required=True, + default="6m", + ) + class IntranetSettingsEditForm(RegistryEditForm): schema = IIntranetSettings @@ -140,3 +154,6 @@ def __call__(self, data): data["kitconcept.intranet.enable_content_rating"] = ( settings.enable_content_rating ) + data["kitconcept.intranet.enable_content_review"] = ( + settings.enable_content_review + ) diff --git a/backend/src/kitconcept/intranet/locales/de/LC_MESSAGES/kitconcept.intranet.po b/backend/src/kitconcept/intranet/locales/de/LC_MESSAGES/kitconcept.intranet.po index 8dca777a0..1fb5d9daa 100644 --- a/backend/src/kitconcept/intranet/locales/de/LC_MESSAGES/kitconcept.intranet.po +++ b/backend/src/kitconcept/intranet/locales/de/LC_MESSAGES/kitconcept.intranet.po @@ -1,7 +1,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: 2026-02-25 14:14+0000\n" +"POT-Creation-Date: 2026-06-11 08:48+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI +ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -40,7 +40,7 @@ msgstr "Akademischer Titel" #: kitconcept/intranet/behaviors/person.py:66 msgid "Academic Title, First and Last Name" -msgstr "" +msgstr "Akademischer Titel, Vor- und Nachname" #: kitconcept/intranet/behaviors/configure.zcml:49 msgid "Add the intranet-specific person fields" @@ -62,6 +62,10 @@ msgstr "Zulässige E-Mail-Domains" msgid "Allowed Iframe Domains" msgstr "Zulässige Iframe-Domains" +#: kitconcept/intranet/behaviors/configure.zcml:56 +msgid "CLM: Reminders for potentially outdated content" +msgstr "CLM: Hinweise auf möglicherweise veraltete Inhalte" + #: kitconcept/intranet/profiles/default/workflows/simple_intranet_workflow/definition.xml #: kitconcept/intranet/profiles/restricted/workflows/simple_intranet_workflow/definition.xml msgid "Can only be seen and edited by the owner." @@ -71,6 +75,10 @@ msgstr "Kann nur vom Eigentümer angesehen und bearbeitet werden." msgid "Default Feedback Email" msgstr "Standard-Feedback-E-Mail" +#: kitconcept/intranet/controlpanels/intranet.py:98 +msgid "Default review interval" +msgstr "Standard-Überprüfungsintervall" + #: kitconcept/intranet/behaviors/person.py:30 msgid "Department" msgstr "Abteilung" @@ -96,6 +104,10 @@ msgstr "E-Mail-Adresse, die in Feedback-Formularen verwendet wird, wenn keine an msgid "Enable Content Rating" msgstr "Inhaltsbewertung aktivieren" +#: kitconcept/intranet/controlpanels/intranet.py:91 +msgid "Enable Content Review" +msgstr "Inhaltsprüfung aktivieren" + #: kitconcept/intranet/behaviors/votes.py:23 msgid "Enable Likes" msgstr "Likes aktivieren" @@ -112,10 +124,30 @@ msgstr "Sticky-Feedback-Button aktivieren" msgid "Enable content rating globally for the Intranet" msgstr "Inhaltsbewertung für das Intranet global aktivieren" +#: kitconcept/intranet/controlpanels/intranet.py:92 +msgid "Enable content review reminders globally for the Intranet." +msgstr "Aktivieren Sie die Erinnerungen zur Inhaltsüberprüfung für das gesamte Intranet." + #: kitconcept/intranet/controlpanels/intranet.py:68 msgid "Enable or disable the sticky feedback button on all pages." msgstr "Aktivieren oder deaktivieren Sie die Sticky-Feedback-Schaltfläche auf allen Seiten." +#: kitconcept/intranet/vocabularies/content_review.py:12 +msgid "Every 2 years" +msgstr "Alle 2 Jahre" + +#: kitconcept/intranet/vocabularies/content_review.py:9 +msgid "Every 3 months" +msgstr "Alle 3 Monate" + +#: kitconcept/intranet/vocabularies/content_review.py:10 +msgid "Every 6 months" +msgstr "Alle 6 Monate" + +#: kitconcept/intranet/vocabularies/content_review.py:11 +msgid "Every year" +msgstr "Jedes Jahr" + #: kitconcept/intranet/controlpanels/intranet.py:21 msgid "External Search URL" msgstr "Externe Such-URL" @@ -132,6 +164,10 @@ msgstr "Felder für Standort" msgid "Fields for Organisational Unit" msgstr "Felder für Organisationseinheit" +#: kitconcept/intranet/behaviors/configure.zcml:56 +msgid "Fields for reviewing content (part of CLM)" +msgstr "Felder zur Überprüfung von Inhalten (Teil von CLM)" + #: kitconcept/intranet/profiles/default/workflows/simple_intranet_workflow/definition.xml #: kitconcept/intranet/profiles/restricted/workflows/simple_intranet_workflow/definition.xml msgid "If you submitted the item by mistake or want to perform additional edits, this will take it back." @@ -145,7 +181,7 @@ msgstr "Öffentlicher Intranet-Workflow" msgid "Intranet Restricted Workflow" msgstr "Intranet-beschränkter Workflow" -#: kitconcept/intranet/controlpanels/intranet.py:93 +#: kitconcept/intranet/controlpanels/intranet.py:107 msgid "Intranet Settings" msgstr "Intranet-Einstellungen" @@ -167,7 +203,7 @@ msgstr "Lebenszyklusmanagement-Felder" #: kitconcept/intranet/behaviors/votes.py:10 msgid "Likes" -msgstr "" +msgstr "Likes" #: kitconcept/intranet/controlpanels/intranet.py:61 msgid "List of allowed email domains for feedback forms." @@ -178,7 +214,7 @@ msgid "List of user IDs" msgstr "Liste der Benutzer-IDs" #: kitconcept/intranet/behaviors/configure.zcml:28 -#: kitconcept/intranet/behaviors/location.py:19 +#: kitconcept/intranet/behaviors/location.py:18 #: kitconcept/intranet/profiles/default/types/Location.xml msgid "Location" msgstr "Standort" @@ -198,7 +234,7 @@ msgid "No responsible person or default feedback email is configured. Please con msgstr "Es ist keine verantwortliche Person oder Standard-Feedback-E-Mail konfiguriert. Bitte wenden Sie sich an den Website-Administrator." #: kitconcept/intranet/behaviors/configure.zcml:35 -#: kitconcept/intranet/behaviors/organisational_unit.py:19 +#: kitconcept/intranet/behaviors/organisational_unit.py:18 #: kitconcept/intranet/profiles/default/types/Organisational_Unit.xml msgid "Organisational Unit" msgstr "Organisationseinheit" @@ -266,6 +302,10 @@ msgstr "Stellt Ihren Artikel in eine Überprüfungswarteschlange, damit er auf d msgid "Retract" msgstr "Zurückziehen" +#: kitconcept/intranet/profiles/default/registry/querystring.xml +msgid "Review" +msgstr "Rezension" + #: kitconcept/intranet/profiles/default/workflows/simple_intranet_workflow/definition.xml #: kitconcept/intranet/profiles/restricted/workflows/simple_intranet_workflow/definition.xml msgid "Reviewer publishes content" @@ -369,7 +409,17 @@ msgstr "Nach Standort filtern" #. Default: "Filter by responsibilities" #: kitconcept/intranet/profiles/default/registry/querystring.xml msgid "help_responsibilities_filter" -msgstr "" +msgstr "Nach Aufgaben filtern" + +#. Default: "... will be notified as soon as the review is due. Unless otherwise specified, the content owner is considered the responsible person." +#: kitconcept/intranet/behaviors/content_review.py:63 +msgid "help_review_assignee" +msgstr "... wird benachrichtigt, sobald die Überprüfung fällig ist. Sofern nicht anders angegeben, gilt der Inhaber der Inhalte als verantwortliche Person." + +#. Default: "Filter by review status" +#: kitconcept/intranet/profiles/default/registry/querystring.xml +msgid "help_review_status_filter" +msgstr "Nach Prüfstatus filtern" #. Default: "Describe what others can contact you about. Focus on topics, tasks, or questions you are responsible for, such as advising on specific funding programs, supporting application processes, or clarifying formal requirements. Write in a way that allows colleagues without detailed organisational knowledge to understand whether you are the right contact." #: kitconcept/intranet/behaviors/person.py:46 @@ -428,6 +478,47 @@ msgstr "Zuständigkeiten" msgid "label_responsible" msgstr "Inhaltseigentümer:" +#. Default: "Reviewer" +#: kitconcept/intranet/behaviors/content_review.py:62 +msgid "label_review_assignee" +msgstr "Rezensent" + +#. Default: "Comment" +#: kitconcept/intranet/behaviors/content_review.py:84 +msgid "label_review_comment" +msgstr "Kommentar" + +#. Default: "Last review on" +#: kitconcept/intranet/behaviors/content_review.py:78 +msgid "label_review_completed_date" +msgstr "Zuletzt überprüft am" + +#. Default: "Next review on" +#: kitconcept/intranet/behaviors/content_review.py:72 +msgid "label_review_due_date" +msgstr "Nächste Rezension zu" + +#. Default: "Content Review & Reminders" +#: kitconcept/intranet/behaviors/content_review.py:26 +msgid "label_review_fieldset" +msgstr "Inhaltsüberprüfung und Erinnerungen" + +#. Default: "Review Interval" +#: kitconcept/intranet/behaviors/content_review.py:55 +msgid "label_review_interval" +msgstr "Überprüfungsintervall" + +#. Default: "Status" +#: kitconcept/intranet/behaviors/content_review.py:47 +#: kitconcept/intranet/profiles/default/registry/querystring.xml +msgid "label_review_status" +msgstr "Status" + +#. Default: "Timeless content - exclude from review reminders" +#: kitconcept/intranet/behaviors/content_review.py:38 +msgid "label_review_timeless" +msgstr "Zeitlose Inhalte – von Überprüfungserinnerungen ausschließen" + #. Default: "Responsibilities & Expertise" #: kitconcept/intranet/behaviors/person.py:37 msgid "label_schema_responsibility_categorization" diff --git a/backend/src/kitconcept/intranet/locales/en/LC_MESSAGES/kitconcept.intranet.po b/backend/src/kitconcept/intranet/locales/en/LC_MESSAGES/kitconcept.intranet.po index b64977926..f661284dd 100644 --- a/backend/src/kitconcept/intranet/locales/en/LC_MESSAGES/kitconcept.intranet.po +++ b/backend/src/kitconcept/intranet/locales/en/LC_MESSAGES/kitconcept.intranet.po @@ -1,7 +1,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: 2026-02-25 14:14+0000\n" +"POT-Creation-Date: 2026-06-11 08:48+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI +ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -62,6 +62,10 @@ msgstr "" msgid "Allowed Iframe Domains" msgstr "" +#: kitconcept/intranet/behaviors/configure.zcml:56 +msgid "CLM: Reminders for potentially outdated content" +msgstr "" + #: kitconcept/intranet/profiles/default/workflows/simple_intranet_workflow/definition.xml #: kitconcept/intranet/profiles/restricted/workflows/simple_intranet_workflow/definition.xml msgid "Can only be seen and edited by the owner." @@ -71,6 +75,10 @@ msgstr "" msgid "Default Feedback Email" msgstr "" +#: kitconcept/intranet/controlpanels/intranet.py:98 +msgid "Default review interval" +msgstr "" + #: kitconcept/intranet/behaviors/person.py:30 msgid "Department" msgstr "" @@ -96,6 +104,10 @@ msgstr "" msgid "Enable Content Rating" msgstr "" +#: kitconcept/intranet/controlpanels/intranet.py:91 +msgid "Enable Content Review" +msgstr "" + #: kitconcept/intranet/behaviors/votes.py:23 msgid "Enable Likes" msgstr "" @@ -112,10 +124,30 @@ msgstr "" msgid "Enable content rating globally for the Intranet" msgstr "" +#: kitconcept/intranet/controlpanels/intranet.py:92 +msgid "Enable content review reminders globally for the Intranet." +msgstr "" + #: kitconcept/intranet/controlpanels/intranet.py:68 msgid "Enable or disable the sticky feedback button on all pages." msgstr "" +#: kitconcept/intranet/vocabularies/content_review.py:12 +msgid "Every 2 years" +msgstr "" + +#: kitconcept/intranet/vocabularies/content_review.py:9 +msgid "Every 3 months" +msgstr "" + +#: kitconcept/intranet/vocabularies/content_review.py:10 +msgid "Every 6 months" +msgstr "" + +#: kitconcept/intranet/vocabularies/content_review.py:11 +msgid "Every year" +msgstr "" + #: kitconcept/intranet/controlpanels/intranet.py:21 msgid "External Search URL" msgstr "" @@ -132,6 +164,10 @@ msgstr "" msgid "Fields for Organisational Unit" msgstr "" +#: kitconcept/intranet/behaviors/configure.zcml:56 +msgid "Fields for reviewing content (part of CLM)" +msgstr "" + #: kitconcept/intranet/profiles/default/workflows/simple_intranet_workflow/definition.xml #: kitconcept/intranet/profiles/restricted/workflows/simple_intranet_workflow/definition.xml msgid "If you submitted the item by mistake or want to perform additional edits, this will take it back." @@ -145,7 +181,7 @@ msgstr "" msgid "Intranet Restricted Workflow" msgstr "" -#: kitconcept/intranet/controlpanels/intranet.py:93 +#: kitconcept/intranet/controlpanels/intranet.py:107 msgid "Intranet Settings" msgstr "" @@ -178,7 +214,7 @@ msgid "List of user IDs" msgstr "" #: kitconcept/intranet/behaviors/configure.zcml:28 -#: kitconcept/intranet/behaviors/location.py:19 +#: kitconcept/intranet/behaviors/location.py:18 #: kitconcept/intranet/profiles/default/types/Location.xml msgid "Location" msgstr "" @@ -198,7 +234,7 @@ msgid "No responsible person or default feedback email is configured. Please con msgstr "" #: kitconcept/intranet/behaviors/configure.zcml:35 -#: kitconcept/intranet/behaviors/organisational_unit.py:19 +#: kitconcept/intranet/behaviors/organisational_unit.py:18 #: kitconcept/intranet/profiles/default/types/Organisational_Unit.xml msgid "Organisational Unit" msgstr "" @@ -266,6 +302,10 @@ msgstr "" msgid "Retract" msgstr "" +#: kitconcept/intranet/profiles/default/registry/querystring.xml +msgid "Review" +msgstr "" + #: kitconcept/intranet/profiles/default/workflows/simple_intranet_workflow/definition.xml #: kitconcept/intranet/profiles/restricted/workflows/simple_intranet_workflow/definition.xml msgid "Reviewer publishes content" @@ -371,6 +411,16 @@ msgstr "" msgid "help_responsibilities_filter" msgstr "" +#. Default: "... will be notified as soon as the review is due. Unless otherwise specified, the content owner is considered the responsible person." +#: kitconcept/intranet/behaviors/content_review.py:63 +msgid "help_review_assignee" +msgstr "" + +#. Default: "Filter by review status" +#: kitconcept/intranet/profiles/default/registry/querystring.xml +msgid "help_review_status_filter" +msgstr "" + #. Default: "Describe what others can contact you about. Focus on topics, tasks, or questions you are responsible for, such as advising on specific funding programs, supporting application processes, or clarifying formal requirements. Write in a way that allows colleagues without detailed organisational knowledge to understand whether you are the right contact." #: kitconcept/intranet/behaviors/person.py:46 msgid "help_tags" @@ -428,6 +478,47 @@ msgstr "" msgid "label_responsible" msgstr "" +#. Default: "Reviewer" +#: kitconcept/intranet/behaviors/content_review.py:62 +msgid "label_review_assignee" +msgstr "" + +#. Default: "Comment" +#: kitconcept/intranet/behaviors/content_review.py:84 +msgid "label_review_comment" +msgstr "" + +#. Default: "Last review on" +#: kitconcept/intranet/behaviors/content_review.py:78 +msgid "label_review_completed_date" +msgstr "" + +#. Default: "Next review on" +#: kitconcept/intranet/behaviors/content_review.py:72 +msgid "label_review_due_date" +msgstr "" + +#. Default: "Content Review & Reminders" +#: kitconcept/intranet/behaviors/content_review.py:26 +msgid "label_review_fieldset" +msgstr "" + +#. Default: "Review Interval" +#: kitconcept/intranet/behaviors/content_review.py:55 +msgid "label_review_interval" +msgstr "" + +#. Default: "Status" +#: kitconcept/intranet/behaviors/content_review.py:47 +#: kitconcept/intranet/profiles/default/registry/querystring.xml +msgid "label_review_status" +msgstr "" + +#. Default: "Timeless content - exclude from review reminders" +#: kitconcept/intranet/behaviors/content_review.py:38 +msgid "label_review_timeless" +msgstr "" + #. Default: "Responsibilities & Expertise" #: kitconcept/intranet/behaviors/person.py:37 msgid "label_schema_responsibility_categorization" diff --git a/backend/src/kitconcept/intranet/locales/kitconcept.intranet.pot b/backend/src/kitconcept/intranet/locales/kitconcept.intranet.pot index 9826c0830..b4ffd5622 100644 --- a/backend/src/kitconcept/intranet/locales/kitconcept.intranet.pot +++ b/backend/src/kitconcept/intranet/locales/kitconcept.intranet.pot @@ -4,7 +4,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: 2026-02-25 14:14+0000\n" +"POT-Creation-Date: 2026-06-11 08:48+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI +ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -65,6 +65,10 @@ msgstr "" msgid "Allowed Iframe Domains" msgstr "" +#: kitconcept/intranet/behaviors/configure.zcml:56 +msgid "CLM: Reminders for potentially outdated content" +msgstr "" + #: kitconcept/intranet/profiles/default/workflows/simple_intranet_workflow/definition.xml #: kitconcept/intranet/profiles/restricted/workflows/simple_intranet_workflow/definition.xml msgid "Can only be seen and edited by the owner." @@ -74,6 +78,10 @@ msgstr "" msgid "Default Feedback Email" msgstr "" +#: kitconcept/intranet/controlpanels/intranet.py:98 +msgid "Default review interval" +msgstr "" + #: kitconcept/intranet/behaviors/person.py:30 msgid "Department" msgstr "" @@ -99,6 +107,10 @@ msgstr "" msgid "Enable Content Rating" msgstr "" +#: kitconcept/intranet/controlpanels/intranet.py:91 +msgid "Enable Content Review" +msgstr "" + #: kitconcept/intranet/behaviors/votes.py:23 msgid "Enable Likes" msgstr "" @@ -115,10 +127,30 @@ msgstr "" msgid "Enable content rating globally for the Intranet" msgstr "" +#: kitconcept/intranet/controlpanels/intranet.py:92 +msgid "Enable content review reminders globally for the Intranet." +msgstr "" + #: kitconcept/intranet/controlpanels/intranet.py:68 msgid "Enable or disable the sticky feedback button on all pages." msgstr "" +#: kitconcept/intranet/vocabularies/content_review.py:12 +msgid "Every 2 years" +msgstr "" + +#: kitconcept/intranet/vocabularies/content_review.py:9 +msgid "Every 3 months" +msgstr "" + +#: kitconcept/intranet/vocabularies/content_review.py:10 +msgid "Every 6 months" +msgstr "" + +#: kitconcept/intranet/vocabularies/content_review.py:11 +msgid "Every year" +msgstr "" + #: kitconcept/intranet/controlpanels/intranet.py:21 msgid "External Search URL" msgstr "" @@ -135,6 +167,10 @@ msgstr "" msgid "Fields for Organisational Unit" msgstr "" +#: kitconcept/intranet/behaviors/configure.zcml:56 +msgid "Fields for reviewing content (part of CLM)" +msgstr "" + #: kitconcept/intranet/profiles/default/workflows/simple_intranet_workflow/definition.xml #: kitconcept/intranet/profiles/restricted/workflows/simple_intranet_workflow/definition.xml msgid "If you submitted the item by mistake or want to perform additional edits, this will take it back." @@ -148,7 +184,7 @@ msgstr "" msgid "Intranet Restricted Workflow" msgstr "" -#: kitconcept/intranet/controlpanels/intranet.py:93 +#: kitconcept/intranet/controlpanels/intranet.py:107 msgid "Intranet Settings" msgstr "" @@ -181,7 +217,7 @@ msgid "List of user IDs" msgstr "" #: kitconcept/intranet/behaviors/configure.zcml:28 -#: kitconcept/intranet/behaviors/location.py:19 +#: kitconcept/intranet/behaviors/location.py:18 #: kitconcept/intranet/profiles/default/types/Location.xml msgid "Location" msgstr "" @@ -201,7 +237,7 @@ msgid "No responsible person or default feedback email is configured. Please con msgstr "" #: kitconcept/intranet/behaviors/configure.zcml:35 -#: kitconcept/intranet/behaviors/organisational_unit.py:19 +#: kitconcept/intranet/behaviors/organisational_unit.py:18 #: kitconcept/intranet/profiles/default/types/Organisational_Unit.xml msgid "Organisational Unit" msgstr "" @@ -269,6 +305,10 @@ msgstr "" msgid "Retract" msgstr "" +#: kitconcept/intranet/profiles/default/registry/querystring.xml +msgid "Review" +msgstr "" + #: kitconcept/intranet/profiles/default/workflows/simple_intranet_workflow/definition.xml #: kitconcept/intranet/profiles/restricted/workflows/simple_intranet_workflow/definition.xml msgid "Reviewer publishes content" @@ -374,6 +414,16 @@ msgstr "" msgid "help_responsibilities_filter" msgstr "" +#. Default: "... will be notified as soon as the review is due. Unless otherwise specified, the content owner is considered the responsible person." +#: kitconcept/intranet/behaviors/content_review.py:63 +msgid "help_review_assignee" +msgstr "" + +#. Default: "Filter by review status" +#: kitconcept/intranet/profiles/default/registry/querystring.xml +msgid "help_review_status_filter" +msgstr "" + #. Default: "Describe what others can contact you about. Focus on topics, tasks, or questions you are responsible for, such as advising on specific funding programs, supporting application processes, or clarifying formal requirements. Write in a way that allows colleagues without detailed organisational knowledge to understand whether you are the right contact." #: kitconcept/intranet/behaviors/person.py:46 msgid "help_tags" @@ -431,6 +481,47 @@ msgstr "" msgid "label_responsible" msgstr "" +#. Default: "Reviewer" +#: kitconcept/intranet/behaviors/content_review.py:62 +msgid "label_review_assignee" +msgstr "" + +#. Default: "Comment" +#: kitconcept/intranet/behaviors/content_review.py:84 +msgid "label_review_comment" +msgstr "" + +#. Default: "Last review on" +#: kitconcept/intranet/behaviors/content_review.py:78 +msgid "label_review_completed_date" +msgstr "" + +#. Default: "Next review on" +#: kitconcept/intranet/behaviors/content_review.py:72 +msgid "label_review_due_date" +msgstr "" + +#. Default: "Content Review & Reminders" +#: kitconcept/intranet/behaviors/content_review.py:26 +msgid "label_review_fieldset" +msgstr "" + +#. Default: "Review Interval" +#: kitconcept/intranet/behaviors/content_review.py:55 +msgid "label_review_interval" +msgstr "" + +#. Default: "Status" +#: kitconcept/intranet/behaviors/content_review.py:47 +#: kitconcept/intranet/profiles/default/registry/querystring.xml +msgid "label_review_status" +msgstr "" + +#. Default: "Timeless content - exclude from review reminders" +#: kitconcept/intranet/behaviors/content_review.py:38 +msgid "label_review_timeless" +msgstr "" + #. Default: "Responsibilities & Expertise" #: kitconcept/intranet/behaviors/person.py:37 msgid "label_schema_responsibility_categorization" diff --git a/backend/src/kitconcept/intranet/locales/pt_BR/LC_MESSAGES/kitconcept.intranet.po b/backend/src/kitconcept/intranet/locales/pt_BR/LC_MESSAGES/kitconcept.intranet.po index b0105761e..5c638694c 100644 --- a/backend/src/kitconcept/intranet/locales/pt_BR/LC_MESSAGES/kitconcept.intranet.po +++ b/backend/src/kitconcept/intranet/locales/pt_BR/LC_MESSAGES/kitconcept.intranet.po @@ -1,7 +1,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: 2026-02-25 14:14+0000\n" +"POT-Creation-Date: 2026-06-11 08:48+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI +ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -62,6 +62,10 @@ msgstr "Domínios de e-mail permitidos" msgid "Allowed Iframe Domains" msgstr "Domínios de iframe permitidos" +#: kitconcept/intranet/behaviors/configure.zcml:56 +msgid "CLM: Reminders for potentially outdated content" +msgstr "" + #: kitconcept/intranet/profiles/default/workflows/simple_intranet_workflow/definition.xml #: kitconcept/intranet/profiles/restricted/workflows/simple_intranet_workflow/definition.xml msgid "Can only be seen and edited by the owner." @@ -71,6 +75,10 @@ msgstr "Só pode ser visto e editado pelo proprietário." msgid "Default Feedback Email" msgstr "E-mail padrão de feedback" +#: kitconcept/intranet/controlpanels/intranet.py:98 +msgid "Default review interval" +msgstr "" + #: kitconcept/intranet/behaviors/person.py:30 msgid "Department" msgstr "Departamento" @@ -96,6 +104,10 @@ msgstr "Endereço de e-mail usado nos formulários de feedback se nenhum estiver msgid "Enable Content Rating" msgstr "Habilitar avaliação de conteúdo" +#: kitconcept/intranet/controlpanels/intranet.py:91 +msgid "Enable Content Review" +msgstr "" + #: kitconcept/intranet/behaviors/votes.py:23 msgid "Enable Likes" msgstr "Habilitar curtidas" @@ -112,10 +124,30 @@ msgstr "Habilitar botão de feedback fixo" msgid "Enable content rating globally for the Intranet" msgstr "Habilitar avaliação de conteúdo globalmente para a Intranet" +#: kitconcept/intranet/controlpanels/intranet.py:92 +msgid "Enable content review reminders globally for the Intranet." +msgstr "" + #: kitconcept/intranet/controlpanels/intranet.py:68 msgid "Enable or disable the sticky feedback button on all pages." msgstr "Habilitar ou desabilitar o botão de feedback fixo em todas as páginas." +#: kitconcept/intranet/vocabularies/content_review.py:12 +msgid "Every 2 years" +msgstr "" + +#: kitconcept/intranet/vocabularies/content_review.py:9 +msgid "Every 3 months" +msgstr "" + +#: kitconcept/intranet/vocabularies/content_review.py:10 +msgid "Every 6 months" +msgstr "" + +#: kitconcept/intranet/vocabularies/content_review.py:11 +msgid "Every year" +msgstr "" + #: kitconcept/intranet/controlpanels/intranet.py:21 msgid "External Search URL" msgstr "URL de busca externa" @@ -132,6 +164,10 @@ msgstr "Campo de relacionamento com locais" msgid "Fields for Organisational Unit" msgstr "Campo de relacionamento com áreas" +#: kitconcept/intranet/behaviors/configure.zcml:56 +msgid "Fields for reviewing content (part of CLM)" +msgstr "" + #: kitconcept/intranet/profiles/default/workflows/simple_intranet_workflow/definition.xml #: kitconcept/intranet/profiles/restricted/workflows/simple_intranet_workflow/definition.xml msgid "If you submitted the item by mistake or want to perform additional edits, this will take it back." @@ -145,7 +181,7 @@ msgstr "Workflow público para Intranet" msgid "Intranet Restricted Workflow" msgstr "Workflow restrito para Intranet" -#: kitconcept/intranet/controlpanels/intranet.py:93 +#: kitconcept/intranet/controlpanels/intranet.py:107 msgid "Intranet Settings" msgstr "Configurações da Intranet" @@ -178,7 +214,7 @@ msgid "List of user IDs" msgstr "Lista de IDs de usuários" #: kitconcept/intranet/behaviors/configure.zcml:28 -#: kitconcept/intranet/behaviors/location.py:19 +#: kitconcept/intranet/behaviors/location.py:18 #: kitconcept/intranet/profiles/default/types/Location.xml msgid "Location" msgstr "Local" @@ -198,7 +234,7 @@ msgid "No responsible person or default feedback email is configured. Please con msgstr "Nenhuma pessoa responsável ou e-mail de feedback padrão está configurado. Por favor, entre em contato com o administrador do site." #: kitconcept/intranet/behaviors/configure.zcml:35 -#: kitconcept/intranet/behaviors/organisational_unit.py:19 +#: kitconcept/intranet/behaviors/organisational_unit.py:18 #: kitconcept/intranet/profiles/default/types/Organisational_Unit.xml msgid "Organisational Unit" msgstr "Área" @@ -266,6 +302,10 @@ msgstr "Adiciona seu item a uma fila de revisão, para que possa ser publicado n msgid "Retract" msgstr "Retrair" +#: kitconcept/intranet/profiles/default/registry/querystring.xml +msgid "Review" +msgstr "" + #: kitconcept/intranet/profiles/default/workflows/simple_intranet_workflow/definition.xml #: kitconcept/intranet/profiles/restricted/workflows/simple_intranet_workflow/definition.xml msgid "Reviewer publishes content" @@ -371,6 +411,16 @@ msgstr "Filtrar por localização" msgid "help_responsibilities_filter" msgstr "Filtrar por responsabilidades" +#. Default: "... will be notified as soon as the review is due. Unless otherwise specified, the content owner is considered the responsible person." +#: kitconcept/intranet/behaviors/content_review.py:63 +msgid "help_review_assignee" +msgstr "" + +#. Default: "Filter by review status" +#: kitconcept/intranet/profiles/default/registry/querystring.xml +msgid "help_review_status_filter" +msgstr "" + #. Default: "Describe what others can contact you about. Focus on topics, tasks, or questions you are responsible for, such as advising on specific funding programs, supporting application processes, or clarifying formal requirements. Write in a way that allows colleagues without detailed organisational knowledge to understand whether you are the right contact." #: kitconcept/intranet/behaviors/person.py:46 msgid "help_tags" @@ -428,6 +478,47 @@ msgstr "Responsabilidades" msgid "label_responsible" msgstr "Responsável pelo conteúdo:" +#. Default: "Reviewer" +#: kitconcept/intranet/behaviors/content_review.py:62 +msgid "label_review_assignee" +msgstr "" + +#. Default: "Comment" +#: kitconcept/intranet/behaviors/content_review.py:84 +msgid "label_review_comment" +msgstr "" + +#. Default: "Last review on" +#: kitconcept/intranet/behaviors/content_review.py:78 +msgid "label_review_completed_date" +msgstr "" + +#. Default: "Next review on" +#: kitconcept/intranet/behaviors/content_review.py:72 +msgid "label_review_due_date" +msgstr "" + +#. Default: "Content Review & Reminders" +#: kitconcept/intranet/behaviors/content_review.py:26 +msgid "label_review_fieldset" +msgstr "" + +#. Default: "Review Interval" +#: kitconcept/intranet/behaviors/content_review.py:55 +msgid "label_review_interval" +msgstr "" + +#. Default: "Status" +#: kitconcept/intranet/behaviors/content_review.py:47 +#: kitconcept/intranet/profiles/default/registry/querystring.xml +msgid "label_review_status" +msgstr "" + +#. Default: "Timeless content - exclude from review reminders" +#: kitconcept/intranet/behaviors/content_review.py:38 +msgid "label_review_timeless" +msgstr "" + #. Default: "Responsibilities & Expertise" #: kitconcept/intranet/behaviors/person.py:37 msgid "label_schema_responsibility_categorization" diff --git a/backend/src/kitconcept/intranet/profiles/default/catalog.xml b/backend/src/kitconcept/intranet/profiles/default/catalog.xml index ae75e0796..e59ebf341 100644 --- a/backend/src/kitconcept/intranet/profiles/default/catalog.xml +++ b/backend/src/kitconcept/intranet/profiles/default/catalog.xml @@ -41,4 +41,17 @@ + + + + + + + + + diff --git a/backend/src/kitconcept/intranet/profiles/default/metadata.xml b/backend/src/kitconcept/intranet/profiles/default/metadata.xml index edf31f387..68649e0ba 100644 --- a/backend/src/kitconcept/intranet/profiles/default/metadata.xml +++ b/backend/src/kitconcept/intranet/profiles/default/metadata.xml @@ -1,6 +1,6 @@ - 20260318001 + 20260611001 plone.app.discussion:default profile-kitconcept.contactblock:default diff --git a/backend/src/kitconcept/intranet/profiles/default/registry/querystring.xml b/backend/src/kitconcept/intranet/profiles/default/registry/querystring.xml index 04c21441d..24b27dd4d 100644 --- a/backend/src/kitconcept/intranet/profiles/default/registry/querystring.xml +++ b/backend/src/kitconcept/intranet/profiles/default/registry/querystring.xml @@ -82,4 +82,24 @@ + + + Review status + Filter by review status + True + False + + plone.app.querystring.operation.selection.any + + Review + + diff --git a/backend/src/kitconcept/intranet/profiles/default/types/Document.xml b/backend/src/kitconcept/intranet/profiles/default/types/Document.xml index c581edeba..221b13c5a 100644 --- a/backend/src/kitconcept/intranet/profiles/default/types/Document.xml +++ b/backend/src/kitconcept/intranet/profiles/default/types/Document.xml @@ -16,6 +16,7 @@ /> + diff --git a/backend/src/kitconcept/intranet/profiles/default/types/Event.xml b/backend/src/kitconcept/intranet/profiles/default/types/Event.xml index 9d12a8fca..3d37b9f68 100644 --- a/backend/src/kitconcept/intranet/profiles/default/types/Event.xml +++ b/backend/src/kitconcept/intranet/profiles/default/types/Event.xml @@ -17,6 +17,7 @@ + diff --git a/backend/src/kitconcept/intranet/profiles/default/types/File.xml b/backend/src/kitconcept/intranet/profiles/default/types/File.xml index 229587608..4b97741e3 100644 --- a/backend/src/kitconcept/intranet/profiles/default/types/File.xml +++ b/backend/src/kitconcept/intranet/profiles/default/types/File.xml @@ -10,6 +10,7 @@ + diff --git a/backend/src/kitconcept/intranet/profiles/default/types/Image.xml b/backend/src/kitconcept/intranet/profiles/default/types/Image.xml index 2097be026..b65f32934 100644 --- a/backend/src/kitconcept/intranet/profiles/default/types/Image.xml +++ b/backend/src/kitconcept/intranet/profiles/default/types/Image.xml @@ -10,6 +10,7 @@ + diff --git a/backend/src/kitconcept/intranet/profiles/default/types/Link.xml b/backend/src/kitconcept/intranet/profiles/default/types/Link.xml index dac2c7d1e..e643f316d 100644 --- a/backend/src/kitconcept/intranet/profiles/default/types/Link.xml +++ b/backend/src/kitconcept/intranet/profiles/default/types/Link.xml @@ -9,5 +9,6 @@ > + diff --git a/backend/src/kitconcept/intranet/profiles/default/types/Location.xml b/backend/src/kitconcept/intranet/profiles/default/types/Location.xml index 825c48a2d..fb4bf4255 100644 --- a/backend/src/kitconcept/intranet/profiles/default/types/Location.xml +++ b/backend/src/kitconcept/intranet/profiles/default/types/Location.xml @@ -56,6 +56,7 @@ + diff --git a/backend/src/kitconcept/intranet/profiles/default/types/News_Item.xml b/backend/src/kitconcept/intranet/profiles/default/types/News_Item.xml index 06e9945b9..9add03b86 100644 --- a/backend/src/kitconcept/intranet/profiles/default/types/News_Item.xml +++ b/backend/src/kitconcept/intranet/profiles/default/types/News_Item.xml @@ -12,6 +12,7 @@ + diff --git a/backend/src/kitconcept/intranet/profiles/default/types/Organisational_Unit.xml b/backend/src/kitconcept/intranet/profiles/default/types/Organisational_Unit.xml index be5b7611c..db23d8d8b 100644 --- a/backend/src/kitconcept/intranet/profiles/default/types/Organisational_Unit.xml +++ b/backend/src/kitconcept/intranet/profiles/default/types/Organisational_Unit.xml @@ -56,6 +56,7 @@ + diff --git a/backend/src/kitconcept/intranet/profiles/default/types/Person.xml b/backend/src/kitconcept/intranet/profiles/default/types/Person.xml index 0dd6d87f3..065cb8a6c 100644 --- a/backend/src/kitconcept/intranet/profiles/default/types/Person.xml +++ b/backend/src/kitconcept/intranet/profiles/default/types/Person.xml @@ -25,5 +25,6 @@ + diff --git a/backend/src/kitconcept/intranet/services/configure.zcml b/backend/src/kitconcept/intranet/services/configure.zcml index 5b21ef80d..8fb410549 100644 --- a/backend/src/kitconcept/intranet/services/configure.zcml +++ b/backend/src/kitconcept/intranet/services/configure.zcml @@ -75,4 +75,12 @@ name="@vote" /> + + diff --git a/backend/src/kitconcept/intranet/services/review.py b/backend/src/kitconcept/intranet/services/review.py new file mode 100644 index 000000000..bfcda4a5a --- /dev/null +++ b/backend/src/kitconcept/intranet/services/review.py @@ -0,0 +1,65 @@ +from datetime import date +from kitconcept.intranet.behaviors.content_review import IContentReview +from kitconcept.intranet.utils.calc_due_date import calc_due_date +from plone import api +from plone.protect.interfaces import IDisableCSRFProtection +from plone.restapi.deserializer import json_body +from plone.restapi.services import Service +from zExceptions import BadRequest +from zope.interface import alsoProvides +from zope.interface import implementer +from zope.publisher.interfaces import IPublishTraverse + + +@implementer(IPublishTraverse) +class ReviewPost(Service): + """@review endpoint.""" + + def __init__(self, context, request): + super().__init__(context, request) + self.params = [] + + def publishTraverse(self, request, name): + # Treat any path segments after /@review as parameters + self.params.append(name) + return self + + def reply(self): + # Disable CSRF protection + alsoProvides(self.request, IDisableCSRFProtection) + + match self.params: + case ["approve"]: + # update review_status + self.context.review_status = "Up-to-date" + # update review_due_date + default_interval = api.portal.get_registry_record( + "kitconcept.intranet.content_review_default_interval" + ) + interval = self.context.review_interval or default_interval + self.context.review_due_date = calc_due_date(interval=interval) + # update review_completed_date + self.context.review_completed_date = date.today() + case ["delegate"]: + field = IContentReview["review_assignee"].bind(self.context) + vocabulary = field.vocabulary + data = json_body(self.request) + if comment := data.get("comment"): + self.context.review_comment = comment + assignee = data.get("assignee", None) + if assignee not in vocabulary: + raise BadRequest(f"Assignee not found in vocabulary: {vocabulary}") + self.context.review_assignee = assignee + case ["postpone"]: + self.context.review_status = "Up-to-date" + data = json_body(self.request) + if comment := data.get("comment"): + self.context.review_comment = comment + due_date = data.get("due_date", None) + if due_date: + self.context.review_due_date = date.fromisoformat(due_date) + case _: + raise BadRequest( + "Unknown action: expected /@review/approve, " + "/@review/delegate, or /@review/postpone" + ) diff --git a/backend/src/kitconcept/intranet/services/types.py b/backend/src/kitconcept/intranet/services/types.py index cc7eed963..228d75deb 100644 --- a/backend/src/kitconcept/intranet/services/types.py +++ b/backend/src/kitconcept/intranet/services/types.py @@ -23,6 +23,12 @@ def reply_for_type(self): ) if not rating_enabled: continue + if fieldset["id"] == "Content Review & Reminders": + review_enabled = registry.get( + "kitconcept.intranet.enable_content_review", False + ) + if not review_enabled: + continue fieldsets.append(fieldset) response["fieldsets"] = fieldsets diff --git a/backend/src/kitconcept/intranet/upgrades/configure.zcml b/backend/src/kitconcept/intranet/upgrades/configure.zcml index b5dfc2570..da056bfce 100644 --- a/backend/src/kitconcept/intranet/upgrades/configure.zcml +++ b/backend/src/kitconcept/intranet/upgrades/configure.zcml @@ -90,6 +90,7 @@ - + + diff --git a/backend/src/kitconcept/intranet/upgrades/v20260401001/__init__.py b/backend/src/kitconcept/intranet/upgrades/v20260401001/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/backend/src/kitconcept/intranet/upgrades/v20260401001/configure.zcml b/backend/src/kitconcept/intranet/upgrades/v20260401001/configure.zcml new file mode 100644 index 000000000..eaa943bf9 --- /dev/null +++ b/backend/src/kitconcept/intranet/upgrades/v20260401001/configure.zcml @@ -0,0 +1,19 @@ + + + + + + diff --git a/backend/src/kitconcept/intranet/upgrades/v20260401001/upgrade.py b/backend/src/kitconcept/intranet/upgrades/v20260401001/upgrade.py new file mode 100644 index 000000000..7651d89d6 --- /dev/null +++ b/backend/src/kitconcept/intranet/upgrades/v20260401001/upgrade.py @@ -0,0 +1,50 @@ +from datetime import date +from kitconcept.intranet.utils.calc_due_date import calc_due_date +from plone import api +from Products.GenericSetup.tool import SetupTool + +import logging +import transaction + + +logger = logging.getLogger("kitconcept.intranet") + + +def update_existing_content(tool: SetupTool): + types_we_want = [] + types_tool = api.portal.get_tool("portal_types") + all_types = types_tool.objectIds() + for type_id in all_types: + fti = types_tool[type_id] + try: + behaviors = fti.behaviors + if "kitconcept.intranet.content_review" in behaviors: + types_we_want.append(type_id) + except AttributeError: + continue + + catalog = api.portal.get_tool("portal_catalog") + indexes = catalog.indexes() + for idx in ("review_status", "review_due_date"): + if idx not in indexes: + catalog.addIndex(idx, "FieldIndex") + logger.info(f"Added {idx} index") + + brains = api.content.find(portal_type=types_we_want) + total = len(brains) + logger.info(f"Found {total} objects to update") + for idx, brain in enumerate(brains): + obj = brain.getObject() + modified = obj.modified().asdatetime().date() + obj.review_due_date = calc_due_date(base_date=modified) + review_due_date = obj.review_due_date + if review_due_date > date.today(): + obj.review_status = "Up-to-date" + else: + obj.review_status = "Due" + obj.reindexObject(idxs=["review_status", "review_due_date"], update_metadata=0) + if idx % 250 == 0: + logger.info(f"Updated {idx}/{total} objects") + transaction.commit() + logger.info(f"Updated {total}/{total} objects") + transaction.commit() diff --git a/backend/src/kitconcept/intranet/upgrades/v20260611001/__init__.py b/backend/src/kitconcept/intranet/upgrades/v20260611001/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/backend/src/kitconcept/intranet/upgrades/v20260611001/configure.zcml b/backend/src/kitconcept/intranet/upgrades/v20260611001/configure.zcml new file mode 100644 index 000000000..ad0057bb0 --- /dev/null +++ b/backend/src/kitconcept/intranet/upgrades/v20260611001/configure.zcml @@ -0,0 +1,15 @@ + + + + + diff --git a/backend/src/kitconcept/intranet/utils/calc_due_date.py b/backend/src/kitconcept/intranet/utils/calc_due_date.py new file mode 100644 index 000000000..28e620381 --- /dev/null +++ b/backend/src/kitconcept/intranet/utils/calc_due_date.py @@ -0,0 +1,22 @@ +from datetime import date +from dateutil.relativedelta import relativedelta +from plone import api +from plone.dexterity.interfaces import IDexterityContent + + +def calc_due_date(base_date: date | None = None, interval: str | None = None) -> date: + if not interval: + interval = api.portal.get_registry_record( + "kitconcept.intranet.content_review_default_interval" + ) + if not base_date or IDexterityContent.providedBy(base_date): + base_date = date.today() + mapping = { + "d": "days", + "w": "weeks", + "m": "months", + "y": "years", + } + unit = mapping.get(interval[-1]) + amount = int(interval[:-1]) + return base_date + relativedelta(**{unit: amount}) diff --git a/backend/src/kitconcept/intranet/utils/review_due_notifier.py b/backend/src/kitconcept/intranet/utils/review_due_notifier.py new file mode 100644 index 000000000..7746c60a6 --- /dev/null +++ b/backend/src/kitconcept/intranet/utils/review_due_notifier.py @@ -0,0 +1,75 @@ +from datetime import date +from plone import api + +import logging + + +logger = logging.getLogger("kitconcept.intranet") + + +def nofity_reviewer(portal): + brains = portal.portal_catalog.unrestrictedSearchResults( + review_due_date=date.today() + ) + for brain in brains: + obj = brain.getObject() + reviewer = api.user.get( + obj.review_assignee if obj.review_assignee else obj.Creator() + ) + + if not reviewer: + logger.warning( + f"Couldn't find user for {brain.getPath()}. No mail will be sent." + ) + continue + + owner_name = reviewer.getProperty("fullname") or reviewer.getUserName() + + mail_subject = { + "de": f"🔔 Erinnerung: Inhaltsprüfung fällig für „{obj.Title()}“", + "en": f"🔔 Reminder: Content review due for “{obj.Title()}”", + } + mail_body = { + "de": ( + f"Hallo {owner_name}," + f"der Inhalt „{obj.Title()}“ ist zur Überprüfung fällig." + "Bitte prüfen Sie, ob die Informationen noch aktuell und korrekt sind." + f"Letzte Aktualisierung: {obj}" + "Nächste Kontrolle (nach Prüfung): wird automatisch neu berechnet" + f"Sie können den Inhalt hier aufrufen:" + f"👉 {obj.absolute_url()}" + "Ihre Optionen:" + "- ✅ Inhalt prüfen und als „geprüft“ markieren" + "- 🕓 Nächste Kontrolle verschieben (z. B. in 3 oder 6 Monaten)" + "- 📝 Inhalt als „Überarbeitung erforderlich“ markieren, falls Änderungen notwendig sind" + "Vielen Dank, dass Sie dafür sorgen, dass unsere Inhalte aktuell bleiben." + "Mit freundlichen Grüßen," + "Ihr Intranet-Team" + ), + "en": ( + f"Hello {owner_name}," + f"The content item “{obj.Title()}” is due for review." + "Please check whether the information is still accurate and up to date." + f"Last updated: {obj}" + "Next review date (after completion): will be recalculated automatically" + "You can open the content here:" + f"👉 {obj.absolute_url()}" + "Available actions:" + "- ✅ Review the content and mark as reviewed" + "- 🕓 Postpone next review (e.g., by 3 or 6 months)" + "- 📝 Mark as “changes required” if updates are needed" + "Thank you for keeping our content accurate and relevant." + "Kind regards," + "Your intranet team" + ), + } + + languages = api.portal.get_tool("portal_languages") + lang = obj.language or languages.getDefaultLanguage() + + api.portal.send_email( + recipient=reviewer.getProperty("email"), + subject=mail_subject.get(lang, mail_subject.get("en")), + body=mail_body.get(lang, mail_body.get("en")), + immediate=True, + ) diff --git a/backend/src/kitconcept/intranet/vocabularies/configure.zcml b/backend/src/kitconcept/intranet/vocabularies/configure.zcml index e8490d3b6..ba1bd41d7 100644 --- a/backend/src/kitconcept/intranet/vocabularies/configure.zcml +++ b/backend/src/kitconcept/intranet/vocabularies/configure.zcml @@ -25,5 +25,14 @@ component=".responsibilities.ResponsibilitiesVocabularyFactory" /> + + + diff --git a/backend/src/kitconcept/intranet/vocabularies/content_review.py b/backend/src/kitconcept/intranet/vocabularies/content_review.py new file mode 100644 index 000000000..4c776587a --- /dev/null +++ b/backend/src/kitconcept/intranet/vocabularies/content_review.py @@ -0,0 +1,28 @@ +from kitconcept.intranet import _ +from zope.interface import provider +from zope.schema.interfaces import IVocabularyFactory +from zope.schema.vocabulary import SimpleTerm +from zope.schema.vocabulary import SimpleVocabulary + + +INTERVALS = [ + ("3m", _("Every 3 months")), + ("6m", _("Every 6 months")), + ("1y", _("Every year")), + ("2y", _("Every 2 years")), +] + + +@provider(IVocabularyFactory) +def review_intervals_vocabulary(context) -> SimpleVocabulary: + terms = [] + for token, title in INTERVALS: + terms.append(SimpleTerm(token, token, title)) + return SimpleVocabulary(terms) + + +@provider(IVocabularyFactory) +def review_users_vocabulary(context): + acl_users = context.acl_users + reviewers = acl_users.getGroupById("Reviewers") + return reviewers.getMemberIds() diff --git a/backend/tests/content_types/test_fti.py b/backend/tests/content_types/test_fti.py index 6f07d8857..06d6bb11b 100644 --- a/backend/tests/content_types/test_fti.py +++ b/backend/tests/content_types/test_fti.py @@ -39,6 +39,7 @@ def _setup(self, portal, get_fti): "kitconcept.intranet.organisational_unit", "kitconcept.intranet.clm", "kitconcept.intranet.votes", + "kitconcept.intranet.content_review", ), ), ("Event", "title", "Event"), @@ -72,6 +73,7 @@ def _setup(self, portal, get_fti): "kitconcept.intranet.location", "kitconcept.intranet.organisational_unit", "kitconcept.intranet.votes", + "kitconcept.intranet.content_review", ), ), ("File", "title", "File"), @@ -95,6 +97,7 @@ def _setup(self, portal, get_fti): "kitconcept.intranet.location", "kitconcept.intranet.organisational_unit", "kitconcept.intranet.votes", + "kitconcept.intranet.content_review", ), ), ("Image", "title", "Image"), @@ -117,6 +120,7 @@ def _setup(self, portal, get_fti): "kitconcept.intranet.location", "kitconcept.intranet.organisational_unit", "kitconcept.intranet.votes", + "kitconcept.intranet.content_review", ), ), ("Link", "title", "Link"), @@ -141,6 +145,7 @@ def _setup(self, portal, get_fti): "plone.allowdiscussion", "kitconcept.intranet.location", "kitconcept.intranet.organisational_unit", + "kitconcept.intranet.content_review", ), ), ("Location", "title", "Location"), @@ -165,6 +170,7 @@ def _setup(self, portal, get_fti): "plone.versioning", "plone.locking", "plone.translatable", + "kitconcept.intranet.content_review", ), ), ("News Item", "title", "News Item"), @@ -193,6 +199,7 @@ def _setup(self, portal, get_fti): "kitconcept.intranet.location", "kitconcept.intranet.organisational_unit", "kitconcept.intranet.votes", + "kitconcept.intranet.content_review", ), ), ("Organisational Unit", "title", "Organisational Unit"), @@ -217,6 +224,7 @@ def _setup(self, portal, get_fti): "plone.versioning", "plone.locking", "plone.translatable", + "kitconcept.intranet.content_review", ), ), ("Person", "title", "Person"), @@ -243,6 +251,7 @@ def _setup(self, portal, get_fti): "plone.translatable", "kitconcept.intranet.location", "kitconcept.intranet.organisational_unit", + "kitconcept.intranet.content_review", ), ), ("Plone Site", "title", "Plone Site"), diff --git a/backend/tests/services/review/test_review_post.py b/backend/tests/services/review/test_review_post.py new file mode 100644 index 000000000..f85ddc54c --- /dev/null +++ b/backend/tests/services/review/test_review_post.py @@ -0,0 +1,94 @@ +from datetime import date +from kitconcept.intranet.utils.calc_due_date import calc_due_date +from plone import api + +import pytest +import transaction + + +@pytest.fixture(scope="class") +def portal(portal_class): + yield portal_class + + +@pytest.fixture(scope="class") +def contents(portal): + with api.env.adopt_roles(["Manager"]): + doc = api.content.create(portal, type="Document", id="doc1") + api.content.transition(obj=doc, transition="publish") + api.user.create(email="jdoe@example.org", username="jdoe") + transaction.commit() + + +class TestReviewPost: + @pytest.fixture(autouse=True) + def _setup(self, contents, api_manager_request, api_anon_request): + self.api_session = api_manager_request + self.anon_api_session = api_anon_request + self.default_review_interval = api.portal.get_registry_record( + "kitconcept.intranet.content_review_default_interval" + ) + + def test_response_not_reviewable(self): + resp = self.api_session.post("/@review") + assert resp.status_code == 404 + + def test_response_no_action(self): + resp = self.api_session.post("/doc1/@review") + assert resp.status_code == 400 + + def test_response_anonymous(self): + resp = self.anon_api_session.post("/doc1/@review") + assert resp.status_code == 401 + + def test_response_unknown_action(self): + resp = self.api_session.post("/doc1/@review/doc1") + assert resp.status_code == 400 + + def test_action_approve(self): + doc = api.content.get("/doc1") + doc.review_status = "Due" + doc.review_due_date = date(2002, 12, 30) + transaction.commit() + + resp = self.api_session.post("/doc1/@review/approve") + assert resp.status_code == 200 + + interval = doc.review_interval or self.default_review_interval + resp = self.api_session.get("/doc1").json() + assert resp["review_status"]["token"] == "Up-to-date" # noqa: S105 + assert resp["review_due_date"] == calc_due_date(interval=interval).isoformat() + assert resp["review_completed_date"] == date.today().isoformat() + + def test_action_delegate(self): + comment = "Lorem Ipsum dolor sit amet" + resp = self.api_session.post( + "/doc1/@review/delegate", + json={"assignee": "jdoe", "comment": comment}, + ) + assert resp.status_code == 200 + + resp = self.api_session.get("/doc1").json() + assert resp["review_assignee"]["token"] == "jdoe" # noqa: S105 + assert resp["review_comment"] == comment + + def test_action_delegate_unknown_assignee(self): + resp = self.api_session.post( + "/doc1/@review/delegate", + json={"assignee": "f.bar"}, + ) + assert resp.status_code == 400 + + def test_action_postpone(self): + doc = api.content.get("/doc1") + due_date = calc_due_date(base_date=doc.review_due_date) + comment = "Lorem Ipsum dolor sit amet" + resp = self.api_session.post( + "/doc1/@review/postpone", + json={"due_date": due_date.isoformat(), "comment": comment}, + ) + assert resp.status_code == 200 + + resp = self.api_session.get("/doc1").json() + assert resp["review_due_date"] == due_date.isoformat() + assert resp["review_comment"] == comment diff --git a/backend/tests/services/site/test_site_get.py b/backend/tests/services/site/test_site_get.py index fde507c5a..b597c6178 100644 --- a/backend/tests/services/site/test_site_get.py +++ b/backend/tests/services/site/test_site_get.py @@ -19,7 +19,10 @@ def test_response_type(self): @pytest.mark.parametrize( "key,type_", - (("kitconcept.person_picture_aspect_ratio", str),), + ( + ("kitconcept.person_picture_aspect_ratio", str), + ("kitconcept.intranet.enable_content_review", bool), + ), ) def test_keys(self, key, type_): response = self.api_session.get("/@site") @@ -29,7 +32,10 @@ def test_keys(self, key, type_): @pytest.mark.parametrize( "key,expected", - (("kitconcept.person_picture_aspect_ratio", "rounded1to1"),), + ( + ("kitconcept.person_picture_aspect_ratio", "rounded1to1"), + ("kitconcept.intranet.enable_content_review", False), + ), ) def test_values(self, key, expected): response = self.api_session.get("/@site") diff --git a/backend/tests/utils/test_calc_due_date.py b/backend/tests/utils/test_calc_due_date.py new file mode 100644 index 000000000..3ea3ff42d --- /dev/null +++ b/backend/tests/utils/test_calc_due_date.py @@ -0,0 +1,92 @@ +from datetime import date +from kitconcept.intranet.utils.calc_due_date import calc_due_date +from plone import api + + +def test_1_day(): + result = calc_due_date(date(2024, 1, 1), "1d") + assert result == date(2024, 1, 2) + + +def test_7_days(): + result = calc_due_date(date(2024, 1, 1), "7d") + assert result == date(2024, 1, 8) + + +def test_days_across_month_boundary(): + result = calc_due_date(date(2024, 1, 30), "5d") + assert result == date(2024, 2, 4) + + +def test_days_across_year_boundary(): + result = calc_due_date(date(2023, 12, 30), "3d") + assert result == date(2024, 1, 2) + + +def test_1_week(): + result = calc_due_date(date(2024, 1, 1), "1w") + assert result == date(2024, 1, 8) + + +def test_2_weeks(): + result = calc_due_date(date(2024, 1, 1), "2w") + assert result == date(2024, 1, 15) + + +def test_weeks_across_month_boundary(): + result = calc_due_date(date(2024, 1, 25), "2w") + assert result == date(2024, 2, 8) + + +def test_1_month(): + result = calc_due_date(date(2024, 1, 15), "1m") + assert result == date(2024, 2, 15) + + +def test_6_months(): + result = calc_due_date(date(2024, 1, 15), "6m") + assert result == date(2024, 7, 15) + + +def test_month_end_clamping(): + """Jan 31 + 1 month → Feb 29 (2024 is a leap year).""" + result = calc_due_date(date(2024, 1, 31), "1m") + assert result == date(2024, 2, 29) + + +def test_months_across_year_boundary(): + result = calc_due_date(date(2024, 11, 1), "3m") + assert result == date(2025, 2, 1) + + +def test_1_year(): + result = calc_due_date(date(2024, 3, 10), "1y") + assert result == date(2025, 3, 10) + + +def test_2_years(): + result = calc_due_date(date(2024, 3, 10), "2y") + assert result == date(2026, 3, 10) + + +def test_leap_day_year_handling(): + """Feb 29 + 1 year → Feb 28 (2025 is not a leap year).""" + result = calc_due_date(date(2024, 2, 29), "1y") + assert result == date(2025, 2, 28) + + +def test_falls_back_to_registry_interval(portal): + result = calc_due_date(date(2024, 1, 1)) + assert result == date(2024, 7, 1) + + +def test_none_interval_triggers_registry(portal): + result = calc_due_date(base_date=date(2024, 1, 1), interval=None) + assert result == date(2024, 7, 1) + + +def test_registry_record_key_is_correct(portal): + result = api.portal.get_registry_record( + "kitconcept.intranet.content_review_default_interval" + ) + assert result == "6m" diff --git a/backend/tests/vocabularies/test_vocab_content_review_intervals.py b/backend/tests/vocabularies/test_vocab_content_review_intervals.py new file mode 100644 index 000000000..98b2160ae --- /dev/null +++ b/backend/tests/vocabularies/test_vocab_content_review_intervals.py @@ -0,0 +1,24 @@ +from plone.app.vocabularies import SimpleVocabulary + +import pytest + + +class TestVocab: + name: str = "kitconcept.intranet.vocabularies.content_review_intervals" + vocab_type = SimpleVocabulary + + @pytest.fixture(autouse=True) + def _setup(self, portal, get_vocabulary): + self.portal = portal + self.vocab = get_vocabulary(self.name, portal) + + def test_vocabulary_type(self): + assert isinstance(self.vocab, self.vocab_type) + + def test_vocab_terms(self): + assert [(term.token, term.title) for term in self.vocab._terms] == [ + ("3m", "Every 3 months"), + ("6m", "Every 6 months"), + ("1y", "Every year"), + ("2y", "Every 2 years"), + ] diff --git a/devops/stacks/persistent.yml b/devops/stacks/persistent.yml index 42f68effa..5fcf7ae74 100644 --- a/devops/stacks/persistent.yml +++ b/devops/stacks/persistent.yml @@ -81,6 +81,23 @@ services: - traefik.http.routers.rt-${STACK_PREFIX}-back-classic.service=svc-${STACK_PREFIX}-back - traefik.http.routers.rt-${STACK_PREFIX}-back-classic.middlewares=gzip,mw-${STACK_PREFIX}-back-auth,mw-${STACK_PREFIX}-back-vhm-classic + backend-cron-worker: + image: ${IMAGE_NAME_PREFIX}-backend:${IMAGE_TAG:-latest} + command: ./docker-entrypoint.sh run scripts/review_reminder.py + environment: + ZEO_ADDRESS: "${STACK_NAME}_zeo:8100" + deploy: + mode: replicated + replicas: 0 + labels: + - "swarm.cronjob.enable=true" + - "swarm.cronjob.schedule=0 0 * * *" + - "swarm.cronjob.skip-running=false" + restart_policy: + condition: none + networks: + - nw-internal + zeo: image: plone/plone-zeo:6.0.0 deploy: diff --git a/docker-compose.yml b/docker-compose.yml index 02179e89c..e5c16c18b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,6 +2,19 @@ name: kitconcept-intranet services: + swarm-cronjob: + image: crazymax/swarm-cronjob:1.16 + volumes: + - /var/run/docker.sock:/var/run/docker.sock + environment: + - "TZ=Europe/Berlin" + - "LOG_LEVEL=info" + - "LOG_JSON=false" + deploy: + placement: + constraints: + - node.role == manager + traefik: image: traefik:v2.11 @@ -93,3 +106,16 @@ services: - traefik.http.routers.rt-backend-admin.entrypoints=http - traefik.http.routers.rt-backend-admin.service=svc-backend - traefik.http.routers.rt-backend-admin.middlewares=gzip,mw-backend-auth + + backend-cron-worker: + image: ghcr.io/kitconcept/kitconcept-intranet-beispiele:${RELEASE:-2.0.0a16} + command: ./docker-entrypoint.sh run scripts/review_reminder.py + deploy: + mode: replicated + replicas: 0 + labels: + - "swarm.cronjob.enable=true" + - "swarm.cronjob.schedule=0 0 * * *" + - "swarm.cronjob.skip-running=false" + restart_policy: + condition: none diff --git a/docs/docs/_static/default-review-interval.png b/docs/docs/_static/default-review-interval.png new file mode 100644 index 000000000..a6d6eb452 Binary files /dev/null and b/docs/docs/_static/default-review-interval.png differ diff --git a/docs/docs/developer/how-to-guides/configure-reminders-for-content.md b/docs/docs/developer/how-to-guides/configure-reminders-for-content.md new file mode 100644 index 000000000..33050556a --- /dev/null +++ b/docs/docs/developer/how-to-guides/configure-reminders-for-content.md @@ -0,0 +1,71 @@ +--- +doc_type: how-to +audience: developer +myst: + html_meta: + "description": "Reminders for potentially outdated content" + "keywords": "Reminders, CLM, content livecycle management, automation, docker, docker swarm" +last_updated: 2026-06-17 +--- + +# Configure reminders for potentially outdated content + +```{versionadded} 2.0.0-alpha.x +``` + +This project uses crazymax/swarm-cronjob to handle periodic background tasks (cron jobs) natively within our Docker Swarm cluster. + +Instead of running an external cron daemon, we deploy a lightweight manager agent that uses Docker Service Labels to scale background worker containers up and down on a schedule. + +## Architecture Overview + +- `swarm-cronjob`: Runs 24/7 **strictly** on a Swarm Manager Node. It binds to the host's `/var/run/docker.sock` to listen to the Docker Swarm API. +- `backend-cron-worker`: Sits dormant at `replicas: 0`. When the cron expression triggers, the agent temporarily scales it to `replicas: 1`. Once the script finishes executing, the container exits cleanly and returns to 0 replicas. + +### The swarm-cronjob Service + +This service must run on a Manager Node within your cluster. You do not need to include or run this service within every stack in your cluster; a single instance manages schedules cluster-wide across all stacks. + +```yaml +services: + swarm-cronjob: + image: crazymax/swarm-cronjob:latest + volumes: + - /var/run/docker.sock:/var/run/docker.sock # Allows the agent to control Swarm scaling + environment: + - "TZ=Europe/Berlin" + - "LOG_LEVEL=info" + - "LOG_JSON=false" + deploy: + placement: + constraints: + - node.role == manager # Mandatory: Worker nodes cannot access global cluster APIs +``` + +For more information about configuring this agent, please refer to the official [installation documentation](https://crazymax.dev/swarm-cronjob/install/docker/). + +### The backend-cron-worker Service + +This service should live inside your application's stack. It must use the same base image as your main `backend` and share the identical environment configuration (e.g., database connections) to keep states synchronized. + +```yaml +services: + # ... your live application services (frontend, backend, db, etc.) ... + + backend-cron-worker: + image: your-backend-image:version + command: ./docker-entrypoint.sh run scripts/review_reminder.py + environment: + ZEO_ADDRESS: "${STACK_NAME}_zeo:8100" + deploy: + mode: replicated + replicas: 0 # CRITICAL: Must start at 0 so it only runs on-demand + restart_policy: + condition: none # CRITICAL: Stops Swarm from restarting the job when it exits cleanly + labels: + - "swarm.cronjob.enable=true" + - "swarm.cronjob.schedule=0 0 * * *" # Standard Cron Expression (Every day at 00:00 midnight) + - "swarm.cronjob.skip-running=false" +``` + +For more information on available service labels, please refer to the official [usage documentation](https://crazymax.dev/swarm-cronjob/usage/get-started/). diff --git a/docs/docs/developer/how-to-guides/index.md b/docs/docs/developer/how-to-guides/index.md index 23333537b..cfbe24d72 100644 --- a/docs/docs/developer/how-to-guides/index.md +++ b/docs/docs/developer/how-to-guides/index.md @@ -26,4 +26,5 @@ add-api-endpoint customize-email-templates add-vocabulary override-components +configure-reminders-for-content ``` diff --git a/docs/docs/developer/reference/api/index.md b/docs/docs/developer/reference/api/index.md index 460179a25..692818412 100644 --- a/docs/docs/developer/reference/api/index.md +++ b/docs/docs/developer/reference/api/index.md @@ -17,4 +17,5 @@ votes feedback byline clm +review ``` diff --git a/docs/docs/developer/reference/api/review.md b/docs/docs/developer/reference/api/review.md new file mode 100644 index 000000000..a084e7cac --- /dev/null +++ b/docs/docs/developer/reference/api/review.md @@ -0,0 +1,104 @@ +--- +myst: + html_meta: + description: "REST API reference for the @review endpoint." + keywords: "API, content, review, reminder, REST, @review" +doc_type: reference +audience: developer +status: draft +last_updated: 2026-04-09 +--- + +# @review Endpoint + +The `@review` endpoint handles approve/delegate/postpone operations on content items with the IContentReview behavior enabled. + +## Actions + +### `POST /@review/approve` + +Marks the content as reviewed and up-to-date. Automatically calculates the next review due date based on the content's review_interval (falling back to the site-wide default interval if not set), and records today as the completion date. + +**Request body:** None required. + +**Effect on content fields:** + +| Field | Value set | +|-------------------------|-----------------------------------------------------| +| `review_status` | "Up-to-date" | +| `review_due_date` | Calculated from `review_interval` (or site default) | +| `review_completed_date` | Today's date | + +**Example:** + +```http +POST /my-page/@review/approve +``` + +*** + +### `POST /@review/delegate` + +Assigns the content review to another user. Optionally attaches a comment. + +**Request body (JSON):** + +| Field | Type | Required | Description | +|------------|--------|----------|--------------------------------------------------------------------------------------------| +| `assignee` | string | Yes | User to assign the review to. Must be a valid value from the `review_assignee` vocabulary. | +| `comment` | string | No | Optional note about the delegation. | + +**Errors:** + +- `400 Bad Request` — if `assignee` is not found in the vocabulary. + +**Example:** + +```http +POST /my-page/@review/delegate +Content-Type: application/json + +{ + "assignee": "jane.doe", + "comment": "Please review the legal section." +} +``` + +*** + +### `POST /@review/postpone` + +Postpones the review to a specified future date. Optionally attaches a comment. Sets the status to "Up-to-date" without recording a completion date. + +**Request body (JSON):** + +| Field | Type | Required | Description | +|------------|------------------------|----------|-------------| +| `due_date` | string (ISO 8601 date) | No | New review due date, e.g. "2026-09-01". If omitted, the existing due date is unchanged. | +| `comment` | string | No | Optional note about why the review was postponed. | + +**Example:** + +```http +POST /my-page/@review/postpone +Content-Type: application/json + +{ + "due_date": "2026-09-01", + "comment": "Waiting for updated policy documents." +} +``` + +*** + +## Error Responses + +| Status | Condition | +|-------------------|------------------------------------------------------------| +| `400 Bad Request` | Unknown action (not approve, delegate, or postpone) | +| `400 Bad Request` | `delegate` called with an `assignee` not in the vocabulary | + +## See Also + +- [How to enable likes](/how-to-guides/engagement/enable-likes) +- [IContentReview behavior](/developer/reference/behaviors/votes) diff --git a/docs/docs/how-to-guides/settings/content-review.md b/docs/docs/how-to-guides/settings/content-review.md new file mode 100644 index 000000000..749657dc0 --- /dev/null +++ b/docs/docs/how-to-guides/settings/content-review.md @@ -0,0 +1,30 @@ +--- +myst: + html_meta: + "description": "Configure automated email reminders that notify content owners when published content is due for review." + "property=og:description": "Configure automated email reminders that notify content owners when published content is due for review." + "property=og:title": "Content Review & Reminders" + "keywords": "Volto, Plone, content review, reminders, comments, creation date, modification date" +--- + +# Content Review & Reminders + +... + +## Screenshot + +--- + +## Overview + +... + +--- + +## Configuration + +### Default review interval + +You can configure the default content review interval in the **Intranet Settings** control panel to determine how long after publication a content owner will be reminded to verify their content. The default is set to every 6 months. + +![Configure default content review interval](/_static/default-review-interval.png) diff --git a/docs/docs/how-to-guides/settings/index.md b/docs/docs/how-to-guides/settings/index.md index 0c91f8847..a336d0ad5 100644 --- a/docs/docs/how-to-guides/settings/index.md +++ b/docs/docs/how-to-guides/settings/index.md @@ -18,4 +18,5 @@ blocks-config import-export search-settings iframe-domains +content-review ``` diff --git a/frontend/packages/kitconcept-intranet/locales/de/LC_MESSAGES/volto.po b/frontend/packages/kitconcept-intranet/locales/de/LC_MESSAGES/volto.po index 62e1cab1e..82eb3539c 100644 --- a/frontend/packages/kitconcept-intranet/locales/de/LC_MESSAGES/volto.po +++ b/frontend/packages/kitconcept-intranet/locales/de/LC_MESSAGES/volto.po @@ -16,6 +16,11 @@ msgstr "" msgid "Address" msgstr "Adresse" +#. Default: "Assignee: *" +#: components/ContentReviewSidebar/DelegateReview +msgid "Assignee" +msgstr "Beauftragte Person: *" + #. Default: "Bio" #: components/theme/PersonView msgid "Bio" @@ -32,21 +37,50 @@ msgid "By" msgstr "Von" #. Default: "Cancel" +#: components/ContentReviewSidebar/DelegateReview +#: components/ContentReviewSidebar/PostponeReview #: components/FeedBackForm/FeedBackForm msgid "Cancel" msgstr "Abbrechen" +#. Default: "Comment:" +#: components/ContentReviewSidebar/DelegateReview +#: components/ContentReviewSidebar/PostponeReview +msgid "Comment" +msgstr "Kommentar:" + #. Default: "Contact" #: components/Blocks/EventMetadata/View #: components/theme/PersonView msgid "Contact" msgstr "Kontakt" +#. Default: "Content marked as reviewed" +#: components/Toolbar/DocumentReview +msgid "Content marked as reviewed" +msgstr "" + #. Default: "Created On" #: components/ContentInteractions/ContentInteractions msgid "Created On" msgstr "Erstellt am" +#. Default: "Delegate Review Update" +#: components/Toolbar/DocumentReview +msgid "Delegate Review Update" +msgstr "Prüfung/Anpassung delegieren" + +#. Default: "Delegate" +#: components/ContentReviewSidebar/DelegateReview +msgid "DelegateButton" +msgstr "Delegieren" + +#. Default: "Document Review" +#: components/Toolbar/DocumentReview +#: components/Toolbar/DocumentReviewPlug +msgid "Document Review" +msgstr "Review dokumentieren" + #. Default: "E-mail" #: components/Summary/PersonSummary #: components/theme/PersonView @@ -65,10 +99,16 @@ msgstr "Ende" #. Default: "Error" #: components/Blocks/IFrame/isValidUrl +#: components/ContentReviewSidebar/DelegateReview #: components/FeedBackForm/FeedBackForm msgid "Error" msgstr "Fehler" +#. Default: "Expand sidebar" +#: components/ContentReviewSidebar/ReviewSidebar +msgid "Expand sidebar" +msgstr "" + #. Default: "Feedback" #: components/FeedBackForm/FeedBackForm msgid "Feedback" @@ -114,6 +154,11 @@ msgstr "Ungültige URL" msgid "Last Modified On" msgstr "Zuletzt geändert am" +#. Default: "Last updated" +#: components/Toolbar/DocumentReview +msgid "Last updated" +msgstr "" + #. Default: "List with date" #: index msgid "List with date" @@ -124,11 +169,26 @@ msgstr "Liste mit Datum" msgid "Location" msgstr "Standort" +#. Default: "Mark Changes Required" +#: components/Toolbar/DocumentReview +msgid "Mark Changes Required" +msgstr "Überarbeitung erforderlich" + +#. Default: "Mark as Reviewed" +#: components/Toolbar/DocumentReview +msgid "Mark as Reviewed" +msgstr "Als geprüft markieren" + #. Default: "Name" #: components/FeedBackForm/FeedBackForm msgid "Name" msgstr "Name" +#. Default: "Next review" +#: components/Toolbar/DocumentReview +msgid "Next review" +msgstr "" + #. Default: "Only internal e-mail addresses are permitted." #: components/FeedBackForm/FeedBackForm msgid "Only internal e-mail addresses are permitted." @@ -156,17 +216,43 @@ msgstr "Bitte geben Sie Ihre geschäftliche E-Mail-Adresse ein." msgid "Please fill in the Feedback field" msgstr "Bitte füllen Sie das Feld „Feedback“ aus." +#. Default: "Postpone" +#: components/ContentReviewSidebar/PostponeReview +msgid "Postpone" +msgstr "Verschieben" + +#. Default: "Postpone Review" +#: components/Toolbar/DocumentReview +msgid "Postpone Review" +msgstr "Überprüfung verschieben" + +#. Default: "Postpone Review" +#: components/ContentReviewSidebar/PostponeReview +msgid "PostponeTitle" +msgstr "Überprüfung verschieben" + #. Default: "Responsibilities" #: index msgid "Responsibilities" msgstr "Zuständigkeiten" +#. Default: "Review" +#: components/ContentReviewSidebar/ReviewSidebar +#: components/Toolbar/DocumentReviewPlug +msgid "Review" +msgstr "Inhaltsprüfung" + #. Default: "Room" #: components/Summary/PersonSummary #: components/theme/PersonView msgid "Room" msgstr "Raum" +#. Default: "Please Select ..." +#: components/ContentReviewSidebar/DelegateReview +msgid "SelectAssigneePlaceholder" +msgstr "Bitte auswählen ..." + #. Default: "Send feedback" #: components/FeedBackForm/FeedBackForm msgid "Send feedback" @@ -182,6 +268,11 @@ msgstr "Ich möchte diesen Intranet-Inhalt mit Ihnen teilen:" msgid "Share this page via email" msgstr "Seite per E-Mail teilen" +#. Default: "Shrink sidebar" +#: components/ContentReviewSidebar/ReviewSidebar +msgid "Shrink sidebar" +msgstr "" + #. Default: "Site" #: components/theme/PersonView msgid "Site" @@ -213,7 +304,10 @@ msgid "Subject page/URL" msgstr "Betreff Seite/URL" #. Default: "Success" +#: components/ContentReviewSidebar/DelegateReview +#: components/ContentReviewSidebar/PostponeReview #: components/FeedBackForm/FeedBackForm +#: components/Toolbar/DocumentReview msgid "Success" msgstr "Erfolg" @@ -227,6 +321,11 @@ msgstr "Die angezeigten Inhalte wurden anhand Deiner Organisationseinheit und De msgid "To submit a Like you must be logged in" msgstr "Um ein „Gefällt mir“ abzugeben, müssen Sie angemeldet sein." +#. Default: "Use preset review interval" +#: components/ContentReviewSidebar/PostponeReview +msgid "Use preset review interval" +msgstr "Voreingestelltes Überprüfungsintervall verwenden." + #. Default: "Website" #: components/Blocks/EventMetadata/View msgid "Website" @@ -237,11 +336,56 @@ msgstr "Website" msgid "Your feedback has been submitted successfully. You will receive a confirmation email shortly." msgstr "Ihr Feedback wurde erfolgreich übermittelt. Sie erhalten in Kürze eine Bestätigungs-E-Mail." +#. Default: "If you wish, you can leave a comment for the person incharge here" +#: components/ContentReviewSidebar/DelegateReview +msgid "delegateComment" +msgstr "Wenn Sie möchten, können Sie hier einen Kommentar für die beauftragte Person hinterlassen." + +#. Default: "Assign the view or update of this content to another person. Select the responsible person and provide a short description of the task." +#: components/ContentReviewSidebar/DelegateReview +msgid "delegateReview" +msgstr "Geben Sie die Überprüfung oder Überarbeitung dieses Inhalts an eine andere Person weiter. Wählen Sie die zuständige Person aus und fügen Sie eine kurze Beschreibung des Auftrags hinzu." + +#. Default: "Review has been successfully delegated" +#: components/ContentReviewSidebar/DelegateReview +msgid "delegateSuccessful" +msgstr "Die Überprüfung wurde erfolgreich delegiert." + +#. Default: "Delegate Review or Update" +#: components/ContentReviewSidebar/DelegateReview +msgid "delegateTitle" +msgstr "Prüfung oder Anpassung delegieren" + +#. Default: "The check interval is set to {interval}. To change it, you must edit the content." +#: components/ContentReviewSidebar/PostponeReview +msgid "help" +msgstr "Das Überprüfungsintervall ist auf %{intervall} eingestellt. Um es zu ändern, müssen Sie den Inhalt bearbeiten." + +#. Default: "Review has been successfully postponed" +#: components/ContentReviewSidebar/PostponeReview +msgid "messagePostpone" +msgstr "Die Überprüfung wurde erfolgreich verschoben." + #. Default: "last modified" #: slots/DocumentByLine/DocumentByLine msgid "modified" msgstr "zuletzt verändert" +#. Default: "Next Review on:" +#: components/ContentReviewSidebar/PostponeReview +msgid "nextReview" +msgstr "Nächste Kontrolle am: " + +#. Default: "If you wish, you can leave a comment here, for example, the reason for the postponement." +#: components/ContentReviewSidebar/PostponeReview +msgid "postponeComment" +msgstr "Wenn Sie möchten, können Sie hier einen Kommentar hinterlassen, beispielsweise den Grund für die " + +#. Default: "Postpone the next review date for this content. Select a new date or a time period after which you would like to be reminded again." +#: components/ContentReviewSidebar/PostponeReview +msgid "postponeReview" +msgstr "Verschieben Sie den nächsten Prüftermin für diesen Inhalt. Wählen Sie ein neues Datum oder einen Zeitraum, nach dem Sie erneut erinnert werden möchten." + #. Default: "published" #: slots/DocumentByLine/DocumentByLine msgid "published" diff --git a/frontend/packages/kitconcept-intranet/locales/en/LC_MESSAGES/volto.po b/frontend/packages/kitconcept-intranet/locales/en/LC_MESSAGES/volto.po index 38c7ad3f1..b0e826f61 100644 --- a/frontend/packages/kitconcept-intranet/locales/en/LC_MESSAGES/volto.po +++ b/frontend/packages/kitconcept-intranet/locales/en/LC_MESSAGES/volto.po @@ -16,6 +16,11 @@ msgstr "" msgid "Address" msgstr "Adresse" +#. Default: "Assignee: *" +#: components/ContentReviewSidebar/DelegateReview +msgid "Assignee" +msgstr "" + #. Default: "Bio" #: components/theme/PersonView msgid "Bio" @@ -32,21 +37,50 @@ msgid "By" msgstr "" #. Default: "Cancel" +#: components/ContentReviewSidebar/DelegateReview +#: components/ContentReviewSidebar/PostponeReview #: components/FeedBackForm/FeedBackForm msgid "Cancel" msgstr "" +#. Default: "Comment:" +#: components/ContentReviewSidebar/DelegateReview +#: components/ContentReviewSidebar/PostponeReview +msgid "Comment" +msgstr "" + #. Default: "Contact" #: components/Blocks/EventMetadata/View #: components/theme/PersonView msgid "Contact" msgstr "Kontakt" +#. Default: "Content marked as reviewed" +#: components/Toolbar/DocumentReview +msgid "Content marked as reviewed" +msgstr "" + #. Default: "Created On" #: components/ContentInteractions/ContentInteractions msgid "Created On" msgstr "" +#. Default: "Delegate Review Update" +#: components/Toolbar/DocumentReview +msgid "Delegate Review Update" +msgstr "" + +#. Default: "Delegate" +#: components/ContentReviewSidebar/DelegateReview +msgid "DelegateButton" +msgstr "" + +#. Default: "Document Review" +#: components/Toolbar/DocumentReview +#: components/Toolbar/DocumentReviewPlug +msgid "Document Review" +msgstr "" + #. Default: "E-mail" #: components/Summary/PersonSummary #: components/theme/PersonView @@ -65,10 +99,16 @@ msgstr "" #. Default: "Error" #: components/Blocks/IFrame/isValidUrl +#: components/ContentReviewSidebar/DelegateReview #: components/FeedBackForm/FeedBackForm msgid "Error" msgstr "" +#. Default: "Expand sidebar" +#: components/ContentReviewSidebar/ReviewSidebar +msgid "Expand sidebar" +msgstr "" + #. Default: "Feedback" #: components/FeedBackForm/FeedBackForm msgid "Feedback" @@ -114,6 +154,11 @@ msgstr "" msgid "Last Modified On" msgstr "" +#. Default: "Last updated" +#: components/Toolbar/DocumentReview +msgid "Last updated" +msgstr "" + #. Default: "List with date" #: index msgid "List with date" @@ -124,11 +169,26 @@ msgstr "" msgid "Location" msgstr "" +#. Default: "Mark Changes Required" +#: components/Toolbar/DocumentReview +msgid "Mark Changes Required" +msgstr "" + +#. Default: "Mark as Reviewed" +#: components/Toolbar/DocumentReview +msgid "Mark as Reviewed" +msgstr "" + #. Default: "Name" #: components/FeedBackForm/FeedBackForm msgid "Name" msgstr "" +#. Default: "Next review" +#: components/Toolbar/DocumentReview +msgid "Next review" +msgstr "" + #. Default: "Only internal e-mail addresses are permitted." #: components/FeedBackForm/FeedBackForm msgid "Only internal e-mail addresses are permitted." @@ -156,17 +216,43 @@ msgstr "" msgid "Please fill in the Feedback field" msgstr "" +#. Default: "Postpone" +#: components/ContentReviewSidebar/PostponeReview +msgid "Postpone" +msgstr "" + +#. Default: "Postpone Review" +#: components/Toolbar/DocumentReview +msgid "Postpone Review" +msgstr "" + +#. Default: "Postpone Review" +#: components/ContentReviewSidebar/PostponeReview +msgid "PostponeTitle" +msgstr "" + #. Default: "Responsibilities" #: index msgid "Responsibilities" msgstr "" +#. Default: "Review" +#: components/ContentReviewSidebar/ReviewSidebar +#: components/Toolbar/DocumentReviewPlug +msgid "Review" +msgstr "" + #. Default: "Room" #: components/Summary/PersonSummary #: components/theme/PersonView msgid "Room" msgstr "" +#. Default: "Please Select ..." +#: components/ContentReviewSidebar/DelegateReview +msgid "SelectAssigneePlaceholder" +msgstr "" + #. Default: "Send feedback" #: components/FeedBackForm/FeedBackForm msgid "Send feedback" @@ -182,6 +268,11 @@ msgstr "" msgid "Share this page via email" msgstr "" +#. Default: "Shrink sidebar" +#: components/ContentReviewSidebar/ReviewSidebar +msgid "Shrink sidebar" +msgstr "" + #. Default: "Site" #: components/theme/PersonView msgid "Site" @@ -213,7 +304,10 @@ msgid "Subject page/URL" msgstr "" #. Default: "Success" +#: components/ContentReviewSidebar/DelegateReview +#: components/ContentReviewSidebar/PostponeReview #: components/FeedBackForm/FeedBackForm +#: components/Toolbar/DocumentReview msgid "Success" msgstr "" @@ -227,6 +321,11 @@ msgstr "" msgid "To submit a Like you must be logged in" msgstr "" +#. Default: "Use preset review interval" +#: components/ContentReviewSidebar/PostponeReview +msgid "Use preset review interval" +msgstr "" + #. Default: "Website" #: components/Blocks/EventMetadata/View msgid "Website" @@ -237,11 +336,56 @@ msgstr "" msgid "Your feedback has been submitted successfully. You will receive a confirmation email shortly." msgstr "" +#. Default: "If you wish, you can leave a comment for the person incharge here" +#: components/ContentReviewSidebar/DelegateReview +msgid "delegateComment" +msgstr "" + +#. Default: "Assign the view or update of this content to another person. Select the responsible person and provide a short description of the task." +#: components/ContentReviewSidebar/DelegateReview +msgid "delegateReview" +msgstr "" + +#. Default: "Review has been successfully delegated" +#: components/ContentReviewSidebar/DelegateReview +msgid "delegateSuccessful" +msgstr "" + +#. Default: "Delegate Review or Update" +#: components/ContentReviewSidebar/DelegateReview +msgid "delegateTitle" +msgstr "" + +#. Default: "The check interval is set to {interval}. To change it, you must edit the content." +#: components/ContentReviewSidebar/PostponeReview +msgid "help" +msgstr "" + +#. Default: "Review has been successfully postponed" +#: components/ContentReviewSidebar/PostponeReview +msgid "messagePostpone" +msgstr "" + #. Default: "last modified" #: slots/DocumentByLine/DocumentByLine msgid "modified" msgstr "" +#. Default: "Next Review on:" +#: components/ContentReviewSidebar/PostponeReview +msgid "nextReview" +msgstr "" + +#. Default: "If you wish, you can leave a comment here, for example, the reason for the postponement." +#: components/ContentReviewSidebar/PostponeReview +msgid "postponeComment" +msgstr "" + +#. Default: "Postpone the next review date for this content. Select a new date or a time period after which you would like to be reminded again." +#: components/ContentReviewSidebar/PostponeReview +msgid "postponeReview" +msgstr "" + #. Default: "published" #: slots/DocumentByLine/DocumentByLine msgid "published" diff --git a/frontend/packages/kitconcept-intranet/locales/es/LC_MESSAGES/volto.po b/frontend/packages/kitconcept-intranet/locales/es/LC_MESSAGES/volto.po index 6e32f789b..cd6fe7ab6 100644 --- a/frontend/packages/kitconcept-intranet/locales/es/LC_MESSAGES/volto.po +++ b/frontend/packages/kitconcept-intranet/locales/es/LC_MESSAGES/volto.po @@ -23,6 +23,11 @@ msgstr "" msgid "Address" msgstr "" +#. Default: "Assignee: *" +#: components/ContentReviewSidebar/DelegateReview +msgid "Assignee" +msgstr "" + #. Default: "Bio" #: components/theme/PersonView msgid "Bio" @@ -39,21 +44,50 @@ msgid "By" msgstr "" #. Default: "Cancel" +#: components/ContentReviewSidebar/DelegateReview +#: components/ContentReviewSidebar/PostponeReview #: components/FeedBackForm/FeedBackForm msgid "Cancel" msgstr "" +#. Default: "Comment:" +#: components/ContentReviewSidebar/DelegateReview +#: components/ContentReviewSidebar/PostponeReview +msgid "Comment" +msgstr "" + #. Default: "Contact" #: components/Blocks/EventMetadata/View #: components/theme/PersonView msgid "Contact" msgstr "" +#. Default: "Content marked as reviewed" +#: components/Toolbar/DocumentReview +msgid "Content marked as reviewed" +msgstr "" + #. Default: "Created On" #: components/ContentInteractions/ContentInteractions msgid "Created On" msgstr "" +#. Default: "Delegate Review Update" +#: components/Toolbar/DocumentReview +msgid "Delegate Review Update" +msgstr "" + +#. Default: "Delegate" +#: components/ContentReviewSidebar/DelegateReview +msgid "DelegateButton" +msgstr "" + +#. Default: "Document Review" +#: components/Toolbar/DocumentReview +#: components/Toolbar/DocumentReviewPlug +msgid "Document Review" +msgstr "" + #. Default: "E-mail" #: components/Summary/PersonSummary #: components/theme/PersonView @@ -72,10 +106,16 @@ msgstr "" #. Default: "Error" #: components/Blocks/IFrame/isValidUrl +#: components/ContentReviewSidebar/DelegateReview #: components/FeedBackForm/FeedBackForm msgid "Error" msgstr "" +#. Default: "Expand sidebar" +#: components/ContentReviewSidebar/ReviewSidebar +msgid "Expand sidebar" +msgstr "" + #. Default: "Feedback" #: components/FeedBackForm/FeedBackForm msgid "Feedback" @@ -121,6 +161,11 @@ msgstr "" msgid "Last Modified On" msgstr "" +#. Default: "Last updated" +#: components/Toolbar/DocumentReview +msgid "Last updated" +msgstr "" + #. Default: "List with date" #: index msgid "List with date" @@ -131,11 +176,26 @@ msgstr "" msgid "Location" msgstr "" +#. Default: "Mark Changes Required" +#: components/Toolbar/DocumentReview +msgid "Mark Changes Required" +msgstr "" + +#. Default: "Mark as Reviewed" +#: components/Toolbar/DocumentReview +msgid "Mark as Reviewed" +msgstr "" + #. Default: "Name" #: components/FeedBackForm/FeedBackForm msgid "Name" msgstr "" +#. Default: "Next review" +#: components/Toolbar/DocumentReview +msgid "Next review" +msgstr "" + #. Default: "Only internal e-mail addresses are permitted." #: components/FeedBackForm/FeedBackForm msgid "Only internal e-mail addresses are permitted." @@ -163,17 +223,43 @@ msgstr "" msgid "Please fill in the Feedback field" msgstr "" +#. Default: "Postpone" +#: components/ContentReviewSidebar/PostponeReview +msgid "Postpone" +msgstr "" + +#. Default: "Postpone Review" +#: components/Toolbar/DocumentReview +msgid "Postpone Review" +msgstr "" + +#. Default: "Postpone Review" +#: components/ContentReviewSidebar/PostponeReview +msgid "PostponeTitle" +msgstr "" + #. Default: "Responsibilities" #: index msgid "Responsibilities" msgstr "" +#. Default: "Review" +#: components/ContentReviewSidebar/ReviewSidebar +#: components/Toolbar/DocumentReviewPlug +msgid "Review" +msgstr "" + #. Default: "Room" #: components/Summary/PersonSummary #: components/theme/PersonView msgid "Room" msgstr "" +#. Default: "Please Select ..." +#: components/ContentReviewSidebar/DelegateReview +msgid "SelectAssigneePlaceholder" +msgstr "" + #. Default: "Send feedback" #: components/FeedBackForm/FeedBackForm msgid "Send feedback" @@ -189,6 +275,11 @@ msgstr "" msgid "Share this page via email" msgstr "" +#. Default: "Shrink sidebar" +#: components/ContentReviewSidebar/ReviewSidebar +msgid "Shrink sidebar" +msgstr "" + #. Default: "Site" #: components/theme/PersonView msgid "Site" @@ -220,7 +311,10 @@ msgid "Subject page/URL" msgstr "" #. Default: "Success" +#: components/ContentReviewSidebar/DelegateReview +#: components/ContentReviewSidebar/PostponeReview #: components/FeedBackForm/FeedBackForm +#: components/Toolbar/DocumentReview msgid "Success" msgstr "" @@ -234,6 +328,11 @@ msgstr "" msgid "To submit a Like you must be logged in" msgstr "" +#. Default: "Use preset review interval" +#: components/ContentReviewSidebar/PostponeReview +msgid "Use preset review interval" +msgstr "" + #. Default: "Website" #: components/Blocks/EventMetadata/View msgid "Website" @@ -244,11 +343,56 @@ msgstr "" msgid "Your feedback has been submitted successfully. You will receive a confirmation email shortly." msgstr "" +#. Default: "If you wish, you can leave a comment for the person incharge here" +#: components/ContentReviewSidebar/DelegateReview +msgid "delegateComment" +msgstr "" + +#. Default: "Assign the view or update of this content to another person. Select the responsible person and provide a short description of the task." +#: components/ContentReviewSidebar/DelegateReview +msgid "delegateReview" +msgstr "" + +#. Default: "Review has been successfully delegated" +#: components/ContentReviewSidebar/DelegateReview +msgid "delegateSuccessful" +msgstr "" + +#. Default: "Delegate Review or Update" +#: components/ContentReviewSidebar/DelegateReview +msgid "delegateTitle" +msgstr "" + +#. Default: "The check interval is set to {interval}. To change it, you must edit the content." +#: components/ContentReviewSidebar/PostponeReview +msgid "help" +msgstr "" + +#. Default: "Review has been successfully postponed" +#: components/ContentReviewSidebar/PostponeReview +msgid "messagePostpone" +msgstr "" + #. Default: "last modified" #: slots/DocumentByLine/DocumentByLine msgid "modified" msgstr "" +#. Default: "Next Review on:" +#: components/ContentReviewSidebar/PostponeReview +msgid "nextReview" +msgstr "" + +#. Default: "If you wish, you can leave a comment here, for example, the reason for the postponement." +#: components/ContentReviewSidebar/PostponeReview +msgid "postponeComment" +msgstr "" + +#. Default: "Postpone the next review date for this content. Select a new date or a time period after which you would like to be reminded again." +#: components/ContentReviewSidebar/PostponeReview +msgid "postponeReview" +msgstr "" + #. Default: "published" #: slots/DocumentByLine/DocumentByLine msgid "published" diff --git a/frontend/packages/kitconcept-intranet/locales/pt_BR/LC_MESSAGES/volto.po b/frontend/packages/kitconcept-intranet/locales/pt_BR/LC_MESSAGES/volto.po index ea2bf6cac..8ac20d3d0 100644 --- a/frontend/packages/kitconcept-intranet/locales/pt_BR/LC_MESSAGES/volto.po +++ b/frontend/packages/kitconcept-intranet/locales/pt_BR/LC_MESSAGES/volto.po @@ -21,6 +21,11 @@ msgstr "" msgid "Address" msgstr "Endereço" +#. Default: "Assignee: *" +#: components/ContentReviewSidebar/DelegateReview +msgid "Assignee" +msgstr "" + #. Default: "Bio" #: components/theme/PersonView msgid "Bio" @@ -37,9 +42,17 @@ msgid "By" msgstr "Por" #. Default: "Cancel" +#: components/ContentReviewSidebar/DelegateReview +#: components/ContentReviewSidebar/PostponeReview #: components/FeedBackForm/FeedBackForm msgid "Cancel" -msgstr "Cancelar" +msgstr "" + +#. Default: "Comment:" +#: components/ContentReviewSidebar/DelegateReview +#: components/ContentReviewSidebar/PostponeReview +msgid "Comment" +msgstr "" #. Default: "Contact" #: components/Blocks/EventMetadata/View @@ -47,11 +60,32 @@ msgstr "Cancelar" msgid "Contact" msgstr "Contato" +#. Default: "Content marked as reviewed" +#: components/Toolbar/DocumentReview +msgid "Content marked as reviewed" +msgstr "" + #. Default: "Created On" #: components/ContentInteractions/ContentInteractions msgid "Created On" msgstr "Criado em" +#. Default: "Delegate Review Update" +#: components/Toolbar/DocumentReview +msgid "Delegate Review Update" +msgstr "" + +#. Default: "Delegate" +#: components/ContentReviewSidebar/DelegateReview +msgid "DelegateButton" +msgstr "" + +#. Default: "Document Review" +#: components/Toolbar/DocumentReview +#: components/Toolbar/DocumentReviewPlug +msgid "Document Review" +msgstr "" + #. Default: "E-mail" #: components/Summary/PersonSummary #: components/theme/PersonView @@ -70,10 +104,16 @@ msgstr "Término" #. Default: "Error" #: components/Blocks/IFrame/isValidUrl +#: components/ContentReviewSidebar/DelegateReview #: components/FeedBackForm/FeedBackForm msgid "Error" msgstr "Erro" +#. Default: "Expand sidebar" +#: components/ContentReviewSidebar/ReviewSidebar +msgid "Expand sidebar" +msgstr "" + #. Default: "Feedback" #: components/FeedBackForm/FeedBackForm msgid "Feedback" @@ -119,6 +159,11 @@ msgstr "URL inválida" msgid "Last Modified On" msgstr "Última modificação em" +#. Default: "Last updated" +#: components/Toolbar/DocumentReview +msgid "Last updated" +msgstr "" + #. Default: "List with date" #: index msgid "List with date" @@ -129,11 +174,26 @@ msgstr "Lista com data" msgid "Location" msgstr "Local" +#. Default: "Mark Changes Required" +#: components/Toolbar/DocumentReview +msgid "Mark Changes Required" +msgstr "" + +#. Default: "Mark as Reviewed" +#: components/Toolbar/DocumentReview +msgid "Mark as Reviewed" +msgstr "" + #. Default: "Name" #: components/FeedBackForm/FeedBackForm msgid "Name" msgstr "Nome" +#. Default: "Next review" +#: components/Toolbar/DocumentReview +msgid "Next review" +msgstr "" + #. Default: "Only internal e-mail addresses are permitted." #: components/FeedBackForm/FeedBackForm msgid "Only internal e-mail addresses are permitted." @@ -161,17 +221,43 @@ msgstr "Por favor, insira seu endereço de e-mail organizacional." msgid "Please fill in the Feedback field" msgstr "Por favor, preencha o campo de Feedback" +#. Default: "Postpone" +#: components/ContentReviewSidebar/PostponeReview +msgid "Postpone" +msgstr "" + +#. Default: "Postpone Review" +#: components/Toolbar/DocumentReview +msgid "Postpone Review" +msgstr "" + +#. Default: "Postpone Review" +#: components/ContentReviewSidebar/PostponeReview +msgid "PostponeTitle" +msgstr "" + #. Default: "Responsibilities" #: index msgid "Responsibilities" msgstr "Responsabilidades" +#. Default: "Review" +#: components/ContentReviewSidebar/ReviewSidebar +#: components/Toolbar/DocumentReviewPlug +msgid "Review" +msgstr "" + #. Default: "Room" #: components/Summary/PersonSummary #: components/theme/PersonView msgid "Room" msgstr "Sala" +#. Default: "Please Select ..." +#: components/ContentReviewSidebar/DelegateReview +msgid "SelectAssigneePlaceholder" +msgstr "" + #. Default: "Send feedback" #: components/FeedBackForm/FeedBackForm msgid "Send feedback" @@ -187,6 +273,11 @@ msgstr "Gostaria de compartilhar este conteúdo da intranet com você:" msgid "Share this page via email" msgstr "Compartilhe esta página por e-mail" +#. Default: "Shrink sidebar" +#: components/ContentReviewSidebar/ReviewSidebar +msgid "Shrink sidebar" +msgstr "" + #. Default: "Site" #: components/theme/PersonView msgid "Site" @@ -218,7 +309,10 @@ msgid "Subject page/URL" msgstr "Página/URL do assunto" #. Default: "Success" +#: components/ContentReviewSidebar/DelegateReview +#: components/ContentReviewSidebar/PostponeReview #: components/FeedBackForm/FeedBackForm +#: components/Toolbar/DocumentReview msgid "Success" msgstr "Sucesso" @@ -232,6 +326,11 @@ msgstr "O conteúdo exibido é personalizado para sua área organizacional e loc msgid "To submit a Like you must be logged in" msgstr "Para curtir, você precisa estar logado" +#. Default: "Use preset review interval" +#: components/ContentReviewSidebar/PostponeReview +msgid "Use preset review interval" +msgstr "" + #. Default: "Website" #: components/Blocks/EventMetadata/View msgid "Website" @@ -242,11 +341,56 @@ msgstr "Site" msgid "Your feedback has been submitted successfully. You will receive a confirmation email shortly." msgstr "Seu feedback foi enviado com sucesso. Você receberá um e-mail de confirmação em breve." +#. Default: "If you wish, you can leave a comment for the person incharge here" +#: components/ContentReviewSidebar/DelegateReview +msgid "delegateComment" +msgstr "" + +#. Default: "Assign the view or update of this content to another person. Select the responsible person and provide a short description of the task." +#: components/ContentReviewSidebar/DelegateReview +msgid "delegateReview" +msgstr "" + +#. Default: "Review has been successfully delegated" +#: components/ContentReviewSidebar/DelegateReview +msgid "delegateSuccessful" +msgstr "" + +#. Default: "Delegate Review or Update" +#: components/ContentReviewSidebar/DelegateReview +msgid "delegateTitle" +msgstr "" + +#. Default: "The check interval is set to {interval}. To change it, you must edit the content." +#: components/ContentReviewSidebar/PostponeReview +msgid "help" +msgstr "" + +#. Default: "Review has been successfully postponed" +#: components/ContentReviewSidebar/PostponeReview +msgid "messagePostpone" +msgstr "" + #. Default: "last modified" #: slots/DocumentByLine/DocumentByLine msgid "modified" msgstr "última modificação" +#. Default: "Next Review on:" +#: components/ContentReviewSidebar/PostponeReview +msgid "nextReview" +msgstr "" + +#. Default: "If you wish, you can leave a comment here, for example, the reason for the postponement." +#: components/ContentReviewSidebar/PostponeReview +msgid "postponeComment" +msgstr "" + +#. Default: "Postpone the next review date for this content. Select a new date or a time period after which you would like to be reminded again." +#: components/ContentReviewSidebar/PostponeReview +msgid "postponeReview" +msgstr "" + #. Default: "published" #: slots/DocumentByLine/DocumentByLine msgid "published" diff --git a/frontend/packages/kitconcept-intranet/locales/volto.pot b/frontend/packages/kitconcept-intranet/locales/volto.pot index 44a0acddb..b5dd7dfa1 100644 --- a/frontend/packages/kitconcept-intranet/locales/volto.pot +++ b/frontend/packages/kitconcept-intranet/locales/volto.pot @@ -1,7 +1,7 @@ msgid "" msgstr "" "Project-Id-Version: Plone\n" -"POT-Creation-Date: 2026-05-27T12:33:50.313Z\n" +"POT-Creation-Date: 2026-06-11T08:48:13.948Z\n" "Last-Translator: Plone i18n \n" "Language-Team: Plone i18n \n" "Content-Type: text/plain; charset=utf-8\n" @@ -18,6 +18,11 @@ msgstr "" msgid "Address" msgstr "" +#. Default: "Assignee: *" +#: components/ContentReviewSidebar/DelegateReview +msgid "Assignee" +msgstr "" + #. Default: "Bio" #: components/theme/PersonView msgid "Bio" @@ -34,21 +39,50 @@ msgid "By" msgstr "" #. Default: "Cancel" +#: components/ContentReviewSidebar/DelegateReview +#: components/ContentReviewSidebar/PostponeReview #: components/FeedBackForm/FeedBackForm msgid "Cancel" msgstr "" +#. Default: "Comment:" +#: components/ContentReviewSidebar/DelegateReview +#: components/ContentReviewSidebar/PostponeReview +msgid "Comment" +msgstr "" + #. Default: "Contact" #: components/Blocks/EventMetadata/View #: components/theme/PersonView msgid "Contact" msgstr "" +#. Default: "Content marked as reviewed" +#: components/Toolbar/DocumentReview +msgid "Content marked as reviewed" +msgstr "" + #. Default: "Created On" #: components/ContentInteractions/ContentInteractions msgid "Created On" msgstr "" +#. Default: "Delegate Review Update" +#: components/Toolbar/DocumentReview +msgid "Delegate Review Update" +msgstr "" + +#. Default: "Delegate" +#: components/ContentReviewSidebar/DelegateReview +msgid "DelegateButton" +msgstr "" + +#. Default: "Document Review" +#: components/Toolbar/DocumentReview +#: components/Toolbar/DocumentReviewPlug +msgid "Document Review" +msgstr "" + #. Default: "E-mail" #: components/Summary/PersonSummary #: components/theme/PersonView @@ -67,10 +101,16 @@ msgstr "" #. Default: "Error" #: components/Blocks/IFrame/isValidUrl +#: components/ContentReviewSidebar/DelegateReview #: components/FeedBackForm/FeedBackForm msgid "Error" msgstr "" +#. Default: "Expand sidebar" +#: components/ContentReviewSidebar/ReviewSidebar +msgid "Expand sidebar" +msgstr "" + #. Default: "Feedback" #: components/FeedBackForm/FeedBackForm msgid "Feedback" @@ -116,6 +156,11 @@ msgstr "" msgid "Last Modified On" msgstr "" +#. Default: "Last updated" +#: components/Toolbar/DocumentReview +msgid "Last updated" +msgstr "" + #. Default: "List with date" #: index msgid "List with date" @@ -126,11 +171,26 @@ msgstr "" msgid "Location" msgstr "" +#. Default: "Mark Changes Required" +#: components/Toolbar/DocumentReview +msgid "Mark Changes Required" +msgstr "" + +#. Default: "Mark as Reviewed" +#: components/Toolbar/DocumentReview +msgid "Mark as Reviewed" +msgstr "" + #. Default: "Name" #: components/FeedBackForm/FeedBackForm msgid "Name" msgstr "" +#. Default: "Next review" +#: components/Toolbar/DocumentReview +msgid "Next review" +msgstr "" + #. Default: "Only internal e-mail addresses are permitted." #: components/FeedBackForm/FeedBackForm msgid "Only internal e-mail addresses are permitted." @@ -158,17 +218,43 @@ msgstr "" msgid "Please fill in the Feedback field" msgstr "" +#. Default: "Postpone" +#: components/ContentReviewSidebar/PostponeReview +msgid "Postpone" +msgstr "" + +#. Default: "Postpone Review" +#: components/Toolbar/DocumentReview +msgid "Postpone Review" +msgstr "" + +#. Default: "Postpone Review" +#: components/ContentReviewSidebar/PostponeReview +msgid "PostponeTitle" +msgstr "" + #. Default: "Responsibilities" #: index msgid "Responsibilities" msgstr "" +#. Default: "Review" +#: components/ContentReviewSidebar/ReviewSidebar +#: components/Toolbar/DocumentReviewPlug +msgid "Review" +msgstr "" + #. Default: "Room" #: components/Summary/PersonSummary #: components/theme/PersonView msgid "Room" msgstr "" +#. Default: "Please Select ..." +#: components/ContentReviewSidebar/DelegateReview +msgid "SelectAssigneePlaceholder" +msgstr "" + #. Default: "Send feedback" #: components/FeedBackForm/FeedBackForm msgid "Send feedback" @@ -184,6 +270,11 @@ msgstr "" msgid "Share this page via email" msgstr "" +#. Default: "Shrink sidebar" +#: components/ContentReviewSidebar/ReviewSidebar +msgid "Shrink sidebar" +msgstr "" + #. Default: "Site" #: components/theme/PersonView msgid "Site" @@ -215,7 +306,10 @@ msgid "Subject page/URL" msgstr "" #. Default: "Success" +#: components/ContentReviewSidebar/DelegateReview +#: components/ContentReviewSidebar/PostponeReview #: components/FeedBackForm/FeedBackForm +#: components/Toolbar/DocumentReview msgid "Success" msgstr "" @@ -229,6 +323,11 @@ msgstr "" msgid "To submit a Like you must be logged in" msgstr "" +#. Default: "Use preset review interval" +#: components/ContentReviewSidebar/PostponeReview +msgid "Use preset review interval" +msgstr "" + #. Default: "Website" #: components/Blocks/EventMetadata/View msgid "Website" @@ -239,11 +338,56 @@ msgstr "" msgid "Your feedback has been submitted successfully. You will receive a confirmation email shortly." msgstr "" +#. Default: "If you wish, you can leave a comment for the person incharge here" +#: components/ContentReviewSidebar/DelegateReview +msgid "delegateComment" +msgstr "" + +#. Default: "Assign the view or update of this content to another person. Select the responsible person and provide a short description of the task." +#: components/ContentReviewSidebar/DelegateReview +msgid "delegateReview" +msgstr "" + +#. Default: "Review has been successfully delegated" +#: components/ContentReviewSidebar/DelegateReview +msgid "delegateSuccessful" +msgstr "" + +#. Default: "Delegate Review or Update" +#: components/ContentReviewSidebar/DelegateReview +msgid "delegateTitle" +msgstr "" + +#. Default: "The check interval is set to {interval}. To change it, you must edit the content." +#: components/ContentReviewSidebar/PostponeReview +msgid "help" +msgstr "" + +#. Default: "Review has been successfully postponed" +#: components/ContentReviewSidebar/PostponeReview +msgid "messagePostpone" +msgstr "" + #. Default: "last modified" #: slots/DocumentByLine/DocumentByLine msgid "modified" msgstr "" +#. Default: "Next Review on:" +#: components/ContentReviewSidebar/PostponeReview +msgid "nextReview" +msgstr "" + +#. Default: "If you wish, you can leave a comment here, for example, the reason for the postponement." +#: components/ContentReviewSidebar/PostponeReview +msgid "postponeComment" +msgstr "" + +#. Default: "Postpone the next review date for this content. Select a new date or a time period after which you would like to be reminded again." +#: components/ContentReviewSidebar/PostponeReview +msgid "postponeReview" +msgstr "" + #. Default: "published" #: slots/DocumentByLine/DocumentByLine msgid "published" diff --git a/frontend/packages/kitconcept-intranet/news/reviewSidebar.feature b/frontend/packages/kitconcept-intranet/news/reviewSidebar.feature new file mode 100644 index 000000000..922c4e156 --- /dev/null +++ b/frontend/packages/kitconcept-intranet/news/reviewSidebar.feature @@ -0,0 +1 @@ +Add review menu and sidebar. @Tishasoumya-02 \ No newline at end of file diff --git a/frontend/packages/kitconcept-intranet/src/actions/index.js b/frontend/packages/kitconcept-intranet/src/actions/index.js index a0e0a3967..88b5fdbae 100644 --- a/frontend/packages/kitconcept-intranet/src/actions/index.js +++ b/frontend/packages/kitconcept-intranet/src/actions/index.js @@ -13,3 +13,4 @@ export { submitFeedbackContactForm } from './emailSend'; export { toggleLike } from './likes/likes'; +export { postponeReview, delegateReview, approveReview } from './review/review'; diff --git a/frontend/packages/kitconcept-intranet/src/actions/review/review.js b/frontend/packages/kitconcept-intranet/src/actions/review/review.js new file mode 100644 index 000000000..7197fd9cc --- /dev/null +++ b/frontend/packages/kitconcept-intranet/src/actions/review/review.js @@ -0,0 +1,35 @@ +import { + POSTPONE_REVIEW, + DELEGATE_REVIEW, + APPROVE_REVIEW, +} from '../../constants/ActionTypes'; + +export function postponeReview(url, data) { + return { + type: POSTPONE_REVIEW, + request: { + op: 'post', + path: `${url}/@review/postpone`, + data, + }, + }; +} +export function delegateReview(url, data) { + return { + type: DELEGATE_REVIEW, + request: { + op: 'post', + path: `${url}/@review/delegate`, + data, + }, + }; +} +export function approveReview(url) { + return { + type: APPROVE_REVIEW, + request: { + op: 'post', + path: `${url}/@review/approve`, + }, + }; +} diff --git a/frontend/packages/kitconcept-intranet/src/components/ContentReviewSidebar/DelegateReview.jsx b/frontend/packages/kitconcept-intranet/src/components/ContentReviewSidebar/DelegateReview.jsx new file mode 100644 index 000000000..0f99a7c6b --- /dev/null +++ b/frontend/packages/kitconcept-intranet/src/components/ContentReviewSidebar/DelegateReview.jsx @@ -0,0 +1,167 @@ +import { useState } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { useIntl, defineMessages } from 'react-intl'; +import { + Accordion, + AccordionItem, + AccordionPanel, + Button, +} from '@plone/components/quanta'; +import { toast } from 'react-toastify'; +import { Form as UiForm } from '@plone/components'; +import { flattenToAppURL } from '@plone/volto/helpers/Url/Url'; +import SelectAutoComplete from '@plone/volto/components/manage/Widgets/SelectAutoComplete'; +import { delegateReview } from '../../actions'; +import Toast from '@plone/volto/components/manage/Toast/Toast'; +import TextareaWidget from '@plone/volto/components/manage/Widgets/TextareaWidget'; + +const messages = defineMessages({ + comment: { + id: 'Comment', + defaultMessage: 'Comment: ', + }, + delegateReview: { + id: 'delegateReview', + defaultMessage: + 'Assign the view or update of this content to another person. Select the responsible person and provide a short description of the task. ', + }, + delegateTitle: { + id: 'delegateTitle', + defaultMessage: 'Delegate Review or Update', + }, + cancel: { + id: 'Cancel', + defaultMessage: 'Cancel', + }, + delegateButton: { + id: 'DelegateButton', + defaultMessage: 'Delegate', + }, + success: { + id: 'Success', + defaultMessage: 'Success', + }, + messageDelegate: { + id: 'delegateSuccessful', + defaultMessage: 'Review has been successfully delegated', + }, + delegateComment: { + id: 'delegateComment', + defaultMessage: + 'If you wish, you can leave a comment for the person incharge here', + }, + selectAssignee: { + id: 'Assignee', + defaultMessage: 'Assignee: *', + }, + selectAssigneePlaceholder: { + id: 'SelectAssigneePlaceholder', + defaultMessage: 'Please Select ...', + }, + error: { + id: 'Error', + defaultMessage: 'Error', + }, +}); + +const DelegateReview = (props) => { + const { onClose } = props; + const dispatch = useDispatch(); + const content = useSelector((state) => state.content.data); + const [assignee, setAssignee] = useState(''); + const [comment, setComment] = useState(''); + + const intl = useIntl(); + const handleSubmit = (e) => { + e.preventDefault(); + const data = {}; + if (comment) data.comment = comment; + if (assignee) data.assignee = assignee; + dispatch(delegateReview(flattenToAppURL(content['@id']), data)) + .then(() => { + onClose(); + toast.success( + , + ); + }) + .catch((error) => { + toast.error( + , + ); + }); + }; + return ( + + + +
+ {intl.formatMessage(messages.delegateTitle)} +
+ +

{intl.formatMessage(messages.delegateReview)}

+ + setAssignee(value)} + wrapped={true} + /> + + setComment(value)} + value={comment} + isDisabled={false} + placeholder={intl.formatMessage(messages.delegateComment)} + /> + +
+ + +
+
+
+
+
+ ); +}; + +export default DelegateReview; diff --git a/frontend/packages/kitconcept-intranet/src/components/ContentReviewSidebar/PostponeReview.jsx b/frontend/packages/kitconcept-intranet/src/components/ContentReviewSidebar/PostponeReview.jsx new file mode 100644 index 000000000..7dcd79418 --- /dev/null +++ b/frontend/packages/kitconcept-intranet/src/components/ContentReviewSidebar/PostponeReview.jsx @@ -0,0 +1,174 @@ +import { useState } from 'react'; +import { useIntl, defineMessages } from 'react-intl'; +import { useDispatch, useSelector } from 'react-redux'; +import { toast } from 'react-toastify'; +import { + Accordion, + AccordionItem, + AccordionPanel, + Button, +} from '@plone/components/quanta'; +import { Form as UiForm } from '@plone/components'; +import CheckboxWidget from '@plone/volto/components/manage/Widgets/CheckboxWidget'; +import Toast from '@plone/volto/components/manage/Toast/Toast'; +import DatetimeWidget from '@plone/volto/components/manage/Widgets/DatetimeWidget'; +import { flattenToAppURL } from '@plone/volto/helpers/Url/Url'; +import { postponeReview } from '../../actions'; +import TextareaWidget from '@plone/volto/components/manage/Widgets/TextareaWidget'; + +const messages = defineMessages({ + usePresetReviewInterval: { + id: 'Use preset review interval', + defaultMessage: 'Use preset review interval', + }, + postponeTitle: { + id: 'PostponeTitle', + defaultMessage: 'Postpone Review', + }, + postponeReview: { + id: 'postponeReview', + defaultMessage: + 'Postpone the next review date for this content. Select a new date or a time period after which you would like to be reminded again.', + }, + comment: { + id: 'Comment', + defaultMessage: 'Comment:', + }, + cancel: { + id: 'Cancel', + defaultMessage: 'Cancel', + }, + postponeButton: { + id: 'Postpone', + defaultMessage: 'Postpone', + }, + help: { + id: 'help', + defaultMessage: + 'The check interval is set to {interval}. To change it, you must edit the content.', + }, + success: { + id: 'Success', + defaultMessage: 'Success', + }, + messagePostpone: { + id: 'messagePostpone', + defaultMessage: 'Review has been successfully postponed', + }, + postponeComment: { + id: 'postponeComment', + defaultMessage: + 'If you wish, you can leave a comment here, for example, the reason for the postponement.', + }, + nextReview: { + id: 'nextReview', + defaultMessage: 'Next Review on: ', + }, +}); + +const PostponeReview = (props) => { + const { onClose } = props; + const dispatch = useDispatch(); + const content = useSelector((state) => state.content.data); + const { review_due_date, review_interval } = content; + const [presetReviewInterval, setPresetReviewInterval] = useState( + Boolean(review_interval), + ); + const [dueDate, setDueDate] = useState(''); + const [comment, setComment] = useState(''); + const intl = useIntl(); + + const handleSubmit = (e) => { + e.preventDefault(); + const data = {}; + if (comment) data.comment = comment; + if (!presetReviewInterval && dueDate) data.due_date = dueDate; + dispatch(postponeReview(flattenToAppURL(content['@id']), data)).then(() => { + onClose(); + toast.success( + , + ); + }); + }; + + return ( + + + +
+ {intl.formatMessage(messages.postponeTitle)} +
+ +

{intl.formatMessage(messages.postponeReview)}

+ { + setPresetReviewInterval(value); + }} + /> + +

+ {intl.formatMessage(messages.help, { + interval: review_interval?.title ?? '0', + })} +

+ setDueDate(value)} + value={!presetReviewInterval ? dueDate : review_due_date} + /> + + setComment(value)} + value={comment} + isDisabled={false} + placeholder={intl.formatMessage(messages.postponeComment)} + /> + +
+ + +
+
+
+
+
+ ); +}; + +export default PostponeReview; diff --git a/frontend/packages/kitconcept-intranet/src/components/ContentReviewSidebar/ReviewSidebar.jsx b/frontend/packages/kitconcept-intranet/src/components/ContentReviewSidebar/ReviewSidebar.jsx new file mode 100644 index 000000000..416581f83 --- /dev/null +++ b/frontend/packages/kitconcept-intranet/src/components/ContentReviewSidebar/ReviewSidebar.jsx @@ -0,0 +1,171 @@ +import { useState, Fragment, useCallback, useEffect, useRef } from 'react'; +import { Button, Tab } from 'semantic-ui-react'; +import { useSelector } from 'react-redux'; +import { compose } from 'redux'; +import { withCookies } from 'react-cookie'; +import { defineMessages, useIntl } from 'react-intl'; +import cx from 'classnames'; +import { createPortal } from 'react-dom'; + +import BodyClass from '@plone/volto/helpers/BodyClass/BodyClass'; +import { getCookieOptions } from '@plone/volto/helpers/Cookies/cookies'; +import Icon from '@plone/volto/components/theme/Icon/Icon'; +import expandSVG from '@plone/volto/icons/left-key.svg'; +import collapseSVG from '@plone/volto/icons/right-key.svg'; +import DelegateReview from './DelegateReview'; +import { useClient } from '@plone/volto/hooks/client/useClient'; +import PostponeReview from './PostponeReview'; + +const messages = defineMessages({ + review: { + id: 'Review', + defaultMessage: 'Review', + }, + shrinkSidebar: { + id: 'Shrink sidebar', + defaultMessage: 'Shrink sidebar', + }, + expandSidebar: { + id: 'Expand sidebar', + defaultMessage: 'Expand sidebar', + }, +}); + +const ReviewSidebar = (props) => { + const intl = useIntl(); + const { cookies, content, documentTab = true, review } = props; + const [expanded, setExpanded] = useState( + cookies.get('sidebar_expanded') !== 'false', + ); + const isClient = useClient(); + const [size] = useState(0); + const [showFull, setshowFull] = useState(true); + const sidebarContainerRef = useRef(null); + + const tab = useSelector((state) => state.sidebar.tab); + const toolbarExpanded = useSelector((state) => state.toolbar.expanded); + + useEffect(() => { + const el = document.getElementById('sidebar'); + if (!el) return; + const handler = (e) => e.stopImmediatePropagation(); + el.addEventListener('mousedown', handler); + return () => el.removeEventListener('mousedown', handler); + }, []); + + const onToggleExpanded = () => { + cookies.set('sidebar_expanded', !expanded, getCookieOptions()); + setExpanded(!expanded); + resetFullSizeSidebar(); + }; + + const resetFullSizeSidebar = useCallback(() => { + if (!expanded) { + const sidebarContainer = sidebarContainerRef.current; + if (!sidebarContainer) return; + sidebarContainer.classList.remove('full-size'); + sidebarContainer.classList.remove('no-toolbar'); + setshowFull(true); + } + }, [expanded]); + + const onToggleFullSize = useCallback(() => { + const sidebarContainer = sidebarContainerRef.current; + if (!sidebarContainer) return; + + if (showFull) { + sidebarContainer.classList.add('full-size'); + if (!toolbarExpanded) { + sidebarContainer.classList.add('no-toolbar'); + } else { + sidebarContainer.classList.remove('no-toolbar'); + } + } else { + sidebarContainer.classList.remove('full-size'); + sidebarContainer.classList.remove('no-toolbar'); + } + setshowFull(!showFull); + }, [showFull, toolbarExpanded]); + + const reviewComponents = { DelegateReview, PostponeReview }; + const ReviewComponent = reviewComponents[review]; + + return ( + + +
0 ? { width: size } : null} + > + + + + ), + }, + ].filter((tab) => tab)} + /> +
+ {isClient && + ReviewComponent && + createPortal( + , + document.getElementById('sidebar-review'), + )} + +
+ + ); +}; + +export default compose(withCookies)(ReviewSidebar); diff --git a/frontend/packages/kitconcept-intranet/src/components/Toolbar/DocumentReview.jsx b/frontend/packages/kitconcept-intranet/src/components/Toolbar/DocumentReview.jsx new file mode 100644 index 000000000..45d2418da --- /dev/null +++ b/frontend/packages/kitconcept-intranet/src/components/Toolbar/DocumentReview.jsx @@ -0,0 +1,125 @@ +import { useDispatch, useSelector } from 'react-redux'; +import { useIntl, defineMessages } from 'react-intl'; +import { toast } from 'react-toastify'; +import { approveReview } from '@kitconcept/intranet/actions/review/review'; +import { flattenToAppURL } from '@plone/volto/helpers/Url/Url'; +import Toast from '@plone/volto/components/manage/Toast/Toast'; + +const messages = defineMessages({ + markAsReviewed: { + id: 'Mark as Reviewed', + defaultMessage: 'Mark as Reviewed', + }, + markChangesRequired: { + id: 'Mark Changes Required', + defaultMessage: 'Mark Changes Required', + }, + delegateReviewUpdate: { + id: 'Delegate Review Update', + defaultMessage: 'Delegate Review Update', + }, + postponeReview: { + id: 'Postpone Review', + defaultMessage: 'Postpone Review', + }, + documentReview: { + id: 'Document Review', + defaultMessage: 'Document Review', + }, + success: { + id: 'Success', + defaultMessage: 'Success', + }, + last_updated: { + id: 'Last updated', + defaultMessage: 'Last updated', + }, + next_review: { + id: 'Next review', + defaultMessage: 'Next review', + }, + messageReviewed: { + id: 'Content marked as reviewed', + defaultMessage: 'Content marked as reviewed', + }, +}); + +const DocumentReview = (props) => { + const dispatch = useDispatch(); + const content = useSelector((state) => state.content.data); + const intl = useIntl(); + const handleMarkAsReviewed = () => { + dispatch(approveReview(flattenToAppURL(content['@id']))).then(() => { + toast.success( + , + ); + }); + }; + return ( +
+
    +
  • + {intl.formatMessage(messages.documentReview)} +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • + +
  • + +
  • + +
    +
    +

    + {intl.formatMessage(messages.last_updated)}: +

    +

    + {content?.review_completed_date ?? ''} +

    +
    +
    +

    + {intl.formatMessage(messages.next_review)}: +

    +

    + {content?.review_due_date ?? ''} +

    +
    +
    +
+
+ ); +}; + +export default DocumentReview; diff --git a/frontend/packages/kitconcept-intranet/src/components/Toolbar/DocumentReviewPlug.jsx b/frontend/packages/kitconcept-intranet/src/components/Toolbar/DocumentReviewPlug.jsx new file mode 100644 index 000000000..5f081964d --- /dev/null +++ b/frontend/packages/kitconcept-intranet/src/components/Toolbar/DocumentReviewPlug.jsx @@ -0,0 +1,74 @@ +import { useState } from 'react'; +import { useSelector } from 'react-redux'; +import { defineMessages, useIntl } from 'react-intl'; +import { Button, DialogTrigger, Popover, Dialog } from 'react-aria-components'; +import { Plug } from '@plone/volto/components/manage/Pluggable'; +import Icon from '@plone/volto/components/theme/Icon/Icon'; +import rightArrowSVG from '@plone/volto/icons/right-key.svg'; +import DocumentReview from '@kitconcept/intranet/components/Toolbar/DocumentReview'; +import ReviewSidebar from '@kitconcept/intranet/components/ContentReviewSidebar/ReviewSidebar'; + +const messages = defineMessages({ + review: { + id: 'Review', + defaultMessage: 'Review', + }, + documentReview: { + id: 'Document Review', + defaultMessage: 'Document Review', + }, +}); + +const DocumentReviewPlug = () => { + const intl = useIntl(); + const site = useSelector((state) => state.site.data); + const enableContentReview = site['kitconcept.intranet.enable_content_review']; + const content = useSelector((state) => state.content?.data); + const [reviewType, setReviewType] = useState(null); + + if (!enableContentReview) return null; + + return ( + <> + +
  • + + + e.stopPropagation()} + > + + + + + +
  • +
    + {reviewType && ( + setReviewType(null)} + /> + )} + + ); +}; + +export default DocumentReviewPlug; diff --git a/frontend/packages/kitconcept-intranet/src/config/settings.ts b/frontend/packages/kitconcept-intranet/src/config/settings.ts index d4f11c28b..182f71c21 100644 --- a/frontend/packages/kitconcept-intranet/src/config/settings.ts +++ b/frontend/packages/kitconcept-intranet/src/config/settings.ts @@ -1,6 +1,7 @@ import type { ConfigType } from '@plone/registry'; import type { apiExpandersType } from '@plone/types'; import FeedBackForm from '../components/FeedBackForm/FeedBackForm'; +import DocumentReviewPlug from '@kitconcept/intranet/components/Toolbar/DocumentReviewPlug'; import feedbackContactForm from '../reducers/feedbackContactForm/feedbackContactForm'; export default function install(config: ConfigType) { @@ -20,6 +21,12 @@ export default function install(config: ConfigType) { ...config.addonReducers, feedbackContactForm, }; + + config.settings.appExtras = [ + ...config.settings.appExtras, + { match: '/', component: DocumentReviewPlug, props: {} }, + ]; + config.settings.isMultilingual = false; config.settings.nonContentRoutes = nonContentRoutes; config.settings.defaultLanguage = process.env.SITE_DEFAULT_LANGUAGE || 'de'; diff --git a/frontend/packages/kitconcept-intranet/src/constants/ActionTypes.js b/frontend/packages/kitconcept-intranet/src/constants/ActionTypes.js index 8e160e27e..22a9ad922 100644 --- a/frontend/packages/kitconcept-intranet/src/constants/ActionTypes.js +++ b/frontend/packages/kitconcept-intranet/src/constants/ActionTypes.js @@ -8,3 +8,6 @@ export const EMAIL_SEND = 'EMAIL_SEND'; export const CONTACTFORM_SUBMIT = 'CONTACTFORM_SUBMIT'; export const TOGGLE_LIKE = 'TOGGLE_LIKE'; +export const POSTPONE_REVIEW = 'POSTPONE_REVIEW'; +export const DELEGATE_REVIEW = 'DELEGATE_REVIEW'; +export const APPROVE_REVIEW = 'APPROVE_REVIEW'; diff --git a/frontend/packages/kitconcept-intranet/src/customizations/volto/components/manage/Form/Form.jsx b/frontend/packages/kitconcept-intranet/src/customizations/volto/components/manage/Form/Form.jsx new file mode 100644 index 000000000..840abc06f --- /dev/null +++ b/frontend/packages/kitconcept-intranet/src/customizations/volto/components/manage/Form/Form.jsx @@ -0,0 +1,1279 @@ +/* Customized to add conditional logic for content review fieldset */ + +/** + * Form component. + * @module components/manage/Form/Form + */ + +import Icon from '@plone/volto/components/theme/Icon/Icon'; +import Toast from '@plone/volto/components/manage/Toast/Toast'; +import { Field, BlocksForm } from '@plone/volto/components/manage/Form'; +import BlocksToolbar from '@plone/volto/components/manage/Form/BlocksToolbar'; +import UndoToolbar from '@plone/volto/components/manage/Form/UndoToolbar'; +import { difference } from '@plone/volto/helpers/Utils/Utils'; +import withSaveAsDraft from '@plone/volto/helpers/Utils/withSaveAsDraft'; +import FormValidation from '@plone/volto/helpers/FormValidation/FormValidation'; +import { + getBlocksFieldname, + getBlocksLayoutFieldname, + hasBlocksData, +} from '@plone/volto/helpers/Blocks/Blocks'; +import { applySchemaEnhancer } from '@plone/volto/helpers/Extensions/withBlockSchemaEnhancer'; +import { messages } from '@plone/volto/helpers/MessageLabels/MessageLabels'; +import aheadSVG from '@plone/volto/icons/ahead.svg'; +import clearSVG from '@plone/volto/icons/clear.svg'; +import upSVG from '@plone/volto/icons/up-key.svg'; +import downSVG from '@plone/volto/icons/down-key.svg'; +import findIndex from 'lodash/findIndex'; +import isEmpty from 'lodash/isEmpty'; +import isEqual from 'lodash/isEqual'; +import keys from 'lodash/keys'; +import map from 'lodash/map'; +import mapValues from 'lodash/mapValues'; +import pickBy from 'lodash/pickBy'; +import without from 'lodash/without'; +import cloneDeep from 'lodash/cloneDeep'; +import xor from 'lodash/xor'; +import isBoolean from 'lodash/isBoolean'; +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { injectIntl } from 'react-intl'; +import { createPortal } from 'react-dom'; +import { connect } from 'react-redux'; +import { + Accordion, + Button, + Container as SemanticContainer, + Form as UiForm, + Message, + Segment, + Tab, +} from 'semantic-ui-react'; +import { v4 as uuid } from 'uuid'; +import { toast } from 'react-toastify'; +import { + setMetadataFieldsets, + resetMetadataFocus, + setSidebarTab, +} from '@plone/volto/actions/sidebar/sidebar'; +import { setFormData, setUIState } from '@plone/volto/actions/form/form'; +import { compose } from 'redux'; +import config from '@plone/volto/registry'; +import SlotRenderer from '@plone/volto/components/theme/SlotRenderer/SlotRenderer'; + +const noop = () => {}; + +/** + * Form container class. + * @class Form + * @extends Component + */ +class Form extends Component { + /** + * Property types. + * @property {Object} propTypes Property types. + * @static + */ + static propTypes = { + schema: PropTypes.shape({ + fieldsets: PropTypes.arrayOf( + PropTypes.shape({ + fields: PropTypes.arrayOf(PropTypes.string), + id: PropTypes.string, + title: PropTypes.string, + }), + ), + properties: PropTypes.objectOf(PropTypes.any), + definitions: PropTypes.objectOf(PropTypes.any), + required: PropTypes.arrayOf(PropTypes.string), + }), + widgets: PropTypes.objectOf(PropTypes.any), + component: PropTypes.any, + formData: PropTypes.objectOf(PropTypes.any), + globalData: PropTypes.objectOf(PropTypes.any), + metadataFieldsets: PropTypes.arrayOf(PropTypes.string), + metadataFieldFocus: PropTypes.string, + pathname: PropTypes.string, + onSubmit: PropTypes.func, + onCancel: PropTypes.func, + submitLabel: PropTypes.string, + cancelLabel: PropTypes.string, + textButtons: PropTypes.bool, + buttonComponent: PropTypes.any, + resetAfterSubmit: PropTypes.bool, + resetOnCancel: PropTypes.bool, + isEditForm: PropTypes.bool, + isAdminForm: PropTypes.bool, + title: PropTypes.string, + error: PropTypes.shape({ + message: PropTypes.string, + }), + loading: PropTypes.bool, + hideActions: PropTypes.bool, + description: PropTypes.string, + visual: PropTypes.bool, + blocks: PropTypes.arrayOf(PropTypes.object), + isFormSelected: PropTypes.bool, + onSelectForm: PropTypes.func, + editable: PropTypes.bool, + onChangeFormData: PropTypes.func, + requestError: PropTypes.string, + allowedBlocks: PropTypes.arrayOf(PropTypes.string), + showRestricted: PropTypes.bool, + global: PropTypes.bool, + checkSavedDraft: PropTypes.func, + onSaveDraft: PropTypes.func, + onCancelDraft: PropTypes.func, + }; + + /** + * Default properties. + * @property {Object} defaultProps Default properties. + * @static + */ + static defaultProps = { + formData: null, + widgets: null, + component: null, + onSubmit: null, + onCancel: null, + submitLabel: null, + cancelLabel: null, + textButtons: false, + buttonComponent: null, + resetAfterSubmit: false, + resetOnCancel: false, + isEditForm: false, + isAdminForm: false, + title: null, + description: null, + error: null, + loading: null, + hideActions: false, + visual: false, + blocks: [], + pathname: '', + schema: {}, + isFormSelected: true, + onSelectForm: null, + editable: true, + requestError: null, + allowedBlocks: null, + global: false, + checkSavedDraft: noop, + onSaveDraft: noop, + onCancelDraft: noop, + }; + + /** + * Constructor + * @method constructor + * @param {Object} props Component properties + * @constructs Form + */ + constructor(props) { + super(props); + const ids = { + title: uuid(), + text: uuid(), + }; + let { formData, schema: originalSchema } = props; + const blocksFieldname = getBlocksFieldname(formData); + const blocksLayoutFieldname = getBlocksLayoutFieldname(formData); + + const schema = this.removeBlocksLayoutFields(originalSchema); + + this.props.setMetadataFieldsets( + schema?.fieldsets ? schema.fieldsets.map((fieldset) => fieldset.id) : [], + ); + + if (!props.isEditForm) { + // It's a normal (add form), get defaults from schema + formData = { + ...mapValues(props.schema.properties, 'default'), + ...formData, + }; + } + + // We initialize the formData snapshot in here, before the initial data checks + const initialFormData = cloneDeep(formData); + + // Adding fallback in case the fields are empty, so we are sure that the edit form + // shows at least the default blocks + if ( + formData?.hasOwnProperty(blocksFieldname) && + formData?.hasOwnProperty(blocksLayoutFieldname) + ) { + if ( + !formData[blocksLayoutFieldname] || + isEmpty(formData[blocksLayoutFieldname].items) + ) { + formData[blocksLayoutFieldname] = { + items: [ids.title, ids.text], + }; + } + if (!formData[blocksFieldname] || isEmpty(formData[blocksFieldname])) { + formData[blocksFieldname] = { + [ids.title]: { + '@type': 'title', + }, + [ids.text]: { + '@type': config.settings.defaultBlockType, + }, + }; + } + } + + let selectedBlock = null; + if ( + formData?.hasOwnProperty(blocksLayoutFieldname) && + formData[blocksLayoutFieldname].items.length > 0 + ) { + if (config.blocks?.initialBlocksFocus === null) { + selectedBlock = null; + } else if (this.props.type in config.blocks?.initialBlocksFocus) { + // Default selected is not the first block, but the one from config. + // TODO Select first block and not an arbitrary one. + Object.keys(formData[blocksFieldname]).forEach((b_key) => { + if ( + formData[blocksFieldname][b_key]['@type'] === + config.blocks?.initialBlocksFocus?.[this.props.type] + ) { + selectedBlock = b_key; + } + }); + } else { + selectedBlock = formData[blocksLayoutFieldname].items[0]; + } + } + + // Sync state to global state + if (this.props.global) { + this.props.setFormData(formData); + } + + this.props.setUIState({ + selected: selectedBlock, + multiSelected: [], + hovered: null, + }); + + // Set initial state + this.state = { + formData, + initialFormData, + errors: {}, + isClient: false, + // Ensure focus remain in field after change + inFocus: {}, + sidebarMetadataIsAvailable: false, + }; + this.onChangeField = this.onChangeField.bind(this); + this.onSelectBlock = this.onSelectBlock.bind(this); + this.onSubmit = this.onSubmit.bind(this); + this.onCancel = this.onCancel.bind(this); + this.onTabChange = this.onTabChange.bind(this); + this.onBlurField = this.onBlurField.bind(this); + this.onClickInput = this.onClickInput.bind(this); + this.onToggleMetadataFieldset = this.onToggleMetadataFieldset.bind(this); + this.updateFormDataWithSaved = this.updateFormDataWithSaved.bind(this); + } + + /** + * Function sent as callback to saveAsDraft when user + * choses to load local data + * @param {Object} savedFormData + */ + updateFormDataWithSaved(savedFormData) { + if (savedFormData) { + this.setState({ formData: savedFormData }); + } + } + + /** + * On updates caused by props change + * if errors from Backend come, these will be shown to their corresponding Fields + * also the first Tab to have any errors will be selected + * @param {Object} prevProps + */ + async componentDidUpdate(prevProps, prevState) { + let { requestError } = this.props; + let errors = {}; + let activeIndex = 0; + + if (!prevProps.schema && this.props.schema) { + this.props.checkSavedDraft( + this.state.formData, + this.updateFormDataWithSaved, + ); + } + if (!this.props.isFormSelected && prevProps.isFormSelected) { + this.props.setUIState({ + selected: null, + }); + } + + if (requestError && prevProps.requestError !== requestError) { + errors = + FormValidation.giveServerErrorsToCorrespondingFields(requestError); + activeIndex = FormValidation.showFirstTabWithErrors({ + errors, + schema: this.props.schema, + }); + + this.setState({ + errors, + activeIndex, + }); + } + + if (this.props.onChangeFormData) { + if (!isEqual(prevState?.formData, this.state.formData)) { + this.props.onChangeFormData(this.state.formData); + } + } + // on each formData update it will save the form to the localStorage + if (!isEqual(prevState?.formData, this.state.formData)) { + this.props.onSaveDraft(this.state.formData); + } + if ( + this.props.global && + !isEqual(this.props.globalData, prevProps.globalData) + ) { + this.setState({ + formData: this.props.globalData, + }); + } + + if (!isEqual(prevProps.schema, this.props.schema)) { + this.props.setMetadataFieldsets( + this.removeBlocksLayoutFields(this.props.schema).fieldsets.map( + (fieldset) => fieldset.id, + ), + ); + } + + if ( + this.props.metadataFieldFocus !== '' && + !isEqual(prevProps.metadataFieldFocus, this.props.metadataFieldFocus) + ) { + // Scroll into view + document + .querySelector(`.field-wrapper-${this.props.metadataFieldFocus}`) + .scrollIntoView(); + + // Set focus to first input if available + document + .querySelector(`.field-wrapper-${this.props.metadataFieldFocus} input`) + ?.focus(); + + // Reset focus field + this.props.resetMetadataFocus(); + } + + if ( + !this.state.sidebarMetadataIsAvailable && + document.getElementById('sidebar-metadata') + ) { + this.setState(() => ({ sidebarMetadataIsAvailable: true })); + } + } + + /** + * Tab selection is done only by setting activeIndex in state + */ + onTabChange(e, { activeIndex }) { + const defaultFocus = this.props.schema.fieldsets[activeIndex].fields[0]; + this.setState({ + activeIndex, + ...(defaultFocus ? { inFocus: { [defaultFocus]: true } } : {}), + }); + } + + /** + * If user clicks on input, the form will be not considered pristine + * this will avoid onBlur effects without interaction with the form + * @param {Object} e event + */ + onClickInput(e) { + this.setState({ isFormPristine: false }); + } + + /** + * Validate fields on blur + * @method onBlurField + * @param {string} id Id of the field + * @param {*} value Value of the field + * @returns {undefined} + */ + onBlurField(id, value) { + if (!this.state.isFormPristine) { + const errors = FormValidation.validateFieldsPerFieldset({ + schema: this.props.schema, + formData: this.state.formData, + formatMessage: this.props.intl.formatMessage, + touchedField: { [id]: value }, + }); + + this.setState({ + errors, + }); + } + } + + /** + * Component did mount + * @method componentDidMount + * @returns {undefined} + */ + componentDidMount() { + this.setState({ isClient: true }); + if (this.props.schema) { + this.props.checkSavedDraft( + this.state.formData, + this.updateFormDataWithSaved, + ); + return; + } + } + /* START CUSTOMIZATION */ + /** + * Get fields to render, filtering content review fields based on review_timeless + * @method getFieldsToRender + * @param {Array} fields Original fields array + * @param {Object} formData Current form data + * @returns {Array} Filtered fields array + */ + getFieldsToRender(fields, formData) { + if (formData?.review_timeless) { + return fields.filter( + (field) => field === 'review_timeless' || !field.startsWith('review_'), + ); + } + return fields; + } + + /** + * Calculate review due date based on interval + * @method calcDueDate + * @param {string} interval Interval string like "1m", "2w" + * @returns {string} ISO date string + */ + calcDueDate(interval) { + if (!interval) return null; + const today = new Date(); + const mapping = { + d: 'days', + w: 'weeks', + m: 'months', + y: 'years', + }; + const unit = mapping[interval.slice(-1)]; + const amount = parseInt(interval.slice(0, -1)); + const dueDate = new Date(today); + if (unit === 'days') dueDate.setDate(today.getDate() + amount); + else if (unit === 'weeks') dueDate.setDate(today.getDate() + amount * 7); + else if (unit === 'months') dueDate.setMonth(today.getMonth() + amount); + else if (unit === 'years') + dueDate.setFullYear(today.getFullYear() + amount); + return dueDate.toISOString().split('T')[0]; + } + /* END CUSTOMIZATION */ + + /** + * Change field handler + * Remove errors for changed field + * @method onChangeField + * @param {string} id Id of the field + * @param {*} value Value of the field + * @returns {undefined} + */ + onChangeField(id, value) { + this.setState((prevState) => { + const { errors, formData } = prevState; + const newFormData = { + ...formData, + // We need to catch also when the value equals false this fixes #888 + [id]: value || (value !== undefined && isBoolean(value)) ? value : null, + }; + // START CUSTOMIZATION: Handle content review field changes + if (id === 'review_interval') { + // Update review_due_date when review_interval changes + newFormData.review_due_date = this.calcDueDate(value); + } else if (id === 'review_due_date') { + newFormData.review_interval = null; + } + // END CUSTOMIZATION + + delete errors[id]; + if (this.props.global) { + this.props.setFormData(newFormData); + } + return { + errors, + formData: newFormData, + // Changing the form data re-renders the select widget which causes the + // focus to get lost. To circumvent this, we set the focus back to + // the input. + // This could fix other widgets too but currently targeted + // against the select widget only. + // Ensure field to be in focus after the change + inFocus: { [id]: true }, + }; + }); + } + + /** + * Select block handler + * @method onSelectBlock + * @param {string} id Id of the field + * @param {string} isMultipleSelection true if multiple blocks are selected + * @returns {undefined} + */ + onSelectBlock(id, isMultipleSelection, event) { + let multiSelected = []; + let selected = id; + const formData = this.state.formData; + + if (isMultipleSelection) { + selected = null; + const blocksLayoutFieldname = getBlocksLayoutFieldname(formData); + + const blocks_layout = formData[blocksLayoutFieldname].items; + + if (event.shiftKey) { + const anchor = + this.props.uiState.multiSelected.length > 0 + ? blocks_layout.indexOf(this.props.uiState.multiSelected[0]) + : blocks_layout.indexOf(this.props.uiState.selected); + const focus = blocks_layout.indexOf(id); + + if (anchor === focus) { + multiSelected = [id]; + } else if (focus > anchor) { + multiSelected = [...blocks_layout.slice(anchor, focus + 1)]; + } else { + multiSelected = [...blocks_layout.slice(focus, anchor + 1)]; + } + window.getSelection().empty(); + } + + if ((event.ctrlKey || event.metaKey) && !event.shiftKey) { + multiSelected = this.props.uiState.multiSelected || []; + if (!this.props.uiState.multiSelected.includes(this.state.selected)) { + multiSelected = [...multiSelected, this.props.uiState.selected]; + selected = null; + } + if (this.props.uiState.multiSelected.includes(id)) { + selected = null; + multiSelected = without(multiSelected, id); + } else { + multiSelected = [...multiSelected, id]; + } + } + } + + this.props.setUIState({ + selected, + multiSelected, + gridSelected: null, + }); + + if (this.props.onSelectForm) { + if (event) event.nativeEvent.stopImmediatePropagation(); + this.props.onSelectForm(); + } + } + + /** + * Cancel handler + * It prevents event from triggering submit, reset form if props.resetAfterSubmit + * and calls this.props.onCancel + * @method onCancel + * @param {Object} event Event object. + * @returns {undefined} + */ + onCancel(event) { + if (event) { + event.preventDefault(); + } + if (this.props.resetOnCancel || this.props.resetAfterSubmit) { + this.setState({ + formData: this.props.formData, + }); + if (this.props.global) { + this.props.setFormData(this.props.formData); + } + } + this.props.onCancel(event); + } + + /** + * Submit handler also validate form and collect errors + * @method onSubmit + * @param {Object} event Event object. + * @returns {undefined} + */ + onSubmit(event) { + const formData = this.state.formData; + + if (event) { + event.preventDefault(); + } + + const errors = this.props.schema + ? FormValidation.validateFieldsPerFieldset({ + schema: this.props.schema, + formData, + formatMessage: this.props.intl.formatMessage, + }) + : {}; + + let blocksErrors = {}; + + if (hasBlocksData(formData)) { + // Validate blocks + const blocks = this.state.formData[getBlocksFieldname(formData)]; + const blocksLayout = + this.state.formData[getBlocksLayoutFieldname(formData)]; + const defaultSchema = { + properties: {}, + fieldsets: [], + required: [], + }; + blocksLayout.items.forEach((block) => { + let blockSchema = + config.blocks.blocksConfig[blocks[block]['@type']].blockSchema || + defaultSchema; + if (typeof blockSchema === 'function') { + blockSchema = blockSchema({ + intl: this.props.intl, + formData: blocks[block], + }); + } + + if (config.blocks.blocksConfig[blocks[block]['@type']].blockSchema) { + blockSchema = applySchemaEnhancer({ + schema: blockSchema, + formData: blocks[block], + intl: this.props.intl, + blocksConfig: config.blocks.blocksConfig, + navRoot: this.props.navRoot, + contentType: this.props.content['@type'], + }); + } + + const blockErrors = FormValidation.validateFieldsPerFieldset({ + schema: blockSchema, + formData: blocks[block], + formatMessage: this.props.intl.formatMessage, + }); + if (keys(blockErrors).length > 0) { + blocksErrors = { + ...blocksErrors, + [block]: { ...blockErrors }, + }; + } + }); + } + + if (keys(errors).length > 0 || keys(blocksErrors).length > 0) { + const activeIndex = FormValidation.showFirstTabWithErrors({ + errors, + schema: this.props.schema, + }); + + this.setState({ + errors: { + ...errors, + ...(!isEmpty(blocksErrors) && { blocks: blocksErrors }), + }, + activeIndex, + }); + + if (keys(errors).length > 0) { + // Changes the focus to the metadata tab in the sidebar if error + Object.keys(errors).forEach((err) => + toast.error( + , + ), + ); + this.props.setSidebarTab(0); + } else if (keys(blocksErrors).length > 0) { + const errorField = Object.entries( + Object.entries(blocksErrors)[0][1], + )[0][0]; + const errorMessage = Object.entries( + Object.entries(blocksErrors)[0][1], + )[0][1]; + const errorFieldTitle = errorMessage.title || errorField; + + toast.error( + , + ); + this.props.setSidebarTab(1); + this.props.setUIState({ + selected: Object.keys(blocksErrors)[0], + multiSelected: [], + hovered: null, + }); + } + } else { + // Get only the values that have been modified (Edit forms), send all in case that + // it's an add form + if (this.props.isEditForm) { + this.props.onSubmit(this.getOnlyFormModifiedValues()); + } else { + this.props.onSubmit(formData); + } + if (this.props.resetAfterSubmit) { + this.setState({ + formData: this.props.formData, + }); + if (this.props.global) { + this.props.setFormData(this.props.formData); + } + } + this.props.onCancelDraft(); + } + } + + /** + * getOnlyFormModifiedValues handler + * It returns only the values of the fields that are have really changed since the + * form was loaded. Useful for edit forms and PATCH operations, when we only want to + * send the changed data. + * @method getOnlyFormModifiedValues + * @param {Object} event Event object. + * @returns {undefined} + */ + getOnlyFormModifiedValues = () => { + const formData = this.state.formData; + + const fieldsModified = Object.keys( + difference(formData, this.state.initialFormData), + ); + return { + ...pickBy(formData, (value, key) => fieldsModified.includes(key)), + ...(formData['@static_behaviors'] && { + '@static_behaviors': formData['@static_behaviors'], + }), + }; + }; + + /** + * Removed blocks and blocks_layout fields from the form. + * @method removeBlocksLayoutFields + * @param {object} schema The schema definition of the form. + * @returns A modified copy of the given schema. + */ + removeBlocksLayoutFields = (schema) => { + const newSchema = { ...schema }; + const layoutFieldsetIndex = findIndex( + newSchema.fieldsets, + (fieldset) => fieldset.id === 'layout', + ); + if (layoutFieldsetIndex > -1) { + const layoutFields = newSchema.fieldsets[layoutFieldsetIndex].fields; + newSchema.fieldsets[layoutFieldsetIndex].fields = layoutFields.filter( + (field) => field !== 'blocks' && field !== 'blocks_layout', + ); + if (newSchema.fieldsets[layoutFieldsetIndex].fields.length === 0) { + newSchema.fieldsets = [ + ...newSchema.fieldsets.slice(0, layoutFieldsetIndex), + ...newSchema.fieldsets.slice(layoutFieldsetIndex + 1), + ]; + } + } + return newSchema; + }; + + /** + * Toggle metadata fieldset handler + * @method onToggleMetadataFieldset + * @param {Object} event Event object. + * @param {Object} blockProps Block properties. + * @returns {undefined} + */ + onToggleMetadataFieldset(event, blockProps) { + const { index } = blockProps; + this.props.setMetadataFieldsets(xor(this.props.metadataFieldsets, [index])); + } + + /** + * Render method. + * @method render + * @returns {string} Markup for the component. + */ + render() { + const { settings } = config; + const { + schema: originalSchema, + onCancel, + onSubmit, + navRoot, + type, + metadataFieldsets, + component, + buttonComponent, + } = this.props; + const formData = this.state.formData; + const schema = this.removeBlocksLayoutFields(originalSchema); + const Container = + config.getComponent({ name: 'Container' }).component || SemanticContainer; + const FormComponent = component || UiForm; + const ButtonComponent = buttonComponent || Button; + + return this.props.visual ? ( + // Removing this from SSR is important, since react-beautiful-dnd supports SSR, + // but draftJS don't like it much and the hydration gets messed up + this.state.isClient && ( + <> + + + + <> + { + const newFormData = { + ...formData, + ...newBlockData, + }; + this.setState({ + formData: newFormData, + }); + if (this.props.global) { + this.props.setFormData(newFormData); + } + }} + onSetSelectedBlocks={(blockIds) => + this.props.setUIState({ multiSelected: blockIds }) + } + onSelectBlock={this.onSelectBlock} + /> + { + if (this.props.global) { + this.props.setFormData(state.formData); + } + return this.setState(state); + }} + /> + { + const newFormData = { + ...formData, + ...newData, + }; + this.setState({ + formData: newFormData, + }); + if (this.props.global) { + this.props.setFormData(newFormData); + } + }} + onChangeField={this.onChangeField} + onSelectBlock={this.onSelectBlock} + properties={formData} + navRoot={navRoot} + type={type} + pathname={this.props.pathname} + selectedBlock={this.props.uiState.selected} + multiSelected={this.props.uiState.multiSelected} + manage={this.props.isAdminForm} + allowedBlocks={this.props.allowedBlocks} + showRestricted={this.props.showRestricted} + editable={this.props.editable} + isMainForm={this.props.editable} + // Properties to pass to the BlocksForm to match the View ones + history={this.props.history} + location={this.props.location} + token={this.props.token} + errors={this.state.errors} + blocksErrors={this.state.errors.blocks} + /> + {this.state.isClient && + this.state.sidebarMetadataIsAvailable && + this.props.editable && + createPortal( + 0} + > + {schema && + map(schema.fieldsets, (fieldset) => ( + +
    + + {fieldset.title} + {metadataFieldsets.includes(fieldset.id) ? ( + + ) : ( + + )} + + + + { + /* START CUSTOMIZATION: Filter fields based on review_timeless */ + map( + this.getFieldsToRender( + fieldset.fields, + formData, + ), + (field, index) => ( + /* END CUSTOMIZATION */ + + ), + ) + } + + +
    +
    + ))} +
    , + document.getElementById('sidebar-metadata'), + )} + + + +
    + + ) + ) : ( + + 0} + className={settings.verticalFormTabs ? 'vertical-form' : ''} + > +
    + + {schema && schema.fieldsets.length > 1 && ( + <> + {settings.verticalFormTabs && this.props.title && ( + + {this.props.title} + + )} + ({ + menuItem: item.title, + render: () => [ + !settings.verticalFormTabs && this.props.title && ( + + {this.props.title} + + ), + item.description && ( + + {item.description} + + ), + ...map( + /* START CUSTOMIZATION*/ + this.getFieldsToRender(item.fields, formData), + /* END CUSTOMIZATION */ + (field, index) => ( + {} + } + onBlur={this.onBlurField} + onClick={this.onClickInput} + key={field} + error={this.state.errors[field]} + /> + ), + ), + ], + }))} + /> + + )} + {schema && schema.fieldsets.length === 1 && ( + + {this.props.title && ( + +

    {this.props.title}

    +
    + )} + {this.props.description && ( + {this.props.description} + )} + {keys(this.state.errors).length > 0 && ( + + )} + {this.props.error && ( + + )} + { + /* START CUSTOMIZATION Filter fields based on review_timeless */ + map( + this.getFieldsToRender( + schema.fieldsets[0].fields, + formData, + ), + (field) => ( + /* END CUSTOMIZATION */ + + ), + ) + } +
    + )} + {!this.props.hideActions && ( + + {onSubmit && + (this.props.textButtons ? ( + + {this.props.submitLabel + ? this.props.submitLabel + : this.props.intl.formatMessage(messages.save)} + + ) : ( + + + + ))} + {onCancel && + (this.props.textButtons ? ( + + {this.props.cancelLabel + ? this.props.cancelLabel + : this.props.intl.formatMessage(messages.cancel)} + + ) : ( + + + + ))} + + )} +
    +
    +
    +
    + ); + } +} + +const FormIntl = injectIntl(Form, { forwardRef: true }); + +export default compose( + connect( + (state, props) => ({ + content: state.content.data, + globalData: state.form?.global, + uiState: state.form?.ui, + metadataFieldsets: state.sidebar?.metadataFieldsets, + metadataFieldFocus: state.sidebar?.metadataFieldFocus, + }), + { + setMetadataFieldsets, + setSidebarTab, + setFormData, + setUIState, + resetMetadataFocus, + }, + null, + { forwardRef: true }, + ), + withSaveAsDraft({ forwardRef: true }), +)(FormIntl); diff --git a/frontend/packages/kitconcept-intranet/src/slots/DocumentByLine/DocumentByLine.tsx b/frontend/packages/kitconcept-intranet/src/slots/DocumentByLine/DocumentByLine.tsx index f1bcd8eb6..65efb3449 100644 --- a/frontend/packages/kitconcept-intranet/src/slots/DocumentByLine/DocumentByLine.tsx +++ b/frontend/packages/kitconcept-intranet/src/slots/DocumentByLine/DocumentByLine.tsx @@ -73,6 +73,10 @@ const DocumentByLine = ({ content, ...props }: DocumentByLineProps) => { }); }, [creators, content]); + if (!content) { + return null; + } + return ( <>
    diff --git a/frontend/packages/kitconcept-intranet/src/theme/_main.scss b/frontend/packages/kitconcept-intranet/src/theme/_main.scss index f4eeceb1f..8b9353ce0 100644 --- a/frontend/packages/kitconcept-intranet/src/theme/_main.scss +++ b/frontend/packages/kitconcept-intranet/src/theme/_main.scss @@ -6,3 +6,4 @@ @import 'components/person'; @import 'components/listingDisclaimer'; @import '_content.scss'; +@import 'reviewSidebar.scss'; diff --git a/frontend/packages/kitconcept-intranet/src/theme/reviewSidebar.scss b/frontend/packages/kitconcept-intranet/src/theme/reviewSidebar.scss new file mode 100644 index 000000000..8cdd1b60e --- /dev/null +++ b/frontend/packages/kitconcept-intranet/src/theme/reviewSidebar.scss @@ -0,0 +1,120 @@ +#sidebar-review { + .delegate-review-buttons, + .postpone-review-buttons { + display: flex; + justify-content: right; + margin-top: 40px; + gap: 10px; + + .postpone-button, + .cancel-button, + .delegate-button { + @include button-style; + } + .cancel-button { + border-color: red; + color: red; + } + } + .postpone-review-form .help { + @include marginal-description(); + color: $grey; + } + + .postpone-form-title, + .delegate-form-title { + padding: 12px 14px; + background: #f3f4f5; + color: #000; + font-size: 12px; + font-weight: 400; + text-transform: uppercase; + } + + .postpone-form-content, + .delegate-form-content { + padding: 1em; + } + + #field-review-comment { + border: none; + border-bottom: 1px solid #c7d5d8; + outline: none; + resize: vertical; + } +} + +.review-menu { + .review-menu-header { + padding: 15px; + background-color: $lightgrey; + color: $grey; + font-size: 18px; + font-weight: 500; + text-transform: capitalize; + } + .review-info-item { + padding: 15px; + background-color: $lightgrey; + } + + .review-info-row { + display: grid; + color: $grey; + column-gap: 15px; + grid-template-columns: 1fr 1fr; + + .review-info-label, + .review-info-value { + margin: 0; + font-size: 12px; + } + + .review-info-value.due_date { + color: red; + } + } +} + +.review-popover { + width: 320px; + border-radius: 0%; + background-color: #fff; + box-shadow: 0 2px 10px rgb(0 0 0 / 25%); + .document-review-dialog { + width: 100%; + outline: none; + } + + .review-menu { + ul { + padding: 0; + margin: 0; + list-style: none; + } + + li { + button { + display: flex; + align-self: stretch; + padding: 15px; + border: none; + background-color: transparent; + color: $black; + cursor: pointer; + font-size: 14px; + font-weight: 400; + text-transform: uppercase; + } + + &:not(:last-child) { + border-bottom: 1px solid #b8c6c8; + } + } + } +} + +.document-review-option:disabled, +.document-review-option[data-disabled] { + opacity: 0.5; +} diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index 704707569..f0667b279 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -17,7 +17,7 @@ catalogs: version: 3.13.1 '@tailwindcss/vite': specifier: ^4.1.4 - version: 4.3.0 + version: 4.3.1 '@testing-library/jest-dom': specifier: ^6.9.1 version: 6.9.1 @@ -74,7 +74,7 @@ catalogs: version: 3.2.2 tailwindcss: specifier: ^4.1.12 - version: 4.3.0 + version: 4.3.1 tsup: specifier: ^8.5.0 version: 8.5.1 @@ -95,7 +95,7 @@ catalogs: version: 5.105.4 webpack-dev-server: specifier: ^5.2.4 - version: 5.2.4 + version: 5.2.5 overrides: '@pmmmwh/react-refresh-webpack-plugin': ^0.5.15 @@ -169,13 +169,13 @@ importers: version: 3.6.0 tailwind-variants: specifier: 'catalog:' - version: 3.2.2(tailwind-merge@3.6.0)(tailwindcss@4.3.0) + version: 3.2.2(tailwind-merge@3.6.0)(tailwindcss@4.3.1) tailwindcss: specifier: 'catalog:' - version: 4.3.0 + version: 4.3.1 tailwindcss-animate: specifier: ^1.0.7 - version: 1.0.7(tailwindcss@4.3.0) + version: 1.0.7(tailwindcss@4.3.1) devDependencies: '@arethetypeswrong/cli': specifier: ^0.16.4 @@ -191,7 +191,7 @@ importers: version: 8.1.0(@svgr/core@8.1.0(typescript@5.9.3))(typescript@5.9.3) '@tailwindcss/vite': specifier: 'catalog:' - version: 4.3.0(vite@6.4.3(@types/node@24.13.1)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0)) + version: 4.3.1(vite@6.4.3(@types/node@24.13.2)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0)) '@testing-library/jest-dom': specifier: 'catalog:' version: 6.9.1 @@ -209,7 +209,7 @@ importers: version: 18.3.7(@types/react@18.3.31) '@vitejs/plugin-react': specifier: 'catalog:' - version: 5.2.0(vite@6.4.3(@types/node@24.13.1)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0)) + version: 5.2.0(vite@6.4.3(@types/node@24.13.2)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0)) '@vitest/coverage-v8': specifier: 'catalog:' version: 3.2.6(vitest@3.2.6) @@ -230,10 +230,10 @@ importers: version: 1.32.0 release-it: specifier: 'catalog:' - version: 20.2.0(@types/node@24.13.1)(magicast@0.3.5) + version: 20.2.0(@types/node@24.13.2)(magicast@0.3.5) tailwindcss-react-aria-components: specifier: ^2.0.1 - version: 2.1.1(tailwindcss@4.3.0) + version: 2.1.1(tailwindcss@4.3.1) tsup: specifier: 'catalog:' version: 8.5.1(jiti@2.7.0)(postcss@8.5.15)(typescript@5.9.3)(yaml@2.9.0) @@ -242,13 +242,13 @@ importers: version: 5.9.3 vite: specifier: 'catalog:' - version: 6.4.3(@types/node@24.13.1)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) + version: 6.4.3(@types/node@24.13.2)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) vite-plugin-svgr: specifier: ^4.3.0 - version: 4.5.0(rollup@4.61.1)(typescript@5.9.3)(vite@6.4.3(@types/node@24.13.1)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0)) + version: 4.5.0(rollup@4.62.0)(typescript@5.9.3)(vite@6.4.3(@types/node@24.13.2)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0)) vitest: specifier: 'catalog:' - version: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.1)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) + version: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.2)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) core/packages/coresandbox: dependencies: @@ -330,7 +330,7 @@ importers: version: 8.1.0 '@types/node': specifier: ^24 - version: 24.13.1 + version: 24.13.2 '@types/react': specifier: ^18 version: 18.3.31 @@ -342,7 +342,7 @@ importers: version: 0.2.6 release-it: specifier: 'catalog:' - version: 20.2.0(@types/node@24.13.1)(magicast@0.3.5) + version: 20.2.0(@types/node@24.13.2)(magicast@0.3.5) tsup: specifier: ^8.3.5 version: 8.5.1(jiti@2.7.0)(postcss@8.5.15)(typescript@5.9.3)(yaml@2.9.0) @@ -351,10 +351,10 @@ importers: version: 5.9.3 vite: specifier: 'catalog:' - version: 6.4.3(@types/node@24.13.1)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) + version: 6.4.3(@types/node@24.13.2)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) vitest: specifier: 'catalog:' - version: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.1)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) + version: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.2)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) core/packages/scripts: dependencies: @@ -406,7 +406,7 @@ importers: devDependencies: release-it: specifier: 'catalog:' - version: 20.2.0(@types/node@24.13.1)(magicast@0.3.5) + version: 20.2.0(@types/node@24.13.2)(magicast@0.3.5) core/packages/types: dependencies: @@ -425,7 +425,7 @@ importers: version: 18.3.7(@types/react@18.3.31) release-it: specifier: 'catalog:' - version: 20.2.0(@types/node@24.13.1)(magicast@0.3.5) + version: 20.2.0(@types/node@24.13.2)(magicast@0.3.5) typescript: specifier: ^5.7.3 version: 5.9.3 @@ -783,7 +783,7 @@ importers: version: 8.6.18(@storybook/test@8.6.15(storybook@8.6.18(prettier@3.2.5)))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(storybook@8.6.18(prettier@3.2.5))(typescript@5.9.3) '@storybook/react-webpack5': specifier: ^8.0.4 - version: 8.6.18(@storybook/test@8.6.15(storybook@8.6.18(prettier@3.2.5)))(esbuild@0.25.12)(lightningcss@1.32.0)(postcss@8.5.15)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(storybook@8.6.18(prettier@3.2.5))(typescript@5.9.3) + version: 8.6.18(@storybook/test@8.6.15(storybook@8.6.18(prettier@3.2.5)))(esbuild@0.25.12)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(storybook@8.6.18(prettier@3.2.5))(typescript@5.9.3) '@storybook/test': specifier: ^8.0.4 version: 8.6.15(storybook@8.6.18(prettier@3.2.5)) @@ -813,7 +813,7 @@ importers: version: 4.17.24 '@types/node': specifier: ^24 - version: 24.13.1 + version: 24.13.2 '@types/react': specifier: ^18 version: 18.3.31 @@ -840,7 +840,7 @@ importers: version: 7.18.0(eslint@8.57.1)(typescript@5.9.3) '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.7.0(vite@6.4.3(@types/node@24.13.1)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0)) + version: 4.7.0(vite@6.4.3(@types/node@24.13.2)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0)) '@vitest/ui': specifier: 'catalog:' version: 3.2.6(vitest@3.2.6) @@ -975,7 +975,7 @@ importers: version: 1.5.4 release-it: specifier: 'catalog:' - version: 20.2.0(@types/node@24.13.1)(magicast@0.3.5) + version: 20.2.0(@types/node@24.13.2)(magicast@0.3.5) resolve-url-loader: specifier: ^5.0.0 version: 5.0.0 @@ -1029,7 +1029,7 @@ importers: version: 1.3.2 vitest: specifier: 'catalog:' - version: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.1)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) + version: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.2)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) wait-on: specifier: 'catalog:' version: 9.0.10(debug@4.3.4) @@ -1041,7 +1041,7 @@ importers: version: 4.10.1 webpack-dev-server: specifier: 'catalog:' - version: 5.2.4(debug@4.3.4)(tslib@2.8.1)(webpack@5.105.4(esbuild@0.25.12)) + version: 5.2.5(debug@4.3.4)(tslib@2.8.1)(webpack@5.105.4(esbuild@0.25.12)) webpack-node-externals: specifier: 3.0.0 version: 3.0.0 @@ -1084,7 +1084,7 @@ importers: devDependencies: release-it: specifier: 'catalog:' - version: 20.2.0(@types/node@24.13.1)(magicast@0.3.5) + version: 20.2.0(@types/node@24.13.2)(magicast@0.3.5) core/packages/volto-razzle: dependencies: @@ -1093,7 +1093,7 @@ importers: version: 7.29.7(@babel/core@7.29.7) '@inquirer/confirm': specifier: ^6.0.12 - version: 6.1.1(@types/node@24.13.1) + version: 6.1.1(@types/node@24.13.2) '@plone/babel-preset-razzle': specifier: workspace:* version: link:../volto-babel-preset-razzle @@ -1102,7 +1102,7 @@ importers: version: link:../volto-razzle-dev-utils '@pmmmwh/react-refresh-webpack-plugin': specifier: ^0.5.15 - version: 0.5.17(react-refresh@0.14.2)(type-fest@4.41.0)(webpack-dev-server@5.2.4(tslib@2.8.1)(webpack@5.105.4(esbuild@0.25.12)))(webpack-hot-middleware@2.26.1)(webpack@5.105.4(esbuild@0.25.12)) + version: 0.5.17(react-refresh@0.14.2)(type-fest@4.41.0)(webpack-dev-server@5.2.5(tslib@2.8.1)(webpack@5.105.4(esbuild@0.25.12)))(webpack-hot-middleware@2.26.1)(webpack@5.105.4(esbuild@0.25.12)) autoprefixer: specifier: ^10.2.3 version: 10.4.8(postcss@8.5.15) @@ -1186,7 +1186,7 @@ importers: version: 0.14.2 release-it: specifier: 'catalog:' - version: 20.2.0(@types/node@24.13.1)(magicast@0.3.5) + version: 20.2.0(@types/node@24.13.2)(magicast@0.3.5) resolve: specifier: ^1.17.0 version: 1.22.12 @@ -1219,7 +1219,7 @@ importers: version: 5.105.4(esbuild@0.25.12) webpack-dev-server: specifier: 'catalog:' - version: 5.2.4(tslib@2.8.1)(webpack@5.105.4(esbuild@0.25.12)) + version: 5.2.5(tslib@2.8.1)(webpack@5.105.4(esbuild@0.25.12)) webpack-manifest-plugin: specifier: ^4.1.1 version: 4.1.1(webpack@5.105.4(esbuild@0.25.12)) @@ -1232,7 +1232,7 @@ importers: version: 28.1.0(@noble/hashes@1.8.0) vitest: specifier: 'catalog:' - version: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.1)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) + version: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.2)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) core/packages/volto-razzle-dev-utils: dependencies: @@ -1262,7 +1262,7 @@ importers: version: 2.2.3 release-it: specifier: 'catalog:' - version: 20.2.0(@types/node@24.13.1)(magicast@0.3.5) + version: 20.2.0(@types/node@24.13.2)(magicast@0.3.5) resolve: specifier: ^1.17.0 version: 1.22.12 @@ -1274,7 +1274,7 @@ importers: version: 5.107.2 webpack-dev-server: specifier: 'catalog:' - version: 5.2.4(tslib@2.8.1)(webpack@5.107.2) + version: 5.2.5(tslib@2.8.1)(webpack@5.107.2) core/packages/volto-slate: dependencies: @@ -1356,7 +1356,7 @@ importers: version: 1.5.4 release-it: specifier: 'catalog:' - version: 20.2.0(@types/node@24.13.1)(magicast@0.3.5) + version: 20.2.0(@types/node@24.13.2)(magicast@0.3.5) packages/kitconcept-core/frontend/packages/kitconcept-core: dependencies: @@ -1396,13 +1396,13 @@ importers: version: 4.17.21 release-it: specifier: ^19.0.5 - version: 19.2.4(@types/node@24.13.1)(magicast@0.3.5) + version: 19.2.4(@types/node@24.13.2)(magicast@0.3.5) typescript: specifier: ^5.7.3 version: 5.9.3 vitest: specifier: ^3.1.2 - version: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.1)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) + version: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.2)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) packages/kitconcept-intranet: dependencies: @@ -1517,13 +1517,13 @@ importers: version: 18.3.7(@types/react@18.3.31) release-it: specifier: ^19.0.5 - version: 19.2.4(@types/node@24.13.1)(magicast@0.3.5) + version: 19.2.4(@types/node@24.13.2)(magicast@0.3.5) typescript: specifier: ^5.7.3 version: 5.9.3 vitest: specifier: ^3.1.2 - version: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.1)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) + version: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.2)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) packages/volto-banner-block/packages/volto-banner-block: dependencies: @@ -1545,7 +1545,7 @@ importers: version: 17.11.0(typescript@5.9.3) vitest: specifier: ^3.2.4 - version: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.1)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) + version: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.2)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) packages/volto-bm3-compat/packages/volto-bm3-compat: dependencies: @@ -1582,7 +1582,7 @@ importers: version: 5.9.3 vitest: specifier: ^3.1.2 - version: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.1)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) + version: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.2)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) packages/volto-button-block/packages/volto-button-block: dependencies: @@ -1622,7 +1622,7 @@ importers: version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) '@types/node': specifier: ^24 - version: 24.13.1 + version: 24.13.2 '@types/react': specifier: ^18 version: 18.3.31 @@ -1631,13 +1631,13 @@ importers: version: 18.3.7(@types/react@18.3.31) release-it: specifier: ^19.0.3 - version: 19.2.4(@types/node@24.13.1)(magicast@0.3.5) + version: 19.2.4(@types/node@24.13.2)(magicast@0.3.5) typescript: specifier: ^5.7.3 version: 5.9.3 vitest: specifier: ^3.2.4 - version: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.1)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) + version: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.2)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) packages/volto-calendar-block/packages/volto-calendar-block: dependencies: @@ -1668,10 +1668,10 @@ importers: version: link:../../../../core/packages/types release-it: specifier: ^19.0.5 - version: 19.2.4(@types/node@24.13.1)(magicast@0.3.5) + version: 19.2.4(@types/node@24.13.2)(magicast@0.3.5) vitest: specifier: ^3.2.4 - version: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.1)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) + version: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.2)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) packages/volto-carousel-block/packages/volto-carousel-block: dependencies: @@ -1708,7 +1708,7 @@ importers: version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) '@types/node': specifier: ^24 - version: 24.13.1 + version: 24.13.2 '@types/react': specifier: ^18 version: 18.3.31 @@ -1717,13 +1717,13 @@ importers: version: 18.3.7(@types/react@18.3.31) release-it: specifier: ^19.0.3 - version: 19.2.4(@types/node@24.13.1)(magicast@0.3.5) + version: 19.2.4(@types/node@24.13.2)(magicast@0.3.5) typescript: specifier: ^5.7.3 version: 5.9.3 vitest: specifier: ^3.1.2 - version: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.1)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) + version: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.2)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) packages/volto-contact-block/frontend/packages/volto-contact-block: dependencies: @@ -1757,13 +1757,13 @@ importers: version: 18.3.7(@types/react@18.3.31) release-it: specifier: ^19.0.5 - version: 19.2.4(@types/node@24.13.1)(magicast@0.3.5) + version: 19.2.4(@types/node@24.13.2)(magicast@0.3.5) typescript: specifier: ^5.7.3 version: 5.9.3 vitest: specifier: ^3.2.4 - version: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.1)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) + version: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.2)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) packages/volto-heading-block/packages/volto-heading-block: dependencies: @@ -1782,7 +1782,7 @@ importers: version: 3.10.6 release-it: specifier: ^19.0.2 - version: 19.2.4(@types/node@24.13.1)(magicast@0.3.5) + version: 19.2.4(@types/node@24.13.2)(magicast@0.3.5) packages/volto-highlight-block/packages/volto-highlight-block: dependencies: @@ -1807,7 +1807,7 @@ importers: version: link:../../../../core/packages/types '@types/node': specifier: ^24 - version: 24.13.1 + version: 24.13.2 '@types/react': specifier: ^18 version: 18.3.31 @@ -1816,13 +1816,13 @@ importers: version: 18.3.7(@types/react@18.3.31) release-it: specifier: ^19.0.5 - version: 19.2.4(@types/node@24.13.1)(magicast@0.3.5) + version: 19.2.4(@types/node@24.13.2)(magicast@0.3.5) typescript: specifier: ^5.7.3 version: 5.9.3 vitest: specifier: ^3.2.4 - version: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.1)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) + version: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.2)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) packages/volto-iframe-block/packages/volto-iframe-block: dependencies: @@ -1854,10 +1854,10 @@ importers: version: 3.10.6 release-it: specifier: ^19.0.5 - version: 19.2.4(@types/node@24.13.1)(magicast@0.3.5) + version: 19.2.4(@types/node@24.13.2)(magicast@0.3.5) vitest: specifier: ^3.2.4 - version: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.1)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) + version: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.2)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) packages/volto-light-theme/frontend/packages/volto-light-theme: dependencies: @@ -1918,7 +1918,7 @@ importers: devDependencies: '@playwright/test': specifier: ^1.60.0 - version: 1.60.0 + version: 1.61.0 '@plone/scripts': specifier: ^3.6.2 version: 3.10.6 @@ -1945,7 +1945,7 @@ importers: version: 4.17.24 '@types/node': specifier: ^22 - version: 22.19.20 + version: 22.19.21 '@types/react': specifier: ^18.3.12 version: 18.3.31 @@ -1954,7 +1954,7 @@ importers: version: 18.3.7(@types/react@18.3.31) playwright: specifier: ^1.60.0 - version: 1.60.0 + version: 1.61.0 react-intl-redux: specifier: 2.3.0 version: 2.3.0(@babel/runtime@7.29.7)(prop-types@15.8.1)(react-intl@3.12.1(@types/react@18.3.31)(react@18.2.0))(react-redux@8.1.2(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(redux@4.2.1))(react@18.2.0) @@ -1963,13 +1963,13 @@ importers: version: 1.5.4 release-it: specifier: ^19.0.3 - version: 19.2.4(@types/node@22.19.20)(magicast@0.3.5) + version: 19.2.4(@types/node@22.19.21)(magicast@0.3.5) typescript: specifier: ^5.7.3 version: 5.9.3 vitest: specifier: ^3.1.2 - version: 3.2.6(@types/debug@4.1.13)(@types/node@22.19.20)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) + version: 3.2.6(@types/debug@4.1.13)(@types/node@22.19.21)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) packages/volto-logos-block/packages/volto-logos-block: dependencies: @@ -2006,7 +2006,7 @@ importers: version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) '@types/node': specifier: ^24 - version: 24.13.1 + version: 24.13.2 '@types/react': specifier: ^18 version: 18.3.31 @@ -2021,13 +2021,13 @@ importers: version: 8.1.2(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(redux@4.2.1) release-it: specifier: ^19.0.3 - version: 19.2.4(@types/node@24.13.1)(magicast@0.3.5) + version: 19.2.4(@types/node@24.13.2)(magicast@0.3.5) typescript: specifier: ^5.7.3 version: 5.9.3 vitest: specifier: ^3.1.2 - version: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.1)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) + version: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.2)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) packages/volto-separator-block/packages/volto-separator-block: dependencies: @@ -2061,7 +2061,7 @@ importers: version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) '@types/node': specifier: ^24 - version: 24.13.1 + version: 24.13.2 '@types/react': specifier: ^18 version: 18.3.31 @@ -2070,13 +2070,13 @@ importers: version: 18.3.7(@types/react@18.3.31) release-it: specifier: ^19.0.3 - version: 19.2.4(@types/node@24.13.1)(magicast@0.3.5) + version: 19.2.4(@types/node@24.13.2)(magicast@0.3.5) typescript: specifier: ^5.7.3 version: 5.9.3 vitest: specifier: ^3.1.2 - version: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.1)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) + version: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.2)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) packages/volto-slider-block/packages/volto-slider-block: dependencies: @@ -2122,7 +2122,7 @@ importers: version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) '@types/node': specifier: ^24 - version: 24.13.1 + version: 24.13.2 '@types/react': specifier: ^18.3.1 version: 18.3.31 @@ -2140,7 +2140,7 @@ importers: version: 5.5.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0) release-it: specifier: ^19.0.5 - version: 19.2.4(@types/node@24.13.1)(magicast@0.3.5) + version: 19.2.4(@types/node@24.13.2)(magicast@0.3.5) typescript: specifier: ^5.7.3 version: 5.9.3 @@ -2149,7 +2149,7 @@ importers: version: 13.0.2 vitest: specifier: ^3.2.4 - version: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.1)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) + version: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.2)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) packages: @@ -2944,8 +2944,8 @@ packages: '@csstools/css-parser-algorithms': ^4.0.0 '@csstools/css-tokenizer': ^4.0.0 - '@csstools/css-color-parser@4.1.1': - resolution: {integrity: sha512-eZ5XOtyhK+mggRafYUWzA0tvaYOFgdY8AkgQiCJF9qNAePnUo/zmsqqYubBBb3sQ8uNUaSKTY9s9klfRaAXL0g==} + '@csstools/css-color-parser@4.1.7': + resolution: {integrity: sha512-CmjJFQTFQx/U/xNJhSjCQ0ilpesPmNQ8+eOUeM/+kDOVW33qsIjeOXc27vrQDdWVkf83ZSWwtg7kXSUvKDJ8cQ==} engines: {node: '>=20.19.0'} peerDependencies: '@csstools/css-parser-algorithms': ^4.0.0 @@ -3487,8 +3487,8 @@ packages: '@hapi/pinpoint@2.0.1': resolution: {integrity: sha512-EKQmr16tM8s16vTT3cA5L0kZZcTMU5DUOZTuvpnY738m+jyP3JIUj+Mm1xc1rsLkGBQ/gVnfKYPwOmPg1tUR4Q==} - '@hapi/tlds@1.1.6': - resolution: {integrity: sha512-xdi7A/4NZokvV0ewovme3aUO5kQhW9pQ2YD1hRqZGhhSi5rBv4usHYidVocXSi9eihYsznZxLtAiEYYUL6VBGw==} + '@hapi/tlds@1.1.7': + resolution: {integrity: sha512-MgNjRwy9Ti92yVAixLmDc8dd1bJIKwO9qlWCfFQRwRmUEDPQHYn4G6hwPFvFGUTzAa0FsS+inMjLin7GnyBRhA==} engines: {node: '>=14.0.0'} '@hapi/topo@6.0.2': @@ -3884,50 +3884,50 @@ packages: peerDependencies: tslib: '2' - '@jsonjoy.com/fs-core@4.57.6': - resolution: {integrity: sha512-uI++Wx6VkBJqVmkb4ZeExwAVpZiA2Do5NrEtXoDk0Pdvce3ytFXJoviT1sLOj16+qDIMnD5nWPfOhVpnDmRJKg==} + '@jsonjoy.com/fs-core@4.57.7': + resolution: {integrity: sha512-GDKuYHjP7vAI1kjBo73V+STKr9XIMZknW/xirpRW/EcShX0IKSev/ALafeRfC8Q331nodrXUFu04PugPB0MAhw==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' - '@jsonjoy.com/fs-fsa@4.57.6': - resolution: {integrity: sha512-pKkw/yC5CzSZKhIIUIsH1przOa+K5jGmZIg1sWaSF24JojyrUFbjcQv7QrcGAudriei6HQ6R0BFj+V8NbQinJw==} + '@jsonjoy.com/fs-fsa@4.57.7': + resolution: {integrity: sha512-1rWsah2nZtRbNeP+c61QcfGfVrJXBmBD0Hm7Akvv4C9MKEasXnbiOS//iH3T3HwUSSBATGrfSp0Xi8nlNhATeQ==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' - '@jsonjoy.com/fs-node-builtins@4.57.6': - resolution: {integrity: sha512-V4DgEFT3Cg5S9fCMOZSCVdTxdJWWLBO0WnAazV7hnCM96u5zXHyW/ubDAfcSVwqjkMJ50W1Y44IXtxRoIwaCVg==} + '@jsonjoy.com/fs-node-builtins@4.57.7': + resolution: {integrity: sha512-LWqfY1m+uAosjwM1RrKhMkUnP9jcq1RUczHsNO779ovm1E9v8I/pmj04eBAcoBjhC7ltcPbNFGyRJ5JqSJ7Jdg==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' - '@jsonjoy.com/fs-node-to-fsa@4.57.6': - resolution: {integrity: sha512-+JptNw3iifihxH2rEXrninDzX4FFVW8JD/wPR8GbJPAeL9CQUSblrlumOPB5gZuS7tYRX+PJPLtT7XzKoRhv/Q==} + '@jsonjoy.com/fs-node-to-fsa@4.57.7': + resolution: {integrity: sha512-9T0zC9LKcAWXDoTLRdLMoJ0seOvJ5bgDKq1tSBoQAFQpPDstQUeV1Oe7PLypdu7F2D3ddRstmwgeNUEN/VaZ4Q==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' - '@jsonjoy.com/fs-node-utils@4.57.6': - resolution: {integrity: sha512-foyUrfS7WmYEUzqYXSNxmJBcSj04TABrkpFabwO9SCDCpVCfJ+qG+2sk5FjfiflG2n0SDFZDCJ6vYlJAEpxJFg==} + '@jsonjoy.com/fs-node-utils@4.57.7': + resolution: {integrity: sha512-jjWSDOsfcog2cZnUCwX5AHmlIq6b6wx5Pz/2LAcNjJ62Rajwg89Fy7ubN+lDHew0/1reLDa9Z5urybYadhh37g==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' - '@jsonjoy.com/fs-node@4.57.6': - resolution: {integrity: sha512-Kbn1jdkvDN4F2+BhoB6mMu7NCbhP0bgA5NcI1aJj/Q5UcU+I1JLLW+dEQean33iV4tXv35AzBVKPICnDltBpxw==} + '@jsonjoy.com/fs-node@4.57.7': + resolution: {integrity: sha512-xhnyeyEVTiIOibFvda/5n89nChMLCPKHHM2WQ+GGDf6+U/IrQBW3Qx6x+Uq1bkDbxBkybLOdIGoBtVBrE8Nngg==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' - '@jsonjoy.com/fs-print@4.57.6': - resolution: {integrity: sha512-96eAn4Dudtt67LTeuU47yUD+pg9/G/oKpI10zei9ljk3X3WK4lYKc+n3cpaPCAbKPzoyfxl0mXm8f8Y7BOSFXw==} + '@jsonjoy.com/fs-print@4.57.7': + resolution: {integrity: sha512-mFM4P4Gjq0QQHkLnXzPYPEMFrAoe6a5Myedgb6+CmL+nGd3MKvTxYPuD7N1dLIH9RBy1fLdzxd80qvuK8xrx3Q==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' - '@jsonjoy.com/fs-snapshot@4.57.6': - resolution: {integrity: sha512-V57CMzbOgTzUWGOWQ8GzHQdpJP6JnrYVNCtTBNxVYEnlVRvo4uEJqHhtAT8vhDFrIuJOXLrTL1Fki4h5oI7xxg==} + '@jsonjoy.com/fs-snapshot@4.57.7': + resolution: {integrity: sha512-1GS3+plfm2giB3PqokiqyydyqYTPLcCQIKSkp0TdMNRh3KVk7rqRM6U785FLlVRG7XLmkc0KWr215OY+22K3QA==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' @@ -4170,35 +4170,35 @@ packages: '@paralleldrive/cuid2@2.3.1': resolution: {integrity: sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==} - '@peculiar/asn1-cms@2.7.0': - resolution: {integrity: sha512-hew63shtzzvBcSHbhm+cyAmKe6AIfinT9hzEqSPjDC6opTTMKmTkQ0gHuN2KsWlvqiKw1S/fS94fhag/FJkioQ==} + '@peculiar/asn1-cms@2.8.0': + resolution: {integrity: sha512-NgekZOrSJFSBFLFoLfwePguAWAx7z1+f2TEsWFUMyiqqfntZ4+S/S5hzqME3q4pCA0iOsFKdwiQ35dwY24eVqA==} - '@peculiar/asn1-csr@2.7.0': - resolution: {integrity: sha512-VVsAyGqErT9D1SY4aEqozThXMVI+ssVRiv2DDeYuvpBKLIgZ3hYs3Ay3u/VSoKq6ESFi9cf6rf3IOOzfwh7oMA==} + '@peculiar/asn1-csr@2.8.0': + resolution: {integrity: sha512-akbF8+uvleHs8sejNPQxwmVFuInAg6FMNHOwMILXfP518YfFJwdR3jr6oNUPOaEJfuEhn/vkNOCIT6ASUd4mbg==} - '@peculiar/asn1-ecc@2.7.0': - resolution: {integrity: sha512-n7KEs/Q/wrB415cxy4fHOBhegp4NdJ15fkJPwcB/3/8iNBQC2L/N7SChJPKDJPZGYH0jD4Tg4/0vnHmwghnbKw==} + '@peculiar/asn1-ecc@2.8.0': + resolution: {integrity: sha512-ohwlk+u9Rv2NOAY1c6MfHj45ATVF8R1DUN/WCgABiRtLi2ZftlZWZX7KvpAbU8v9xPcmoILfELeEABj/rn18AQ==} - '@peculiar/asn1-pfx@2.7.0': - resolution: {integrity: sha512-V/nrlQVmhg7lYAsM7E13UDL5erAwFv6kCIVFqNaMIHSVi7dngcT839JkRTkQBqznMG98l2XjxYk74ZztAohZzA==} + '@peculiar/asn1-pfx@2.8.0': + resolution: {integrity: sha512-5yof1ytoB++RQtaFbqSUJ8pxDJtZT6vbVqZ8XoJ61ph7UjNVvfFwAilnCodqkNsAodpy13gDhoxZXw00pghnyg==} - '@peculiar/asn1-pkcs8@2.7.0': - resolution: {integrity: sha512-9GTl1nE8Mx1kTZ+7QyYatDyKsm34QcWRBFkY1iPvWC3X4Dona5s/tlLiQsx5WzVdZqiMBZNYT0buyw4/vbhnjw==} + '@peculiar/asn1-pkcs8@2.8.0': + resolution: {integrity: sha512-qAKXtLpBEw9LqhKpjw3ajZSXlBur+ipW+y2ivVBQAG6F6qRx94yO+1ZR4mvw+YaCfKSaOzLeYEzsPaBp4SJELA==} - '@peculiar/asn1-pkcs9@2.7.0': - resolution: {integrity: sha512-Bh7m+OuIaSEllPQcSd9OSp93F4ROWH7sbITWV8MI+8dwsjE5111/87VxiWVvYFKyww3vp39geLv9ENqhwWHcew==} + '@peculiar/asn1-pkcs9@2.8.0': + resolution: {integrity: sha512-b5nDWCnkV60+cQ141D6sVVwK9nz64R5n3zSVnklGd+ECdkW2Ol3U1a6yYFlalpSOaD557yuJB64A+q42jG7lUQ==} - '@peculiar/asn1-rsa@2.7.0': - resolution: {integrity: sha512-/qvENQrXyTZURjMqSeofHul0JJt2sNSzSwk36pl2olkHbaioMQgrASDZAlHXl0xUlnVbHj0uGgOrBMTb5x2aJQ==} + '@peculiar/asn1-rsa@2.8.0': + resolution: {integrity: sha512-zHEUlCqB2mk7x2lxDwHHJy7hWZOPdGHVlsmITWKB5/PbQo61atbu9PJ/0r9dQNMwFzbKPXZ8uK8/91eUhRznSg==} - '@peculiar/asn1-schema@2.7.0': - resolution: {integrity: sha512-W8ZfWzLmQnrcky+eh3tni4IozMdqBDiHWU0N+vve/UGjMaUs8c0L7A2oEdkBXS8rTpWDpK/aoI3DG/L/hxmxPg==} + '@peculiar/asn1-schema@2.8.0': + resolution: {integrity: sha512-7YT0U/ze0tF2QOBbE15gKZwy5tvgGyLRiRHLzhlbOpf7BT032oBSd0haZqXn5W6l26WLlu3dyxzjM+2638/z2Q==} - '@peculiar/asn1-x509-attr@2.7.0': - resolution: {integrity: sha512-NS8e7SOgXipkzUPLF/sce7ukpMpWjhxYsH0n6Y+bHYo4TTxOb95Zv7hqwSuL212mj5YxovjdOKQOgH1As3E94w==} + '@peculiar/asn1-x509-attr@2.8.0': + resolution: {integrity: sha512-tHjkfS/qhMnmrlB2J9NhflQlQ7In3khO3CfmVrriOlpTeErY9ZIKOso1hQ5JQiyrJ7ShvqVPk7E5fQmbclkSKA==} - '@peculiar/asn1-x509@2.7.0': - resolution: {integrity: sha512-mUn9RRrkGDnG4ALfunDmzyRW5dg+sWCj/pfnCCqEHYbkGxEpvUt6iVJv8Yw1cyp6SWZ26ZE5oSmI5SqEaen15g==} + '@peculiar/asn1-x509@2.8.0': + resolution: {integrity: sha512-N0CMuhWUzsWEVq6F1q9X6+VKUnWzSW+cSVg+aPaGGwDdbFoFWTYgin5MHwXgpWd6y9COMBxnfy/Qc+Xc7F0Zwg==} '@peculiar/utils@2.0.3': resolution: {integrity: sha512-+oL3HPFRIZ1St2K50lWCXiioIgSoxzz7R1J3uF6neO2yl1sgmpgY6XXJH4BdpoDkMWznQTeYF6oWNDZLCdQ4eQ==} @@ -4219,8 +4219,8 @@ packages: resolution: {integrity: sha512-SEeaJLb3qBNF/OaXnaR1NmmBbFYk1zC0ZH/52fATcRPLFg/p791YrcyFFy44Bo9sLaGuSuLp5Q6axbb/O+v/RA==} engines: {node: ^14.18.0 || >=16.0.0} - '@playwright/test@1.60.0': - resolution: {integrity: sha512-O71yZIbAh/PxDMNGns37GHBIfrVkEVyn+AXyIa5dOTfb4/xNvRWV+Vv/NMbNCtODB/pO7vLlF2OTmMVLhmr7Ag==} + '@playwright/test@1.61.0': + resolution: {integrity: sha512-cKA5B6lpFEMyMGjxF54QihfYpB4FkEGH+qZhtArDEG+wezQAJY8Pq6C7T1SjWz+FFzt3TbyoXBQYk/0292TdJA==} engines: {node: '>=18'} hasBin: true @@ -4313,8 +4313,8 @@ packages: resolution: {integrity: sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==} engines: {node: '>=12.22.0'} - '@pnpm/npm-conf@3.0.2': - resolution: {integrity: sha512-h104Kh26rR8tm+a3Qkc5S4VLYint3FE48as7+/5oCEcKR2idC/pF1G6AhIXKI+eHPJa/3J9i5z0Al47IeGHPkA==} + '@pnpm/npm-conf@3.0.3': + resolution: {integrity: sha512-//0sR/cow/s4ICQaYoAobOl4aU8cjU6x/V24V7XkKotb9+O+3zySIYp146vpaobYHnxa4pZX8NkV54Z5AwbDKA==} engines: {node: '>=12'} '@polka/url@1.0.0-next.29': @@ -4360,128 +4360,128 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.61.1': - resolution: {integrity: sha512-JnBB8MdXj45cajvTuO5FmPlvFVJRQgvrz1uSEl3NwqFnReAPGwb8EanbGi4z2nRaqLzjJSv5/JmycoTKlRZxHA==} + '@rollup/rollup-android-arm-eabi@4.62.0': + resolution: {integrity: sha512-IPIQ55ythEHkfEd9jMEi32OQ7SxURsGA43JI22lj01OLZNt2NUbJX8YUHxkVWyQ6daHPNn0truF5nSj3DQp6YQ==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.61.1': - resolution: {integrity: sha512-Jx2g7iSjw4AOT0HDPHM9RV3GNjRXwybWtSFZiZAYUTjUwjVrYIwq3kBf+LnhqJlzXFAqTAh2F7IGI+O568exPw==} + '@rollup/rollup-android-arm64@4.62.0': + resolution: {integrity: sha512-M6s9cr10MibETyo8JsOkq+Lo1+lU6hcvb1MApnUql5qte/5hMEgzlN8/ReIKNfRV8rrqX50W1BX9zoUhC192RA==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.61.1': - resolution: {integrity: sha512-0F1L/Z3Eqv8mT2n3dCpeO8GcTvHvVqkP5/t6DMsn0KzhYVcg+s7Ncl5DS8qjKYEeio6Az0Gt6nyBORay5qIlCA==} + '@rollup/rollup-darwin-arm64@4.62.0': + resolution: {integrity: sha512-BqCoMoIbn0keKys+dEAdBa70EtOwV1bEsQCUgU9FdiZmmMge/Zk7LlkYGqbrdHR+Frnt0E1FOanly+rlwvvQzw==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.61.1': - resolution: {integrity: sha512-qLttcH871ujY4YcVfUSShhOw+CsoTatYz8gRbHO7Bb92QH059/P0y5do1KMs41fY0BpD2x4AJH/gID0zFiqVKQ==} + '@rollup/rollup-darwin-x64@4.62.0': + resolution: {integrity: sha512-SIMzST3VFNXDAbeIWDWiFCNM5qncUBDWaEV7NfE7oZbDt2mgfW4MvbKdbYiGOLoM32gbTv608UMd0XktEYSD7w==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.61.1': - resolution: {integrity: sha512-fUI4RapGE0Oh3mb8mgfvC1O2nU1RpDZUKnDQm3xB1Ipg7C2wTs5Kstz7G2uWK99a8S2yTMq8/P4uycwNa0nJyw==} + '@rollup/rollup-freebsd-arm64@4.62.0': + resolution: {integrity: sha512-ezjfSQMP7ArdUsbBwbQIfwAlhE84I2iVnzQNCFSveqV42q+BmKlzVpf7mxv5EchLcoWU4y6/heFzVg1F+hodUQ==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.61.1': - resolution: {integrity: sha512-H5YrdvJaDtI/U9/emrD4b++xkvp3y/JvOe4rizHbxvkyMfRS/CiRYdji+Pl8D0brEaNFWUh1drQxgAGIl6Xudw==} + '@rollup/rollup-freebsd-x64@4.62.0': + resolution: {integrity: sha512-9+qTWGW9AZRhnUgwtTwzNwcPlL87ngkeN0LA+q1bADvmY9aNvWaF2TFW8BZgnQPYxpDI7+rMVLivcd4V737TAQ==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.61.1': - resolution: {integrity: sha512-Q8CBCCQtDFrYtXoeUXSrnFXKOnyUhx6bz+SkL6A0E7V8kAiCJ5pamq1WtbfpVGhR5TSpXY6ak3avmDc5fHTyJA==} + '@rollup/rollup-linux-arm-gnueabihf@4.62.0': + resolution: {integrity: sha512-T1dMEQhXA/jkJ/jyMIw9IovK8bSUq7A8kLIlvZTb/6YIVsp2zLavr4F3oyllHWo7eIVJRyE5n3tUjQJEbE1IuQ==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.61.1': - resolution: {integrity: sha512-nwnhk1581l0FBVellGcVCAT0Oi06onEA3WB53sf01VO3I0UPBkMH9sXONYME2K0ovXcNayJfNtHfm6mpJElatQ==} + '@rollup/rollup-linux-arm-musleabihf@4.62.0': + resolution: {integrity: sha512-2as0LgT7qQpyceQq6VUJYnumUMUrgGQCWIiDIN9DE0/tglsk6o66uCB4f3djRawAltvfCNLyZZrsqbPA6inCsA==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.61.1': - resolution: {integrity: sha512-x5Xr49hwt3hdW75UOZm3395YwwzPyauktslv29KpWL/T+vVAzoT3azLcTWv0eMciBNrx+DYjH4paehHoLpPvpg==} + '@rollup/rollup-linux-arm64-gnu@4.62.0': + resolution: {integrity: sha512-bVURMg+6eNN9C/yc0aVjooZcwTTtYF4YW3xta5pP0//r3o1V8gXEHXWCndj47w/HhwsFroZrFhR+6uQP5T0n0g==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.61.1': - resolution: {integrity: sha512-unMS3H73DpaoPyyEVPjGKleM/s0mkmsauTENpw4INQY8y4+IuLNjkueQ5QCtC0D3N38Y38yhAU8OoZ20S2Tm6w==} + '@rollup/rollup-linux-arm64-musl@4.62.0': + resolution: {integrity: sha512-Ful8pM/2yYI83PViWdFdpZhdI8HJ5qsXANe5atypbHDf+KIBBDsZsbyy8hbXnULVvW9NsTh5DHwbcBftyLTfiw==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-loong64-gnu@4.61.1': - resolution: {integrity: sha512-zNZzGRnAhwjFEYmvphJRV5XaQGjs62cCmeYYHUT//NbvEnHauw+I85nGG+SiVg5ld4GX8D1IbKIX+ozITQnhMQ==} + '@rollup/rollup-linux-loong64-gnu@4.62.0': + resolution: {integrity: sha512-9Gp/DgrkzfUBmNPVTyPTvay+4xEP7M/clXpj3efXBcm6uTIVIgDg4rqUpqKXvLEuFRVuEpSAOkhgNeecvaZ4Cg==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-loong64-musl@4.61.1': - resolution: {integrity: sha512-LdpWGL8X209B2SIvWjqlc8VZgM6PKfontSerGepuldQmHYrAOtnMCXeJkxXGbC+PPZVOuu5czJo7fNV6aeW8rQ==} + '@rollup/rollup-linux-loong64-musl@4.62.0': + resolution: {integrity: sha512-m9tsJz54LUXkSYM8+8PG81B9IKK5r+2T0clMq4QrS16xFosufU7firBDAZEsDheDs7wTlP7h3++S7lMsU955HA==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-ppc64-gnu@4.61.1': - resolution: {integrity: sha512-EC5kTtNaNGOmbMGqar8dvJy6y/hg99GAwjfBz++pxZhQATXGcRjd6c5en5wcbru0vkRmiMGsQKdMJOOf6sza4g==} + '@rollup/rollup-linux-ppc64-gnu@4.62.0': + resolution: {integrity: sha512-3UvJ5PNVU16aJf6M3tFI24pWzAl2/ynfbyRN3ICyQajK1lSkrnVYNnLz3v04J32qKa0FczJc22zeToc0lr2A3w==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-ppc64-musl@4.61.1': - resolution: {integrity: sha512-8hiwp6D4acEcNK78I4rP0/XtS1sknWIAMJBPdR4l6zUtyTm5KiTDr5bXmWt4foY7nAN7AThDHgkLIEZOWKbzWw==} + '@rollup/rollup-linux-ppc64-musl@4.62.0': + resolution: {integrity: sha512-vRWUAbYLGHBZS6Q8Msb2sfnf1fvJf+47t8l/TwOerM2qArzy+IeNMTHrYLHXh95h8MoatPHI5hhSZNs+mGXKPg==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.61.1': - resolution: {integrity: sha512-10dh/h/BqA7DuMPWSxkR8uks18FRwnwOEqr5zOTEl+NOwP/OMzKX8OFR/Of9xxDA7D5qef1Nzar5WDD2kCCr1g==} + '@rollup/rollup-linux-riscv64-gnu@4.62.0': + resolution: {integrity: sha512-c00T5SYENHAt86cfW47URaP3Us5vLC/4QO7GYud1G5VNRffCwwCuBspwqYrriuJB+5m0WFzClCn9wed0FBjKvg==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-riscv64-musl@4.61.1': - resolution: {integrity: sha512-YKJ5lg35DP17gcAOggnihe+APw9HLyj1Xn7gsmGumBJAUDa6NGXNixJzmkWLhcK9TOuuyQjdamzvJefkO7qHZQ==} + '@rollup/rollup-linux-riscv64-musl@4.62.0': + resolution: {integrity: sha512-krrCDilhXOwFkSkO3Wm9I/f9H0L92XHHwy2fwxjukxIbh0dem8gZqOW5Y8BsHrpJv5qwlRBV+Wl4ZFyRWhUpwg==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.61.1': - resolution: {integrity: sha512-Mlil5G2Jj6a7B3LWGctg+XPL9vdXYuzCtNXfxOQ0nPjc2m6ueUktocPGH9bnAM0bNRKb/bAWTujUU7IJQdQA+g==} + '@rollup/rollup-linux-s390x-gnu@4.62.0': + resolution: {integrity: sha512-7pfYFSTc4/rUC/FtAI0Qp6QthDBCIi6/AuP1xYqFk5vanI6KnL5dWKP60OM/05LOsbwTmIcvr6eXC4CJuJ75IA==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.61.1': - resolution: {integrity: sha512-bVWIOIk6pV01p4CdUbPP7CJ/434z+OooYjDuFcR+44N35YvKUC66G8MGnvcWx5mWKW3g61J+t74l3Kj15Kwn2Q==} + '@rollup/rollup-linux-x64-gnu@4.62.0': + resolution: {integrity: sha512-7SDIalKeIpG0Ifogbbdn58HmSotYMlf23K3dCJEmiVd9Fg36Vmni82iPQec27N3wY4Bvbxftkxz6vSx9OcouTg==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.61.1': - resolution: {integrity: sha512-qy5pBvZbqNFheBz61R1rzsezjm0J7O2oNGoWtGoY89SZYLUfxAJTBAqDChqAIdB4rCiIbi9nF7yZ83GnNiLwSw==} + '@rollup/rollup-linux-x64-musl@4.62.0': + resolution: {integrity: sha512-eRZevouTH2i1HeAVLqJuLnt256krQkGY0TN6WsTmsIhuzbh457HuWDMakKwmi0Cjadux983CoSr8Lim2QhUIFw==} cpu: [x64] os: [linux] - '@rollup/rollup-openbsd-x64@4.61.1': - resolution: {integrity: sha512-E83TXjI4zm0+5f2qO+UOudaCYIhYwpJ5jq6YCZNIZ+6CbfhKrkAGezeiASBL9ElxAxFsRS9ZhESv8mfnj6TKeg==} + '@rollup/rollup-openbsd-x64@4.62.0': + resolution: {integrity: sha512-3oVS7FLGa4U1qcvao9ylGxrjXZyUQqR8UwxEcnUEyPX53O/C/mKDZegNXTdHCP+h3e6ta/f1EN38Yif1mmZHYg==} cpu: [x64] os: [openbsd] - '@rollup/rollup-openharmony-arm64@4.61.1': - resolution: {integrity: sha512-fbWnKqVkjrJN38vNe3ahkbk6iejS/3b0Nt7EEtPpE6RBacZcGXNKbzfHN3GUUlXOPghUg0j6XUGrtjX9z1sIvA==} + '@rollup/rollup-openharmony-arm64@4.62.0': + resolution: {integrity: sha512-yTB9TgfWj5wHe5QgktAgXTLLot1gvEjl1NiPPAUiCs4oPrIWFl5V4nC3GrkNdj9LaAU4s94nVrGbGOCqUpyWsg==} cpu: [arm64] os: [openharmony] - '@rollup/rollup-win32-arm64-msvc@4.61.1': - resolution: {integrity: sha512-ArMl38iVAbk0New1ogihQNY6iphLi4ZaRsa037gUzv5yeKPY8TD3Dmy4x2RNC1VztU/uqm+G+/RwFrSka3Oy2g==} + '@rollup/rollup-win32-arm64-msvc@4.62.0': + resolution: {integrity: sha512-5LOhoaesY3doG1c+ac/2JtgREpKoJr5bUHH8tKY0V8di7+uSV6BwLs2PlR0/yzefGOkR+wE7ZolZphHCsyG5Rw==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.61.1': - resolution: {integrity: sha512-0mYtjHS9ucAbcATycCNK9IGBk/cCe/ma7EmSLGZdsxnOA8cjRIyU04wDpVAD9NiOfLUR9KTxdiO53uOkherqjQ==} + '@rollup/rollup-win32-ia32-msvc@4.62.0': + resolution: {integrity: sha512-yYkWHhmbhRTWTnWos5HC4GcPQfjlzzCNbM9e/+GXrLuaBXYA3qSDR9f0Vgufd5S8yX81U8jPKp7ZnAjZFMtRnw==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-gnu@4.61.1': - resolution: {integrity: sha512-gK1iCEPfpoSG9wfBihXxvBMi8ZfcWffYkEsC/Eih+iFENTaewvNcrEQ69lIOWYO5pePHKLHHO7nq5AILGO/HQQ==} + '@rollup/rollup-win32-x64-gnu@4.62.0': + resolution: {integrity: sha512-SoTb6lPg25xZlA2ibwQ++ahCCnH+FP0qmEuafMJ4gznZKOlXioKEAeJLgCrqjM98ACziXM9V1amFjICVL4IFoA==} cpu: [x64] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.61.1': - resolution: {integrity: sha512-X+zaP2x+j4RXGfbp/seSoRHWnPxzApilDszisZxbYH5C/jTxFhCtDNdPGZb9lJyYPs24wGxruPF7Y+sIXt9Gzw==} + '@rollup/rollup-win32-x64-msvc@4.62.0': + resolution: {integrity: sha512-5L+T1fMX4RIEBoZzT0+sQ0PhTS36NULFmMXtl1TZo44TMAROIMHbZufSOjVWt/Y622BtxgxtaNOokbTDvfsrZA==} cpu: [x64] os: [win32] @@ -4865,65 +4865,65 @@ packages: '@swc/helpers@0.5.23': resolution: {integrity: sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==} - '@tailwindcss/node@4.3.0': - resolution: {integrity: sha512-aFb4gUhFOgdh9AXo4IzBEOzBkkAxm9VigwDJnMIYv3lcfXCJVesNfbEaBl4BNgVRyid92AmdviqwBUBRKSeY3g==} + '@tailwindcss/node@4.3.1': + resolution: {integrity: sha512-6NDaqRoAMSXD1mr/RXu0HBvNE9a2n5tHPsxu9XHLws8o4Twes5rBM2205SUUiJ9goAtadrN6xTGX0UDEwp/N4A==} - '@tailwindcss/oxide-android-arm64@4.3.0': - resolution: {integrity: sha512-TJPiq67tKlLuObP6RkwvVGDoxCMBVtDgKkLfa/uyj7/FyxvQwHS+UOnVrXXgbEsfUaMgiVvC4KbJnRr26ho4Ng==} + '@tailwindcss/oxide-android-arm64@4.3.1': + resolution: {integrity: sha512-SVlyf61g374l5cHyg8x9kf5xmLcOaxvOTsbsqDnSsDJaKOEFZ7GCvi84VAVGpxojYOs1+3K6M0UjXfqPU8vmOQ==} engines: {node: '>= 20'} cpu: [arm64] os: [android] - '@tailwindcss/oxide-darwin-arm64@4.3.0': - resolution: {integrity: sha512-oMN/WZRb+SO37BmUElEgeEWuU8E/HXRkiODxJxLe1UTHVXLrdVSgfaJV7pSlhRGMSOiXLuxTIjfsF3wYvz8cgQ==} + '@tailwindcss/oxide-darwin-arm64@4.3.1': + resolution: {integrity: sha512-hVnWLwv+e/l7c4WKyVtHVrIPvYdqWHjRB3MDIqARynzFtnQg85kmQEFCbV9Ja0VVx4xXTIiDWY60Y7iz/iNoDA==} engines: {node: '>= 20'} cpu: [arm64] os: [darwin] - '@tailwindcss/oxide-darwin-x64@4.3.0': - resolution: {integrity: sha512-N6CUmu4a6bKVADfw77p+iw6Yd9Q3OBhe0veaDX+QazfuVYlQsHfDgxBrsjQ/IW+zywL8mTrNd0SdJT/zgtvMdA==} + '@tailwindcss/oxide-darwin-x64@4.3.1': + resolution: {integrity: sha512-Cf7abu0WVgbhU7ANgPUnSAvm7nCvMweusHb8FnaHlLfv/Caq4GYaEZg7ZImzzmjx4lIAfuS8q+eLIS7A7IzxIg==} engines: {node: '>= 20'} cpu: [x64] os: [darwin] - '@tailwindcss/oxide-freebsd-x64@4.3.0': - resolution: {integrity: sha512-zDL5hBkQdH5C6MpqbK3gQAgP80tsMwSI26vjOzjJtNCMUo0lFgOItzHKBIupOZNQxt3ouPH7RPhvNhiTfCe5CQ==} + '@tailwindcss/oxide-freebsd-x64@4.3.1': + resolution: {integrity: sha512-ZZqzX2Y+GXtXXfqSfpJhDm60OoZfvLHLCgm+J7NVqgHHJjG/m9ugZI77RwTsVd4fnBJuCFP6Ae6kTJb71UdS8g==} engines: {node: '>= 20'} cpu: [x64] os: [freebsd] - '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.0': - resolution: {integrity: sha512-R06HdNi7A7OEoMsf6d4tjZ71RCWnZQPHj2mnotSFURjNLdBC+cIgXQ7l81CqeoiQftjf6OOblxXMInMgN2VzMA==} + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.1': + resolution: {integrity: sha512-/Ah/xik0LaMYfv9DZ0S/t4pBlBNYOcqtRwusjgovHkvT8ixueWCLyJjsaF5kQIckjb4IT8Q6K6p/iPmZMixYgg==} engines: {node: '>= 20'} cpu: [arm] os: [linux] - '@tailwindcss/oxide-linux-arm64-gnu@4.3.0': - resolution: {integrity: sha512-qTJHELX8jetjhRQHCLilkVLmybpzNQAtaI/gaoVoidn/ufbNDbAo8KlK2J+yPoc8wQxvDxCmh/5lr8nC1+lTbg==} + '@tailwindcss/oxide-linux-arm64-gnu@4.3.1': + resolution: {integrity: sha512-gqdFoVJlw444GvpnheZLHmvTzSxI/cOUUh2KSNejQjTcYkW062SVD+En0rUgD+QV91bz1XGIGtt1HJd48xUGbQ==} engines: {node: '>= 20'} cpu: [arm64] os: [linux] - '@tailwindcss/oxide-linux-arm64-musl@4.3.0': - resolution: {integrity: sha512-Z6sukiQsngnWO+l39X4pPbiWT81IC+PLKF+PHxIlyZbGNb9MODfYlXEVlFvej5BOZInWX01kVyzeLvHsXhfczQ==} + '@tailwindcss/oxide-linux-arm64-musl@4.3.1': + resolution: {integrity: sha512-Bwv9KwOvE0VKa86xPFif9b9c3Y1NxOV1P0gLti/IYaWEsQYZXDlxfGEtA8mdDZ7SG3wyNXAWYT5SIn3giL57oA==} engines: {node: '>= 20'} cpu: [arm64] os: [linux] - '@tailwindcss/oxide-linux-x64-gnu@4.3.0': - resolution: {integrity: sha512-DRNdQRpSGzRGfARVuVkxvM8Q12nh19l4BF/G7zGA1oe+9wcC6saFBHTISrpIcKzhiXtSrlSrluCfvMuledoCTQ==} + '@tailwindcss/oxide-linux-x64-gnu@4.3.1': + resolution: {integrity: sha512-Ymi8O8T15HYQdOUWUtTI6ldN0neHP85FC+Qz32xTcZ7iJXtem/x8ITev0o1e9e5rkqj4lONZfTRLvkmin1+tKg==} engines: {node: '>= 20'} cpu: [x64] os: [linux] - '@tailwindcss/oxide-linux-x64-musl@4.3.0': - resolution: {integrity: sha512-Z0IADbDo8bh6I7h2IQMx601AdXBLfFpEdUotft86evd/8ZPflZe9COPO8Q1vw+pfLWIUo9zN/JGZvwuAJqduqg==} + '@tailwindcss/oxide-linux-x64-musl@4.3.1': + resolution: {integrity: sha512-M+P/91qJ6uILLw4k2G93GMDRAXj61SMvFQYt39AqvUqYgExXpLL5aepfns7sj4HiAQeolirQF9E0lzRvdf4zPQ==} engines: {node: '>= 20'} cpu: [x64] os: [linux] - '@tailwindcss/oxide-wasm32-wasi@4.3.0': - resolution: {integrity: sha512-HNZGOUxEmElksYR7S6sC5jTeNGpobAsy9u7Gu0AskJ8/20FR9GqebUyB+HBcU/ax6BHuiuJi+Oda4B+YX6H1yA==} + '@tailwindcss/oxide-wasm32-wasi@4.3.1': + resolution: {integrity: sha512-zsM8uOeqvVGHsAXsJxsT28ttosFahLJKCLOTUBqRAtKnVgGSRitds9T432QiT8b77Yga7JIBkulIRRlJPtYhRA==} engines: {node: '>=14.0.0'} cpu: [wasm32] bundledDependencies: @@ -4934,24 +4934,24 @@ packages: - '@emnapi/wasi-threads' - tslib - '@tailwindcss/oxide-win32-arm64-msvc@4.3.0': - resolution: {integrity: sha512-Pe+RPVTi1T+qymuuRpcdvwSVZjnll/f7n8gBxMMh3xLTctMDKqpdfGimbMyioqtLhUYZxdJ9wGNhV7MKHvgZsQ==} + '@tailwindcss/oxide-win32-arm64-msvc@4.3.1': + resolution: {integrity: sha512-aiNvSq9BsVk8V513lDKlrCFAgf8qBMPZTpgEhInL+NwQqs97mYmupVMrPrgBBSL8Pv/0zXu9MrMF9rMun1ZeNg==} engines: {node: '>= 20'} cpu: [arm64] os: [win32] - '@tailwindcss/oxide-win32-x64-msvc@4.3.0': - resolution: {integrity: sha512-Mvrf2kXW/yeW/OTezZlCGOirXRcUuLIBx/5Y12BaPM7wJoryG6dfS/NJL8aBPqtTEx/Vm4T4vKzFUcKDT+TKUA==} + '@tailwindcss/oxide-win32-x64-msvc@4.3.1': + resolution: {integrity: sha512-xDEyu1rg290472FEGaKHnzyDyh5QH+AlWvsU5hMoMtPpzmKlRI0jaYKCgSHDYtaQWZOYbMaduSyCwFwY4n1HmA==} engines: {node: '>= 20'} cpu: [x64] os: [win32] - '@tailwindcss/oxide@4.3.0': - resolution: {integrity: sha512-F7HZGBeN9I0/AuuJS5PwcD8xayx5ri5GhjYUDBEVYUkexyA/giwbDNjRVrxSezE3T250OU2K/wp/ltWx3UOefg==} + '@tailwindcss/oxide@4.3.1': + resolution: {integrity: sha512-yVPyo8RNkabVr3O2EhHEE0Rewu7YKzc1DhIqfL46LKveFrmu9XbDazNOJY7/GRuvw1h6u3utWnR29H/p5JPlgA==} engines: {node: '>= 20'} - '@tailwindcss/vite@4.3.0': - resolution: {integrity: sha512-t6J3OrB5Fc0ExuhohouH0fWUGMYL6PTLhW+E7zIk/pdbnJARZDCwjBznFnkh5ynRnIRSI4YjtTH0t6USjJISrw==} + '@tailwindcss/vite@4.3.1': + resolution: {integrity: sha512-hItDHuIIlEV61R+faXu66s1K36aTurO/Qw0e45Vskz57gXl9pWOT6eg3zmcEui6CZXddbN7zd41bwmvag4JGwQ==} peerDependencies: vite: ^5.2.0 || ^6 || ^7 || ^8 @@ -5142,11 +5142,11 @@ packages: '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} - '@types/node@22.19.20': - resolution: {integrity: sha512-6tELRwSDYWW9EdZhbeZmYGZ1/7Djkt+Ah3/ScEYT9cDord7UJzasR/4D3VONg9tQI5CDp+/CZC1AXj2pCFOvpw==} + '@types/node@22.19.21': + resolution: {integrity: sha512-VMeFBSCKQKmm2swI2kW51SFusDqekC6q9trBCvJ/JliDchFSuoYYKN7yVNjPthP1HKZcx3U1gI/wTcEBjEFKTA==} - '@types/node@24.13.1': - resolution: {integrity: sha512-RSpUJGmvsJ1ZeBehQZFhIdpsz+bIpES0nIQXko4Ybq+N+kX6XvOq3Jo+iJ82FWLdblFq85AsMikd3m35jgezYg==} + '@types/node@24.13.2': + resolution: {integrity: sha512-fRa09kZTgu8o71KFcDjUFuc7F+dEbZYZmkI0mg5YBTRs0yMKjYHsq/c0urDKeDb+D5qVgXOdFcuu+DZPKOITwA==} '@types/parse-json@4.0.2': resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} @@ -5625,8 +5625,8 @@ packages: resolution: {integrity: sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==} engines: {node: '>=0.4.0'} - acorn@8.16.0: - resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} + acorn@8.17.0: + resolution: {integrity: sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==} engines: {node: '>=0.4.0'} hasBin: true @@ -5894,8 +5894,8 @@ packages: resolution: {integrity: sha512-LEUDjgmdJoA3LqklSTwKYqkjcZ4HKc4ddIYGSAiSkr46NTjzg2L9RNB+lekO9P7Dlpa87+hBtzc2Fzn/+GUWMQ==} engines: {node: '>=4'} - axe-core@4.12.0: - resolution: {integrity: sha512-FTavr/7Ba0IptwGOPxnQvdyW2tAsdLBMTBXz7rKH6xJ2skpyxpBxyHkDdBs4lf69yRqYpkqCdfhnwS8YULGOmg==} + axe-core@4.12.1: + resolution: {integrity: sha512-s7iGf5GaVMxEG0ENN9x+xTr7GFZCb1ZP/1uATUpCEK2X78nDB3RwbtFCo9pGAf9ru+VwoQ464DkaLEeRM08wJA==} engines: {node: '>=4'} axe-core@4.4.2: @@ -5906,8 +5906,8 @@ packages: resolution: {integrity: sha512-zIURGIS1E1Q4pcrMjp+nnEh+16G56eG/MUllJH8yEvw7asDo7Ac9uhC9KIH5jzpITueEZolfYglnCGIuSBz39g==} engines: {node: '>=4'} - axios@1.17.0: - resolution: {integrity: sha512-J8SwNxprqqpbfenehxWYXE7CW+wM1BB4w3+N+g+/Wx40xM4rsLrfPmHHxSWIxJLYDgSY/HqlFPIYb2/S3rxafw==} + axios@1.18.0: + resolution: {integrity: sha512-E32NzpYKp++W7XRe52rHiXV2ehxmh3wbdgO7MHeFM+vqxLBYHzt0ElkiImtOBxtOmyp0yoC8C6uESVV84Y2/hw==} axobject-query@4.1.0: resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} @@ -6000,8 +6000,8 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - baseline-browser-mapping@2.10.35: - resolution: {integrity: sha512-honAfLBde0HAFLdNyBEfuuENkF6zR+ozxqxa/2zJKHBe1qzLqyTSeRKpdPEHAP03rlDGyQOPnCSxnVpVqQo9Mg==} + baseline-browser-mapping@2.10.38: + resolution: {integrity: sha512-31/02mVB4yuQU6adKk5SlY6m+mxDwUq5KZkyYgnLrrKl7TEm1+3PyDtDBz2kOv/wxZz41GHsvV1A/u6RmiyBvw==} engines: {node: '>=6.0.0'} hasBin: true @@ -6162,8 +6162,8 @@ packages: caniuse-api@3.0.0: resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} - caniuse-lite@1.0.30001797: - resolution: {integrity: sha512-l8xKG+gwAIExZGl9FrF7KUwuOmk6wbEPC9Xoy/RtnWv1XG0Q4LFlagaLpUv3Kiza3W/wm27zy0yWJEieYKAP6w==} + caniuse-lite@1.0.30001799: + resolution: {integrity: sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==} case-sensitive-paths-webpack-plugin@2.4.0: resolution: {integrity: sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==} @@ -7024,8 +7024,8 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - electron-to-chromium@1.5.371: - resolution: {integrity: sha512-e9htk9mAYL6AzmkEhSvVVw7IWGSBJ/Bqdn2eRyRLrj1g6sncN4WbFt5qnILYoCktktr45pyjIrOiRvBThQ808w==} + electron-to-chromium@1.5.375: + resolution: {integrity: sha512-ZWP5eB4BVPW/ZYo9252hQZHZ5XavtsTgpbhcmMmRwymavC5AsLWQWBPaKMeNd2LW0KGby5HPXvj7+sr4ta5j/Q==} embla-carousel-autoplay@8.5.2: resolution: {integrity: sha512-27emJ0px3q/c0kCHCjwRrEbYcyYUPfGO3g5IBWF1i7714TTzE6L9P81V6PHLoSMAKJ1aHoT2e7YFOsuFKCbyag==} @@ -7071,8 +7071,12 @@ packages: endent@2.1.0: resolution: {integrity: sha512-r8VyPX7XL8U01Xgnb1CjZ3XV+z90cXIJ9JPE/R9SEC9vpw2P6CfsRPJmp20DppC5N7ZAMCmjYkJIa744Iyg96w==} - enhanced-resolve@5.23.0: - resolution: {integrity: sha512-yJN/BOOLxcOW2aQgeif9mSnaUB8KtvmMMp56oA1kx1CRfBKbhZm2pJ+NBY+3eOboHxix8lfjWpHE0Ei5U8RbSA==} + enhanced-resolve@5.21.6: + resolution: {integrity: sha512-aNnGCvbJ/RIyWo1IuhNdVjnNF+EjH9wpzpNHt+ci/m9He9LJvUN8wrCcXjp9cWsGNAuvSpVFTx/vraAFQ8qGjQ==} + engines: {node: '>=10.13.0'} + + enhanced-resolve@5.24.0: + resolution: {integrity: sha512-SkE2t82KlkkxQRVMVLAGKxLfORGQfrkx5dkj+vlgXRVNEdPc4eZcR+J/Fvj8C+yKSFH5L0q3NFlyufOVQnCcYQ==} engines: {node: '>=10.13.0'} entities@1.1.2: @@ -7110,6 +7114,10 @@ packages: error-stack-parser@2.1.4: resolution: {integrity: sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==} + es-abstract-get@1.0.0: + resolution: {integrity: sha512-6PMWXpdhshVvFp+FoWYs1EvG1Nj0tvk0dZM+XcK0xMEM1czRVcP6ohqPWHy6qPagSpC8j4+p89WXlT+xXJs/fg==} + engines: {node: '>= 0.4'} + es-abstract@1.24.2: resolution: {integrity: sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==} engines: {node: '>= 0.4'} @@ -7144,8 +7152,8 @@ packages: resolution: {integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==} engines: {node: '>= 0.4'} - es-to-primitive@1.3.0: - resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} + es-to-primitive@1.3.1: + resolution: {integrity: sha512-CxN9N56HYfd2m/acc/NOFrZQsN9kU4eh+2kk6A707Kz1krH8tKmfrs5RnftB8WNX80T0NS7vSQsDOlg23diR2g==} engines: {node: '>= 0.4'} es6-promise@4.2.8: @@ -7652,8 +7660,8 @@ packages: typescript: '>3.6.0' webpack: ^5.11.0 - form-data@4.0.5: - resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + form-data@4.0.6: + resolution: {integrity: sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==} engines: {node: '>= 6'} formidable@3.5.4: @@ -7705,8 +7713,8 @@ packages: function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - function.prototype.name@1.1.8: - resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} + function.prototype.name@1.2.0: + resolution: {integrity: sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew==} engines: {node: '>= 0.4'} functions-have-names@1.2.3: @@ -8226,6 +8234,10 @@ packages: engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} hasBin: true + is-document.all@1.0.0: + resolution: {integrity: sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g==} + engines: {node: '>= 0.4'} + is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -8515,8 +8527,8 @@ packages: resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} hasBin: true - joi@18.2.1: - resolution: {integrity: sha512-2/OKlogiESf2Nh3TFCrRjrr9z1DRHeW0I+KReF67+4J0Ns+8hBtHRmoWAZ2OFU6I5+TWLEe6sVlSdXPjHm5UbQ==} + joi@18.2.3: + resolution: {integrity: sha512-N5A3KTWQpPWT4ExxxPlUx7WmykGXRzhNidWhV41d6Abu9YfI2NyWCJuxdPnslJCPWtbRpSVOWSnSS6GakLM/Rg==} engines: {node: '>= 20'} jotai@2.11.3: @@ -9055,8 +9067,8 @@ packages: resolution: {integrity: sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==} engines: {node: '>= 4.0.0'} - memfs@4.57.6: - resolution: {integrity: sha512-WQK+DGjKCnPdpSyJUXphz+COF2uEhhsxQ3VIWBSbzpbbXuch3h4FePMqXrXGdLjsTgo4JFzBFsP6AWd9pVazGw==} + memfs@4.57.7: + resolution: {integrity: sha512-YZPphUQZSRGk6ddPlsNuMbztrLwsbUATFNZcqKscSbSJZ4g0+Y3vSZLJ/rfnGZaB1FFhC7SrywZXev6i8lnHgg==} peerDependencies: tslib: '2' @@ -9274,8 +9286,8 @@ packages: node-fetch-native@1.6.7: resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==} - node-releases@2.0.47: - resolution: {integrity: sha512-Uzmd6LXpouKo8EUK68IjH4+E01w/hXyV3R3g/geCJo+rXLNfh1xucB+LOzYEOQPSiUK3h/xZf0cQGcSsmyL2Og==} + node-releases@2.0.48: + resolution: {integrity: sha512-1uz8041X6LoI6ZSdZacM9lVY28vuzDlSKitnpbSNK0RfKoIJkX29NBPVEFXhnuSuEOA9Ww0xnPJ+ILWbGAv8DA==} engines: {node: '>=18'} normalize-path@3.0.0: @@ -9307,8 +9319,8 @@ packages: peerDependencies: webpack: ^4.0.0 || ^5.0.0 - nypm@0.6.6: - resolution: {integrity: sha512-vRyr0r4cbBapw07Xw8xrj9Teq3o7MUD35rSaTcanDbW+aK2XHDgJFiU6ZTj2GBw7Q12ysdsyFss+Vdz4hQ0Y6Q==} + nypm@0.6.7: + resolution: {integrity: sha512-s3ds97SD5pd1dULE+tHUk1DrV0cSHOnsfpcdGATJ8JpBo21DoKqN9exTH4/2nhPQNOLomBdTFMicN94S4DrZrQ==} engines: {node: '>=18'} hasBin: true @@ -9664,13 +9676,13 @@ packages: resolution: {integrity: sha512-emEcLuomt2j03vxD54giVB4SxTjnsqkU692xZOZXHDVoYyypEm+b3jpiTcc+Cf+myooc+/Ly0z01jqeNHVgJGw==} engines: {node: '>=16.0.0'} - playwright-core@1.60.0: - resolution: {integrity: sha512-9bW6zvX/m0lEbgTKJ6YppOKx8H3VOPBMOCFh2irXFOT4BbHgrx5hPjwJYLT40Lu+4qtD36qKc/Hn56StUW57IA==} + playwright-core@1.61.0: + resolution: {integrity: sha512-caX7TrY3Ml6egyDX0WUcTHDxodl/b51y5wJOdCEA36QviK/s2g081hvmGs8eaE3DWb6NYZQ6BjO/QkNRPenoPA==} engines: {node: '>=18'} hasBin: true - playwright@1.60.0: - resolution: {integrity: sha512-hheHdokM8cdqCb0lcE3s+zT4t4W+vvjpGxsZlDnikarzx8tSzMebh3UiFtgqwFwnTnjYQcsyMF8ei2mCO/tpeA==} + playwright@1.61.0: + resolution: {integrity: sha512-Z+7BeeqQPRRzklHsVFP4KTGIyMxKUmfeRA4WisM6G3/XW6nwGeX6fX9qYaDa+CiUqpOkb2f6X3nar05R3kSuJQ==} engines: {node: '>=18'} hasBin: true @@ -9920,8 +9932,8 @@ packages: peerDependencies: postcss: ^8.4.29 - postcss-selector-parser@7.1.2: - resolution: {integrity: sha512-Wjvt4scRFouioIInHf51IFNP4ltJ2EngJM+cZPGiqbKetBfmP3vpdPV8ID2S6JS6/jdo74N8+aEYH9lQr2C6sA==} + postcss-selector-parser@7.1.4: + resolution: {integrity: sha512-HeP7D2wyhkR+XaK6v4W8oRF62Dsz4flyuczALJp61GckGm42u1saSSJ/0auvcBqxs3jMRFEcPK34At/0JBKdOg==} engines: {node: '>=4'} postcss-sorting@8.0.2: @@ -10616,8 +10628,8 @@ packages: regjsgen@0.8.0: resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==} - regjsparser@0.13.1: - resolution: {integrity: sha512-dLsljMd9sqwRkby8zhO1gSg3PnJIBFid8f4CQj/sXx+7cKx+E7u0PKhZ+U4wmhx7EfmtvnA318oVaIkAB1lRJw==} + regjsparser@0.13.2: + resolution: {integrity: sha512-NgRBy2Nx/bE+9F27nVHnqcN5HjyLmecqsqx2PJHu3/IEtADD4WuxuXIVExD5PoSDFVrl78dOonfcOe5O+5nbzQ==} hasBin: true relateurl@0.2.7: @@ -10711,8 +10723,8 @@ packages: deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true - rollup@4.61.1: - resolution: {integrity: sha512-I4KW6iuRpuu2uHBLraZ1wNZe0DP7lnRha+VJ9tNaYVaVgKhW0aI3h4RYnoRPeql0flHm/Co55b7snEDcOfOJrA==} + rollup@4.62.0: + resolution: {integrity: sha512-nc72Wgq62I7rtDV4izT5/aaS0zxy3kttkinf9586ApknY3jZO9NYsmtc24fUckA0X7Q2v+ML4a15pdUlV5V/jA==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -11376,8 +11388,8 @@ packages: peerDependencies: tailwindcss: ^4.0.0 - tailwindcss@4.3.0: - resolution: {integrity: sha512-y6nxMGB1nMW9R6k96e5gdIFzcfL/gTJRNaqGes1YvkLnPVXzWgbqFF2yLC0T8G774n24cx3Pe8XrKoniCOAH+Q==} + tailwindcss@4.3.1: + resolution: {integrity: sha512-hk+TB1m+K8CYNrP6rjQaq/Y+4Zylwpa87mLYBKCunwnnQ9p+fHb7kmSfGqyEJoxF/O6CDyABWVFEafNSYKll+Q==} tapable@1.1.3: resolution: {integrity: sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==} @@ -11541,15 +11553,15 @@ packages: tldts-core@6.1.86: resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==} - tldts-core@7.4.2: - resolution: {integrity: sha512-nwEyF4vl4RSJjwSjBUmOSxc3BFPoIFdlRthJ6e+5v9P3bHNsoD06UjuqMUspqp7vsEZ1beaHi1km+optiE17yA==} + tldts-core@7.4.3: + resolution: {integrity: sha512-27ep5H9PzdBrNd5OFM/j3WCU8F3kPwM9D0BOaOf7uYfxMJfyr0K5Tjj69Gri+sZlh2WXd5buIm47NuPF29CDiw==} tldts@6.1.86: resolution: {integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==} hasBin: true - tldts@7.4.2: - resolution: {integrity: sha512-kCwffuaH8ntKtygnWe1b4BJKWiCUH30n5KfoTr6IchcXOwR7chAOFJxFrH3vjANafUYrIA4a7SDL+nn7SiR4Sw==} + tldts@7.4.3: + resolution: {integrity: sha512-A3BDQBeeukYPzB4QdQ1DtdlUmp4x2OCH8n5UVhEWbyANxNep8GavottKzd1xYKFJKjUgMyPT7EzOfnBO55s8Sg==} hasBin: true tmp@0.0.33: @@ -11764,8 +11776,8 @@ packages: resolution: {integrity: sha512-3IWdCpjgxp15CbJnsi/Y9TCDE7HWVN19j1hmzVhoAkY/+CJx449tVxT5wZc1Gwg8J+P0LWvzlBzxYRnHJ+1i7Q==} engines: {node: '>=20.18.1'} - undici@7.27.2: - resolution: {integrity: sha512-uZsKNuzQxDMUY6M3pIMvy5tvlGmtq8XJ2oLAkfRKGNu+1VQAIvLy2xIVG5ATZl5wDXl/tddByAWCizRbOme+TA==} + undici@7.28.0: + resolution: {integrity: sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==} engines: {node: '>=20.18.1'} undoo@0.5.0: @@ -12034,8 +12046,8 @@ packages: warning@4.0.3: resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==} - watchpack@2.5.1: - resolution: {integrity: sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==} + watchpack@2.5.2: + resolution: {integrity: sha512-6i/00NBjP4yGPs+caKSyRfpTF/8Torsu0MOW3mMzIbhgISFder8i7xbqgHlLMwJrdiN8ndBV3UA1/AfzPSr+jg==} engines: {node: '>=10.13.0'} wbuf@1.7.3: @@ -12074,8 +12086,8 @@ packages: webpack: optional: true - webpack-dev-server@5.2.4: - resolution: {integrity: sha512-GqDPGZN9bRqKBTkp4aWkobDDHMsrXKoGSdOH56smIri8qR0JG8gfL8/v/f/OZR3/OKXjG8uwJbFVhKm/FNU/UA==} + webpack-dev-server@5.2.5: + resolution: {integrity: sha512-4wZtCquSuv9CKX8oybo+mqxtxZqWz47uM1Ch94lxowBztOhWCbhqvRbfC/mODOwxgV2brY+JGZpHq58/SuVFYg==} engines: {node: '>= 18.12.0'} hasBin: true peerDependencies: @@ -12409,7 +12421,7 @@ snapshots: dependencies: '@asamuzakjp/generational-cache': 1.0.1 '@csstools/css-calc': 3.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - '@csstools/css-color-parser': 4.1.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-color-parser': 4.1.7(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) '@csstools/css-tokenizer': 4.0.0 @@ -13353,7 +13365,7 @@ snapshots: '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) '@csstools/css-tokenizer': 4.0.0 - '@csstools/css-color-parser@4.1.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': + '@csstools/css-color-parser@4.1.7(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': dependencies: '@csstools/color-helpers': 6.0.2 '@csstools/css-calc': 3.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) @@ -13381,9 +13393,9 @@ snapshots: '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 - '@csstools/selector-specificity@5.0.0(postcss-selector-parser@7.1.2)': + '@csstools/selector-specificity@5.0.0(postcss-selector-parser@7.1.4)': dependencies: - postcss-selector-parser: 7.1.2 + postcss-selector-parser: 7.1.4 '@cypress/request@4.0.1': dependencies: @@ -13393,7 +13405,7 @@ snapshots: combined-stream: 1.0.8 extend: 3.0.2 forever-agent: 0.6.1 - form-data: 4.0.5 + form-data: 4.0.6 http-signature: 1.4.0 is-typedarray: 1.0.0 isstream: 0.1.2 @@ -13775,7 +13787,7 @@ snapshots: '@hapi/pinpoint@2.0.1': {} - '@hapi/tlds@1.1.6': {} + '@hapi/tlds@1.1.7': {} '@hapi/topo@6.0.2': dependencies: @@ -13804,366 +13816,366 @@ snapshots: '@inquirer/ansi@2.0.7': {} - '@inquirer/checkbox@4.3.2(@types/node@22.19.20)': + '@inquirer/checkbox@4.3.2(@types/node@22.19.21)': dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@22.19.20) + '@inquirer/core': 10.3.2(@types/node@22.19.21) '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@22.19.20) + '@inquirer/type': 3.0.10(@types/node@22.19.21) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 22.19.20 + '@types/node': 22.19.21 - '@inquirer/checkbox@4.3.2(@types/node@24.13.1)': + '@inquirer/checkbox@4.3.2(@types/node@24.13.2)': dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@24.13.1) + '@inquirer/core': 10.3.2(@types/node@24.13.2) '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@24.13.1) + '@inquirer/type': 3.0.10(@types/node@24.13.2) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 - '@inquirer/checkbox@5.2.1(@types/node@24.13.1)': + '@inquirer/checkbox@5.2.1(@types/node@24.13.2)': dependencies: '@inquirer/ansi': 2.0.7 - '@inquirer/core': 11.2.1(@types/node@24.13.1) + '@inquirer/core': 11.2.1(@types/node@24.13.2) '@inquirer/figures': 2.0.7 - '@inquirer/type': 4.0.7(@types/node@24.13.1) + '@inquirer/type': 4.0.7(@types/node@24.13.2) optionalDependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 - '@inquirer/confirm@5.1.21(@types/node@22.19.20)': + '@inquirer/confirm@5.1.21(@types/node@22.19.21)': dependencies: - '@inquirer/core': 10.3.2(@types/node@22.19.20) - '@inquirer/type': 3.0.10(@types/node@22.19.20) + '@inquirer/core': 10.3.2(@types/node@22.19.21) + '@inquirer/type': 3.0.10(@types/node@22.19.21) optionalDependencies: - '@types/node': 22.19.20 + '@types/node': 22.19.21 - '@inquirer/confirm@5.1.21(@types/node@24.13.1)': + '@inquirer/confirm@5.1.21(@types/node@24.13.2)': dependencies: - '@inquirer/core': 10.3.2(@types/node@24.13.1) - '@inquirer/type': 3.0.10(@types/node@24.13.1) + '@inquirer/core': 10.3.2(@types/node@24.13.2) + '@inquirer/type': 3.0.10(@types/node@24.13.2) optionalDependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 - '@inquirer/confirm@6.1.1(@types/node@24.13.1)': + '@inquirer/confirm@6.1.1(@types/node@24.13.2)': dependencies: - '@inquirer/core': 11.2.1(@types/node@24.13.1) - '@inquirer/type': 4.0.7(@types/node@24.13.1) + '@inquirer/core': 11.2.1(@types/node@24.13.2) + '@inquirer/type': 4.0.7(@types/node@24.13.2) optionalDependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 - '@inquirer/core@10.3.2(@types/node@22.19.20)': + '@inquirer/core@10.3.2(@types/node@22.19.21)': dependencies: '@inquirer/ansi': 1.0.2 '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@22.19.20) + '@inquirer/type': 3.0.10(@types/node@22.19.21) cli-width: 4.1.0 mute-stream: 2.0.0 signal-exit: 4.1.0 wrap-ansi: 6.2.0 yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 22.19.20 + '@types/node': 22.19.21 - '@inquirer/core@10.3.2(@types/node@24.13.1)': + '@inquirer/core@10.3.2(@types/node@24.13.2)': dependencies: '@inquirer/ansi': 1.0.2 '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@24.13.1) + '@inquirer/type': 3.0.10(@types/node@24.13.2) cli-width: 4.1.0 mute-stream: 2.0.0 signal-exit: 4.1.0 wrap-ansi: 6.2.0 yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 - '@inquirer/core@11.2.1(@types/node@24.13.1)': + '@inquirer/core@11.2.1(@types/node@24.13.2)': dependencies: '@inquirer/ansi': 2.0.7 '@inquirer/figures': 2.0.7 - '@inquirer/type': 4.0.7(@types/node@24.13.1) + '@inquirer/type': 4.0.7(@types/node@24.13.2) cli-width: 4.1.0 fast-wrap-ansi: 0.2.2 mute-stream: 3.0.0 signal-exit: 4.1.0 optionalDependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 - '@inquirer/editor@4.2.23(@types/node@22.19.20)': + '@inquirer/editor@4.2.23(@types/node@22.19.21)': dependencies: - '@inquirer/core': 10.3.2(@types/node@22.19.20) - '@inquirer/external-editor': 1.0.3(@types/node@22.19.20) - '@inquirer/type': 3.0.10(@types/node@22.19.20) + '@inquirer/core': 10.3.2(@types/node@22.19.21) + '@inquirer/external-editor': 1.0.3(@types/node@22.19.21) + '@inquirer/type': 3.0.10(@types/node@22.19.21) optionalDependencies: - '@types/node': 22.19.20 + '@types/node': 22.19.21 - '@inquirer/editor@4.2.23(@types/node@24.13.1)': + '@inquirer/editor@4.2.23(@types/node@24.13.2)': dependencies: - '@inquirer/core': 10.3.2(@types/node@24.13.1) - '@inquirer/external-editor': 1.0.3(@types/node@24.13.1) - '@inquirer/type': 3.0.10(@types/node@24.13.1) + '@inquirer/core': 10.3.2(@types/node@24.13.2) + '@inquirer/external-editor': 1.0.3(@types/node@24.13.2) + '@inquirer/type': 3.0.10(@types/node@24.13.2) optionalDependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 - '@inquirer/editor@5.2.2(@types/node@24.13.1)': + '@inquirer/editor@5.2.2(@types/node@24.13.2)': dependencies: - '@inquirer/core': 11.2.1(@types/node@24.13.1) - '@inquirer/external-editor': 3.0.3(@types/node@24.13.1) - '@inquirer/type': 4.0.7(@types/node@24.13.1) + '@inquirer/core': 11.2.1(@types/node@24.13.2) + '@inquirer/external-editor': 3.0.3(@types/node@24.13.2) + '@inquirer/type': 4.0.7(@types/node@24.13.2) optionalDependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 - '@inquirer/expand@4.0.23(@types/node@22.19.20)': + '@inquirer/expand@4.0.23(@types/node@22.19.21)': dependencies: - '@inquirer/core': 10.3.2(@types/node@22.19.20) - '@inquirer/type': 3.0.10(@types/node@22.19.20) + '@inquirer/core': 10.3.2(@types/node@22.19.21) + '@inquirer/type': 3.0.10(@types/node@22.19.21) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 22.19.20 + '@types/node': 22.19.21 - '@inquirer/expand@4.0.23(@types/node@24.13.1)': + '@inquirer/expand@4.0.23(@types/node@24.13.2)': dependencies: - '@inquirer/core': 10.3.2(@types/node@24.13.1) - '@inquirer/type': 3.0.10(@types/node@24.13.1) + '@inquirer/core': 10.3.2(@types/node@24.13.2) + '@inquirer/type': 3.0.10(@types/node@24.13.2) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 - '@inquirer/expand@5.1.1(@types/node@24.13.1)': + '@inquirer/expand@5.1.1(@types/node@24.13.2)': dependencies: - '@inquirer/core': 11.2.1(@types/node@24.13.1) - '@inquirer/type': 4.0.7(@types/node@24.13.1) + '@inquirer/core': 11.2.1(@types/node@24.13.2) + '@inquirer/type': 4.0.7(@types/node@24.13.2) optionalDependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 - '@inquirer/external-editor@1.0.3(@types/node@22.19.20)': + '@inquirer/external-editor@1.0.3(@types/node@22.19.21)': dependencies: chardet: 2.1.1 iconv-lite: 0.7.2 optionalDependencies: - '@types/node': 22.19.20 + '@types/node': 22.19.21 - '@inquirer/external-editor@1.0.3(@types/node@24.13.1)': + '@inquirer/external-editor@1.0.3(@types/node@24.13.2)': dependencies: chardet: 2.1.1 iconv-lite: 0.7.2 optionalDependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 - '@inquirer/external-editor@3.0.3(@types/node@24.13.1)': + '@inquirer/external-editor@3.0.3(@types/node@24.13.2)': dependencies: chardet: 2.1.1 iconv-lite: 0.7.2 optionalDependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 '@inquirer/figures@1.0.15': {} '@inquirer/figures@2.0.7': {} - '@inquirer/input@4.3.1(@types/node@22.19.20)': + '@inquirer/input@4.3.1(@types/node@22.19.21)': dependencies: - '@inquirer/core': 10.3.2(@types/node@22.19.20) - '@inquirer/type': 3.0.10(@types/node@22.19.20) + '@inquirer/core': 10.3.2(@types/node@22.19.21) + '@inquirer/type': 3.0.10(@types/node@22.19.21) optionalDependencies: - '@types/node': 22.19.20 + '@types/node': 22.19.21 - '@inquirer/input@4.3.1(@types/node@24.13.1)': + '@inquirer/input@4.3.1(@types/node@24.13.2)': dependencies: - '@inquirer/core': 10.3.2(@types/node@24.13.1) - '@inquirer/type': 3.0.10(@types/node@24.13.1) + '@inquirer/core': 10.3.2(@types/node@24.13.2) + '@inquirer/type': 3.0.10(@types/node@24.13.2) optionalDependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 - '@inquirer/input@5.1.2(@types/node@24.13.1)': + '@inquirer/input@5.1.2(@types/node@24.13.2)': dependencies: - '@inquirer/core': 11.2.1(@types/node@24.13.1) - '@inquirer/type': 4.0.7(@types/node@24.13.1) + '@inquirer/core': 11.2.1(@types/node@24.13.2) + '@inquirer/type': 4.0.7(@types/node@24.13.2) optionalDependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 - '@inquirer/number@3.0.23(@types/node@22.19.20)': + '@inquirer/number@3.0.23(@types/node@22.19.21)': dependencies: - '@inquirer/core': 10.3.2(@types/node@22.19.20) - '@inquirer/type': 3.0.10(@types/node@22.19.20) + '@inquirer/core': 10.3.2(@types/node@22.19.21) + '@inquirer/type': 3.0.10(@types/node@22.19.21) optionalDependencies: - '@types/node': 22.19.20 + '@types/node': 22.19.21 - '@inquirer/number@3.0.23(@types/node@24.13.1)': + '@inquirer/number@3.0.23(@types/node@24.13.2)': dependencies: - '@inquirer/core': 10.3.2(@types/node@24.13.1) - '@inquirer/type': 3.0.10(@types/node@24.13.1) + '@inquirer/core': 10.3.2(@types/node@24.13.2) + '@inquirer/type': 3.0.10(@types/node@24.13.2) optionalDependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 - '@inquirer/number@4.1.1(@types/node@24.13.1)': + '@inquirer/number@4.1.1(@types/node@24.13.2)': dependencies: - '@inquirer/core': 11.2.1(@types/node@24.13.1) - '@inquirer/type': 4.0.7(@types/node@24.13.1) + '@inquirer/core': 11.2.1(@types/node@24.13.2) + '@inquirer/type': 4.0.7(@types/node@24.13.2) optionalDependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 - '@inquirer/password@4.0.23(@types/node@22.19.20)': + '@inquirer/password@4.0.23(@types/node@22.19.21)': dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@22.19.20) - '@inquirer/type': 3.0.10(@types/node@22.19.20) + '@inquirer/core': 10.3.2(@types/node@22.19.21) + '@inquirer/type': 3.0.10(@types/node@22.19.21) optionalDependencies: - '@types/node': 22.19.20 + '@types/node': 22.19.21 - '@inquirer/password@4.0.23(@types/node@24.13.1)': + '@inquirer/password@4.0.23(@types/node@24.13.2)': dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@24.13.1) - '@inquirer/type': 3.0.10(@types/node@24.13.1) + '@inquirer/core': 10.3.2(@types/node@24.13.2) + '@inquirer/type': 3.0.10(@types/node@24.13.2) optionalDependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 - '@inquirer/password@5.1.1(@types/node@24.13.1)': + '@inquirer/password@5.1.1(@types/node@24.13.2)': dependencies: '@inquirer/ansi': 2.0.7 - '@inquirer/core': 11.2.1(@types/node@24.13.1) - '@inquirer/type': 4.0.7(@types/node@24.13.1) + '@inquirer/core': 11.2.1(@types/node@24.13.2) + '@inquirer/type': 4.0.7(@types/node@24.13.2) optionalDependencies: - '@types/node': 24.13.1 - - '@inquirer/prompts@7.10.1(@types/node@22.19.20)': - dependencies: - '@inquirer/checkbox': 4.3.2(@types/node@22.19.20) - '@inquirer/confirm': 5.1.21(@types/node@22.19.20) - '@inquirer/editor': 4.2.23(@types/node@22.19.20) - '@inquirer/expand': 4.0.23(@types/node@22.19.20) - '@inquirer/input': 4.3.1(@types/node@22.19.20) - '@inquirer/number': 3.0.23(@types/node@22.19.20) - '@inquirer/password': 4.0.23(@types/node@22.19.20) - '@inquirer/rawlist': 4.1.11(@types/node@22.19.20) - '@inquirer/search': 3.2.2(@types/node@22.19.20) - '@inquirer/select': 4.4.2(@types/node@22.19.20) + '@types/node': 24.13.2 + + '@inquirer/prompts@7.10.1(@types/node@22.19.21)': + dependencies: + '@inquirer/checkbox': 4.3.2(@types/node@22.19.21) + '@inquirer/confirm': 5.1.21(@types/node@22.19.21) + '@inquirer/editor': 4.2.23(@types/node@22.19.21) + '@inquirer/expand': 4.0.23(@types/node@22.19.21) + '@inquirer/input': 4.3.1(@types/node@22.19.21) + '@inquirer/number': 3.0.23(@types/node@22.19.21) + '@inquirer/password': 4.0.23(@types/node@22.19.21) + '@inquirer/rawlist': 4.1.11(@types/node@22.19.21) + '@inquirer/search': 3.2.2(@types/node@22.19.21) + '@inquirer/select': 4.4.2(@types/node@22.19.21) optionalDependencies: - '@types/node': 22.19.20 - - '@inquirer/prompts@7.10.1(@types/node@24.13.1)': - dependencies: - '@inquirer/checkbox': 4.3.2(@types/node@24.13.1) - '@inquirer/confirm': 5.1.21(@types/node@24.13.1) - '@inquirer/editor': 4.2.23(@types/node@24.13.1) - '@inquirer/expand': 4.0.23(@types/node@24.13.1) - '@inquirer/input': 4.3.1(@types/node@24.13.1) - '@inquirer/number': 3.0.23(@types/node@24.13.1) - '@inquirer/password': 4.0.23(@types/node@24.13.1) - '@inquirer/rawlist': 4.1.11(@types/node@24.13.1) - '@inquirer/search': 3.2.2(@types/node@24.13.1) - '@inquirer/select': 4.4.2(@types/node@24.13.1) + '@types/node': 22.19.21 + + '@inquirer/prompts@7.10.1(@types/node@24.13.2)': + dependencies: + '@inquirer/checkbox': 4.3.2(@types/node@24.13.2) + '@inquirer/confirm': 5.1.21(@types/node@24.13.2) + '@inquirer/editor': 4.2.23(@types/node@24.13.2) + '@inquirer/expand': 4.0.23(@types/node@24.13.2) + '@inquirer/input': 4.3.1(@types/node@24.13.2) + '@inquirer/number': 3.0.23(@types/node@24.13.2) + '@inquirer/password': 4.0.23(@types/node@24.13.2) + '@inquirer/rawlist': 4.1.11(@types/node@24.13.2) + '@inquirer/search': 3.2.2(@types/node@24.13.2) + '@inquirer/select': 4.4.2(@types/node@24.13.2) optionalDependencies: - '@types/node': 24.13.1 - - '@inquirer/prompts@8.4.2(@types/node@24.13.1)': - dependencies: - '@inquirer/checkbox': 5.2.1(@types/node@24.13.1) - '@inquirer/confirm': 6.1.1(@types/node@24.13.1) - '@inquirer/editor': 5.2.2(@types/node@24.13.1) - '@inquirer/expand': 5.1.1(@types/node@24.13.1) - '@inquirer/input': 5.1.2(@types/node@24.13.1) - '@inquirer/number': 4.1.1(@types/node@24.13.1) - '@inquirer/password': 5.1.1(@types/node@24.13.1) - '@inquirer/rawlist': 5.3.1(@types/node@24.13.1) - '@inquirer/search': 4.2.1(@types/node@24.13.1) - '@inquirer/select': 5.2.1(@types/node@24.13.1) + '@types/node': 24.13.2 + + '@inquirer/prompts@8.4.2(@types/node@24.13.2)': + dependencies: + '@inquirer/checkbox': 5.2.1(@types/node@24.13.2) + '@inquirer/confirm': 6.1.1(@types/node@24.13.2) + '@inquirer/editor': 5.2.2(@types/node@24.13.2) + '@inquirer/expand': 5.1.1(@types/node@24.13.2) + '@inquirer/input': 5.1.2(@types/node@24.13.2) + '@inquirer/number': 4.1.1(@types/node@24.13.2) + '@inquirer/password': 5.1.1(@types/node@24.13.2) + '@inquirer/rawlist': 5.3.1(@types/node@24.13.2) + '@inquirer/search': 4.2.1(@types/node@24.13.2) + '@inquirer/select': 5.2.1(@types/node@24.13.2) optionalDependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 - '@inquirer/rawlist@4.1.11(@types/node@22.19.20)': + '@inquirer/rawlist@4.1.11(@types/node@22.19.21)': dependencies: - '@inquirer/core': 10.3.2(@types/node@22.19.20) - '@inquirer/type': 3.0.10(@types/node@22.19.20) + '@inquirer/core': 10.3.2(@types/node@22.19.21) + '@inquirer/type': 3.0.10(@types/node@22.19.21) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 22.19.20 + '@types/node': 22.19.21 - '@inquirer/rawlist@4.1.11(@types/node@24.13.1)': + '@inquirer/rawlist@4.1.11(@types/node@24.13.2)': dependencies: - '@inquirer/core': 10.3.2(@types/node@24.13.1) - '@inquirer/type': 3.0.10(@types/node@24.13.1) + '@inquirer/core': 10.3.2(@types/node@24.13.2) + '@inquirer/type': 3.0.10(@types/node@24.13.2) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 - '@inquirer/rawlist@5.3.1(@types/node@24.13.1)': + '@inquirer/rawlist@5.3.1(@types/node@24.13.2)': dependencies: - '@inquirer/core': 11.2.1(@types/node@24.13.1) - '@inquirer/type': 4.0.7(@types/node@24.13.1) + '@inquirer/core': 11.2.1(@types/node@24.13.2) + '@inquirer/type': 4.0.7(@types/node@24.13.2) optionalDependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 - '@inquirer/search@3.2.2(@types/node@22.19.20)': + '@inquirer/search@3.2.2(@types/node@22.19.21)': dependencies: - '@inquirer/core': 10.3.2(@types/node@22.19.20) + '@inquirer/core': 10.3.2(@types/node@22.19.21) '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@22.19.20) + '@inquirer/type': 3.0.10(@types/node@22.19.21) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 22.19.20 + '@types/node': 22.19.21 - '@inquirer/search@3.2.2(@types/node@24.13.1)': + '@inquirer/search@3.2.2(@types/node@24.13.2)': dependencies: - '@inquirer/core': 10.3.2(@types/node@24.13.1) + '@inquirer/core': 10.3.2(@types/node@24.13.2) '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@24.13.1) + '@inquirer/type': 3.0.10(@types/node@24.13.2) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 - '@inquirer/search@4.2.1(@types/node@24.13.1)': + '@inquirer/search@4.2.1(@types/node@24.13.2)': dependencies: - '@inquirer/core': 11.2.1(@types/node@24.13.1) + '@inquirer/core': 11.2.1(@types/node@24.13.2) '@inquirer/figures': 2.0.7 - '@inquirer/type': 4.0.7(@types/node@24.13.1) + '@inquirer/type': 4.0.7(@types/node@24.13.2) optionalDependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 - '@inquirer/select@4.4.2(@types/node@22.19.20)': + '@inquirer/select@4.4.2(@types/node@22.19.21)': dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@22.19.20) + '@inquirer/core': 10.3.2(@types/node@22.19.21) '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@22.19.20) + '@inquirer/type': 3.0.10(@types/node@22.19.21) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 22.19.20 + '@types/node': 22.19.21 - '@inquirer/select@4.4.2(@types/node@24.13.1)': + '@inquirer/select@4.4.2(@types/node@24.13.2)': dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@24.13.1) + '@inquirer/core': 10.3.2(@types/node@24.13.2) '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@24.13.1) + '@inquirer/type': 3.0.10(@types/node@24.13.2) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 - '@inquirer/select@5.2.1(@types/node@24.13.1)': + '@inquirer/select@5.2.1(@types/node@24.13.2)': dependencies: '@inquirer/ansi': 2.0.7 - '@inquirer/core': 11.2.1(@types/node@24.13.1) + '@inquirer/core': 11.2.1(@types/node@24.13.2) '@inquirer/figures': 2.0.7 - '@inquirer/type': 4.0.7(@types/node@24.13.1) + '@inquirer/type': 4.0.7(@types/node@24.13.2) optionalDependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 - '@inquirer/type@3.0.10(@types/node@22.19.20)': + '@inquirer/type@3.0.10(@types/node@22.19.21)': optionalDependencies: - '@types/node': 22.19.20 + '@types/node': 22.19.21 - '@inquirer/type@3.0.10(@types/node@24.13.1)': + '@inquirer/type@3.0.10(@types/node@24.13.2)': optionalDependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 - '@inquirer/type@4.0.7(@types/node@24.13.1)': + '@inquirer/type@4.0.7(@types/node@24.13.2)': optionalDependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 '@internationalized/date@3.12.2': dependencies: @@ -14194,7 +14206,7 @@ snapshots: '@jest/pattern@30.4.0': dependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 jest-regex-util: 30.4.0 '@jest/schemas@29.6.3': @@ -14209,7 +14221,7 @@ snapshots: dependencies: '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 24.13.1 + '@types/node': 24.13.2 '@types/yargs': 15.0.20 chalk: 4.1.2 @@ -14218,7 +14230,7 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 22.19.20 + '@types/node': 22.19.21 '@types/yargs': 17.0.35 chalk: 4.1.2 @@ -14228,7 +14240,7 @@ snapshots: '@jest/schemas': 30.4.1 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 24.13.1 + '@types/node': 24.13.2 '@types/yargs': 17.0.35 chalk: 4.1.2 @@ -14280,58 +14292,58 @@ snapshots: dependencies: tslib: 2.8.1 - '@jsonjoy.com/fs-core@4.57.6(tslib@2.8.1)': + '@jsonjoy.com/fs-core@4.57.7(tslib@2.8.1)': dependencies: - '@jsonjoy.com/fs-node-builtins': 4.57.6(tslib@2.8.1) - '@jsonjoy.com/fs-node-utils': 4.57.6(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.57.7(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.7(tslib@2.8.1) thingies: 2.6.0(tslib@2.8.1) tslib: 2.8.1 - '@jsonjoy.com/fs-fsa@4.57.6(tslib@2.8.1)': + '@jsonjoy.com/fs-fsa@4.57.7(tslib@2.8.1)': dependencies: - '@jsonjoy.com/fs-core': 4.57.6(tslib@2.8.1) - '@jsonjoy.com/fs-node-builtins': 4.57.6(tslib@2.8.1) - '@jsonjoy.com/fs-node-utils': 4.57.6(tslib@2.8.1) + '@jsonjoy.com/fs-core': 4.57.7(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.57.7(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.7(tslib@2.8.1) thingies: 2.6.0(tslib@2.8.1) tslib: 2.8.1 - '@jsonjoy.com/fs-node-builtins@4.57.6(tslib@2.8.1)': + '@jsonjoy.com/fs-node-builtins@4.57.7(tslib@2.8.1)': dependencies: tslib: 2.8.1 - '@jsonjoy.com/fs-node-to-fsa@4.57.6(tslib@2.8.1)': + '@jsonjoy.com/fs-node-to-fsa@4.57.7(tslib@2.8.1)': dependencies: - '@jsonjoy.com/fs-fsa': 4.57.6(tslib@2.8.1) - '@jsonjoy.com/fs-node-builtins': 4.57.6(tslib@2.8.1) - '@jsonjoy.com/fs-node-utils': 4.57.6(tslib@2.8.1) + '@jsonjoy.com/fs-fsa': 4.57.7(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.57.7(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.7(tslib@2.8.1) tslib: 2.8.1 - '@jsonjoy.com/fs-node-utils@4.57.6(tslib@2.8.1)': + '@jsonjoy.com/fs-node-utils@4.57.7(tslib@2.8.1)': dependencies: - '@jsonjoy.com/fs-node-builtins': 4.57.6(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.57.7(tslib@2.8.1) tslib: 2.8.1 - '@jsonjoy.com/fs-node@4.57.6(tslib@2.8.1)': + '@jsonjoy.com/fs-node@4.57.7(tslib@2.8.1)': dependencies: - '@jsonjoy.com/fs-core': 4.57.6(tslib@2.8.1) - '@jsonjoy.com/fs-node-builtins': 4.57.6(tslib@2.8.1) - '@jsonjoy.com/fs-node-utils': 4.57.6(tslib@2.8.1) - '@jsonjoy.com/fs-print': 4.57.6(tslib@2.8.1) - '@jsonjoy.com/fs-snapshot': 4.57.6(tslib@2.8.1) + '@jsonjoy.com/fs-core': 4.57.7(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.57.7(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.7(tslib@2.8.1) + '@jsonjoy.com/fs-print': 4.57.7(tslib@2.8.1) + '@jsonjoy.com/fs-snapshot': 4.57.7(tslib@2.8.1) glob-to-regex.js: 1.2.0(tslib@2.8.1) thingies: 2.6.0(tslib@2.8.1) tslib: 2.8.1 - '@jsonjoy.com/fs-print@4.57.6(tslib@2.8.1)': + '@jsonjoy.com/fs-print@4.57.7(tslib@2.8.1)': dependencies: - '@jsonjoy.com/fs-node-utils': 4.57.6(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.7(tslib@2.8.1) tree-dump: 1.1.0(tslib@2.8.1) tslib: 2.8.1 - '@jsonjoy.com/fs-snapshot@4.57.6(tslib@2.8.1)': + '@jsonjoy.com/fs-snapshot@4.57.7(tslib@2.8.1)': dependencies: '@jsonjoy.com/buffers': 17.67.0(tslib@2.8.1) - '@jsonjoy.com/fs-node-utils': 4.57.6(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.7(tslib@2.8.1) '@jsonjoy.com/json-pack': 17.67.0(tslib@2.8.1) '@jsonjoy.com/util': 17.67.0(tslib@2.8.1) tslib: 2.8.1 @@ -14427,7 +14439,7 @@ snapshots: '@loadable/server@5.16.7(@loadable/component@5.16.7(react@18.2.0))(react@18.2.0)': dependencies: '@loadable/component': 5.16.7(react@18.2.0) - lodash: 4.17.21 + lodash: 4.18.1 react: 18.2.0 '@loadable/webpack-plugin@5.15.2(webpack@5.105.4(esbuild@0.25.12))': @@ -14604,78 +14616,78 @@ snapshots: dependencies: '@noble/hashes': 1.8.0 - '@peculiar/asn1-cms@2.7.0': + '@peculiar/asn1-cms@2.8.0': dependencies: - '@peculiar/asn1-schema': 2.7.0 - '@peculiar/asn1-x509': 2.7.0 - '@peculiar/asn1-x509-attr': 2.7.0 + '@peculiar/asn1-schema': 2.8.0 + '@peculiar/asn1-x509': 2.8.0 + '@peculiar/asn1-x509-attr': 2.8.0 asn1js: 3.0.10 tslib: 2.8.1 - '@peculiar/asn1-csr@2.7.0': + '@peculiar/asn1-csr@2.8.0': dependencies: - '@peculiar/asn1-schema': 2.7.0 - '@peculiar/asn1-x509': 2.7.0 + '@peculiar/asn1-schema': 2.8.0 + '@peculiar/asn1-x509': 2.8.0 asn1js: 3.0.10 tslib: 2.8.1 - '@peculiar/asn1-ecc@2.7.0': + '@peculiar/asn1-ecc@2.8.0': dependencies: - '@peculiar/asn1-schema': 2.7.0 - '@peculiar/asn1-x509': 2.7.0 + '@peculiar/asn1-schema': 2.8.0 + '@peculiar/asn1-x509': 2.8.0 asn1js: 3.0.10 tslib: 2.8.1 - '@peculiar/asn1-pfx@2.7.0': + '@peculiar/asn1-pfx@2.8.0': dependencies: - '@peculiar/asn1-cms': 2.7.0 - '@peculiar/asn1-pkcs8': 2.7.0 - '@peculiar/asn1-rsa': 2.7.0 - '@peculiar/asn1-schema': 2.7.0 + '@peculiar/asn1-cms': 2.8.0 + '@peculiar/asn1-pkcs8': 2.8.0 + '@peculiar/asn1-rsa': 2.8.0 + '@peculiar/asn1-schema': 2.8.0 asn1js: 3.0.10 tslib: 2.8.1 - '@peculiar/asn1-pkcs8@2.7.0': + '@peculiar/asn1-pkcs8@2.8.0': dependencies: - '@peculiar/asn1-schema': 2.7.0 - '@peculiar/asn1-x509': 2.7.0 + '@peculiar/asn1-schema': 2.8.0 + '@peculiar/asn1-x509': 2.8.0 asn1js: 3.0.10 tslib: 2.8.1 - '@peculiar/asn1-pkcs9@2.7.0': + '@peculiar/asn1-pkcs9@2.8.0': dependencies: - '@peculiar/asn1-cms': 2.7.0 - '@peculiar/asn1-pfx': 2.7.0 - '@peculiar/asn1-pkcs8': 2.7.0 - '@peculiar/asn1-schema': 2.7.0 - '@peculiar/asn1-x509': 2.7.0 - '@peculiar/asn1-x509-attr': 2.7.0 + '@peculiar/asn1-cms': 2.8.0 + '@peculiar/asn1-pfx': 2.8.0 + '@peculiar/asn1-pkcs8': 2.8.0 + '@peculiar/asn1-schema': 2.8.0 + '@peculiar/asn1-x509': 2.8.0 + '@peculiar/asn1-x509-attr': 2.8.0 asn1js: 3.0.10 tslib: 2.8.1 - '@peculiar/asn1-rsa@2.7.0': + '@peculiar/asn1-rsa@2.8.0': dependencies: - '@peculiar/asn1-schema': 2.7.0 - '@peculiar/asn1-x509': 2.7.0 + '@peculiar/asn1-schema': 2.8.0 + '@peculiar/asn1-x509': 2.8.0 asn1js: 3.0.10 tslib: 2.8.1 - '@peculiar/asn1-schema@2.7.0': + '@peculiar/asn1-schema@2.8.0': dependencies: '@peculiar/utils': 2.0.3 asn1js: 3.0.10 tslib: 2.8.1 - '@peculiar/asn1-x509-attr@2.7.0': + '@peculiar/asn1-x509-attr@2.8.0': dependencies: - '@peculiar/asn1-schema': 2.7.0 - '@peculiar/asn1-x509': 2.7.0 + '@peculiar/asn1-schema': 2.8.0 + '@peculiar/asn1-x509': 2.8.0 asn1js: 3.0.10 tslib: 2.8.1 - '@peculiar/asn1-x509@2.7.0': + '@peculiar/asn1-x509@2.8.0': dependencies: - '@peculiar/asn1-schema': 2.7.0 + '@peculiar/asn1-schema': 2.8.0 '@peculiar/utils': 2.0.3 asn1js: 3.0.10 tslib: 2.8.1 @@ -14686,13 +14698,13 @@ snapshots: '@peculiar/x509@1.14.3': dependencies: - '@peculiar/asn1-cms': 2.7.0 - '@peculiar/asn1-csr': 2.7.0 - '@peculiar/asn1-ecc': 2.7.0 - '@peculiar/asn1-pkcs9': 2.7.0 - '@peculiar/asn1-rsa': 2.7.0 - '@peculiar/asn1-schema': 2.7.0 - '@peculiar/asn1-x509': 2.7.0 + '@peculiar/asn1-cms': 2.8.0 + '@peculiar/asn1-csr': 2.8.0 + '@peculiar/asn1-ecc': 2.8.0 + '@peculiar/asn1-pkcs9': 2.8.0 + '@peculiar/asn1-rsa': 2.8.0 + '@peculiar/asn1-schema': 2.8.0 + '@peculiar/asn1-x509': 2.8.0 pvtsutils: 1.3.6 reflect-metadata: 0.2.2 tslib: 2.8.1 @@ -14705,9 +14717,9 @@ snapshots: '@pkgr/core@0.3.6': {} - '@playwright/test@1.60.0': + '@playwright/test@1.61.0': dependencies: - playwright: 1.60.0 + playwright: 1.61.0 '@plone-collective/volto-authomatic@3.0.0-alpha.6(@plone/components@core+packages+components)(@plone/registry@core+packages+registry)(react-dom@18.2.0(react@18.2.0))(react-intl@3.12.1(@types/react@18.3.31)(react@18.2.0))(react@18.2.0)(semantic-ui-react@2.1.5(react-dom@18.2.0(react@18.2.0))(react@18.2.0))': dependencies: @@ -14755,9 +14767,9 @@ snapshots: react-aria-components: 1.18.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0) react-stately: 3.47.0(react@18.2.0) tailwind-merge: 3.6.0 - tailwind-variants: 1.0.0(tailwindcss@4.3.0) - tailwindcss: 4.3.0 - tailwindcss-animate: 1.0.7(tailwindcss@4.3.0) + tailwind-variants: 1.0.0(tailwindcss@4.3.1) + tailwindcss: 4.3.1 + tailwindcss-animate: 1.0.7(tailwindcss@4.3.1) optionalDependencies: react-dom: 18.2.0(react@18.2.0) @@ -14798,7 +14810,7 @@ snapshots: transitivePeerDependencies: - storybook - '@pmmmwh/react-refresh-webpack-plugin@0.5.17(react-refresh@0.14.2)(type-fest@4.41.0)(webpack-dev-server@5.2.4(tslib@2.8.1)(webpack@5.105.4(esbuild@0.25.12)))(webpack-hot-middleware@2.26.1)(webpack@5.105.4(esbuild@0.25.12))': + '@pmmmwh/react-refresh-webpack-plugin@0.5.17(react-refresh@0.14.2)(type-fest@4.41.0)(webpack-dev-server@5.2.5(tslib@2.8.1)(webpack@5.105.4(esbuild@0.25.12)))(webpack-hot-middleware@2.26.1)(webpack@5.105.4(esbuild@0.25.12))': dependencies: ansi-html: 0.0.9 core-js-pure: 3.49.0 @@ -14811,7 +14823,7 @@ snapshots: webpack: 5.105.4(esbuild@0.25.12) optionalDependencies: type-fest: 4.41.0 - webpack-dev-server: 5.2.4(tslib@2.8.1)(webpack@5.105.4(esbuild@0.25.12)) + webpack-dev-server: 5.2.5(tslib@2.8.1)(webpack@5.105.4(esbuild@0.25.12)) webpack-hot-middleware: 2.26.1 '@pnpm/config.env-replace@1.1.0': {} @@ -14820,7 +14832,7 @@ snapshots: dependencies: graceful-fs: 4.2.10 - '@pnpm/npm-conf@3.0.2': + '@pnpm/npm-conf@3.0.3': dependencies: '@pnpm/config.env-replace': 1.1.0 '@pnpm/network.ca-file': 1.0.2 @@ -14860,87 +14872,87 @@ snapshots: '@rolldown/pluginutils@1.0.0-rc.3': {} - '@rollup/pluginutils@5.4.0(rollup@4.61.1)': + '@rollup/pluginutils@5.4.0(rollup@4.62.0)': dependencies: '@types/estree': 1.0.9 estree-walker: 2.0.2 picomatch: 4.0.4 optionalDependencies: - rollup: 4.61.1 + rollup: 4.62.0 - '@rollup/rollup-android-arm-eabi@4.61.1': + '@rollup/rollup-android-arm-eabi@4.62.0': optional: true - '@rollup/rollup-android-arm64@4.61.1': + '@rollup/rollup-android-arm64@4.62.0': optional: true - '@rollup/rollup-darwin-arm64@4.61.1': + '@rollup/rollup-darwin-arm64@4.62.0': optional: true - '@rollup/rollup-darwin-x64@4.61.1': + '@rollup/rollup-darwin-x64@4.62.0': optional: true - '@rollup/rollup-freebsd-arm64@4.61.1': + '@rollup/rollup-freebsd-arm64@4.62.0': optional: true - '@rollup/rollup-freebsd-x64@4.61.1': + '@rollup/rollup-freebsd-x64@4.62.0': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.61.1': + '@rollup/rollup-linux-arm-gnueabihf@4.62.0': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.61.1': + '@rollup/rollup-linux-arm-musleabihf@4.62.0': optional: true - '@rollup/rollup-linux-arm64-gnu@4.61.1': + '@rollup/rollup-linux-arm64-gnu@4.62.0': optional: true - '@rollup/rollup-linux-arm64-musl@4.61.1': + '@rollup/rollup-linux-arm64-musl@4.62.0': optional: true - '@rollup/rollup-linux-loong64-gnu@4.61.1': + '@rollup/rollup-linux-loong64-gnu@4.62.0': optional: true - '@rollup/rollup-linux-loong64-musl@4.61.1': + '@rollup/rollup-linux-loong64-musl@4.62.0': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.61.1': + '@rollup/rollup-linux-ppc64-gnu@4.62.0': optional: true - '@rollup/rollup-linux-ppc64-musl@4.61.1': + '@rollup/rollup-linux-ppc64-musl@4.62.0': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.61.1': + '@rollup/rollup-linux-riscv64-gnu@4.62.0': optional: true - '@rollup/rollup-linux-riscv64-musl@4.61.1': + '@rollup/rollup-linux-riscv64-musl@4.62.0': optional: true - '@rollup/rollup-linux-s390x-gnu@4.61.1': + '@rollup/rollup-linux-s390x-gnu@4.62.0': optional: true - '@rollup/rollup-linux-x64-gnu@4.61.1': + '@rollup/rollup-linux-x64-gnu@4.62.0': optional: true - '@rollup/rollup-linux-x64-musl@4.61.1': + '@rollup/rollup-linux-x64-musl@4.62.0': optional: true - '@rollup/rollup-openbsd-x64@4.61.1': + '@rollup/rollup-openbsd-x64@4.62.0': optional: true - '@rollup/rollup-openharmony-arm64@4.61.1': + '@rollup/rollup-openharmony-arm64@4.62.0': optional: true - '@rollup/rollup-win32-arm64-msvc@4.61.1': + '@rollup/rollup-win32-arm64-msvc@4.62.0': optional: true - '@rollup/rollup-win32-ia32-msvc@4.61.1': + '@rollup/rollup-win32-ia32-msvc@4.62.0': optional: true - '@rollup/rollup-win32-x64-gnu@4.61.1': + '@rollup/rollup-win32-x64-gnu@4.62.0': optional: true - '@rollup/rollup-win32-x64-msvc@4.61.1': + '@rollup/rollup-win32-x64-msvc@4.62.0': optional: true '@rtsao/scc@1.1.0': {} @@ -15142,7 +15154,7 @@ snapshots: react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - '@storybook/builder-webpack5@8.6.18(esbuild@0.25.12)(lightningcss@1.32.0)(postcss@8.5.15)(storybook@8.6.18(prettier@3.2.5))(typescript@5.9.3)': + '@storybook/builder-webpack5@8.6.18(esbuild@0.25.12)(storybook@8.6.18(prettier@3.2.5))(typescript@5.9.3)': dependencies: '@storybook/core-webpack': 8.6.18(storybook@8.6.18(prettier@3.2.5)) '@types/semver': 7.7.1 @@ -15150,40 +15162,31 @@ snapshots: case-sensitive-paths-webpack-plugin: 2.4.0 cjs-module-lexer: 1.4.3 constants-browserify: 1.0.0 - css-loader: 6.11.0(webpack@5.107.2(esbuild@0.25.12)(lightningcss@1.32.0)(postcss@8.5.15)) + css-loader: 6.11.0(webpack@5.105.4(esbuild@0.25.12)) es-module-lexer: 1.7.0 - fork-ts-checker-webpack-plugin: 8.0.0(typescript@5.9.3)(webpack@5.107.2(esbuild@0.25.12)(lightningcss@1.32.0)(postcss@8.5.15)) - html-webpack-plugin: 5.6.7(webpack@5.107.2(esbuild@0.25.12)(lightningcss@1.32.0)(postcss@8.5.15)) + fork-ts-checker-webpack-plugin: 8.0.0(typescript@5.9.3)(webpack@5.105.4(esbuild@0.25.12)) + html-webpack-plugin: 5.6.7(webpack@5.105.4(esbuild@0.25.12)) magic-string: 0.30.21 path-browserify: 1.0.1 process: 0.11.10 semver: 7.8.4 storybook: 8.6.18(prettier@3.2.5) - style-loader: 3.3.1(webpack@5.107.2(esbuild@0.25.12)(lightningcss@1.32.0)(postcss@8.5.15)) - terser-webpack-plugin: 5.4.0(esbuild@0.25.12)(webpack@5.107.2(esbuild@0.25.12)(lightningcss@1.32.0)(postcss@8.5.15)) + style-loader: 3.3.1(webpack@5.105.4(esbuild@0.25.12)) + terser-webpack-plugin: 5.4.0(esbuild@0.25.12)(webpack@5.105.4(esbuild@0.25.12)) ts-dedent: 2.3.0 url: 0.11.4 util: 0.12.5 util-deprecate: 1.0.2 - webpack: 5.107.2(esbuild@0.25.12)(lightningcss@1.32.0)(postcss@8.5.15) - webpack-dev-middleware: 6.1.3(webpack@5.107.2(esbuild@0.25.12)(lightningcss@1.32.0)(postcss@8.5.15)) + webpack: 5.105.4(esbuild@0.25.12) + webpack-dev-middleware: 6.1.3(webpack@5.105.4(esbuild@0.25.12)) webpack-hot-middleware: 2.26.1 webpack-virtual-modules: 0.6.2 optionalDependencies: typescript: 5.9.3 transitivePeerDependencies: - - '@minify-html/node' - '@rspack/core' - '@swc/core' - - '@swc/css' - - '@swc/html' - - clean-css - - cssnano - - csso - esbuild - - html-minifier-terser - - lightningcss - - postcss - uglify-js - webpack-cli @@ -15244,11 +15247,11 @@ snapshots: dependencies: storybook: 8.6.18(prettier@3.2.5) - '@storybook/preset-react-webpack@8.6.18(@storybook/test@8.6.15(storybook@8.6.18(prettier@3.2.5)))(esbuild@0.25.12)(lightningcss@1.32.0)(postcss@8.5.15)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(storybook@8.6.18(prettier@3.2.5))(typescript@5.9.3)': + '@storybook/preset-react-webpack@8.6.18(@storybook/test@8.6.15(storybook@8.6.18(prettier@3.2.5)))(esbuild@0.25.12)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(storybook@8.6.18(prettier@3.2.5))(typescript@5.9.3)': dependencies: '@storybook/core-webpack': 8.6.18(storybook@8.6.18(prettier@3.2.5)) '@storybook/react': 8.6.18(@storybook/test@8.6.15(storybook@8.6.18(prettier@3.2.5)))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(storybook@8.6.18(prettier@3.2.5))(typescript@5.9.3) - '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.9.3)(webpack@5.107.2(esbuild@0.25.12)(lightningcss@1.32.0)(postcss@8.5.15)) + '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.9.3)(webpack@5.105.4(esbuild@0.25.12)) '@types/semver': 7.7.1 find-up: 5.0.0 magic-string: 0.30.21 @@ -15259,22 +15262,13 @@ snapshots: semver: 7.8.4 storybook: 8.6.18(prettier@3.2.5) tsconfig-paths: 4.2.0 - webpack: 5.107.2(esbuild@0.25.12)(lightningcss@1.32.0)(postcss@8.5.15) + webpack: 5.105.4(esbuild@0.25.12) optionalDependencies: typescript: 5.9.3 transitivePeerDependencies: - - '@minify-html/node' - '@storybook/test' - '@swc/core' - - '@swc/css' - - '@swc/html' - - clean-css - - cssnano - - csso - esbuild - - html-minifier-terser - - lightningcss - - postcss - supports-color - uglify-js - webpack-cli @@ -15283,7 +15277,7 @@ snapshots: dependencies: storybook: 8.6.18(prettier@3.2.5) - '@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0(typescript@5.9.3)(webpack@5.107.2(esbuild@0.25.12)(lightningcss@1.32.0)(postcss@8.5.15))': + '@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0(typescript@5.9.3)(webpack@5.105.4(esbuild@0.25.12))': dependencies: debug: 4.3.4(supports-color@8.1.1) endent: 2.1.0 @@ -15293,7 +15287,7 @@ snapshots: react-docgen-typescript: 2.4.0(typescript@5.9.3) tslib: 2.8.1 typescript: 5.9.3 - webpack: 5.107.2(esbuild@0.25.12)(lightningcss@1.32.0)(postcss@8.5.15) + webpack: 5.105.4(esbuild@0.25.12) transitivePeerDependencies: - supports-color @@ -15309,10 +15303,10 @@ snapshots: react-dom: 18.2.0(react@18.2.0) storybook: 8.6.18(prettier@3.2.5) - '@storybook/react-webpack5@8.6.18(@storybook/test@8.6.15(storybook@8.6.18(prettier@3.2.5)))(esbuild@0.25.12)(lightningcss@1.32.0)(postcss@8.5.15)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(storybook@8.6.18(prettier@3.2.5))(typescript@5.9.3)': + '@storybook/react-webpack5@8.6.18(@storybook/test@8.6.15(storybook@8.6.18(prettier@3.2.5)))(esbuild@0.25.12)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(storybook@8.6.18(prettier@3.2.5))(typescript@5.9.3)': dependencies: - '@storybook/builder-webpack5': 8.6.18(esbuild@0.25.12)(lightningcss@1.32.0)(postcss@8.5.15)(storybook@8.6.18(prettier@3.2.5))(typescript@5.9.3) - '@storybook/preset-react-webpack': 8.6.18(@storybook/test@8.6.15(storybook@8.6.18(prettier@3.2.5)))(esbuild@0.25.12)(lightningcss@1.32.0)(postcss@8.5.15)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(storybook@8.6.18(prettier@3.2.5))(typescript@5.9.3) + '@storybook/builder-webpack5': 8.6.18(esbuild@0.25.12)(storybook@8.6.18(prettier@3.2.5))(typescript@5.9.3) + '@storybook/preset-react-webpack': 8.6.18(@storybook/test@8.6.15(storybook@8.6.18(prettier@3.2.5)))(esbuild@0.25.12)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(storybook@8.6.18(prettier@3.2.5))(typescript@5.9.3) '@storybook/react': 8.6.18(@storybook/test@8.6.15(storybook@8.6.18(prettier@3.2.5)))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(storybook@8.6.18(prettier@3.2.5))(typescript@5.9.3) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) @@ -15320,19 +15314,10 @@ snapshots: optionalDependencies: typescript: 5.9.3 transitivePeerDependencies: - - '@minify-html/node' - '@rspack/core' - '@storybook/test' - '@swc/core' - - '@swc/css' - - '@swc/html' - - clean-css - - cssnano - - csso - esbuild - - html-minifier-terser - - lightningcss - - postcss - supports-color - uglify-js - webpack-cli @@ -15454,73 +15439,73 @@ snapshots: dependencies: tslib: 2.8.1 - '@tailwindcss/node@4.3.0': + '@tailwindcss/node@4.3.1': dependencies: '@jridgewell/remapping': 2.3.5 - enhanced-resolve: 5.23.0 + enhanced-resolve: 5.21.6 jiti: 2.7.0 lightningcss: 1.32.0 magic-string: 0.30.21 source-map-js: 1.2.1 - tailwindcss: 4.3.0 + tailwindcss: 4.3.1 - '@tailwindcss/oxide-android-arm64@4.3.0': + '@tailwindcss/oxide-android-arm64@4.3.1': optional: true - '@tailwindcss/oxide-darwin-arm64@4.3.0': + '@tailwindcss/oxide-darwin-arm64@4.3.1': optional: true - '@tailwindcss/oxide-darwin-x64@4.3.0': + '@tailwindcss/oxide-darwin-x64@4.3.1': optional: true - '@tailwindcss/oxide-freebsd-x64@4.3.0': + '@tailwindcss/oxide-freebsd-x64@4.3.1': optional: true - '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.0': + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.1': optional: true - '@tailwindcss/oxide-linux-arm64-gnu@4.3.0': + '@tailwindcss/oxide-linux-arm64-gnu@4.3.1': optional: true - '@tailwindcss/oxide-linux-arm64-musl@4.3.0': + '@tailwindcss/oxide-linux-arm64-musl@4.3.1': optional: true - '@tailwindcss/oxide-linux-x64-gnu@4.3.0': + '@tailwindcss/oxide-linux-x64-gnu@4.3.1': optional: true - '@tailwindcss/oxide-linux-x64-musl@4.3.0': + '@tailwindcss/oxide-linux-x64-musl@4.3.1': optional: true - '@tailwindcss/oxide-wasm32-wasi@4.3.0': + '@tailwindcss/oxide-wasm32-wasi@4.3.1': optional: true - '@tailwindcss/oxide-win32-arm64-msvc@4.3.0': + '@tailwindcss/oxide-win32-arm64-msvc@4.3.1': optional: true - '@tailwindcss/oxide-win32-x64-msvc@4.3.0': + '@tailwindcss/oxide-win32-x64-msvc@4.3.1': optional: true - '@tailwindcss/oxide@4.3.0': + '@tailwindcss/oxide@4.3.1': optionalDependencies: - '@tailwindcss/oxide-android-arm64': 4.3.0 - '@tailwindcss/oxide-darwin-arm64': 4.3.0 - '@tailwindcss/oxide-darwin-x64': 4.3.0 - '@tailwindcss/oxide-freebsd-x64': 4.3.0 - '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.0 - '@tailwindcss/oxide-linux-arm64-gnu': 4.3.0 - '@tailwindcss/oxide-linux-arm64-musl': 4.3.0 - '@tailwindcss/oxide-linux-x64-gnu': 4.3.0 - '@tailwindcss/oxide-linux-x64-musl': 4.3.0 - '@tailwindcss/oxide-wasm32-wasi': 4.3.0 - '@tailwindcss/oxide-win32-arm64-msvc': 4.3.0 - '@tailwindcss/oxide-win32-x64-msvc': 4.3.0 - - '@tailwindcss/vite@4.3.0(vite@6.4.3(@types/node@24.13.1)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0))': - dependencies: - '@tailwindcss/node': 4.3.0 - '@tailwindcss/oxide': 4.3.0 - tailwindcss: 4.3.0 - vite: 6.4.3(@types/node@24.13.1)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) + '@tailwindcss/oxide-android-arm64': 4.3.1 + '@tailwindcss/oxide-darwin-arm64': 4.3.1 + '@tailwindcss/oxide-darwin-x64': 4.3.1 + '@tailwindcss/oxide-freebsd-x64': 4.3.1 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.1 + '@tailwindcss/oxide-linux-arm64-gnu': 4.3.1 + '@tailwindcss/oxide-linux-arm64-musl': 4.3.1 + '@tailwindcss/oxide-linux-x64-gnu': 4.3.1 + '@tailwindcss/oxide-linux-x64-musl': 4.3.1 + '@tailwindcss/oxide-wasm32-wasi': 4.3.1 + '@tailwindcss/oxide-win32-arm64-msvc': 4.3.1 + '@tailwindcss/oxide-win32-x64-msvc': 4.3.1 + + '@tailwindcss/vite@4.3.1(vite@6.4.3(@types/node@24.13.2)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0))': + dependencies: + '@tailwindcss/node': 4.3.1 + '@tailwindcss/oxide': 4.3.1 + tailwindcss: 4.3.1 + vite: 6.4.3(@types/node@24.13.2)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) '@testing-library/cypress@10.0.3(cypress@15.16.0)': dependencies: @@ -15563,7 +15548,7 @@ snapshots: chalk: 3.0.0 css.escape: 1.5.1 dom-accessibility-api: 0.6.3 - lodash: 4.17.21 + lodash: 4.18.1 redent: 3.0.0 '@testing-library/jest-dom@6.9.1': @@ -15632,11 +15617,11 @@ snapshots: '@types/body-parser@1.19.6': dependencies: '@types/connect': 3.4.38 - '@types/node': 24.13.1 + '@types/node': 24.13.2 '@types/bonjour@3.5.13': dependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 '@types/chai@5.2.3': dependencies: @@ -15646,11 +15631,11 @@ snapshots: '@types/connect-history-api-fallback@1.5.4': dependencies: '@types/express-serve-static-core': 4.19.8 - '@types/node': 24.13.1 + '@types/node': 24.13.2 '@types/connect@3.4.38': dependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 '@types/debug@4.1.13': dependencies: @@ -15674,7 +15659,7 @@ snapshots: '@types/express-serve-static-core@4.19.8': dependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 '@types/qs': 6.15.1 '@types/range-parser': 1.2.7 '@types/send': 1.2.1 @@ -15689,7 +15674,7 @@ snapshots: '@types/glob@8.1.0': dependencies: '@types/minimatch': 5.1.2 - '@types/node': 24.13.1 + '@types/node': 24.13.2 '@types/history@4.7.11': {} @@ -15704,7 +15689,7 @@ snapshots: '@types/http-proxy@1.17.17': dependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 '@types/invariant@2.2.37': {} @@ -15746,11 +15731,11 @@ snapshots: '@types/ms@2.1.0': {} - '@types/node@22.19.20': + '@types/node@22.19.21': dependencies: undici-types: 6.21.0 - '@types/node@24.13.1': + '@types/node@24.13.2': dependencies: undici-types: 7.18.2 @@ -15821,11 +15806,11 @@ snapshots: '@types/send@0.17.6': dependencies: '@types/mime': 1.3.5 - '@types/node': 24.13.1 + '@types/node': 24.13.2 '@types/send@1.2.1': dependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 '@types/serve-index@1.9.4': dependencies: @@ -15834,7 +15819,7 @@ snapshots: '@types/serve-static@1.15.10': dependencies: '@types/http-errors': 2.0.5 - '@types/node': 24.13.1 + '@types/node': 24.13.2 '@types/send': 0.17.6 '@types/sinonjs__fake-timers@8.1.1': {} @@ -15843,7 +15828,7 @@ snapshots: '@types/sockjs@0.3.36': dependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 '@types/stack-utils@2.0.3': {} @@ -15855,7 +15840,7 @@ snapshots: '@types/ws@8.18.1': dependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 '@types/yargs-parser@21.0.3': {} @@ -16112,7 +16097,7 @@ snapshots: '@unrs/resolver-binding-win32-x64-msvc@1.12.2': optional: true - '@vitejs/plugin-react@4.7.0(vite@6.4.3(@types/node@24.13.1)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0))': + '@vitejs/plugin-react@4.7.0(vite@6.4.3(@types/node@24.13.2)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0))': dependencies: '@babel/core': 7.29.7 '@babel/plugin-transform-react-jsx-self': 7.29.7(@babel/core@7.29.7) @@ -16120,11 +16105,11 @@ snapshots: '@rolldown/pluginutils': 1.0.0-beta.27 '@types/babel__core': 7.20.5 react-refresh: 0.14.2 - vite: 6.4.3(@types/node@24.13.1)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) + vite: 6.4.3(@types/node@24.13.2)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) transitivePeerDependencies: - supports-color - '@vitejs/plugin-react@5.2.0(vite@6.4.3(@types/node@24.13.1)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0))': + '@vitejs/plugin-react@5.2.0(vite@6.4.3(@types/node@24.13.2)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0))': dependencies: '@babel/core': 7.29.7 '@babel/plugin-transform-react-jsx-self': 7.29.7(@babel/core@7.29.7) @@ -16132,7 +16117,7 @@ snapshots: '@rolldown/pluginutils': 1.0.0-rc.3 '@types/babel__core': 7.20.5 react-refresh: 0.14.2 - vite: 6.4.3(@types/node@24.13.1)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) + vite: 6.4.3(@types/node@24.13.2)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) transitivePeerDependencies: - supports-color @@ -16151,7 +16136,7 @@ snapshots: std-env: 3.10.0 test-exclude: 7.0.2 tinyrainbow: 2.0.0 - vitest: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.1)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) + vitest: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.2)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) transitivePeerDependencies: - supports-color @@ -16170,21 +16155,21 @@ snapshots: chai: 5.3.3 tinyrainbow: 2.0.0 - '@vitest/mocker@3.2.6(vite@6.4.3(@types/node@22.19.20)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0))': + '@vitest/mocker@3.2.6(vite@6.4.3(@types/node@22.19.21)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0))': dependencies: '@vitest/spy': 3.2.6 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 6.4.3(@types/node@22.19.20)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) + vite: 6.4.3(@types/node@22.19.21)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) - '@vitest/mocker@3.2.6(vite@6.4.3(@types/node@24.13.1)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0))': + '@vitest/mocker@3.2.6(vite@6.4.3(@types/node@24.13.2)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0))': dependencies: '@vitest/spy': 3.2.6 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 6.4.3(@types/node@24.13.1)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) + vite: 6.4.3(@types/node@24.13.2)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) '@vitest/pretty-format@2.0.5': dependencies: @@ -16227,7 +16212,7 @@ snapshots: sirv: 3.0.2 tinyglobby: 0.2.17 tinyrainbow: 2.0.0 - vitest: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.1)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) + vitest: 3.2.6(@types/debug@4.1.13)(@types/node@24.13.2)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) '@vitest/utils@2.0.5': dependencies: @@ -16333,19 +16318,19 @@ snapshots: mime-types: 2.1.35 negotiator: 0.6.3 - acorn-import-phases@1.0.4(acorn@8.16.0): + acorn-import-phases@1.0.4(acorn@8.17.0): dependencies: - acorn: 8.16.0 + acorn: 8.17.0 - acorn-jsx@5.3.2(acorn@8.16.0): + acorn-jsx@5.3.2(acorn@8.17.0): dependencies: - acorn: 8.16.0 + acorn: 8.17.0 acorn-walk@8.3.5: dependencies: - acorn: 8.16.0 + acorn: 8.17.0 - acorn@8.16.0: {} + acorn@8.17.0: {} add-dom-event-listener@1.1.0: dependencies: @@ -16375,7 +16360,7 @@ snapshots: airbnb-prop-types@2.16.0(react@18.2.0): dependencies: array.prototype.find: 2.2.3 - function.prototype.name: 1.1.8 + function.prototype.name: 1.2.0 is-regex: 1.2.1 object-is: 1.1.6 object.assign: 4.1.7 @@ -16616,7 +16601,7 @@ snapshots: autoprefixer@10.4.8(postcss@8.5.15): dependencies: browserslist: 4.28.2 - caniuse-lite: 1.0.30001797 + caniuse-lite: 1.0.30001799 fraction.js: 4.3.7 normalize-range: 0.1.2 picocolors: 1.1.1 @@ -16633,36 +16618,36 @@ snapshots: axe-core@3.5.6: {} - axe-core@4.12.0: {} + axe-core@4.12.1: {} axe-core@4.4.2: {} axe-core@4.7.2: {} - axios@1.17.0: + axios@1.18.0: dependencies: follow-redirects: 1.16.0(debug@4.4.3) - form-data: 4.0.5 + form-data: 4.0.6 https-proxy-agent: 5.0.1 proxy-from-env: 2.1.0 transitivePeerDependencies: - debug - supports-color - axios@1.17.0(debug@4.3.4): + axios@1.18.0(debug@4.3.4): dependencies: follow-redirects: 1.16.0(debug@4.3.4) - form-data: 4.0.5 + form-data: 4.0.6 https-proxy-agent: 5.0.1 proxy-from-env: 2.1.0 transitivePeerDependencies: - debug - supports-color - axios@1.17.0(debug@4.4.3): + axios@1.18.0(debug@4.4.3): dependencies: follow-redirects: 1.16.0(debug@4.4.3) - form-data: 4.0.5 + form-data: 4.0.6 https-proxy-agent: 5.0.1 proxy-from-env: 2.1.0 transitivePeerDependencies: @@ -16701,7 +16686,7 @@ snapshots: '@babel/helper-module-imports': 7.29.7 '@babel/types': 7.20.5 glob: 7.2.3 - lodash: 4.17.21 + lodash: 4.18.1 require-package-name: 2.0.1 transitivePeerDependencies: - supports-color @@ -16822,7 +16807,7 @@ snapshots: base64-js@1.5.1: {} - baseline-browser-mapping@2.10.35: {} + baseline-browser-mapping@2.10.38: {} basic-ftp@5.3.1: {} @@ -16916,10 +16901,10 @@ snapshots: browserslist@4.28.2: dependencies: - baseline-browser-mapping: 2.10.35 - caniuse-lite: 1.0.30001797 - electron-to-chromium: 1.5.371 - node-releases: 2.0.47 + baseline-browser-mapping: 2.10.38 + caniuse-lite: 1.0.30001799 + electron-to-chromium: 1.5.375 + node-releases: 2.0.48 update-browserslist-db: 1.2.3(browserslist@4.28.2) buffer-equal-constant-time@1.0.1: {} @@ -17009,11 +16994,11 @@ snapshots: caniuse-api@3.0.0: dependencies: browserslist: 4.28.2 - caniuse-lite: 1.0.30001797 + caniuse-lite: 1.0.30001799 lodash.memoize: 4.1.2 lodash.uniq: 4.5.0 - caniuse-lite@1.0.30001797: {} + caniuse-lite@1.0.30001799: {} case-sensitive-paths-webpack-plugin@2.4.0: {} @@ -17401,7 +17386,7 @@ snapshots: semver: 7.8.4 webpack: 5.105.4(esbuild@0.25.12) - css-loader@6.11.0(webpack@5.107.2(esbuild@0.25.12)(lightningcss@1.32.0)(postcss@8.5.15)): + css-loader@6.11.0(webpack@5.105.4(esbuild@0.25.12)): dependencies: icss-utils: 5.1.0(postcss@8.5.15) postcss: 8.5.15 @@ -17412,7 +17397,7 @@ snapshots: postcss-value-parser: 4.2.0 semver: 7.8.4 optionalDependencies: - webpack: 5.107.2(esbuild@0.25.12)(lightningcss@1.32.0)(postcss@8.5.15) + webpack: 5.105.4(esbuild@0.25.12) css-minimizer-webpack-plugin@8.0.0(clean-css@5.3.3)(esbuild@0.25.12)(lightningcss@1.32.0)(webpack@5.105.4(esbuild@0.25.12)): dependencies: @@ -17862,7 +17847,7 @@ snapshots: ee-first@1.1.1: {} - electron-to-chromium@1.5.371: {} + electron-to-chromium@1.5.375: {} embla-carousel-autoplay@8.5.2(embla-carousel@8.5.2): dependencies: @@ -17902,7 +17887,12 @@ snapshots: fast-json-parse: 1.0.3 objectorarray: 1.0.5 - enhanced-resolve@5.23.0: + enhanced-resolve@5.21.6: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.3.3 + + enhanced-resolve@5.24.0: dependencies: graceful-fs: 4.2.11 tapable: 2.3.3 @@ -17937,6 +17927,13 @@ snapshots: dependencies: stackframe: 1.3.4 + es-abstract-get@1.0.0: + dependencies: + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + is-callable: 1.2.7 + object-inspect: 1.13.4 + es-abstract@1.24.2: dependencies: array-buffer-byte-length: 1.0.2 @@ -17951,8 +17948,8 @@ snapshots: es-errors: 1.3.0 es-object-atoms: 1.1.2 es-set-tostringtag: 2.1.0 - es-to-primitive: 1.3.0 - function.prototype.name: 1.1.8 + es-to-primitive: 1.3.1 + function.prototype.name: 1.2.0 get-intrinsic: 1.3.0 get-proto: 1.0.1 get-symbol-description: 1.1.0 @@ -18036,8 +18033,10 @@ snapshots: dependencies: hasown: 2.0.4 - es-to-primitive@1.3.0: + es-to-primitive@1.3.1: dependencies: + es-abstract-get: 1.0.0 + es-errors: 1.3.0 is-callable: 1.2.7 is-date-object: 1.1.0 is-symbol: 1.1.1 @@ -18214,7 +18213,7 @@ snapshots: '@babel/plugin-syntax-flow': 7.29.7(@babel/core@7.29.7) '@babel/plugin-transform-react-jsx': 7.29.7(@babel/core@7.29.7) eslint: 8.57.1 - lodash: 4.17.21 + lodash: 4.18.1 string-natural-compare: 3.0.1 eslint-plugin-import@2.32.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1): @@ -18291,7 +18290,7 @@ snapshots: array-includes: 3.1.9 array.prototype.flatmap: 1.3.3 ast-types-flow: 0.0.8 - axe-core: 4.12.0 + axe-core: 4.12.1 axobject-query: 4.1.0 damerau-levenshtein: 1.0.8 emoji-regex: 9.2.2 @@ -18409,8 +18408,8 @@ snapshots: espree@9.6.1: dependencies: - acorn: 8.16.0 - acorn-jsx: 5.3.2(acorn@8.16.0) + acorn: 8.17.0 + acorn-jsx: 5.3.2(acorn@8.17.0) eslint-visitor-keys: 3.4.3 esprima@4.0.1: {} @@ -18720,7 +18719,7 @@ snapshots: dependencies: magic-string: 0.30.21 mlly: 1.8.2 - rollup: 4.61.1 + rollup: 4.62.0 flat-cache@3.2.0: dependencies: @@ -18795,7 +18794,7 @@ snapshots: optionalDependencies: eslint: 8.57.1 - fork-ts-checker-webpack-plugin@8.0.0(typescript@5.9.3)(webpack@5.107.2(esbuild@0.25.12)(lightningcss@1.32.0)(postcss@8.5.15)): + fork-ts-checker-webpack-plugin@8.0.0(typescript@5.9.3)(webpack@5.105.4(esbuild@0.25.12)): dependencies: '@babel/code-frame': 7.29.7 chalk: 4.1.2 @@ -18810,9 +18809,9 @@ snapshots: semver: 7.8.4 tapable: 2.3.3 typescript: 5.9.3 - webpack: 5.107.2(esbuild@0.25.12)(lightningcss@1.32.0)(postcss@8.5.15) + webpack: 5.105.4(esbuild@0.25.12) - form-data@4.0.5: + form-data@4.0.6: dependencies: asynckit: 0.4.0 combined-stream: 1.0.8 @@ -18865,14 +18864,17 @@ snapshots: function-bind@1.1.2: {} - function.prototype.name@1.1.8: + function.prototype.name@1.2.0: dependencies: call-bind: 1.0.9 call-bound: 1.0.4 - define-properties: 1.2.1 + es-define-property: 1.0.1 + es-errors: 1.3.0 functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 hasown: 2.0.4 is-callable: 1.2.7 + is-document.all: 1.0.0 functions-have-names@1.2.3: {} @@ -18951,7 +18953,7 @@ snapshots: consola: 3.4.2 defu: 6.1.7 node-fetch-native: 1.6.7 - nypm: 0.6.6 + nypm: 0.6.7 pathe: 2.0.3 git-up@7.0.0: @@ -19165,22 +19167,12 @@ snapshots: dependencies: '@types/html-minifier-terser': 6.1.0 html-minifier-terser: 6.1.0 - lodash: 4.17.21 + lodash: 4.18.1 pretty-error: 4.0.0 tapable: 2.3.3 optionalDependencies: webpack: 5.105.4(esbuild@0.25.12) - html-webpack-plugin@5.6.7(webpack@5.107.2(esbuild@0.25.12)(lightningcss@1.32.0)(postcss@8.5.15)): - dependencies: - '@types/html-minifier-terser': 6.1.0 - html-minifier-terser: 6.1.0 - lodash: 4.17.21 - pretty-error: 4.0.0 - tapable: 2.3.3 - optionalDependencies: - webpack: 5.107.2(esbuild@0.25.12)(lightningcss@1.32.0)(postcss@8.5.15) - htmlparser2@6.1.0: dependencies: domelementtype: 2.3.0 @@ -19356,29 +19348,29 @@ snapshots: ini@5.0.0: {} - inquirer@12.11.1(@types/node@22.19.20): + inquirer@12.11.1(@types/node@22.19.21): dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@22.19.20) - '@inquirer/prompts': 7.10.1(@types/node@22.19.20) - '@inquirer/type': 3.0.10(@types/node@22.19.20) + '@inquirer/core': 10.3.2(@types/node@22.19.21) + '@inquirer/prompts': 7.10.1(@types/node@22.19.21) + '@inquirer/type': 3.0.10(@types/node@22.19.21) mute-stream: 2.0.0 run-async: 4.0.6 rxjs: 7.8.2 optionalDependencies: - '@types/node': 22.19.20 + '@types/node': 22.19.21 - inquirer@12.11.1(@types/node@24.13.1): + inquirer@12.11.1(@types/node@24.13.2): dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@24.13.1) - '@inquirer/prompts': 7.10.1(@types/node@24.13.1) - '@inquirer/type': 3.0.10(@types/node@24.13.1) + '@inquirer/core': 10.3.2(@types/node@24.13.2) + '@inquirer/prompts': 7.10.1(@types/node@24.13.2) + '@inquirer/type': 3.0.10(@types/node@24.13.2) mute-stream: 2.0.0 run-async: 4.0.6 rxjs: 7.8.2 optionalDependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 inquirer@9.3.2: dependencies: @@ -19479,6 +19471,10 @@ snapshots: is-docker@3.0.0: {} + is-document.all@1.0.0: + dependencies: + call-bound: 1.0.4 + is-extglob@2.1.1: {} is-finalizationregistry@1.1.1: @@ -19740,7 +19736,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 22.19.20 + '@types/node': 22.19.21 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -19749,7 +19745,7 @@ snapshots: jest-util@30.4.1: dependencies: '@jest/types': 30.4.1 - '@types/node': 24.13.1 + '@types/node': 24.13.2 chalk: 4.1.2 ci-info: 4.4.0 graceful-fs: 4.2.11 @@ -19757,13 +19753,13 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 merge-stream: 2.0.0 supports-color: 8.1.1 jest-worker@30.4.1: dependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 '@ungap/structured-clone': 1.3.1 jest-util: 30.4.1 merge-stream: 2.0.0 @@ -19773,13 +19769,13 @@ snapshots: jiti@2.7.0: {} - joi@18.2.1: + joi@18.2.3: dependencies: '@hapi/address': 5.1.1 '@hapi/formula': 3.0.2 '@hapi/hoek': 11.0.7 '@hapi/pinpoint': 2.0.1 - '@hapi/tlds': 1.1.6 + '@hapi/tlds': 1.1.7 '@hapi/topo': 6.0.2 '@standard-schema/spec': 1.1.0 @@ -19823,7 +19819,7 @@ snapshots: saxes: 6.0.0 symbol-tree: 3.2.4 tough-cookie: 6.0.1 - undici: 7.27.2 + undici: 7.28.0 w3c-xmlserializer: 5.0.0 webidl-conversions: 8.0.1 whatwg-mimetype: 5.0.0 @@ -19859,7 +19855,7 @@ snapshots: jsonc-eslint-parser@2.4.2: dependencies: - acorn: 8.16.0 + acorn: 8.17.0 eslint-visitor-keys: 3.4.3 espree: 9.6.1 semver: 7.8.4 @@ -19877,7 +19873,7 @@ snapshots: jsonwebtoken@9.0.0: dependencies: jws: 3.2.3 - lodash: 4.17.21 + lodash: 4.18.1 ms: 2.1.3 semver: 7.8.4 @@ -20121,11 +20117,11 @@ snapshots: lodash-move@1.1.1: dependencies: - lodash: 4.17.21 + lodash: 4.18.1 lodash-webpack-plugin@0.11.6(webpack@5.105.4(esbuild@0.25.12)): dependencies: - lodash: 4.17.21 + lodash: 4.18.1 webpack: 5.105.4(esbuild@0.25.12) lodash.capitalize@4.2.1: {} @@ -20262,16 +20258,16 @@ snapshots: dependencies: fs-monkey: 1.1.0 - memfs@4.57.6(tslib@2.8.1): + memfs@4.57.7(tslib@2.8.1): dependencies: - '@jsonjoy.com/fs-core': 4.57.6(tslib@2.8.1) - '@jsonjoy.com/fs-fsa': 4.57.6(tslib@2.8.1) - '@jsonjoy.com/fs-node': 4.57.6(tslib@2.8.1) - '@jsonjoy.com/fs-node-builtins': 4.57.6(tslib@2.8.1) - '@jsonjoy.com/fs-node-to-fsa': 4.57.6(tslib@2.8.1) - '@jsonjoy.com/fs-node-utils': 4.57.6(tslib@2.8.1) - '@jsonjoy.com/fs-print': 4.57.6(tslib@2.8.1) - '@jsonjoy.com/fs-snapshot': 4.57.6(tslib@2.8.1) + '@jsonjoy.com/fs-core': 4.57.7(tslib@2.8.1) + '@jsonjoy.com/fs-fsa': 4.57.7(tslib@2.8.1) + '@jsonjoy.com/fs-node': 4.57.7(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.57.7(tslib@2.8.1) + '@jsonjoy.com/fs-node-to-fsa': 4.57.7(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.7(tslib@2.8.1) + '@jsonjoy.com/fs-print': 4.57.7(tslib@2.8.1) + '@jsonjoy.com/fs-snapshot': 4.57.7(tslib@2.8.1) '@jsonjoy.com/json-pack': 1.21.0(tslib@2.8.1) '@jsonjoy.com/util': 1.9.0(tslib@2.8.1) glob-to-regex.js: 1.2.0(tslib@2.8.1) @@ -20359,7 +20355,7 @@ snapshots: mlly@1.8.2: dependencies: - acorn: 8.16.0 + acorn: 8.17.0 pathe: 2.0.3 pkg-types: 1.3.1 ufo: 1.6.4 @@ -20453,7 +20449,7 @@ snapshots: node-fetch-native@1.6.7: {} - node-releases@2.0.47: {} + node-releases@2.0.48: {} normalize-path@3.0.0: {} @@ -20482,7 +20478,7 @@ snapshots: schema-utils: 3.3.0 webpack: 5.105.4(esbuild@0.25.12) - nypm@0.6.6: + nypm@0.6.7: dependencies: citty: 0.2.2 pathe: 2.0.3 @@ -20757,7 +20753,7 @@ snapshots: ky: 1.14.3 registry-auth-token: 5.1.1 registry-url: 6.0.1 - semver: 7.8.4 + semver: 7.6.3 param-case@3.0.4: dependencies: @@ -20900,11 +20896,11 @@ snapshots: pvutils: 1.1.5 tslib: 2.8.1 - playwright-core@1.60.0: {} + playwright-core@1.61.0: {} - playwright@1.60.0: + playwright@1.61.0: dependencies: - playwright-core: 1.60.0 + playwright-core: 1.61.0 optionalDependencies: fsevents: 2.3.2 @@ -20925,7 +20921,7 @@ snapshots: postcss-calc@10.1.1(postcss@8.5.15): dependencies: postcss: 8.5.15 - postcss-selector-parser: 7.1.2 + postcss-selector-parser: 7.1.4 postcss-value-parser: 4.2.0 postcss-colormin@7.0.10(postcss@8.5.15): @@ -20945,7 +20941,7 @@ snapshots: postcss-discard-comments@7.0.8(postcss@8.5.15): dependencies: postcss: 8.5.15 - postcss-selector-parser: 7.1.2 + postcss-selector-parser: 7.1.4 postcss-discard-duplicates@7.0.4(postcss@8.5.15): dependencies: @@ -20998,7 +20994,7 @@ snapshots: caniuse-api: 3.0.0 cssnano-utils: 5.0.3(postcss@8.5.15) postcss: 8.5.15 - postcss-selector-parser: 7.1.2 + postcss-selector-parser: 7.1.4 postcss-minify-font-values@7.0.3(postcss@8.5.15): dependencies: @@ -21025,7 +21021,7 @@ snapshots: caniuse-api: 3.0.0 cssesc: 3.0.0 postcss: 8.5.15 - postcss-selector-parser: 7.1.2 + postcss-selector-parser: 7.1.4 postcss-modules-extract-imports@3.1.0(postcss@8.5.15): dependencies: @@ -21035,13 +21031,13 @@ snapshots: dependencies: icss-utils: 5.1.0(postcss@8.5.15) postcss: 8.5.15 - postcss-selector-parser: 7.1.2 + postcss-selector-parser: 7.1.4 postcss-value-parser: 4.2.0 postcss-modules-scope@3.2.1(postcss@8.5.15): dependencies: postcss: 8.5.15 - postcss-selector-parser: 7.1.2 + postcss-selector-parser: 7.1.4 postcss-modules-values@4.0.0(postcss@8.5.15): dependencies: @@ -21120,7 +21116,7 @@ snapshots: dependencies: postcss: 8.5.15 - postcss-selector-parser@7.1.2: + postcss-selector-parser@7.1.4: dependencies: cssesc: 3.0.0 util-deprecate: 1.0.2 @@ -21138,7 +21134,7 @@ snapshots: postcss-unique-selectors@7.0.7(postcss@8.5.15): dependencies: postcss: 8.5.15 - postcss-selector-parser: 7.1.2 + postcss-selector-parser: 7.1.4 postcss-value-parser@4.2.0: {} @@ -21168,7 +21164,7 @@ snapshots: pretty-error@4.0.0: dependencies: - lodash: 4.17.21 + lodash: 4.18.1 renderkid: 3.0.0 pretty-format@26.6.2: @@ -21498,7 +21494,7 @@ snapshots: consolidated-events: 2.0.2 enzyme-shallow-equal: 1.0.7 is-touch-device: 1.0.1 - lodash: 4.17.21 + lodash: 4.18.1 moment: 2.29.4 object.assign: 4.1.7 object.values: 1.2.1 @@ -22043,13 +22039,13 @@ snapshots: regenerate: 1.4.2 regenerate-unicode-properties: 10.2.2 regjsgen: 0.8.0 - regjsparser: 0.13.1 + regjsparser: 0.13.2 unicode-match-property-ecmascript: 2.0.0 unicode-match-property-value-ecmascript: 2.2.1 registry-auth-token@5.1.1: dependencies: - '@pnpm/npm-conf': 3.0.2 + '@pnpm/npm-conf': 3.0.3 registry-url@6.0.1: dependencies: @@ -22057,7 +22053,7 @@ snapshots: regjsgen@0.8.0: {} - regjsparser@0.13.1: + regjsparser@0.13.2: dependencies: jsesc: 3.1.0 @@ -22093,7 +22089,7 @@ snapshots: - supports-color - typescript - release-it@19.2.4(@types/node@22.19.20)(magicast@0.3.5): + release-it@19.2.4(@types/node@22.19.21)(magicast@0.3.5): dependencies: '@nodeutils/defaults-deep': 1.1.0 '@octokit/rest': 22.0.1 @@ -22103,7 +22099,7 @@ snapshots: ci-info: 4.4.0 eta: 4.5.0 git-url-parse: 16.1.0 - inquirer: 12.11.1(@types/node@22.19.20) + inquirer: 12.11.1(@types/node@22.19.21) issue-parser: 7.0.1 lodash.merge: 4.6.2 mime-types: 3.0.2 @@ -22123,7 +22119,7 @@ snapshots: - magicast - supports-color - release-it@19.2.4(@types/node@24.13.1)(magicast@0.3.5): + release-it@19.2.4(@types/node@24.13.2)(magicast@0.3.5): dependencies: '@nodeutils/defaults-deep': 1.1.0 '@octokit/rest': 22.0.1 @@ -22133,7 +22129,7 @@ snapshots: ci-info: 4.4.0 eta: 4.5.0 git-url-parse: 16.1.0 - inquirer: 12.11.1(@types/node@24.13.1) + inquirer: 12.11.1(@types/node@24.13.2) issue-parser: 7.0.1 lodash.merge: 4.6.2 mime-types: 3.0.2 @@ -22153,9 +22149,9 @@ snapshots: - magicast - supports-color - release-it@20.2.0(@types/node@24.13.1)(magicast@0.3.5): + release-it@20.2.0(@types/node@24.13.2)(magicast@0.3.5): dependencies: - '@inquirer/prompts': 8.4.2(@types/node@24.13.1) + '@inquirer/prompts': 8.4.2(@types/node@24.13.2) '@octokit/rest': 22.0.1 '@phun-ky/typeof': 2.0.3 async-retry: 1.3.3 @@ -22188,7 +22184,7 @@ snapshots: css-select: 4.3.0 dom-converter: 0.2.0 htmlparser2: 6.1.0 - lodash: 4.17.21 + lodash: 4.18.1 strip-ansi: 6.0.1 request-progress@3.0.0: @@ -22255,35 +22251,35 @@ snapshots: dependencies: glob: 7.2.3 - rollup@4.61.1: + rollup@4.62.0: dependencies: '@types/estree': 1.0.9 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.61.1 - '@rollup/rollup-android-arm64': 4.61.1 - '@rollup/rollup-darwin-arm64': 4.61.1 - '@rollup/rollup-darwin-x64': 4.61.1 - '@rollup/rollup-freebsd-arm64': 4.61.1 - '@rollup/rollup-freebsd-x64': 4.61.1 - '@rollup/rollup-linux-arm-gnueabihf': 4.61.1 - '@rollup/rollup-linux-arm-musleabihf': 4.61.1 - '@rollup/rollup-linux-arm64-gnu': 4.61.1 - '@rollup/rollup-linux-arm64-musl': 4.61.1 - '@rollup/rollup-linux-loong64-gnu': 4.61.1 - '@rollup/rollup-linux-loong64-musl': 4.61.1 - '@rollup/rollup-linux-ppc64-gnu': 4.61.1 - '@rollup/rollup-linux-ppc64-musl': 4.61.1 - '@rollup/rollup-linux-riscv64-gnu': 4.61.1 - '@rollup/rollup-linux-riscv64-musl': 4.61.1 - '@rollup/rollup-linux-s390x-gnu': 4.61.1 - '@rollup/rollup-linux-x64-gnu': 4.61.1 - '@rollup/rollup-linux-x64-musl': 4.61.1 - '@rollup/rollup-openbsd-x64': 4.61.1 - '@rollup/rollup-openharmony-arm64': 4.61.1 - '@rollup/rollup-win32-arm64-msvc': 4.61.1 - '@rollup/rollup-win32-ia32-msvc': 4.61.1 - '@rollup/rollup-win32-x64-gnu': 4.61.1 - '@rollup/rollup-win32-x64-msvc': 4.61.1 + '@rollup/rollup-android-arm-eabi': 4.62.0 + '@rollup/rollup-android-arm64': 4.62.0 + '@rollup/rollup-darwin-arm64': 4.62.0 + '@rollup/rollup-darwin-x64': 4.62.0 + '@rollup/rollup-freebsd-arm64': 4.62.0 + '@rollup/rollup-freebsd-x64': 4.62.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.62.0 + '@rollup/rollup-linux-arm-musleabihf': 4.62.0 + '@rollup/rollup-linux-arm64-gnu': 4.62.0 + '@rollup/rollup-linux-arm64-musl': 4.62.0 + '@rollup/rollup-linux-loong64-gnu': 4.62.0 + '@rollup/rollup-linux-loong64-musl': 4.62.0 + '@rollup/rollup-linux-ppc64-gnu': 4.62.0 + '@rollup/rollup-linux-ppc64-musl': 4.62.0 + '@rollup/rollup-linux-riscv64-gnu': 4.62.0 + '@rollup/rollup-linux-riscv64-musl': 4.62.0 + '@rollup/rollup-linux-s390x-gnu': 4.62.0 + '@rollup/rollup-linux-x64-gnu': 4.62.0 + '@rollup/rollup-linux-x64-musl': 4.62.0 + '@rollup/rollup-openbsd-x64': 4.62.0 + '@rollup/rollup-openharmony-arm64': 4.62.0 + '@rollup/rollup-win32-arm64-msvc': 4.62.0 + '@rollup/rollup-win32-ia32-msvc': 4.62.0 + '@rollup/rollup-win32-x64-gnu': 4.62.0 + '@rollup/rollup-win32-x64-msvc': 4.62.0 fsevents: 2.3.3 rrule@2.7.1: @@ -22594,7 +22590,7 @@ snapshots: direction: 1.0.4 is-hotkey: 0.2.0 is-plain-object: 5.0.0 - lodash: 4.17.21 + lodash: 4.18.1 scroll-into-view-if-needed: 3.1.0 slate: 0.118.1 tiny-invariant: 1.3.1 @@ -22613,7 +22609,7 @@ snapshots: '@juggle/resize-observer': 3.4.0 direction: 1.0.4 is-hotkey: 0.2.0 - lodash: 4.17.21 + lodash: 4.18.1 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) scroll-into-view-if-needed: 3.1.0 @@ -22912,15 +22908,11 @@ snapshots: dependencies: webpack: 5.105.4(esbuild@0.25.12) - style-loader@3.3.1(webpack@5.107.2(esbuild@0.25.12)(lightningcss@1.32.0)(postcss@8.5.15)): - dependencies: - webpack: 5.107.2(esbuild@0.25.12)(lightningcss@1.32.0)(postcss@8.5.15) - stylehacks@7.0.11(postcss@8.5.15): dependencies: browserslist: 4.28.2 postcss: 8.5.15 - postcss-selector-parser: 7.1.2 + postcss-selector-parser: 7.1.4 stylelint-config-idiomatic-order@10.0.0(stylelint@16.26.1(typescript@5.9.3)): dependencies: @@ -22945,7 +22937,7 @@ snapshots: '@csstools/css-syntax-patches-for-csstree': 1.1.5(css-tree@3.2.1) '@csstools/css-tokenizer': 3.0.4 '@csstools/media-query-list-parser': 4.0.3(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - '@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.2) + '@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.4) '@dual-bundle/import-meta-resolve': 4.2.1 balanced-match: 2.0.0 colord: 2.9.3 @@ -22972,7 +22964,7 @@ snapshots: postcss: 8.5.15 postcss-resolve-nested-selector: 0.1.6 postcss-safe-parser: 7.0.1(postcss@8.5.15) - postcss-selector-parser: 7.1.2 + postcss-selector-parser: 7.1.4 postcss-value-parser: 4.2.0 resolve-from: 5.0.0 string-width: 4.2.3 @@ -23002,7 +22994,7 @@ snapshots: cookiejar: 2.1.4 debug: 4.4.3 fast-safe-stringify: 2.1.1 - form-data: 4.0.5 + form-data: 4.0.6 formidable: 3.5.4 methods: 1.1.2 mime: 2.6.0 @@ -23090,26 +23082,26 @@ snapshots: tailwind-merge@3.6.0: {} - tailwind-variants@1.0.0(tailwindcss@4.3.0): + tailwind-variants@1.0.0(tailwindcss@4.3.1): dependencies: tailwind-merge: 3.0.2 - tailwindcss: 4.3.0 + tailwindcss: 4.3.1 - tailwind-variants@3.2.2(tailwind-merge@3.6.0)(tailwindcss@4.3.0): + tailwind-variants@3.2.2(tailwind-merge@3.6.0)(tailwindcss@4.3.1): dependencies: - tailwindcss: 4.3.0 + tailwindcss: 4.3.1 optionalDependencies: tailwind-merge: 3.6.0 - tailwindcss-animate@1.0.7(tailwindcss@4.3.0): + tailwindcss-animate@1.0.7(tailwindcss@4.3.1): dependencies: - tailwindcss: 4.3.0 + tailwindcss: 4.3.1 - tailwindcss-react-aria-components@2.1.1(tailwindcss@4.3.0): + tailwindcss-react-aria-components@2.1.1(tailwindcss@4.3.1): dependencies: - tailwindcss: 4.3.0 + tailwindcss: 4.3.1 - tailwindcss@4.3.0: {} + tailwindcss@4.3.1: {} tapable@1.1.3: {} @@ -23129,28 +23121,6 @@ snapshots: optionalDependencies: esbuild: 0.25.12 - terser-webpack-plugin@5.4.0(esbuild@0.25.12)(webpack@5.107.2(esbuild@0.25.12)(lightningcss@1.32.0)(postcss@8.5.15)): - dependencies: - '@jridgewell/trace-mapping': 0.3.31 - jest-worker: 27.5.1 - schema-utils: 4.3.3 - terser: 5.48.0 - webpack: 5.107.2(esbuild@0.25.12)(lightningcss@1.32.0)(postcss@8.5.15) - optionalDependencies: - esbuild: 0.25.12 - - terser-webpack-plugin@5.6.1(esbuild@0.25.12)(lightningcss@1.32.0)(postcss@8.5.15)(webpack@5.107.2(esbuild@0.25.12)(lightningcss@1.32.0)(postcss@8.5.15)): - dependencies: - '@jridgewell/trace-mapping': 0.3.31 - jest-worker: 27.5.1 - schema-utils: 4.3.3 - terser: 5.48.0 - webpack: 5.107.2(esbuild@0.25.12)(lightningcss@1.32.0)(postcss@8.5.15) - optionalDependencies: - esbuild: 0.25.12 - lightningcss: 1.32.0 - postcss: 8.5.15 - terser-webpack-plugin@5.6.1(webpack@5.107.2): dependencies: '@jridgewell/trace-mapping': 0.3.31 @@ -23162,7 +23132,7 @@ snapshots: terser@5.48.0: dependencies: '@jridgewell/source-map': 0.3.11 - acorn: 8.16.0 + acorn: 8.17.0 commander: 2.20.3 source-map-support: 0.5.21 @@ -23232,15 +23202,15 @@ snapshots: tldts-core@6.1.86: {} - tldts-core@7.4.2: {} + tldts-core@7.4.3: {} tldts@6.1.86: dependencies: tldts-core: 6.1.86 - tldts@7.4.2: + tldts@7.4.3: dependencies: - tldts-core: 7.4.2 + tldts-core: 7.4.3 tmp@0.0.33: dependencies: @@ -23268,7 +23238,7 @@ snapshots: tough-cookie@6.0.1: dependencies: - tldts: 7.4.2 + tldts: 7.4.3 tr46@6.0.0: dependencies: @@ -23293,7 +23263,7 @@ snapshots: ts-loader@9.4.4(typescript@5.9.3)(webpack@5.105.4(esbuild@0.25.12)): dependencies: chalk: 4.1.2 - enhanced-resolve: 5.23.0 + enhanced-resolve: 5.24.0 micromatch: 4.0.8 semver: 7.8.4 typescript: 5.9.3 @@ -23333,7 +23303,7 @@ snapshots: picocolors: 1.1.1 postcss-load-config: 6.0.1(jiti@2.7.0)(postcss@8.5.15)(yaml@2.9.0) resolve-from: 5.0.0 - rollup: 4.61.1 + rollup: 4.62.0 source-map: 0.7.6 sucrase: 3.35.1 tinyexec: 0.3.2 @@ -23440,7 +23410,7 @@ snapshots: undici@7.24.5: {} - undici@7.27.2: {} + undici@7.28.0: {} undoo@0.5.0: dependencies: @@ -23484,7 +23454,7 @@ snapshots: unplugin@1.16.1: dependencies: - acorn: 8.16.0 + acorn: 8.17.0 webpack-virtual-modules: 0.6.2 unrs-resolver@1.12.2: @@ -23532,7 +23502,7 @@ snapshots: is-npm: 6.1.0 latest-version: 9.0.0 pupa: 3.3.0 - semver: 7.8.4 + semver: 7.6.3 xdg-basedir: 5.1.0 uri-js@4.4.1: @@ -23607,13 +23577,13 @@ snapshots: core-util-is: 1.0.2 extsprintf: 1.3.0 - vite-node@3.2.4(@types/node@22.19.20)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0): + vite-node@3.2.4(@types/node@22.19.21)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0): dependencies: cac: 6.7.14 debug: 4.4.3 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 6.4.3(@types/node@22.19.20)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) + vite: 6.4.3(@types/node@22.19.21)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) transitivePeerDependencies: - '@types/node' - jiti @@ -23628,13 +23598,13 @@ snapshots: - tsx - yaml - vite-node@3.2.4(@types/node@24.13.1)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0): + vite-node@3.2.4(@types/node@24.13.2)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0): dependencies: cac: 6.7.14 debug: 4.4.3 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 6.4.3(@types/node@24.13.1)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) + vite: 6.4.3(@types/node@24.13.2)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) transitivePeerDependencies: - '@types/node' - jiti @@ -23649,27 +23619,27 @@ snapshots: - tsx - yaml - vite-plugin-svgr@4.5.0(rollup@4.61.1)(typescript@5.9.3)(vite@6.4.3(@types/node@24.13.1)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0)): + vite-plugin-svgr@4.5.0(rollup@4.62.0)(typescript@5.9.3)(vite@6.4.3(@types/node@24.13.2)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0)): dependencies: - '@rollup/pluginutils': 5.4.0(rollup@4.61.1) + '@rollup/pluginutils': 5.4.0(rollup@4.62.0) '@svgr/core': 8.1.0(typescript@5.9.3) '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.9.3)) - vite: 6.4.3(@types/node@24.13.1)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) + vite: 6.4.3(@types/node@24.13.2)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) transitivePeerDependencies: - rollup - supports-color - typescript - vite@6.4.3(@types/node@22.19.20)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0): + vite@6.4.3(@types/node@22.19.21)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0): dependencies: esbuild: 0.25.12 fdir: 6.5.0(picomatch@4.0.4) picomatch: 4.0.4 postcss: 8.5.15 - rollup: 4.61.1 + rollup: 4.62.0 tinyglobby: 0.2.17 optionalDependencies: - '@types/node': 22.19.20 + '@types/node': 22.19.21 fsevents: 2.3.3 jiti: 2.7.0 less: 3.13.1 @@ -23678,16 +23648,16 @@ snapshots: terser: 5.48.0 yaml: 2.9.0 - vite@6.4.3(@types/node@24.13.1)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0): + vite@6.4.3(@types/node@24.13.2)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0): dependencies: esbuild: 0.25.12 fdir: 6.5.0(picomatch@4.0.4) picomatch: 4.0.4 postcss: 8.5.15 - rollup: 4.61.1 + rollup: 4.62.0 tinyglobby: 0.2.17 optionalDependencies: - '@types/node': 24.13.1 + '@types/node': 24.13.2 fsevents: 2.3.3 jiti: 2.7.0 less: 3.13.1 @@ -23696,11 +23666,11 @@ snapshots: terser: 5.48.0 yaml: 2.9.0 - vitest@3.2.6(@types/debug@4.1.13)(@types/node@22.19.20)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0): + vitest@3.2.6(@types/debug@4.1.13)(@types/node@22.19.21)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0): dependencies: '@types/chai': 5.2.3 '@vitest/expect': 3.2.6 - '@vitest/mocker': 3.2.6(vite@6.4.3(@types/node@22.19.20)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0)) + '@vitest/mocker': 3.2.6(vite@6.4.3(@types/node@22.19.21)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0)) '@vitest/pretty-format': 3.2.6 '@vitest/runner': 3.2.6 '@vitest/snapshot': 3.2.6 @@ -23718,12 +23688,12 @@ snapshots: tinyglobby: 0.2.17 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 6.4.3(@types/node@22.19.20)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) - vite-node: 3.2.4(@types/node@22.19.20)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) + vite: 6.4.3(@types/node@22.19.21)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) + vite-node: 3.2.4(@types/node@22.19.21)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: '@types/debug': 4.1.13 - '@types/node': 22.19.20 + '@types/node': 22.19.21 '@vitest/ui': 3.2.6(vitest@3.2.6) jsdom: 28.1.0(@noble/hashes@1.8.0) transitivePeerDependencies: @@ -23740,11 +23710,11 @@ snapshots: - tsx - yaml - vitest@3.2.6(@types/debug@4.1.13)(@types/node@24.13.1)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0): + vitest@3.2.6(@types/debug@4.1.13)(@types/node@24.13.2)(@vitest/ui@3.2.6)(jiti@2.7.0)(jsdom@28.1.0(@noble/hashes@1.8.0))(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0): dependencies: '@types/chai': 5.2.3 '@vitest/expect': 3.2.6 - '@vitest/mocker': 3.2.6(vite@6.4.3(@types/node@24.13.1)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0)) + '@vitest/mocker': 3.2.6(vite@6.4.3(@types/node@24.13.2)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0)) '@vitest/pretty-format': 3.2.6 '@vitest/runner': 3.2.6 '@vitest/snapshot': 3.2.6 @@ -23762,12 +23732,12 @@ snapshots: tinyglobby: 0.2.17 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 6.4.3(@types/node@24.13.1)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) - vite-node: 3.2.4(@types/node@24.13.1)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) + vite: 6.4.3(@types/node@24.13.2)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) + vite-node: 3.2.4(@types/node@24.13.2)(jiti@2.7.0)(less@3.13.1)(lightningcss@1.32.0)(sass@1.58.0)(terser@5.48.0)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: '@types/debug': 4.1.13 - '@types/node': 24.13.1 + '@types/node': 24.13.2 '@vitest/ui': 3.2.6(vitest@3.2.6) jsdom: 28.1.0(@noble/hashes@1.8.0) transitivePeerDependencies: @@ -23795,8 +23765,8 @@ snapshots: wait-on@9.0.10: dependencies: - axios: 1.17.0 - joi: 18.2.1 + axios: 1.18.0 + joi: 18.2.3 lodash: 4.18.1 minimist: 1.2.8 rxjs: 7.8.2 @@ -23806,8 +23776,8 @@ snapshots: wait-on@9.0.10(debug@4.3.4): dependencies: - axios: 1.17.0(debug@4.3.4) - joi: 18.2.1 + axios: 1.18.0(debug@4.3.4) + joi: 18.2.3 lodash: 4.18.1 minimist: 1.2.8 rxjs: 7.8.2 @@ -23817,8 +23787,8 @@ snapshots: wait-on@9.0.4(debug@4.4.3): dependencies: - axios: 1.17.0(debug@4.4.3) - joi: 18.2.1 + axios: 1.18.0(debug@4.4.3) + joi: 18.2.3 lodash: 4.18.1 minimist: 1.2.8 rxjs: 7.8.2 @@ -23830,9 +23800,8 @@ snapshots: dependencies: loose-envify: 1.4.0 - watchpack@2.5.1: + watchpack@2.5.2: dependencies: - glob-to-regexp: 0.4.1 graceful-fs: 4.2.11 wbuf@1.7.3: @@ -23850,7 +23819,7 @@ snapshots: webpack-bundle-analyzer@4.10.1: dependencies: '@discoveryjs/json-ext': 0.5.7 - acorn: 8.16.0 + acorn: 8.17.0 acorn-walk: 8.3.5 commander: 7.2.0 debounce: 1.2.1 @@ -23866,7 +23835,7 @@ snapshots: - bufferutil - utf-8-validate - webpack-dev-middleware@6.1.3(webpack@5.107.2(esbuild@0.25.12)(lightningcss@1.32.0)(postcss@8.5.15)): + webpack-dev-middleware@6.1.3(webpack@5.105.4(esbuild@0.25.12)): dependencies: colorette: 2.0.20 memfs: 3.5.3 @@ -23874,12 +23843,12 @@ snapshots: range-parser: 1.2.1 schema-utils: 4.3.3 optionalDependencies: - webpack: 5.107.2(esbuild@0.25.12)(lightningcss@1.32.0)(postcss@8.5.15) + webpack: 5.105.4(esbuild@0.25.12) webpack-dev-middleware@7.4.5(tslib@2.8.1)(webpack@5.105.4(esbuild@0.25.12)): dependencies: colorette: 2.0.20 - memfs: 4.57.6(tslib@2.8.1) + memfs: 4.57.7(tslib@2.8.1) mime-types: 3.0.2 on-finished: 2.4.1 range-parser: 1.2.1 @@ -23892,7 +23861,7 @@ snapshots: webpack-dev-middleware@7.4.5(tslib@2.8.1)(webpack@5.107.2): dependencies: colorette: 2.0.20 - memfs: 4.57.6(tslib@2.8.1) + memfs: 4.57.7(tslib@2.8.1) mime-types: 3.0.2 on-finished: 2.4.1 range-parser: 1.2.1 @@ -23902,7 +23871,7 @@ snapshots: transitivePeerDependencies: - tslib - webpack-dev-server@5.2.4(debug@4.3.4)(tslib@2.8.1)(webpack@5.105.4(esbuild@0.25.12)): + webpack-dev-server@5.2.5(debug@4.3.4)(tslib@2.8.1)(webpack@5.105.4(esbuild@0.25.12)): dependencies: '@types/bonjour': 3.5.13 '@types/connect-history-api-fallback': 1.5.4 @@ -23941,7 +23910,7 @@ snapshots: - tslib - utf-8-validate - webpack-dev-server@5.2.4(tslib@2.8.1)(webpack@5.105.4(esbuild@0.25.12)): + webpack-dev-server@5.2.5(tslib@2.8.1)(webpack@5.105.4(esbuild@0.25.12)): dependencies: '@types/bonjour': 3.5.13 '@types/connect-history-api-fallback': 1.5.4 @@ -23980,7 +23949,7 @@ snapshots: - tslib - utf-8-validate - webpack-dev-server@5.2.4(tslib@2.8.1)(webpack@5.107.2): + webpack-dev-server@5.2.5(tslib@2.8.1)(webpack@5.107.2): dependencies: '@types/bonjour': 3.5.13 '@types/connect-history-api-fallback': 1.5.4 @@ -24050,11 +24019,11 @@ snapshots: '@webassemblyjs/ast': 1.14.1 '@webassemblyjs/wasm-edit': 1.14.1 '@webassemblyjs/wasm-parser': 1.14.1 - acorn: 8.16.0 - acorn-import-phases: 1.0.4(acorn@8.16.0) + acorn: 8.17.0 + acorn-import-phases: 1.0.4(acorn@8.17.0) browserslist: 4.28.2 chrome-trace-event: 1.0.4 - enhanced-resolve: 5.23.0 + enhanced-resolve: 5.24.0 es-module-lexer: 2.1.0 eslint-scope: 5.1.1 events: 3.3.0 @@ -24067,7 +24036,7 @@ snapshots: schema-utils: 4.3.3 tapable: 2.3.3 terser-webpack-plugin: 5.4.0(esbuild@0.25.12)(webpack@5.105.4(esbuild@0.25.12)) - watchpack: 2.5.1 + watchpack: 2.5.2 webpack-sources: 3.5.0 transitivePeerDependencies: - '@swc/core' @@ -24081,11 +24050,11 @@ snapshots: '@webassemblyjs/ast': 1.14.1 '@webassemblyjs/wasm-edit': 1.14.1 '@webassemblyjs/wasm-parser': 1.14.1 - acorn: 8.16.0 - acorn-import-phases: 1.0.4(acorn@8.16.0) + acorn: 8.17.0 + acorn-import-phases: 1.0.4(acorn@8.17.0) browserslist: 4.28.2 chrome-trace-event: 1.0.4 - enhanced-resolve: 5.23.0 + enhanced-resolve: 5.24.0 es-module-lexer: 2.1.0 eslint-scope: 5.1.1 events: 3.3.0 @@ -24097,46 +24066,7 @@ snapshots: schema-utils: 4.3.3 tapable: 2.3.3 terser-webpack-plugin: 5.6.1(webpack@5.107.2) - watchpack: 2.5.1 - webpack-sources: 3.5.0 - transitivePeerDependencies: - - '@minify-html/node' - - '@swc/core' - - '@swc/css' - - '@swc/html' - - clean-css - - cssnano - - csso - - esbuild - - html-minifier-terser - - lightningcss - - postcss - - uglify-js - - webpack@5.107.2(esbuild@0.25.12)(lightningcss@1.32.0)(postcss@8.5.15): - dependencies: - '@types/estree': 1.0.9 - '@types/json-schema': 7.0.15 - '@webassemblyjs/ast': 1.14.1 - '@webassemblyjs/wasm-edit': 1.14.1 - '@webassemblyjs/wasm-parser': 1.14.1 - acorn: 8.16.0 - acorn-import-phases: 1.0.4(acorn@8.16.0) - browserslist: 4.28.2 - chrome-trace-event: 1.0.4 - enhanced-resolve: 5.23.0 - es-module-lexer: 2.1.0 - eslint-scope: 5.1.1 - events: 3.3.0 - glob-to-regexp: 0.4.1 - graceful-fs: 4.2.11 - loader-runner: 4.3.2 - mime-db: 1.54.0 - neo-async: 2.6.2 - schema-utils: 4.3.3 - tapable: 2.3.3 - terser-webpack-plugin: 5.6.1(esbuild@0.25.12)(lightningcss@1.32.0)(postcss@8.5.15)(webpack@5.107.2(esbuild@0.25.12)(lightningcss@1.32.0)(postcss@8.5.15)) - watchpack: 2.5.1 + watchpack: 2.5.2 webpack-sources: 3.5.0 transitivePeerDependencies: - '@minify-html/node' @@ -24192,7 +24122,7 @@ snapshots: which-builtin-type@1.2.1: dependencies: call-bound: 1.0.4 - function.prototype.name: 1.1.8 + function.prototype.name: 1.2.0 has-tostringtag: 1.0.2 is-async-function: 2.1.1 is-date-object: 1.1.0 diff --git a/news/330.documentation b/news/330.documentation new file mode 100644 index 000000000..924e1d720 --- /dev/null +++ b/news/330.documentation @@ -0,0 +1 @@ +Added documentation for content review & reminders. @jnptk