This commit is contained in:
Joey Yakimowich-Payne 2025-04-19 06:40:51 -06:00
commit bc90290959
No known key found for this signature in database
GPG key ID: 6BFE655FA5ABD1E1
4 changed files with 529 additions and 523 deletions

View file

@ -439,6 +439,14 @@
</div>
</div>
<script src="js/beango.js?v=1.0.1"></script>
<script type="module" src="js/beango.js?v=1.0.1"></script>
<script type="module">
import { toggleConfig, exportSettings, importSettings, resetAllSettings, explodeBeans } from './js/beango.js';
window.explodeBeans = explodeBeans;
window.toggleConfig = toggleConfig;
window.exportSettings = exportSettings;
window.importSettings = importSettings;
window.resetAllSettings = resetAllSettings;
</script>
</body>
</html>

File diff suppressed because it is too large Load diff

139
beango/js/utils.js Normal file
View file

@ -0,0 +1,139 @@
let notificationTimeout = null; // To manage hiding notifications
// --- Notification Function ---
export function showNotification(message, type = 'info', duration = 3000) {
const notificationArea = document.getElementById('notification-area');
if (!notificationArea) return;
// Clear any existing timeout
if (notificationTimeout) {
clearTimeout(notificationTimeout);
}
notificationArea.textContent = message;
// Apply Tailwind classes based on type
notificationArea.className = 'fixed bottom-4 left-1/2 transform -translate-x-1/2 z-50 px-4 py-2 rounded shadow-lg text-white text-sm transition-opacity duration-300'; // Reset classes
switch (type) {
case 'success':
notificationArea.classList.add('bg-green-500');
break;
case 'warning':
notificationArea.classList.add('bg-yellow-500');
break;
case 'error':
notificationArea.classList.add('bg-red-500');
break;
default: // info
notificationArea.classList.add('bg-blue-500');
break;
}
// Make it visible
notificationArea.classList.add('opacity-100');
// Set timeout to hide
notificationTimeout = setTimeout(() => {
notificationArea.classList.remove('opacity-100');
notificationArea.classList.add('opacity-0');
}, duration);
}
// --- Helper Function ---
export function hexToRgba(hex, opacityPercent = 100) {
// Ensure opacityPercent is a number before using it
let numericOpacity = parseInt(opacityPercent, 10); // Try parsing
// If parsing failed (e.g., input was not a number string) or input was null/undefined, default to 100
if (isNaN(numericOpacity)) {
numericOpacity = 100;
}
// Remove hash if it exists
hex = hex.replace('#', '');
// Handle short hex codes
if (hex.length === 3) {
hex = hex.split('').map(char => char + char).join('');
}
// Ensure hex is 6 digits
if (hex.length !== 6) {
console.warn(`Invalid hex color: ${hex}. Using fallback.`);
hex = '000000'; // Default to black on error
}
const r = parseInt(hex.substring(0, 2), 16);
const g = parseInt(hex.substring(2, 4), 16);
const b = parseInt(hex.substring(4, 6), 16);
// Clamp and normalize opacity using the correctly parsed/defaulted value
const clampedOpacityPercent = Math.max(0, Math.min(100, numericOpacity));
const opacity = clampedOpacityPercent / 100;
return `rgba(${r}, ${g}, ${b}, ${opacity})`;
}
// --- Event Listener Helper Functions --- START
// Helper function for standard input/select elements
export function setupInputListener(elementId, eventType, saveFn, refreshFn) {
const element = document.getElementById(elementId);
if (element) {
element.addEventListener(eventType, () => {
if (saveFn) saveFn();
if (refreshFn) refreshFn();
});
} else {
console.warn(`Element with ID ${elementId} not found for listener setup.`);
}
}
// Helper function for opacity sliders with value display
export function setupOpacitySliderListener(sliderId, valueSpanId, saveFn, refreshFn) {
const slider = document.getElementById(sliderId);
const valueSpan = document.getElementById(valueSpanId);
if (slider) {
slider.addEventListener('input', (e) => {
if (valueSpan) valueSpan.textContent = e.target.value;
if (saveFn) saveFn();
if (refreshFn) refreshFn();
});
} else {
console.warn(`Element with ID ${sliderId} not found for listener setup.`);
}
}
// --- Event Listener Helper Functions --- END
// Helper function to restore a checkbox state
export function _restoreCheckboxSetting(checkboxId, savedValue) {
const checkbox = document.getElementById(checkboxId);
if (checkbox) {
checkbox.checked = savedValue; // savedValue should be boolean
}
}
// Helper function to restore opacity slider and value display
export function _restoreOpacitySetting(sliderId, valueSpanId, savedOpacityValue) {
const slider = document.getElementById(sliderId);
const valueSpan = document.getElementById(valueSpanId);
if (slider) {
slider.value = savedOpacityValue;
}
if (valueSpan) {
valueSpan.textContent = savedOpacityValue;
}
}
// Helper function to restore a color picker value
export function _restoreColorPickerSetting(pickerId, savedColorValue) {
const picker = document.getElementById(pickerId);
if (picker) {
picker.value = savedColorValue;
}
}
// Helper function to restore a generic input value
export function _restoreInputSetting(inputId, savedValue) {
const input = document.getElementById(inputId);
if (input) {
input.value = savedValue;
}
}

