/** * WordPress dependencies */ import type { dispatch as Dispatch, select as Select, } from '@safe-wordpress/data'; /** * External dependencies */ import type { CssWorkingContentValue, Maybe } from '@nab/types'; /** * Internal dependencies */ import { isSelectorTag, isTag } from './is-tag'; import { isContentEditableSelector } from '../../../../../../../assets/src/admin/scripts/css-selector-finder/editable-content'; import { elementReady } from '../../../../../../../assets/src/public/utils/helpers/element-ready'; import type { AlternativeAttributes } from '../../../../../../../packages/experiment-library/css/types'; /* eslint-disable */ const parent = window.parent as any; const dispatch = parent.wp.data.dispatch as typeof Dispatch; const select = parent.wp.data.select as typeof Select; /* eslint-enable */ // NOTE. No @nab packages in front. import type { store as dataStore } from '@nab/data'; const NAB_DATA = 'nab/data' as unknown as typeof dataStore; // NOTE. No @nab packages in front. import type { store as editorStore } from '@nab/editor'; const NAB_EDITOR = 'nab/editor' as unknown as typeof editorStore; type CssContentValue = AlternativeAttributes[ 'content' ][ number ]; export function initContentValues(): void { const editor = select( NAB_DATA ).getPageAttribute( 'css-editor/cssEditorState' ); if ( ! editor ) { return; } const alternative = select( NAB_EDITOR ).getAlternative< AlternativeAttributes >( editor.alternativeId ) ?.attributes; if ( ! alternative ) { return; } const contentValues = alternative.content.map( ( cv ) => updateContentValue( cv, querySelector( cv.selector ) ) ); const activeSelector = ( (): string => { if ( editor.activeSelector ) { return editor.activeSelector; } if ( editor.mode === 'content-editor' ) { const value = contentValues.find( ( cv ) => 'active' === cv.status ) || contentValues[ 0 ]; return value?.selector || ''; } return ''; } )(); void dispatch( NAB_DATA ).setPageAttribute( 'css-editor/cssEditorState', { ...editor, contentValues, activeSelector, } ); contentValues .filter( ( cv ) => cv.status === 'waiting-for-element' ) .forEach( ( pendingContentValue ) => elementReady( pendingContentValue.selector, ( el ) => { const currentEditor = select( NAB_DATA ).getPageAttribute( 'css-editor/cssEditorState' ); if ( ! currentEditor ) { return; } const currentContentValues = currentEditor.contentValues.map( ( cv ): CssWorkingContentValue => cv.selector === pendingContentValue.selector ? updateContentValue( cv, el ) : cv ); void dispatch( NAB_DATA ).setPageAttribute( 'css-editor/cssEditorState', { ...currentEditor, contentValues: currentContentValues, } ); } ) ); } // ======= // HELPERS // ======= function querySelector( s: string ): Maybe< HTMLElement > { try { return document.querySelector< HTMLElement >( s ) || undefined; } catch ( _ ) { return undefined; } } function isImage( el: Maybe< Element > ): el is HTMLImageElement { return 'IMG' === el?.nodeName; } function updateContentValue( cv: CssContentValue, el: Maybe< HTMLElement > ): CssWorkingContentValue { const status = ( () => { if ( ! el ) { return 'waiting-for-element'; } return isContentEditableSelector( cv.selector ) ? 'active' : 'inactive'; } )(); switch ( cv.type ) { case 'element': return { type: 'element', selector: cv.selector, html: cv.html, originalHtml: el?.innerHTML || '', formats: { bold: el ? isTag( el, [ 'B', 'STRONG' ] ) : isSelectorTag( cv.selector, [ 'B', 'STRONG' ] ), link: el ? isTag( el, [ 'A' ] ) : isSelectorTag( cv.selector, [ 'A' ] ), italic: el ? isTag( el, [ 'I', 'EM' ] ) : isSelectorTag( cv.selector, [ 'I', 'EM' ] ), underline: el ? isTag( el, [ 'U' ] ) : isSelectorTag( cv.selector, [ 'U' ] ), }, status, }; case 'image': return { type: 'image', selector: cv.selector, src: cv.src, alt: cv.alt, originalSrc: isImage( el ) ? el.src : '', originalAlt: isImage( el ) ? el.alt : '', status, }; } }