accordion.css
3 months ago
button.css
4 weeks ago
card.css
3 months ago
common.css
3 months ago
common.js
3 months ago
deprecated.css
3 months ago
form.css
3 months ago
header.css
3 months ago
modal-new.css
3 months ago
modal.css
3 months ago
modal.js
3 months ago
screen-options.js
3 months ago
tabs.js
3 months ago
toast.css
3 months ago
toaster.js
3 months ago
toggles.js
3 months ago
toaster.js
130 lines
| 1 | const TOAST_CONTAINER_ID = 'advads-toast-container'; |
| 2 | |
| 3 | /** |
| 4 | * Ensures a single container for toasts exists in the DOM. |
| 5 | * |
| 6 | * @param {boolean} inDialog Whether the toast is in a dialog. |
| 7 | * |
| 8 | * @return {HTMLElement} The toast container element. |
| 9 | */ |
| 10 | function getToastContainer( inDialog = false ) { |
| 11 | let container = document.getElementById( TOAST_CONTAINER_ID ); |
| 12 | if ( ! container ) { |
| 13 | container = document.createElement( 'div' ); |
| 14 | container.id = TOAST_CONTAINER_ID; |
| 15 | container.setAttribute( 'aria-live', 'polite' ); |
| 16 | } |
| 17 | |
| 18 | let whereToAppend = document.body; |
| 19 | |
| 20 | if ( inDialog ) { |
| 21 | const dialog = document.querySelector( '.advads-dialog[open]' ); |
| 22 | if ( dialog ) { |
| 23 | whereToAppend = dialog.querySelector( '.advads-dialog-frame' ); |
| 24 | } |
| 25 | } |
| 26 | |
| 27 | whereToAppend.appendChild( container ); |
| 28 | |
| 29 | return container; |
| 30 | } |
| 31 | |
| 32 | function createIconByType( type ) { |
| 33 | switch ( type ) { |
| 34 | case 'muted': |
| 35 | case 'info': |
| 36 | case 'warning': |
| 37 | return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" x2="12" y1="8" y2="12"/><line x1="12" x2="12.01" y1="16" y2="16"/></svg>'; |
| 38 | case 'success': |
| 39 | return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21.801 10A10 10 0 1 1 17 3.335"/><path d="m9 11 3 3L22 4"/></svg>'; |
| 40 | case 'error': |
| 41 | return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="m15 9-6 6"/><path d="m9 9 6 6"/></svg>'; |
| 42 | } |
| 43 | } |
| 44 | |
| 45 | /** |
| 46 | * Adds a notice (toast) to the page. |
| 47 | * |
| 48 | * @param {Object} options Options object. |
| 49 | * @param {string} options.type Notice type: 'success' | 'error' | 'warning' | 'info'. |
| 50 | * @param {string} options.iconType Notice icon type: 'success' | 'error' | 'warning' | 'info'. |
| 51 | * @param {string} options.title Notice title. |
| 52 | * @param {string} options.message Notice message body. |
| 53 | * @param {boolean} [options.isDismissible] Whether the notice can be dismissed. Default true. |
| 54 | * @param {string} [options.actions] Optional HTML string for action buttons/links. |
| 55 | * @param {boolean} [options.inDialog] Whether the toast is in a dialog. Default false. |
| 56 | * @param {boolean} [options.autoClose] Whether the toast should auto close. Default true. |
| 57 | * @param {number} [options.autoCloseTimeout] The timeout in milliseconds for auto close. Default 4000. |
| 58 | * |
| 59 | * @return {HTMLElement} The created toast element. |
| 60 | */ |
| 61 | export function createToast( { |
| 62 | type = 'muted', |
| 63 | iconType, |
| 64 | title, |
| 65 | message, |
| 66 | autoClose = true, |
| 67 | autoCloseTimeout = 4000, |
| 68 | isDismissible = true, |
| 69 | actions = '', |
| 70 | inDialog = false, |
| 71 | } ) { |
| 72 | const container = getToastContainer( inDialog ); |
| 73 | const toast = document.createElement( 'div' ); |
| 74 | toast.className = `advads-toast advads-toast-${ type }`; |
| 75 | if ( isDismissible ) { |
| 76 | toast.classList.add( 'advads-toast-dismissible' ); |
| 77 | } |
| 78 | |
| 79 | const iconEl = document.createElement( 'div' ); |
| 80 | iconEl.className = 'advads-toast-icon'; |
| 81 | iconEl.innerHTML = createIconByType( iconType || type || 'info' ); |
| 82 | toast.appendChild( iconEl ); |
| 83 | |
| 84 | const titleEl = document.createElement( 'div' ); |
| 85 | titleEl.className = 'advads-toast-title'; |
| 86 | titleEl.textContent = title; |
| 87 | |
| 88 | const messageEl = document.createElement( 'div' ); |
| 89 | messageEl.className = 'advads-toast-message'; |
| 90 | messageEl.textContent = message; |
| 91 | |
| 92 | const contentEl = document.createElement( 'div' ); |
| 93 | contentEl.className = 'advads-toast-content'; |
| 94 | contentEl.appendChild( titleEl ); |
| 95 | contentEl.appendChild( messageEl ); |
| 96 | toast.appendChild( contentEl ); |
| 97 | |
| 98 | if ( actions ) { |
| 99 | const actionsWrap = document.createElement( 'div' ); |
| 100 | actionsWrap.className = 'advads-toast-actions'; |
| 101 | actionsWrap.innerHTML = actions; |
| 102 | toast.appendChild( actionsWrap ); |
| 103 | } |
| 104 | |
| 105 | if ( isDismissible ) { |
| 106 | const closeBtn = document.createElement( 'a' ); |
| 107 | closeBtn.href = '#'; |
| 108 | closeBtn.className = 'advads-toast-dismiss'; |
| 109 | closeBtn.setAttribute( 'aria-label', 'Dismiss' ); |
| 110 | closeBtn.innerHTML = '×'; |
| 111 | closeBtn.addEventListener( 'click', () => { |
| 112 | toast.remove(); |
| 113 | } ); |
| 114 | toast.appendChild( closeBtn ); |
| 115 | } |
| 116 | |
| 117 | container.appendChild( toast ); |
| 118 | |
| 119 | if ( autoClose ) { |
| 120 | setTimeout( () => { |
| 121 | toast.remove(); |
| 122 | }, autoCloseTimeout ); |
| 123 | } |
| 124 | |
| 125 | return toast; |
| 126 | } |
| 127 | |
| 128 | globalThis.advancedAds.utils = globalThis.advancedAds.utils || {}; |
| 129 | globalThis.advancedAds.utils.createToast = createToast; |
| 130 |