@fluid-topics/ft-text-field 0.3.37 → 0.3.39
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/build/ft-text-field-suggestion.css.d.ts +2 -0
- package/build/ft-text-field-suggestion.css.js +29 -0
- package/build/ft-text-field-suggestion.d.ts +20 -0
- package/build/ft-text-field-suggestion.js +75 -0
- package/build/ft-text-field-suggestion.properties.d.ts +4 -0
- package/build/ft-text-field-suggestion.properties.js +2 -0
- package/build/ft-text-field.css.d.ts +5 -0
- package/build/ft-text-field.css.js +54 -24
- package/build/ft-text-field.d.ts +23 -8
- package/build/ft-text-field.js +137 -45
- package/build/ft-text-field.light.js +203 -134
- package/build/ft-text-field.min.js +294 -221
- package/build/ft-text-field.properties.d.ts +3 -2
- package/build/index.d.ts +3 -0
- package/build/index.js +5 -0
- package/package.json +7 -6
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { css } from "lit";
|
|
2
|
+
// language=CSS
|
|
3
|
+
export const suggestionStyles = css `
|
|
4
|
+
.ft-text-field-suggestion {
|
|
5
|
+
position: relative;
|
|
6
|
+
padding: 8px 16px;
|
|
7
|
+
cursor: pointer;
|
|
8
|
+
min-height: 44px;
|
|
9
|
+
box-sizing: border-box;
|
|
10
|
+
outline: none;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.ft-text-field-suggestion,
|
|
14
|
+
.ft-text-field-suggestion--label {
|
|
15
|
+
display: flex;
|
|
16
|
+
align-items: center;
|
|
17
|
+
gap: 8px;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.ft-text-field-suggestion--label {
|
|
21
|
+
flex-grow: 1;
|
|
22
|
+
flex-shrink: 1;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
slot {
|
|
26
|
+
pointer-events: none;
|
|
27
|
+
}
|
|
28
|
+
`;
|
|
29
|
+
//# sourceMappingURL=ft-text-field-suggestion.css.js.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ElementDefinitionsMap, FtLitElement } from "@fluid-topics/ft-wc-utils";
|
|
2
|
+
import { FtTextFieldSuggestionProperties } from "./ft-text-field-suggestion.properties";
|
|
3
|
+
export declare class SuggestionSelectedEvent extends CustomEvent<string> {
|
|
4
|
+
constructor(value: string);
|
|
5
|
+
}
|
|
6
|
+
export declare class FtTextFieldSuggestion extends FtLitElement implements FtTextFieldSuggestionProperties {
|
|
7
|
+
static elementDefinitions: ElementDefinitionsMap;
|
|
8
|
+
value?: string;
|
|
9
|
+
private container?;
|
|
10
|
+
private assignedNodes;
|
|
11
|
+
static styles: import("lit").CSSResult;
|
|
12
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
13
|
+
focus(options?: FocusOptions): void;
|
|
14
|
+
click(): void;
|
|
15
|
+
private confirmSuggestion;
|
|
16
|
+
getValue(): string;
|
|
17
|
+
get textContent(): string;
|
|
18
|
+
private onKeyDown;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=ft-text-field-suggestion.d.ts.map
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { FtLitElement } from "@fluid-topics/ft-wc-utils";
|
|
8
|
+
import { html } from "lit";
|
|
9
|
+
import { property, query, queryAssignedNodes } from "lit/decorators.js";
|
|
10
|
+
import { FtRipple } from "@fluid-topics/ft-ripple";
|
|
11
|
+
import { FtTypography } from "@fluid-topics/ft-typography";
|
|
12
|
+
import { suggestionStyles } from "./ft-text-field-suggestion.css";
|
|
13
|
+
import { FtIcon } from "@fluid-topics/ft-icon";
|
|
14
|
+
export class SuggestionSelectedEvent extends CustomEvent {
|
|
15
|
+
constructor(value) {
|
|
16
|
+
super("suggestion-selected", { detail: value, bubbles: true, composed: true });
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export class FtTextFieldSuggestion extends FtLitElement {
|
|
20
|
+
render() {
|
|
21
|
+
return html `
|
|
22
|
+
<div class="ft-text-field-suggestion"
|
|
23
|
+
tabindex="-1"
|
|
24
|
+
@keydown=${this.onKeyDown}
|
|
25
|
+
@click=${this.confirmSuggestion}>
|
|
26
|
+
<ft-ripple></ft-ripple>
|
|
27
|
+
<ft-typography part="label"
|
|
28
|
+
variant="body1"
|
|
29
|
+
class="ft-text-field-suggestion--label">
|
|
30
|
+
<slot></slot>
|
|
31
|
+
</ft-typography>
|
|
32
|
+
</div>
|
|
33
|
+
`;
|
|
34
|
+
}
|
|
35
|
+
focus(options) {
|
|
36
|
+
var _a;
|
|
37
|
+
(_a = this.container) === null || _a === void 0 ? void 0 : _a.focus(options);
|
|
38
|
+
}
|
|
39
|
+
click() {
|
|
40
|
+
var _a;
|
|
41
|
+
(_a = this.container) === null || _a === void 0 ? void 0 : _a.click();
|
|
42
|
+
}
|
|
43
|
+
confirmSuggestion() {
|
|
44
|
+
this.dispatchEvent(new SuggestionSelectedEvent(this.getValue()));
|
|
45
|
+
}
|
|
46
|
+
getValue() {
|
|
47
|
+
return this.value || this.textContent;
|
|
48
|
+
}
|
|
49
|
+
get textContent() {
|
|
50
|
+
return this.assignedNodes.map(n => n.textContent).join("").trim();
|
|
51
|
+
}
|
|
52
|
+
onKeyDown(event) {
|
|
53
|
+
if (["Enter", " "].includes(event.key)) {
|
|
54
|
+
event.preventDefault();
|
|
55
|
+
event.stopPropagation();
|
|
56
|
+
this.confirmSuggestion();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
FtTextFieldSuggestion.elementDefinitions = {
|
|
61
|
+
"ft-ripple": FtRipple,
|
|
62
|
+
"ft-typography": FtTypography,
|
|
63
|
+
"ft-icon": FtIcon,
|
|
64
|
+
};
|
|
65
|
+
FtTextFieldSuggestion.styles = suggestionStyles;
|
|
66
|
+
__decorate([
|
|
67
|
+
property()
|
|
68
|
+
], FtTextFieldSuggestion.prototype, "value", void 0);
|
|
69
|
+
__decorate([
|
|
70
|
+
query(".ft-text-field-suggestion")
|
|
71
|
+
], FtTextFieldSuggestion.prototype, "container", void 0);
|
|
72
|
+
__decorate([
|
|
73
|
+
queryAssignedNodes()
|
|
74
|
+
], FtTextFieldSuggestion.prototype, "assignedNodes", void 0);
|
|
75
|
+
//# sourceMappingURL=ft-text-field-suggestion.js.map
|
|
@@ -11,6 +11,11 @@ export declare const FtTextFieldCssVariables: {
|
|
|
11
11
|
colorError: import("@fluid-topics/ft-wc-utils").FtCssVariable;
|
|
12
12
|
prefixColor: import("@fluid-topics/ft-wc-utils").FtCssVariable;
|
|
13
13
|
iconColor: import("@fluid-topics/ft-wc-utils").FtCssVariable;
|
|
14
|
+
floatingZIndex: import("@fluid-topics/ft-wc-utils").FtCssVariable;
|
|
15
|
+
colorSurface: import("@fluid-topics/ft-wc-utils").FtCssVariable;
|
|
16
|
+
colorOutline: import("@fluid-topics/ft-wc-utils").FtCssVariable;
|
|
17
|
+
elevation02: import("@fluid-topics/ft-wc-utils").FtCssVariable;
|
|
18
|
+
suggestSize: import("@fluid-topics/ft-wc-utils").FtCssVariable;
|
|
14
19
|
};
|
|
15
20
|
export declare const styles: import("lit").CSSResult;
|
|
16
21
|
//# sourceMappingURL=ft-text-field.css.d.ts.map
|
|
@@ -16,6 +16,11 @@ export const FtTextFieldCssVariables = {
|
|
|
16
16
|
colorError: FtCssVariableFactory.external(designSystemVariables.colorError, "Design system"),
|
|
17
17
|
prefixColor: FtCssVariableFactory.extend("--ft-text-field-prefix-color", designSystemVariables.colorOnSurfaceMedium),
|
|
18
18
|
iconColor: FtCssVariableFactory.extend("--ft-text-field-icon-color", designSystemVariables.colorOnSurfaceMedium),
|
|
19
|
+
floatingZIndex: FtCssVariableFactory.create("--ft-text-field-floating-components-z-index", "NUMBER", "3"),
|
|
20
|
+
colorSurface: FtCssVariableFactory.external(designSystemVariables.colorSurface, "Design system"),
|
|
21
|
+
colorOutline: FtCssVariableFactory.external(designSystemVariables.colorOutline, "Design system"),
|
|
22
|
+
elevation02: FtCssVariableFactory.external(designSystemVariables.elevation02, "Design system"),
|
|
23
|
+
suggestSize: FtCssVariableFactory.create("--ft-text-field-suggest-size", "SIZE", "300px"),
|
|
19
24
|
};
|
|
20
25
|
// language=CSS
|
|
21
26
|
export const styles = css `
|
|
@@ -27,6 +32,7 @@ export const styles = css `
|
|
|
27
32
|
display: flex;
|
|
28
33
|
flex-direction: column;
|
|
29
34
|
align-items: stretch;
|
|
35
|
+
position: relative;
|
|
30
36
|
}
|
|
31
37
|
|
|
32
38
|
ft-input-label {
|
|
@@ -48,6 +54,10 @@ export const styles = css `
|
|
|
48
54
|
display: flex;
|
|
49
55
|
align-items: center;
|
|
50
56
|
overflow: hidden;
|
|
57
|
+
padding: 0 ${FtTextFieldCssVariables.horizontalSpacing};
|
|
58
|
+
|
|
59
|
+
${setVariable(FtTypographyBody1CssVariables.fontSize, FtTextFieldCssVariables.fontSize)};
|
|
60
|
+
${setVariable(FtTypographyBody1CssVariables.lineHeight, FtTextFieldCssVariables.fontSize)};
|
|
51
61
|
}
|
|
52
62
|
|
|
53
63
|
.ft-text-field--input-panel ft-ripple {
|
|
@@ -55,31 +65,22 @@ export const styles = css `
|
|
|
55
65
|
${setVariable(FtRippleCssVariables.opacityContentOnSurfacePressed, "0.04")};
|
|
56
66
|
}
|
|
57
67
|
|
|
58
|
-
.ft-text-field--input-
|
|
59
|
-
flex-grow: 1;
|
|
60
|
-
flex-shrink: 1;
|
|
61
|
-
|
|
62
|
-
display: flex;
|
|
63
|
-
align-items: center;
|
|
64
|
-
|
|
65
|
-
${setVariable(FtTypographyBody1CssVariables.fontSize, FtTextFieldCssVariables.fontSize)};
|
|
66
|
-
${setVariable(FtTypographyBody1CssVariables.lineHeight, FtTextFieldCssVariables.fontSize)};
|
|
67
|
-
|
|
68
|
-
padding: 0 ${FtTextFieldCssVariables.horizontalSpacing};
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
.ft-text-field--filled:not(.ft-text-field--no-label) .ft-text-field--input-wrapper {
|
|
68
|
+
.ft-text-field--filled.ft-text-field--with-label .ft-text-field--input-panel {
|
|
72
69
|
align-items: flex-end;
|
|
73
70
|
padding: 0 ${FtTextFieldCssVariables.horizontalSpacing} ${FtTextFieldCssVariables.verticalSpacing} ${FtTextFieldCssVariables.horizontalSpacing};
|
|
74
71
|
}
|
|
75
72
|
|
|
76
73
|
.ft-text-field--prefix {
|
|
77
|
-
|
|
78
|
-
|
|
74
|
+
color: ${FtTextFieldCssVariables.prefixColor};
|
|
75
|
+
margin-right: 2px;
|
|
76
|
+
flex-shrink: 1;
|
|
77
|
+
overflow: hidden;
|
|
78
|
+
white-space: nowrap;
|
|
79
|
+
text-overflow: ellipsis;
|
|
79
80
|
}
|
|
80
81
|
|
|
81
|
-
.ft-text-field--with-
|
|
82
|
-
display:
|
|
82
|
+
.ft-text-field--with-label:not(.ft-text-field--raised-label) .ft-text-field--prefix {
|
|
83
|
+
display: none;
|
|
83
84
|
}
|
|
84
85
|
|
|
85
86
|
.ft-text-field--input {
|
|
@@ -95,7 +96,7 @@ export const styles = css `
|
|
|
95
96
|
background: none;
|
|
96
97
|
}
|
|
97
98
|
|
|
98
|
-
.ft-text-field--filled
|
|
99
|
+
.ft-text-field--filled.ft-text-field--with-label .ft-text-field--input {
|
|
99
100
|
padding-bottom: 0;
|
|
100
101
|
padding-top: calc(${FtTextFieldCssVariables.labelSize} + 2 * ${FtTextFieldCssVariables.verticalSpacing});
|
|
101
102
|
}
|
|
@@ -109,10 +110,6 @@ export const styles = css `
|
|
|
109
110
|
color: ${FtTextFieldCssVariables.colorOnSurfaceDisabled};
|
|
110
111
|
}
|
|
111
112
|
|
|
112
|
-
.ft-text-field:not(.ft-text-field--disabled) .ft-text-field--input-panel {
|
|
113
|
-
cursor: pointer;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
113
|
.ft-text-field:not(.ft-text-field--disabled):focus-within ft-input-label {
|
|
117
114
|
${setVariable(FtInputLabelCssVariables.borderColor, FtTextFieldCssVariables.colorPrimary)};
|
|
118
115
|
${setVariable(FtInputLabelCssVariables.textColor, FtTextFieldCssVariables.colorPrimary)};
|
|
@@ -138,8 +135,41 @@ export const styles = css `
|
|
|
138
135
|
}
|
|
139
136
|
|
|
140
137
|
.ft-text-field--icon {
|
|
141
|
-
|
|
138
|
+
align-self: center;
|
|
139
|
+
margin-left: 8px;
|
|
142
140
|
color: ${FtTextFieldCssVariables.iconColor};
|
|
143
141
|
}
|
|
142
|
+
|
|
143
|
+
.ft-text-field--container {
|
|
144
|
+
position: relative;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.ft-text-field--suggestions {
|
|
148
|
+
display: none;
|
|
149
|
+
flex-direction: column;
|
|
150
|
+
position: absolute;
|
|
151
|
+
left: 0;
|
|
152
|
+
right: 0;
|
|
153
|
+
z-index: ${FtTextFieldCssVariables.floatingZIndex};
|
|
154
|
+
background: ${FtTextFieldCssVariables.colorSurface};
|
|
155
|
+
border: 1px solid ${FtTextFieldCssVariables.colorOutline};
|
|
156
|
+
border-radius: 0 0 ${FtTextFieldCssVariables.borderRadiusS} ${FtTextFieldCssVariables.borderRadiusS};
|
|
157
|
+
box-shadow: ${FtTextFieldCssVariables.elevation02};
|
|
158
|
+
outline: none;
|
|
159
|
+
max-height: ${FtTextFieldCssVariables.suggestSize};
|
|
160
|
+
overflow-y: auto;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.ft-text-field--suggestions:not(.ft-text-field--suggestions-on-top) {
|
|
164
|
+
top: 100%;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.ft-text-field--suggestions.ft-text-field--suggestions-on-top {
|
|
168
|
+
bottom: 100%;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.ft-text-field:not(.ft-text-field--hide-suggestions):focus-within .ft-text-field--suggestions {
|
|
172
|
+
display: flex;
|
|
173
|
+
}
|
|
144
174
|
`;
|
|
145
175
|
//# sourceMappingURL=ft-text-field.css.js.map
|
package/build/ft-text-field.d.ts
CHANGED
|
@@ -1,24 +1,39 @@
|
|
|
1
1
|
import { PropertyValues } from "lit";
|
|
2
2
|
import { ElementDefinitionsMap, FtLitElement } from "@fluid-topics/ft-wc-utils";
|
|
3
3
|
import { FtTextFieldProperties } from "./ft-text-field.properties";
|
|
4
|
+
import type { FtTextFieldSuggestion } from "./ft-text-field-suggestion";
|
|
4
5
|
export declare class FtTextField extends FtLitElement implements FtTextFieldProperties {
|
|
5
6
|
static elementDefinitions: ElementDefinitionsMap;
|
|
6
7
|
static styles: import("lit").CSSResult[];
|
|
7
|
-
label
|
|
8
|
+
label?: string;
|
|
8
9
|
value: string;
|
|
9
|
-
helper
|
|
10
|
+
helper?: string;
|
|
10
11
|
outlined: boolean;
|
|
11
12
|
disabled: boolean;
|
|
12
13
|
error: boolean;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
prefix: string | null;
|
|
15
|
+
icon?: string;
|
|
16
|
+
iconVariant?: string;
|
|
17
|
+
filterSuggestions: boolean;
|
|
18
|
+
focused: boolean;
|
|
19
|
+
suggestionsOnTop: boolean;
|
|
20
|
+
hideSuggestions: boolean;
|
|
21
|
+
visibleSuggestions: FtTextFieldSuggestion[];
|
|
22
|
+
input?: HTMLInputElement;
|
|
23
|
+
suggestionsContainer?: HTMLElement;
|
|
24
|
+
suggestions: FtTextFieldSuggestion[];
|
|
18
25
|
focus(): void;
|
|
19
26
|
protected render(): import("lit-html").TemplateResult<1>;
|
|
20
27
|
protected updated(props: PropertyValues): void;
|
|
28
|
+
private filterSuggestionsIfNeeded;
|
|
29
|
+
protected contentAvailableCallback(props: PropertyValues): void;
|
|
21
30
|
private updateValueFromInputField;
|
|
22
|
-
private
|
|
31
|
+
private handleInput;
|
|
32
|
+
private handleClick;
|
|
33
|
+
setValue(newValue: string, fireEvent?: boolean): void;
|
|
34
|
+
private handleKeyboardNavigation;
|
|
35
|
+
private onSuggestionSelected;
|
|
36
|
+
private onFocus;
|
|
37
|
+
private onInputBlur;
|
|
23
38
|
}
|
|
24
39
|
//# sourceMappingURL=ft-text-field.d.ts.map
|
package/build/ft-text-field.js
CHANGED
|
@@ -4,8 +4,8 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { html } from "lit";
|
|
8
|
-
import { property, query, state } from "lit/decorators.js";
|
|
7
|
+
import { html, nothing } from "lit";
|
|
8
|
+
import { property, query, queryAssignedElements, state } from "lit/decorators.js";
|
|
9
9
|
import { classMap } from "lit/directives/class-map.js";
|
|
10
10
|
import { FtLitElement } from "@fluid-topics/ft-wc-utils";
|
|
11
11
|
import { FtTypography, FtTypographyBody1 } from "@fluid-topics/ft-typography";
|
|
@@ -16,16 +16,16 @@ import { styles } from "./ft-text-field.css";
|
|
|
16
16
|
export class FtTextField extends FtLitElement {
|
|
17
17
|
constructor() {
|
|
18
18
|
super(...arguments);
|
|
19
|
-
this.label = "";
|
|
20
19
|
this.value = "";
|
|
21
|
-
this.helper = "";
|
|
22
20
|
this.outlined = false;
|
|
23
21
|
this.disabled = false;
|
|
24
22
|
this.error = false;
|
|
25
|
-
this.prefix =
|
|
26
|
-
this.
|
|
27
|
-
this.iconVariant = "";
|
|
23
|
+
this.prefix = null;
|
|
24
|
+
this.filterSuggestions = false;
|
|
28
25
|
this.focused = false;
|
|
26
|
+
this.suggestionsOnTop = false;
|
|
27
|
+
this.hideSuggestions = false;
|
|
28
|
+
this.visibleSuggestions = [];
|
|
29
29
|
}
|
|
30
30
|
focus() {
|
|
31
31
|
var _a;
|
|
@@ -38,62 +38,136 @@ export class FtTextField extends FtLitElement {
|
|
|
38
38
|
"ft-text-field--outlined": this.outlined,
|
|
39
39
|
"ft-text-field--disabled": this.disabled,
|
|
40
40
|
"ft-text-field--has-value": !!this.value,
|
|
41
|
-
"ft-text-field--
|
|
41
|
+
"ft-text-field--with-label": !!this.label,
|
|
42
42
|
"ft-text-field--in-error": this.error,
|
|
43
43
|
"ft-text-field--with-prefix": !!this.prefix,
|
|
44
|
+
"ft-text-field--hide-suggestions": this.visibleSuggestions.length === 0 || this.hideSuggestions,
|
|
44
45
|
"ft-text-field--raised-label": this.focused || this.value != "",
|
|
45
46
|
};
|
|
46
47
|
return html `
|
|
47
48
|
<div class="${classMap(classes)}">
|
|
48
|
-
<div class="ft-text-field--main-panel"
|
|
49
|
+
<div class="ft-text-field--main-panel"
|
|
50
|
+
@keydown=${this.handleKeyboardNavigation}>
|
|
49
51
|
<ft-input-label text="${this.label}"
|
|
50
52
|
?disabled=${this.disabled}
|
|
51
53
|
?outlined=${this.outlined}
|
|
52
54
|
?raised=${this.focused || this.value != ""}
|
|
53
|
-
?error=${this.error}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
aria-label="${this.label}">
|
|
57
|
-
${this.outlined ? null : html `
|
|
55
|
+
?error=${this.error}></ft-input-label>
|
|
56
|
+
<div class="ft-text-field--input-panel">
|
|
57
|
+
${this.outlined ? nothing : html `
|
|
58
58
|
<ft-ripple ?disabled=${this.disabled} activated></ft-ripple>
|
|
59
59
|
`}
|
|
60
|
-
<
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
</div>
|
|
60
|
+
<ft-typography class="ft-text-field--prefix" vaiant="body1">${this.prefix}</ft-typography>
|
|
61
|
+
<input type="text"
|
|
62
|
+
aria-label="${this.label}"
|
|
63
|
+
class="ft-typography--body1 ft-text-field--input"
|
|
64
|
+
?disabled=${this.disabled}
|
|
65
|
+
.value=${this.value}
|
|
66
|
+
@click=${this.handleClick}
|
|
67
|
+
@change=${this.updateValueFromInputField}
|
|
68
|
+
@keyup=${this.handleInput}
|
|
69
|
+
@focus=${this.onFocus}
|
|
70
|
+
@blur=${this.onInputBlur}/>
|
|
72
71
|
${this.icon ? html `
|
|
73
|
-
<ft-icon class="ft-text-field--icon"
|
|
74
|
-
|
|
72
|
+
<ft-icon class="ft-text-field--icon"
|
|
73
|
+
.variant=${this.iconVariant}
|
|
74
|
+
.value=${this.icon}
|
|
75
|
+
@click=${() => { var _a; return (_a = this.input) === null || _a === void 0 ? void 0 : _a.focus(); }}></ft-icon>
|
|
76
|
+
` : nothing}
|
|
77
|
+
</div>
|
|
78
|
+
<div class="ft-text-field--suggestions ${this.suggestionsOnTop ? "ft-text-field--suggestions-on-top" : ""}"
|
|
79
|
+
@suggestion-selected=${this.onSuggestionSelected}>
|
|
80
|
+
<slot @slotchange=${() => this.filterSuggestionsIfNeeded()}></slot>
|
|
75
81
|
</div>
|
|
76
82
|
</div>
|
|
77
83
|
${this.helper ? html `
|
|
78
|
-
<ft-typography class="ft-text-field--helper-text" variant="caption"
|
|
79
|
-
|
|
84
|
+
<ft-typography class="ft-text-field--helper-text" variant="caption">
|
|
85
|
+
${this.helper}
|
|
86
|
+
</ft-typography>
|
|
87
|
+
` : nothing}
|
|
80
88
|
</div>
|
|
81
89
|
`;
|
|
82
90
|
}
|
|
83
91
|
updated(props) {
|
|
84
92
|
super.updated(props);
|
|
85
|
-
if (props.has("value")) {
|
|
86
|
-
this.
|
|
93
|
+
if (props.has("value") || props.has("filterSuggestions")) {
|
|
94
|
+
this.filterSuggestionsIfNeeded();
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
filterSuggestionsIfNeeded() {
|
|
98
|
+
if (this.filterSuggestions) {
|
|
99
|
+
this.suggestions.forEach(s => s.hidden = !s.getValue().toLowerCase().includes(this.value.toLowerCase()));
|
|
100
|
+
this.visibleSuggestions = this.suggestions.filter(s => !s.hidden);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
this.visibleSuggestions = this.suggestions;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
contentAvailableCallback(props) {
|
|
107
|
+
var _a, _b;
|
|
108
|
+
super.contentAvailableCallback(props);
|
|
109
|
+
if (!this.hideSuggestions && this.visibleSuggestions.length > 0) {
|
|
110
|
+
const rect = (_a = this.input) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
|
|
111
|
+
const suggestRect = (_b = this.suggestionsContainer) === null || _b === void 0 ? void 0 : _b.getBoundingClientRect();
|
|
112
|
+
if (rect && suggestRect) {
|
|
113
|
+
this.suggestionsOnTop = rect.bottom + suggestRect.height > window.innerHeight && rect.top - suggestRect.height > 0;
|
|
114
|
+
}
|
|
87
115
|
}
|
|
88
116
|
}
|
|
89
117
|
updateValueFromInputField() {
|
|
90
118
|
var _a;
|
|
91
|
-
this.
|
|
92
|
-
this.dispatchEvent(new CustomEvent("change", { detail: this.value }));
|
|
119
|
+
this.setValue(((_a = this.input) === null || _a === void 0 ? void 0 : _a.value) || "", true);
|
|
93
120
|
}
|
|
94
|
-
|
|
121
|
+
handleInput() {
|
|
95
122
|
var _a;
|
|
96
|
-
|
|
123
|
+
const newValue = ((_a = this.input) === null || _a === void 0 ? void 0 : _a.value) || "";
|
|
124
|
+
if (this.value !== newValue) {
|
|
125
|
+
this.hideSuggestions = false;
|
|
126
|
+
this.value = newValue;
|
|
127
|
+
this.dispatchEvent(new CustomEvent("live-change", { detail: this.value }));
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
handleClick() {
|
|
131
|
+
this.hideSuggestions = false;
|
|
132
|
+
}
|
|
133
|
+
setValue(newValue, fireEvent) {
|
|
134
|
+
this.value = newValue;
|
|
135
|
+
if (fireEvent) {
|
|
136
|
+
this.dispatchEvent(new CustomEvent("change", { detail: this.value }));
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
handleKeyboardNavigation(event) {
|
|
140
|
+
var _a;
|
|
141
|
+
if ((event.key === "ArrowDown" || event.key === "ArrowUp")) {
|
|
142
|
+
event.preventDefault();
|
|
143
|
+
event.stopPropagation();
|
|
144
|
+
this.hideSuggestions = false;
|
|
145
|
+
const currentSuggestion = this.visibleSuggestions.findIndex((element) => element.matches((":focus-within")));
|
|
146
|
+
let target;
|
|
147
|
+
if (event.key === "ArrowDown") {
|
|
148
|
+
target = currentSuggestion < this.visibleSuggestions.length - 1 ? currentSuggestion + 1 : 0;
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
target = currentSuggestion > 0 ? currentSuggestion - 1 : this.visibleSuggestions.length - 1;
|
|
152
|
+
}
|
|
153
|
+
(_a = this.visibleSuggestions[target]) === null || _a === void 0 ? void 0 : _a.focus();
|
|
154
|
+
}
|
|
155
|
+
if (event.key == "Escape" || event.key == "Enter") {
|
|
156
|
+
this.hideSuggestions = true;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
onSuggestionSelected(event) {
|
|
160
|
+
var _a;
|
|
161
|
+
this.setValue(event.detail, true);
|
|
162
|
+
(_a = this.input) === null || _a === void 0 ? void 0 : _a.focus();
|
|
163
|
+
setTimeout(() => this.hideSuggestions = true, 0);
|
|
164
|
+
}
|
|
165
|
+
onFocus() {
|
|
166
|
+
this.focused = true;
|
|
167
|
+
this.hideSuggestions = false;
|
|
168
|
+
}
|
|
169
|
+
onInputBlur() {
|
|
170
|
+
this.focused = false;
|
|
97
171
|
}
|
|
98
172
|
}
|
|
99
173
|
FtTextField.elementDefinitions = {
|
|
@@ -108,13 +182,13 @@ FtTextField.styles = [
|
|
|
108
182
|
styles
|
|
109
183
|
];
|
|
110
184
|
__decorate([
|
|
111
|
-
property(
|
|
185
|
+
property()
|
|
112
186
|
], FtTextField.prototype, "label", void 0);
|
|
113
187
|
__decorate([
|
|
114
|
-
property(
|
|
188
|
+
property()
|
|
115
189
|
], FtTextField.prototype, "value", void 0);
|
|
116
190
|
__decorate([
|
|
117
|
-
property(
|
|
191
|
+
property()
|
|
118
192
|
], FtTextField.prototype, "helper", void 0);
|
|
119
193
|
__decorate([
|
|
120
194
|
property({ type: Boolean })
|
|
@@ -126,18 +200,36 @@ __decorate([
|
|
|
126
200
|
property({ type: Boolean })
|
|
127
201
|
], FtTextField.prototype, "error", void 0);
|
|
128
202
|
__decorate([
|
|
129
|
-
|
|
130
|
-
], FtTextField.prototype, "input", void 0);
|
|
131
|
-
__decorate([
|
|
132
|
-
property({ type: String })
|
|
203
|
+
property()
|
|
133
204
|
], FtTextField.prototype, "prefix", void 0);
|
|
134
205
|
__decorate([
|
|
135
|
-
property(
|
|
206
|
+
property()
|
|
136
207
|
], FtTextField.prototype, "icon", void 0);
|
|
137
208
|
__decorate([
|
|
138
|
-
property(
|
|
209
|
+
property()
|
|
139
210
|
], FtTextField.prototype, "iconVariant", void 0);
|
|
211
|
+
__decorate([
|
|
212
|
+
property({ type: Boolean })
|
|
213
|
+
], FtTextField.prototype, "filterSuggestions", void 0);
|
|
140
214
|
__decorate([
|
|
141
215
|
state()
|
|
142
216
|
], FtTextField.prototype, "focused", void 0);
|
|
217
|
+
__decorate([
|
|
218
|
+
state()
|
|
219
|
+
], FtTextField.prototype, "suggestionsOnTop", void 0);
|
|
220
|
+
__decorate([
|
|
221
|
+
state()
|
|
222
|
+
], FtTextField.prototype, "hideSuggestions", void 0);
|
|
223
|
+
__decorate([
|
|
224
|
+
state()
|
|
225
|
+
], FtTextField.prototype, "visibleSuggestions", void 0);
|
|
226
|
+
__decorate([
|
|
227
|
+
query(".ft-text-field--input")
|
|
228
|
+
], FtTextField.prototype, "input", void 0);
|
|
229
|
+
__decorate([
|
|
230
|
+
query(".ft-text-field--suggestions")
|
|
231
|
+
], FtTextField.prototype, "suggestionsContainer", void 0);
|
|
232
|
+
__decorate([
|
|
233
|
+
queryAssignedElements({ selector: "ft-text-field-suggestion" })
|
|
234
|
+
], FtTextField.prototype, "suggestions", void 0);
|
|
143
235
|
//# sourceMappingURL=ft-text-field.js.map
|