@web-atoms/web-controls 2.5.8 → 2.5.9

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.
@@ -0,0 +1,134 @@
1
+ import Bind from "@web-atoms/core/dist/core/Bind";
2
+ import XNode from "@web-atoms/core/dist/core/XNode";
3
+ import { AtomControl } from "@web-atoms/core/dist/web/controls/AtomControl";
4
+ import { askSuggestionPopup, Match, MatchAnyCaseInsensitive } from "./AtomRepeater";
5
+ import { BindableProperty } from "@web-atoms/core/dist/core/BindableProperty";
6
+ import { Focusable } from "../Focusable";
7
+
8
+ import "./DropDownInput.global.css";
9
+
10
+ export default class DropDownInput<T> extends AtomControl {
11
+
12
+ public "event-selection-changed"?: (e: CustomEvent) => void;
13
+
14
+ public items: any[];
15
+
16
+ public value: any;
17
+
18
+ public label: any;
19
+
20
+ public "data-alignment"?: "bottom-right" | "bottom-left";
21
+
22
+ public disableSearch: boolean;
23
+
24
+ @BindableProperty
25
+ public popupSuggestions: boolean;
26
+
27
+ @BindableProperty
28
+ public search: string;
29
+
30
+ @BindableProperty
31
+ public prompt: string;
32
+
33
+ @BindableProperty
34
+ public suggestionPrompt: string;
35
+
36
+ @BindableProperty
37
+ public autofocus: boolean;
38
+
39
+ @BindableProperty
40
+ public itemRenderer: (item: T) => XNode;
41
+
42
+ @BindableProperty
43
+ public labelPath: (item: T) => string;
44
+
45
+ @BindableProperty
46
+ public valuePath: (item: T) => string;
47
+
48
+ @BindableProperty
49
+ public match: Match<any>;
50
+
51
+ @BindableProperty
52
+ public suggestionRenderer: (item: T) => XNode;
53
+
54
+ private isPopupOpen: boolean;
55
+ input: HTMLInputElement;
56
+ labelElement: HTMLLabelElement;
57
+ anchorItem: any;
58
+ selectedItem: any;
59
+
60
+ constructor(app, e = document.createElement("drop-down-input")) {
61
+ super(app, e);
62
+ }
63
+
64
+ protected preCreate(): void {
65
+ this.items = null;
66
+ this.value = null;
67
+ this.selectedItem = null;
68
+ this.labelPath = (x) => (x as any)?.label ?? x;
69
+ this.valuePath = (x) => (x as any)?.value ?? x;
70
+ this.itemRenderer = (x) => <div text={this.labelPath?.(x) ?? x}/>;
71
+ this.search = "";
72
+ this.label = "";
73
+ this.isPopupOpen = false;
74
+ this.disableSearch = true;
75
+ this.render(<div
76
+ event-click={() => this.input.focus()}>
77
+ <input
78
+ autofocus={Bind.oneTime(() => this.autofocus)}
79
+ event-focus={() => this.onFocus()}
80
+ value={Bind.twoWaysImmediate(() => this.search)}
81
+ placeholder={Bind.oneWay(() => this.label)}/>
82
+ <label text={Bind.oneWay((x) => this.labelPath(this.items.find((i) => this.valuePath(i) === this.value)))}/>
83
+ <i/>
84
+ </div>);
85
+
86
+ this.input = this.element.querySelector("input");
87
+ this.labelElement = this.element.querySelector("label");
88
+ }
89
+ onFocus(): any {
90
+
91
+ const value = this.value;
92
+ if (value) {
93
+ this.input.placeholder = this.items.find((i) => this.valuePath?.(i) === value)?.label;
94
+ }
95
+ this.input.value = "";
96
+ this.app.runAsync(() => this.openPopup())
97
+ }
98
+
99
+ async openPopup() {
100
+ if(this.isPopupOpen) {
101
+ return;
102
+ }
103
+ this.isPopupOpen = true;
104
+ try {
105
+
106
+ let selectedItem = this.items.find((i) => this.value === (this.valuePath?.(i) ?? i));
107
+ this.anchorItem = selectedItem;
108
+ this.selectedItem = selectedItem;
109
+
110
+ const newItem = await askSuggestionPopup(
111
+ this as any,
112
+ this.items,
113
+ this.itemRenderer,
114
+ this.match ?? MatchAnyCaseInsensitive(this.labelPath),
115
+ selectedItem);
116
+ if (newItem !== selectedItem) {
117
+ this.selectedItem = selectedItem;
118
+ this.value = this.valuePath?.(newItem) ?? newItem;
119
+ this.element.dispatchEvent(new CustomEvent(
120
+ "selectionChanged",
121
+ {
122
+ bubbles: true,
123
+ detail: newItem,
124
+ cancelable: true
125
+ }
126
+ ));
127
+ }
128
+ Focusable.moveNext(this.input);
129
+ } finally {
130
+ this.isPopupOpen = false;
131
+ }
132
+ }
133
+
134
+ }
@@ -239,6 +239,7 @@ export default abstract class AtomPopover<T = any> {
239
239
  resultReject: (reason?: any) => void;
240
240
  parent: HTMLElement;
241
241
  popoverContainer: HTMLElement;
242
+ removed: boolean;
242
243
 
243
244
  static create(
244
245
  parent: HTMLElement | AtomControl,
@@ -372,11 +373,13 @@ export default abstract class AtomPopover<T = any> {
372
373
  abstract init(data?: any);
373
374
 
374
375
  close(r) {
376
+ this.removed = true;
375
377
  (this.popover as any).result = r ?? null;
376
378
  this.popover.remove();
377
379
  }
378
380
 
379
381
  async cancel() {
382
+ this.removed = true;
380
383
  delete (this.popover as any).result;
381
384
  this.popover.remove();
382
385
  }
package/src/tags.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ /* eslint-disable @typescript-eslint/naming-convention */
2
+ namespace JSX {
3
+ interface IntrinsicElements {
4
+ "data-list-input": any;
5
+ }
6
+ }