Current Path : /var/www/wptbox/wp-content/plugins/astra-sites/inc/lib/ai-builder/inc/assets/src/utils/ |
Current File : /var/www/wptbox/wp-content/plugins/astra-sites/inc/lib/ai-builder/inc/assets/src/utils/helpers.js |
import { twMerge } from 'tailwind-merge'; import clsx from 'clsx'; import apiFetch from '@wordpress/api-fetch'; export const classNames = ( ...classes ) => twMerge( clsx( classes ) ); export const debounce = ( func, wait, immediate ) => { let timeout; return ( ...args ) => { const later = () => { timeout = null; if ( ! immediate ) { func( ...args ); } }; const callNow = immediate && ! timeout; clearTimeout( timeout ); timeout = setTimeout( later, wait ); if ( callNow ) { func( ...args ); } }; }; /** * Get row number by index value. * * @param {number} index * @return {number} number of row */ export const getRowNum = ( index ) => { return Math.floor( index / 3 ) + 1; }; /** * Get column number by index value. * * @param {number} index * @return {number} number of column */ export const getColumnNum = ( index ) => { return ( index % 3 ) + 1; }; /** * Get the loading skeleton type by row and column number. * * @param {number} row row number. * @param {number} column column number. * @return {number} skeleton type number. */ export const getLoadingSkeletonType = ( row, column ) => { const types = [ 1, 2, 3 ]; const index = ( row - 1 ) % 3; const typeIndex = ( column - 1 + index ) % 3; return types[ typeIndex ]; }; /** * Set value to session storage by key. * * @param {string} key * @param {*} value */ export const setToSessionStorage = ( key, value ) => { const sessionStorageAPI = window.sessionStorage; try { sessionStorageAPI.setItem( key, JSON.stringify( value ) ); } catch ( error ) { console.error( error ); } }; /** * Get value from session storage by key. * * @param {string} key * @param {*} defaultValue * @return {*} value */ export const getFromSessionStorage = ( key, defaultValue = undefined ) => { const sessionStorageAPI = typeof sessionStorage !== 'undefined' ? sessionStorage : window.sessionStorage; try { const value = sessionStorageAPI.getItem( key ); return !! value ? JSON.parse( value ) : defaultValue; } catch ( error ) { console.error( error ); return defaultValue; } }; /** * Clear the session storage by key. * * @param {string} key */ export const clearSessionStorage = ( key ) => { const sessionStorageAPI = typeof sessionStorage !== 'undefined' ? sessionStorage : window.sessionStorage; try { sessionStorageAPI.removeItem( key ); } catch ( error ) { console.error( error ); } }; /** * Generate a unique string of specified length. * * @param {number} length The length of the string to be generated. Default is 8. * @return {string} The generated unique string. */ const uniqString = ( length = 8 ) => { // Define the characters to be used in the string. const chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; let result = ''; // Generate the string by randomly selecting characters from the defined set. for ( let i = length; i > 0; --i ) { result += chars[ Math.floor( Math.random() * chars.length ) ]; } return result.toLowerCase(); }; /** * Recursively manipulate the block ID attribute of an array of blocks. * * @param {Array} blocks The array of blocks to manipulate. */ export const manipulateAttributeBlockId = ( blocks ) => { blocks.forEach( ( item ) => { if ( item?.attributes ) { item.attributes.block_id = uniqString(); } if ( item?.innerBlocks?.length > 0 ) { manipulateAttributeBlockId( item.innerBlocks ); } } ); // Return the manipulated blocks. return blocks; }; /** * Adjusts the height of a textarea element based on its content. * If the content exceeds a maximum height, the element will be scrollable. * * @param {HTMLElement} node - The textarea element to adjust. * @param {number} maxHeight */ export const adjustTextAreaHeight = ( node, maxHeight = 400 ) => { if ( ! node ) { return; } node.style.height = 'auto'; if ( node.scrollHeight > maxHeight ) { node.style.height = `${ maxHeight }px`; node.style.overflowY = 'auto'; } else { node.style.height = `${ node.scrollHeight }px`; node.style.overflowY = 'hidden'; } }; /** * Converts an object's keys from snake_case to camelCase. * * @param {Object} obj - The object to convert. * @return {Object} - A new object with camelCase keys. */ export const objSnakeToCamelCase = ( obj ) => { if ( ! obj ) { return {}; } const newObj = {}; for ( const [ key, value ] of Object.entries( obj ) ) { const camelKey = key.replace( /_([a-z])/g, ( match, p1 ) => p1.toUpperCase() ); newObj[ camelKey ] = value; } return newObj; }; /** * Formats a number to display in a human-readable format. * * @param {number} num - The number to format. * @return {string} The formatted number. */ export const formatNumber = ( num ) => { if ( ! num ) { return '0'; } const thresholds = [ { magnitude: 1e12, suffix: 'T' }, { magnitude: 1e9, suffix: 'B' }, { magnitude: 1e6, suffix: 'M' }, { magnitude: 1e3, suffix: 'K' }, { magnitude: 1, suffix: '' }, ]; const { magnitude, suffix } = thresholds.find( ( { magnitude: magnitudeValue } ) => num >= magnitudeValue ); const formattedNum = ( num / magnitude ).toFixed( 1 ).replace( /\.0$/, '' ); return num < 1000 ? num.toString() : formattedNum + suffix + ( num % magnitude > 0 ? '+' : '' ); }; /** * Get color className based on the percentage. * * @param {number} percentage - The percentage. * @return {string} - The color className. */ export const getColorClass = ( percentage ) => { const colorClassNames = { default: '', warning: 'text-credit-warning', danger: 'text-credit-danger', }; if ( percentage <= 10 ) { return colorClassNames.danger; } else if ( percentage <= 20 ) { return colorClassNames.warning; } return colorClassNames.default; }; export const addHttps = ( url ) => { if ( ! /^https?:\/\//i.test( url ) ) { url = 'https://' + url; } return url; }; export const sendPostMessage = ( data, id ) => { const frame = document.getElementById( id ); if ( ! frame ) { return; } frame.contentWindow.postMessage( { call: 'zipwpPreviewDispatch', value: data, }, '*' ); }; export const copyToClipboard = ( text ) => { // Copy the text inside the text field navigator.clipboard.writeText( text ); }; export const handleCopyToClipboard = ( event, text ) => { copyToClipboard( text ); }; export const socialMediaParser = { socialMediaPrefix: { twitter: 'twitter.com/', facebook: 'facebook.com/', instagram: 'instagram.com/', linkedin: 'linkedin.com/in/', youtube: 'youtube.com/', google: 'google.com/maps/place', yelp: 'yelp.com/biz/', }, patterns: { twitter: /^(?:http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?twitter\.com\/([a-zA-Z0-9_#?&=+]+)\/?$/, linkedin: /^(?:http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?linkedin\.com\/in\/([a-zA-Z0-9-._#?&=+]+)\/?$/, facebook: /^(?:http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?facebook\.com\/([a-zA-Z0-9._@#?&=+]+)\/?$/, instagram: /^(?:http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?instagram\.com\/([a-zA-Z0-9._@?&=]+)\/?$/, youtube: /^(?:http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?youtube\.com\/([a-zA-Z0-9_#?&=+@]+)\/?$/, google: /^(?:http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?google\.com\/maps\/place\/([a-zA-Z0-9-+_.#?&=+]+)\/?$/, yelp: /^(?:http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?yelp\.com\/biz\/([a-zA-Z0-9-_#?&=+]+)\/?$/, }, validate( platform, url ) { if ( this.patterns[ platform ] ) { return this.patterns[ platform ].test( url ); } return false; }, parse( text ) { const matches = {}; Object.keys( this.patterns ).forEach( ( platform ) => { try { const match = text.match( this.patterns[ platform ] ); if ( match && match[ 1 ] ) { matches[ platform ] = { handle: match[ 1 ], prefix: match[ 0 ].replace( match[ 1 ], '' ), }; } } catch ( error ) { console.log( error ); } } ); return matches; }, }; export const isValidURL = ( url ) => { try { new URL( url ); return true; // If the URL constructor doesn't throw an error, the URL is valid } catch ( _ ) { return false; // Invalid URL } }; export const isValidImageURL = ( fileURL ) => { // regex only matches letters, numbers, spaces, dots, underscores, colons, slashes, and hyphens const validPattern = /^[a-zA-Z0-9_\-\. :/]+$/; if ( ! isValidURL( fileURL ) ) { return false; } if ( ! validPattern.test( fileURL ) ) { return false; } return true; }; const { plan_data } = aiBuilderVars?.zip_plans; export const showAISitesNotice = () => { // if only 1 AI Site is remaining if ( plan_data?.remaining?.ai_sites_count === 1 ) { return true; } const usagePercentage = ( plan_data?.usage?.ai_sites_count / plan_data?.limit?.ai_sites_count ) * 100; if ( usagePercentage >= 60 ) { return true; } return false; }; export const getPlanPromoDissmissTime = async () => { const data = await apiFetch( { path: 'zipwp/v1/get-plan-promo-dismiss-time', method: 'GET', headers: { 'X-WP-Nonce': aiBuilderVars.rest_api_nonce, 'content-type': 'application/json', }, } ); return data; }; export const getTimeDiff = ( timeToCompare ) => { const timeDiff = Math.floor( Date.now() / 1000 ) - timeToCompare; return timeDiff; };