@zinnect-test/embed-react
Version:
React package for embedding Zinnect booking widget
230 lines (203 loc) • 7.06 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
/**
* @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);
}
};
}
exports.default = getBookingApi;
exports.getBookingApi = getBookingApi;
//# sourceMappingURL=index.js.map