@lovebowls/leagueelements
Version:
League Elements package for LoveBowls
1,559 lines (1,365 loc) • 256 kB
JavaScript
var LeagueTeams = (function () {
'use strict';
const baseFontSizeConstants = (fontScale = 1.0) => `
/* Base font sizes for different contexts */
--le-font-size-base-desktop: ${16 * fontScale}px;
--le-font-size-base-mobile: ${18 * fontScale}px;
line-height: 1.2;
`;
// Shared font size base variables and UI element font sizes (used internally)
const getFontSizeElementVariables = (isMobile = false) => `
/* Specific sizes for common UI elements */
--le-font-size-button: var(--le-font-size-base-${isMobile ? 'mobile' : 'desktop'});
--le-font-size-label: var(--le-font-size-base-${isMobile ? 'mobile' : 'desktop'});
--le-font-size-input: var(--le-font-size-base-${isMobile ? 'mobile' : 'desktop'});
--le-font-size-table-header: var(--le-font-size-base-${isMobile ? 'mobile' : 'desktop'});
--le-font-size-table-cell: 0.7em;
--le-font-size-dropdown: var(--le-font-size-base-${isMobile ? 'mobile' : 'desktop'});
--le-padding-xs: 0.25rem;
--le-padding-s: 0.6rem;
--le-padding-m: 1rem;
`;
const getMobileStyles = (fontScale = 1.0) => `
:host {
${baseFontSizeConstants(fontScale)}
font-size: var(--le-font-size-base-mobile);
/* Mobile-specific styling that can be added to host elements */
--le-font-size-base: 1em;
--le-font-size-xs: 0.6em;
--le-font-size-small: 0.8em;
--le-font-size-medium: 1.0em;
--le-font-size-large: 1.2em;
--le-font-size-xlarge: 1.4em;
--le-font-size-xxlarge: 1.6em;
${getFontSizeElementVariables(true)}
.no-data
padding: var(--le-padding-m, 1rem);
color: var(--le-text-color-secondary, #666);
background-color: transparent;
border: none;
}
.controls-panel {
gap: var(--le-padding-s, 0.5rem);
}
/* Mobile-specific dropdown styling */
.controls-panel .filter-controls .dropdown-shared {
flex: 1;
}
.controls-panel .dropdown-shared {
flex: 1;
}
.controls-panel .dropdown-shared .dropdown-select-shared {
width: 100%;
padding: var(--le-padding-s, 0.75rem) calc(var(--le-padding-m, 1rem) * 2.5) var(--le-padding-s, 0.75rem) var(--le-padding-m, 1rem);
min-height: 44px; /* Minimum touch target size */
background-size: 1.2rem;
background-position: right 1rem center;
border-width: 2px;
}
.controls-panel .dropdown-select-shared:focus {
border-width: 2px;
}
/* Input fields on mobile */
.form-input-shared,
.form-select-shared,
{
min-height: 44px; /* Standard mobile touch target */
padding: var(--le-padding-xs, 0.5rem) var(--le-padding-m, 1rem);
font-size: var(--le-font-size-medium, 1.0em);
border-width: 2px;
width: 100% !important; /* Force width consistency on mobile */
max-width: 100%;
box-sizing: border-box;
}
/* Specific handling for date inputs on mobile */
.form-input-shared[type="date"] {
-webkit-appearance: none;
-moz-appearance: textfield;
appearance: none;
}
.form-input-shared:focus, .form-select-shared:focus {
border-width: 2px;
}
.form-label-shared {
margin-bottom: var(--le-padding-s, 0.75rem);
}
.resizer {
display: none !important;
}
}
`;
const getDesktopStyles = (fontScale = 1.0) => `
:host {
${baseFontSizeConstants(fontScale)}
font-size: var(--le-font-size-base-desktop);
/* Standardized font sizes for desktop - these cascade to all sub-components */
--le-font-size-base: 1em;
--le-font-size-xs: 0.75em;
--le-font-size-small: 0.9em;
--le-font-size-medium: 1.0em;
--le-font-size-large: 1.2em;
--le-font-size-xlarge: 1.4em;
--le-font-size-xxlarge: 1.6em;
${getFontSizeElementVariables(false)}
.no-data
padding: var(--le-padding-m, 1rem);
color: var(--le-text-color-secondary, #666);
background-color: transparent;
border: none;
}
/* Desktop-specific dropdown styling */
.controls-panel .filter-controls .dropdown-shared {
width: auto;
min-width: 200px;
}
.controls-panel .dropdown-shared .dropdown-select-shared {
min-width: 160px;
width: auto;
}
.resizer {
width: 5px;
min-width: 5px;
cursor: col-resize;
background-color: var(--swal-background-color-header);
border-left: 1px solid var(--swal-border-color-light);
border-right: 1px solid var(--swal-border-color-light);
z-index: 10;
}
.resizer:hover {
background: var(--le-text-color-secondary);
}
}
`;
const buttonStyles = `
.button-shared {
padding: 4px 8px;
border: 1px solid var(--le-border-color-medium, #ccc);
background-color: var(--le-background-color-button, #f0f0f0);
color: var(--le-text-color-primary, #333); /* Ensure text color contrasts with button background */
cursor: pointer;
border-radius: var(--le-border-radius-standard, 4px);
font-size: var(--le-font-size-button, var(--le-font-size-medium, 1.15em)); /* Use variable with fallback */
text-decoration: none;
display: inline-block;
text-align: center;
line-height: normal; /* Ensure consistent line height */
white-space: nowrap; /* Prevent text wrapping */
vertical-align: middle; /* Align nicely if next to text/icons */
user-select: none; /* Prevent text selection on click */
transition: background-color 0.2s ease-in-out, border-color 0.2s ease-in-out; /* Smooth transitions */
}
.button-shared:hover:not(:disabled) {
background-color: var(--le-background-color-button-hover, #e0e0e0);
border-color: var(--le-border-color-dark, #bbb); /* Slightly darker border on hover */
/* color: var(--le-text-color-accent-hover, inherit); Optional: change text color on hover */
}
.button-shared:active:not(:disabled) {
/* Optional: style for active (pressed) state */
/* background-color: var(--le-background-color-button-active, #d0d0d0); */
}
.button-shared:disabled,
.button-shared.disabled { /* Allow class-based disabling too */
background-color: var(--le-background-color-button-disabled, #eee);
color: var(--le-text-color-secondary, #aaa);
border-color: var(--le-border-color-medium, #ccc); /* Use medium border for disabled state */
cursor: not-allowed;
opacity: 0.7; /* Visually indicate disabled state */
}
/* Variations */
.button-shared.button-primary {
background-color: var(--le-color-primary, #007bff);
color: var(--le-text-color-on-primary, #fff);
border-color: var(--le-color-primary, #007bff);
}
.button-shared.button-primary:hover:not(:disabled) {
background-color: var(--le-color-primary-hover, #0056b3);
border-color: var(--le-color-primary-hover, #0056b3);
}
.button-shared.button-secondary-light {
background-color: var(--le-background-color-button-secondary-light, #f8f9fa);
color: var(--le-text-color-secondary-light-text, #212529);
border-color: var(--le-border-color-secondary-light, #ced4da);
}
.button-shared.button-secondary-light:hover:not(:disabled) {
background-color: var(--le-background-color-button-secondary-light-hover, #e2e6ea);
border-color: var(--le-border-color-secondary-light-hover, #dae0e5);
color: var(--le-text-color-secondary-light-text-hover, #212529);
}
/* Example for a darker secondary button if needed elsewhere
.button-shared.button-secondary {
background-color: var(--le-color-secondary, #6c757d);
color: var(--le-text-color-on-secondary, #fff);
border-color: var(--le-color-secondary, #6c757d);
}
.button-shared.button-secondary:hover:not(:disabled) {
background-color: var(--le-color-secondary-hover, #5a6268);
border-color: var(--le-color-secondary-hover, #5a6268);
}
*/
`;
const modalStyles = `
.modal-shared-overlay {
display: none; /* Hidden by default */
position: fixed;
z-index: var(--le-z-index-modal-overlay, 1000); /* Ensure it's on top */
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: var(--le-background-color-modal-overlay, rgba(0,0,0,0.4));
padding-top: 5%;
padding-bottom: 5%;
}
.modal-shared-overlay.open {
display: flex;
justify-content: center;
}
.modal-shared-content {
background-color: var(--le-background-color-panel, #fff);
margin: 10% auto; /* Default to 10% from top, centered */
padding: 0;
border: 1px solid var(--le-border-color-dark, #ccc);
max-width: 600px;
border-radius: var(--le-border-radius-large, 8px);
box-shadow: var(--le-shadow-modal, 0 4px 8px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19));
display: flex;
flex-direction: column;
align-self: flex-start;
}
/* Specific styles for modal mobile-view class */
.modal-shared-content.mobile-view {
width: 90%; /* Override any fixed width from shared styles */
margin: 0; /* Less margin from top on mobile */
max-width: 90%;
min-width: 280px !important;
}
.modal-shared-header {
padding: var(--le-padding-s, 0.75em) var(--le-padding-m, 1.25em); /* Increased padding */
border-bottom: 1px solid var(--le-border-color-medium, #eee);
font-weight: bold;
color: var(--le-text-color-primary, #333);
background-color: var(--le-background-color-header, #f9f9f9); /* Modal header distinct background */
display: flex;
justify-content: space-between;
align-items: center;
font-size: var(--le-font-size-large, 1.4em); /* Increased large font size */
border-top-left-radius: var(--le-border-radius-large, 8px); /* Match content radius */
border-top-right-radius: var(--le-border-radius-large, 8px); /* Match content radius */
}
.modal-shared-header .close-button-shared { /* Specific styling for a close button if needed */
color: var(--le-text-color-secondary, #aaa);
font-size: var(--le-font-size-xlarge, 1.8em); /* Increased size */
font-weight: bold;
background: none;
border: none;
cursor: pointer;
}
.modal-shared-header .close-button-shared:hover,
.modal-shared-header .close-button-shared:focus {
color: var(--le-text-color-primary, #000);
text-decoration: none;
}
.modal-shared-body {
padding: var(--le-padding-m, 1.25em); /* Increased padding */
overflow-y: auto; /* Allow body to scroll if content is too long */
flex-grow: 1; /* Allows body to take up available space if modal has fixed height */
}
.modal-shared-footer {
padding: var(--le-padding-m, 1.25em);
text-align: right;
border-top: 1px solid var(--le-border-color-medium, #eee);
background-color: var(--le-background-color-header, #f9f9f9); /* Optional: footer background */
border-bottom-left-radius: var(--le-border-radius-large, 8px); /* Match content radius */
border-bottom-right-radius: var(--le-border-radius-large, 8px); /* Match content radius */
}
.modal-shared-footer .button-shared + .button-shared { /* Spacing between buttons in footer */
margin-left: var(--le-padding-s, 0.75em); /* Increased margin */
}
`;
const formStyles = `
.form-group-shared {
margin-bottom: var(--le-padding-m, 1.25em); /* Increased margin */
}
.form-label-shared {
display: block;
margin-bottom: var(--le-padding-xs, 0.4em); /* Increased margin */
font-weight: bold;
color: var(--le-text-color-primary, #333);
font-size: var(--le-font-size-label, 1em)); /* Use variable with fallback */
}
.form-input-shared,
.form-select-shared {
width: 100%;
height: auto;
padding: var(--le-padding-s, 0.75em);
border: 1px solid var(--le-border-color-dark, #ccc);
border-radius: var(--le-border-radius-standard, 4px);
box-sizing: border-box;
font-size: var(--le-font-size-input, 1em)); /* Use variable with fallback */
color: var(--le-text-color-primary, #333);
background-color: var(--le-background-color-panel, #fff);
}
/* Ensure date inputs have consistent styling across browsers */
.form-input-shared[type="date"] {
max-width: 100%;
}
.form-input-shared:focus,
.form-select-shared:focus {
border-color: var(--le-border-color-accent, #2196f3);
outline: none; /* Or a custom focus ring */
box-shadow: 0 0 0 2px var(--le-focus-ring-color, rgba(33, 150, 243, 0.3));
}
/* Specific styling for checkbox groups if needed */
.form-checkbox-label-shared {
display: flex; /* Changed to flex for better alignment */
align-items: center;
font-weight: normal; /* Typically labels for checkboxes are not bold by default */
color: var(--le-text-color-primary, #333);
}
.form-checkbox-label-shared input[type="checkbox"] {
margin-right: var(--le-padding-s, 0.75em); /* Increased margin */
/* Consider custom styling for checkboxes if desired, or rely on browser defaults */
/* For consistent appearance across browsers, custom checkbox styling can be complex */
/* For now, using default with adjusted margin */
width: auto; /* Override width: 100% from .form-input-shared if a generic class was applied */
vertical-align: middle; /* Align checkbox with text */
}
/* Styling for a container of multiple checkboxes or radio buttons */
.form-options-group-shared {
/* Styles for a group of checkboxes/radios, e.g., display: flex; flex-direction: column; gap: ... */
}
/* Styling for individual option within a group */
.form-option-item-shared {
/* Styles for each checkbox/radio item within a group */
}
/* Enhanced checkbox styles for better mobile usability */
.checkbox-enhanced-shared {
position: relative;
display: inline-block;
cursor: pointer;
user-select: none;
margin-right: var(--le-padding-s, 0.75em);
}
.checkbox-enhanced-shared input[type="checkbox"] {
position: absolute;
opacity: 0;
cursor: pointer;
height: 0;
width: 0;
}
.checkbox-enhanced-shared .checkmark-shared {
position: relative;
display: inline-block;
width: 1.5em;
height: 1.5em;
background-color: var(--le-background-color-panel, #fff);
border: 2px solid var(--le-border-color-dark, #ccc);
border-radius: var(--le-border-radius-small, 3px);
transition: all 0.2s ease;
vertical-align: middle;
margin-right: var(--le-padding-xs, 0.25em);
}
/* Mobile-specific larger checkboxes */
@media (max-width: 768px) {
.checkbox-enhanced-shared .checkmark-shared {
width: 2em;
height: 2em;
border-width: 2px;
}
}
/* Hover state */
.checkbox-enhanced-shared:hover input[type="checkbox"] ~ .checkmark-shared {
border-color: var(--le-text-color-accent, #2196f3);
background-color: var(--le-background-color-row-hover, #f9f9f9);
}
/* Focus state */
.checkbox-enhanced-shared input[type="checkbox"]:focus ~ .checkmark-shared {
border-color: var(--le-text-color-accent, #2196f3);
box-shadow: 0 0 0 2px rgba(33, 150, 243, 0.2);
}
/* Checked state */
.checkbox-enhanced-shared input[type="checkbox"]:checked ~ .checkmark-shared {
background-color: var(--le-text-color-accent, #2196f3);
border-color: var(--le-text-color-accent, #2196f3);
}
/* Checkmark icon */
.checkbox-enhanced-shared .checkmark-shared:after {
content: "";
position: absolute;
display: none;
left: 50%;
top: 50%;
transform: translate(-50%, -50%) rotate(45deg);
width: 0.4em;
height: 0.8em;
border: solid var(--le-text-color-on-primary, #fff);
border-width: 0 0.15em 0.15em 0;
}
/* Mobile-specific larger checkmark */
@media (max-width: 768px) {
.checkbox-enhanced-shared .checkmark-shared:after {
width: 0.5em;
height: 1em;
border-width: 0 0.2em 0.2em 0;
}
}
/* Show checkmark when checked */
.checkbox-enhanced-shared input[type="checkbox"]:checked ~ .checkmark-shared:after {
display: block;
}
/* Disabled state */
.checkbox-enhanced-shared input[type="checkbox"]:disabled ~ .checkmark-shared {
background-color: var(--le-background-color-button-disabled, #eee);
border-color: var(--le-border-color-medium, #ddd);
cursor: not-allowed;
}
.checkbox-enhanced-shared input[type="checkbox"]:disabled ~ .checkmark-shared:after {
border-color: var(--le-text-color-secondary, #aaa);
}
/* Legend/checkbox list styles for responsive layouts */
.checkbox-list-responsive-shared {
display: grid;
gap: var(--le-padding-s, 0.75em);
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
}
/* Mobile-specific responsive checkbox list */
@media (max-width: 768px) {
.checkbox-list-responsive-shared {
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
gap: var(--le-padding-m, 1em);
}
}
/* Extra small screens - force 2 columns */
@media (max-width: 480px) {
.checkbox-list-responsive-shared {
grid-template-columns: 1fr 1fr;
gap: var(--le-padding-s, 0.75em);
}
}
/* Legend item styling for checkbox lists */
.legend-item-shared {
display: flex;
align-items: center;
font-size: var(--le-font-size-small, 0.9em);
padding: var(--le-padding-xs, 0.25em);
border-radius: var(--le-border-radius-small, 3px);
transition: background-color 0.2s ease;
}
.legend-item-shared:hover {
background-color: var(--le-background-color-row-hover, #f9f9f9);
}
/* Mobile-specific legend item styling */
@media (max-width: 768px) {
.legend-item-shared {
font-size: var(--le-font-size-medium, 1.2em);
padding: var(--le-padding-s, 0.75em) var(--le-padding-xs, 0.25em);
min-height: 3em;
}
}
`;
const listStyles = `
.list-container {
max-height: 200px;
overflow-y: auto;
}
.list-panel {
border: 1px solid var(--le-border-color-medium, #ddd);
border-radius: var(--le-border-radius-standard, 4px);
background: var(--le-background-color-panel, #fff);
}
.list-panel h4 {
margin: 0;
padding: var(--le-padding-m, 1rem);
background: var(--le-background-color-header, #f8f9fa);
border-bottom: 1px solid var(--le-border-color-light, #eee);
color: var(--le-text-color-primary, #333);
}
.list-panel.disabled {
pointer-events: none;
opacity: 0.6;
}
.list {
list-style: none;
margin: 0;
padding: 0;
}
.list-item{
display: flex;
justify-content: space-between;
align-items: center;
padding: var(--le-padding-xs) var(--le-padding-s);
border-bottom: 1px solid var(--le-border-color-light, #eee);
cursor: pointer;
transition: background-color 0.2s ease;
min-height: 2.5rem; /* Ensure consistent height for action buttons */
box-sizing: border-box;
}
.list-panel.disabled .list-item {
cursor: not-allowed;
}
.list-item:last-child {
border-bottom: none;
}
/* Example of a text part within a list item that should grow */
.list-item .list-item-text-primary {
flex-grow: 1;
font-size: var(--le-font-size-medium, 1.2em);
text-align: left; /* Ensure text is left-aligned */
display: flex;
align-items: center; /* Center text vertically within its container */
}
/* Example of an actions container part within a list item */
.list-item .list-item-actions {
flex-shrink: 0; /* Prevent actions from shrinking */
display: flex;
gap: var(--le-padding-xs, 0.4em); /* Increased gap */
align-items: center;
min-height: 2rem; /* Reserve space for buttons even when empty */
}
.list-item:hover {
background-color: var(--le-background-color-hover, #f5f5f5);
}
.list-item.selected {
background-color: var(--le-background-color-selected, #e3f2fd);
border-left: 3px solid var(--le-border-color-primary, #2196f3);
animation: highlightItem 0.6s ease-out;
}
@keyframes highlightItem {
0% {
background-color: var(--le-background-color-accent, #108CFF);
box-shadow: 0 0 0 2px rgba(16, 140, 255, 0.3), 0 2px 8px rgba(16, 140, 255, 0.2);
}
100% {
background-color: var(--le-background-color-selected, #e3f2fd);
box-shadow: none;
}
}
/* Mobile-specific list item adjustments */
@media (max-width: 768px) {
.list-item {
min-height: 4rem; /* Slightly taller for mobile touch targets */
padding: 0 var(--le-padding-xs, 1rem);;
}
.list-item .list-item-actions {
min-height: 2.5rem; /* Larger touch targets for mobile */
}
.list-item .list-item-actions .button-shared {
min-height: 2.5rem; /* Ensure buttons are touch-friendly */
}
}
`;
// SweetAlert2 Mobile-Specific Style Overrides
// These styles are specifically designed to improve the appearance and usability
// of SweetAlert2 dialogs on smaller screens (mobile devices).
// They should be injected globally by elements that use SweetAlert2.
const sweetAlertMobileOverrides = `
/* Injected SweetAlert2 Mobile Styles - Production v1 */
.swal2-popup.swal-popup-mobile {
width: 90vw !important;
max-width: 480px !important;
padding: var(--le-padding-m, 1rem) !important; /* Increased padding for better touch spacing */
font-size: var(--le-font-size-base, 1.5em) !important; /* Use mobile base font size */
}
.swal-popup-mobile .swal2-title,
.swal-title-mobile {
font-size: var(--le-font-size-large, 1.4em) !important; /* Readable title size for mobile */
padding: 0.5rem 0.5rem 0.75rem !important; /* Adjusted padding */
margin-bottom: 0 !important; /* Remove default bottom margin if any, handled by container */
line-height: 1.3 !important;
}
.swal-popup-mobile .swal2-html-container,
.swal-html-container-mobile {
font-size: var(--le-font-size-small, 1.0em) !important; /* Use shared variable instead of hardcoded rem */
margin: 0.75rem 0.5rem !important; /* Vertical and horizontal margin */
line-height: 1.5 !important;
text-align: center !important;
}
.swal-popup-mobile .swal2-actions,
.swal-actions-mobile {
width: 100% !important;
margin-top: 1rem !important;
gap: 0.65rem !important; /* Space between stacked buttons */
flex-direction: column-reverse !important; /* Stack buttons, confirm on top */
}
.swal-popup-mobile .swal2-styled,
.swal-styled-mobile {
width: 100% !important; /* Full width buttons */
padding: 0.85rem !important; /* Generous padding for touch targets */
font-size: var(--le-font-size-medium, 1.2em) !important;
margin: 0 !important; /* Remove individual margins, gap handles spacing */
border-radius: 0.3rem !important;
}
/* Optional: If you want to ensure default button colors are explicitly set or overridden for mobile */
/* .swal-popup-mobile .swal2-confirm.swal-styled-mobile {
background-color: #3085d6 !important; /* Example: Default confirm blue */
/* }
.swal-popup-mobile .swal2-cancel.swal-styled-mobile {
background-color: #d33 !important; /* Example: Default cancel red */
/* } */
`;
// SweetAlert2 Global Style Overrides
// These are general global styles for SweetAlert2 dialogs, ensuring a consistent
// base appearance. They should be injected globally by elements that use SweetAlert2.
const sweetAlertGlobalStyles = `
/* SweetAlert2 Global Styles */
.swal2-popup {
font-family: var(--le-font-family-base, sans-serif); /* Assuming you have a base font family variable */
background-color: var(--le-background-color-panel, #fff) !important;
border-radius: var(--le-border-radius-large, 8px) !important;
border: 1px solid var(--le-border-color-dark, #ccc) !important;
color: var(--le-text-color-primary, #333) !important;
}
.swal2-title {
color: var(--le-text-color-primary, #333) !important;
font-size: var(--le-font-size-large, 1.4em) !important; /* Match modal header */
font-weight: bold !important;
}
.swal2-html-container {
color: var(--le-text-color-primary, #333) !important;
font-size: var(--le-font-size-base, 1em) !important;
margin: var(--le-padding-m, 1.25em) !important; /* Add some margin */
}
.swal2-actions {
margin-top: var(--le-padding-m, 1.25em) !important;
}
.swal2-styled { /* Base for swal buttons */
padding: var(--le-padding-s, 0.75em) var(--le-padding-m, 1.25em) !important;
border-radius: var(--le-border-radius-standard, 4px) !important;
font-size: var(--le-font-size-medium, 1.15em) !important;
text-decoration: none !important;
/* display: inline-block !important; */ /* Removed to allow SweetAlert2 to control visibility */
text-align: center !important;
line-height: normal !important;
white-space: nowrap !important;
vertical-align: middle !important;
user-select: none !important;
transition: background-color 0.2s ease-in-out, border-color 0.2s ease-in-out !important;
border: 1px solid transparent !important; /* Start with transparent border, colors will override */
}
.swal2-styled:focus {
outline: none !important;
box-shadow: 0 0 0 2px rgba(33, 150, 243, 0.2) !important; /* Example focus, adjust as needed */
}
.swal2-styled:hover:not(:disabled) {
/* General hover, specific button types might override */
filter: brightness(90%);
}
.swal2-confirm {
background-color: var(--le-color-confirm, #28a745) !important; /* Define --le-color-confirm or use existing */
color: var(--le-text-color-on-primary, #fff) !important;
border-color: var(--le-color-confirm, #28a745) !important;
}
.swal2-confirm:hover:not(:disabled) {
background-color: var(--le-color-confirm-hover, #218838) !important; /* Define --le-color-confirm-hover */
border-color: var(--le-color-confirm-hover, #218838) !important;
}
.swal2-cancel {
background-color: var(--le-color-cancel, #dc3545) !important; /* Define --le-color-cancel or use existing */
color: var(--le-text-color-on-primary, #fff) !important;
border-color: var(--le-color-cancel, #dc3545) !important;
}
.swal2-cancel:hover:not(:disabled) {
background-color: var(--le-color-cancel-hover, #c82333) !important; /* Define --le-color-cancel-hover */
border-color: var(--le-color-cancel-hover, #c82333) !important;
}
/* If you use a deny button */
.swal2-deny {
background-color: var(--le-color-deny, #6c757d) !important; /* Define --le-color-deny */
color: var(--le-text-color-on-primary, #fff) !important;
border-color: var(--le-color-deny, #6c757d) !important;
}
.swal2-deny:hover:not(:disabled) {
background-color: var(--le-color-deny-hover, #5a6268) !important; /* Define --le-color-deny-hover */
border-color: var(--le-color-deny-hover, #5a6268) !important;
}
/* Icon styling - optional, if you want to color default icons */
.swal2-icon.swal2-warning {
color: var(--le-text-color-warning, #ffc107) !important; /* Define --le-text-color-warning */
border-color: var(--le-text-color-warning, #ffc107) !important;
}
.swal2-icon.swal2-error {
color: var(--le-text-color-error, #dc3545) !important; /* Define --le-text-color-error */
border-color: var(--le-text-color-error, #dc3545) !important;
}
.swal2-icon.swal2-success {
color: var(--le-text-color-success, #28a745) !important; /* Define --le-text-color-success */
border-color: var(--le-text-color-success, #28a745) !important;
}
.swal2-icon.swal2-info {
color: var(--le-text-color-info, #17a2b8) !important; /* Define --le-text-color-info */
border-color: var(--le-text-color-info, #17a2b8) !important;
}
`;
const BASE_STYLES = `
${buttonStyles}
${modalStyles}
${formStyles}
${listStyles}
:host {
display: none;
position: fixed;
z-index: var(--le-z-index-modal, 1001);
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: var(--le-background-color-modal-overlay, rgba(0,0,0,0.4));
align-items: center;
justify-content: center;
}
:host {
display: flex;
}
/* Teams Manager Layout */
.teams-manager-content {
background: var(--le-background-color-panel, #fff);
border-radius: var(--le-border-radius-large, 8px);
max-width: 900px;
width: 90%;
max-height: 80vh;
box-shadow: 0 4px 20px rgba(0,0,0,0.15);
display: flex;
flex-direction: column;
overflow: hidden;
margin: auto; /* Center the modal */
}
.teams-manager-content.mobile-view {
width: 95%;
max-width: 95%;
max-height: 90vh;
}
.teams-manager-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: var(--le-padding-l, 1.5rem);
border-bottom: 1px solid var(--le-border-color-light, #eee);
background: var(--le-background-color-header, #f8f9fa);
}
.teams-manager-header h3 {
margin: 0;
color: var(--le-text-color-primary, #333);
}
.teams-manager-body {
padding: var(--le-padding-l, 1.5rem);
flex: 1;
overflow: auto;
display: flex;
flex-direction: column;
gap: var(--le-padding-l, 1.5rem);
}
.teams-manager-footer {
display: flex;
justify-content: space-between;
align-items: center;
gap: var(--le-padding-m, 1rem);
padding: var(--le-padding-l, 1.5rem);
border-top: 1px solid var(--le-border-color-light, #eee);
background: var(--le-background-color-footer, #f8f9fa);
}
.footer-options {
display: flex;
align-items: center;
}
.footer-buttons {
display: flex;
gap: var(--le-padding-m, 1rem);
justify-content: flex-end;
margin-left: auto;
}
.checkbox-label {
display: flex;
align-items: center;
gap: var(--le-padding-s, 0.5rem);
cursor: pointer;
color: var(--le-text-color-primary, #333);
user-select: none;
}
.checkbox-label input[type="checkbox"] {
margin: 0;
cursor: pointer;
}
/* Team Input with Inline Buttons */
.team-input-with-buttons {
display: flex;
gap: var(--le-padding-m, 1rem);
align-items: flex-end;
}
.team-input-with-buttons .form-input-shared {
flex: 1;
}
.inline-buttons {
display: flex;
gap: var(--le-padding-s, 0.5rem);
flex-shrink: 0;
}
.inline-buttons .button-shared {
min-width: 80px;
white-space: nowrap;
}
/* Update button disabled state */
.button-update:disabled {
background-color: var(--le-background-color-disabled, #f5f5f5) !important;
color: var(--le-text-color-disabled, #999) !important;
border-color: var(--le-border-color-disabled, #ddd) !important;
cursor: not-allowed;
opacity: 0.6;
}
.button-update:disabled:hover {
background-color: var(--le-background-color-disabled, #f5f5f5) !important;
border-color: var(--le-border-color-disabled, #ddd) !important;
}
/* Action Buttons */
.teams-action-buttons {
display: flex;
gap: var(--le-padding-m, 1rem);
flex-wrap: wrap;
}
.teams-action-buttons .button-shared {
min-width: 100px;
}
.teams-action-buttons.disabled {
pointer-events: none;
opacity: 0.5;
}
/* Custom team styling for the shared list items */
.list-item .team-name {
font-weight: 500;
}
.list-item .team-source {
color: var(--le-text-color-secondary, #666);
font-style: italic;
margin-left: var(--le-padding-s, 0.5rem);
}
.no-teams-message {
padding: var(--le-padding-l, 1.5rem);
text-align: center;
color: var(--le-text-color-secondary, #666);
font-style: italic;
}
/* Team Editor Panel */
.team-editor-panel {
border: 1px solid var(--le-border-color-medium, #ddd);
border-radius: var(--le-border-radius-standard, 4px);
background: var(--le-background-color-panel, #fff);
animation: slideDown 0.3s ease-out;
}
@keyframes slideDown {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.team-editor-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: var(--le-padding-m, 1rem);
background: var(--le-background-color-header, #f8f9fa);
border-bottom: 1px solid var(--le-border-color-light, #eee);
}
.team-editor-header h4 {
margin: 0;
color: var(--le-text-color-primary, #333);
}
.team-editor-body {
padding: var(--le-padding-l, 1.5rem);
}
/* These form styles are provided by shared-styles.js formStyles import */
/* Update button styling */
.button-update {
background-color: var(--le-background-color-accent, #4caf50) !important;
color: white !important;
border-color: var(--le-border-color-accent, #45a049) !important;
}
.button-update:hover {
background-color: var(--le-background-color-accent-hover, #45a049) !important;
border-color: var(--le-border-color-accent-hover, #3d8b40) !important;
}
/* Mobile-specific adjustments */
@media (max-width: 480px) {
.teams-manager-content {
width: 95% !important;
max-width: 95% !important;
margin: 5% auto;
max-height: 95vh;
}
.teams-manager-header {
padding: 15px;
}
.teams-manager-body {
padding: 15px;
gap: 10px; /* Reduced gap to collapse space */
}
.teams-manager-footer {
padding: 15px;
flex-direction: row; /* Keep buttons side by side like league modal */
gap: 10px;
}
.footer-options {
order: 1;
justify-content: flex-start;
}
.footer-buttons {
order: 2;
flex-direction: row; /* Keep buttons side by side */
gap: 10px;
margin-left: auto;
}
.footer-buttons .button-shared {
width: auto; /* Allow buttons to size naturally */
margin: 0;
min-width: 80px; /* Ensure minimum touch target */
}
.teams-action-buttons {
flex-direction: column;
gap: 10px;
}
.teams-action-buttons .button-shared {
width: 100%;
min-width: auto;
}
.team-editor-header {
padding: 15px 10px;
flex-direction: column;
gap: 10px;
align-items: flex-start;
}
.team-editor-body {
padding: 15px 10px;
}
/* Mobile inline buttons */
.team-input-with-buttons {
flex-direction: column;
gap: 10px;
align-items: stretch;
}
.inline-buttons {
justify-content: flex-end;
gap: 10px;
}
.inline-buttons .button-shared {
min-width: 100px;
}
/* Form and button styles handled by shared-styles.js */
}
`;
function getDefaultExportFromCjs (x) {
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}
var sweetalert2_all$2 = {exports: {}};
/*!
* sweetalert2 v11.22.0
* Released under the MIT License.
*/
var sweetalert2_all$1 = sweetalert2_all$2.exports;
var hasRequiredSweetalert2_all;
function requireSweetalert2_all () {
if (hasRequiredSweetalert2_all) return sweetalert2_all$2.exports;
hasRequiredSweetalert2_all = 1;
(function (module, exports) {
(function (global, factory) {
module.exports = factory() ;
})(sweetalert2_all$1, (function () {
function _assertClassBrand(e, t, n) {
if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n;
throw new TypeError("Private element is not present on this object");
}
function _checkPrivateRedeclaration(e, t) {
if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object");
}
function _classPrivateFieldGet2(s, a) {
return s.get(_assertClassBrand(s, a));
}
function _classPrivateFieldInitSpec(e, t, a) {
_checkPrivateRedeclaration(e, t), t.set(e, a);
}
function _classPrivateFieldSet2(s, a, r) {
return s.set(_assertClassBrand(s, a), r), r;
}
const RESTORE_FOCUS_TIMEOUT = 100;
/** @type {GlobalState} */
const globalState = {};
const focusPreviousActiveElement = () => {
if (globalState.previousActiveElement instanceof HTMLElement) {
globalState.previousActiveElement.focus();
globalState.previousActiveElement = null;
} else if (document.body) {
document.body.focus();
}
};
/**
* Restore previous active (focused) element
*
* @param {boolean} returnFocus
* @returns {Promise<void>}
*/
const restoreActiveElement = returnFocus => {
return new Promise(resolve => {
if (!returnFocus) {
return resolve();
}
const x = window.scrollX;
const y = window.scrollY;
globalState.restoreFocusTimeout = setTimeout(() => {
focusPreviousActiveElement();
resolve();
}, RESTORE_FOCUS_TIMEOUT); // issues/900
window.scrollTo(x, y);
});
};
const swalPrefix = 'swal2-';
/**
* @typedef {Record<SwalClass, string>} SwalClasses
*/
/**
* @typedef {'success' | 'warning' | 'info' | 'question' | 'error'} SwalIcon
* @typedef {Record<SwalIcon, string>} SwalIcons
*/
/** @type {SwalClass[]} */
const classNames = ['container', 'shown', 'height-auto', 'iosfix', 'popup', 'modal', 'no-backdrop', 'no-transition', 'toast', 'toast-shown', 'show', 'hide', 'close', 'title', 'html-container', 'actions', 'confirm', 'deny', 'cancel', 'footer', 'icon', 'icon-content', 'image', 'input', 'file', 'range', 'select', 'radio', 'checkbox', 'label', 'textarea', 'inputerror', 'input-label', 'validation-message', 'progress-steps', 'active-progress-step', 'progress-step', 'progress-step-line', 'loader', 'loading', 'styled', 'top', 'top-start', 'top-end', 'top-left', 'top-right', 'center', 'center-start', 'center-end', 'center-left', 'center-right', 'bottom', 'bottom-start', 'bottom-end', 'bottom-left', 'bottom-right', 'grow-row', 'grow-column', 'grow-fullscreen', 'rtl', 'timer-progress-bar', 'timer-progress-bar-container', 'scrollbar-measure', 'icon-success', 'icon-warning', 'icon-info', 'icon-question', 'icon-error', 'draggable', 'dragging'];
const swalClasses = classNames.reduce((acc, className) => {
acc[className] = swalPrefix + className;
return acc;
}, /** @type {SwalClasses} */{});
/** @type {SwalIcon[]} */
const icons = ['success', 'warning', 'info', 'question', 'error'];
const iconTypes = icons.reduce((acc, icon) => {
acc[icon] = swalPrefix + icon;
return acc;
}, /** @type {SwalIcons} */{});
const consolePrefix = 'SweetAlert2:';
/**
* Capitalize the first letter of a string
*
* @param {string} str
* @returns {string}
*/
const capitalizeFirstLetter = str => str.charAt(0).toUpperCase() + str.slice(1);
/**
* Standardize console warnings
*
* @param {string | string[]} message
*/
const warn = message => {
console.warn(`${consolePrefix} ${typeof message === 'object' ? message.join(' ') : message}`);
};
/**
* Standardize console errors
*
* @param {string} message
*/
const error = message => {
console.error(`${consolePrefix} ${message}`);
};
/**
* Private global state for `warnOnce`
*
* @type {string[]}
* @private
*/
const previousWarnOnceMessages = [];
/**
* Show a console warning, but only if it hasn't already been shown
*
* @param {string} message
*/
const warnOnce = message => {
if (!previousWarnOnceMessages.includes(message)) {
previousWarnOnceMessages.push(message);
warn(message);
}
};
/**
* Show a one-time console warning about deprecated params/methods
*
* @param {string} deprecatedParam
* @param {string?} useInstead
*/
const warnAboutDeprecation = (deprecatedParam, useInstead = null) => {
warnOnce(`"${deprecatedParam}" is deprecated and will be removed in the next major release.${useInstead ? ` Use "${useInstead}" instead.` : ''}`);
};
/**
* If `arg` is a function, call it (with no arguments or context) and return the result.
* Otherwise, just pass the value through
*
* @param {Function | any} arg
* @returns {any}
*/
const callIfFunction = arg => typeof arg === 'function' ? arg() : arg;
/**
* @param {any} arg
* @returns {boolean}
*/
const hasToPromiseFn = arg => arg && typeof arg.toPromise === 'function';
/**
* @param {any} arg
* @returns {Promise<any>}
*/
const asPromise = arg => hasToPromiseFn(arg) ? arg.toPromise() : Promise.resolve(arg);
/**
* @param {any} arg
* @returns {boolean}
*/
const isPromise = arg => arg && Promise.resolve(arg) === arg;
/**
* Gets the popup container which contains the backdrop and the popup itself.
*
* @returns {HTMLElement | null}
*/
const getContainer = () => document.body.querySelector(`.${swalClasses.container}`);
/**
* @param {string} selectorString
* @returns {HTMLElement | null}
*/
const elementBySelector = selectorString => {
const container = getContainer();
return container ? container.querySelector(selectorString) : null;
};
/**
* @param {string} className
* @returns {HTMLElement | null}
*/
const elementByClass = className => {
return elementBySelector(`.${className}`);
};
/**
* @returns {HTMLElement | null}
*/
const getPopup = () => elementByClass(swalClasses.popup);
/**
* @returns {HTMLElement | null}
*/
const getIcon = () => elementByClass(swalClasses.icon);
/**
* @returns {HTMLElement | null}
*/
const getIconContent = () => elementByClass(swalClasses['icon-content']);
/**
* @returns {HTMLElement | null}
*/
const getTitle = () => elementByClass(swalClasses.title);
/**
* @returns {HTMLElement | null}
*/
const getHtmlContainer = () => elementByClass(swalClasses['html-container']);
/**
* @returns {HTMLElement | null}
*/
const getImage = () => elementByClass(swalClasses.image);
/**
* @returns {HTMLElement | null}
*/
const getProgressSteps = () => elementByClass(swalClasses['progress-steps']);
/**
* @returns {HTMLElement | null}
*/
const getValidationMessage = () => elementByClass(swalClasses['validation-message']);
/**
* @returns {HTMLButtonElement | null}
*/
const getConfirmButton = () => (/** @type {HTMLButtonElement} */elementBySelector(`.${swalClasses.actions} .${swalClasses.confirm}`));
/**
* @returns {HTMLButtonElement | null}
*/
const getCancelButton = () => (/** @type {HTMLButtonElement} */elementBySelector(`.${swalClasses.actions} .${swalClasses.cancel}`));
/**
* @returns {HTMLButtonElement | null}
*/
const getDenyButton = () => (/** @type {HTMLButtonElement} */elementBySelector(`.${swalClasses.actions} .${swalClasses.deny}`));
/**
* @returns {HTMLElement | null}
*/
const getInputLabel = () => elementByClass(swalClasses['input-label']);
/**
* @returns {HTMLElement | null}
*/
const getLoader = () => elementBySelector(`.${swalClasses.loader}`);
/**
* @returns {HTMLElement | null}
*/
const getActions = () => elementByClass(swalClasses.actions);
/**
* @returns {HTMLElement | null}
*/
const getFooter = () => elementByClass(swalClasses.footer);
/**
* @returns {HTMLElement | null}
*/
const getTimerProgressBar = () => elementByClass(swalClasses['timer-progress-bar']);
/**
* @returns {HTMLElement | null}
*/
const getCloseButton = () => elementByClass(swalClasses.close);
// https://github.com/jkup/focusable/blob/master/index.js
const focusable = `
a[href],
area[href],
input:not([disabled]),
select:not([disabled]),
textarea:not([disabled]),
button:not([disabled]),
iframe,
object,
embed,
[tabindex="0"],
[contenteditable],
audio[controls],
video[controls],
summary
`;
/**
* @returns {HTMLElement[]}
*/
const getFocusableElements = () => {
const popup = getPopup();
if (!popup) {
return [];
}
/** @type {NodeListOf<HTMLElement>} */
const focusableElementsWithTabindex = popup.querySelectorAll('[tabindex]:not([tabindex="-1"]):not([tabindex="0"])');
const focusableElementsWithTabindexSorted = Array.from(focusableElementsWithTabindex)
// sort according to tabindex
.sort((a, b) => {
const tabindexA = parseInt(a.getAttribute('tabindex') || '0');
const tabindexB = parseInt(b.getAttribute('tabindex') || '0');
if (tabindexA > tabindexB) {
return 1;
} else if (tabindexA < tabindexB) {
return -1;
}
return 0;
});
/** @type {NodeListOf<HTMLElement>} */
const otherFocusableElements = popup.querySelectorAll(focusable);
const otherFocusableElementsFiltered = Array.from(otherFocusableElements).filter(el => el.getAttribute('tabindex') !== '-1');
return [...new Set(focusableElementsWithTabindexSorted.concat(otherFocusableElementsFiltered))].filter(el => isVisible$1(el));
};
/**
* @returns {boolean}
*/
const isModal = () => {
return hasClass(document.body, swalClasses.shown) && !hasClass(document.body, swalClasses['toast-shown']) && !hasClass(document.body, swalClasses['no-backdrop']);
};
/**
* @returns {boolean}
*/
const isToast = () => {
const popup = getPopup();
if (!popup) {
return false;
}
return hasClass(popup, swalClasses.toast);
};
/**
* @returns {boolean}
*/
const isLoading = () => {
const popup = getPopup();
if (!popup) {
return false;
}
return popup.hasAttribute('data-loading');
};
/**
* Securely set innerHTML of an element
* https://github.com/sweetalert2/sweetalert2/issues/1926
*
* @param {HTMLElement} elem
* @param {string} html
*/
const setInnerHtml = (elem, html) => {
elem.textContent = '';
if (html) {
const parser = new DOMParser();
const parsed = parser.parseFromString(html, `text/html`);
const head = parsed.querySelector('head');
if (head) {
Array.from(head.childNodes).forEach(child => {
elem.appendChild(child);
});
}
const body = parsed.querySelector('body');
if (body) {
Array.from(body.childNodes).forEach(child => {
if (child instanceof HTMLVideoElement || child instanceof HTMLAudioElement) {
elem.appendChild(child.cloneNode(true)); // https://github.com/sweetalert2/sweetalert2/issues/2507
} else {
elem.appendChild(child);
}
});
}
}
};
/**
* @param {HTMLElement} elem
* @param {string} className
* @returns {boolean}
*/
const hasClass = (elem, className) => {
if (!className) {
return false;
}
const classList = className.split(/\s+/);
for (let i = 0; i < classList.length; i++) {
if (!elem.classList.contains(classList[i])) {
return false;
}
}
return true;
};
/**
* @param {HTMLElement} elem
* @param {SweetAlertOptions} params
*/
const removeCustomClasses = (elem, params) => {
Array.from(elem.classList).forEach(className => {
if (!Object.values(swalClasses).includes(className) && !Object.values(iconTypes).includes(className) && !Object.values(params.showClass || {}).includes(className)) {
elem.classList.remove(className);
}
});
};
/**
* @param {HTMLElement} elem
* @param {SweetAlertOptions} params
* @param {string} className
*/
const applyCustomClass = (elem, params, className) => {
removeCustomClasses(elem, params);
if (!params.customClass) {
return;
}
const customClass = params.customClass[(/** @type {keyof SweetAlertCustomClass} */className)];
if (!customClass) {
return;
}
if (typeof customClass !== 'string' && !customClass.forEach) {
warn(`Invalid type of customClass.${className}! Expected string or iterable object, got "${typeof customClass}"`);
return;
}
addClass(elem, customClass);
};
/**
* @param {HTMLElement} popup
* @param {import('./renderers/renderInput').InputClass | SweetAlertInput} inputClass
* @returns {HTMLInputElement | null}
*/
const getInput$1 = (popup, inputClass) => {
if (!inputClass) {
return null;
}
switch (inputClass) {
case 'select':
case 'textarea':
case 'file':
return popup.querySelector(`.${swalClasses.popup} > .${swalClasses[inputClass]}`);
case 'checkbox':
return popup.querySelector(`.${swalClasses.popup} > .${swalClasses.checkbox} input`);
case 'radio':
return popup.querySelector(`.${swalClasses.popup} >