@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.
- package/dist/Focusable.d.ts +4 -0
- package/dist/Focusable.d.ts.map +1 -0
- package/dist/Focusable.js +23 -0
- package/dist/Focusable.js.map +1 -0
- package/dist/basic/AtomRepeater.d.ts.map +1 -1
- package/dist/basic/AtomRepeater.js +29 -3
- package/dist/basic/AtomRepeater.js.map +1 -1
- package/dist/basic/DropDownInput.d.ts +32 -0
- package/dist/basic/DropDownInput.d.ts.map +1 -0
- package/dist/basic/DropDownInput.global.css +2 -0
- package/dist/basic/DropDownInput.global.css.map +1 -0
- package/dist/basic/DropDownInput.js +121 -0
- package/dist/basic/DropDownInput.js.map +1 -0
- package/dist/basic/elements/AtomPopover.d.ts +1 -0
- package/dist/basic/elements/AtomPopover.d.ts.map +1 -1
- package/dist/basic/elements/AtomPopover.js +2 -0
- package/dist/basic/elements/AtomPopover.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/images/svgs/caret-down.svg +1 -0
- package/package.json +1 -1
- package/src/Focusable.ts +14 -0
- package/src/basic/AtomRepeater.tsx +24 -1
- package/src/basic/DropDownInput.global.css +39 -0
- package/src/basic/DropDownInput.tsx +134 -0
- package/src/basic/elements/AtomPopover.tsx +3 -0
- package/src/tags.d.ts +6 -0
|
@@ -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
|
}
|