HEX
Server: Apache
System: Linux d5123.usc1.stableserver.net 5.14.0-570.17.1.el9_6.x86_64 #1 SMP PREEMPT_DYNAMIC Sat May 24 12:53:17 EDT 2025 x86_64
User: d5123 (1001)
PHP: 8.4.21
Disabled: NONE
Upload Files
File: /home/d5123/myboofola_com/wp-content/plugins/extendify/src/Toolbar/toolbar.js
/**
 * Simple toolbar bootstrap.
 *
 * Vanilla JS bound to the bar that `Frontend::render()` writes at
 * `wp_body_open`. Three integrations:
 *
 *   - "AI Agent" button → drives the Extendify Agent's mounted
 *     admin-bar button (the bar is hidden via CSS but stays in the
 *     DOM so the Agent's React code can still target it).
 *   - "Quick Edit" toggle → dispatches a custom event the Quick Edit
 *     bootstrap listens for. Aria-checked mirrors the
 *     `extendify-quick-edit-on` class on `<html>` so the toggle
 *     reflects state changes from any source (admin-bar pill,
 *     chat-input "Select" button, etc.).
 *   - When the Agent sidebar opens, the toolbar slides next to it
 *     so the rounded-frame layout matches what the Agent does to
 *     the core admin bar.
 */
import { isEmbedded } from '@shared/lib/embedded-guard';
import { __ } from '@wordpress/i18n';
import './toolbar.css';

const QUICK_EDIT_TOGGLE_EVENT = 'extendify-quick-edit:toggle';
const QUICK_EDIT_ON_CLASS = 'extendify-quick-edit-on';
const AGENT_BTN_HOST_ID = 'wp-admin-bar-extendify-agent-btn';
const AGENT_SIDEBAR_ID = 'extendify-agent-sidebar';

function findExtendifyAgentButton() {
	const host = document.getElementById(AGENT_BTN_HOST_ID);
	if (!host) return null;
	return host.querySelector('button') || host;
}

function clickExtendifyAgent() {
	const btn = findExtendifyAgentButton();
	if (btn) {
		btn.click();
		return true;
	}
	return false;
}

function waitFor(predicate, maxTries, intervalMs) {
	return new Promise((resolve, reject) => {
		let tries = 0;
		const tick = () => {
			if (predicate()) return resolve();
			if (++tries >= maxTries) return reject();
			setTimeout(tick, intervalMs);
		};
		tick();
	});
}

/**
 * When the Agent sidebar opens we want the toolbar to slide next
 * to it (matches how the Agent reframes the core admin bar). We
 * watch the sidebar's `inert` attribute rather than subscribing to
 * the Zustand store so we don't have to share a chunk with the
 * agent bundle.
 */
function watchAgentSidebar(toolbar, aiBtn) {
	let attached = false;
	const observer = new MutationObserver(() => {
		const sidebar = document.getElementById(AGENT_SIDEBAR_ID);
		if (!sidebar || attached) return;
		attached = true;
		const update = () => {
			const open = !sidebar.hasAttribute('inert');
			toolbar.classList.toggle('ext-tb-agent-open', open);
			if (!aiBtn) return;
			aiBtn.inert = open;
			if (open) {
				aiBtn.setAttribute('tabindex', '-1');
				aiBtn.setAttribute('aria-hidden', 'true');
			} else {
				aiBtn.removeAttribute('tabindex');
				aiBtn.removeAttribute('aria-hidden');
			}
		};
		new MutationObserver(update).observe(sidebar, {
			attributes: true,
			attributeFilter: ['inert'],
		});
		update();
	});
	observer.observe(document.body, { childList: true, subtree: true });
	if (document.getElementById(AGENT_SIDEBAR_ID)) observer.takeRecords();
}

/**
 * Mirror Quick Edit's `extendify-quick-edit-on` html-class onto
 * `aria-checked` so the visual toggle reflects state changes from
 * any source (admin-bar pill, chat input Select button, …).
 */
function watchQuickEditState(btn) {
	const sync = () => {
		const on = document.documentElement.classList.contains(QUICK_EDIT_ON_CLASS);
		btn.setAttribute('aria-checked', on ? 'true' : 'false');
	};
	sync();
	new MutationObserver(sync).observe(document.documentElement, {
		attributes: true,
		attributeFilter: ['class'],
	});
}

function init() {
	// Don't wire the toolbar inside another tool's iframe (Customizer preview,
	// page-builder previews). The server skips rendering it there too.
	if (isEmbedded()) return;
	const toolbar = document.getElementById('extendify-toolbar');
	if (!toolbar) return;

	const aiBtn = document.getElementById('ext-tb-ai-agent');
	const quickBtn = document.getElementById('ext-tb-quick-edit');

	if (aiBtn) {
		aiBtn.disabled = true;
		aiBtn.title = __('Loading…', 'extendify-local');
		aiBtn.setAttribute('aria-busy', 'true');
		waitFor(findExtendifyAgentButton, 100, 50).then(
			() => {
				aiBtn.disabled = false;
				aiBtn.removeAttribute('title');
				aiBtn.setAttribute('aria-busy', 'false');
			},
			() => {
				aiBtn.title = __('AI Agent unavailable', 'extendify-local');
				aiBtn.setAttribute('aria-busy', 'false');
			},
		);
		aiBtn.addEventListener('click', (e) => {
			e.preventDefault();
			if (!clickExtendifyAgent()) {
				waitFor(findExtendifyAgentButton, 20, 50).then(clickExtendifyAgent);
			}
		});
	}

	if (quickBtn) {
		watchQuickEditState(quickBtn);
		quickBtn.addEventListener('click', (e) => {
			e.preventDefault();
			window.dispatchEvent(new CustomEvent(QUICK_EDIT_TOGGLE_EVENT));
		});
	}

	watchAgentSidebar(toolbar, aiBtn);
}

if (document.readyState === 'loading') {
	document.addEventListener('DOMContentLoaded', init);
} else {
	init();
}