composite-select 1.0.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.
Files changed (105) hide show
  1. package/README.md +5 -0
  2. package/commitlint.config.js +3 -0
  3. package/composition/composite-select/CompositeManager.js +43 -0
  4. package/composition/composite-select/composite-select.js +199 -0
  5. package/composition/composite-select/debounce.js +10 -0
  6. package/composition/composite-select/helpers.js +96 -0
  7. package/composition/composite-select/react.js +189 -0
  8. package/composition/container/ContainerManager.js +76 -0
  9. package/composition/img/ai.png +0 -0
  10. package/composition/img/chatgpt.png +0 -0
  11. package/composition/img/claude.png +0 -0
  12. package/composition/img/gemini.png +0 -0
  13. package/composition/img/gmail.png +0 -0
  14. package/composition/img/google_calendar.png +0 -0
  15. package/composition/img/google_drive.png +0 -0
  16. package/composition/img/google_keep.png +0 -0
  17. package/composition/img/img.json +5 -0
  18. package/composition/img/perplexity.png +0 -0
  19. package/composition/img/t3chat.png +0 -0
  20. package/composition/img/timeanddate.png +0 -0
  21. package/composition/img/tools.png +0 -0
  22. package/composition/img/youtube.png +0 -0
  23. package/composition/options-section/OptionsSectionManager.css +263 -0
  24. package/composition/options-section/OptionsSectionManager.js +486 -0
  25. package/composition/options-section/options-section.js +245 -0
  26. package/composition/options-section/react.js +90 -0
  27. package/composition/selected-section/SelectedSectionManager.css +214 -0
  28. package/composition/selected-section/SelectedSectionManager.js +336 -0
  29. package/composition/selected-section/react.js +91 -0
  30. package/composition/selected-section/selected-section.js +207 -0
  31. package/composition/unbind/clickOutside.js +17 -0
  32. package/diff/coreBundle.patch +13 -0
  33. package/diff/recorderApp.patch +13 -0
  34. package/dist/cjs/Module.cjs +15 -0
  35. package/dist/cjs/composite-select/CompositeManager.js +43 -0
  36. package/dist/cjs/composite-select/composite-select.js +199 -0
  37. package/dist/cjs/composite-select/debounce.js +10 -0
  38. package/dist/cjs/composite-select/helpers.js +96 -0
  39. package/dist/cjs/composite-select/react.js +189 -0
  40. package/dist/cjs/container/ContainerManager.js +76 -0
  41. package/dist/cjs/createSubscriber.cjs +48 -0
  42. package/dist/cjs/options-section/OptionsSectionManager.js +486 -0
  43. package/dist/cjs/options-section/options-section.js +245 -0
  44. package/dist/cjs/options-section/react.js +90 -0
  45. package/dist/cjs/selected-section/SelectedSectionManager.js +336 -0
  46. package/dist/cjs/selected-section/react.js +91 -0
  47. package/dist/cjs/selected-section/selected-section.js +207 -0
  48. package/dist/cjs/types.cjs +1 -0
  49. package/dist/cjs/unbind/clickOutside.js +17 -0
  50. package/dist/esm/Module.js +15 -0
  51. package/dist/esm/composite-select/CompositeManager.js +43 -0
  52. package/dist/esm/composite-select/composite-select.js +199 -0
  53. package/dist/esm/composite-select/debounce.js +10 -0
  54. package/dist/esm/composite-select/helpers.js +96 -0
  55. package/dist/esm/composite-select/react.js +189 -0
  56. package/dist/esm/container/ContainerManager.js +76 -0
  57. package/dist/esm/createSubscriber.js +48 -0
  58. package/dist/esm/options-section/OptionsSectionManager.js +486 -0
  59. package/dist/esm/options-section/options-section.js +245 -0
  60. package/dist/esm/options-section/react.js +90 -0
  61. package/dist/esm/selected-section/SelectedSectionManager.js +336 -0
  62. package/dist/esm/selected-section/react.js +91 -0
  63. package/dist/esm/selected-section/selected-section.js +207 -0
  64. package/dist/esm/types.js +1 -0
  65. package/dist/esm/unbind/clickOutside.js +17 -0
  66. package/dist/types/Module.d.ts +15 -0
  67. package/dist/types/composite-select/CompositeManager.d.ts +21 -0
  68. package/dist/types/composite-select/ContainerManager.html.d.ts +1 -0
  69. package/dist/types/composite-select/composite-select.d.ts +26 -0
  70. package/dist/types/composite-select/composite-select.html.d.ts +1 -0
  71. package/dist/types/composite-select/debounce.d.ts +1 -0
  72. package/dist/types/composite-select/helpers.d.ts +38 -0
  73. package/dist/types/composite-select/namesSource.d.ts +4 -0
  74. package/dist/types/composite-select/react.d.ts +61 -0
  75. package/dist/types/composite-select/urlManager.d.ts +49 -0
  76. package/dist/types/composite-select/urlManagerWc.d.ts +44 -0
  77. package/dist/types/container/ContainerManager.d.ts +33 -0
  78. package/dist/types/createSubscriber.d.ts +26 -0
  79. package/dist/types/options-section/OptionsSectionManager.d.ts +117 -0
  80. package/dist/types/options-section/OptionsSectionManager.html.d.ts +1 -0
  81. package/dist/types/options-section/OptionsSectionManagerWebComponent.attributes.html.d.ts +1 -0
  82. package/dist/types/options-section/OptionsSectionManagerWebComponent.html.d.ts +1 -0
  83. package/dist/types/options-section/OptionsSectionManagerWebComponent.nocssrequest.html.d.ts +1 -0
  84. package/dist/types/options-section/options-section.d.ts +67 -0
  85. package/dist/types/options-section/react.d.ts +27 -0
  86. package/dist/types/options-section/urlManager.d.ts +28 -0
  87. package/dist/types/selected-section/SelectedSectionManager.d.ts +89 -0
  88. package/dist/types/selected-section/SelectedSectionManager.html.d.ts +1 -0
  89. package/dist/types/selected-section/SelectedSectionManager.templates.html.d.ts +1 -0
  90. package/dist/types/selected-section/SelectedSectionManagerWebComponent.attributes.html.d.ts +1 -0
  91. package/dist/types/selected-section/SelectedSectionManagerWebComponent.html.d.ts +1 -0
  92. package/dist/types/selected-section/SelectedSectionManagerWebComponent.nocssrequest.html.d.ts +1 -0
  93. package/dist/types/selected-section/react.d.ts +32 -0
  94. package/dist/types/selected-section/selected-section.d.ts +54 -0
  95. package/dist/types/selected-section/urlManager.d.ts +25 -0
  96. package/dist/types/types.d.ts +9 -0
  97. package/dist/types/unbind/clickOutside.d.ts +1 -0
  98. package/floating-label-pattern.css +502 -0
  99. package/js/CenterAndHeightResizer.js +263 -0
  100. package/js/CenterResizer.js +190 -0
  101. package/madooei.tar.gz +0 -0
  102. package/package.json +28 -0
  103. package/release.config.js +3 -0
  104. package/test/lib.d.ts +6 -0
  105. package/test/lib.js +30 -0
