@liwe3/webcomponents 1.0.2 → 1.1.0
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/dist/AITextEditor.d.ts +173 -0
- package/dist/AITextEditor.d.ts.map +1 -0
- package/dist/ChunkUploader.d.ts +103 -0
- package/dist/ChunkUploader.d.ts.map +1 -0
- package/dist/ChunkUploader.js +614 -0
- package/dist/ChunkUploader.js.map +1 -0
- package/dist/ContainerBox.d.ts +112 -0
- package/dist/ContainerBox.d.ts.map +1 -0
- package/dist/ContainerBox.js +359 -0
- package/dist/ContainerBox.js.map +1 -0
- package/dist/DateSelector.d.ts +103 -0
- package/dist/DateSelector.d.ts.map +1 -0
- package/dist/DateSelector.js +372 -0
- package/dist/DateSelector.js.map +1 -0
- package/dist/Drawer.d.ts +63 -0
- package/dist/Drawer.d.ts.map +1 -0
- package/dist/Drawer.js +340 -0
- package/dist/Drawer.js.map +1 -0
- package/dist/ImageView.d.ts +42 -0
- package/dist/ImageView.d.ts.map +1 -0
- package/dist/ImageView.js +209 -0
- package/dist/ImageView.js.map +1 -0
- package/dist/PopoverMenu.d.ts +103 -0
- package/dist/PopoverMenu.d.ts.map +1 -0
- package/dist/PopoverMenu.js +312 -0
- package/dist/PopoverMenu.js.map +1 -0
- package/dist/SmartSelect.d.ts +99 -0
- package/dist/SmartSelect.d.ts.map +1 -0
- package/dist/SmartSelect.js.map +1 -1
- package/dist/Toast.d.ts +127 -0
- package/dist/Toast.d.ts.map +1 -0
- package/dist/Toast.js +507 -0
- package/dist/Toast.js.map +1 -0
- package/dist/TreeView.d.ts +84 -0
- package/dist/TreeView.d.ts.map +1 -0
- package/dist/TreeView.js +478 -0
- package/dist/TreeView.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -6
- package/dist/index.js.map +1 -1
- package/package.json +43 -3
- package/src/ChunkUploader.ts +921 -0
- package/src/ContainerBox.ts +570 -0
- package/src/DateSelector.ts +550 -0
- package/src/Drawer.ts +435 -0
- package/src/ImageView.ts +265 -0
- package/src/PopoverMenu.ts +595 -0
- package/src/SmartSelect.ts +231 -231
- package/src/Toast.ts +834 -0
- package/src/TreeView.ts +673 -0
- package/src/index.ts +70 -3
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PopoverMenu Web Component
|
|
3
|
+
* A customizable menu component using fixed positioning with support for nested submenus
|
|
4
|
+
*/
|
|
5
|
+
export type PopoverMenuItem = {
|
|
6
|
+
label: string;
|
|
7
|
+
enabled?: boolean;
|
|
8
|
+
items?: PopoverMenuItem[];
|
|
9
|
+
onclick?: () => void;
|
|
10
|
+
};
|
|
11
|
+
export type PopoverMenuConfig = {
|
|
12
|
+
label: string;
|
|
13
|
+
items: PopoverMenuItem[];
|
|
14
|
+
};
|
|
15
|
+
export declare class PopoverMenuElement extends HTMLElement {
|
|
16
|
+
shadowRoot: ShadowRoot;
|
|
17
|
+
private items;
|
|
18
|
+
private openPopovers;
|
|
19
|
+
private hoverTimeouts;
|
|
20
|
+
private initialized;
|
|
21
|
+
private globalClickHandler;
|
|
22
|
+
constructor();
|
|
23
|
+
connectedCallback(): void;
|
|
24
|
+
disconnectedCallback(): void;
|
|
25
|
+
/**
|
|
26
|
+
* Set up global event listeners
|
|
27
|
+
*/
|
|
28
|
+
private setupGlobalListeners;
|
|
29
|
+
/**
|
|
30
|
+
* Clean up global event listeners
|
|
31
|
+
*/
|
|
32
|
+
private cleanupGlobalListeners;
|
|
33
|
+
/**
|
|
34
|
+
* Set menu items
|
|
35
|
+
*/
|
|
36
|
+
setItems(items: PopoverMenuConfig[]): void;
|
|
37
|
+
/**
|
|
38
|
+
* Get current menu items
|
|
39
|
+
*/
|
|
40
|
+
getItems(): PopoverMenuConfig[];
|
|
41
|
+
/**
|
|
42
|
+
* Add a new menu item
|
|
43
|
+
*/
|
|
44
|
+
addMenuItem(item: PopoverMenuConfig, index?: number | null): void;
|
|
45
|
+
/**
|
|
46
|
+
* Remove a menu item
|
|
47
|
+
*/
|
|
48
|
+
removeMenuItem(index: number): void;
|
|
49
|
+
/**
|
|
50
|
+
* Update a menu item
|
|
51
|
+
*/
|
|
52
|
+
updateMenuItem(index: number, item: PopoverMenuConfig): void;
|
|
53
|
+
/**
|
|
54
|
+
* Render the menu component
|
|
55
|
+
*/
|
|
56
|
+
private render;
|
|
57
|
+
/**
|
|
58
|
+
* Create a menu trigger button
|
|
59
|
+
*/
|
|
60
|
+
private createMenuTrigger;
|
|
61
|
+
/**
|
|
62
|
+
* Create a popover if it doesn't exist
|
|
63
|
+
*/
|
|
64
|
+
private createPopoverIfNeeded;
|
|
65
|
+
/**
|
|
66
|
+
* Populate a popover with menu items
|
|
67
|
+
*/
|
|
68
|
+
private populatePopover;
|
|
69
|
+
/**
|
|
70
|
+
* Create a menu item element
|
|
71
|
+
*/
|
|
72
|
+
private createMenuItem;
|
|
73
|
+
/**
|
|
74
|
+
* Show a submenu
|
|
75
|
+
*/
|
|
76
|
+
private showSubmenu;
|
|
77
|
+
/**
|
|
78
|
+
* Close other submenus except the specified one and its ancestors
|
|
79
|
+
*/
|
|
80
|
+
private closeOtherSubmenus;
|
|
81
|
+
/**
|
|
82
|
+
* Close all menus
|
|
83
|
+
*/
|
|
84
|
+
private closeAllMenus;
|
|
85
|
+
/**
|
|
86
|
+
* Handle menu trigger click
|
|
87
|
+
*/
|
|
88
|
+
private handleMenuTriggerClick;
|
|
89
|
+
/**
|
|
90
|
+
* Show the main menu
|
|
91
|
+
*/
|
|
92
|
+
private showMainMenu;
|
|
93
|
+
/**
|
|
94
|
+
* Adjust popover position to handle overflow
|
|
95
|
+
*/
|
|
96
|
+
private adjustPopoverPosition;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Conditionally defines the custom element if in a browser environment.
|
|
100
|
+
*/
|
|
101
|
+
declare const definePopoverMenu: (tagName?: string) => void;
|
|
102
|
+
export { definePopoverMenu };
|
|
103
|
+
//# sourceMappingURL=PopoverMenu.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PopoverMenu.d.ts","sourceRoot":"","sources":["../src/PopoverMenu.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,eAAe,EAAE,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,eAAe,EAAE,CAAC;CAC1B,CAAC;AAEF,qBAAa,kBAAmB,SAAQ,WAAW;IACzC,UAAU,EAAE,UAAU,CAAC;IAC/B,OAAO,CAAC,KAAK,CAA2B;IACxC,OAAO,CAAC,YAAY,CAAuC;IAC3D,OAAO,CAAC,aAAa,CAAkC;IACvD,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,kBAAkB,CAA8C;;IAOxE,iBAAiB,IAAK,IAAI;IAQ1B,oBAAoB,IAAK,IAAI;IAI7B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAU5B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAO9B;;OAEG;IACH,QAAQ,CAAG,KAAK,EAAE,iBAAiB,EAAE,GAAI,IAAI;IAK7C;;OAEG;IACH,QAAQ,IAAK,iBAAiB,EAAE;IAIhC;;OAEG;IACH,WAAW,CAAG,IAAI,EAAE,iBAAiB,EAAE,KAAK,GAAE,MAAM,GAAG,IAAW,GAAI,IAAI;IAS1E;;OAEG;IACH,cAAc,CAAG,KAAK,EAAE,MAAM,GAAI,IAAI;IAOtC;;OAEG;IACH,cAAc,CAAG,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,GAAI,IAAI;IAO/D;;OAEG;IACH,OAAO,CAAC,MAAM;IAiId;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAezB;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAqB7B;;OAEG;IACH,OAAO,CAAC,eAAe;IAevB;;OAEG;IACH,OAAO,CAAC,cAAc;IAsDtB;;OAEG;IACH,OAAO,CAAC,WAAW;IAmBnB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAqC1B;;OAEG;IACH,OAAO,CAAC,aAAa;IAarB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAsB9B;;OAEG;IACH,OAAO,CAAC,YAAY;IAgBpB;;OAEG;IACH,OAAO,CAAC,qBAAqB;CA8F9B;AAED;;GAEG;AACH,QAAA,MAAM,iBAAiB,GAAK,gBAA8B,KAAI,IAI7D,CAAC;AAKF,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
class u extends HTMLElement {
|
|
2
|
+
constructor() {
|
|
3
|
+
super(), this.items = [], this.openPopovers = /* @__PURE__ */ new Map(), this.hoverTimeouts = /* @__PURE__ */ new Map(), this.initialized = !1, this.globalClickHandler = null, this.attachShadow({ mode: "open" });
|
|
4
|
+
}
|
|
5
|
+
connectedCallback() {
|
|
6
|
+
this.initialized || (this.render(), this.setupGlobalListeners(), this.initialized = !0);
|
|
7
|
+
}
|
|
8
|
+
disconnectedCallback() {
|
|
9
|
+
this.cleanupGlobalListeners();
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Set up global event listeners
|
|
13
|
+
*/
|
|
14
|
+
setupGlobalListeners() {
|
|
15
|
+
this.globalClickHandler = (e) => {
|
|
16
|
+
!this.contains(e.target) && !this.shadowRoot.contains(e.target) && this.closeAllMenus();
|
|
17
|
+
}, document.addEventListener("click", this.globalClickHandler);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Clean up global event listeners
|
|
21
|
+
*/
|
|
22
|
+
cleanupGlobalListeners() {
|
|
23
|
+
this.globalClickHandler && (document.removeEventListener("click", this.globalClickHandler), this.globalClickHandler = null);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Set menu items
|
|
27
|
+
*/
|
|
28
|
+
setItems(e) {
|
|
29
|
+
this.items = e, this.render();
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Get current menu items
|
|
33
|
+
*/
|
|
34
|
+
getItems() {
|
|
35
|
+
return this.items;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Add a new menu item
|
|
39
|
+
*/
|
|
40
|
+
addMenuItem(e, i = null) {
|
|
41
|
+
i === null ? this.items.push(e) : this.items.splice(i, 0, e), this.render();
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Remove a menu item
|
|
45
|
+
*/
|
|
46
|
+
removeMenuItem(e) {
|
|
47
|
+
e >= 0 && e < this.items.length && (this.items.splice(e, 1), this.render());
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Update a menu item
|
|
51
|
+
*/
|
|
52
|
+
updateMenuItem(e, i) {
|
|
53
|
+
e >= 0 && e < this.items.length && (this.items[e] = i, this.render());
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Render the menu component
|
|
57
|
+
*/
|
|
58
|
+
render() {
|
|
59
|
+
const e = this.shadowRoot.querySelector(".popover-menu-bar");
|
|
60
|
+
e && e.remove(), this.openPopovers.clear(), this.hoverTimeouts.forEach((t) => clearTimeout(t)), this.hoverTimeouts.clear(), this.shadowRoot.innerHTML = `
|
|
61
|
+
<style>
|
|
62
|
+
:host {
|
|
63
|
+
display: block;
|
|
64
|
+
font-family: var(--font-family, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* PopoverMenu Component Styles */
|
|
68
|
+
.popover-menu-bar {
|
|
69
|
+
display: flex;
|
|
70
|
+
background: var(--popover-menu-bar-background, #fff);
|
|
71
|
+
border: 1px solid var(--popover-menu-bar-border, #ddd);
|
|
72
|
+
border-radius: var(--popover-menu-bar-radius, 6px);
|
|
73
|
+
padding: var(--popover-menu-bar-padding, 4px);
|
|
74
|
+
box-shadow: var(--popover-menu-bar-shadow, 0 1px 3px rgba(0,0,0,0.1));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.popover-menu-trigger {
|
|
78
|
+
background: none;
|
|
79
|
+
border: none;
|
|
80
|
+
padding: 8px 16px;
|
|
81
|
+
cursor: pointer;
|
|
82
|
+
border-radius: 4px;
|
|
83
|
+
font-size: 14px;
|
|
84
|
+
transition: background-color 0.2s;
|
|
85
|
+
font-family: inherit;
|
|
86
|
+
color: var(--popover-menu-trigger-color, #333);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.popover-menu-trigger:hover {
|
|
90
|
+
background: var(--popover-menu-trigger-hover-bg, #f0f0f0);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.popover-menu-trigger.active {
|
|
94
|
+
background: var(--popover-menu-trigger-active-bg, #e3f2fd);
|
|
95
|
+
color: var(--popover-menu-trigger-active-color, #1976d2);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.popover-menu-popover {
|
|
99
|
+
margin: 0;
|
|
100
|
+
padding: 4px;
|
|
101
|
+
border: 1px solid var(--popover-menu-border, #ccc);
|
|
102
|
+
border-radius: var(--popover-menu-radius, 6px);
|
|
103
|
+
background: var(--popover-menu-background, white);
|
|
104
|
+
box-shadow: var(--popover-menu-shadow, 0 4px 12px rgba(0,0,0,0.15));
|
|
105
|
+
min-width: 180px;
|
|
106
|
+
z-index: 1000;
|
|
107
|
+
font-family: inherit;
|
|
108
|
+
position: fixed;
|
|
109
|
+
display: none;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.popover-menu-item {
|
|
113
|
+
display: flex;
|
|
114
|
+
align-items: center;
|
|
115
|
+
justify-content: space-between;
|
|
116
|
+
padding: 8px 12px;
|
|
117
|
+
cursor: pointer;
|
|
118
|
+
border-radius: 4px;
|
|
119
|
+
font-size: 14px;
|
|
120
|
+
transition: background-color 0.2s;
|
|
121
|
+
position: relative;
|
|
122
|
+
color: var(--popover-menu-item-color, #333);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.popover-menu-item:hover {
|
|
126
|
+
background: var(--popover-menu-item-hover-bg, #f5f5f5);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.popover-menu-item.disabled {
|
|
130
|
+
color: var(--popover-menu-item-disabled-color, #999);
|
|
131
|
+
cursor: not-allowed;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.popover-menu-item.disabled:hover {
|
|
135
|
+
background: transparent;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.popover-menu-item.has-submenu::after {
|
|
139
|
+
content: '▶';
|
|
140
|
+
font-size: 10px;
|
|
141
|
+
color: var(--popover-menu-submenu-arrow-color, #666);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.popover-menu-separator {
|
|
145
|
+
height: 1px;
|
|
146
|
+
background: var(--popover-menu-separator-color, #e0e0e0);
|
|
147
|
+
margin: 4px 0;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.popover-submenu-popover {
|
|
151
|
+
margin: 0;
|
|
152
|
+
padding: 4px;
|
|
153
|
+
border: 1px solid var(--popover-menu-border, #ccc);
|
|
154
|
+
border-radius: var(--popover-menu-radius, 6px);
|
|
155
|
+
background: var(--popover-menu-background, white);
|
|
156
|
+
box-shadow: var(--popover-menu-shadow, 0 4px 12px rgba(0,0,0,0.15));
|
|
157
|
+
min-width: 160px;
|
|
158
|
+
z-index: 1001;
|
|
159
|
+
font-family: inherit;
|
|
160
|
+
position: fixed;
|
|
161
|
+
display: none;
|
|
162
|
+
}
|
|
163
|
+
</style>
|
|
164
|
+
<div class="popover-menu-bar"></div>
|
|
165
|
+
`;
|
|
166
|
+
const i = this.shadowRoot.querySelector(".popover-menu-bar");
|
|
167
|
+
this.items.forEach((t, o) => {
|
|
168
|
+
const r = this.createMenuTrigger(t, o);
|
|
169
|
+
i.appendChild(r);
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Create a menu trigger button
|
|
174
|
+
*/
|
|
175
|
+
createMenuTrigger(e, i) {
|
|
176
|
+
const t = document.createElement("button");
|
|
177
|
+
return t.className = "popover-menu-trigger", t.textContent = e.label, t.dataset.menuIndex = i.toString(), t.addEventListener("click", (o) => {
|
|
178
|
+
o.preventDefault(), o.stopPropagation(), this.handleMenuTriggerClick(t, e.items, i);
|
|
179
|
+
}), t;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Create a popover if it doesn't exist
|
|
183
|
+
*/
|
|
184
|
+
createPopoverIfNeeded(e, i, t = !1) {
|
|
185
|
+
let o = this.shadowRoot.querySelector(`#${i}`);
|
|
186
|
+
return o || (o = document.createElement("div"), o.id = i, o.className = t ? "popover-submenu-popover" : "popover-menu-popover", o.style.display = "none", o.style.position = "fixed", this.shadowRoot.appendChild(o), this.openPopovers.set(i, o)), this.populatePopover(o, e, i), o;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Populate a popover with menu items
|
|
190
|
+
*/
|
|
191
|
+
populatePopover(e, i, t) {
|
|
192
|
+
e.innerHTML = "", i.forEach((o, r) => {
|
|
193
|
+
if (o.label === "---sep") {
|
|
194
|
+
const s = document.createElement("div");
|
|
195
|
+
s.className = "popover-menu-separator", e.appendChild(s);
|
|
196
|
+
} else {
|
|
197
|
+
const s = this.createMenuItem(o, `${t}-item-${r}`);
|
|
198
|
+
e.appendChild(s);
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Create a menu item element
|
|
204
|
+
*/
|
|
205
|
+
createMenuItem(e, i) {
|
|
206
|
+
const t = document.createElement("div");
|
|
207
|
+
if (t.className = "popover-menu-item", t.textContent = e.label, e.enabled === !1)
|
|
208
|
+
return t.classList.add("disabled"), t;
|
|
209
|
+
if (e.items && e.items.length > 0) {
|
|
210
|
+
t.classList.add("has-submenu");
|
|
211
|
+
const o = `${i}-submenu`;
|
|
212
|
+
let r;
|
|
213
|
+
t.addEventListener("mouseenter", (s) => {
|
|
214
|
+
s.stopPropagation(), this.hoverTimeouts.has(o) && clearTimeout(this.hoverTimeouts.get(o)), r = window.setTimeout(() => {
|
|
215
|
+
this.closeOtherSubmenus(o), this.showSubmenu(e.items, o, t);
|
|
216
|
+
}, 100), this.hoverTimeouts.set(o, r);
|
|
217
|
+
}), t.addEventListener("mouseleave", (s) => {
|
|
218
|
+
s.stopPropagation();
|
|
219
|
+
}), t.addEventListener("click", (s) => {
|
|
220
|
+
s.stopPropagation(), this.closeOtherSubmenus(o), this.showSubmenu(e.items, o, t);
|
|
221
|
+
});
|
|
222
|
+
} else e.onclick && t.addEventListener("click", (o) => {
|
|
223
|
+
o.stopPropagation(), e.onclick(), this.closeAllMenus();
|
|
224
|
+
});
|
|
225
|
+
return t;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Show a submenu
|
|
229
|
+
*/
|
|
230
|
+
showSubmenu(e, i, t) {
|
|
231
|
+
const o = this.createPopoverIfNeeded(e, i, !0);
|
|
232
|
+
o.style.display = "block";
|
|
233
|
+
const r = t.getBoundingClientRect();
|
|
234
|
+
o.style.position = "fixed", o.style.left = `${r.right + 5}px`, o.style.top = `${r.top}px`, requestAnimationFrame(() => {
|
|
235
|
+
const s = t.getBoundingClientRect();
|
|
236
|
+
this.adjustPopoverPosition(o, s, "submenu");
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Close other submenus except the specified one and its ancestors
|
|
241
|
+
*/
|
|
242
|
+
closeOtherSubmenus(e = null) {
|
|
243
|
+
const i = /* @__PURE__ */ new Set();
|
|
244
|
+
if (e) {
|
|
245
|
+
i.add(e);
|
|
246
|
+
let t = e;
|
|
247
|
+
for (; t.includes("-submenu"); ) {
|
|
248
|
+
const o = t.lastIndexOf("-submenu");
|
|
249
|
+
if (o > 0) {
|
|
250
|
+
const s = t.substring(0, o).lastIndexOf("-item-");
|
|
251
|
+
if (s > 0)
|
|
252
|
+
t = t.substring(0, s), t.endsWith("-submenu") && i.add(t);
|
|
253
|
+
else
|
|
254
|
+
break;
|
|
255
|
+
} else
|
|
256
|
+
break;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
this.openPopovers.forEach((t, o) => {
|
|
260
|
+
!i.has(o) && t.classList.contains("popover-submenu-popover") && (t.style.display = "none");
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Close all menus
|
|
265
|
+
*/
|
|
266
|
+
closeAllMenus() {
|
|
267
|
+
this.hoverTimeouts.forEach((e) => clearTimeout(e)), this.hoverTimeouts.clear(), this.openPopovers.forEach((e) => {
|
|
268
|
+
e.style.display = "none";
|
|
269
|
+
}), this.shadowRoot.querySelectorAll(".popover-menu-trigger").forEach((e) => e.classList.remove("active"));
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Handle menu trigger click
|
|
273
|
+
*/
|
|
274
|
+
handleMenuTriggerClick(e, i, t) {
|
|
275
|
+
const o = `menu-${t}`, r = this.shadowRoot.querySelector(`#${o}`);
|
|
276
|
+
if (r && r.style.display === "block")
|
|
277
|
+
this.closeAllMenus();
|
|
278
|
+
else {
|
|
279
|
+
this.closeAllMenus();
|
|
280
|
+
const s = this.createPopoverIfNeeded(i, o);
|
|
281
|
+
e.classList.add("active"), this.showMainMenu(s, e);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Show the main menu
|
|
286
|
+
*/
|
|
287
|
+
showMainMenu(e, i) {
|
|
288
|
+
e.style.display = "block";
|
|
289
|
+
const t = i.getBoundingClientRect();
|
|
290
|
+
e.style.position = "fixed", e.style.left = `${t.left}px`, e.style.top = `${t.bottom + 2}px`, requestAnimationFrame(() => {
|
|
291
|
+
const o = i.getBoundingClientRect();
|
|
292
|
+
this.adjustPopoverPosition(e, o, "main");
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Adjust popover position to handle overflow
|
|
297
|
+
*/
|
|
298
|
+
adjustPopoverPosition(e, i, t) {
|
|
299
|
+
const o = e.getBoundingClientRect(), r = window.innerWidth, s = window.innerHeight, n = 10;
|
|
300
|
+
let l = parseFloat(e.style.left), a = parseFloat(e.style.top);
|
|
301
|
+
t === "main" ? (o.right > r - n && (l = i.right - o.width), l < n && (l = n), o.width > r - 2 * n && (l = n), o.bottom > s - n && (a = i.top - o.height - 2, a < n && (a = s - o.height - n)), a < n && (a = n), o.height > s - 2 * n && (a = n)) : t === "submenu" && (o.right > r - n && (l = i.left - o.width - 5, l < n && (l = n)), l < n && (l = n), o.bottom > s - n && (a = i.bottom - o.height, a < n && (a = s - o.height - n)), a < n && (a = n), o.height > s - 2 * n && (a = n)), e.style.left = `${l}px`, e.style.top = `${a}px`;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
const d = (p = "liwe3-popover-menu") => {
|
|
305
|
+
typeof window < "u" && !window.customElements.get(p) && customElements.define(p, u);
|
|
306
|
+
};
|
|
307
|
+
d();
|
|
308
|
+
export {
|
|
309
|
+
u as PopoverMenuElement,
|
|
310
|
+
d as definePopoverMenu
|
|
311
|
+
};
|
|
312
|
+
//# sourceMappingURL=PopoverMenu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PopoverMenu.js","sources":["../src/PopoverMenu.ts"],"sourcesContent":["/**\n * PopoverMenu Web Component\n * A customizable menu component using fixed positioning with support for nested submenus\n */\n\nexport type PopoverMenuItem = {\n label: string;\n enabled?: boolean;\n items?: PopoverMenuItem[];\n onclick?: () => void;\n};\n\nexport type PopoverMenuConfig = {\n label: string;\n items: PopoverMenuItem[];\n};\n\nexport class PopoverMenuElement extends HTMLElement {\n declare shadowRoot: ShadowRoot;\n private items: PopoverMenuConfig[] = [];\n private openPopovers: Map<string, HTMLElement> = new Map();\n private hoverTimeouts: Map<string, number> = new Map();\n private initialized = false;\n private globalClickHandler: ( ( e: MouseEvent ) => void ) | null = null;\n\n constructor () {\n super();\n this.attachShadow( { mode: 'open' } );\n }\n\n connectedCallback (): void {\n if ( !this.initialized ) {\n this.render();\n this.setupGlobalListeners();\n this.initialized = true;\n }\n }\n\n disconnectedCallback (): void {\n this.cleanupGlobalListeners();\n }\n\n /**\n * Set up global event listeners\n */\n private setupGlobalListeners (): void {\n // Add global click listener to close menus when clicking outside\n this.globalClickHandler = ( e: MouseEvent ) => {\n if ( !this.contains( e.target as Node ) && !this.shadowRoot.contains( e.target as Node ) ) {\n this.closeAllMenus();\n }\n };\n document.addEventListener( 'click', this.globalClickHandler );\n }\n\n /**\n * Clean up global event listeners\n */\n private cleanupGlobalListeners (): void {\n if ( this.globalClickHandler ) {\n document.removeEventListener( 'click', this.globalClickHandler );\n this.globalClickHandler = null;\n }\n }\n\n /**\n * Set menu items\n */\n setItems ( items: PopoverMenuConfig[] ): void {\n this.items = items;\n this.render();\n }\n\n /**\n * Get current menu items\n */\n getItems (): PopoverMenuConfig[] {\n return this.items;\n }\n\n /**\n * Add a new menu item\n */\n addMenuItem ( item: PopoverMenuConfig, index: number | null = null ): void {\n if ( index === null ) {\n this.items.push( item );\n } else {\n this.items.splice( index, 0, item );\n }\n this.render();\n }\n\n /**\n * Remove a menu item\n */\n removeMenuItem ( index: number ): void {\n if ( index >= 0 && index < this.items.length ) {\n this.items.splice( index, 1 );\n this.render();\n }\n }\n\n /**\n * Update a menu item\n */\n updateMenuItem ( index: number, item: PopoverMenuConfig ): void {\n if ( index >= 0 && index < this.items.length ) {\n this.items[ index ] = item;\n this.render();\n }\n }\n\n /**\n * Render the menu component\n */\n private render (): void {\n // Clear all existing content\n const existingContainer = this.shadowRoot.querySelector( '.popover-menu-bar' );\n if ( existingContainer ) {\n existingContainer.remove();\n }\n\n // Clear popover tracking\n this.openPopovers.clear();\n\n // Clear any existing hover timeouts\n this.hoverTimeouts.forEach( timeout => clearTimeout( timeout ) );\n this.hoverTimeouts.clear();\n\n this.shadowRoot.innerHTML = `\n <style>\n :host {\n display: block;\n font-family: var(--font-family, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif);\n }\n\n /* PopoverMenu Component Styles */\n .popover-menu-bar {\n display: flex;\n background: var(--popover-menu-bar-background, #fff);\n border: 1px solid var(--popover-menu-bar-border, #ddd);\n border-radius: var(--popover-menu-bar-radius, 6px);\n padding: var(--popover-menu-bar-padding, 4px);\n box-shadow: var(--popover-menu-bar-shadow, 0 1px 3px rgba(0,0,0,0.1));\n }\n\n .popover-menu-trigger {\n background: none;\n border: none;\n padding: 8px 16px;\n cursor: pointer;\n border-radius: 4px;\n font-size: 14px;\n transition: background-color 0.2s;\n font-family: inherit;\n color: var(--popover-menu-trigger-color, #333);\n }\n\n .popover-menu-trigger:hover {\n background: var(--popover-menu-trigger-hover-bg, #f0f0f0);\n }\n\n .popover-menu-trigger.active {\n background: var(--popover-menu-trigger-active-bg, #e3f2fd);\n color: var(--popover-menu-trigger-active-color, #1976d2);\n }\n\n .popover-menu-popover {\n margin: 0;\n padding: 4px;\n border: 1px solid var(--popover-menu-border, #ccc);\n border-radius: var(--popover-menu-radius, 6px);\n background: var(--popover-menu-background, white);\n box-shadow: var(--popover-menu-shadow, 0 4px 12px rgba(0,0,0,0.15));\n min-width: 180px;\n z-index: 1000;\n font-family: inherit;\n position: fixed;\n display: none;\n }\n\n .popover-menu-item {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 12px;\n cursor: pointer;\n border-radius: 4px;\n font-size: 14px;\n transition: background-color 0.2s;\n position: relative;\n color: var(--popover-menu-item-color, #333);\n }\n\n .popover-menu-item:hover {\n background: var(--popover-menu-item-hover-bg, #f5f5f5);\n }\n\n .popover-menu-item.disabled {\n color: var(--popover-menu-item-disabled-color, #999);\n cursor: not-allowed;\n }\n\n .popover-menu-item.disabled:hover {\n background: transparent;\n }\n\n .popover-menu-item.has-submenu::after {\n content: '▶';\n font-size: 10px;\n color: var(--popover-menu-submenu-arrow-color, #666);\n }\n\n .popover-menu-separator {\n height: 1px;\n background: var(--popover-menu-separator-color, #e0e0e0);\n margin: 4px 0;\n }\n\n .popover-submenu-popover {\n margin: 0;\n padding: 4px;\n border: 1px solid var(--popover-menu-border, #ccc);\n border-radius: var(--popover-menu-radius, 6px);\n background: var(--popover-menu-background, white);\n box-shadow: var(--popover-menu-shadow, 0 4px 12px rgba(0,0,0,0.15));\n min-width: 160px;\n z-index: 1001;\n font-family: inherit;\n position: fixed;\n display: none;\n }\n </style>\n <div class=\"popover-menu-bar\"></div>\n `;\n\n const menuBar = this.shadowRoot.querySelector( '.popover-menu-bar' ) as HTMLElement;\n\n this.items.forEach( ( item, index ) => {\n const trigger = this.createMenuTrigger( item, index );\n menuBar.appendChild( trigger );\n } );\n }\n\n /**\n * Create a menu trigger button\n */\n private createMenuTrigger ( item: PopoverMenuConfig, index: number ): HTMLElement {\n const trigger = document.createElement( 'button' );\n trigger.className = 'popover-menu-trigger';\n trigger.textContent = item.label;\n trigger.dataset.menuIndex = index.toString();\n\n trigger.addEventListener( 'click', ( e ) => {\n e.preventDefault();\n e.stopPropagation();\n this.handleMenuTriggerClick( trigger, item.items, index );\n } );\n\n return trigger;\n }\n\n /**\n * Create a popover if it doesn't exist\n */\n private createPopoverIfNeeded ( items: PopoverMenuItem[], id: string, isSubmenu = false ): HTMLElement {\n let popover = this.shadowRoot.querySelector( `#${ id }` ) as HTMLElement;\n\n if ( !popover ) {\n popover = document.createElement( 'div' );\n popover.id = id;\n popover.className = isSubmenu ? 'popover-submenu-popover' : 'popover-menu-popover';\n popover.style.display = 'none';\n popover.style.position = 'fixed';\n this.shadowRoot.appendChild( popover );\n\n // Track this popover\n this.openPopovers.set( id, popover );\n }\n\n // Always repopulate with current items to ensure content is up-to-date\n this.populatePopover( popover, items, id );\n\n return popover;\n }\n\n /**\n * Populate a popover with menu items\n */\n private populatePopover ( popover: HTMLElement, items: PopoverMenuItem[], baseId: string ): void {\n popover.innerHTML = '';\n\n items.forEach( ( item, index ) => {\n if ( item.label === '---sep' ) {\n const separator = document.createElement( 'div' );\n separator.className = 'popover-menu-separator';\n popover.appendChild( separator );\n } else {\n const menuItem = this.createMenuItem( item, `${ baseId }-item-${ index }` );\n popover.appendChild( menuItem );\n }\n } );\n }\n\n /**\n * Create a menu item element\n */\n private createMenuItem ( item: PopoverMenuItem, id: string ): HTMLElement {\n const menuItem = document.createElement( 'div' );\n menuItem.className = 'popover-menu-item';\n menuItem.textContent = item.label;\n\n if ( item.enabled === false ) {\n menuItem.classList.add( 'disabled' );\n return menuItem;\n }\n\n if ( item.items && item.items.length > 0 ) {\n // Has submenu\n menuItem.classList.add( 'has-submenu' );\n const submenuId = `${ id }-submenu`;\n\n let hoverTimeout: number;\n\n menuItem.addEventListener( 'mouseenter', ( e ) => {\n e.stopPropagation();\n\n // Clear any existing timeout\n if ( this.hoverTimeouts.has( submenuId ) ) {\n clearTimeout( this.hoverTimeouts.get( submenuId ) );\n }\n\n hoverTimeout = window.setTimeout( () => {\n this.closeOtherSubmenus( submenuId );\n this.showSubmenu( item.items!, submenuId, menuItem );\n }, 100 );\n\n this.hoverTimeouts.set( submenuId, hoverTimeout );\n } );\n\n menuItem.addEventListener( 'mouseleave', ( e ) => {\n e.stopPropagation();\n } );\n\n menuItem.addEventListener( 'click', ( e ) => {\n e.stopPropagation();\n this.closeOtherSubmenus( submenuId );\n this.showSubmenu( item.items!, submenuId, menuItem );\n } );\n } else if ( item.onclick ) {\n // Regular menu item with click handler\n menuItem.addEventListener( 'click', ( e ) => {\n e.stopPropagation();\n item.onclick!();\n this.closeAllMenus();\n } );\n }\n\n return menuItem;\n }\n\n /**\n * Show a submenu\n */\n private showSubmenu ( items: PopoverMenuItem[], submenuId: string, parentItem: HTMLElement ): void {\n const submenu = this.createPopoverIfNeeded( items, submenuId, true );\n\n // Show the menu first so it's in the DOM and can be measured\n submenu.style.display = 'block';\n\n // Get the parent item's position AFTER showing the menu\n const rect = parentItem.getBoundingClientRect();\n submenu.style.position = 'fixed';\n submenu.style.left = `${ rect.right + 5 }px`;\n submenu.style.top = `${ rect.top }px`;\n\n // Adjust position with comprehensive overflow handling\n requestAnimationFrame( () => {\n const newRect = parentItem.getBoundingClientRect();\n this.adjustPopoverPosition( submenu, newRect, 'submenu' );\n } );\n }\n\n /**\n * Close other submenus except the specified one and its ancestors\n */\n private closeOtherSubmenus ( exceptSubmenuId: string | null = null ): void {\n // Build a set of IDs to keep open (the submenu being opened and all its ancestors)\n const idsToKeep = new Set<string>();\n if ( exceptSubmenuId ) {\n idsToKeep.add( exceptSubmenuId );\n\n // Add all ancestor IDs by traversing up the ID hierarchy\n let currentId = exceptSubmenuId;\n while ( currentId.includes( '-submenu' ) ) {\n // Remove the last submenu part to get the parent\n const lastSubmenuIndex = currentId.lastIndexOf( '-submenu' );\n if ( lastSubmenuIndex > 0 ) {\n // Find the item part before this submenu\n const beforeSubmenu = currentId.substring( 0, lastSubmenuIndex );\n const lastItemIndex = beforeSubmenu.lastIndexOf( '-item-' );\n if ( lastItemIndex > 0 ) {\n currentId = currentId.substring( 0, lastItemIndex );\n if ( currentId.endsWith( '-submenu' ) ) {\n idsToKeep.add( currentId );\n }\n } else {\n break;\n }\n } else {\n break;\n }\n }\n }\n\n // Close all submenus that are not in the keep set\n this.openPopovers.forEach( ( popover, id ) => {\n if ( !idsToKeep.has( id ) && popover.classList.contains( 'popover-submenu-popover' ) ) {\n popover.style.display = 'none';\n }\n } );\n }\n\n /**\n * Close all menus\n */\n private closeAllMenus (): void {\n // Clear all hover timeouts\n this.hoverTimeouts.forEach( timeout => clearTimeout( timeout ) );\n this.hoverTimeouts.clear();\n\n this.openPopovers.forEach( popover => {\n popover.style.display = 'none';\n } );\n\n // Remove active class from all triggers\n this.shadowRoot.querySelectorAll( '.popover-menu-trigger' ).forEach( t => t.classList.remove( 'active' ) );\n }\n\n /**\n * Handle menu trigger click\n */\n private handleMenuTriggerClick ( trigger: HTMLElement, items: PopoverMenuItem[], index: number ): void {\n const popoverId = `menu-${ index }`;\n const popover = this.shadowRoot.querySelector( `#${ popoverId }` ) as HTMLElement;\n\n if ( popover && popover.style.display === 'block' ) {\n // Menu is open, close it\n this.closeAllMenus();\n } else {\n // Close other menus first\n this.closeAllMenus();\n\n // Create the popover and show it\n const mainPopover = this.createPopoverIfNeeded( items, popoverId );\n\n // Add active class to clicked trigger\n trigger.classList.add( 'active' );\n\n // Position and show the popover\n this.showMainMenu( mainPopover, trigger );\n }\n }\n\n /**\n * Show the main menu\n */\n private showMainMenu ( popover: HTMLElement, trigger: HTMLElement ): void {\n // Show the menu first so it's in the DOM and can be measured\n popover.style.display = 'block';\n\n const rect = trigger.getBoundingClientRect();\n popover.style.position = 'fixed';\n popover.style.left = `${ rect.left }px`;\n popover.style.top = `${ rect.bottom + 2 }px`;\n\n // Adjust position with comprehensive overflow handling\n requestAnimationFrame( () => {\n const updatedRect = trigger.getBoundingClientRect();\n this.adjustPopoverPosition( popover, updatedRect, 'main' );\n } );\n }\n\n /**\n * Adjust popover position to handle overflow\n */\n private adjustPopoverPosition ( popover: HTMLElement, triggerRect: DOMRect, type: 'main' | 'submenu' ): void {\n const popoverRect = popover.getBoundingClientRect();\n const viewportWidth = window.innerWidth;\n const viewportHeight = window.innerHeight;\n const margin = 10; // Minimum margin from screen edges\n\n let newLeft = parseFloat( popover.style.left );\n let newTop = parseFloat( popover.style.top );\n\n if ( type === 'main' ) {\n // Main menu positioning\n\n // Handle horizontal overflow - check right edge first\n if ( popoverRect.right > viewportWidth - margin ) {\n // If overflowing right, align right edge of popover with right edge of trigger\n newLeft = triggerRect.right - popoverRect.width;\n }\n\n // Then ensure minimum margin from left edge\n if ( newLeft < margin ) {\n newLeft = margin;\n }\n\n // If popover is wider than viewport, center it\n if ( popoverRect.width > viewportWidth - ( 2 * margin ) ) {\n newLeft = margin;\n }\n\n // Handle vertical overflow - check bottom first\n if ( popoverRect.bottom > viewportHeight - margin ) {\n // Try positioning above the trigger\n newTop = triggerRect.top - popoverRect.height - 2;\n\n // If positioning above would go off-screen, position at bottom margin\n if ( newTop < margin ) {\n newTop = viewportHeight - popoverRect.height - margin;\n }\n }\n\n // Ensure minimum margin from top\n if ( newTop < margin ) {\n newTop = margin;\n }\n\n // If popover is taller than viewport, position at top margin\n if ( popoverRect.height > viewportHeight - ( 2 * margin ) ) {\n newTop = margin;\n }\n\n } else if ( type === 'submenu' ) {\n // Submenu positioning\n\n // Handle horizontal overflow\n if ( popoverRect.right > viewportWidth - margin ) {\n // Position to the left of the parent item\n newLeft = triggerRect.left - popoverRect.width - 5;\n\n // If still overflowing left, position at margin from left edge\n if ( newLeft < margin ) {\n newLeft = margin;\n }\n }\n\n // Ensure minimum margin from left edge\n if ( newLeft < margin ) {\n newLeft = margin;\n }\n\n // Handle vertical overflow\n if ( popoverRect.bottom > viewportHeight - margin ) {\n // Try aligning bottom of submenu with bottom of parent item\n newTop = triggerRect.bottom - popoverRect.height;\n\n // If that would go off-screen at top, position at bottom margin\n if ( newTop < margin ) {\n newTop = viewportHeight - popoverRect.height - margin;\n }\n }\n\n // Ensure minimum margin from top\n if ( newTop < margin ) {\n newTop = margin;\n }\n\n // If submenu is taller than viewport, position at top margin\n if ( popoverRect.height > viewportHeight - ( 2 * margin ) ) {\n newTop = margin;\n }\n }\n\n // Apply the new position\n popover.style.left = `${ newLeft }px`;\n popover.style.top = `${ newTop }px`;\n }\n}\n\n/**\n * Conditionally defines the custom element if in a browser environment.\n */\nconst definePopoverMenu = ( tagName = 'liwe3-popover-menu' ): void => {\n if ( typeof window !== 'undefined' && !window.customElements.get( tagName ) ) {\n customElements.define( tagName, PopoverMenuElement );\n }\n};\n\n// Auto-register with default tag name\ndefinePopoverMenu();\n\nexport { definePopoverMenu };\n"],"names":["PopoverMenuElement","items","item","index","existingContainer","timeout","menuBar","trigger","e","id","isSubmenu","popover","baseId","separator","menuItem","submenuId","hoverTimeout","parentItem","submenu","rect","newRect","exceptSubmenuId","idsToKeep","currentId","lastSubmenuIndex","lastItemIndex","t","popoverId","mainPopover","updatedRect","triggerRect","type","popoverRect","viewportWidth","viewportHeight","margin","newLeft","newTop","definePopoverMenu","tagName"],"mappings":"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"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SmartSelect Web Component
|
|
3
|
+
* A customizable select dropdown with search, multi-select, and keyboard navigation
|
|
4
|
+
*/
|
|
5
|
+
export type SelectOption = {
|
|
6
|
+
value: string;
|
|
7
|
+
label: string;
|
|
8
|
+
};
|
|
9
|
+
export declare class SmartSelectElement extends HTMLElement {
|
|
10
|
+
shadowRoot: ShadowRoot;
|
|
11
|
+
private isOpen;
|
|
12
|
+
private selectedOptions;
|
|
13
|
+
private filteredOptions;
|
|
14
|
+
private focusedIndex;
|
|
15
|
+
private searchValue;
|
|
16
|
+
private keyboardNavigating;
|
|
17
|
+
private keyboardTimer?;
|
|
18
|
+
constructor();
|
|
19
|
+
static get observedAttributes(): string[];
|
|
20
|
+
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
|
|
21
|
+
get multiple(): boolean;
|
|
22
|
+
set multiple(value: boolean);
|
|
23
|
+
get searchable(): boolean;
|
|
24
|
+
set searchable(value: boolean);
|
|
25
|
+
get placeholder(): string;
|
|
26
|
+
set placeholder(value: string);
|
|
27
|
+
get disabled(): boolean;
|
|
28
|
+
set disabled(value: boolean);
|
|
29
|
+
get value(): string | string[];
|
|
30
|
+
set value(val: string | string[]);
|
|
31
|
+
get options(): SelectOption[];
|
|
32
|
+
set options(opts: SelectOption[]);
|
|
33
|
+
/**
|
|
34
|
+
* Opens the dropdown
|
|
35
|
+
*/
|
|
36
|
+
open(): void;
|
|
37
|
+
/**
|
|
38
|
+
* Closes the dropdown
|
|
39
|
+
*/
|
|
40
|
+
close(): void;
|
|
41
|
+
/**
|
|
42
|
+
* Toggles the dropdown open/closed state
|
|
43
|
+
*/
|
|
44
|
+
toggle(): void;
|
|
45
|
+
/**
|
|
46
|
+
* Selects an option by its value
|
|
47
|
+
*/
|
|
48
|
+
selectOption(value: string): void;
|
|
49
|
+
/**
|
|
50
|
+
* Deselects an option by its value
|
|
51
|
+
*/
|
|
52
|
+
deselectOption(value: string): void;
|
|
53
|
+
/**
|
|
54
|
+
* Returns an array of currently selected options
|
|
55
|
+
*/
|
|
56
|
+
getSelectedOptions(): SelectOption[];
|
|
57
|
+
/**
|
|
58
|
+
* Sets the options for the select component
|
|
59
|
+
*/
|
|
60
|
+
setOptions(options: SelectOption[]): void;
|
|
61
|
+
/**
|
|
62
|
+
* Handles search functionality
|
|
63
|
+
*/
|
|
64
|
+
private handleSearch;
|
|
65
|
+
/**
|
|
66
|
+
* Updates the visual focus state without full re-render
|
|
67
|
+
*/
|
|
68
|
+
private updateFocusedOption;
|
|
69
|
+
/**
|
|
70
|
+
* Scrolls the focused option into view
|
|
71
|
+
*/
|
|
72
|
+
private scrollToFocusedOption;
|
|
73
|
+
/**
|
|
74
|
+
* Calculates the optimal dropdown position based on viewport constraints
|
|
75
|
+
*/
|
|
76
|
+
private _calculateDropdownPosition;
|
|
77
|
+
/**
|
|
78
|
+
* Updates dropdown position using fixed positioning relative to viewport
|
|
79
|
+
*/
|
|
80
|
+
private _updateDropdownPosition;
|
|
81
|
+
/**
|
|
82
|
+
* Handles keyboard navigation
|
|
83
|
+
*/
|
|
84
|
+
private handleKeydown;
|
|
85
|
+
/**
|
|
86
|
+
* Binds all event listeners
|
|
87
|
+
*/
|
|
88
|
+
private bindEvents;
|
|
89
|
+
/**
|
|
90
|
+
* Renders the component
|
|
91
|
+
*/
|
|
92
|
+
private render;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Conditionally defines the custom element if in a browser environment.
|
|
96
|
+
*/
|
|
97
|
+
declare const defineSmartSelect: (tagName?: string) => void;
|
|
98
|
+
export { defineSmartSelect };
|
|
99
|
+
//# sourceMappingURL=SmartSelect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SmartSelect.d.ts","sourceRoot":"","sources":["../src/SmartSelect.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,qBAAa,kBAAmB,SAAQ,WAAW;IACzC,UAAU,EAAE,UAAU,CAAC;IAC/B,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,eAAe,CAAsB;IAC7C,OAAO,CAAC,eAAe,CAAsB;IAC7C,OAAO,CAAC,YAAY,CAAc;IAClC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,kBAAkB,CAAkB;IAC5C,OAAO,CAAC,aAAa,CAAC,CAAS;;IAe/B,MAAM,KAAK,kBAAkB,IAAK,MAAM,EAAE,CAEzC;IAED,wBAAwB,CAAG,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAI,IAAI;IASjG,IAAI,QAAQ,IAAK,OAAO,CAEvB;IAED,IAAI,QAAQ,CAAG,KAAK,EAAE,OAAO,EAM5B;IAED,IAAI,UAAU,IAAK,OAAO,CAEzB;IAED,IAAI,UAAU,CAAG,KAAK,EAAE,OAAO,EAM9B;IAED,IAAI,WAAW,IAAK,MAAM,CAEzB;IAED,IAAI,WAAW,CAAG,KAAK,EAAE,MAAM,EAE9B;IAED,IAAI,QAAQ,IAAK,OAAO,CAEvB;IAED,IAAI,QAAQ,CAAG,KAAK,EAAE,OAAO,EAM5B;IAED,IAAI,KAAK,IAAK,MAAM,GAAG,MAAM,EAAE,CAK9B;IAED,IAAI,KAAK,CAAG,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,EAQjC;IAED,IAAI,OAAO,IAAK,YAAY,EAAE,CAW7B;IAED,IAAI,OAAO,CAAG,IAAI,EAAE,YAAY,EAAE,EAEjC;IAED;;OAEG;IACH,IAAI,IAAK,IAAI;IAyBb;;OAEG;IACH,KAAK,IAAK,IAAI;IAuBd;;OAEG;IACH,MAAM,IAAK,IAAI;IAQf;;OAEG;IACH,YAAY,CAAG,KAAK,EAAE,MAAM,GAAI,IAAI;IAiBpC;;OAEG;IACH,cAAc,CAAG,KAAK,EAAE,MAAM,GAAI,IAAI;IAMtC;;OAEG;IACH,kBAAkB,IAAK,YAAY,EAAE;IAIrC;;OAEG;IACH,UAAU,CAAG,OAAO,EAAE,YAAY,EAAE,GAAI,IAAI;IAO5C;;OAEG;IACH,OAAO,CAAC,YAAY;IAUpB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAc3B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAuB7B;;OAEG;IACH,OAAO,CAAC,0BAA0B;IA2ClC;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAgB/B;;OAEG;IACH,OAAO,CAAC,aAAa;IA0FrB;;OAEG;IACH,OAAO,CAAC,UAAU;IA4FlB;;OAEG;IACH,OAAO,CAAC,MAAM;CAwNf;AAED;;GAEG;AACH,QAAA,MAAM,iBAAiB,GAAK,UAAS,MAAuB,KAAI,IAI/D,CAAC;AAKF,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
|