UNPKG

@zinnect-test/embed-react

Version:

React package for embedding Zinnect booking widget

225 lines (200 loc) 6.96 kB
/** * @zinnect/embed-react * React package for embedding Zinnect booking widget */ /** * Load the embed script dynamically * @param {string} embedUrl - The URL to the embed.js file * @returns {Promise<void>} */ function loadScript(embedUrl) { return new Promise((resolve, reject) => { // Check if script is already loaded const existingScript = document.querySelector(`script[src="${embedUrl}"]`); if (existingScript) { // Wait for Booking to be available if (window.Booking && window.Booking.loaded) { resolve(); return; } // Wait a bit for the script to load const checkInterval = setInterval(() => { if (window.Booking && window.Booking.loaded) { clearInterval(checkInterval); resolve(); } }, 50); return; } // Check if Booking is already defined if (window.Booking) { resolve(); return; } const script = document.createElement("script"); script.type = "text/javascript"; script.src = embedUrl; script.async = true; script.onload = () => { // Wait for Booking to be available const checkInterval = setInterval(() => { if (window.Booking) { window.Booking.loaded = true; clearInterval(checkInterval); resolve(); } }, 50); // Timeout after 5 seconds setTimeout(() => { clearInterval(checkInterval); if (!window.Booking) { reject(new Error("Failed to load Booking script")); } }, 5000); }; script.onerror = () => { reject(new Error(`Failed to load script from ${embedUrl}`)); }; document.head.appendChild(script); }); } /** * Get the Booking API for a specific namespace * @param {Object} config - Configuration object * @param {string} config.namespace - Namespace identifier * @param {string} [config.origin] - Origin URL for the booking API * @param {string} [config.embedUrl] - Custom embed.js URL (defaults to {origin}/embed/embed.js) * @returns {Promise<Function>} - Booking API function for the namespace */ async function getBookingApi(config = {}) { const { namespace, origin, embedUrl } = config; if (!namespace) { throw new Error("namespace is required"); } // Determine embed URL let scriptUrl = embedUrl; if (!scriptUrl) { if (origin) { scriptUrl = `${origin}/embed/embed.js`; } else { scriptUrl = `${window.location.origin}/embed/embed.js`; } } // Load the embed script await loadScript(scriptUrl); // Initialize namespace if provided if (namespace) { // Initialize Booking namespace if (!window.Booking.ns || !window.Booking.ns[namespace]) { window.Booking("init", namespace, { origin: origin || window.location.origin, }); } } // Auto-initialize elements with data-booking attributes (similar to embed.js autoInit) function autoInitElements() { // Only run if we're in a browser environment if (typeof document === "undefined") return; const elements = document.querySelectorAll("[data-booking-link]"); elements.forEach(function (element) { const elementNamespace = element.getAttribute("data-booking-namespace"); const bookingLink = element.getAttribute("data-booking-link"); if (bookingLink && elementNamespace) { // Initialize namespace if needed if (!window.Booking.ns || !window.Booking.ns[elementNamespace]) { window.Booking("init", elementNamespace, { origin: origin || window.location.origin, }); } // Attach click handler if not already attached if (!element.hasAttribute("data-booking-initialized")) { element.setAttribute("data-booking-initialized", "true"); window.Booking("inline", { elementOrSelector: element, bookingLink: bookingLink, namespace: elementNamespace, }); } } }); } // Run auto-init immediately and on DOM ready if (typeof document !== "undefined") { if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", autoInitElements); } else { autoInitElements(); } } // Return the namespace API function return function bookingApi(method, ...args) { if (!window.Booking) { console.error("Booking API not loaded"); return; } if (namespace && window.Booking.ns && window.Booking.ns[namespace]) { // Use namespace-specific API if (method === "ui") { // Set UI configuration // Try namespace function first (if loader script initialized it), otherwise use Booking() format const uiConfig = args[0] || {}; if (typeof window.Booking.ns[namespace] === "function") { // Namespace is callable (initialized by loader script) window.Booking.ns[namespace]("ui", uiConfig); } else { // Use Booking("ui", uiConfig, namespace) format as per embed.js window.Booking("ui", uiConfig, namespace); } } else if (method === "inline") { // Inline booking const options = args[0] || {}; window.Booking("inline", { ...options, namespace: namespace, origin: origin || window.Booking.ns[namespace]?.origin || window.location.origin, }); } else if (method === "open") { // Open booking modal const options = args[0] || {}; const bookingLink = options.bookingLink || args[0]?.bookingLink; // Get UI config from namespace let uiConfig = {}; if (window.Booking.ns[namespace]) { uiConfig = window.Booking.ns[namespace].uiConfig || {}; } // Merge with provided config if (options.config) { uiConfig = { ...uiConfig, ...options.config }; } // Create a temporary element to trigger booking const tempElement = document.createElement("div"); tempElement.setAttribute("data-booking-link", bookingLink || ""); tempElement.setAttribute("data-booking-namespace", namespace); if (Object.keys(uiConfig).length > 0) { tempElement.setAttribute( "data-booking-config", JSON.stringify(uiConfig) ); } // Trigger the booking window.Booking("inline", { elementOrSelector: tempElement, bookingLink: bookingLink, namespace: namespace, layout: uiConfig.layout || "month", }); } else { // Forward other methods to Booking API with namespace window.Booking(method, ...args, namespace); } } else { // Fallback to global Booking API window.Booking(method, ...args); } }; } export { getBookingApi as default, getBookingApi }; //# sourceMappingURL=index.esm.js.map