Agrar- und Genussmittel
Agrar- und Genussmittel
Kunst, Kreativität und Design
Kunst, Kreativität und Design
Automatisierung und Mechatronik
Automatisierung und Mechatronik
Automotive und Mobilität
Automotive und Mobilität
Biomedizin und Gesundheit
Biomedizin und Gesundheit
Energie und Umwelt
Energie und Umwelt
Logistik
Logistik
Mechanik, CNC und Produktion
Mechanik, CNC und Produktion
Wissenschaften und Technologien
Wissenschaften und Technologien
Tourismus, Marketing und Kommunikation
Tourismus, Marketing und Kommunikation
Dienstleistungen für die Gastronomie und die Hotellerie
Dienstleistungen für die Gastronomie und die Hotellerie
Wassermanagement und Umweltsanierung
Wassermanagement und Umweltsanierung
Industrie und Handwerk
Industrie und Handwerk
Wartung und technische Unterstützung
Wartung und technische Unterstützung
Lebensmittelproduktion / Agrarverarbeitung
Lebensmittelproduktion / Agrarverarbeitung
Audiovisuelle Produktionen
Audiovisuelle Produktionen
Industrielle und handwerkliche Produkte
Industrielle und handwerkliche Produkte
Geschäftsdienstleistungen
Geschäftsdienstleistungen
Dienstleistungen für Landwirtschaft und ländliche Entwicklung
Dienstleistungen für Landwirtschaft und ländliche Entwicklung
Sozial- und Gesundheitsdienste
Sozial- und Gesundheitsdienste
Agrarwirtschaft, Ernährungswirtschaft und Agrarindustrie
Agrarwirtschaft, Ernährungswirtschaft und Agrarindustrie
Verwaltung, Finanzen und Marketing
Verwaltung, Finanzen und Marketing
Chemie, Materialien und Biotechnologien
Chemie, Materialien und Biotechnologien
Bau, Umwelt und Territorium
Bau, Umwelt und Territorium
Elektrotechnik, Elektronik, Automatisierung
Elektrotechnik, Elektronik, Automatisierung
Grafik und Kommunikation
Grafik und Kommunikation
Informatik und Telekommunikation
Informatik und Telekommunikation
Mechanik, Mechatronik und Energie
Mechanik, Mechatronik und Energie
Modensystem
Modensystem
Transport und Logistik
Transport und Logistik
Tourismus
Tourismus
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) // Lade alle benötigten Skripte und Stile useEffect(() => { const loadKrossWidget = () => { // Lade jQuery, wenn es nicht vorhanden ist 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 = () => { // Lade 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) // Lade 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() }, []) // Vorschau für das Framer-Canvas 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" }}> Kross Booking Widget </h3> <p style={{ margin: "0", color: "#666", fontSize: "14px" }}> Das Buchungs-Widget wird in der Vorschau angezeigt </p> </div> </motion.div> ) } return ( <motion.div style={{ ...style, minHeight: "400px", position: "relative", }} initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ duration: 0.3 }} > {/* Hauptcontainer mit anpassbaren Stilen */} <div style={{ ...containerStyle, border: showBorder ? `2px solid ${borderColor}` : "none", borderRadius: `${borderRadius}px`, padding: `${padding}px`, backgroundColor: "transparent", width: "100%", minHeight: "400px", }} > {/* Kross-Embed-Container */} <div ref={containerRef} className="kross-container" style={{ width: "100%", minHeight: "400px", }} /> </div> {/* Ladeindikator */} {!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", }} > Laden... </div> )} </motion.div> ) } // Standard-Props KrossEmbedComplete.defaultProps = { showBorder: false, borderColor: "#09F", borderRadius: 8, padding: 20, } // Property Controls für Framer addPropertyControls(KrossEmbedComplete, { showBorder: { type: ControlType.Boolean, title: "Rand anzeigen", description: "Zeigt einen Rand um das Widget an", defaultValue: false, }, borderColor: { type: ControlType.Color, title: "Randfarbe", description: "Farbe des Randes", defaultValue: "#09F", hidden: (props) => !props.showBorder, }, borderRadius: { type: ControlType.Number, title: "Eckenradius", description: "Radius der abgerundeten Ecken", min: 0, max: 50, unit: "px", defaultValue: 8, }, padding: { type: ControlType.Number, title: "Innenabstand", description: "Innenabstand des Containers", min: 0, max: 100, unit: "px", defaultValue: 20, }, }) // Erweiterung des Window-Typs zur Einbeziehung von jQuery declare global { interface Window { jQuery: any } }