gd-bs 6.7.5 → 6.7.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/build/bs.js +1 -1
- package/build/components/dropdown/formItem.js +4 -0
- package/build/components/dropdown/index.js +75 -0
- package/build/components/dropdown/item.js +4 -0
- package/build/components/floating-ui/index.js +45 -42
- package/dist/gd-bs-icons.js +1 -1
- package/dist/gd-bs-icons.min.js +1 -1
- package/dist/gd-bs.d.ts +5 -0
- package/dist/gd-bs.js +1 -1
- package/dist/gd-bs.min.js +1 -1
- package/indexv2.html +2 -2
- package/package.json +1 -1
- package/src/components/dropdown/formItem.ts +6 -0
- package/src/components/dropdown/index.ts +84 -0
- package/src/components/dropdown/item.ts +6 -0
- package/src/components/dropdown/types.d.ts +1 -0
- package/src/components/floating-ui/index.ts +59 -49
- package/src/components/floating-ui/types.d.ts +4 -0
- package/src/styles/_floating-ui.scss +137 -33
package/indexv2.html
CHANGED
|
@@ -177,7 +177,7 @@
|
|
|
177
177
|
|
|
178
178
|
<h5>Dropdown</h5>
|
|
179
179
|
|
|
180
|
-
<bs-dropdown auto-select="true" is-split="false" label="My Dropdown:" on-change="MyLib.ddlChange">
|
|
180
|
+
<bs-dropdown auto-select="true" is-split="false" label="My Dropdown:" search="true" on-change="MyLib.ddlChange">
|
|
181
181
|
<item is-header="true">Header 1</item>
|
|
182
182
|
<item is-divider="true"></item>
|
|
183
183
|
<item value="1">Item 1</item>
|
|
@@ -545,7 +545,7 @@
|
|
|
545
545
|
cardRender: (el) => { console.log("Card Render: ", el); },
|
|
546
546
|
cardBodyRender: (el) => { console.log("Card Body Render: ", el); },
|
|
547
547
|
collapseInit: obj => { window["collapseDemo"] = obj; },
|
|
548
|
-
ddlChange: (item) => { alert("Selected Item: " + (item ? item.text : "No Selection")); },
|
|
548
|
+
ddlChange: (item) => { debugger; alert("Selected Item: " + (item ? item.text : "No Selection")); },
|
|
549
549
|
fileClicked: (btn) => { alert(btn.text + " clicked."); },
|
|
550
550
|
formCustomControl: (ctrl) => { ctrl.el.innerHTML = "<h3>Custom Control</h3>"; },
|
|
551
551
|
inputGrouponChange: (val) => { console.log("Value changed to: " + val); },
|
package/package.json
CHANGED
|
@@ -87,6 +87,9 @@ export class DropdownFormItem {
|
|
|
87
87
|
// The component HTML element
|
|
88
88
|
get el(): HTMLElement { return this._el; }
|
|
89
89
|
|
|
90
|
+
// Hides the item
|
|
91
|
+
hide() { this._el.classList.add("d-none"); }
|
|
92
|
+
|
|
90
93
|
// Returns true if the item is selected
|
|
91
94
|
get isSelected(): boolean { return this._isSelected; }
|
|
92
95
|
set isSelected(value: boolean) { this._isSelected = value; }
|
|
@@ -94,6 +97,9 @@ export class DropdownFormItem {
|
|
|
94
97
|
// The component properties
|
|
95
98
|
get props(): IDropdownItem { return this._props; }
|
|
96
99
|
|
|
100
|
+
// Shows the item
|
|
101
|
+
show() { this._el.classList.remove("d-none"); }
|
|
102
|
+
|
|
97
103
|
// Toggles the item selection
|
|
98
104
|
toggle() {
|
|
99
105
|
// Skip the dividers, headers
|
|
@@ -38,6 +38,7 @@ class _Dropdown extends Base<IDropdownProps> implements IDropdown {
|
|
|
38
38
|
private _autoSelect: boolean = null;
|
|
39
39
|
private _cb: ICheckboxGroup = null;
|
|
40
40
|
private _elMenu: HTMLElement;
|
|
41
|
+
private _elSearch: HTMLInputElement;
|
|
41
42
|
private _floatingUI: IFloatingUI = null;
|
|
42
43
|
private _initFl: boolean = false;
|
|
43
44
|
private _items: Array<DropdownFormItem | DropdownItem> = null;
|
|
@@ -52,6 +53,9 @@ class _Dropdown extends Base<IDropdownProps> implements IDropdown {
|
|
|
52
53
|
// Configure the events
|
|
53
54
|
this.configureEvents();
|
|
54
55
|
|
|
56
|
+
// Configure search
|
|
57
|
+
this.configureSearch();
|
|
58
|
+
|
|
55
59
|
// Configure the parent
|
|
56
60
|
this.configureParent();
|
|
57
61
|
|
|
@@ -258,6 +262,16 @@ class _Dropdown extends Base<IDropdownProps> implements IDropdown {
|
|
|
258
262
|
elTarget: toggle,
|
|
259
263
|
placement: typeof (this.props.placement) === "number" ? this.props.placement : FloatingUIPlacements.BottomStart,
|
|
260
264
|
theme: popoverType,
|
|
265
|
+
onShow: () => {
|
|
266
|
+
// See if the search element exists
|
|
267
|
+
if (this._elSearch) {
|
|
268
|
+
// Clear the search
|
|
269
|
+
this._elSearch.value = "";
|
|
270
|
+
|
|
271
|
+
// Show all the items
|
|
272
|
+
for (let i = 0; i < this._items.length; i++) { this._items[i].show(); }
|
|
273
|
+
}
|
|
274
|
+
},
|
|
261
275
|
options: {
|
|
262
276
|
arrow: false,
|
|
263
277
|
flip: true,
|
|
@@ -396,6 +410,73 @@ class _Dropdown extends Base<IDropdownProps> implements IDropdown {
|
|
|
396
410
|
}
|
|
397
411
|
}
|
|
398
412
|
|
|
413
|
+
// Configures the search option for the dropdown
|
|
414
|
+
private configureSearch() {
|
|
415
|
+
// See if search is enabled and the menu exists
|
|
416
|
+
if (this.props.search != true || this._elMenu == null) { return; }
|
|
417
|
+
|
|
418
|
+
// Create the search textbox
|
|
419
|
+
this._elSearch = document.createElement("input");
|
|
420
|
+
this._elSearch.classList.add("form-control");
|
|
421
|
+
this._elSearch.type = "search";
|
|
422
|
+
this._elSearch.placeholder = "Search for item...";
|
|
423
|
+
|
|
424
|
+
// Insert the item as the first element
|
|
425
|
+
this._elMenu.firstChild ? this._elMenu.insertBefore(this._elSearch, this._elMenu.firstChild) : this._elMenu.appendChild(this._elSearch);
|
|
426
|
+
|
|
427
|
+
// Create the empty text
|
|
428
|
+
let elEmptyText = document.createElement("h6")
|
|
429
|
+
elEmptyText.classList.add("dropdown-header");
|
|
430
|
+
elEmptyText.classList.add("d-none");
|
|
431
|
+
elEmptyText.innerHTML = "No items were found...";
|
|
432
|
+
this._elMenu.appendChild(elEmptyText);
|
|
433
|
+
|
|
434
|
+
// Add the element to the ignore list
|
|
435
|
+
this._floatingUI.addIgnoreElement(this._elSearch);
|
|
436
|
+
|
|
437
|
+
// Add the event
|
|
438
|
+
this._elSearch.addEventListener("input", () => {
|
|
439
|
+
// Get the value
|
|
440
|
+
let searchText = (this._elSearch.value || "").toLocaleLowerCase();
|
|
441
|
+
|
|
442
|
+
// Set the flags
|
|
443
|
+
let itemsFound = false;
|
|
444
|
+
let showAll = searchText == "";
|
|
445
|
+
|
|
446
|
+
// Hide the empty text
|
|
447
|
+
elEmptyText.classList.add("d-none");
|
|
448
|
+
|
|
449
|
+
// Parse the items
|
|
450
|
+
for (let i = 0; i < this._items.length; i++) {
|
|
451
|
+
let item = this._items[i];
|
|
452
|
+
|
|
453
|
+
// See if we are showing all the items
|
|
454
|
+
if (showAll) {
|
|
455
|
+
// Show the item
|
|
456
|
+
item.show();
|
|
457
|
+
} else {
|
|
458
|
+
// See if the value contains the text
|
|
459
|
+
if ((item.props.text || "").toLowerCase().indexOf(searchText) >= 0) {
|
|
460
|
+
// Show the item
|
|
461
|
+
item.show();
|
|
462
|
+
|
|
463
|
+
// Set the flag
|
|
464
|
+
itemsFound = true;
|
|
465
|
+
} else {
|
|
466
|
+
// Hide the item
|
|
467
|
+
item.hide();
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// See if no items were found
|
|
473
|
+
if (!showAll && !itemsFound) {
|
|
474
|
+
// Show the empty message
|
|
475
|
+
elEmptyText.classList.remove("d-none");
|
|
476
|
+
}
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
|
|
399
480
|
// Generates the checkbox items
|
|
400
481
|
private generateCheckboxItems(): ICheckboxGroupItem[] {
|
|
401
482
|
let cbItems: ICheckboxGroupItem[] = [];
|
|
@@ -644,6 +725,9 @@ class _Dropdown extends Base<IDropdownProps> implements IDropdown {
|
|
|
644
725
|
}
|
|
645
726
|
}
|
|
646
727
|
}
|
|
728
|
+
|
|
729
|
+
// Configure search
|
|
730
|
+
this.configureSearch();
|
|
647
731
|
}
|
|
648
732
|
|
|
649
733
|
// Sets the label of the dropdown
|
|
@@ -153,12 +153,18 @@ export class DropdownItem {
|
|
|
153
153
|
// The component HTML element
|
|
154
154
|
get el(): HTMLElement { return this._el; }
|
|
155
155
|
|
|
156
|
+
// Hides the item
|
|
157
|
+
hide() { this._el.classList.add("d-none"); }
|
|
158
|
+
|
|
156
159
|
// Returns true if the item is selected
|
|
157
160
|
get isSelected(): boolean { return this._isSelected; }
|
|
158
161
|
|
|
159
162
|
// The component properties
|
|
160
163
|
get props(): IDropdownItem { return this._props; }
|
|
161
164
|
|
|
165
|
+
// Shows the item
|
|
166
|
+
show() { this._el.classList.remove("d-none"); }
|
|
167
|
+
|
|
162
168
|
// Toggles the item selection
|
|
163
169
|
toggle() {
|
|
164
170
|
// Skip the dividers, headers and nav items
|
|
@@ -155,6 +155,7 @@ export interface IDropdownProps extends IBaseProps<IDropdown> {
|
|
|
155
155
|
onMenuRendering?: (props: IFloatingUIProps) => IFloatingUIProps;
|
|
156
156
|
placement?: number;
|
|
157
157
|
required?: boolean;
|
|
158
|
+
search?: boolean;
|
|
158
159
|
title?: string;
|
|
159
160
|
type?: number;
|
|
160
161
|
updateLabel?: boolean;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
arrow, autoPlacement, computePosition, flip, hide, inline, offset, shift, size, ComputePositionConfig
|
|
3
|
+
} from "@floating-ui/dom";
|
|
2
4
|
import { setClassNames } from "../common";
|
|
3
5
|
import { IFloatingUIProps, IFloatingUI } from "./types";
|
|
4
6
|
export * as FloatingUILib from "@floating-ui/dom";
|
|
@@ -47,18 +49,15 @@ export enum FloatingUITypes {
|
|
|
47
49
|
*/
|
|
48
50
|
class _FloatingUI {
|
|
49
51
|
private _elArrow: HTMLElement = null;
|
|
50
|
-
private _elTarget: HTMLElement = null;
|
|
51
52
|
private _elContent: HTMLElement = null;
|
|
53
|
+
private _elIgnore: HTMLElement[] = null;
|
|
54
|
+
private _elTarget: HTMLElement = null;
|
|
52
55
|
private _options: ComputePositionConfig = null;
|
|
53
56
|
private _props: IFloatingUIProps = null;
|
|
54
57
|
|
|
55
|
-
// Static events
|
|
56
|
-
private static Events = [];
|
|
57
|
-
private static EventsCreated = false;
|
|
58
|
-
private static ScrollEvents = [];
|
|
59
|
-
|
|
60
58
|
// Constructor
|
|
61
59
|
constructor(props: IFloatingUIProps) {
|
|
60
|
+
this._elIgnore = [];
|
|
62
61
|
this._elTarget = props.elTarget;
|
|
63
62
|
this._props = props;
|
|
64
63
|
|
|
@@ -80,6 +79,7 @@ class _FloatingUI {
|
|
|
80
79
|
this._props.show ? this.show() : this.hide();
|
|
81
80
|
}
|
|
82
81
|
|
|
82
|
+
// Add the events to trigger, refresh and hide the element
|
|
83
83
|
private addEvents(trigger: string = "") {
|
|
84
84
|
// Events
|
|
85
85
|
if (trigger.indexOf("mouse") >= 0) {
|
|
@@ -97,48 +97,29 @@ class _FloatingUI {
|
|
|
97
97
|
});
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
//
|
|
101
|
-
|
|
102
|
-
//
|
|
103
|
-
if (
|
|
104
|
-
// Hide the element
|
|
105
|
-
this.hide();
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
_FloatingUI.ScrollEvents.push((ev: Event) => {
|
|
109
|
-
// Refresh the content
|
|
110
|
-
this.refresh();
|
|
111
|
-
});
|
|
100
|
+
// Create the event
|
|
101
|
+
document.addEventListener("click", (ev) => {
|
|
102
|
+
// Do nothing if we toggled this component
|
|
103
|
+
if (this._elTarget.contains(ev.target as HTMLElement)) { return; }
|
|
112
104
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
setTimeout(() => {
|
|
119
|
-
// Parse the events
|
|
120
|
-
_FloatingUI.Events.forEach(fnEvent => {
|
|
121
|
-
// Call the event
|
|
122
|
-
fnEvent(ev);
|
|
123
|
-
});
|
|
124
|
-
}, 10);
|
|
125
|
-
});
|
|
105
|
+
// Parse the elements to ignore
|
|
106
|
+
for (let i = 0; i < this._elIgnore.length; i++) {
|
|
107
|
+
// Do nothing if it triggered the click
|
|
108
|
+
if (this._elIgnore[i].contains(ev.target as HTMLElement)) { return; }
|
|
109
|
+
}
|
|
126
110
|
|
|
127
|
-
//
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
setTimeout(() => {
|
|
131
|
-
// Parse the events
|
|
132
|
-
_FloatingUI.ScrollEvents.forEach(fnEvent => {
|
|
133
|
-
// Call the event
|
|
134
|
-
fnEvent(ev);
|
|
135
|
-
});
|
|
136
|
-
}, 10);
|
|
137
|
-
});
|
|
111
|
+
// Hide the element
|
|
112
|
+
this.hide();
|
|
113
|
+
});
|
|
138
114
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
115
|
+
// Create the scroll event
|
|
116
|
+
window.addEventListener("scroll", (ev) => {
|
|
117
|
+
// Wait for the other events to run
|
|
118
|
+
setTimeout(() => {
|
|
119
|
+
// Refresh the content
|
|
120
|
+
this.refresh();
|
|
121
|
+
}, 10);
|
|
122
|
+
});
|
|
142
123
|
}
|
|
143
124
|
|
|
144
125
|
// Creates the floating ui
|
|
@@ -367,13 +348,33 @@ class _FloatingUI {
|
|
|
367
348
|
* Public Methods
|
|
368
349
|
*/
|
|
369
350
|
|
|
370
|
-
|
|
351
|
+
addIgnoreElement(el: HTMLElement) { this._elIgnore.push(el); }
|
|
352
|
+
|
|
353
|
+
removeIgnoreElement(el: HTMLElement) {
|
|
354
|
+
// Parse the elements
|
|
355
|
+
for (let i = 0; i < this._elIgnore.length; i++) {
|
|
356
|
+
// See if this is the element to remove
|
|
357
|
+
if (this._elIgnore[i].isEqualNode(el)) {
|
|
358
|
+
// Remove it
|
|
359
|
+
this._elIgnore.splice(i, 1);
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
setContent(el) { this._elContent = el; this.refresh(); }
|
|
371
366
|
|
|
372
367
|
// Hides the content
|
|
373
368
|
hide() {
|
|
374
369
|
// Remove it from the document
|
|
375
370
|
this._elContent.classList.add("d-none");
|
|
376
|
-
if (document.body.contains(this._elContent)) {
|
|
371
|
+
if (document.body.contains(this._elContent)) {
|
|
372
|
+
// Remove the element from the page
|
|
373
|
+
document.body.removeChild(this._elContent);
|
|
374
|
+
|
|
375
|
+
// Call the event
|
|
376
|
+
this._props.onHide ? this._props.onHide() : null;
|
|
377
|
+
}
|
|
377
378
|
}
|
|
378
379
|
|
|
379
380
|
// Determines if the content is visible
|
|
@@ -383,7 +384,16 @@ class _FloatingUI {
|
|
|
383
384
|
show() {
|
|
384
385
|
// Append it to the document
|
|
385
386
|
this._elContent.classList.remove("d-none");
|
|
386
|
-
if (!document.body.contains(this._elContent)) {
|
|
387
|
+
if (!document.body.contains(this._elContent)) {
|
|
388
|
+
// Add the element to the page
|
|
389
|
+
document.body.appendChild(this._elContent);
|
|
390
|
+
|
|
391
|
+
// Refresh the position
|
|
392
|
+
this.refresh();
|
|
393
|
+
|
|
394
|
+
// Call the event
|
|
395
|
+
this._props.onShow ? this._props.onShow() : null;
|
|
396
|
+
}
|
|
387
397
|
}
|
|
388
398
|
|
|
389
399
|
// Toggles the floating ui
|
|
@@ -5,8 +5,10 @@ import { IBaseProps } from "../types";
|
|
|
5
5
|
export const FloatingUIPlacements: IFloatingUIPlacements;
|
|
6
6
|
|
|
7
7
|
export interface IFloatingUI {
|
|
8
|
+
addIgnoreElement: (el: Element) => void;
|
|
8
9
|
hide: () => void;
|
|
9
10
|
isVisible: boolean;
|
|
11
|
+
removeIgnoreElement: (el: Element) => void;
|
|
10
12
|
setContent: (el: string | Element) => void;
|
|
11
13
|
show: () => void;
|
|
12
14
|
toggle: () => void;
|
|
@@ -29,6 +31,8 @@ export interface IFloatingUIOptions {
|
|
|
29
31
|
export interface IFloatingUIProps extends IBaseProps<IFloatingUI> {
|
|
30
32
|
elContent: HTMLElement;
|
|
31
33
|
elTarget: HTMLElement;
|
|
34
|
+
onHide?: (el?: HTMLElement) => void;
|
|
35
|
+
onShow?: (el?: HTMLElement) => void;
|
|
32
36
|
options?: IFloatingUIOptions;
|
|
33
37
|
placement?: number;
|
|
34
38
|
show?: boolean;
|