113
beango/js/variables.js Normal file
View file

@ -0,0 +1,113 @@
// --- localStorage Keys ---
export const LS_BOARD_SIZE = 'beango_boardSize';
export const LS_CELL_ITEMS = 'beango_cellItems'; // Original items from textarea/file
export const LS_DISPLAYED_ITEMS = 'beango_displayedItems'; // Items currently shown on the board
export const LS_MARKED_INDICES = 'beango_markedIndices';
export const LS_CONFIG_OPEN = 'beango_configOpen'; // Changed from minimized
export const LS_BACKGROUND_TYPE = 'beango_backgroundType'; // 'solid' or 'gradient'
export const LS_SOLID_COLOR = 'beango_solidColor';
export const LS_SOLID_COLOR_OPACITY = 'beango_solidColorOpacity';
export const LS_GRADIENT_COLOR_1 = 'beango_gradientColor1';
export const LS_GRADIENT_COLOR_1_OPACITY = 'beango_gradientColor1Opacity';
export const LS_GRADIENT_COLOR_2 = 'beango_gradientColor2';
export const LS_GRADIENT_COLOR_2_OPACITY = 'beango_gradientColor2Opacity';
export const LS_GRADIENT_DIRECTION = 'beango_gradientDirection';
export const LS_ORIGINAL_ITEMS = 'beango_originalItems'; // User's raw input
export const LS_HEADER_TEXT = 'beango_headerText';
export const LS_HEADER_IMAGE_URL = 'beango_headerImageUrl';
export const LS_HEADER_TEXT_COLOR = 'beango_headerTextColor';
export const LS_HEADER_TEXT_COLOR_OPACITY = 'beango_headerTextColorOpacity';
export const LS_HEADER_BG_COLOR = 'beango_headerBgColor';
export const LS_HEADER_BG_OPACITY = 'beango_headerBgOpacity';
export const LS_MARKED_COLOR = 'beango_markedColor';
export const LS_MARKED_COLOR_OPACITY = 'beango_markedColorOpacity'; // (replaces LS_MARKED_OPACITY)
export const LS_MARKED_IMAGE_URL = 'beango_markedImageUrl';
export const LS_MARKED_IMAGE_OPACITY = 'beango_markedImageOpacity';
export const LS_CELL_BORDER_COLOR = 'beango_cellBorderColor';
export const LS_CELL_BORDER_OPACITY = 'beango_cellBorderOpacity';
export const LS_CELL_BORDER_WIDTH = 'beango_cellBorderWidth';
export const LS_CELL_BG_COLOR = 'beango_cellBgColor';
export const LS_CELL_BG_OPACITY = 'beango_cellBgOpacity';
export const LS_CELL_BG_IMAGE_URL = 'beango_cellBgImageUrl';
export const LS_CELL_BG_IMAGE_OPACITY = 'beango_cellBgImageOpacity';
export const LS_CELL_TEXT_COLOR = 'beango_cellTextColor';
export const LS_CELL_TEXT_OPACITY = 'beango_cellTextOpacity';
export const LS_CELL_OUTLINE_COLOR = 'beango_cellOutlineColor';
export const LS_CELL_OUTLINE_OPACITY = 'beango_cellOutlineOpacity';
export const LS_CELL_OUTLINE_WIDTH = 'beango_cellOutlineWidth';
export const LS_MARKED_BORDER_COLOR = 'beango_markedBorderColor';
export const LS_MARKED_BORDER_OPACITY = 'beango_markedBorderOpacity';
export const LS_MARKED_BORDER_WIDTH = 'beango_markedBorderWidth';
export const LS_BOARD_BG_COLOR = 'beango_boardBgColor';
export const LS_BOARD_BG_COLOR_OPACITY = 'beango_boardBgColorOpacity'; // (replaces LS_BOARD_BG_OPACITY)
export const LS_BOARD_BG_IMAGE_URL = 'beango_boardBgImageUrl';
export const LS_BOARD_BG_IMAGE_OPACITY = 'beango_boardBgImageOpacity'; // NEW
export const LS_MARKED_CELL_TEXT_COLOR = 'beango_markedCellTextColor';
export const LS_MARKED_CELL_TEXT_OPACITY = 'beango_markedCellTextOpacity';
export const LS_MARKED_CELL_OUTLINE_COLOR = 'beango_markedCellOutlineColor';
export const LS_MARKED_CELL_OUTLINE_OPACITY = 'beango_markedCellOutlineOpacity';
export const LS_MARKED_CELL_OUTLINE_WIDTH = 'beango_markedCellOutlineWidth';
export const LS_HEADER_TEXT_OUTLINE_COLOR = 'beango_headerTextOutlineColor';
export const LS_HEADER_TEXT_OUTLINE_OPACITY = 'beango_headerTextOutlineOpacity';
export const LS_HEADER_TEXT_OUTLINE_WIDTH = 'beango_headerTextOutlineWidth';
export const LS_HEADER_TEXT_FONT_SIZE = 'beango_headerTextFontSize'; // New key
export const LS_HEADER_TEXT_FONT_FAMILY = 'beango_headerTextFontFamily'; // New key
export const LS_HEADER_TEXT_STYLE_ITALIC = 'beango_headerTextStyleItalic'; // New key for italic
export const LS_HEADER_TEXT_STYLE_BOLD = 'beango_headerTextStyleBold'; // New key for bold
// --- Default Values ---
export const DEFAULT_SAMPLE_ITEMS = [
"Sample Item 1", "Sample Item 2", "Sample Item 3", "Sample Item 4", "Sample Item 5",
"Sample Item 6", "Sample Item 7", "Free Space", "Sample Item 9", "Sample Item 10",
"Sample Item 11", "Sample Item 12", "Sample Item 13", "Sample Item 14", "Sample Item 15",
"Sample Item 16", "Sample Item 17", "Sample Item 18", "Sample Item 19", "Sample Item 20",
"Sample Item 21", "Sample Item 22", "Sample Item 23", "Sample Item 24", "Sample Item 25"
];
export const DEFAULT_SOLID_COLOR = '#ff7e5f'; // Default to first color of gradient
export const DEFAULT_SOLID_COLOR_OPACITY = 100; //
export const DEFAULT_GRADIENT_COLOR_1 = '#faaca8'; // Softer pink/orange
export const DEFAULT_GRADIENT_COLOR_1_OPACITY = 100; //
export const DEFAULT_GRADIENT_COLOR_2 = '#ddd6f3'; // Soft purple
export const DEFAULT_GRADIENT_COLOR_2_OPACITY = 100; //
export const DEFAULT_GRADIENT_DIRECTION = 'to right top'; // Changed direction
export const DEFAULT_HEADER_TEXT = 'Beango!'; // REVERTED default back to Beango!
export const DEFAULT_HEADER_IMAGE_URL = '/bean.svg'; // No default image
export const DEFAULT_HEADER_TEXT_COLOR = '#15803d'; // Tailwind green-700 (approx)
export const DEFAULT_HEADER_TEXT_COLOR_OPACITY = 100; //
export const DEFAULT_HEADER_BG_COLOR = '#ffffff';
export const DEFAULT_HEADER_BG_OPACITY = 100;
export const DEFAULT_MARKED_COLOR = '#e9ecef'; // Light grey for marked cells
export const DEFAULT_MARKED_COLOR_OPACITY = 40; // (replaces DEFAULT_MARKED_OPACITY) - Significantly lower
export const DEFAULT_MARKED_IMAGE_URL = 'https://www.svgrepo.com/download/286496/cross.svg'; // Default cross image
export const DEFAULT_MARKED_IMAGE_OPACITY = 70; //
export const DEFAULT_CELL_BORDER_COLOR = '#808080'; // Default dark grey
export const DEFAULT_CELL_BORDER_OPACITY = 80; // Slightly transparent
export const DEFAULT_CELL_BORDER_WIDTH = 1; //
export const DEFAULT_CELL_BG_COLOR = '#f8f9fa'; // Off-white
export const DEFAULT_CELL_BG_OPACITY = 95; // Slightly transparent
export const DEFAULT_CELL_BG_IMAGE_URL = ''; // Default no image
export const DEFAULT_CELL_BG_IMAGE_OPACITY = 100; //
export const DEFAULT_CELL_TEXT_COLOR = '#000000';
export const DEFAULT_CELL_TEXT_OPACITY = 100;
export const DEFAULT_CELL_OUTLINE_COLOR = '#ffffff';
export const DEFAULT_CELL_OUTLINE_OPACITY = 100;
export const DEFAULT_CELL_OUTLINE_WIDTH = 0; // Default 0px - Cleaner look
export const DEFAULT_MARKED_BORDER_COLOR = DEFAULT_CELL_BORDER_COLOR; // Match default border color
export const DEFAULT_MARKED_BORDER_OPACITY = 50; // Less opaque than default border
export const DEFAULT_MARKED_BORDER_WIDTH = 0; // No border for marked cells
export const DEFAULT_BOARD_BG_COLOR = '#ffffff'; // Default white
export const DEFAULT_BOARD_BG_COLOR_OPACITY = 100; // (replaces DEFAULT_BOARD_BG_OPACITY)
export const DEFAULT_BOARD_BG_IMAGE_URL = ''; // Default no image
export const DEFAULT_BOARD_BG_IMAGE_OPACITY = 100; // NEW
export const DEFAULT_MARKED_CELL_TEXT_COLOR = '#000000'; // Keep black for readability
export const DEFAULT_MARKED_CELL_TEXT_OPACITY = 50;
export const DEFAULT_MARKED_CELL_OUTLINE_COLOR = '#ffffff';
export const DEFAULT_MARKED_CELL_OUTLINE_OPACITY = 100;
export const DEFAULT_MARKED_CELL_OUTLINE_WIDTH = 0; // Default 0px - No outline for marked
export const DEFAULT_HEADER_TEXT_OUTLINE_COLOR = '#ffffff'; // Default outline white
export const DEFAULT_HEADER_TEXT_OUTLINE_OPACITY = 100;
export const DEFAULT_HEADER_TEXT_OUTLINE_WIDTH = 0; // Default no outline
export const DEFAULT_HEADER_TEXT_FONT_SIZE = 36; // New default (approx text-4xl)
export const DEFAULT_HEADER_TEXT_FONT_FAMILY = 'sans-serif'; // New default
export const DEFAULT_HEADER_TEXT_STYLE_ITALIC = false; // Default not italic
export const DEFAULT_HEADER_TEXT_STYLE_BOLD = true; // Default bold