Agri-food and Food and Wine
Agri-food and Food and Wine
Art, Creativity, and Design
Art, Creativity, and Design
Automation and Mechatronics
Automation and Mechatronics
Automotive and Mobility
Automotive and Mobility
Biomedical and Health
Biomedical and Health
Energy and Environment
Energy and Environment
Logistics
Logistics
Mechanics, CNC and Production
Mechanics, CNC and Production
Science and Technology
Science and Technology
Tourism, Marketing and Communication
Tourism, Marketing and Communication
Services for Food and Wine and Hotel Hospitality
Services for Food and Wine and Hotel Hospitality
Water Management and Environmental Remediation
Water Management and Environmental Remediation
Industry and Craftsmanship
Industry and Craftsmanship
Maintenance and Technical Support
Maintenance and Technical Support
Food Production / Agri-food Processing
Food Production / Agri-food Processing
Audiovisual Productions
Audiovisual Productions
Industrial and artisanal productions
Industrial and artisanal productions
Commercial Services
Commercial Services
Services for agriculture and rural development
Services for agriculture and rural development
Social and Healthcare Services
Social and Healthcare Services
Agriculture, Agri-food, and Agro-industry
Agriculture, Agri-food, and Agro-industry
Administration, Finance and Marketing
Administration, Finance and Marketing
Chemistry, Materials and Biotechnology
Chemistry, Materials and Biotechnology
Construction, Environment and Territory
Construction, Environment and Territory
Electrical Engineering, Electronics, Automation
Electrical Engineering, Electronics, Automation
Graphics and Communication
Graphics and Communication
Informatics and Telecommunications
Informatics and Telecommunications
Mechanics, Mechatronics and Energy
Mechanics, Mechatronics and Energy
Fashion System
Fashion System
Transport and Logistics
Transport and Logistics
Tourism
Tourism
import React, { useEffect, useRef } from "react" import { motion } from "framer-motion" import { addPropertyControls, ControlType, RenderTarget } from "framer" /** * @framerDisableUnlink * @framerSupportedLayoutWidth any * @framerSupportedLayoutHeight auto * @framerIntrinsicWidth 400 * @framerIntrinsicHeight 600 */ export default function KrossEmbedComplete(props) { const { containerStyle, showBorder = false, borderColor = "#09F", borderRadius = 8, padding = 20, style, } = props const containerRef = useRef(null) const [isLoaded, setIsLoaded] = React.useState(false) // Carica tutti gli script e stili necessari useEffect(() => { const loadKrossWidget = () => { // Carica jQuery se non è presente if (!window.jQuery) { const jqueryScript = document.createElement("script") jqueryScript.src = "https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.4.1.min.js" jqueryScript.onload = () => { loadKrossResources() } document.head.appendChild(jqueryScript) } else { loadKrossResources() } } const loadKrossResources = () => { // Carica CSS const link = document.createElement("link") link.rel = "stylesheet" link.type = "text/css" link.href = "https://data.krossbooking.com/widget/v6/mystay/4.css" link.media = "all" document.head.appendChild(link) // Carica JS const script = document.createElement("script") script.type = "text/javascript" script.defer = true script.src = "https://data.krossbooking.com/widget/v6/mystay/4.js" script.onload = () => { setIsLoaded(true) } document.head.appendChild(script) } loadKrossWidget() }, []) // Preview per il canvas di Framer if (RenderTarget.current() === RenderTarget.canvas) { return ( <motion.div style={{ ...style, display: "flex", alignItems: "center", justifyContent: "center", backgroundColor: "#f5f5f5", border: "2px dashed #09F", borderRadius: "8px", padding: "20px", minHeight: "400px", }} initial={{ opacity: 0 }} animate={{ opacity: 1 }} > <div style={{ textAlign: "center" }}> <div style={{ fontSize: "24px", marginBottom: "10px", color: "#09F", }} > 🏨 </div> <h3 style={{ margin: "0 0 10px 0", color: "#333" }}> Widget Kross Booking </h3> <p style={{ margin: "0", color: "#666", fontSize: "14px" }}> Il widget di prenotazione sarà visibile in anteprima </p> </div> </motion.div> ) } return ( <motion.div style={{ ...style, minHeight: "400px", position: "relative", }} initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ duration: 0.3 }} > {/* Container principale con stili personalizzabili */} <div style={{ ...containerStyle, border: showBorder ? `2px solid ${borderColor}` : "none", borderRadius: `${borderRadius}px`, padding: `${padding}px`, backgroundColor: "transparent", width: "100%", minHeight: "400px", }} > {/* Container dell'embed Kross */} <div ref={containerRef} className="kross-container" style={{ width: "100%", minHeight: "400px", }} /> </div> {/* Indicatore di caricamento */} {!isLoaded && ( <div style={{ position: "absolute", top: "10px", right: "10px", background: "rgba(0,0,0,0.7)", color: "white", padding: "5px 10px", borderRadius: "4px", fontSize: "12px", }} > Caricamento... </div> )} </motion.div> ) } // Props di default KrossEmbedComplete.defaultProps = { showBorder: false, borderColor: "#09F", borderRadius: 8, padding: 20, } // Property Controls per Framer addPropertyControls(KrossEmbedComplete, { showBorder: { type: ControlType.Boolean, title: "Mostra Bordo", description: "Mostra un bordo attorno al widget", defaultValue: false, }, borderColor: { type: ControlType.Color, title: "Colore Bordo", description: "Colore del bordo", defaultValue: "#09F", hidden: (props) => !props.showBorder, }, borderRadius: { type: ControlType.Number, title: "Raggio Bordi", description: "Raggio degli angoli arrotondati", min: 0, max: 50, unit: "px", defaultValue: 8, }, padding: { type: ControlType.Number, title: "Spaziatura", description: "Spaziatura interna del container", min: 0, max: 100, unit: "px", defaultValue: 20, }, }) // Estendi il tipo Window per includere jQuery declare global { interface Window { jQuery: any } }