const { CSS_CLASSES } = window; const ICON_PATHS = { checked: [ "M7.89561 14.8538L6.30462 13.2629L14.3099 5.25755L15.9009 6.84854L7.89561 14.8538Z", "M4.08643 11.0903L5.67742 9.49929L9.4485 13.2704L7.85751 14.8614L4.08643 11.0903Z" ], unchecked: [ "M5.13231 6.72963L6.7233 5.13864L14.855 13.2704L13.264 14.8614L5.13231 6.72963Z", "M13.2704 5.13864L14.8614 6.72963L6.72963 14.8614L5.13864 13.2704L13.2704 5.13864Z" ] }; const CHECKED_COLOR = "hsl(139, 47.3%, 43.9%)"; const UNCHECKED_COLOR = "hsl(218, 4.6%, 46.9%)"; function createSwitch( labelText, descriptionText, inputId, defaultChecked = false, onToggle = null ) { let isToggling = false; const container = document.createElement("div"); container.className = CSS_CLASSES.container; const checkbox = document.createElement("input"); checkbox.id = inputId; checkbox.type = "checkbox"; checkbox.className = CSS_CLASSES.input; checkbox.tabIndex = 0; checkbox.checked = defaultChecked; const sliderSVG = createSliderSVG(defaultChecked); const switchControl = document.createElement("div"); switchControl.className = `${CSS_CLASSES.switchControl} ${defaultChecked ? CSS_CLASSES.switchControlChecked : ""}`; switchControl.style.opacity = "1"; switchControl.style.backgroundColor = defaultChecked ? CHECKED_COLOR : UNCHECKED_COLOR; switchControl.style.cursor = "pointer"; switchControl.tabIndex = -1; switchControl.appendChild(sliderSVG); switchControl.appendChild(checkbox); const controlWrapper = document.createElement("div"); controlWrapper.className = CSS_CLASSES.control; controlWrapper.appendChild(switchControl); const label = document.createElement("label"); label.htmlFor = inputId; label.className = CSS_CLASSES.label; label.textContent = labelText; const labelRow = document.createElement("div"); labelRow.className = CSS_CLASSES.labelRow; labelRow.appendChild(label); labelRow.appendChild(controlWrapper); container.appendChild(labelRow); if (descriptionText) { const description = document.createElement("div"); description.className = CSS_CLASSES.description; description.textContent = descriptionText; const noteWrapper = document.createElement("div"); noteWrapper.className = CSS_CLASSES.note; noteWrapper.appendChild(description); container.appendChild(noteWrapper); } const divider = document.createElement("div"); divider.className = CSS_CLASSES.divider; container.appendChild(divider); const updateSwitch = (checked) => { switchControl.classList.toggle(CSS_CLASSES.switchControlChecked, checked); switchControl.style.backgroundColor = checked ? CHECKED_COLOR : UNCHECKED_COLOR; sliderSVG.style.left = checked ? "12px" : "-3px"; updateSVGIcon(sliderSVG, checked); }; const handleToggle = async () => { if (isToggling) return; isToggling = true; const prev = !checkbox.checked; if (typeof onToggle === "function") { try { const ret = await onToggle(checkbox.checked); if (ret === false) checkbox.checked = prev; } finally { isToggling = false; } } else { isToggling = false; } updateSwitch(checkbox.checked); }; switchControl.addEventListener("click", (e) => { if (isToggling) return; if (e.target === checkbox) return; e.preventDefault(); e.stopPropagation(); checkbox.checked = !checkbox.checked; checkbox.dispatchEvent(new Event("change", { bubbles: true })); }); checkbox.addEventListener("click", (e) => { if (isToggling) { e.stopPropagation(); e.preventDefault(); return; } }); checkbox.addEventListener("change", handleToggle); return container; } function createSliderSVG(isChecked) { const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); svg.setAttribute("class", CSS_CLASSES.slider); svg.setAttribute("viewBox", "0 0 28 20"); svg.setAttribute("preserveAspectRatio", "xMinYMid meet"); svg.style.left = isChecked ? "12px" : "-3px"; svg.style.position = "absolute"; svg.style.transition = "left 0.2s"; const circle = document.createElementNS("http://www.w3.org/2000/svg", "rect"); circle.setAttribute("fill", "white"); circle.setAttribute("x", "4"); circle.setAttribute("y", "0"); circle.setAttribute("height", "20"); circle.setAttribute("width", "20"); circle.setAttribute("rx", "10"); svg.appendChild(circle); const icon = document.createElementNS("http://www.w3.org/2000/svg", "svg"); icon.setAttribute("viewBox", "0 0 20 20"); icon.setAttribute("fill", "none"); const color = isChecked ? CHECKED_COLOR : UNCHECKED_COLOR; if (isChecked) { const checkPaths = [ "M7.89561 14.8538L6.30462 13.2629L14.3099 5.25755L15.9009 6.84854L7.89561 14.8538Z", "M4.08643 11.0903L5.67742 9.49929L9.4485 13.2704L7.85751 14.8614L4.08643 11.0903Z" ]; checkPaths.forEach(d => { const path = document.createElementNS("http://www.w3.org/2000/svg", "path"); path.setAttribute("fill", color); path.setAttribute("d", d); icon.appendChild(path); }); } else { const xPaths = [ "M5.13231 6.72963L6.7233 5.13864L14.855 13.2704L13.264 14.8614L5.13231 6.72963Z", "M13.2704 5.13864L14.8614 6.72963L6.72963 14.8614L5.13864 13.2704L13.2704 5.13864Z" ]; xPaths.forEach(d => { const path = document.createElementNS("http://www.w3.org/2000/svg", "path"); path.setAttribute("fill", color); path.setAttribute("d", d); icon.appendChild(path); }); } svg.appendChild(icon); return svg; } function createSVGIcon(parentSVG, isChecked) { const color = isChecked ? CHECKED_COLOR : UNCHECKED_COLOR; const paths = ICON_PATHS[isChecked ? "checked" : "unchecked"]; const icon = document.createElementNS("http://www.w3.org/2000/svg", "svg"); icon.setAttribute("viewBox", "0 0 20 20"); icon.setAttribute("fill", "none"); paths.forEach(d => { const path = document.createElementNS("http://www.w3.org/2000/svg", "path"); path.setAttribute("fill", color); path.setAttribute("d", d); icon.appendChild(path); }); parentSVG.appendChild(icon); } function updateSVGIcon(sliderSVG, isChecked) { const oldIcon = sliderSVG.querySelector("svg svg"); if (oldIcon) { oldIcon.remove(); } createSVGIcon(sliderSVG, isChecked); }