UNPKG

@gravityforms/components

Version:

UI components for use in Gravity Forms development. Both React and vanilla js flavors.

209 lines (182 loc) 4.75 kB
import { consoleError, getNodes, setAttributes, speak, trigger, } from '@gravityforms/utils'; export const el = { closeTrigger: null, container: null, target: null, }; export const state = { hideTimer: () => {}, hideAnimationTimer: () => {}, }; export const defaults = { attributes: {}, autoHide: true, autoHideDelay: 4000, closeButton: true, closeTitle: '', ctaShowExternalLinkIcon: false, ctaExternalLinkMessage: '', container: '', ctaLink: '', ctaTarget: '_self', ctaText: '', icon: '', message: '', onClose: () => {}, onReveal: () => {}, position: 'bottomleft', speak: true, type: 'normal', wrapperClasses: 'gform-snackbar', }; export let options = {}; /** * @function snackBarHtml * @description Uses our options to render the snackbar. * * @return {string} The html for the snackbar. */ export const snackBarHtml = () => ( ` <article class="${ options.wrapperClasses } gform-snackbar--${ options.position } gform-snackbar--${ options.type }${ options.closeButton ? ` gform-snackbar--has-close` : `` }" data-js="gform-snackbar" > ${ options.icon ? `<span class="gform-snackbar__icon gform-icon gform-icon--${ options.icon }"></span>` : `` } ${ options.message ? `<span class="gform-snackbar__message">${ options.message }</span>` : `` } ${ options.ctaLink ? ` <a class="gform-snackbar__cta" href="${ options.ctaLink }" target="${ options.ctaTarget }" ${ options.ctaTarget === '_blank' ? `rel="noopener"` : `` } > ${ options.ctaText } ${ options.ctaShowExternalLinkIcon && options.ctaExternalLinkMessage ? `<span class="screen-reader-text">${ options.ctaExternalLinkMessage }</span><span class="gform-icon gform-icon--external-link" aria-hidden="true"></span>` : `` } </a> ` : `` } ${ options.closeButton ? ` <button class="gform-snackbar__close gform-icon gform-icon--delete" data-js="gform-snackbar-close" title="${ options.closeTitle }" ></button> ` : `` } </article> ` ); /** * @function cleanUp * @description Clears timeouts and does all needed garbage cleanup. * */ export const cleanUp = () => { if ( ! el.container ) { return; } el.target.style.position = ''; el.container.parentNode.removeChild( el.container ); if ( el.closeTrigger ) { el.closeTrigger.removeEventListener( 'click', close ); } clearTimeout( state.hideTimer ); clearTimeout( state.hideAnimationTimer ); el.container = null; el.closeTrigger = null; el.target = null; }; /** * @function close * @description Animates out the snackbar and then removes it from dom. * */ export const close = () => { el.container.classList.remove( 'gform-snackbar--reveal' ); state.hideAnimationTimer = setTimeout( () => { trigger( { event: 'gform/snackbar/close', native: false, data: { el, options, state, }, } ); cleanUp(); }, 300 ); }; /** * @function reveal * @description Reveals the snackbar and if autohide true it starts the hide timer. If speak is true, announces the * message as well to screenreaders. * */ export const reveal = () => { trigger( { event: 'gform/snackbar/pre_reveal', native: false, data: { el, options, state, }, } ); setTimeout( () => { el.container.classList.add( 'gform-snackbar--reveal' ); if ( options.autoHide ) { state.hideTimer = setTimeout( () => { close(); }, options.autoHideDelay ); } if ( options.speak ) { speak( options.message ); } options.onReveal(); }, 20 ); }; /** * @function render * @description Renders the snackbar in the passed container option. * */ export const render = () => { el.target = getNodes( options.container, false, document, true )[ 0 ]; if ( ! el.target ) { consoleError( `Gform snackBar couldn't find ${ options.container } to instantiate in.` ); } el.target.style.position = 'relative'; el.target.insertAdjacentHTML( 'beforeend', snackBarHtml() ); el.container = getNodes( 'gform-snackbar', false, el.target )[ 0 ]; el.closeTrigger = getNodes( 'gform-snackbar-close', false, el.target )[ 0 ]; setAttributes( el.container, options.attributes ); }; /** * @function setOptions * @description Merges the default options with the passed args. * */ export const setOptions = ( args = {} ) => { options = Object.assign( {}, defaults, args ); trigger( { event: 'gform/snackbar/pre_init', native: false, data: options } ); }; /** * @function bindEvents * @description Bind event handlers * */ const bindEvents = () => { if ( el.closeTrigger ) { el.closeTrigger.addEventListener( 'click', close ); } }; /** * @function init * @description Initialize and execute a snackbar. * */ const init = ( args ) => { cleanUp(); setOptions( args ); render(); reveal(); bindEvents(); }; export default init;