Compare commits

...

1 Commits

Author SHA1 Message Date
Mark Otto 2b9f1fcaab Rebuild dist for v6 2025-12-29 15:00:16 -08:00
38 changed files with 5500 additions and 1407 deletions
+13 -13
View File
@@ -4,19 +4,19 @@
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
:root {
--bs-blue-025: color-mix(in lab, #fff 94%, oklch(60% 0.24 258deg));
--bs-blue-050: color-mix(in lab, #fff 90%, oklch(60% 0.24 258deg));
--bs-blue-100: color-mix(in lab, #fff 80%, oklch(60% 0.24 258deg));
--bs-blue-200: color-mix(in lab, #fff 60%, oklch(60% 0.24 258deg));
--bs-blue-300: color-mix(in lab, #fff 40%, oklch(60% 0.24 258deg));
--bs-blue-400: color-mix(in lab, #fff 20%, oklch(60% 0.24 258deg));
--bs-blue-500: oklch(60% 0.24 258deg);
--bs-blue-600: color-mix(in lab, #000 16%, oklch(60% 0.24 258deg));
--bs-blue-700: color-mix(in lab, #000 32%, oklch(60% 0.24 258deg));
--bs-blue-800: color-mix(in lab, #000 48%, oklch(60% 0.24 258deg));
--bs-blue-900: color-mix(in lab, #000 64%, oklch(60% 0.24 258deg));
--bs-blue-950: color-mix(in lab, #000 76%, oklch(60% 0.24 258deg));
--bs-blue-975: color-mix(in lab, #000 88%, oklch(60% 0.24 258deg));
--bs-blue-025: color-mix(in lab, #fff 94%, oklch(60% 0.24 240deg));
--bs-blue-050: color-mix(in lab, #fff 90%, oklch(60% 0.24 240deg));
--bs-blue-100: color-mix(in lab, #fff 80%, oklch(60% 0.24 240deg));
--bs-blue-200: color-mix(in lab, #fff 60%, oklch(60% 0.24 240deg));
--bs-blue-300: color-mix(in lab, #fff 40%, oklch(60% 0.24 240deg));
--bs-blue-400: color-mix(in lab, #fff 20%, oklch(60% 0.24 240deg));
--bs-blue-500: oklch(60% 0.24 240deg);
--bs-blue-600: color-mix(in lab, #000 16%, oklch(60% 0.24 240deg));
--bs-blue-700: color-mix(in lab, #000 32%, oklch(60% 0.24 240deg));
--bs-blue-800: color-mix(in lab, #000 48%, oklch(60% 0.24 240deg));
--bs-blue-900: color-mix(in lab, #000 64%, oklch(60% 0.24 240deg));
--bs-blue-950: color-mix(in lab, #000 76%, oklch(60% 0.24 240deg));
--bs-blue-975: color-mix(in lab, #000 88%, oklch(60% 0.24 240deg));
--bs-indigo-025: color-mix(in lab, #fff 94%, oklch(56% 0.26 288deg));
--bs-indigo-050: color-mix(in lab, #fff 90%, oklch(56% 0.26 288deg));
--bs-indigo-100: color-mix(in lab, #fff 80%, oklch(56% 0.26 288deg));
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+19 -20
View File
@@ -4,19 +4,19 @@
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
:root {
--bs-blue-025: color-mix(in lab, #fff 94%, oklch(60% 0.24 258deg));
--bs-blue-050: color-mix(in lab, #fff 90%, oklch(60% 0.24 258deg));
--bs-blue-100: color-mix(in lab, #fff 80%, oklch(60% 0.24 258deg));
--bs-blue-200: color-mix(in lab, #fff 60%, oklch(60% 0.24 258deg));
--bs-blue-300: color-mix(in lab, #fff 40%, oklch(60% 0.24 258deg));
--bs-blue-400: color-mix(in lab, #fff 20%, oklch(60% 0.24 258deg));
--bs-blue-500: oklch(60% 0.24 258deg);
--bs-blue-600: color-mix(in lab, #000 16%, oklch(60% 0.24 258deg));
--bs-blue-700: color-mix(in lab, #000 32%, oklch(60% 0.24 258deg));
--bs-blue-800: color-mix(in lab, #000 48%, oklch(60% 0.24 258deg));
--bs-blue-900: color-mix(in lab, #000 64%, oklch(60% 0.24 258deg));
--bs-blue-950: color-mix(in lab, #000 76%, oklch(60% 0.24 258deg));
--bs-blue-975: color-mix(in lab, #000 88%, oklch(60% 0.24 258deg));
--bs-blue-025: color-mix(in lab, #fff 94%, oklch(60% 0.24 240deg));
--bs-blue-050: color-mix(in lab, #fff 90%, oklch(60% 0.24 240deg));
--bs-blue-100: color-mix(in lab, #fff 80%, oklch(60% 0.24 240deg));
--bs-blue-200: color-mix(in lab, #fff 60%, oklch(60% 0.24 240deg));
--bs-blue-300: color-mix(in lab, #fff 40%, oklch(60% 0.24 240deg));
--bs-blue-400: color-mix(in lab, #fff 20%, oklch(60% 0.24 240deg));
--bs-blue-500: oklch(60% 0.24 240deg);
--bs-blue-600: color-mix(in lab, #000 16%, oklch(60% 0.24 240deg));
--bs-blue-700: color-mix(in lab, #000 32%, oklch(60% 0.24 240deg));
--bs-blue-800: color-mix(in lab, #000 48%, oklch(60% 0.24 240deg));
--bs-blue-900: color-mix(in lab, #000 64%, oklch(60% 0.24 240deg));
--bs-blue-950: color-mix(in lab, #000 76%, oklch(60% 0.24 240deg));
--bs-blue-975: color-mix(in lab, #000 88%, oklch(60% 0.24 240deg));
--bs-indigo-025: color-mix(in lab, #fff 94%, oklch(56% 0.26 288deg));
--bs-indigo-050: color-mix(in lab, #fff 90%, oklch(56% 0.26 288deg));
--bs-indigo-100: color-mix(in lab, #fff 80%, oklch(56% 0.26 288deg));
@@ -450,6 +450,7 @@
--bs-body-color-rgb: to-rgb(var(--bs-color-body));
--bs-body-bg-rgb: to-rgb(var(--bs-bg-body));
--bs-heading-color: inherit;
--bs-hr-border-color: var(--bs-border-color);
--bs-link-color: light-dark(var(--bs-primary-base), var(--bs-primary-text));
--bs-link-decoration: underline;
--bs-link-hover-color: color-mix(in oklch, var(--bs-link-color) 90%, #000);
@@ -471,7 +472,7 @@
--bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175);
--bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075);
--bs-focus-ring-width: 3px;
--bs-focus-ring-offset: -1px;
--bs-focus-ring-offset: 1px;
--bs-focus-ring-color: var(--bs-primary-focus-ring);
--bs-focus-ring: var(--bs-focus-ring-width) solid var(--bs-focus-ring-color);
--bs-form-valid-color: var(--bs-success);
@@ -521,10 +522,8 @@
}
hr {
margin: 1rem 0;
color: inherit;
border: 0;
border-block-start: var(--bs-border-width) solid;
opacity: 0.25;
border-block-start: var(--bs-border-width) solid var(--bs-hr-border-color);
}
h6,
.h6, h5,
@@ -633,13 +632,13 @@
top: -0.5em;
}
a {
color: var(--bs-link-color);
color: var(--bs-theme-text, var(--bs-link-color));
-webkit-text-decoration: var(--bs-link-decoration);
text-decoration: var(--bs-link-decoration);
text-underline-offset: 0.2em;
}
a:hover {
color: var(--bs-link-hover-color);
color: var(--bs-theme-text-emphasis, var(--bs-link-hover-color));
-webkit-text-decoration: var(--bs-link-hover-decoration, var(--bs-link-decoration));
text-decoration: var(--bs-link-hover-decoration, var(--bs-link-decoration));
}
@@ -678,7 +677,7 @@
padding: 0.1875rem 0.375rem;
font-size: 95%;
color: var(--bs-bg-body);
background-color: var(--bs-color-body);
background-color: var(--bs-fg-body);
border-radius: 0.375rem;
}
kbd kbd {
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+61 -146
View File
@@ -4,19 +4,19 @@
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
:root {
--bs-blue-025: color-mix(in lab, #fff 94%, oklch(60% 0.24 258deg));
--bs-blue-050: color-mix(in lab, #fff 90%, oklch(60% 0.24 258deg));
--bs-blue-100: color-mix(in lab, #fff 80%, oklch(60% 0.24 258deg));
--bs-blue-200: color-mix(in lab, #fff 60%, oklch(60% 0.24 258deg));
--bs-blue-300: color-mix(in lab, #fff 40%, oklch(60% 0.24 258deg));
--bs-blue-400: color-mix(in lab, #fff 20%, oklch(60% 0.24 258deg));
--bs-blue-500: oklch(60% 0.24 258deg);
--bs-blue-600: color-mix(in lab, #000 16%, oklch(60% 0.24 258deg));
--bs-blue-700: color-mix(in lab, #000 32%, oklch(60% 0.24 258deg));
--bs-blue-800: color-mix(in lab, #000 48%, oklch(60% 0.24 258deg));
--bs-blue-900: color-mix(in lab, #000 64%, oklch(60% 0.24 258deg));
--bs-blue-950: color-mix(in lab, #000 76%, oklch(60% 0.24 258deg));
--bs-blue-975: color-mix(in lab, #000 88%, oklch(60% 0.24 258deg));
--bs-blue-025: color-mix(in lab, #fff 94%, oklch(60% 0.24 240deg));
--bs-blue-050: color-mix(in lab, #fff 90%, oklch(60% 0.24 240deg));
--bs-blue-100: color-mix(in lab, #fff 80%, oklch(60% 0.24 240deg));
--bs-blue-200: color-mix(in lab, #fff 60%, oklch(60% 0.24 240deg));
--bs-blue-300: color-mix(in lab, #fff 40%, oklch(60% 0.24 240deg));
--bs-blue-400: color-mix(in lab, #fff 20%, oklch(60% 0.24 240deg));
--bs-blue-500: oklch(60% 0.24 240deg);
--bs-blue-600: color-mix(in lab, #000 16%, oklch(60% 0.24 240deg));
--bs-blue-700: color-mix(in lab, #000 32%, oklch(60% 0.24 240deg));
--bs-blue-800: color-mix(in lab, #000 48%, oklch(60% 0.24 240deg));
--bs-blue-900: color-mix(in lab, #000 64%, oklch(60% 0.24 240deg));
--bs-blue-950: color-mix(in lab, #000 76%, oklch(60% 0.24 240deg));
--bs-blue-975: color-mix(in lab, #000 88%, oklch(60% 0.24 240deg));
--bs-indigo-025: color-mix(in lab, #fff 94%, oklch(56% 0.26 288deg));
--bs-indigo-050: color-mix(in lab, #fff 90%, oklch(56% 0.26 288deg));
--bs-indigo-100: color-mix(in lab, #fff 80%, oklch(56% 0.26 288deg));
@@ -450,6 +450,7 @@
--bs-body-color-rgb: to-rgb(var(--bs-color-body));
--bs-body-bg-rgb: to-rgb(var(--bs-bg-body));
--bs-heading-color: inherit;
--bs-hr-border-color: var(--bs-border-color);
--bs-link-color: light-dark(var(--bs-primary-base), var(--bs-primary-text));
--bs-link-decoration: underline;
--bs-link-hover-color: color-mix(in oklch, var(--bs-link-color) 90%, #000);
@@ -471,7 +472,7 @@
--bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175);
--bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075);
--bs-focus-ring-width: 3px;
--bs-focus-ring-offset: -1px;
--bs-focus-ring-offset: 1px;
--bs-focus-ring-color: var(--bs-primary-focus-ring);
--bs-focus-ring: var(--bs-focus-ring-width) solid var(--bs-focus-ring-color);
--bs-form-valid-color: var(--bs-success);
@@ -493,106 +494,6 @@
--bs-form-invalid-border-color: var(--bs-red-300);
}
@layer helpers {
.text-bg-primary {
color: var(--bs-primary-text);
--bs-bg: var(--bs-primary-bg-subtle);
}
.text-bg-accent {
color: var(--bs-accent-text);
--bs-bg: var(--bs-accent-bg-subtle);
}
.text-bg-success {
color: var(--bs-success-text);
--bs-bg: var(--bs-success-bg-subtle);
}
.text-bg-danger {
color: var(--bs-danger-text);
--bs-bg: var(--bs-danger-bg-subtle);
}
.text-bg-warning {
color: var(--bs-warning-text);
--bs-bg: var(--bs-warning-bg-subtle);
}
.text-bg-info {
color: var(--bs-info-text);
--bs-bg: var(--bs-info-bg-subtle);
}
.text-bg-inverse {
color: var(--bs-inverse-text);
--bs-bg: var(--bs-inverse-bg-subtle);
}
.text-bg-secondary {
color: var(--bs-secondary-text);
--bs-bg: var(--bs-secondary-bg-subtle);
}
}
@layer helpers {
.link-primary {
--bs-link-color: var(--bs-primary-text);
}
.link-primary:hover, .link-primary:focus {
--bs-link-color: var(--bs-primary-text-emphasis);
--bs-link-hover-color: var(--bs-primary-text-emphasis);
}
.link-accent {
--bs-link-color: var(--bs-accent-text);
}
.link-accent:hover, .link-accent:focus {
--bs-link-color: var(--bs-accent-text-emphasis);
--bs-link-hover-color: var(--bs-accent-text-emphasis);
}
.link-success {
--bs-link-color: var(--bs-success-text);
}
.link-success:hover, .link-success:focus {
--bs-link-color: var(--bs-success-text-emphasis);
--bs-link-hover-color: var(--bs-success-text-emphasis);
}
.link-danger {
--bs-link-color: var(--bs-danger-text);
}
.link-danger:hover, .link-danger:focus {
--bs-link-color: var(--bs-danger-text-emphasis);
--bs-link-hover-color: var(--bs-danger-text-emphasis);
}
.link-warning {
--bs-link-color: var(--bs-warning-text);
}
.link-warning:hover, .link-warning:focus {
--bs-link-color: var(--bs-warning-text-emphasis);
--bs-link-hover-color: var(--bs-warning-text-emphasis);
}
.link-info {
--bs-link-color: var(--bs-info-text);
}
.link-info:hover, .link-info:focus {
--bs-link-color: var(--bs-info-text-emphasis);
--bs-link-hover-color: var(--bs-info-text-emphasis);
}
.link-inverse {
--bs-link-color: var(--bs-inverse-text);
}
.link-inverse:hover, .link-inverse:focus {
--bs-link-color: var(--bs-inverse-text-emphasis);
--bs-link-hover-color: var(--bs-inverse-text-emphasis);
}
.link-secondary {
--bs-link-color: var(--bs-secondary-text);
}
.link-secondary:hover, .link-secondary:focus {
--bs-link-color: var(--bs-secondary-text-emphasis);
--bs-link-hover-color: var(--bs-secondary-text-emphasis);
}
.link-body-emphasis {
color: color-mix(in srgb, var(--bs-emphasis-color), transparent var(--bs-link-opacity));
text-decoration-color: color-mix(in srgb, var(--bs-emphasis-color), transparent var(--bs-link-underline-opacity));
}
.link-body-emphasis:hover, .link-body-emphasis:focus {
color: color-mix(in srgb, var(--bs-emphasis-color), transparent var(--bs-link-opacity, 0.75));
text-decoration-color: color-mix(in srgb, var(--bs-emphasis-color), transparent var(--bs-link-underline-opacity, 0.75));
}
}
@layer helpers {
.focus-ring:focus-visible {
outline: var(--bs-focus-ring);
@@ -770,8 +671,7 @@
align-self: stretch;
width: var(--bs-border-width);
min-height: 1em;
background-color: currentcolor;
opacity: 0.25;
background-color: var(--bs-border-color);
}
}
@layer utilities {
@@ -2091,36 +1991,6 @@
--bs-fg: light-dark(var(--bs-gray-800), var(--bs-gray-200));
color: var(--bs-fg);
}
.fg-10 {
color: color-mix(in oklch, var(--bs-fg) 10%, transparent);
}
.fg-20 {
color: color-mix(in oklch, var(--bs-fg) 20%, transparent);
}
.fg-30 {
color: color-mix(in oklch, var(--bs-fg) 30%, transparent);
}
.fg-40 {
color: color-mix(in oklch, var(--bs-fg) 40%, transparent);
}
.fg-50 {
color: color-mix(in oklch, var(--bs-fg) 50%, transparent);
}
.fg-60 {
color: color-mix(in oklch, var(--bs-fg) 60%, transparent);
}
.fg-70 {
color: color-mix(in oklch, var(--bs-fg) 70%, transparent);
}
.fg-80 {
color: color-mix(in oklch, var(--bs-fg) 80%, transparent);
}
.fg-90 {
color: color-mix(in oklch, var(--bs-fg) 90%, transparent);
}
.fg-100 {
color: var(--bs-fg);
}
.fg-contrast-primary {
--bs-fg: var(--bs-white);
color: var(--bs-fg);
@@ -2153,6 +2023,36 @@
--bs-fg: light-dark(var(--bs-gray-900), var(--bs-white));
color: var(--bs-fg);
}
.fg-10 {
color: color-mix(in oklch, var(--bs-fg) 10%, transparent);
}
.fg-20 {
color: color-mix(in oklch, var(--bs-fg) 20%, transparent);
}
.fg-30 {
color: color-mix(in oklch, var(--bs-fg) 30%, transparent);
}
.fg-40 {
color: color-mix(in oklch, var(--bs-fg) 40%, transparent);
}
.fg-50 {
color: color-mix(in oklch, var(--bs-fg) 50%, transparent);
}
.fg-60 {
color: color-mix(in oklch, var(--bs-fg) 60%, transparent);
}
.fg-70 {
color: color-mix(in oklch, var(--bs-fg) 70%, transparent);
}
.fg-80 {
color: color-mix(in oklch, var(--bs-fg) 80%, transparent);
}
.fg-90 {
color: color-mix(in oklch, var(--bs-fg) 90%, transparent);
}
.fg-100 {
color: var(--bs-fg);
}
.link-10 {
color: color-mix(in oklch, var(--bs-link-color) 10%, transparent);
}
@@ -2507,6 +2407,21 @@
.bg-100 {
background-color: var(--bs-bg);
}
.theme-contrast {
background-color: var(--bs-theme-bg);
color: var(--bs-theme-contrast);
}
.theme-subtle {
background-color: var(--bs-theme-bg-subtle);
color: var(--bs-theme-text);
}
.theme-muted {
background-color: var(--bs-theme-bg-muted);
color: var(--bs-theme-text-emphasis);
}
.theme-border {
border: var(--bs-border-width) solid var(--bs-theme-border);
}
.bg-gradient {
background-image: var(--bs-gradient);
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+528 -352
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1258 -268
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1256 -269
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1258 -268
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+471 -48
View File
@@ -29,8 +29,16 @@
const TAB_KEY = 'Tab';
const ARROW_UP_KEY = 'ArrowUp';
const ARROW_DOWN_KEY = 'ArrowDown';
const RIGHT_MOUSE_BUTTON = 2; // MouseEvent.button value for the secondary button, usually the right button
const ARROW_LEFT_KEY = 'ArrowLeft';
const ARROW_RIGHT_KEY = 'ArrowRight';
const HOME_KEY = 'Home';
const END_KEY = 'End';
const ENTER_KEY = 'Enter';
const SPACE_KEY = ' ';
const RIGHT_MOUSE_BUTTON = 2;
// Hover intent delay (ms) - grace period before closing submenu
const SUBMENU_CLOSE_DELAY = 100;
const EVENT_HIDE = `hide${EVENT_KEY}`;
const EVENT_HIDDEN = `hidden${EVENT_KEY}`;
const EVENT_SHOW = `show${EVENT_KEY}`;
@@ -42,11 +50,28 @@
const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="dropdown"]:not(.disabled):not(:disabled)';
const SELECTOR_DATA_TOGGLE_SHOWN = `${SELECTOR_DATA_TOGGLE}.${CLASS_NAME_SHOW}`;
const SELECTOR_MENU = '.dropdown-menu';
const SELECTOR_SUBMENU = '.dropdown-submenu';
const SELECTOR_SUBMENU_TOGGLE = '.dropdown-submenu > .dropdown-item';
const SELECTOR_NAVBAR_NAV = '.navbar-nav';
const SELECTOR_VISIBLE_ITEMS = '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)';
const SELECTOR_VISIBLE_ITEMS = '.dropdown-item:not(.disabled):not(:disabled)';
// Default placement with RTL support
const DEFAULT_PLACEMENT = index_js.isRTL() ? 'bottom-end' : 'bottom-start';
// Default logical placement (uses start/end which get resolved to left/right based on RTL)
const DEFAULT_PLACEMENT = 'bottom-start';
const SUBMENU_PLACEMENT = 'end-start';
// Resolve logical placement (start/end) to physical (left/right) based on RTL
const resolveLogicalPlacement = placement => {
if (index_js.isRTL()) {
// RTL: start → right, end → left
return placement.replace(/^start(?=-|$)/, 'right').replace(/^end(?=-|$)/, 'left');
}
// LTR: start → left, end → right
return placement.replace(/^start(?=-|$)/, 'left').replace(/^end(?=-|$)/, 'right');
};
// Helper for barycentric coordinate calculation (point in triangle check)
const triangleSign = (p1, p2, p3) => (p1.x - p3.x) * (p2.y - p3.y) - (p2.x - p3.x) * (p1.y - p3.y);
const Default = {
autoClose: true,
boundary: 'clippingParents',
@@ -54,7 +79,11 @@
offset: [0, 2],
floatingConfig: null,
placement: DEFAULT_PLACEMENT,
reference: 'toggle'
reference: 'toggle',
// Submenu options
submenuTrigger: 'both',
// 'click', 'hover', or 'both'
submenuDelay: SUBMENU_CLOSE_DELAY
};
const DefaultType = {
autoClose: '(boolean|string)',
@@ -63,7 +92,9 @@
offset: '(array|string|function)',
floatingConfig: '(null|object|function)',
placement: 'string',
reference: '(string|element|object)'
reference: '(string|element|object)',
submenuTrigger: 'string',
submenuDelay: 'number'
};
/**
@@ -80,11 +111,19 @@
this._mediaQueryListeners = [];
this._responsivePlacements = null;
this._parent = this._element.parentNode; // dropdown wrapper
this._isSubmenu = this._parent.classList.contains('dropdown-submenu');
this._openSubmenus = new Map(); // Map of submenu element -> cleanup function
this._submenuCloseTimeouts = new Map(); // Map of submenu element -> timeout ID
this._hoverIntentData = null; // For safe triangle calculation
// TODO: v6 revert #37011 & change markup https://getbootstrap.com/docs/5.3/forms/input-group/
this._menu = SelectorEngine.next(this._element, SELECTOR_MENU)[0] || SelectorEngine.prev(this._element, SELECTOR_MENU)[0] || SelectorEngine.findOne(SELECTOR_MENU, this._parent);
// Parse responsive placements on init
this._parseResponsivePlacements();
// Set up submenu event listeners
this._setupSubmenuListeners();
}
// Getters
@@ -125,9 +164,10 @@
}
}
this._element.focus();
this._element.setAttribute('aria-expanded', true);
this._element.setAttribute('aria-expanded', 'true');
this._menu.classList.add(CLASS_NAME_SHOW);
this._element.classList.add(CLASS_NAME_SHOW);
this._parent.classList.add(CLASS_NAME_SHOW);
EventHandler.trigger(this._element, EVENT_SHOWN, relatedTarget);
}
hide() {
@@ -142,6 +182,8 @@
dispose() {
this._disposeFloating();
this._disposeMediaQueryListeners();
this._closeAllSubmenus();
this._clearAllSubmenuTimeouts();
super.dispose();
}
update() {
@@ -157,6 +199,9 @@
return;
}
// Close all open submenus first
this._closeAllSubmenus();
// If this is a touch-enabled device we remove the extra
// empty mouseover listeners we added for iOS support
if ('ontouchstart' in document.documentElement) {
@@ -167,6 +212,7 @@
this._disposeFloating();
this._menu.classList.remove(CLASS_NAME_SHOW);
this._element.classList.remove(CLASS_NAME_SHOW);
this._parent.classList.remove(CLASS_NAME_SHOW);
this._element.setAttribute('aria-expanded', 'false');
Manipulator.removeDataAttribute(this._menu, 'placement');
Manipulator.removeDataAttribute(this._menu, 'display');
@@ -201,8 +247,7 @@
this._floatingCleanup = dom.autoUpdate(referenceElement, this._menu, () => this._updateFloatingPosition(referenceElement));
}
async _updateFloatingPosition(referenceElement = null) {
// Check if menu exists and is still in the DOM
if (!this._menu || !this._menu.isConnected) {
if (!this._menu) {
return;
}
if (!referenceElement) {
@@ -219,37 +264,17 @@
const placement = this._getPlacement();
const middleware = this._getFloatingMiddleware();
const floatingConfig = this._getFloatingConfig(placement, middleware);
const {
x,
y,
placement: finalPlacement
} = await dom.computePosition(referenceElement, this._menu, floatingConfig);
// Menu may have been disposed during the async computePosition call
if (!this._menu || !this._menu.isConnected) {
return;
}
// Apply position to dropdown menu
Object.assign(this._menu.style, {
position: 'absolute',
left: `${x}px`,
top: `${y}px`,
margin: '0'
});
// Set placement attribute for CSS styling
Manipulator.setDataAttribute(this._menu, 'placement', finalPlacement);
await this._applyFloatingPosition(referenceElement, this._menu, floatingConfig.placement, floatingConfig.middleware);
}
_isShown() {
return this._menu.classList.contains(CLASS_NAME_SHOW);
}
_getPlacement() {
// If we have responsive placements, find the appropriate one for current viewport
if (this._responsivePlacements) {
return floatingUi_js.getResponsivePlacement(this._responsivePlacements, DEFAULT_PLACEMENT);
}
return this._config.placement;
const placement = this._responsivePlacements ? floatingUi_js.getResponsivePlacement(this._responsivePlacements, DEFAULT_PLACEMENT) : this._config.placement;
// Resolve logical placements (start/end) to physical (left/right) based on RTL
return resolveLogicalPlacement(placement);
}
_parseResponsivePlacements() {
this._responsivePlacements = floatingUi_js.parseResponsivePlacement(this._config.placement, DEFAULT_PLACEMENT);
@@ -271,18 +296,18 @@
}
_getOffset() {
const {
offset
offset: offsetConfig
} = this._config;
if (typeof offset === 'string') {
return offset.split(',').map(value => Number.parseInt(value, 10));
if (typeof offsetConfig === 'string') {
return offsetConfig.split(',').map(value => Number.parseInt(value, 10));
}
if (typeof offset === 'function') {
if (typeof offsetConfig === 'function') {
// Floating UI passes different args, adapt the interface for offset function callbacks
return ({
placement,
rects
}) => {
const result = offset({
const result = offsetConfig({
placement,
reference: rects.reference,
floating: rects.floating
@@ -290,7 +315,7 @@
return result;
};
}
return offset;
return offsetConfig;
}
_getFloatingMiddleware() {
const offsetValue = this._getOffset();
@@ -348,11 +373,296 @@
this._floatingCleanup = null;
}
}
// Shared helper for positioning any floating element
async _applyFloatingPosition(reference, floating, placement, middleware) {
if (!floating.isConnected) {
return null;
}
const {
x,
y,
placement: finalPlacement
} = await dom.computePosition(reference, floating, {
placement,
middleware
});
if (!floating.isConnected) {
return null;
}
Object.assign(floating.style, {
position: 'absolute',
left: `${x}px`,
top: `${y}px`,
margin: '0'
});
Manipulator.setDataAttribute(floating, 'placement', finalPlacement);
return finalPlacement;
}
// -------------------------------------------------------------------------
// Submenu handling
// -------------------------------------------------------------------------
_setupSubmenuListeners() {
// Set up hover listeners for submenu triggers
if (this._config.submenuTrigger === 'hover' || this._config.submenuTrigger === 'both') {
EventHandler.on(this._menu, 'mouseenter', SELECTOR_SUBMENU_TOGGLE, event => {
this._onSubmenuTriggerEnter(event);
});
EventHandler.on(this._menu, 'mouseleave', SELECTOR_SUBMENU, event => {
this._onSubmenuLeave(event);
});
// Track mouse movement for safe triangle calculation
EventHandler.on(this._menu, 'mousemove', event => {
this._trackMousePosition(event);
});
}
// Set up click listener for submenu triggers
if (this._config.submenuTrigger === 'click' || this._config.submenuTrigger === 'both') {
EventHandler.on(this._menu, 'click', SELECTOR_SUBMENU_TOGGLE, event => {
this._onSubmenuTriggerClick(event);
});
}
}
_onSubmenuTriggerEnter(event) {
const trigger = event.target.closest(SELECTOR_SUBMENU_TOGGLE);
if (!trigger) {
return;
}
const submenuWrapper = trigger.closest(SELECTOR_SUBMENU);
const submenu = SelectorEngine.findOne(SELECTOR_MENU, submenuWrapper);
if (!submenu) {
return;
}
// Cancel any pending close timeout for this submenu
this._cancelSubmenuCloseTimeout(submenu);
// Close other open submenus at the same level
this._closeSiblingSubmenus(submenuWrapper);
// Open this submenu
this._openSubmenu(trigger, submenu, submenuWrapper);
}
_onSubmenuLeave(event) {
const submenuWrapper = event.target.closest(SELECTOR_SUBMENU);
const submenu = SelectorEngine.findOne(SELECTOR_MENU, submenuWrapper);
if (!submenu || !this._openSubmenus.has(submenu)) {
return;
}
// Check if we're moving toward the submenu (safe triangle)
if (this._isMovingTowardSubmenu(event, submenu)) {
return;
}
// Schedule submenu close with delay
this._scheduleSubmenuClose(submenu, submenuWrapper);
}
_onSubmenuTriggerClick(event) {
const trigger = event.target.closest(SELECTOR_SUBMENU_TOGGLE);
if (!trigger) {
return;
}
event.preventDefault();
event.stopPropagation();
const submenuWrapper = trigger.closest(SELECTOR_SUBMENU);
const submenu = SelectorEngine.findOne(SELECTOR_MENU, submenuWrapper);
if (!submenu) {
return;
}
// Toggle submenu
if (this._openSubmenus.has(submenu)) {
this._closeSubmenu(submenu, submenuWrapper);
} else {
this._closeSiblingSubmenus(submenuWrapper);
this._openSubmenu(trigger, submenu, submenuWrapper);
}
}
_openSubmenu(trigger, submenu, submenuWrapper) {
if (this._openSubmenus.has(submenu)) {
return;
}
// Set ARIA attributes
trigger.setAttribute('aria-expanded', 'true');
trigger.setAttribute('aria-haspopup', 'true');
// Position and show submenu
submenu.classList.add(CLASS_NAME_SHOW);
submenuWrapper.classList.add(CLASS_NAME_SHOW);
// Set up Floating UI positioning for submenu
const cleanup = this._createSubmenuFloating(trigger, submenu, submenuWrapper);
this._openSubmenus.set(submenu, cleanup);
// Set up mouseenter on submenu to cancel close timeout
EventHandler.on(submenu, 'mouseenter', () => {
this._cancelSubmenuCloseTimeout(submenu);
});
}
_closeSubmenu(submenu, submenuWrapper) {
if (!this._openSubmenus.has(submenu)) {
return;
}
// Close any nested submenus first
const nestedSubmenus = SelectorEngine.find(`${SELECTOR_SUBMENU} ${SELECTOR_MENU}.${CLASS_NAME_SHOW}`, submenu);
for (const nested of nestedSubmenus) {
const nestedWrapper = nested.closest(SELECTOR_SUBMENU);
this._closeSubmenu(nested, nestedWrapper);
}
// Get the trigger
const trigger = SelectorEngine.findOne(SELECTOR_SUBMENU_TOGGLE, submenuWrapper);
// Clean up Floating UI
const cleanup = this._openSubmenus.get(submenu);
if (cleanup) {
cleanup();
}
this._openSubmenus.delete(submenu);
// Remove event listeners
EventHandler.off(submenu, 'mouseenter');
// Update ARIA and visibility
if (trigger) {
trigger.setAttribute('aria-expanded', 'false');
}
submenu.classList.remove(CLASS_NAME_SHOW);
submenuWrapper.classList.remove(CLASS_NAME_SHOW);
// Clear inline styles
submenu.style.position = '';
submenu.style.left = '';
submenu.style.top = '';
submenu.style.margin = '';
}
_closeAllSubmenus() {
for (const [submenu] of this._openSubmenus) {
const submenuWrapper = submenu.closest(SELECTOR_SUBMENU);
this._closeSubmenu(submenu, submenuWrapper);
}
}
_closeSiblingSubmenus(currentSubmenuWrapper) {
// Find all sibling submenu wrappers and close their menus
const parent = currentSubmenuWrapper.parentNode;
const siblingSubmenus = SelectorEngine.find(`${SELECTOR_SUBMENU} > ${SELECTOR_MENU}.${CLASS_NAME_SHOW}`, parent);
for (const siblingMenu of siblingSubmenus) {
const siblingWrapper = siblingMenu.closest(SELECTOR_SUBMENU);
if (siblingWrapper !== currentSubmenuWrapper) {
this._closeSubmenu(siblingMenu, siblingWrapper);
}
}
}
_createSubmenuFloating(trigger, submenu, submenuWrapper) {
const referenceElement = submenuWrapper;
const placement = resolveLogicalPlacement(SUBMENU_PLACEMENT);
const middleware = [dom.offset({
mainAxis: 0,
crossAxis: -4
}), dom.flip({
fallbackPlacements: [resolveLogicalPlacement('start-start'), resolveLogicalPlacement('end-end'), resolveLogicalPlacement('start-end')]
}), dom.shift({
padding: 8
})];
const updatePosition = () => this._applyFloatingPosition(referenceElement, submenu, placement, middleware);
updatePosition();
return dom.autoUpdate(referenceElement, submenu, updatePosition);
}
_scheduleSubmenuClose(submenu, submenuWrapper) {
this._cancelSubmenuCloseTimeout(submenu);
const timeoutId = setTimeout(() => {
this._closeSubmenu(submenu, submenuWrapper);
this._submenuCloseTimeouts.delete(submenu);
}, this._config.submenuDelay);
this._submenuCloseTimeouts.set(submenu, timeoutId);
}
_cancelSubmenuCloseTimeout(submenu) {
const timeoutId = this._submenuCloseTimeouts.get(submenu);
if (timeoutId) {
clearTimeout(timeoutId);
this._submenuCloseTimeouts.delete(submenu);
}
}
_clearAllSubmenuTimeouts() {
for (const timeoutId of this._submenuCloseTimeouts.values()) {
clearTimeout(timeoutId);
}
this._submenuCloseTimeouts.clear();
}
// -------------------------------------------------------------------------
// Hover intent / Safe triangle
// -------------------------------------------------------------------------
_trackMousePosition(event) {
this._hoverIntentData = {
x: event.clientX,
y: event.clientY,
timestamp: Date.now()
};
}
_isMovingTowardSubmenu(event, submenu) {
if (!this._hoverIntentData) {
return false;
}
const submenuRect = submenu.getBoundingClientRect();
const currentPos = {
x: event.clientX,
y: event.clientY
};
const lastPos = {
x: this._hoverIntentData.x,
y: this._hoverIntentData.y
};
// Create a triangle from current position to submenu edges
// The triangle represents the "safe zone" for diagonal movement
const isRtl = index_js.isRTL();
// Determine which edge of the submenu to target based on direction
const targetX = isRtl ? submenuRect.right : submenuRect.left;
const topCorner = {
x: targetX,
y: submenuRect.top
};
const bottomCorner = {
x: targetX,
y: submenuRect.bottom
};
// Check if cursor is moving toward the submenu
// by checking if the current position is within the safe triangle
return this._pointInTriangle(currentPos, lastPos, topCorner, bottomCorner);
}
_pointInTriangle(point, v1, v2, v3) {
// Barycentric coordinate method to check if point is inside triangle
const d1 = triangleSign(point, v1, v2);
const d2 = triangleSign(point, v2, v3);
const d3 = triangleSign(point, v3, v1);
const hasNeg = d1 < 0 || d2 < 0 || d3 < 0;
const hasPos = d1 > 0 || d2 > 0 || d3 > 0;
return !(hasNeg && hasPos);
}
// -------------------------------------------------------------------------
// Keyboard navigation
// -------------------------------------------------------------------------
_selectMenuItem({
key,
target
}) {
const items = SelectorEngine.find(SELECTOR_VISIBLE_ITEMS, this._menu).filter(element => index_js.isVisible(element));
// Get items only from the current menu level (not nested submenus)
// If target is inside a menu, use that menu; otherwise use the main menu
const currentMenu = target.closest(SELECTOR_MENU) || this._menu;
const items = SelectorEngine.find(`:scope > li > ${SELECTOR_VISIBLE_ITEMS}, :scope > ${SELECTOR_VISIBLE_ITEMS}`, currentMenu).filter(element => index_js.isVisible(element));
if (!items.length) {
return;
}
@@ -361,6 +671,89 @@
// allow cycling to get the last item in case key equals ARROW_UP_KEY
index_js.getNextActiveElement(items, target, key === ARROW_DOWN_KEY, !items.includes(target)).focus();
}
_handleSubmenuKeydown(event) {
const {
key,
target
} = event;
const isRtl = index_js.isRTL();
// Determine the "enter submenu" and "exit submenu" keys based on RTL
const enterKey = isRtl ? ARROW_LEFT_KEY : ARROW_RIGHT_KEY;
const exitKey = isRtl ? ARROW_RIGHT_KEY : ARROW_LEFT_KEY;
// Check if target is a submenu trigger
const submenuWrapper = target.closest(SELECTOR_SUBMENU);
const isSubmenuTrigger = submenuWrapper && target.matches(SELECTOR_SUBMENU_TOGGLE);
// Handle Enter/Space on submenu trigger
if ((key === ENTER_KEY || key === SPACE_KEY) && isSubmenuTrigger) {
event.preventDefault();
event.stopPropagation();
const submenu = SelectorEngine.findOne(SELECTOR_MENU, submenuWrapper);
if (submenu) {
this._closeSiblingSubmenus(submenuWrapper);
this._openSubmenu(target, submenu, submenuWrapper);
// Focus first item in submenu
requestAnimationFrame(() => {
const firstItem = SelectorEngine.findOne(SELECTOR_VISIBLE_ITEMS, submenu);
if (firstItem) {
firstItem.focus();
}
});
}
return true;
}
// Handle Right arrow (or Left in RTL) - enter submenu
if (key === enterKey && isSubmenuTrigger) {
event.preventDefault();
event.stopPropagation();
const submenu = SelectorEngine.findOne(SELECTOR_MENU, submenuWrapper);
if (submenu) {
this._closeSiblingSubmenus(submenuWrapper);
this._openSubmenu(target, submenu, submenuWrapper);
// Focus first item in submenu
requestAnimationFrame(() => {
const firstItem = SelectorEngine.findOne(SELECTOR_VISIBLE_ITEMS, submenu);
if (firstItem) {
firstItem.focus();
}
});
}
return true;
}
// Handle Left arrow (or Right in RTL) - exit submenu
if (key === exitKey) {
const currentMenu = target.closest(SELECTOR_MENU);
const parentSubmenuWrapper = currentMenu?.closest(SELECTOR_SUBMENU);
if (parentSubmenuWrapper) {
event.preventDefault();
event.stopPropagation();
const parentTrigger = SelectorEngine.findOne(SELECTOR_SUBMENU_TOGGLE, parentSubmenuWrapper);
this._closeSubmenu(currentMenu, parentSubmenuWrapper);
if (parentTrigger) {
parentTrigger.focus();
}
return true;
}
}
// Handle Home/End keys
if (key === HOME_KEY || key === END_KEY) {
event.preventDefault();
event.stopPropagation();
const currentMenu = target.closest(SELECTOR_MENU);
const items = SelectorEngine.find(`:scope > li > ${SELECTOR_VISIBLE_ITEMS}, :scope > ${SELECTOR_VISIBLE_ITEMS}`, currentMenu).filter(element => index_js.isVisible(element));
if (items.length) {
const targetItem = key === HOME_KEY ? items[0] : items[items.length - 1];
targetItem.focus();
}
return true;
}
return false;
}
static clearMenus(event) {
if (event.button === RIGHT_MOUSE_BUTTON || event.type === 'keyup' && event.key !== TAB_KEY) {
return;
@@ -391,32 +784,62 @@
}
}
static dataApiKeydownHandler(event) {
// If not an UP | DOWN | ESCAPE key => not a dropdown command
// If input/textarea && if key is other than ESCAPE => not a dropdown command
// If not a relevant key => not a dropdown command
const isInput = /input|textarea/i.test(event.target.tagName);
const isEscapeEvent = event.key === ESCAPE_KEY;
const isUpOrDownEvent = [ARROW_UP_KEY, ARROW_DOWN_KEY].includes(event.key);
if (!isUpOrDownEvent && !isEscapeEvent) {
const isLeftOrRightEvent = [ARROW_LEFT_KEY, ARROW_RIGHT_KEY].includes(event.key);
const isHomeOrEndEvent = [HOME_KEY, END_KEY].includes(event.key);
const isEnterOrSpaceEvent = [ENTER_KEY, SPACE_KEY].includes(event.key);
// Allow Enter/Space only on submenu triggers
const isSubmenuTrigger = event.target.matches(SELECTOR_SUBMENU_TOGGLE);
if (!isUpOrDownEvent && !isEscapeEvent && !isLeftOrRightEvent && !isHomeOrEndEvent && !(isEnterOrSpaceEvent && isSubmenuTrigger)) {
return;
}
if (isInput && !isEscapeEvent) {
return;
}
event.preventDefault();
// TODO: v6 revert #37011 & change markup https://getbootstrap.com/docs/5.3/forms/input-group/
const getToggleButton = this.matches(SELECTOR_DATA_TOGGLE) ? this : SelectorEngine.prev(this, SELECTOR_DATA_TOGGLE)[0] || SelectorEngine.next(this, SELECTOR_DATA_TOGGLE)[0] || SelectorEngine.findOne(SELECTOR_DATA_TOGGLE, event.delegateTarget.parentNode);
if (!getToggleButton) {
return;
}
const instance = Dropdown.getOrCreateInstance(getToggleButton);
// Handle submenu navigation first
if ((isLeftOrRightEvent || isHomeOrEndEvent || isEnterOrSpaceEvent && isSubmenuTrigger) && instance._handleSubmenuKeydown(event)) {
return;
}
// Handle Up/Down navigation
if (isUpOrDownEvent) {
event.preventDefault();
event.stopPropagation();
instance.show();
instance._selectMenuItem(event);
return;
}
if (instance._isShown()) {
// else is escape and we check if it is shown
// Handle Escape
if (isEscapeEvent && instance._isShown()) {
event.preventDefault();
event.stopPropagation();
// If in a submenu, close just that submenu
const currentMenu = event.target.closest(SELECTOR_MENU);
const parentSubmenuWrapper = currentMenu?.closest(SELECTOR_SUBMENU);
if (parentSubmenuWrapper && instance._openSubmenus.size > 0) {
const parentTrigger = SelectorEngine.findOne(SELECTOR_SUBMENU_TOGGLE, parentSubmenuWrapper);
instance._closeSubmenu(currentMenu, parentSubmenuWrapper);
if (parentTrigger) {
parentTrigger.focus();
}
return;
}
// Otherwise close the whole dropdown
instance.hide();
getToggleButton.focus();
}
+1 -1
View File
File diff suppressed because one or more lines are too long
+238
View File
@@ -0,0 +1,238 @@
/*!
* Bootstrap otp-input.js v5.3.8 (https://getbootstrap.com/)
* Copyright 2011-2025 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('./base-component.js'), require('./dom/event-handler.js'), require('./dom/selector-engine.js')) :
typeof define === 'function' && define.amd ? define(['./base-component', './dom/event-handler', './dom/selector-engine'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.OtpInput = factory(global.BaseComponent, global.EventHandler, global.SelectorEngine));
})(this, (function (BaseComponent, EventHandler, SelectorEngine) { 'use strict';
/**
* --------------------------------------------------------------------------
* Bootstrap otp-input.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
/**
* Constants
*/
const NAME = 'otpInput';
const DATA_KEY = 'bs.otp-input';
const EVENT_KEY = `.${DATA_KEY}`;
const DATA_API_KEY = '.data-api';
const EVENT_COMPLETE = `complete${EVENT_KEY}`;
const EVENT_INPUT = `input${EVENT_KEY}`;
const SELECTOR_DATA_OTP = '[data-bs-otp]';
const SELECTOR_INPUT = 'input';
const Default = {
length: 6,
mask: false
};
const DefaultType = {
length: 'number',
mask: 'boolean'
};
/**
* Class definition
*/
class OtpInput extends BaseComponent {
constructor(element, config) {
super(element, config);
this._inputs = SelectorEngine.find(SELECTOR_INPUT, this._element);
this._setupInputs();
this._addEventListeners();
}
// Getters
static get Default() {
return Default;
}
static get DefaultType() {
return DefaultType;
}
static get NAME() {
return NAME;
}
// Public
getValue() {
return this._inputs.map(input => input.value).join('');
}
setValue(value) {
const chars = String(value).split('');
for (const [index, input] of this._inputs.entries()) {
input.value = chars[index] || '';
}
this._checkComplete();
}
clear() {
for (const input of this._inputs) {
input.value = '';
}
this._inputs[0]?.focus();
}
focus() {
// Focus first empty input, or last input if all filled
const emptyInput = this._inputs.find(input => !input.value);
if (emptyInput) {
emptyInput.focus();
} else {
this._inputs.at(-1)?.focus();
}
}
// Private
_setupInputs() {
for (const input of this._inputs) {
// Set attributes for proper OTP handling
input.setAttribute('maxlength', '1');
input.setAttribute('inputmode', 'numeric');
input.setAttribute('pattern', '\\d*');
// First input gets autocomplete for browser OTP autofill
if (input === this._inputs[0]) {
input.setAttribute('autocomplete', 'one-time-code');
} else {
input.setAttribute('autocomplete', 'off');
}
// Mask input if configured
if (this._config.mask) {
input.setAttribute('type', 'password');
}
}
}
_addEventListeners() {
for (const [index, input] of this._inputs.entries()) {
EventHandler.on(input, 'input', event => this._handleInput(event, index));
EventHandler.on(input, 'keydown', event => this._handleKeydown(event, index));
EventHandler.on(input, 'paste', event => this._handlePaste(event));
EventHandler.on(input, 'focus', event => this._handleFocus(event));
}
}
_handleInput(event, index) {
const input = event.target;
// Only allow digits
if (!/^\d*$/.test(input.value)) {
input.value = input.value.replace(/\D/g, '');
}
const {
value
} = input;
// Handle multi-character input (some browsers/autofill)
if (value.length > 1) {
// Distribute characters across inputs
const chars = value.split('');
input.value = chars[0] || '';
for (let i = 1; i < chars.length && index + i < this._inputs.length; i++) {
this._inputs[index + i].value = chars[i];
}
// Focus appropriate input
const nextIndex = Math.min(index + chars.length, this._inputs.length - 1);
this._inputs[nextIndex].focus();
} else if (value && index < this._inputs.length - 1) {
// Auto-advance to next input
this._inputs[index + 1].focus();
}
EventHandler.trigger(this._element, EVENT_INPUT, {
value: this.getValue(),
index
});
this._checkComplete();
}
_handleKeydown(event, index) {
const {
key
} = event;
switch (key) {
case 'Backspace':
{
if (!this._inputs[index].value && index > 0) {
// Move to previous input and clear it
event.preventDefault();
this._inputs[index - 1].value = '';
this._inputs[index - 1].focus();
}
break;
}
case 'Delete':
{
// Clear current and shift remaining values left
event.preventDefault();
for (let i = index; i < this._inputs.length - 1; i++) {
this._inputs[i].value = this._inputs[i + 1].value;
}
this._inputs.at(-1).value = '';
break;
}
case 'ArrowLeft':
{
if (index > 0) {
event.preventDefault();
this._inputs[index - 1].focus();
}
break;
}
case 'ArrowRight':
{
if (index < this._inputs.length - 1) {
event.preventDefault();
this._inputs[index + 1].focus();
}
break;
}
// No default
}
}
_handlePaste(event) {
event.preventDefault();
const pastedData = (event.clipboardData || window.clipboardData).getData('text');
const digits = pastedData.replace(/\D/g, '').slice(0, this._inputs.length);
if (digits) {
this.setValue(digits);
// Focus last filled input or last input
const lastIndex = Math.min(digits.length, this._inputs.length) - 1;
this._inputs[lastIndex].focus();
}
}
_handleFocus(event) {
// Select the content on focus for easy replacement
event.target.select();
}
_checkComplete() {
const value = this.getValue();
const isComplete = value.length === this._inputs.length && this._inputs.every(input => input.value !== '');
if (isComplete) {
EventHandler.trigger(this._element, EVENT_COMPLETE, {
value
});
}
}
}
/**
* Data API implementation
*/
EventHandler.on(document, `DOMContentLoaded${EVENT_KEY}${DATA_API_KEY}`, () => {
for (const element of SelectorEngine.find(SELECTOR_DATA_OTP)) {
OtpInput.getOrCreateInstance(element);
}
});
return OtpInput;
}));
//# sourceMappingURL=otp-input.js.map
+1
View File
File diff suppressed because one or more lines are too long
+245
View File
@@ -0,0 +1,245 @@
/*!
* Bootstrap strength.js v5.3.8 (https://getbootstrap.com/)
* Copyright 2011-2025 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('./base-component.js'), require('./dom/event-handler.js'), require('./dom/selector-engine.js')) :
typeof define === 'function' && define.amd ? define(['./base-component', './dom/event-handler', './dom/selector-engine'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Strength = factory(global.BaseComponent, global.EventHandler, global.SelectorEngine));
})(this, (function (BaseComponent, EventHandler, SelectorEngine) { 'use strict';
/**
* --------------------------------------------------------------------------
* Bootstrap strength.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
/**
* Constants
*/
const NAME = 'strength';
const DATA_KEY = 'bs.strength';
const EVENT_KEY = `.${DATA_KEY}`;
const DATA_API_KEY = '.data-api';
const EVENT_STRENGTH_CHANGE = `strengthChange${EVENT_KEY}`;
const SELECTOR_DATA_STRENGTH = '[data-bs-strength]';
const STRENGTH_LEVELS = ['weak', 'fair', 'good', 'strong'];
const Default = {
input: null,
// Selector or element for password input
minLength: 8,
messages: {
weak: 'Weak',
fair: 'Fair',
good: 'Good',
strong: 'Strong'
},
weights: {
minLength: 1,
extraLength: 1,
lowercase: 1,
uppercase: 1,
numbers: 1,
special: 1,
multipleSpecial: 1,
longPassword: 1
},
thresholds: [2, 4, 6],
// weak ≤2, fair ≤4, good ≤6, strong >6
scorer: null // Custom scoring function (password) => number
};
const DefaultType = {
input: '(string|element|null)',
minLength: 'number',
messages: 'object',
weights: 'object',
thresholds: 'array',
scorer: '(function|null)'
};
/**
* Class definition
*/
class Strength extends BaseComponent {
constructor(element, config) {
super(element, config);
this._input = this._getInput();
this._segments = SelectorEngine.find('.strength-segment', this._element);
this._textElement = SelectorEngine.findOne('.strength-text', this._element.parentElement);
this._currentStrength = null;
if (this._input) {
this._addEventListeners();
// Check initial value
this._evaluate();
}
}
// Getters
static get Default() {
return Default;
}
static get DefaultType() {
return DefaultType;
}
static get NAME() {
return NAME;
}
// Public
getStrength() {
return this._currentStrength;
}
evaluate() {
this._evaluate();
}
// Private
_getInput() {
if (this._config.input) {
return typeof this._config.input === 'string' ? SelectorEngine.findOne(this._config.input) : this._config.input;
}
// Look for preceding password input
const parent = this._element.parentElement;
return SelectorEngine.findOne('input[type="password"]', parent);
}
_addEventListeners() {
EventHandler.on(this._input, 'input', () => this._evaluate());
EventHandler.on(this._input, 'change', () => this._evaluate());
}
_evaluate() {
const password = this._input.value;
const score = this._calculateScore(password);
const strength = this._scoreToStrength(score);
if (strength !== this._currentStrength) {
this._currentStrength = strength;
this._updateUI(strength, score);
EventHandler.trigger(this._element, EVENT_STRENGTH_CHANGE, {
strength,
score,
password: password.length > 0 ? '***' : '' // Don't expose actual password
});
}
}
_calculateScore(password) {
if (!password) {
return 0;
}
// Use custom scorer if provided
if (typeof this._config.scorer === 'function') {
return this._config.scorer(password);
}
const {
weights
} = this._config;
let score = 0;
// Length scoring
if (password.length >= this._config.minLength) {
score += weights.minLength;
}
if (password.length >= this._config.minLength + 4) {
score += weights.extraLength;
}
// Character variety
if (/[a-z]/.test(password)) {
score += weights.lowercase;
}
if (/[A-Z]/.test(password)) {
score += weights.uppercase;
}
if (/\d/.test(password)) {
score += weights.numbers;
}
// Special characters
if (/[!@#$%^&*(),.?":{}|<>]/.test(password)) {
score += weights.special;
}
// Extra points for more special chars or length
if (/[!@#$%^&*(),.?":{}|<>].*[!@#$%^&*(),.?":{}|<>]/.test(password)) {
score += weights.multipleSpecial;
}
if (password.length >= 16) {
score += weights.longPassword;
}
return score;
}
_scoreToStrength(score) {
if (score === 0) {
return null;
}
const [weak, fair, good] = this._config.thresholds;
if (score <= weak) {
return 'weak';
}
if (score <= fair) {
return 'fair';
}
if (score <= good) {
return 'good';
}
return 'strong';
}
_updateUI(strength) {
// Update data attribute on element
if (strength) {
this._element.dataset.bsStrength = strength;
} else {
delete this._element.dataset.bsStrength;
}
// Update segmented meter
const strengthIndex = strength ? STRENGTH_LEVELS.indexOf(strength) : -1;
for (const [index, segment] of this._segments.entries()) {
if (index <= strengthIndex) {
segment.classList.add('active');
} else {
segment.classList.remove('active');
}
}
// Update text feedback
if (this._textElement) {
if (strength && this._config.messages[strength]) {
this._textElement.textContent = this._config.messages[strength];
this._textElement.dataset.bsStrength = strength;
// Also set the color via inheriting from parent or using CSS variable
const colorMap = {
weak: 'danger',
fair: 'warning',
good: 'info',
strong: 'success'
};
this._textElement.style.setProperty('--strength-color', `var(--${colorMap[strength]}-text)`);
} else {
this._textElement.textContent = '';
delete this._textElement.dataset.bsStrength;
}
}
}
}
/**
* Data API implementation
*/
EventHandler.on(document, `DOMContentLoaded${EVENT_KEY}${DATA_API_KEY}`, () => {
for (const element of SelectorEngine.find(SELECTOR_DATA_STRENGTH)) {
Strength.getOrCreateInstance(element);
}
});
return Strength;
}));
//# sourceMappingURL=strength.js.map
+1
View File
File diff suppressed because one or more lines are too long
+98
View File
@@ -0,0 +1,98 @@
/*!
* Bootstrap toggler.js v5.3.8 (https://getbootstrap.com/)
* Copyright 2011-2025 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('./base-component.js'), require('./dom/event-handler.js'), require('./util/component-functions.js')) :
typeof define === 'function' && define.amd ? define(['./base-component', './dom/event-handler', './util/component-functions'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Toggler = factory(global.BaseComponent, global.EventHandler, global.ComponentFunctions));
})(this, (function (BaseComponent, EventHandler, componentFunctions_js) { 'use strict';
/**
* --------------------------------------------------------------------------
* Bootstrap toggler.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
/**
* Constants
*/
const NAME = 'toggler';
const DATA_KEY = 'bs.toggler';
const EVENT_KEY = `.${DATA_KEY}`;
const EVENT_TOGGLE = `toggle${EVENT_KEY}`;
const EVENT_TOGGLED = `toggled${EVENT_KEY}`;
const EVENT_CLICK = 'click';
const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="toggler"]';
const DefaultType = {
attribute: 'string',
value: '(string|number|boolean)'
};
const Default = {
attribute: 'class',
value: null
};
/**
* Class definition
*/
class Toggler extends BaseComponent {
// Getters
static get Default() {
return Default;
}
static get DefaultType() {
return DefaultType;
}
static get NAME() {
return NAME;
}
// Public
toggle() {
const toggleEvent = EventHandler.trigger(this._element, EVENT_TOGGLE);
if (toggleEvent.defaultPrevented) {
return;
}
this._execute();
EventHandler.trigger(this._element, EVENT_TOGGLED);
}
// Private
_execute() {
const {
attribute,
value
} = this._config;
if (attribute === 'id') {
return; // You have to be kidding
}
if (attribute === 'class') {
this._element.classList.toggle(value);
return;
}
// Compare as strings since getAttribute() always returns a string
if (this._element.getAttribute(attribute) === String(value)) {
this._element.removeAttribute(attribute);
return;
}
this._element.setAttribute(attribute, value);
}
}
/**
* Data API implementation
*/
componentFunctions_js.eventActionOnPlugin(Toggler, EVENT_CLICK, SELECTOR_DATA_TOGGLE, 'toggle');
return Toggler;
}));
//# sourceMappingURL=toggler.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"toggler.js","sources":["../src/toggler.js"],"sourcesContent":["/**\n * --------------------------------------------------------------------------\n * Bootstrap toggler.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport BaseComponent from './base-component.js'\nimport EventHandler from './dom/event-handler.js'\nimport { eventActionOnPlugin } from './util/component-functions.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'toggler'\nconst DATA_KEY = 'bs.toggler'\nconst EVENT_KEY = `.${DATA_KEY}`\n\nconst EVENT_TOGGLE = `toggle${EVENT_KEY}`\nconst EVENT_TOGGLED = `toggled${EVENT_KEY}`\nconst EVENT_CLICK = 'click'\n\nconst SELECTOR_DATA_TOGGLE = '[data-bs-toggle=\"toggler\"]'\n\nconst DefaultType = {\n attribute: 'string',\n value: '(string|number|boolean)'\n}\n\nconst Default = {\n attribute: 'class',\n value: null\n}\n\n/**\n * Class definition\n */\n\nclass Toggler extends BaseComponent {\n // Getters\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n static get NAME() {\n return NAME\n }\n\n // Public\n toggle() {\n const toggleEvent = EventHandler.trigger(this._element, EVENT_TOGGLE)\n\n if (toggleEvent.defaultPrevented) {\n return\n }\n\n this._execute()\n\n EventHandler.trigger(this._element, EVENT_TOGGLED)\n }\n\n // Private\n _execute() {\n const { attribute, value } = this._config\n\n if (attribute === 'id') {\n return // You have to be kidding\n }\n\n if (attribute === 'class') {\n this._element.classList.toggle(value)\n return\n }\n\n // Compare as strings since getAttribute() always returns a string\n if (this._element.getAttribute(attribute) === String(value)) {\n this._element.removeAttribute(attribute)\n return\n }\n\n this._element.setAttribute(attribute, value)\n }\n}\n\n/**\n * Data API implementation\n */\n\neventActionOnPlugin(Toggler, EVENT_CLICK, SELECTOR_DATA_TOGGLE, 'toggle')\n\nexport default Toggler\n"],"names":["NAME","DATA_KEY","EVENT_KEY","EVENT_TOGGLE","EVENT_TOGGLED","EVENT_CLICK","SELECTOR_DATA_TOGGLE","DefaultType","attribute","value","Default","Toggler","BaseComponent","toggle","toggleEvent","EventHandler","trigger","_element","defaultPrevented","_execute","_config","classList","getAttribute","String","removeAttribute","setAttribute","eventActionOnPlugin"],"mappings":";;;;;;;;;;;EAAA;EACA;EACA;EACA;EACA;EACA;;;EAMA;EACA;EACA;;EAEA,MAAMA,IAAI,GAAG,SAAS;EACtB,MAAMC,QAAQ,GAAG,YAAY;EAC7B,MAAMC,SAAS,GAAG,CAAA,CAAA,EAAID,QAAQ,CAAA,CAAE;EAEhC,MAAME,YAAY,GAAG,CAAA,MAAA,EAASD,SAAS,CAAA,CAAE;EACzC,MAAME,aAAa,GAAG,CAAA,OAAA,EAAUF,SAAS,CAAA,CAAE;EAC3C,MAAMG,WAAW,GAAG,OAAO;EAE3B,MAAMC,oBAAoB,GAAG,4BAA4B;EAEzD,MAAMC,WAAW,GAAG;EAClBC,EAAAA,SAAS,EAAE,QAAQ;EACnBC,EAAAA,KAAK,EAAE;EACT,CAAC;EAED,MAAMC,OAAO,GAAG;EACdF,EAAAA,SAAS,EAAE,OAAO;EAClBC,EAAAA,KAAK,EAAE;EACT,CAAC;;EAED;EACA;EACA;;EAEA,MAAME,OAAO,SAASC,aAAa,CAAC;EAClC;IACA,WAAWF,OAAOA,GAAG;EACnB,IAAA,OAAOA,OAAO;EAChB,EAAA;IAEA,WAAWH,WAAWA,GAAG;EACvB,IAAA,OAAOA,WAAW;EACpB,EAAA;IAEA,WAAWP,IAAIA,GAAG;EAChB,IAAA,OAAOA,IAAI;EACb,EAAA;;EAEA;EACAa,EAAAA,MAAMA,GAAG;MACP,MAAMC,WAAW,GAAGC,YAAY,CAACC,OAAO,CAAC,IAAI,CAACC,QAAQ,EAAEd,YAAY,CAAC;MAErE,IAAIW,WAAW,CAACI,gBAAgB,EAAE;EAChC,MAAA;EACF,IAAA;MAEA,IAAI,CAACC,QAAQ,EAAE;MAEfJ,YAAY,CAACC,OAAO,CAAC,IAAI,CAACC,QAAQ,EAAEb,aAAa,CAAC;EACpD,EAAA;;EAEA;EACAe,EAAAA,QAAQA,GAAG;MACT,MAAM;QAAEX,SAAS;EAAEC,MAAAA;OAAO,GAAG,IAAI,CAACW,OAAO;MAEzC,IAAIZ,SAAS,KAAK,IAAI,EAAE;EACtB,MAAA,OAAM;EACR,IAAA;MAEA,IAAIA,SAAS,KAAK,OAAO,EAAE;QACzB,IAAI,CAACS,QAAQ,CAACI,SAAS,CAACR,MAAM,CAACJ,KAAK,CAAC;EACrC,MAAA;EACF,IAAA;;EAEA;EACA,IAAA,IAAI,IAAI,CAACQ,QAAQ,CAACK,YAAY,CAACd,SAAS,CAAC,KAAKe,MAAM,CAACd,KAAK,CAAC,EAAE;EAC3D,MAAA,IAAI,CAACQ,QAAQ,CAACO,eAAe,CAAChB,SAAS,CAAC;EACxC,MAAA;EACF,IAAA;MAEA,IAAI,CAACS,QAAQ,CAACQ,YAAY,CAACjB,SAAS,EAAEC,KAAK,CAAC;EAC9C,EAAA;EACF;;EAEA;EACA;EACA;;AAEAiB,2CAAmB,CAACf,OAAO,EAAEN,WAAW,EAAEC,oBAAoB,EAAE,QAAQ,CAAC;;;;;;;;"}
+29
View File
@@ -33,8 +33,37 @@
instance[method]();
});
};
const eventActionOnPlugin = (Plugin, onEvent, stringSelector, method, callback = null) => {
eventAction(`${onEvent}.${Plugin.NAME}`, stringSelector, data => {
const instances = data.targets.filter(Boolean).map(element => Plugin.getOrCreateInstance(element));
if (typeof callback === 'function') {
callback({
...data,
instances
});
}
for (const instance of instances) {
instance[method]();
}
});
};
const eventAction = (onEvent, stringSelector, callback) => {
const selector = `${stringSelector}:not(.disabled):not(:disabled)`;
EventHandler.on(document, onEvent, selector, function (event) {
if (['A', 'AREA'].includes(this.tagName)) {
event.preventDefault();
}
const selector = SelectorEngine.getSelectorFromElement(this);
const targets = selector ? SelectorEngine.find(selector) : [this];
callback({
targets,
event
});
});
};
exports.enableDismissTrigger = enableDismissTrigger;
exports.eventActionOnPlugin = eventActionOnPlugin;
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"component-functions.js","sources":["../../src/util/component-functions.js"],"sourcesContent":["/**\n * --------------------------------------------------------------------------\n * Bootstrap util/component-functions.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport EventHandler from '../dom/event-handler.js'\nimport SelectorEngine from '../dom/selector-engine.js'\nimport { isDisabled } from './index.js'\n\nconst enableDismissTrigger = (component, method = 'hide') => {\n const clickEvent = `click.dismiss${component.EVENT_KEY}`\n const name = component.NAME\n\n EventHandler.on(document, clickEvent, `[data-bs-dismiss=\"${name}\"]`, function (event) {\n if (['A', 'AREA'].includes(this.tagName)) {\n event.preventDefault()\n }\n\n if (isDisabled(this)) {\n return\n }\n\n const target = SelectorEngine.getElementFromSelector(this) || this.closest(`.${name}`)\n const instance = component.getOrCreateInstance(target)\n\n // Method argument is left, for Alert and only, as it doesn't implement the 'hide' method\n instance[method]()\n })\n}\n\nexport {\n enableDismissTrigger\n}\n"],"names":["enableDismissTrigger","component","method","clickEvent","EVENT_KEY","name","NAME","EventHandler","on","document","event","includes","tagName","preventDefault","isDisabled","target","SelectorEngine","getElementFromSelector","closest","instance","getOrCreateInstance"],"mappings":";;;;;;;;;;;EAAA;EACA;EACA;EACA;EACA;EACA;;AAMA,QAAMA,oBAAoB,GAAGA,CAACC,SAAS,EAAEC,MAAM,GAAG,MAAM,KAAK;EAC3D,EAAA,MAAMC,UAAU,GAAG,CAAA,aAAA,EAAgBF,SAAS,CAACG,SAAS,CAAA,CAAE;EACxD,EAAA,MAAMC,IAAI,GAAGJ,SAAS,CAACK,IAAI;EAE3BC,EAAAA,YAAY,CAACC,EAAE,CAACC,QAAQ,EAAEN,UAAU,EAAE,CAAA,kBAAA,EAAqBE,IAAI,CAAA,EAAA,CAAI,EAAE,UAAUK,KAAK,EAAE;EACpF,IAAA,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAACC,QAAQ,CAAC,IAAI,CAACC,OAAO,CAAC,EAAE;QACxCF,KAAK,CAACG,cAAc,EAAE;EACxB,IAAA;EAEA,IAAA,IAAIC,mBAAU,CAAC,IAAI,CAAC,EAAE;EACpB,MAAA;EACF,IAAA;EAEA,IAAA,MAAMC,MAAM,GAAGC,cAAc,CAACC,sBAAsB,CAAC,IAAI,CAAC,IAAI,IAAI,CAACC,OAAO,CAAC,CAAA,CAAA,EAAIb,IAAI,EAAE,CAAC;EACtF,IAAA,MAAMc,QAAQ,GAAGlB,SAAS,CAACmB,mBAAmB,CAACL,MAAM,CAAC;;EAEtD;EACAI,IAAAA,QAAQ,CAACjB,MAAM,CAAC,EAAE;EACpB,EAAA,CAAC,CAAC;EACJ;;;;;;;;;;"}
{"version":3,"file":"component-functions.js","sources":["../../src/util/component-functions.js"],"sourcesContent":["/**\n * --------------------------------------------------------------------------\n * Bootstrap util/component-functions.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport EventHandler from '../dom/event-handler.js'\nimport SelectorEngine from '../dom/selector-engine.js'\nimport { isDisabled } from './index.js'\n\nconst enableDismissTrigger = (component, method = 'hide') => {\n const clickEvent = `click.dismiss${component.EVENT_KEY}`\n const name = component.NAME\n\n EventHandler.on(document, clickEvent, `[data-bs-dismiss=\"${name}\"]`, function (event) {\n if (['A', 'AREA'].includes(this.tagName)) {\n event.preventDefault()\n }\n\n if (isDisabled(this)) {\n return\n }\n\n const target = SelectorEngine.getElementFromSelector(this) || this.closest(`.${name}`)\n const instance = component.getOrCreateInstance(target)\n\n // Method argument is left, for Alert and only, as it doesn't implement the 'hide' method\n instance[method]()\n })\n}\n\nconst eventActionOnPlugin = (Plugin, onEvent, stringSelector, method, callback = null) => {\n eventAction(`${onEvent}.${Plugin.NAME}`, stringSelector, data => {\n const instances = data.targets.filter(Boolean).map(element => Plugin.getOrCreateInstance(element))\n if (typeof callback === 'function') {\n callback({ ...data, instances })\n }\n\n for (const instance of instances) {\n instance[method]()\n }\n })\n}\n\nconst eventAction = (onEvent, stringSelector, callback) => {\n const selector = `${stringSelector}:not(.disabled):not(:disabled)`\n EventHandler.on(document, onEvent, selector, function (event) {\n if (['A', 'AREA'].includes(this.tagName)) {\n event.preventDefault()\n }\n\n const selector = SelectorEngine.getSelectorFromElement(this)\n const targets = selector ? SelectorEngine.find(selector) : [this]\n\n callback({ targets, event })\n })\n}\n\nexport {\n enableDismissTrigger,\n eventActionOnPlugin\n}\n"],"names":["enableDismissTrigger","component","method","clickEvent","EVENT_KEY","name","NAME","EventHandler","on","document","event","includes","tagName","preventDefault","isDisabled","target","SelectorEngine","getElementFromSelector","closest","instance","getOrCreateInstance","eventActionOnPlugin","Plugin","onEvent","stringSelector","callback","eventAction","data","instances","targets","filter","Boolean","map","element","selector","getSelectorFromElement","find"],"mappings":";;;;;;;;;;;EAAA;EACA;EACA;EACA;EACA;EACA;;AAMA,QAAMA,oBAAoB,GAAGA,CAACC,SAAS,EAAEC,MAAM,GAAG,MAAM,KAAK;EAC3D,EAAA,MAAMC,UAAU,GAAG,CAAA,aAAA,EAAgBF,SAAS,CAACG,SAAS,CAAA,CAAE;EACxD,EAAA,MAAMC,IAAI,GAAGJ,SAAS,CAACK,IAAI;EAE3BC,EAAAA,YAAY,CAACC,EAAE,CAACC,QAAQ,EAAEN,UAAU,EAAE,CAAA,kBAAA,EAAqBE,IAAI,CAAA,EAAA,CAAI,EAAE,UAAUK,KAAK,EAAE;EACpF,IAAA,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAACC,QAAQ,CAAC,IAAI,CAACC,OAAO,CAAC,EAAE;QACxCF,KAAK,CAACG,cAAc,EAAE;EACxB,IAAA;EAEA,IAAA,IAAIC,mBAAU,CAAC,IAAI,CAAC,EAAE;EACpB,MAAA;EACF,IAAA;EAEA,IAAA,MAAMC,MAAM,GAAGC,cAAc,CAACC,sBAAsB,CAAC,IAAI,CAAC,IAAI,IAAI,CAACC,OAAO,CAAC,CAAA,CAAA,EAAIb,IAAI,EAAE,CAAC;EACtF,IAAA,MAAMc,QAAQ,GAAGlB,SAAS,CAACmB,mBAAmB,CAACL,MAAM,CAAC;;EAEtD;EACAI,IAAAA,QAAQ,CAACjB,MAAM,CAAC,EAAE;EACpB,EAAA,CAAC,CAAC;EACJ;AAEA,QAAMmB,mBAAmB,GAAGA,CAACC,MAAM,EAAEC,OAAO,EAAEC,cAAc,EAAEtB,MAAM,EAAEuB,QAAQ,GAAG,IAAI,KAAK;EACxFC,EAAAA,WAAW,CAAC,CAAA,EAAGH,OAAO,CAAA,CAAA,EAAID,MAAM,CAAChB,IAAI,CAAA,CAAE,EAAEkB,cAAc,EAAEG,IAAI,IAAI;MAC/D,MAAMC,SAAS,GAAGD,IAAI,CAACE,OAAO,CAACC,MAAM,CAACC,OAAO,CAAC,CAACC,GAAG,CAACC,OAAO,IAAIX,MAAM,CAACF,mBAAmB,CAACa,OAAO,CAAC,CAAC;EAClG,IAAA,IAAI,OAAOR,QAAQ,KAAK,UAAU,EAAE;EAClCA,MAAAA,QAAQ,CAAC;EAAE,QAAA,GAAGE,IAAI;EAAEC,QAAAA;EAAU,OAAC,CAAC;EAClC,IAAA;EAEA,IAAA,KAAK,MAAMT,QAAQ,IAAIS,SAAS,EAAE;EAChCT,MAAAA,QAAQ,CAACjB,MAAM,CAAC,EAAE;EACpB,IAAA;EACF,EAAA,CAAC,CAAC;EACJ;EAEA,MAAMwB,WAAW,GAAGA,CAACH,OAAO,EAAEC,cAAc,EAAEC,QAAQ,KAAK;EACzD,EAAA,MAAMS,QAAQ,GAAG,CAAA,EAAGV,cAAc,CAAA,8BAAA,CAAgC;IAClEjB,YAAY,CAACC,EAAE,CAACC,QAAQ,EAAEc,OAAO,EAAEW,QAAQ,EAAE,UAAUxB,KAAK,EAAE;EAC5D,IAAA,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAACC,QAAQ,CAAC,IAAI,CAACC,OAAO,CAAC,EAAE;QACxCF,KAAK,CAACG,cAAc,EAAE;EACxB,IAAA;EAEA,IAAA,MAAMqB,QAAQ,GAAGlB,cAAc,CAACmB,sBAAsB,CAAC,IAAI,CAAC;EAC5D,IAAA,MAAMN,OAAO,GAAGK,QAAQ,GAAGlB,cAAc,CAACoB,IAAI,CAACF,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;EAEjET,IAAAA,QAAQ,CAAC;QAAEI,OAAO;EAAEnB,MAAAA;EAAM,KAAC,CAAC;EAC9B,EAAA,CAAC,CAAC;EACJ,CAAC;;;;;;;;;;;"}