-
-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathct-input-autocomplete.ts
More file actions
executable file
·126 lines (113 loc) · 3.33 KB
/
ct-input-autocomplete.ts
File metadata and controls
executable file
·126 lines (113 loc) · 3.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import "./ct-autocomplete-suggestions.js";
import "./ct-input.js";
import { html } from "lit";
import { sleep } from "./ct-helpers.js";
import { CtLit, customElement, property, query, state } from "./ct-lit.js";
/**
* # `ct-input-autocomplete`
*
* @group lit-ct-components
* @element ct-input-autocomplete
*/
@customElement("ct-input-autocomplete")
export class CtInputAutocomplete extends CtLit {
render() {
return html`
<style>
:host {
display: inline-block;
box-sizing: border-box;
position: relative;
}
.input-wrapper {
display: flex;
flex-direction: row;
}
#autocompleteInput {
flex: 1;
}
</style>
<div class="input-wrapper" role="combobox" aria-haspopup="true" aria-owns="suggestionsWrapper">
<ct-input
id="autocompleteInput"
.value="${this.text}"
@value="${(e: any) => (this.text = e.detail)}"
.placeholder=${this.placeholder}
.errorMessage=${this.errorMessage}
?required=${this.required}
@blur=${this.onBlur}
.label="${this.label}"
>
<slot name="prefix" slot="prefix"></slot>
<slot name="suffix" slot="suffix"></slot>
</ct-input>
</div>
<ct-autocomplete-suggestions id="autocompleteSuggestions" .text="${this.text}" ?remote=${this.remote} .renderItem=${this.renderItem as any} .source="${this.source}">
</ct-autocomplete-suggestions>
`;
}
@query("#autocompleteInput") $autocompleteInput!: HTMLInputElement;
@query("#autocompleteSuggestions") $autocompleteSuggestions!: HTMLElementTagNameMap["ct-autocomplete-suggestions"];
@property({ type: String }) label = "";
@property({ type: String }) placeholder = "";
@property({ type: String }) errorMessage = "";
@property({ type: Boolean }) required = false;
@property({ type: Boolean }) compute = false;
@property({ type: Boolean }) remote = false;
@property({ type: Number }) maxlength!: number;
@property({ type: Array }) source: any[] = [];
@property({ type: String }) textProperty = "text";
@property({ type: String }) valueProperty = "value";
@property({ type: Object }) renderItem = (item: any, index: number) => html`<button>item ${index}</button>`;
@state() _text: string = "";
@state() _value?: any = undefined;
async onBlur() {
await sleep(500);
this.$autocompleteSuggestions.hiddeSugg();
}
get value() {
return this._value;
}
set value(val) {
if (this._value != val) {
let old = this._value;
this._value = val;
this.requestUpdate("value", old);
this.dispatchEvent(new CustomEvent("value", { detail: { value: val } }));
// Si seteo un valor y este existe en el source entonces
for (let i = 0; this.compute && this.source && i < this.source.length; i++) {
let el = this.source[i];
if (val == el.value) {
this.text = el.text;
return;
}
}
}
}
get text() {
return this._text;
}
set text(text) {
if (this._text != text) {
let old = this._text;
this._text = text;
this.requestUpdate("text", old);
this.dispatchEvent(new CustomEvent("text", { detail: { value: text } }));
for (let i = 0; this.compute && this.source && i < this.source.length; i++) {
let el = this.source[i];
if (text == el.text) {
this.value = el.value;
return;
}
}
}
}
validate() {
return true;
}
}
declare global {
interface HTMLElementTagNameMap {
"ct-input-autocomplete": CtInputAutocomplete;
}
}