@fluid-topics/ft-number-field 1.1.19

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/README.md ADDED
@@ -0,0 +1,19 @@
1
+ A number field input component.
2
+
3
+ ## Install
4
+
5
+ ```shell
6
+ npm install @fluid-topics/ft-number-field
7
+ yarn add @fluid-topics/ft-number-field
8
+ ```
9
+
10
+ ## Usage
11
+
12
+ ```typescript
13
+ import { html } from "lit"
14
+ import "@fluid-topics/ft-number-field"
15
+
16
+ function render() {
17
+ return html` <ft-number-field foo="bar"></ft-number-field> `
18
+ }
19
+ ```
@@ -0,0 +1,13 @@
1
+ export declare const FtNumberFieldCssVariables: {
2
+ fontSize: import("@fluid-topics/ft-wc-utils").FtCssVariable;
3
+ labelSize: import("@fluid-topics/ft-wc-utils").FtCssVariable;
4
+ verticalSpacing: import("@fluid-topics/ft-wc-utils").FtCssVariable;
5
+ horizontalSpacing: import("@fluid-topics/ft-wc-utils").FtCssVariable;
6
+ colorPrimary: import("@fluid-topics/ft-wc-utils").FtCssVariable;
7
+ colorOnSurface: import("@fluid-topics/ft-wc-utils").FtCssVariable;
8
+ colorOnSurfaceDisabled: import("@fluid-topics/ft-wc-utils").FtCssVariable;
9
+ borderRadiusS: import("@fluid-topics/ft-wc-utils").FtCssVariable;
10
+ colorSurface: import("@fluid-topics/ft-wc-utils").FtCssVariable;
11
+ colorOutline: import("@fluid-topics/ft-wc-utils").FtCssVariable;
12
+ };
13
+ export declare const styles: import("lit").CSSResult;
@@ -0,0 +1,108 @@
1
+ import { css } from "lit";
2
+ import { designSystemVariables, FtCssVariableFactory, setVariable } from "@fluid-topics/ft-wc-utils";
3
+ import { FtTypographyBody1CssVariables } from "@fluid-topics/ft-typography/build/ft-typography.css";
4
+ import { FtInputLabelCssVariables } from "@fluid-topics/ft-input-label/build/ft-input-label.css";
5
+ import { FtRippleCssVariables } from "@fluid-topics/ft-ripple/build/ft-ripple.css";
6
+ export const FtNumberFieldCssVariables = {
7
+ fontSize: FtCssVariableFactory.create("--ft-number-field-font-size", "", "SIZE", "14px"),
8
+ labelSize: FtCssVariableFactory.create("--ft-number-field-label-size", "", "SIZE", "11px"),
9
+ verticalSpacing: FtCssVariableFactory.create("--ft-number-field-vertical-spacing", "", "SIZE", "4px"),
10
+ horizontalSpacing: FtCssVariableFactory.create("--ft-number-field-horizontal-spacing", "", "SIZE", "16px"),
11
+ colorPrimary: FtCssVariableFactory.external(designSystemVariables.colorPrimary, "Design system"),
12
+ colorOnSurface: FtCssVariableFactory.external(designSystemVariables.colorOnSurface, "Design system"),
13
+ colorOnSurfaceDisabled: FtCssVariableFactory.external(designSystemVariables.colorOnSurfaceDisabled, "Design system"),
14
+ borderRadiusS: FtCssVariableFactory.external(designSystemVariables.borderRadiusS, "Design system"),
15
+ colorSurface: FtCssVariableFactory.external(designSystemVariables.colorSurface, "Design system"),
16
+ colorOutline: FtCssVariableFactory.external(designSystemVariables.colorOutline, "Design system"),
17
+ };
18
+ // language=CSS
19
+ export const styles = css `
20
+ *:focus {
21
+ outline: none;
22
+ }
23
+
24
+ .ft-number-field {
25
+ display: flex;
26
+ flex-direction: column;
27
+ align-items: stretch;
28
+ position: relative;
29
+ }
30
+
31
+ ft-input-label {
32
+ ${setVariable(FtInputLabelCssVariables.fontSize, FtNumberFieldCssVariables.fontSize)};
33
+ ${setVariable(FtInputLabelCssVariables.raisedFontSize, FtNumberFieldCssVariables.labelSize)};
34
+ ${setVariable(FtInputLabelCssVariables.verticalSpacing, FtNumberFieldCssVariables.verticalSpacing)};
35
+ ${setVariable(FtInputLabelCssVariables.horizontalSpacing, FtNumberFieldCssVariables.horizontalSpacing)};
36
+ }
37
+
38
+ .ft-number-field--main-panel {
39
+ position: relative;
40
+ display: flex;
41
+ height: calc(4 * ${FtNumberFieldCssVariables.verticalSpacing} + ${FtNumberFieldCssVariables.labelSize} + ${FtNumberFieldCssVariables.fontSize});
42
+ }
43
+
44
+ .ft-number-field--input-panel {
45
+ flex-grow: 1;
46
+ position: relative;
47
+ display: flex;
48
+ align-items: center;
49
+ overflow: hidden;
50
+ padding: 0 ${FtNumberFieldCssVariables.horizontalSpacing};
51
+
52
+ ${setVariable(FtTypographyBody1CssVariables.fontSize, FtNumberFieldCssVariables.fontSize)};
53
+ ${setVariable(FtTypographyBody1CssVariables.lineHeight, FtNumberFieldCssVariables.fontSize)};
54
+ }
55
+
56
+ .ft-number-field--input-panel ft-ripple {
57
+ ${setVariable(FtRippleCssVariables.opacityContentOnSurfaceHover, "0.08")};
58
+ ${setVariable(FtRippleCssVariables.opacityContentOnSurfacePressed, "0.04")};
59
+ }
60
+
61
+ .ft-number-field--filled.ft-number-field--with-label .ft-number-field--input-panel {
62
+ align-items: flex-end;
63
+ padding: 0 ${FtNumberFieldCssVariables.horizontalSpacing} ${FtNumberFieldCssVariables.verticalSpacing} ${FtNumberFieldCssVariables.horizontalSpacing};
64
+ }
65
+
66
+ .ft-number-field--input {
67
+ display: block;
68
+ position: relative;
69
+ flex-grow: 1;
70
+ flex-shrink: 1;
71
+ min-width: 0; /* flex sets this to auto an prevents input from shrinking properly */
72
+
73
+ color: ${FtNumberFieldCssVariables.colorOnSurface};
74
+ padding: calc(2 * ${FtNumberFieldCssVariables.verticalSpacing}) 0;
75
+ border: none;
76
+ background: none;
77
+
78
+ -moz-appearance: textfield;
79
+ }
80
+
81
+ .ft-number-field--filled.ft-number-field--with-label .ft-number-field--input {
82
+ padding-bottom: 0;
83
+ padding-top: calc(${FtNumberFieldCssVariables.labelSize} + 2 * ${FtNumberFieldCssVariables.verticalSpacing});
84
+ }
85
+
86
+ .ft-number-field--disabled .ft-number-field--input {
87
+ color: ${FtNumberFieldCssVariables.colorOnSurfaceDisabled};
88
+ }
89
+
90
+ .ft-number-field:not(.ft-number-field--disabled):focus-within ft-input-label {
91
+ ${setVariable(FtInputLabelCssVariables.borderColor, FtNumberFieldCssVariables.colorPrimary)};
92
+ ${setVariable(FtInputLabelCssVariables.textColor, FtNumberFieldCssVariables.colorPrimary)};
93
+ }
94
+
95
+ .ft-number-field--filled .ft-number-field--input-panel {
96
+ border-radius: ${FtNumberFieldCssVariables.borderRadiusS} ${FtNumberFieldCssVariables.borderRadiusS} 0 0;
97
+ }
98
+
99
+ .ft-number-field--outlined .ft-number-field--input-panel {
100
+ border-radius: ${FtNumberFieldCssVariables.borderRadiusS};
101
+ }
102
+
103
+ input::-webkit-outer-spin-button,
104
+ input::-webkit-inner-spin-button {
105
+ -webkit-appearance: none;
106
+ margin: 0;
107
+ }
108
+ `;
@@ -0,0 +1,24 @@
1
+ import { PropertyValues } from "lit";
2
+ import { ElementDefinitionsMap, FtLitElement } from "@fluid-topics/ft-wc-utils";
3
+ import { FtNumberFieldProperties } from "./ft-number-field.properties";
4
+ export declare class FtNumberField extends FtLitElement implements FtNumberFieldProperties {
5
+ static elementDefinitions: ElementDefinitionsMap;
6
+ static styles: import("lit").CSSResult;
7
+ label?: string;
8
+ value?: number;
9
+ outlined: boolean;
10
+ disabled: boolean;
11
+ min?: number;
12
+ max?: number;
13
+ focused: boolean;
14
+ input?: HTMLInputElement;
15
+ mainPanel?: HTMLElement;
16
+ protected render(): import("lit").TemplateResult<1>;
17
+ protected update(changedProperties: PropertyValues): void;
18
+ lowerBound(value: number): number;
19
+ upperBound(value: number): number;
20
+ private onChange;
21
+ private setValue;
22
+ private onFocus;
23
+ private onMainPanelBlur;
24
+ }
@@ -0,0 +1,131 @@
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 { html, nothing } from "lit";
8
+ import { FtLitElement, optionalNumberProperty } from "@fluid-topics/ft-wc-utils";
9
+ import { styles } from "./ft-number-field.css";
10
+ import { property, query, state } from "lit/decorators.js";
11
+ import { classMap } from "lit/directives/class-map.js";
12
+ import { FtInputLabel } from "@fluid-topics/ft-input-label";
13
+ import { FtRipple } from "@fluid-topics/ft-ripple";
14
+ import { FtTypography } from "@fluid-topics/ft-typography";
15
+ class FtNumberField extends FtLitElement {
16
+ constructor() {
17
+ super(...arguments);
18
+ this.outlined = false;
19
+ this.disabled = false;
20
+ this.focused = false;
21
+ }
22
+ render() {
23
+ const classes = {
24
+ "ft-number-field": true,
25
+ "ft-number-field--filled": !this.outlined,
26
+ "ft-number-field--outlined": this.outlined,
27
+ "ft-number-field--disabled": this.disabled,
28
+ "ft-number-field--has-value": this.value != null,
29
+ "ft-number-field--with-label": !!this.label,
30
+ };
31
+ return html `
32
+ <div class="${classMap(classes)}">
33
+ <div class="ft-number-field--main-panel"
34
+ @focusout=${this.onMainPanelBlur}>
35
+ <ft-input-label text="${this.label}"
36
+ ?disabled=${this.disabled}
37
+ ?outlined=${this.outlined}
38
+ ?raised=${this.focused || this.value != null}>
39
+ </ft-input-label>
40
+ <div class="ft-number-field--input-panel">
41
+ ${this.outlined ? nothing : html `
42
+ <ft-ripple ?disabled=${this.disabled} activated></ft-ripple>
43
+ `}
44
+ <input type="number"
45
+ .min=${this.min}
46
+ .max=${this.max}
47
+ aria-label="${this.label}"
48
+ class="ft-typography--body1 ft-number-field--input"
49
+ part="input"
50
+ ?disabled=${this.disabled}
51
+ .value=${this.value}
52
+ @change=${this.onChange}
53
+ @focus=${this.onFocus}
54
+ />
55
+ </div>
56
+ </div>
57
+ </div>
58
+ `;
59
+ }
60
+ update(changedProperties) {
61
+ super.update(changedProperties);
62
+ if (changedProperties.has("max") || changedProperties.has("min")) {
63
+ this.setValue(this.value);
64
+ }
65
+ }
66
+ lowerBound(value) {
67
+ return this.min != undefined ? Math.max(this.min, value) : value;
68
+ }
69
+ upperBound(value) {
70
+ return this.max != undefined ? Math.min(this.max, value) : value;
71
+ }
72
+ onChange(event) {
73
+ event.preventDefault();
74
+ event.stopPropagation();
75
+ this.setValue(+event.target.value);
76
+ }
77
+ setValue(value) {
78
+ let oldValue = this.value;
79
+ this.value = value;
80
+ let boundedValue = this.value == undefined ? undefined : this.lowerBound(this.upperBound(this.value));
81
+ setTimeout(() => {
82
+ this.value = boundedValue;
83
+ if (oldValue !== boundedValue) {
84
+ this.dispatchEvent(new CustomEvent("change", { detail: this.value }));
85
+ }
86
+ });
87
+ }
88
+ onFocus() {
89
+ this.focused = true;
90
+ }
91
+ onMainPanelBlur() {
92
+ var _a;
93
+ if (!((_a = this.mainPanel) === null || _a === void 0 ? void 0 : _a.matches(":focus-within"))) {
94
+ this.focused = false;
95
+ }
96
+ }
97
+ }
98
+ FtNumberField.elementDefinitions = {
99
+ "ft-input-label": FtInputLabel,
100
+ "ft-ripple": FtRipple,
101
+ "ft-typography": FtTypography,
102
+ };
103
+ FtNumberField.styles = styles;
104
+ __decorate([
105
+ property()
106
+ ], FtNumberField.prototype, "label", void 0);
107
+ __decorate([
108
+ optionalNumberProperty()
109
+ ], FtNumberField.prototype, "value", void 0);
110
+ __decorate([
111
+ property({ type: Boolean })
112
+ ], FtNumberField.prototype, "outlined", void 0);
113
+ __decorate([
114
+ property({ type: Boolean })
115
+ ], FtNumberField.prototype, "disabled", void 0);
116
+ __decorate([
117
+ optionalNumberProperty()
118
+ ], FtNumberField.prototype, "min", void 0);
119
+ __decorate([
120
+ optionalNumberProperty()
121
+ ], FtNumberField.prototype, "max", void 0);
122
+ __decorate([
123
+ state()
124
+ ], FtNumberField.prototype, "focused", void 0);
125
+ __decorate([
126
+ query(".ft-number-field--input")
127
+ ], FtNumberField.prototype, "input", void 0);
128
+ __decorate([
129
+ query(".ft-number-field--main-panel")
130
+ ], FtNumberField.prototype, "mainPanel", void 0);
131
+ export { FtNumberField };