diff --git a/.gitignore b/.gitignore index 2dbbd53..5fb578b 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ !.github # ignore node/grunt dependency directories node_modules/ +wp-content/ # ignore vendor vendor/ diff --git a/composer.json b/composer.json index 78da85e..db5c15b 100644 --- a/composer.json +++ b/composer.json @@ -54,7 +54,8 @@ "helsingborg-stad/acf-export-manager": ">=1.0.0", "symfony/polyfill-intl-idn": "1.31.0", "helsingborg-stad/wpservice": "^2.0", - "helsingborg-stad/acfservice": "^0.8.1" + "helsingborg-stad/acfservice": "^0.8.1", + "helsingborg-stad/component-library": "^4" }, "require-dev": { "codedungeon/phpunit-result-printer": "^0.32.0", diff --git a/dist/manifest.json b/dist/manifest.json index eec7bb1..d324661 100644 --- a/dist/manifest.json +++ b/dist/manifest.json @@ -1,5 +1,5 @@ { - "css/broken-link-detector.css": "css/broken-link-detector.024cd1a77a7b5c050e6a.css", - "js/context-detector.js": "js/context-detector.93354089fe4a513a8445.js", + "css/broken-link-detector.css": "css/broken-link-detector.40888f073f7fe120bcae.css", + "js/context-detector.js": "js/context-detector.09d51a4f92bccb526918.js", "js/editor-highlight.js": "js/editor-highlight.a7ccb59aeba3991ac935.js" } \ No newline at end of file diff --git a/languages/broken-link-detector-sv_SE.mo b/languages/broken-link-detector-sv_SE.mo index b618fcd..4fecc97 100644 Binary files a/languages/broken-link-detector-sv_SE.mo and b/languages/broken-link-detector-sv_SE.mo differ diff --git a/languages/broken-link-detector-sv_SE.po b/languages/broken-link-detector-sv_SE.po index 3b6bc30..0252c3d 100644 --- a/languages/broken-link-detector-sv_SE.po +++ b/languages/broken-link-detector-sv_SE.po @@ -1,8 +1,8 @@ msgid "" msgstr "" "Project-Id-Version: Broken Link Detector\n" -"POT-Creation-Date: 2024-11-13 10:53+0100\n" -"PO-Revision-Date: 2024-11-13 11:03+0100\n" +"POT-Creation-Date: 2024-12-03 12:37+0100\n" +"PO-Revision-Date: 2024-12-03 12:38+0100\n" "Last-Translator: \n" "Language-Team: \n" "Language: sv_SE\n" @@ -15,23 +15,23 @@ msgstr "" "X-Poedit-WPHeader: broken-link-detector.php\n" "X-Poedit-SourceCharset: UTF-8\n" "X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;esc_attr__;" -"esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c;" -"_n_noop:1,2;_nx_noop:3c,1,2;__ngettext_noop:1,2\n" +"esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c;_n_noop:1,2;" +"_nx_noop:3c,1,2;__ngettext_noop:1,2\n" "X-Poedit-SearchPath-0: .\n" "X-Poedit-SearchPathExcluded-0: *.js\n" "X-Poedit-SearchPathExcluded-1: dist\n" "X-Poedit-SearchPathExcluded-2: vendor\n" "X-Poedit-SearchPathExcluded-3: node_modules\n" -#: source/fields/php/context-detection.php:6 +#: source/fields/php/context-detection.php:8 msgid "Context Detect" msgstr "Identifiering av användarkontext" -#: source/fields/php/context-detection.php:10 +#: source/fields/php/context-detection.php:12 msgid "Enable detection of user context" msgstr "Identifiera användarens kontext i nätverket" -#: source/fields/php/context-detection.php:14 +#: source/fields/php/context-detection.php:16 msgid "" "The user detection functionality will disable links that are internal only. " "It also adds a tipbox to them explaining why the link is unreachable." @@ -41,51 +41,71 @@ msgstr "" "tillgängliga om denna resurs är otillgänglig, kommer markeras som icke " "klickbara." -#: source/fields/php/context-detection.php:22 +#: source/fields/php/context-detection.php:24 msgid "Detects user context by fetching a internal resource." msgstr "" "Identifierar användarens kontext i nätverket genom att försöka hämta en " "intern resurs." -#: source/fields/php/context-detection.php:24 +#: source/fields/php/context-detection.php:26 msgid "Enabled" msgstr "Aktiverad" -#: source/fields/php/context-detection.php:25 +#: source/fields/php/context-detection.php:27 msgid "Disabled" msgstr "Avaktiverad" -#: source/fields/php/context-detection.php:30 +#: source/fields/php/context-detection.php:32 msgid "Internal Context Detection Resource" msgstr "Resurs som ska hämtas" -#: source/fields/php/context-detection.php:34 +#: source/fields/php/context-detection.php:36 msgid "" "The internal context checker require you to publish a image on a server " "without public access. The image should be as small as possible, if your " "site is running on https, this resource must also be served with https." msgstr "" -"För att identifiera användarens kontext, krävs det att du publicerar en " -"bild på en webbadress som bara kan nås från det interna nätverket. Resursen " -"måste vara tillgänglig via http eller https (om din webbplats använder ssl-" +"För att identifiera användarens kontext, krävs det att du publicerar en bild " +"på en webbadress som bara kan nås från det interna nätverket. Resursen måste " +"vara tillgänglig via http eller https (om din webbplats använder ssl-" "certifikat)." -#: source/fields/php/context-detection.php:51 +#: source/fields/php/context-detection.php:53 msgid "https://internal.resource.admin-network.local/image-1x1.jpg" msgstr "" -#: source/fields/php/context-detection.php:55 +#: source/fields/php/context-detection.php:57 +msgid "Inform user by the following methods" +msgstr "Informera användaren genom" + +#: source/fields/php/context-detection.php:78 +msgid "Tooltip" +msgstr "Text på tooltip" + +#: source/fields/php/context-detection.php:79 +msgid "Modal" +msgstr "Modalfönster" + +#: source/fields/php/context-detection.php:92 msgid "Tooltip Text" msgstr "Text på tooltip" -#: source/fields/php/context-detection.php:59 -msgid "The text that displays in the tooltip, whenever a link is unavabile." +#: source/fields/php/context-detection.php:96 +msgid "The text that displays in the tooltip, whenever a link is unavailable." msgstr "Den text som ska visas när en länk inte är tillgänglig." -#: source/fields/php/context-detection.php:77 source/php/Config/Config.php:340 -msgid "Link unavabile" +#: source/fields/php/context-detection.php:114 source/php/Config/Config.php:360 +msgid "Link unavailable" msgstr "Otillgänglig" +#: source/fields/php/context-detection.php:120 +msgid "Modal Title" +msgstr "Titel i modalfönster" + +#: source/fields/php/context-detection.php:148 +msgid "Modal Content" +msgstr "Innehåll i modalfönster" + #: source/fields/php/local-domains.php:6 msgid "Local Domain Settings" msgstr "Inställningar för lokala domäner" @@ -177,6 +197,43 @@ msgstr "Alla HTTP Koder" msgid "Filter" msgstr "Filter" +#: source/php/Config/Config.php:396 +msgid "Content unavailable" +msgstr "Länk otillgänglig" + +#: source/php/Config/Config.php:414 +msgid "" +"\n" +" This link cannot be accessed on your current network. The system you " +"are trying to reach is only available through a secure, authorized " +"connection. \n" +"\n" +" To access it, you need to either be connected to the network in a " +"specific location, such as an office, or use a secure connection method, " +"like a VPN. \n" +"\n" +" Please ensure you are connected to the correct network to proceed.\n" +" " +msgstr "" +"\n" +" Den här länken kan inte nås på ditt nuvarande nätverk. Systemet du " +"försöker nå är endast tillgängligt genom en säker, auktoriserad anslutning.\n" +"\n" +" För att få åtkomst behöver du antingen vara ansluten till nätverket på " +"en specifik plats, som ett kontor, eller använda en säker anslutningsmetod, " +"som en VPN.\n" +"\n" +" Vänligen säkerställ att du är ansluten till rätt nätverk för att " +"fortsätta. " + +#: source/php/Modal.php:28 +msgid "Open Anyway" +msgstr "Fortsätt ändå" + +#: source/php/Modal.php:29 +msgid "Close" +msgstr "Stäng" + #. Plugin Name of the plugin/theme msgid "Broken Link Detector" msgstr "Brutna länkar (Broken Link Detector)" diff --git a/source/fields/json/context-detection.json b/source/fields/json/context-detection.json index 47537b5..dd4645f 100644 --- a/source/fields/json/context-detection.json +++ b/source/fields/json/context-detection.json @@ -47,20 +47,82 @@ "default_value": "", "placeholder": "https:\/\/internal.resource.admin-network.local\/image-1x1.jpg" }, + { + "key": "field_674ed2cff358e", + "label": "Inform user by the following methods", + "name": "broken_links_context_notify_by", + "aria-label": "", + "type": "checkbox", + "instructions": "", + "required": 0, + "conditional_logic": [ + [ + { + "field": "field_6718e9eed55b7", + "operator": "==", + "value": "1" + } + ] + ], + "wrapper": { + "width": "", + "class": "", + "id": "" + }, + "choices": { + "tooltip": "Tooltip", + "modal": "Modal" + }, + "default_value": [], + "return_format": "value", + "allow_custom": 0, + "layout": "horizontal", + "toggle": 0, + "save_custom": 0, + "custom_choice_button_text": "L\u00e4gg till nytt val" + }, { "key": "field_6733096f5d072", "label": "Tooltip Text", "name": "broken_links_context_tooltip", "aria-label": "", "type": "text", - "instructions": "The text that displays in the tooltip, whenever a link is unavabile.", + "instructions": "The text that displays in the tooltip, whenever a link is unavailable.", "required": 0, "conditional_logic": [ [ { - "field": "field_6718e9eed55b7", + "field": "field_674ed2cff358e", "operator": "==", - "value": "1" + "value": "tooltip" + } + ] + ], + "wrapper": { + "width": "", + "class": "", + "id": "" + }, + "default_value": "", + "maxlength": "", + "placeholder": "Link unavailable", + "prepend": "", + "append": "" + }, + { + "key": "field_674ed3fcf358f", + "label": "Modal Title", + "name": "broken_links_context_modal_title", + "aria-label": "", + "type": "text", + "instructions": "", + "required": 0, + "conditional_logic": [ + [ + { + "field": "field_674ed2cff358e", + "operator": "==", + "value": "modal" } ] ], @@ -71,9 +133,38 @@ }, "default_value": "", "maxlength": "", - "placeholder": "Link unavabile", + "placeholder": "", "prepend": "", "append": "" + }, + { + "key": "field_674ed42ef3590", + "label": "Modal Content", + "name": "broken_links_context_modal_content", + "aria-label": "", + "type": "textarea", + "instructions": "", + "required": 0, + "conditional_logic": [ + [ + { + "field": "field_674ed2cff358e", + "operator": "==", + "value": "modal" + } + ] + ], + "wrapper": { + "width": "", + "class": "", + "id": "" + }, + "default_value": "", + "acfe_textarea_code": 0, + "maxlength": "", + "rows": "", + "placeholder": "", + "new_lines": "" } ], "location": [ @@ -102,4 +193,4 @@ "acfe_meta": "", "acfe_note": "" }] - \ No newline at end of file + diff --git a/source/fields/php/context-detection.php b/source/fields/php/context-detection.php index 963177e..610d01f 100644 --- a/source/fields/php/context-detection.php +++ b/source/fields/php/context-detection.php @@ -1,7 +1,9 @@ 'group_6718e9e8554ca', 'title' => __('Context Detect', 'api-event-manager'), 'fields' => array( @@ -51,19 +53,82 @@ 'placeholder' => __('https://internal.resource.admin-network.local/image-1x1.jpg', 'api-event-manager'), ), 2 => array( + 'key' => 'field_674ed2cff358e', + 'label' => __('Inform user by the following methods', 'api-event-manager'), + 'name' => 'broken_links_context_notify_by', + 'aria-label' => '', + 'type' => 'checkbox', + 'instructions' => '', + 'required' => 0, + 'conditional_logic' => array( + 0 => array( + 0 => array( + 'field' => 'field_6718e9eed55b7', + 'operator' => '==', + 'value' => '1', + ), + ), + ), + 'wrapper' => array( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'choices' => array( + 'tooltip' => __('Tooltip', 'api-event-manager'), + 'modal' => __('Modal', 'api-event-manager'), + ), + 'default_value' => array( + ), + 'return_format' => 'value', + 'allow_custom' => 0, + 'layout' => 'horizontal', + 'toggle' => 0, + 'save_custom' => 0, + 'custom_choice_button_text' => 'Lägg till nytt val', + ), + 3 => array( 'key' => 'field_6733096f5d072', 'label' => __('Tooltip Text', 'api-event-manager'), 'name' => 'broken_links_context_tooltip', 'aria-label' => '', 'type' => 'text', - 'instructions' => __('The text that displays in the tooltip, whenever a link is unavabile.', 'api-event-manager'), + 'instructions' => __('The text that displays in the tooltip, whenever a link is unavailable.', 'api-event-manager'), 'required' => 0, 'conditional_logic' => array( 0 => array( 0 => array( - 'field' => 'field_6718e9eed55b7', + 'field' => 'field_674ed2cff358e', 'operator' => '==', - 'value' => '1', + 'value' => 'tooltip', + ), + ), + ), + 'wrapper' => array( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'default_value' => '', + 'maxlength' => '', + 'placeholder' => __('Link unavailable', 'api-event-manager'), + 'prepend' => '', + 'append' => '', + ), + 4 => array( + 'key' => 'field_674ed3fcf358f', + 'label' => __('Modal Title', 'api-event-manager'), + 'name' => 'broken_links_context_modal_title', + 'aria-label' => '', + 'type' => 'text', + 'instructions' => '', + 'required' => 0, + 'conditional_logic' => array( + 0 => array( + 0 => array( + 'field' => 'field_674ed2cff358e', + 'operator' => '==', + 'value' => 'modal', ), ), ), @@ -74,10 +139,39 @@ ), 'default_value' => '', 'maxlength' => '', - 'placeholder' => __('Link unavabile', 'api-event-manager'), + 'placeholder' => '', 'prepend' => '', 'append' => '', ), + 5 => array( + 'key' => 'field_674ed42ef3590', + 'label' => __('Modal Content', 'api-event-manager'), + 'name' => 'broken_links_context_modal_content', + 'aria-label' => '', + 'type' => 'textarea', + 'instructions' => '', + 'required' => 0, + 'conditional_logic' => array( + 0 => array( + 0 => array( + 'field' => 'field_674ed2cff358e', + 'operator' => '==', + 'value' => 'modal', + ), + ), + ), + 'wrapper' => array( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'default_value' => '', + 'acfe_textarea_code' => 0, + 'maxlength' => '', + 'rows' => '', + 'placeholder' => '', + 'new_lines' => '', + ), ), 'location' => array( 0 => array( @@ -105,4 +199,5 @@ 'acfe_meta' => '', 'acfe_note' => '', )); - } \ No newline at end of file + +} \ No newline at end of file diff --git a/source/js/context-detector.ts b/source/js/context-detector.ts index b256f59..96a4717 100644 --- a/source/js/context-detector.ts +++ b/source/js/context-detector.ts @@ -79,13 +79,48 @@ class ClientTypeChecker { this.config.domains.forEach(domain => { const elements = document.querySelectorAll(`a[href*="${domain}"]`); elements.forEach(element => { - element.classList.add('broken-link-detector-link-is-unavabile'); - element.setAttribute("data-tooltip", this.config.tooltip); - element.addEventListener("click", (event) => { - event.preventDefault(); - }); + this.addUnavailableClass(element); + this.preventDefaultOnClick(element); + + if (this.config.isToolTipActive) { + this.addTooltip(element); + } + + if (this.config.isModalActive) { + this.addModalAttributes(element); + } }); }); + + this.reindexModals(); + } + + private addUnavailableClass(element: Element): void { + element.classList.add('broken-link-detector-link-is-unavailable'); + } + + private preventDefaultOnClick(element: Element): void { + element.addEventListener("click", (event) => { + event.preventDefault(); + }); + } + + private addTooltip(element: Element): void { + element.setAttribute("data-tooltip", this.config.tooltip); + } + + private addModalAttributes(element: Element): void { + element.setAttribute("data-open", "modal-broken-link"); + element.addEventListener("click", () => { + const modalButton = document.getElementById("modal-broken-link-button"); + if (modalButton) { + modalButton.setAttribute("href", element.getAttribute("href") || "#linknotfound"); + } + }); + } + + private reindexModals(): void { + document.dispatchEvent(new CustomEvent('reindexModals')); } } @@ -98,6 +133,8 @@ interface brokenLinkContextDetectionData { tooltip: string; successClass: string; failedClass: string; + isToolTipActive: boolean; + isModalActive: boolean; } declare global { diff --git a/source/php/App.php b/source/php/App.php index fc2c9d1..2cda73c 100644 --- a/source/php/App.php +++ b/source/php/App.php @@ -31,6 +31,9 @@ use BrokenLinkDetector\Cli\FindLinks; use BrokenLinkDetector\Cli\ClassifyLinks; +/* Vendors */ +use ComponentLibrary\Init; + class App { public static $dbTable = 'broken_links_detector'; @@ -216,6 +219,18 @@ public function __construct( $config ); $contextDetectionAsset->addHooks(); + + // Add modal, if enabled + if($config->getContextCheckIsModalActive()) { + $modal = new \BrokenLinkDetector\Modal( + $wpService, + $config, + new \ComponentLibrary\Init( + [$config->getTemplateDirectory()] + ) + ); + $modal->addHooks(); + } } } diff --git a/source/php/Asset/ContextDetection.php b/source/php/Asset/ContextDetection.php index 251203a..1e48433 100644 --- a/source/php/Asset/ContextDetection.php +++ b/source/php/Asset/ContextDetection.php @@ -33,9 +33,11 @@ public function getLocalizeData(): ?array 'checkUrl' => $this->config->getContextCheckUrl(), 'checkTimeout' => $this->config->getContextCheckTimeout(), 'domains' => $this->config->getContextCheckDomainsToDisable(), - 'tooltip' => $this->config->getContextCheckTooltipText(), 'successClass' => $this->config->getContextCheckSuccessClass(), 'failedClass' => $this->config->getContextCheckFailedClass(), + 'isToolTipActive' => $this->config->getContextCheckIsToolTipActive(), + 'tooltip' => $this->config->getContextCheckTooltipText(), + 'isModalActive' => $this->config->getContextCheckIsModalActive(), ]; } } \ No newline at end of file diff --git a/source/php/Config/Config.php b/source/php/Config/Config.php index 3208a36..c9988f5 100644 --- a/source/php/Config/Config.php +++ b/source/php/Config/Config.php @@ -318,7 +318,27 @@ public function getContextCheckSuccessClass() : string { public function getContextCheckFailedClass() : string { return $this->wpService->applyFilters( $this->createFilterKey(__FUNCTION__), - 'context-check-unavabile' + 'context-check-unavailable' + ); + } + + /** + * Get the active status for the tooltip. + * + * @return bool + */ + public function getContextCheckIsToolTipActive(): bool + { + $notifyByValues = $this->acfService->getField( + 'broken_links_context_notify_by', + 'option' + ) ?: []; + + $isActive = in_array('tooltip', $notifyByValues); + + return $this->wpService->applyFilters( + $this->createFilterKey(__FUNCTION__), + $isActive ?? true ); } @@ -337,12 +357,75 @@ public function getContextCheckTooltipText(): string return $this->wpService->applyFilters( $this->createFilterKey(__FUNCTION__), $dbLabel ?: $this->wpService->__( - 'Link unavabile', + 'Link unavailable', 'broken-link-detector' ) ); } + /** + * Get the active status for the modal. + * + * @return bool + */ + public function getContextCheckIsModalActive(): bool + { + $notifyByValues = $this->acfService->getField( + 'broken_links_context_notify_by', + 'option' + ) ?: []; + + $isActive = in_array('modal', $notifyByValues); + + return $this->wpService->applyFilters( + $this->createFilterKey(__FUNCTION__), + $isActive ?? true + ); + } + + /** + * Get the title for the modal. + * + * @return string + */ + public function getContextCheckModalTitle(): string + { + $title = $this->acfService->getField( + 'broken_links_context_modal_title', + 'option' + ) ?: $this->wpService->__('Content unavailable', 'broken-link-detector'); + + return $this->wpService->applyFilters( + $this->createFilterKey(__FUNCTION__), + $title + ); + } + + /** + * Get the content for the modal. + * + * @return string + */ + public function getContextCheckModalContent(): string + { + $content = $this->acfService->getField( + 'broken_links_context_modal_content', + 'option' + ) ?: $this->wpService->__(' + This link cannot be accessed on your current network. The system you are trying to reach is only available through a secure, authorized connection. + + To access it, you need to either be connected to the network in a specific location, such as an office, or use a secure connection method, like a VPN. + + Please ensure you are connected to the correct network to proceed. + ', 'broken-link-detector' + ); + + return $this->wpService->applyFilters( + $this->createFilterKey(__FUNCTION__), + $this->wpService->wpautop($content) + ); + } + /** * Get the namespace for the WP CLI command. * @@ -356,6 +439,19 @@ public function getCommandNamespace(): string ); } + /** + * Get the template directory. + * + * @return string + */ + public function getTemplateDirectory(): string + { + return $this->wpService->applyFilters( + $this->createFilterKey(__FUNCTION__), + $this->getPluginPath() . 'source/views' + ); + } + /** * Create a prefix for image conversion filter. * diff --git a/source/php/Config/ConfigInterface.php b/source/php/Config/ConfigInterface.php index 13bd693..6174768 100644 --- a/source/php/Config/ConfigInterface.php +++ b/source/php/Config/ConfigInterface.php @@ -46,4 +46,11 @@ public function getContextCheckDomainsToDisable(): array; public function getContextCheckSuccessClass(): string; public function getContextCheckFailedClass(): string; public function getContextCheckTooltipText(): string; + + /* Modal */ + public function getTemplateDirectory(): string; + public function getContextCheckIsModalActive(): bool; + public function getContextCheckIsToolTipActive(): bool; + public function getContextCheckModalTitle(): string; + public function getContextCheckModalContent(): string; } \ No newline at end of file diff --git a/source/php/Modal.php b/source/php/Modal.php new file mode 100644 index 0000000..fc96555 --- /dev/null +++ b/source/php/Modal.php @@ -0,0 +1,41 @@ +wpService->addAction('wp_footer', [$this, 'renderView']); + } + + /** + * Render the modal view + */ + public function renderView(): string + { + $data = [ + 'title' => $this->config->getContextCheckModalTitle(), + 'content' => $this->config->getContextCheckModalContent(), + 'ctaLink' => '{{BLD_CTA_LINK}}', + 'ctaLabel' => $this->wpService->__("Open Anyway", 'broken-link-detector'), + 'close' => $this->wpService->__("Close", 'broken-link-detector'), + ]; + + $blade = $this->componentLibrary->getEngine(); + + try { + echo $blade->makeView('modal', $data, [], [])->render(); + } catch (Throwable $e) { + $blade->errorHandler($e)->print(); + } + return false; + } +} \ No newline at end of file diff --git a/source/sass/broken-link-detector.scss b/source/sass/broken-link-detector.scss index 5f262a6..a1c69ef 100644 --- a/source/sass/broken-link-detector.scss +++ b/source/sass/broken-link-detector.scss @@ -1,3 +1,3 @@ -.broken-link-detector-link-is-unavabile { +.broken-link-detector-link-is-unavailable { cursor: not-allowed !important; } diff --git a/source/views/modal.blade.php b/source/views/modal.blade.php new file mode 100644 index 0000000..1d27814 --- /dev/null +++ b/source/views/modal.blade.php @@ -0,0 +1,30 @@ + +@modal( + [ + 'closeButtonText' => 'Close', + 'heading' => $title, + 'id' => 'modal-broken-link', + 'size' => 'sm', + 'padding' => 3, + 'borderRadius' => 'lg', + 'attributeList' => [ + 'style' => 'max-width: calc(var(--base, 8px) * 75);' + ] + ] +) + {!!$content!!} + + @slot('bottom') + @button([ + 'id' => 'modal-broken-link-button', + 'href' => $ctaLink, + 'type' => 'filled', + 'text' => $ctaLabel, + 'icon' => 'open_in_new', + 'size' => 'md', + 'color' => 'primary', + 'classList' => ['u-width--100'] + ]) + @endbutton + @endslot +@endmodal \ No newline at end of file