-
Notifications
You must be signed in to change notification settings - Fork 25
/
input-percent.js
154 lines (143 loc) · 4.53 KB
/
input-percent.js
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
import './input-number.js';
import { css, html, LitElement } from 'lit';
import { FocusMixin } from '../../mixins/focus/focus-mixin.js';
import { FormElementMixin } from '../form/form-element-mixin.js';
import { ifDefined } from 'lit/directives/if-defined.js';
import { LabelledMixin } from '../../mixins/labelled/labelled-mixin.js';
import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
import { RtlMixin } from '../../mixins/rtl/rtl-mixin.js';
import { SkeletonMixin } from '../skeleton/skeleton-mixin.js';
/**
* This component wraps the "<d2l-input-number>" tag and is intended for inputting percent values.
* @slot after - Slot beside the input on the right side. Useful for an "icon" or "button-icon".
* @slot inline-help - Help text that will appear below the input. Use this only when other helpful cues are not sufficient, such as a carefully-worded label.
* @fires change - Dispatched when an alteration to the value is committed (typically after focus is lost) by the user. The `value` attribute reflects a JavaScript Number which is parsed from the formatted input value.
*/
class InputPercent extends FocusMixin(LabelledMixin(SkeletonMixin(FormElementMixin(LocalizeCoreElement(RtlMixin(LitElement)))))) {
static get properties() {
return {
/**
* @ignore
*/
// eslint-disable-next-line lit/no-native-attributes
autofocus: { type: Boolean },
/**
* Disables the input
* @type {boolean}
*/
disabled: { type: Boolean },
/**
* Restricts the maximum width of the input box without impacting the width of the label.
* @type {string}
*/
inputWidth: { attribute: 'input-width', type: String },
/**
* Hides the label visually. Hidden labels are still read by screen readers so make sure to set an appropriate label.
* @type {boolean}
*/
labelHidden: { type: Boolean, attribute: 'label-hidden' },
/**
* Maximum number of decimal values to show (rounds value up or down).
* @type {number}
*/
maxFractionDigits: { type: Number, attribute: 'max-fraction-digits' },
/**
* Minimum number of decimal values to show.
* @type {number}
*/
minFractionDigits: { type: Number, attribute: 'min-fraction-digits' },
/**
* Indicates that a value is required
* @type {boolean}
*/
required: { type: Boolean },
/**
* Value of the input
* @type {number}
*/
value: { type: Number }
};
}
static get styles() {
return [ super.styles,
css`
:host {
display: inline-block;
position: relative;
width: 100%;
}
:host([hidden]) {
display: none;
}
`
];
}
constructor() {
super();
this.autofocus = false;
this.disabled = false;
this.labelHidden = false;
this.required = false;
}
get value() { return this._value; }
set value(val) {
const oldValue = this.value;
if (val < 0) val = 0;
else if (val > 100) val = 100;
this._value = val;
this.requestUpdate('value', oldValue);
}
static get focusElementSelector() {
return 'd2l-input-number';
}
render() {
return html`
<d2l-input-number
?autofocus="${this.autofocus}"
@blur="${this._handleBlur}"
@change="${this._handleChange}"
class="vdiff-target"
?disabled="${this.disabled}"
.forceInvalid="${this.invalid}"
input-width="${ifDefined(this.inputWidth)}"
label="${ifDefined(this.label)}"
?label-hidden="${this.labelHidden || this.labelledBy}"
.labelRequired="${false}"
max="100"
max-fraction-digits="${ifDefined(this.maxFractionDigits)}"
min="0"
min-fraction-digits="${ifDefined(this.minFractionDigits)}"
name="${ifDefined(this.name)}"
?noValidate="${this.noValidate}"
?required="${this.required}"
?skeleton="${this.skeleton}"
unit="%"
value="${ifDefined(this.value)}"
value-align="end">
<slot slot="after" name="after"></slot>
<slot slot="inline-help" name="inline-help"></slot>
</d2l-input-number>
`;
}
async validate() {
if (!this.shadowRoot) return;
const inputNumberElem = this.shadowRoot.querySelector('d2l-input-number');
await inputNumberElem.updateComplete;
const childErrors = await inputNumberElem.validate();
const errors = await super.validate();
return [...childErrors, ...errors];
}
async _handleChange(e) {
const oldValue = this.value;
this.value = e.target.value;
this.requestUpdate();
await this.updateComplete;
if (oldValue !== this.value) {
this.dispatchEvent(new CustomEvent(
'change',
{ bubbles: true, composed: false }
));
}
}
}
customElements.define('d2l-input-percent', InputPercent);