Updated to new Settings page

This commit is contained in:
nuttylmao
2025-04-23 04:45:52 +10:00
parent 076ade1f54
commit c4d1b67312
10 changed files with 666 additions and 737 deletions
+40 -38
View File
@@ -2,49 +2,51 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="../../.resources/logo.png" type="image/png">
<title>Settings</title>
<link rel="stylesheet" href="style.css">
<script type="text/javascript" src="https://unpkg.com/@streamerbot/client/dist/streamerbot-client.js"></script>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Settings</title>
<link rel="stylesheet" href="style.css">
<script type="text/javascript" src="https://unpkg.com/@streamerbot/client/dist/streamerbot-client.js"></script>
</head>
<body>
<div id="pinned-header">
<div style="display: flex; align-items: center; padding-bottom: 20px;">
<img src="../../.resources/logo.png" style="height: 40px;"/>
<button style="display: flex; width: auto; margin-left: auto; background: var(--accent-color);" onclick="OpenMembershipPage()">Check out my premium widgets</button>
</div>
<h2>Widget URL</h2>
<input id="widget-url" type="text" readonly onfocus="this.select();">
<div style="display: flex; gap: 10px;">
<button id="save-settings">Click to copy URL</button>
<button onclick="OpenLoadSettingsPopup()">Load Settings</button>
</div>
<!-- <button onclick="OpenMembershipPage()">💎 Member Exclusive Widgets</button> -->
</div>
<div id="settings-container">
<div id="settings-content"></div>
</div>
<script src="script.js"></script>
<div id="mommy-milkers">
<div id="load-settings-container">
<h2>Load Settings</h2>
<label style="font-size: 0.8em;">Paste in your existing widget URL</label>
<input id="load-url" type="text">
<div style="display: flex;">
<button id="cancel-settings" onclick="CloseSettings()">Cancel</button>
<span style="width: 20px;"></span>
<button id="load-settings" onclick="LoadSettings()">Load Settings</button>
</div>
<!-- Header -->
<div id="header">
<img src="../../.resources/logo.png" style="height: 40px;" />
<button id="membershipsButton" onclick="OpenMembershipPage()">Check out my member exclusive widgets!</button>
<div id="widgetUrlInputWrapper">
<span id="urlLabel">Click to copy URL</span>
<input id="widgetUrlInput" type="text" readonly onclick="CopyURLToClipboard()">
</div>
<button id="loadSettingsButton" onclick="OpenLoadSettingsPopup()">Load Settings</button>
</div>
</div>
<!-- Main Content Area -->
<div id="contentArea">
<!-- Settings Panel -->
<div id="settingsPanel">
</div>
<!-- Widget Preview Panel -->
<iframe id="widgetPreview">
</iframe>
</div>
<!-- Load Settings Popup -->
<div id="loadSettingsWrapper">
<div id="loadSettingsContainer">
<h2>Load Settings</h2>
<label style="font-size: 0.8em;">Paste in your existing widget URL</label>
<input id="loadUrlBox" type="text" style="width: 100%;">
<div style="display: flex; gap: 20px">
<button id="cancelSettingsButton" onclick="CloseSettings()">Cancel</button>
<button style="background-color: var(--accent-color);" onclick="LoadSettings()">Load Settings</button>
</div>
</div>
</div>
</body>
</html>
</html>
<script src="script.js"></script>
+293 -282
View File
@@ -2,6 +2,231 @@
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
const settingsJson = urlParams.get("settingsJson") || "";
const widgetURL = urlParams.get("widgetURL") || "";
// Page elements
const widgetUrlInputWrapper = document.getElementById('widgetUrlInputWrapper');
const widgetUrlInput = document.getElementById('widgetUrlInput');
const urlLabel = document.getElementById('urlLabel');
const settingsPanel = document.getElementById('settingsPanel');
const widgetPreview = document.getElementById('widgetPreview');
const loadURLBox = document.getElementById('loadUrlBox');
const cancelSettingsButton = document.getElementById('cancelSettingsButton');
const loadSettingsBox = document.getElementById('loadSettingsWrapper');
/////////////////////////////
// LOAD FROM SETTINGS.JSON //
/////////////////////////////
fetch(settingsJson)
.then(response => response.json())
.then(data => {
const groupedSettings = {};
// Group settings by their 'group' property
data.settings.forEach(setting => {
if (!groupedSettings[setting.group]) {
groupedSettings[setting.group] = [];
}
groupedSettings[setting.group].push(setting);
});
// Render settings for each group
for (const groupName in groupedSettings) {
const groupDiv = document.createElement('div');
groupDiv.classList.add('setting-group');
const groupHeader = document.createElement('h2');
groupHeader.textContent = groupName;
groupDiv.appendChild(groupHeader);
groupedSettings[groupName].forEach(setting => {
const settingItem = document.createElement('div');
settingItem.classList.add('setting-item');
settingItem.id = `item-${setting.id}`;
const labelDescriptionDiv = document.createElement('div');
if (setting.label) {
const label = document.createElement('label');
label.textContent = setting.label;
labelDescriptionDiv.appendChild(label);
}
if (setting.description) {
const description = document.createElement('p');
description.innerHTML = setting.description;
labelDescriptionDiv.appendChild(description);
}
const settingItemContent = document.createElement('div');
settingItemContent.classList.add('setting-item-content');
let inputElement;
switch (setting.type) {
case 'text':
inputElement = document.createElement('input');
inputElement.type = 'text';
inputElement.id = setting.id; //Added setting ID
inputElement.value = setting.defaultValue;
break;
case 'checkbox':
const labelDiv = document.createElement('label');
labelDiv.classList.add('switch');
checkBoxElement = document.createElement('input');
checkBoxElement.type = 'checkbox';
checkBoxElement.id = setting.id;
checkBoxElement.checked = setting.defaultValue;
labelDiv.appendChild(checkBoxElement);
const slider = document.createElement('span');
slider.classList.add('slider');
slider.classList.add('round');
labelDiv.appendChild(slider);
// Add event listener to the switchDiv
labelDiv.addEventListener('click', () => {
checkBoxElement.checked = !checkBoxElement.checked;
UpdateSettingItemVisibility();
});
inputElement = labelDiv;
break;
case 'select':
inputElement = document.createElement('select');
inputElement.id = setting.id; //Added setting ID
setting.options.forEach(option => {
const optionElement = document.createElement('option');
optionElement.value = option.value;
optionElement.textContent = option.label;
if (option === setting.defaultValue) {
optionElement.selected = true;
}
inputElement.appendChild(optionElement);
});
inputElement.value = setting.defaultValue;
break;
case 'color':
inputElement = document.createElement('input');
inputElement.type = 'color';
inputElement.id = setting.id; //Added setting ID
inputElement.value = setting.defaultValue;
break;
case 'number':
inputElement = document.createElement('input');
inputElement.type = 'number';
inputElement.id = setting.id; //Added setting ID
inputElement.value = setting.defaultValue;
inputElement.min = setting.min;
inputElement.max = setting.max;
inputElement.step = setting.step;
break;
case 'sb-actions':
inputElement = document.createElement('input');
inputElement.type = 'text';
inputElement.placeholder = 'Type to search...';
inputElement.id = setting.id; //Added setting ID
inputElement.value = setting.defaultValue;
inputElement.setAttribute('list', 'streamer-bot-actions');
inputElement.autocomplete = 'off';
break;
case 'button':
inputElement = document.createElement('button');
inputElement.id = setting.id; //Added setting ID
inputElement.textContent = setting.label;
inputElement.addEventListener('click', () => {
widgetPreview.contentWindow.callFunction(setting.callFunction);
const defaultBackgroundColor = "#2e2e2e";
const defaultTextColor = "white";
inputElement.style.transitionDuration = '0s'
inputElement.style.backgroundColor = "#2196f3"
inputElement.style.color = "#ffffff";
setTimeout(() => {
inputElement.style.transitionDuration = '0.2s'
inputElement.style.backgroundColor = defaultBackgroundColor;
inputElement.style.color = defaultTextColor;
}, 100);
});
break;
default:
inputElement = document.createElement('input');
inputElement.type = 'text';
inputElement.id = setting.id; //Added setting ID
inputElement.value = setting.defaultValue;
}
inputElement.addEventListener('input', function (event) {
RefreshWidgetPreview(data);
});
settingItemContent.appendChild(inputElement);
if (setting.type == 'button') {
settingItem.style.display = 'block'
settingItem.appendChild(settingItemContent);
}
else {
settingItem.appendChild(labelDescriptionDiv);
settingItem.appendChild(settingItemContent);
}
groupDiv.appendChild(settingItem);
});
settingsPanel.appendChild(groupDiv);
}
function UpdateSettingItemVisibility() {
data.settings.forEach(setting => {
if (setting.showIf) {
if (!document.getElementById(setting.showIf).checked)
document.getElementById(`item-${setting.id}`).style.display = 'none'
else
document.getElementById(`item-${setting.id}`).style.display = 'flex'
}
});
}
UpdateSettingItemVisibility();
RefreshWidgetPreview(data);
})
.catch(error => console.error('Error loading settings:', error));
function RefreshWidgetPreview(data) {
const settings = {};
data.settings.forEach(setting => {
let inputElement = document.getElementById(setting.id);
if (setting.type === 'checkbox') {
settings[setting.id] = inputElement.checked;
} else {
settings[setting.id] = inputElement.value;
}
});
// Generate parameter string
const paramString = Object.entries(settings)
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
.join('&');
console.debug('Parameter String:', paramString);
widgetUrlInput.value = widgetURL + "?" + paramString;
widgetPreview.src = widgetUrlInput.value;
}
//////////////////
// STREAMER.BOT //
//////////////////
// Connect to Streamer.bot and get list of actions
const sbServerAddress = '127.0.0.1';
@@ -14,8 +239,8 @@ const client = new StreamerbotClient({
console.log(`Streamer.bot successfully connected to ${sbServerAddress}:${sbServerPort}`)
console.debug(data);
// Get list of actions
GetSBActions();
// Get list of actions
GetSBActions();
},
onDisconnect: () => {
@@ -24,310 +249,96 @@ const client = new StreamerbotClient({
});
async function GetSBActions() {
const response = await client.getActions();
const response = await client.getActions();
console.debug(response);
const datalistElement = document.createElement('datalist');
datalistElement.id = 'streamer-bot-actions';
console.debug(response);
for (const action of response.actions)
{
const option = document.createElement('option');
option.value = action.name;
datalistElement.appendChild(option);
}
const datalistElement = document.createElement('datalist');
datalistElement.id = 'streamer-bot-actions';
document.body.appendChild(datalistElement);
}
for (const action of response.actions) {
const option = document.createElement('option');
option.value = action.name;
datalistElement.appendChild(option);
}
document.addEventListener('DOMContentLoaded', () => {
const settingsContent = document.getElementById('settings-content');
const saveButton = document.getElementById('save-settings');
fetch(settingsJson)
.then(response => response.json())
.then(data => {
const groupedSettings = {};
// Group settings by their 'group' property
data.settings.forEach(setting => {
if (!groupedSettings[setting.group]) {
groupedSettings[setting.group] = [];
}
groupedSettings[setting.group].push(setting);
});
// Render settings for each group
for (const groupName in groupedSettings) {
const groupDiv = document.createElement('div');
groupDiv.classList.add('setting-group');
const groupHeader = document.createElement('h2');
groupHeader.textContent = groupName;
groupDiv.appendChild(groupHeader);
groupedSettings[groupName].forEach(setting => {
const settingItem = document.createElement('div');
settingItem.classList.add('setting-item');
settingItem.id = `item-${setting.id}`;
const labelDescriptionDiv = document.createElement('div');
if (setting.label) {
const label = document.createElement('label');
label.textContent = setting.label;
labelDescriptionDiv.appendChild(label);
}
if (setting.description) {
const description = document.createElement('p');
description.innerHTML = setting.description;
labelDescriptionDiv.appendChild(description);
}
const settingItemContent = document.createElement('div');
settingItemContent.classList.add('setting-item-content');
let inputElement;
switch (setting.type) {
case 'text':
inputElement = document.createElement('input');
inputElement.type = 'text';
inputElement.id = setting.id; //Added setting ID
inputElement.value = setting.defaultValue;
break;
case 'checkbox':
const labelDiv = document.createElement('label');
labelDiv.classList.add('switch');
checkBoxElement = document.createElement('input');
checkBoxElement.type = 'checkbox';
checkBoxElement.id = setting.id;
checkBoxElement.checked = setting.defaultValue;
labelDiv.appendChild(checkBoxElement);
const slider = document.createElement('span');
slider.classList.add('slider');
slider.classList.add('round');
labelDiv.appendChild(slider);
// Add event listener to the switchDiv
labelDiv.addEventListener('click', () => {
checkBoxElement.checked = !checkBoxElement.checked;
UpdateSettingItemVisibility();
});
inputElement = labelDiv;
break;
case 'select':
inputElement = document.createElement('select');
inputElement.id = setting.id; //Added setting ID
setting.options.forEach(option => {
const optionElement = document.createElement('option');
optionElement.value = option.value;
optionElement.textContent = option.label;
if (option === setting.defaultValue) {
optionElement.selected = true;
}
inputElement.appendChild(optionElement);
});
inputElement.value = setting.defaultValue;
break;
case 'color':
inputElement = document.createElement('input');
inputElement.type = 'color';
inputElement.id = setting.id; //Added setting ID
inputElement.value = setting.defaultValue;
break;
case 'number':
inputElement = document.createElement('input');
inputElement.type = 'number';
inputElement.id = setting.id; //Added setting ID
inputElement.value = setting.defaultValue;
inputElement.min = setting.min;
inputElement.max = setting.max;
inputElement.step = setting.step;
break;
case 'sb-actions':
inputElement = document.createElement('input');
inputElement.type = 'text';
inputElement.placeholder = 'Type to search...';
inputElement.id = setting.id; //Added setting ID
inputElement.value = setting.defaultValue;
inputElement.setAttribute('list', 'streamer-bot-actions');
inputElement.autocomplete = 'off';
break;
case 'button':
inputElement = document.createElement('button');
inputElement.id = setting.id; //Added setting ID
inputElement.textContent = setting.label;
inputElement.addEventListener('click', () => {
window.parent.callFunction(setting.callFunction);
const defaultBackgroundColor = "#2e2e2e";
const defaultTextColor = "white";
inputElement.style.transitionDuration = '0s'
inputElement.style.backgroundColor = "#2196f3"
inputElement.style.color = "#ffffff";
setTimeout(() => {
inputElement.style.transitionDuration = '0.2s'
inputElement.style.backgroundColor = defaultBackgroundColor;
inputElement.style.color = defaultTextColor;
}, 100);
});
break;
default:
inputElement = document.createElement('input');
inputElement.type = 'text';
inputElement.id = setting.id; //Added setting ID
inputElement.value = setting.defaultValue;
}
inputElement.addEventListener('input', function (event) {
SendDataToParent(data);
});
settingItemContent.appendChild(inputElement);
if (setting.type == 'button')
{
settingItem.style.display = 'block'
settingItem.appendChild(settingItemContent);
}
else
{
settingItem.appendChild(labelDescriptionDiv);
settingItem.appendChild(settingItemContent);
}
groupDiv.appendChild(settingItem);
});
settingsContent.appendChild(groupDiv);
}
function UpdateSettingItemVisibility() {
data.settings.forEach(setting => {
if (setting.showIf)
{
if (!document.getElementById(setting.showIf).checked)
document.getElementById(`item-${setting.id}`).style.display = 'none'
else
document.getElementById(`item-${setting.id}`).style.display = 'flex'
}
});
}
UpdateSettingItemVisibility();
// saveButton.addEventListener('click', () => {
// SendDataToParent(data);
// });
SendDataToParent(data);
})
.catch(error => console.error('Error loading settings:', error));
});
// In the iframe's JavaScript:
function SendDataToParent(data) {
const settings = {};
data.settings.forEach(setting => {
let inputElement = document.getElementById(setting.id);
if (setting.type === 'checkbox') {
settings[setting.id] = inputElement.checked;
} else {
settings[setting.id] = inputElement.value;
}
});
// Generate parameter string
const paramString = Object.entries(settings)
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
.join('&');
console.log('Parameter String:', paramString);
let widgetURLBox = document.getElementById('widget-url');
widgetURLBox.value = GetWidgetURL() + "?" + paramString;
window.parent.reloadWidget(paramString);
document.body.appendChild(datalistElement);
}
let saveButton = document.getElementById('save-settings');
let widgetURLBox = document.getElementById('widget-url');
let cancelSettingsButton = document.getElementById('cancel-settings');
saveButton.addEventListener('click', () => {
navigator.clipboard.writeText(widgetURLBox.value);
/////////////////////////
// BUTTON CLICK EVENTS //
/////////////////////////
const defaultBackgroundColor = "#2e2e2e";
const defaultTextColor = "white";
function CopyURLToClipboard() {
// Copy to clipboard
navigator.clipboard.writeText(widgetUrlInput.value);
saveButton.innerText = "Copied to clipboard";
saveButton.style.backgroundColor = "#00dd63"
saveButton.style.color = "#ffffff";
// Create the "Copied!" message
const copiedMessage = document.createElement('span');
copiedMessage.textContent = 'Copied to clipboard!';
copiedMessage.style.textAlign = 'center';
copiedMessage.style.fontWeight = 'absolute';
copiedMessage.style.position = 'absolute';
copiedMessage.style.top = '50%';
copiedMessage.style.left = '50%';
copiedMessage.style.transform = 'translate(-50%, -50%)';
copiedMessage.style.backgroundColor = '#00dd63'; // Green with some transparency
copiedMessage.style.color = 'white';
copiedMessage.style.padding = '5px 10px';
copiedMessage.style.borderRadius = '5px';
copiedMessage.style.zIndex = '2'; // Ensure it's above the input and label
copiedMessage.style.opacity = '0'; // Start with opacity 0 for fade-in
copiedMessage.style.transition = 'opacity 0.2s ease-in-out';
setTimeout(() => {
saveButton.innerText = "Click to copy URL";
saveButton.style.backgroundColor = defaultBackgroundColor;
saveButton.style.color = defaultTextColor;
}, 3000);
});
widgetUrlInputWrapper.appendChild(copiedMessage);
// Force a reflow to trigger the transition
void copiedMessage.offsetWidth;
// Fade in the message
copiedMessage.style.opacity = '1';
// Fade out and remove the message after 3 seconds
setTimeout(() => {
copiedMessage.style.opacity = '0';
setTimeout(() => {
widgetUrlInputWrapper.removeChild(copiedMessage);
}, 500); // Wait for the fade-out
}, 5000);
}
function CloseSettings() {
let loadSettingsBox = document.getElementById('mommy-milkers');
loadSettingsBox.style.visibility = 'hidden';
loadSettingsBox.style.opacity = 0;
loadSettingsBox.style.visibility = 'hidden';
loadSettingsBox.style.opacity = 0;
};
function LoadSettings() {
let loadURLBox = document.getElementById('load-url');
const url = new URL(loadURLBox.value);
const url = new URL(loadURLBox.value);
url.searchParams.forEach((value, key) => {
url.searchParams.forEach((value, key) => {
const inputElement = document.getElementById(key);
if (inputElement != null) {
if (inputElement.type == 'checkbox')
inputElement.checked = value.toLocaleLowerCase() == 'true';
else
inputElement.value = value;
}
});
const inputElement = document.getElementById(key);
if (inputElement != null) {
if (inputElement.type == 'checkbox')
inputElement.checked = value.toLocaleLowerCase() == 'true';
else
inputElement.value = value;
}
});
loadURLBox.value = '';
loadURLBox.value = '';
let loadSettingsBox = document.getElementById('mommy-milkers');
loadSettingsBox.style.visibility = 'hidden';
loadSettingsBox.style.opacity = 0;
}
function GetWidgetURL() {
const parsedUrl = new URL(settingsJson);
let result = parsedUrl.origin; // Base domain (protocol + hostname + port)
const pathSegments = parsedUrl.pathname.split('/').filter(segment => segment); // Split and remove empty segments
if (pathSegments.length > 0) {
result += '/' + pathSegments[0]; // Add the first path segment
}
return result;
//return 'D:/Projects/GitHub Projects/nutty.gg/multistream-alerts/index.html'
loadSettingsBox.style.visibility = 'hidden';
loadSettingsBox.style.opacity = 0;
}
function OpenMembershipPage() {
window.open("https://nutty.gg/supporters/sign_in", '_blank').focus();
window.open("https://nutty.gg/collections/member-exclusive-widgets", '_blank').focus();
}
function OpenLoadSettingsPopup() {
let loadSettingsBox = document.getElementById('mommy-milkers');
loadSettingsBox.style.visibility = 'visible';
loadSettingsBox.style.opacity = 1;
loadSettingsBox.style.visibility = 'visible';
loadSettingsBox.style.opacity = 1;
}
+244 -171
View File
@@ -1,273 +1,346 @@
* {
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica, Arial, sans-serif;
font-size: 16px;
color: white;
--accent-color: #2196f3;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica, Arial, sans-serif;
font-size: 16px;
font-weight: 500;
color: white;
--accent-color: #2196f3;
}
html,
body {
background-color: #181818;
margin: 0px 20px;
background-color: #181818;
margin: 0px 0px;
display: flex;
flex-flow: column;
height: 100%;
overflow: hidden;
/* Prevent overall page scroll */
}
body::-webkit-scrollbar {
width: 8px;
/* Width of the entire scrollbar */
#header {
display: flex;
flex-direction: row;
gap: 10px;
align-items: center;
padding: 0px 20px;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 1);
/* Add the shadow */
z-index: 1;
/* Ensure the shadow isn't hidden by content */
}
body::-webkit-scrollbar-track {
background: #2c2c2c;
/* Color of the tracking area */
#contentArea {
display: flex;
flex-direction: row;
flex-grow: 1;
overflow: hidden;
/* Prevent overall page scroll */
}
body::-webkit-scrollbar-thumb {
background-color: #9f9f9f;
/* Color of the scroll thumb */
border-radius: 4px;
/* Roundness of the scroll thumb */
border: none;
#header > button {
width: auto;
/* Allow buttons to size based on content */
flex-shrink: 0;
/* Prevent buttons from shrinking */
}
body::-webkit-scrollbar-thumb:hover {
background-color: #d1d1d1;
/* Color of the scroll thumb on hover */
#membershipsButton {
background: var(--accent-color);
}
#pinned-header {
position: sticky;
top: 0;
margin: 40px auto;
padding: 10px 0;
z-index: 100;
background: #181818af;
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
#settingsPanel {
width: 600px;
overflow-y: auto;
height: 100%;
padding: 0px 20px;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 1);
}
#widget-url {
font-size: 1em;
width: 100%;
margin: 10px 0px;
padding: 10px 10px;
#settingsPanel::-webkit-scrollbar {
width: 8px;
/* Width of the entire scrollbar */
}
#settings-container {
margin: 0px auto;
/* border: 1px solid #ddd; */
border-radius: 5px;
#settingsPanel::-webkit-scrollbar-track {
background: #2c2c2c;
/* Color of the tracking area */
}
#settings-container h1 {
text-align: center;
margin-bottom: 20px;
#settingsPanel::-webkit-scrollbar-thumb {
background-color: #9f9f9f;
/* Color of the scroll thumb */
border-radius: 4px;
/* Roundness of the scroll thumb */
border: none;
}
#settingsPanel::-webkit-scrollbar-thumb:hover {
background-color: #d1d1d1;
/* Color of the scroll thumb on hover */
}
#widgetPreview {
flex-grow: 1;
overflow: hidden;
border: transparent;
}
#widgetUrlInputWrapper {
position: relative;
/* Make the wrapper a positioning context */
display: inline-block;
/* Or block, depending on your layout */
width: 100%;
/* Match the input width */
flex-grow: 1;
}
#widgetUrlInputWrapper:hover #urlLabel {
opacity: 0;
/* Fade out the label on hover of the wrapper */
}
#widgetUrlInput {
font-size: 1em;
width: 100%;
padding: 10px 10px;
filter: blur(4px) brightness(0.4);
/* Apply a blur effect */
transition: filter 0.1s ease-in-out;
cursor: pointer;
}
#urlLabel {
border-radius: 0.5em;
padding: 5px 20px;
z-index: 1;
}
#urlLabel,
#copiedToClipboard {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
pointer-events: none;
opacity: 1;
transition: opacity 0.2s ease-in-out;
}
#widgetUrlInput:hover {
filter: none;
/* Remove blur when the input is focused */
outline: none;
/* Remove default focus outline */
}
.setting-group {
margin-bottom: 20px;
/* border: 1px solid #ddd; */
padding-bottom: 15px;
border-radius: 5px;
margin-bottom: 20px;
/* border: 1px solid #ddd; */
padding-bottom: 15px;
border-radius: 5px;
}
.setting-group:last-child {
padding-bottom: 0px;
}
h2 {
font-size: 0.9em;
font-weight: 500;
color: #93cdfd;
font-size: 0.9em;
font-weight: 500;
color: #93cdfd;
}
.setting-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 0;
/* border-bottom: 1px solid #eee; */
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 0;
/* border-bottom: 1px solid #eee; */
}
.setting-item:last-child {
border-bottom: none;
padding-bottom: 0px;
}
.setting-item label {
font-weight: 500;
margin-bottom: 5px;
display: block;
font-weight: 500;
margin-bottom: 5px;
display: block;
}
.setting-item p,
.setting-item a {
font-size: 0.9em;
font-weight: 300;
/* color: #666; */
opacity: 0.6;
margin: 0;
font-size: 0.9em;
font-weight: 300;
/* color: #666; */
opacity: 0.6;
margin: 0;
}
a {
font-weight: 500 !important;
font-weight: 500 !important;
}
.setting-item-content {
display: flex;
align-items: center;
display: flex;
align-items: center;
}
input[type="text"],
select,
input[type="number"] {
width: 250px;
padding: 5px;
width: 250px;
padding: 5px;
margin: 10px 0px;
padding: 10px 10px;
background-color: #ffffff05;
border-width: 0px;
color: white;
border-radius: 0.5em;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
margin: 10px 0px;
padding: 10px 10px;
background-color: #ffffff05;
border-width: 0px;
color: white;
border-radius: 0.5em;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.setting-item-content option {
color: black;
color: black;
}
textarea:focus,
input:focus {
outline: none;
outline: none;
}
.setting-item-content input[type="color"] {
width: 40px;
height: 40px;
margin-left: 10px;
/* padding: 2px; */
/* border: 1px solid #ccc; */
/* border-radius: 4px; */
width: 40px;
height: 40px;
margin-left: 10px;
/* padding: 2px; */
/* border: 1px solid #ccc; */
/* border-radius: 4px; */
appearance: none;
-moz-appearance: none;
-webkit-appearance: none;
background: none;
border: 0;
cursor: pointer;
padding: 0;
appearance: none;
-moz-appearance: none;
-webkit-appearance: none;
background: none;
border: 0;
cursor: pointer;
padding: 0;
}
/* Switch styling */
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
position: relative;
display: inline-block;
width: 60px;
height: 34px;
}
.switch input {
opacity: 0;
width: 0;
height: 0;
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked+.slider {
background-color: var(--accent-color);
background-color: var(--accent-color);
}
input:focus+.slider {
box-shadow: 0 0 1px var(--accent-color);
box-shadow: 0 0 1px var(--accent-color);
}
input:checked+.slider:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px);
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px);
}
/* Rounded sliders */
.slider.round {
border-radius: 34px;
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
border-radius: 50%;
}
button {
font-weight: 500;
background-color: #2e2e2e;
color: white;
opacity: 0.8;
margin: 5px 0px;
border-width: 0;
border-radius: 0.5em;
padding: 10px 20px;
width: 100%;
transition: all 0.2s ease-in-out;
font-weight: 500;
background-color: #2e2e2e;
color: white;
opacity: 0.8;
margin: 5px 0px;
border-width: 0;
border-radius: 0.5em;
padding: 10px 20px;
width: 100%;
transition: all 0.2s ease-in-out;
}
button:hover {
opacity: 1;
cursor: pointer;
opacity: 1;
cursor: pointer;
}
#mommy-milkers {
visibility: hidden;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #181818af;
backdrop-filter: blur(10px); /* Adjust blur radius as needed */
z-index: 9999; /* Ensure it's on top */
/* Add any other styles for the overlay content */
transition: all 0.2s ease-in-out;
opacity: 0;
#loadSettingsWrapper {
visibility: hidden;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #181818af;
backdrop-filter: blur(20px) grayscale(50%) brightness(200%);
/* Adjust blur radius as needed */
z-index: 9999;
/* Ensure it's on top */
/* Add any other styles for the overlay content */
transition: all 0.2s ease-in-out;
opacity: 0;
}
#load-url {
width: 100%;
}
#load-settings-container {
position: fixed;
left: 50%;
top: 50%;
width: calc(100% - 75px);
border-radius: 0.5em;
padding: 1em;
box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.5);
background: #181818af;
/* background: rgba(255, 0, 0, 0.637); */
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
transform: translate(-50%, -50%);
}
#load-settings {
background-color: var(--accent-color);
#loadSettingsContainer {
position: absolute;
left: 50%;
top: 50%;
max-width: 1000px;
width: calc(100% - 75px);
border-radius: 1em;
border: 1px rgba(255, 255, 255, 0.24) solid ;
padding: 1em;
box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.5);
background: #181818af;
/* background: rgba(255, 0, 0, 0.637); */
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
transform: translate(-50%, -50%);
}