@dodlhuat/basix 1.2.5 → 1.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/css/push-menu.scss +1 -0
- package/css/style.css +66 -38
- package/css/style.css.map +1 -1
- package/css/style.min.css +1 -1
- package/css/style.min.css.map +1 -0
- package/css/virtual-dropdown.scss +107 -45
- package/js/datepicker.js +3 -1
- package/js/datepicker.ts +3 -1
- package/js/lightbox.js +7 -5
- package/js/lightbox.ts +7 -5
- package/js/modal.js +3 -1
- package/js/modal.ts +3 -1
- package/js/tabs.js +2 -2
- package/js/tabs.ts +2 -2
- package/js/tooltip.js +1 -1
- package/js/tooltip.ts +1 -2
- package/js/virtual-dropdown.js +31 -4
- package/js/virtual-dropdown.ts +39 -5
- package/package.json +1 -1
package/js/virtual-dropdown.ts
CHANGED
|
@@ -25,6 +25,9 @@ class VirtualDropdown {
|
|
|
25
25
|
private readonly renderLimit: number;
|
|
26
26
|
private readonly itemHeight: number;
|
|
27
27
|
private readonly onSelect: ((selectedValues: Array<string | number>) => void) | null;
|
|
28
|
+
// Unique CSS anchor name for this instance — prevents conflicts when
|
|
29
|
+
// multiple dropdowns exist on the same page.
|
|
30
|
+
private readonly anchorName: string;
|
|
28
31
|
|
|
29
32
|
private trigger!: HTMLElement;
|
|
30
33
|
private triggerText!: HTMLElement;
|
|
@@ -59,6 +62,7 @@ class VirtualDropdown {
|
|
|
59
62
|
this.renderLimit = config.renderLimit || 20;
|
|
60
63
|
this.itemHeight = config.itemHeight || 40;
|
|
61
64
|
this.onSelect = config.onSelect ?? null;
|
|
65
|
+
this.anchorName = `--vd-${Math.random().toString(36).slice(2, 9)}`;
|
|
62
66
|
|
|
63
67
|
this.selectedValues = new Set();
|
|
64
68
|
this.filteredOptions = [...this.options];
|
|
@@ -82,7 +86,7 @@ class VirtualDropdown {
|
|
|
82
86
|
<span class="trigger-text">${escapeHtml(this.placeholder)}</span>
|
|
83
87
|
<span class="trigger-arrow" aria-hidden="true">▼</span>
|
|
84
88
|
</div>
|
|
85
|
-
<div class="dropdown-menu" role="listbox">
|
|
89
|
+
<div class="dropdown-menu" popover="manual" role="listbox">
|
|
86
90
|
${this.searchable ? '<div class="dropdown-search"><input type="text" placeholder="Search..." aria-label="Search options"></div>' : ''}
|
|
87
91
|
<div class="dropdown-list-wrapper">
|
|
88
92
|
<div class="dropdown-list-scroller">
|
|
@@ -101,6 +105,11 @@ class VirtualDropdown {
|
|
|
101
105
|
this.spacer = this.querySelector('.virtual-spacer');
|
|
102
106
|
this.content = this.querySelector('.virtual-content');
|
|
103
107
|
|
|
108
|
+
// Wire up anchor positioning: each instance gets a unique anchor name
|
|
109
|
+
// so multiple dropdowns on the same page don't interfere.
|
|
110
|
+
this.trigger.style.setProperty('anchor-name', this.anchorName);
|
|
111
|
+
this.menu.style.setProperty('position-anchor', this.anchorName);
|
|
112
|
+
|
|
104
113
|
if (this.searchable) {
|
|
105
114
|
this.searchInput = this.querySelector('.dropdown-search input');
|
|
106
115
|
}
|
|
@@ -130,8 +139,10 @@ class VirtualDropdown {
|
|
|
130
139
|
this.trigger.addEventListener('keydown', handleTriggerKeydown as EventListener);
|
|
131
140
|
this.boundHandlers.set('triggerKeydown', handleTriggerKeydown as EventListener);
|
|
132
141
|
|
|
142
|
+
// Close when clicking outside. Still needed because popover="manual"
|
|
143
|
+
// does not auto-dismiss on outside clicks.
|
|
133
144
|
const handleDocumentClick = (e: MouseEvent): void => {
|
|
134
|
-
if (!this.container.contains(e.target as Node)) {
|
|
145
|
+
if (!this.container.contains(e.target as Node) && !this.menu.contains(e.target as Node)) {
|
|
135
146
|
this.close();
|
|
136
147
|
}
|
|
137
148
|
};
|
|
@@ -154,6 +165,20 @@ class VirtualDropdown {
|
|
|
154
165
|
};
|
|
155
166
|
this.listWrapper.addEventListener('scroll', handleScroll);
|
|
156
167
|
this.boundHandlers.set('scroll', handleScroll);
|
|
168
|
+
|
|
169
|
+
// Sync isOpen if the browser closes the popover externally (e.g. another
|
|
170
|
+
// popover="auto" element stealing focus — not typical for "manual" but
|
|
171
|
+
// good defensive practice).
|
|
172
|
+
const handlePopoverToggle = (e: Event): void => {
|
|
173
|
+
const te = e as ToggleEvent;
|
|
174
|
+
if (te.newState === 'closed' && this.isOpen) {
|
|
175
|
+
this.isOpen = false;
|
|
176
|
+
this.container.classList.remove('open');
|
|
177
|
+
this.trigger.setAttribute('aria-expanded', 'false');
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
this.menu.addEventListener('toggle', handlePopoverToggle);
|
|
181
|
+
this.boundHandlers.set('popoverToggle', handlePopoverToggle);
|
|
157
182
|
}
|
|
158
183
|
|
|
159
184
|
private toggle(): void {
|
|
@@ -163,7 +188,7 @@ class VirtualDropdown {
|
|
|
163
188
|
private open(): void {
|
|
164
189
|
this.isOpen = true;
|
|
165
190
|
this.container.classList.add('open');
|
|
166
|
-
this.menu.
|
|
191
|
+
this.menu.showPopover();
|
|
167
192
|
this.trigger.setAttribute('aria-expanded', 'true');
|
|
168
193
|
this.renderList();
|
|
169
194
|
|
|
@@ -175,7 +200,7 @@ class VirtualDropdown {
|
|
|
175
200
|
private close(): void {
|
|
176
201
|
this.isOpen = false;
|
|
177
202
|
this.container.classList.remove('open');
|
|
178
|
-
this.menu.
|
|
203
|
+
this.menu.hidePopover();
|
|
179
204
|
this.trigger.setAttribute('aria-expanded', 'false');
|
|
180
205
|
}
|
|
181
206
|
|
|
@@ -327,6 +352,10 @@ class VirtualDropdown {
|
|
|
327
352
|
}
|
|
328
353
|
|
|
329
354
|
public destroy(): void {
|
|
355
|
+
if (this.isOpen) {
|
|
356
|
+
this.menu.hidePopover();
|
|
357
|
+
}
|
|
358
|
+
|
|
330
359
|
const triggerClick = this.boundHandlers.get('triggerClick');
|
|
331
360
|
if (triggerClick) {
|
|
332
361
|
this.trigger.removeEventListener('click', triggerClick);
|
|
@@ -352,6 +381,11 @@ class VirtualDropdown {
|
|
|
352
381
|
this.listWrapper.removeEventListener('scroll', scroll);
|
|
353
382
|
}
|
|
354
383
|
|
|
384
|
+
const popoverToggle = this.boundHandlers.get('popoverToggle');
|
|
385
|
+
if (popoverToggle) {
|
|
386
|
+
this.menu.removeEventListener('toggle', popoverToggle);
|
|
387
|
+
}
|
|
388
|
+
|
|
355
389
|
this.boundHandlers.clear();
|
|
356
390
|
|
|
357
391
|
this.container.innerHTML = '';
|
|
@@ -359,4 +393,4 @@ class VirtualDropdown {
|
|
|
359
393
|
}
|
|
360
394
|
}
|
|
361
395
|
|
|
362
|
-
export { VirtualDropdown, DropdownOption, VirtualDropdownConfig };
|
|
396
|
+
export { VirtualDropdown, DropdownOption, VirtualDropdownConfig };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dodlhuat/basix",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.7",
|
|
4
4
|
"description": "Basix is intended as a starter for the rapid development of a design. Each design element can be added individually to include only the data required. It is using plain javascript / typescript and therefore is not dependent on any plugin.",
|
|
5
5
|
"exports": {
|
|
6
6
|
"./css/*": "./css/*",
|