@@ -0,0 +1,486 @@
1
+ import { markSearchWithSpan } from "../composite-select/helpers.js";
2
+ import createSubscriber from "../createSubscriber.js";
3
+ export class OptionsSectionManager {
4
+ propOptions;
5
+ propParentElement;
6
+ propFilterContainer;
7
+ propOptionsContainer;
8
+ propFooterContainer;
9
+ propInputElement = null;
10
+ propSpinnerElement = null;
11
+ propLabelElement = null;
12
+ propOkButton;
13
+ propLeftSpace;
14
+ propCancelButton;
15
+ propClearButton;
16
+ propHighlightedId = null;
17
+ _skipNextFocusEvent = false;
18
+ _attachedElements = new Map();
19
+ _subscriber = createSubscriber();
20
+ constructor(bindElement, options = {}) {
21
+ this.propParentElement = bindElement;
22
+ this.propParentElement.classList.add("options-section-manager");
23
+ const { options: opt = [], loading = false, disabled = false, value = "", showFooter = true, showFilter = true, renderItem = (item, def, searchValue) => def(item, searchValue), renderList = (list, def) => def(list), renderEmpty = (def) => def(), onClear = () => { }, ...rest } = options;
24
+ this.propOptions = {
25
+ options: opt,
26
+ loading,
27
+ disabled,
28
+ value,
29
+ showFooter,
30
+ showFilter,
31
+ renderItem,
32
+ renderList,
33
+ renderEmpty,
34
+ onClear,
35
+ ...rest,
36
+ };
37
+ this.render();
38
+ Promise.resolve().then(() => {
39
+ if (this.propOptions.maxHeight) {
40
+ this.setMaxHeight(this.propOptions.maxHeight);
41
+ }
42
+ this._bindEvents();
43
+ });
44
+ }
45
+ getSubscriber() {
46
+ return this._subscriber;
47
+ }
48
+ _triggerOnComponentChange(reason) {
49
+ if (this.propOptions.onComponentChange) {
50
+ this.propOptions.onComponentChange.call(this, this.propOptions, reason);
51
+ }
52
+ this._subscriber.trigger("onComponentChange", this.propOptions, reason);
53
+ }
54
+ _scrollToHighlighted() {
55
+ if (this.propHighlightedId === null)
56
+ return;
57
+ const el = this.propOptionsContainer.querySelector(`.element[data-id="${this.propHighlightedId}"]`);
58
+ if (el) {
59
+ el.scrollIntoView({ block: "nearest" });
60
+ }
61
+ }
62
+ _defaultRenderEmpty() {
63
+ return `<div class="empty-msg">No options to display</div>`;
64
+ }
65
+ _defaultRenderItem(item, searchValue) {
66
+ const el = document.createElement("div");
67
+ el.className = "element";
68
+ el.classList.toggle("selected", item.selected === true);
69
+ el.dataset.id = String(item.id);
70
+ const label = document.createElement("label");
71
+ label.innerHTML = markSearchWithSpan(item.label, searchValue || "");
72
+ el.appendChild(label);
73
+ return el;
74
+ }
75
+ _defaultRenderList(list) {
76
+ return list.map((item) => this.propOptions.renderItem(item, this._defaultRenderItem.bind(this), this.propOptions.value));
77
+ }
78
+ _bindEvents() {
79
+ if (this.propInputElement) {
80
+ this.propInputElement.addEventListener("input", (e) => {
81
+ const previousValue = this.propOptions.value;
82
+ this.propOptions.value = this.propInputElement.value;
83
+ this._triggerOnInputChange(e, previousValue, "input");
84
+ });
85
+ this.propInputElement.addEventListener("focus", (e) => {
86
+ if (this._skipNextFocusEvent) {
87
+ this._skipNextFocusEvent = false;
88
+ return;
89
+ }
90
+ if (this.propOptions.onFocus) {
91
+ this.propOptions.onFocus.call(this, e);
92
+ }
93
+ this._subscriber.trigger("onFocus", e);
94
+ this.attachArrowsUpAndDown();
95
+ });
96
+ this.propInputElement.addEventListener("blur", () => {
97
+ this.detachArrowsUpAndDown();
98
+ });
99
+ }
100
+ this.propClearButton.addEventListener("click", (e) => {
101
+ e.preventDefault();
102
+ this.clearSearch();
103
+ });
104
+ this.propOkButton.addEventListener("click", () => {
105
+ if (this.propOptions.onOk) {
106
+ this.propOptions.onOk.call(this);
107
+ }
108
+ this._subscriber.trigger("onOk");
109
+ });
110
+ this.propCancelButton.addEventListener("click", () => {
111
+ if (this.propOptions.onCancel) {
112
+ this.propOptions.onCancel.call(this);
113
+ }
114
+ this._subscriber.trigger("onCancel");
115
+ });
116
+ this.propOptionsContainer.addEventListener("click", (e) => {
117
+ if (this.propOptions.disabled)
118
+ return;
119
+ const target = e.target;
120
+ const element = target.closest(".element");
121
+ if (element) {
122
+ const id = element.dataset.id;
123
+ const item = this.propOptions.options?.find((opt) => String(opt.id) === id);
124
+ if (item) {
125
+ this.setFocus();
126
+ this.highlightAndScrollToElementOnTheList(item.id);
127
+ this._triggerOnItemPick(item);
128
+ }
129
+ }
130
+ });
131
+ }
132
+ _handleKeyDown(e) {
133
+ const options = this.propOptions.options || [];
134
+ const currentIndex = options.findIndex((item) => String(item.id) === String(this.propHighlightedId));
135
+ if (e.key === "ArrowDown") {
136
+ e.preventDefault();
137
+ e.stopPropagation();
138
+ if (currentIndex === -1) {
139
+ this.highlightAndScrollToElementOnTheList(options[0]?.id);
140
+ }
141
+ else if (currentIndex < options.length - 1) {
142
+ this.highlightAndScrollToElementOnTheList(options[currentIndex + 1].id);
143
+ }
144
+ }
145
+ else if (e.key === "ArrowUp") {
146
+ e.preventDefault();
147
+ e.stopPropagation();
148
+ if (currentIndex === -1) {
149
+ this.highlightAndScrollToElementOnTheList(options[options.length - 1]?.id);
150
+ }
151
+ else if (currentIndex > 0) {
152
+ this.highlightAndScrollToElementOnTheList(options[currentIndex - 1].id);
153
+ }
154
+ }
155
+ else if (e.key === "Enter") {
156
+ if (this.propHighlightedId !== null) {
157
+ e.preventDefault();
158
+ e.stopPropagation();
159
+ this.pickHighlighted();
160
+ }
161
+ else if (this.propInputElement.value === "") {
162
+ e.stopPropagation();
163
+ this._triggerOnInputChange(e, this.propOptions.value, "enter");
164
+ }
165
+ }
166
+ else if (e.key === "Escape") {
167
+ e.preventDefault();
168
+ e.stopPropagation();
169
+ this.highlightAndScrollToElementOnTheList(null);
170
+ }
171
+ else if (e.key === "Backspace" && this.propInputElement.value === "") {
172
+ e.stopPropagation();
173
+ this._triggerOnInputChange(e, this.propOptions.value, "backspace");
174
+ }
175
+ }
176
+ _updateOptionsDisplay() {
177
+ const container = this.propOptionsContainer;
178
+ if (!container)
179
+ return;
180
+ const options = this.propOptions.options || [];
181
+ if (options.length === 0) {
182
+ const result = this.propOptions.renderEmpty(this._defaultRenderEmpty.bind(this));
183
+ if (typeof result === "string") {
184
+ container.innerHTML = result;
185
+ }
186
+ else {
187
+ container.innerHTML = "";
188
+ container.appendChild(result);
189
+ }
190
+ return;
191
+ }
192
+ const renderedItems = this.propOptions.renderList(options, this._defaultRenderList.bind(this));
193
+ container.innerHTML = "";
194
+ renderedItems.forEach((item, index) => {
195
+ const dataItem = options[index];
196
+ let el = null;
197
+ if (typeof item === "string") {
198
+ const temp = document.createElement("div");
199
+ temp.innerHTML = item;
200
+ el = temp.firstElementChild;
201
+ el.classList.add("element");
202
+ el.dataset.id = String(dataItem.id);
203
+ el.classList.toggle("selected", dataItem.selected === true);
204
+ }
205
+ else {
206
+ el = item;
207
+ }
208
+ if (el) {
209
+ el.classList.toggle("highlighted", this.propHighlightedId !== null && String(dataItem.id) === String(this.propHighlightedId));
210
+ container.appendChild(el);
211
+ }
212
+ });
213
+ }
214
+ _updateLoadingDisplay() {
215
+ if (this.propSpinnerElement) {
216
+ this.propSpinnerElement.classList.toggle("loading", Boolean(this.propOptions.loading));
217
+ }
218
+ if (this.propClearButton) {
219
+ this.propClearButton.style.display = this.propOptions.loading ? "none" : "flex";
220
+ }
221
+ }
222
+ _updateDisabledDisplay() {
223
+ if (this.propOptionsContainer) {
224
+ this.propOptionsContainer.classList.toggle("disabled", Boolean(this.propOptions.disabled));
225
+ }
226
+ if (this.propClearButton) {
227
+ this.propClearButton.disabled = Boolean(this.propOptions.disabled);
228
+ }
229
+ }
230
+ _updateFooterDisplay() {
231
+ if (this.propFooterContainer) {
232
+ this.propFooterContainer.style.display = this.propOptions.showFooter !== false ? "flex" : "none";
233
+ }
234
+ }
235
+ _updateFilterDisplay() {
236
+ if (this.propFilterContainer) {
237
+ this.propFilterContainer.style.display = this.propOptions.showFilter !== false ? "flex" : "none";
238
+ }
239
+ }
240
+ /**
241
+ * Internal helper to notify both the callback provided in options and the internal subscriber
242
+ * when the input value changes.
243
+ */
244
+ _triggerOnInputChange(e, previousValue, origin) {
245
+ if (this.propOptions.onInputChange) {
246
+ this.propOptions.onInputChange.call(this, e, previousValue, origin);
247
+ }
248
+ this._subscriber.trigger("onInputChange", e, previousValue, origin);
249
+ }
250
+ /**
251
+ * Internal helper to notify both the callback provided in options and the internal subscriber
252
+ * when an item is picked (e.g. via click or Enter key).
253
+ */
254
+ _triggerOnItemPick(item) {
255
+ if (this.propOptions.disabled)
256
+ return;
257
+ if (this.propOptions.onItemPick) {
258
+ this.propOptions.onItemPick.call(this, item);
259
+ }
260
+ this._subscriber.trigger("onItemPick", item);
261
+ }
262
+ // setters
263
+ setMaxHeight(maxHeight) {
264
+ this.propOptions.maxHeight = maxHeight || "";
265
+ if (this.propParentElement) {
266
+ this.propParentElement.style.maxHeight = maxHeight || "none";
267
+ }
268
+ this._triggerOnComponentChange("setMaxHeight");
269
+ }
270
+ setDisabled(disabled) {
271
+ this.propOptions.disabled = Boolean(disabled);
272
+ this._updateDisabledDisplay();
273
+ this._triggerOnComponentChange("setDisabled");
274
+ }
275
+ setShowFooter(show) {
276
+ this.propOptions.showFooter = Boolean(show);
277
+ this._updateFooterDisplay();
278
+ this._triggerOnComponentChange("showFooter");
279
+ }
280
+ setShowFilter(show) {
281
+ this.propOptions.showFilter = Boolean(show);
282
+ this._updateFilterDisplay();
283
+ this._triggerOnComponentChange("showFilter");
284
+ }
285
+ setOptions(options) {
286
+ this.propOptions.options = options;
287
+ this._updateOptionsDisplay();
288
+ this._triggerOnComponentChange("setOptions");
289
+ }
290
+ setLoading(loading) {
291
+ this.propOptions.loading = Boolean(loading);
292
+ this._updateLoadingDisplay();
293
+ this._triggerOnComponentChange("setLoading");
294
+ }
295
+ setValue(value, triggerOnChange = true) {
296
+ const previousValue = this.propOptions.value;
297
+ this.propOptions.value = value;
298
+ if (this.propInputElement) {
299
+ this.propInputElement.value = value;
300
+ }
301
+ if (triggerOnChange) {
302
+ const event = new Event("input");
303
+ Object.defineProperty(event, "target", { writable: false, value: this.propInputElement });
304
+ this._triggerOnInputChange(event, previousValue, "setValue");
305
+ }
306
+ this._triggerOnComponentChange("setValue");
307
+ }
308
+ // getters
309
+ getShowFilter() {
310
+ return this.propOptions.showFilter;
311
+ }
312
+ getShowFooter() {
313
+ return this.propOptions.showFooter;
314
+ }
315
+ getDisabled() {
316
+ return this.propOptions.disabled;
317
+ }
318
+ getLabel() {
319
+ return this.propOptions.label;
320
+ }
321
+ getLoading() {
322
+ return this.propOptions.loading;
323
+ }
324
+ getValue() {
325
+ return this.propOptions.value;
326
+ }
327
+ getOptions() {
328
+ return this.propOptions.options || [];
329
+ }
330
+ getMaxHeight() {
331
+ return this.propOptions.maxHeight;
332
+ }
333
+ getHighlightedId() {
334
+ return this.propHighlightedId;
335
+ }
336
+ clearSearch(triggerOnClear = true, triggerOnChange = true) {
337
+ const previousValue = this.propOptions.value;
338
+ this.setValue("", triggerOnChange);
339
+ if (triggerOnClear) {
340
+ if (this.propOptions.onClear) {
341
+ this.propOptions.onClear();
342
+ }
343
+ this._subscriber.trigger("onClear");
344
+ const event = new Event("input");
345
+ Object.defineProperty(event, "target", { writable: false, value: this.propInputElement });
346
+ this._triggerOnInputChange(event, previousValue, "clear");
347
+ }
348
+ }
349
+ setLabel(label) {
350
+ this.propOptions.label = label;
351
+ if (this.propLabelElement) {
352
+ this.propLabelElement.textContent = label || "";
353
+ }
354
+ this._triggerOnComponentChange("setLabel");
355
+ }
356
+ highlightAndScrollToElementOnTheList(id) {
357
+ this.propHighlightedId = id ?? null;
358
+ this._updateOptionsDisplay();
359
+ if (this.propHighlightedId !== null) {
360
+ this._scrollToHighlighted();
361
+ }
362
+ if (this.propOptions.onHighlightChange) {
363
+ this.propOptions.onHighlightChange.call(this, this.propHighlightedId);
364
+ }
365
+ this._subscriber.trigger("onHighlightChange", this.propHighlightedId);
366
+ }
367
+ pickHighlighted() {
368
+ if (this.propHighlightedId === null)
369
+ return;
370
+ const item = this.propOptions.options?.find((opt) => String(opt.id) === String(this.propHighlightedId));
371
+ if (item) {
372
+ this._triggerOnItemPick(item);
373
+ }
374
+ }
375
+ setRenderEmpty(renderEmpty) {
376
+ this.propOptions.renderEmpty = renderEmpty || ((def) => def());
377
+ this._updateOptionsDisplay();
378
+ this._triggerOnComponentChange("setRenderEmpty");
379
+ }
380
+ setRenderItem(renderItem) {
381
+ this.propOptions.renderItem =
382
+ renderItem || ((item, defaultRender, searchValue) => defaultRender(item, searchValue));
383
+ this._updateOptionsDisplay();
384
+ this._triggerOnComponentChange("setRenderItem");
385
+ }
386
+ setRenderList(renderList) {
387
+ this.propOptions.renderList = renderList || ((list, def) => def(list));
388
+ this._updateOptionsDisplay();
389
+ this._triggerOnComponentChange("setRenderList");
390
+ }
391
+ setFocus(triggerOnFocus = true) {
392
+ if (!triggerOnFocus) {
393
+ this._skipNextFocusEvent = true;
394
+ }
395
+ this.propInputElement.focus();
396
+ }
397
+ setBlur() {
398
+ this.propInputElement.blur();
399
+ }
400
+ attachArrowsUpAndDown() {
401
+ const element = this.propInputElement;
402
+ if (this._attachedElements.has(element)) {
403
+ return;
404
+ }
405
+ const listener = (e) => this._handleKeyDown(e);
406
+ this._attachedElements.set(element, listener);
407
+ element.addEventListener("keydown", listener);
408
+ }
409
+ detachArrowsUpAndDown() {
410
+ const element = this.propInputElement;
411
+ const listener = this._attachedElements.get(element);
412
+ if (listener) {
413
+ element.removeEventListener("keydown", listener);
414
+ this._attachedElements.delete(element);
415
+ }
416
+ }
417
+ destroy() {
418
+ // This is the trick: we track all elements we've attached to and detach them here.
419
+ // This is especially important for the 'window' object which persists.
420
+ for (const [element] of this._attachedElements) {
421
+ const listener = this._attachedElements.get(element);
422
+ if (listener) {
423
+ element.removeEventListener("keydown", listener);
424
+ }
425
+ }
426
+ this._attachedElements.clear();
427
+ this._subscriber.destroy();
428
+ }
429
+ render() {
430
+ if (!this.propFilterContainer) {
431
+ this.propFilterContainer = document.createElement("div");
432
+ this.propFilterContainer.className = "filter";
433
+ const inputWrapper = document.createElement("div");
434
+ inputWrapper.className = "input-wrapper";
435
+ this.propInputElement = document.createElement("input");
436
+ this.propInputElement.type = "text";
437
+ this.propInputElement.id = "search-input-" + Math.random().toString(36).substr(2, 9);
438
+ this.propInputElement.placeholder = " ";
439
+ this.propInputElement.autocomplete = "off";
440
+ this.propLabelElement = document.createElement("label");
441
+ this.propLabelElement.setAttribute("for", this.propInputElement.id);
442
+ this.propLabelElement.textContent = this.propOptions.label || "Search...";
443
+ inputWrapper.appendChild(this.propInputElement);
444
+ inputWrapper.appendChild(this.propLabelElement);
445
+ this.propSpinnerElement = document.createElement("div");
446
+ this.propSpinnerElement.className = "spinner";
447
+ inputWrapper.appendChild(this.propSpinnerElement);
448
+ this.propClearButton = document.createElement("button");
449
+ this.propClearButton.type = "button";
450
+ this.propClearButton.className = "clear-btn";
451
+ this.propClearButton.textContent = "✕";
452
+ inputWrapper.appendChild(this.propClearButton);
453
+ this.propFilterContainer.appendChild(inputWrapper);
454
+ this.propOptionsContainer = document.createElement("div");
455
+ this.propOptionsContainer.className = "options";
456
+ this.propOptionsContainer.tabIndex = 0;
457
+ this.propFooterContainer = document.createElement("div");
458
+ this.propFooterContainer.className = "footer";
459
+ this.propCancelButton = document.createElement("button");
460
+ this.propCancelButton.type = "button";
461
+ this.propCancelButton.dataset.role = "cancel";
462
+ this.propCancelButton.className = "gcp-css white";
463
+ this.propCancelButton.textContent = "Cancel";
464
+ this.propOkButton = document.createElement("button");
465
+ this.propOkButton.type = "button";
466
+ this.propOkButton.dataset.role = "ok";
467
+ this.propOkButton.className = "gcp-css";
468
+ this.propOkButton.textContent = "OK";
469
+ this.propLeftSpace = document.createElement("span");
470
+ this.propLeftSpace.className = "left-space";
471
+ this.propLeftSpace.textContent = "";
472
+ this.propFooterContainer.appendChild(this.propLeftSpace);
473
+ this.propFooterContainer.appendChild(this.propCancelButton);
474
+ this.propFooterContainer.appendChild(this.propOkButton);
475
+ this.propParentElement.appendChild(this.propFilterContainer);
476
+ this.propParentElement.appendChild(this.propOptionsContainer);
477
+ this.propParentElement.appendChild(this.propFooterContainer);
478
+ }
479
+ this._updateOptionsDisplay();
480
+ this._updateLoadingDisplay();
481
+ this._updateDisabledDisplay();
482
+ this._updateFooterDisplay();
483
+ this._updateFilterDisplay();
484
+ // this.setValue(this.propOptions.value || "");
485
+ }
486
+ }