Agroalimentare e Enogastronomia
Agroalimentare e Enogastronomia
Arte, Creatività e Design
Arte, Creatività e Design
Automazione e Meccatronica
Automazione e Meccatronica
Automotive e Mobilità
Automotive e Mobilità
Biomedicale e Salute
Biomedicale e Salute
Energia e Ambiente
Energia e Ambiente
Logistica
Logistica
Meccanica, CNC e Produzione
Meccanica, CNC e Produzione
Scienze e Tecnologie
Scienze e Tecnologie
Turismo, Marketing e Comunicazione
Turismo, Marketing e Comunicazione
Servizi per l’Enogastronomia e l’Ospitalità Alberghiera
Servizi per l’Enogastronomia e l’Ospitalità Alberghiera
Gestione delle Acque e Risanamento Ambientale
Gestione delle Acque e Risanamento Ambientale
Industria e Artigianato
Industria e Artigianato
Manutenzione e assistenza tecnica
Manutenzione e assistenza tecnica
Produzioni alimentari / Trasformazioni agroalimentari
Produzioni alimentari / Trasformazioni agroalimentari
Produzioni Audiovisive
Produzioni Audiovisive
Produzioni industriali e artigianali
Produzioni industriali e artigianali
Servizi commerciali
Servizi commerciali
Servizi per l’agricoltura e lo sviluppo rurale
Servizi per l’agricoltura e lo sviluppo rurale
Servizi Socio-Sanitari
Servizi Socio-Sanitari
Agraria, Agroalimentare e Agroindustria
Agraria, Agroalimentare e Agroindustria
Amministrazione, Finanza e Marketing
Amministrazione, Finanza e Marketing
Chimica, Materiali e Biotecnologie
Chimica, Materiali e Biotecnologie
Costruzioni, Ambiente e Territorio
Costruzioni, Ambiente e Territorio
Elettrotecnica, Elettronica, Automazione
Elettrotecnica, Elettronica, Automazione
Grafica e Comunicazione
Grafica e Comunicazione
Informatica e Telecomunicazioni
Informatica e Telecomunicazioni
Meccanica, Meccatronica ed Energia
Meccanica, Meccatronica ed Energia
Sistema Moda
Sistema Moda
Trasporti e Logistica
Trasporti e Logistica
Turismo
Turismo
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 } }