@momentum-design/components 0.134.0 → 0.134.2
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/browser/index.js +493 -445
- package/dist/browser/index.js.map +4 -4
- package/dist/components/button/button.component.d.ts +6 -0
- package/dist/components/button/button.component.js +7 -0
- package/dist/components/button/button.constants.d.ts +6 -1
- package/dist/components/button/button.constants.js +6 -1
- package/dist/components/button/button.styles.js +22 -0
- package/dist/components/buttonlink/buttonlink.component.js +1 -0
- package/dist/components/input/index.d.ts +1 -0
- package/dist/components/input/index.js +1 -0
- package/dist/components/input/input.component.d.ts +7 -1
- package/dist/components/input/input.component.js +36 -3
- package/dist/components/input/input.styles.js +20 -0
- package/dist/components/input/input.types.d.ts +3 -1
- package/dist/components/textarea/textarea.component.d.ts +1 -35
- package/dist/components/textarea/textarea.component.js +6 -87
- package/dist/components/textarea/textarea.constants.d.ts +0 -1
- package/dist/components/textarea/textarea.constants.js +0 -2
- package/dist/custom-elements.json +709 -59
- package/dist/react/button/index.d.ts +6 -0
- package/dist/react/button/index.js +6 -0
- package/dist/react/input/index.d.ts +6 -0
- package/dist/react/input/index.js +5 -0
- package/dist/react/password/index.d.ts +8 -6
- package/dist/react/password/index.js +1 -0
- package/dist/react/searchfield/index.d.ts +8 -6
- package/dist/react/searchfield/index.js +1 -0
- package/dist/react/searchpopover/index.d.ts +2 -0
- package/dist/react/searchpopover/index.js +1 -0
- package/dist/react/textarea/index.d.ts +2 -1
- package/dist/react/textarea/index.js +1 -1
- package/dist/utils/mixins/ButtonComponentMixin.js +7 -4
- package/dist/utils/mixins/CharacterLimitMixin.d.ts +37 -0
- package/dist/utils/mixins/CharacterLimitMixin.js +124 -0
- package/package.json +1 -1
|
@@ -37,6 +37,12 @@ declare const Button_base: import("../../utils/mixins/index.types").Constructor<
|
|
|
37
37
|
* - **Accent**: For informational actions
|
|
38
38
|
* - **Promotional**: For promotional actions
|
|
39
39
|
*
|
|
40
|
+
* Color options for **Tertiary** buttons:
|
|
41
|
+
*
|
|
42
|
+
* - **Default**: For standard actions
|
|
43
|
+
* - **Accent**: For informational actions
|
|
44
|
+
* - **Negative**: For destructive or error actions
|
|
45
|
+
*
|
|
40
46
|
* ### Button Sizes
|
|
41
47
|
*
|
|
42
48
|
* Size options for different button configurations in REM:
|
|
@@ -49,6 +49,12 @@ import { getIconNameWithoutStyle } from './button.utils';
|
|
|
49
49
|
* - **Accent**: For informational actions
|
|
50
50
|
* - **Promotional**: For promotional actions
|
|
51
51
|
*
|
|
52
|
+
* Color options for **Tertiary** buttons:
|
|
53
|
+
*
|
|
54
|
+
* - **Default**: For standard actions
|
|
55
|
+
* - **Accent**: For informational actions
|
|
56
|
+
* - **Negative**: For destructive or error actions
|
|
57
|
+
*
|
|
52
58
|
* ### Button Sizes
|
|
53
59
|
*
|
|
54
60
|
* Size options for different button configurations in REM:
|
|
@@ -143,6 +149,7 @@ class Button extends OverflowMixin(ButtonComponentMixin(Buttonsimple)) {
|
|
|
143
149
|
}
|
|
144
150
|
if (changedProperties.has('variant')) {
|
|
145
151
|
this.setVariant(this.variant);
|
|
152
|
+
this.setColor(this.color);
|
|
146
153
|
this.setSize(this.size);
|
|
147
154
|
}
|
|
148
155
|
if (changedProperties.has('color')) {
|
|
@@ -32,6 +32,11 @@ declare const BUTTON_TYPE_INTERNAL: {
|
|
|
32
32
|
readonly ICON: "icon";
|
|
33
33
|
readonly PILL_WITH_ICON: "pill-with-icon";
|
|
34
34
|
};
|
|
35
|
+
declare const TERTIARY_BUTTON_COLORS: {
|
|
36
|
+
readonly DEFAULT: "default";
|
|
37
|
+
readonly ACCENT: "accent";
|
|
38
|
+
readonly NEGATIVE: "negative";
|
|
39
|
+
};
|
|
35
40
|
declare const DEFAULTS: {
|
|
36
41
|
readonly VARIANT: "primary";
|
|
37
42
|
readonly SIZE: 32;
|
|
@@ -40,4 +45,4 @@ declare const DEFAULTS: {
|
|
|
40
45
|
readonly TYPE: "button";
|
|
41
46
|
readonly INVERTED: false;
|
|
42
47
|
};
|
|
43
|
-
export { TAG_NAME, DEFAULTS, BUTTON_VARIANTS, PILL_BUTTON_SIZES, ICON_BUTTON_SIZES, BUTTON_COLORS, BUTTON_TYPE_INTERNAL, BUTTON_TYPE, };
|
|
48
|
+
export { TAG_NAME, DEFAULTS, BUTTON_VARIANTS, PILL_BUTTON_SIZES, ICON_BUTTON_SIZES, BUTTON_COLORS, TERTIARY_BUTTON_COLORS, BUTTON_TYPE_INTERNAL, BUTTON_TYPE, };
|
|
@@ -30,6 +30,11 @@ const BUTTON_TYPE_INTERNAL = {
|
|
|
30
30
|
ICON: 'icon',
|
|
31
31
|
PILL_WITH_ICON: 'pill-with-icon',
|
|
32
32
|
};
|
|
33
|
+
const TERTIARY_BUTTON_COLORS = {
|
|
34
|
+
DEFAULT: BUTTON_COLORS.DEFAULT,
|
|
35
|
+
ACCENT: BUTTON_COLORS.ACCENT,
|
|
36
|
+
NEGATIVE: BUTTON_COLORS.NEGATIVE,
|
|
37
|
+
};
|
|
33
38
|
const DEFAULTS = {
|
|
34
39
|
VARIANT: BUTTON_VARIANTS.PRIMARY,
|
|
35
40
|
SIZE: PILL_BUTTON_SIZES[32],
|
|
@@ -38,4 +43,4 @@ const DEFAULTS = {
|
|
|
38
43
|
TYPE: BUTTON_TYPE.BUTTON,
|
|
39
44
|
INVERTED: false,
|
|
40
45
|
};
|
|
41
|
-
export { TAG_NAME, DEFAULTS, BUTTON_VARIANTS, PILL_BUTTON_SIZES, ICON_BUTTON_SIZES, BUTTON_COLORS, BUTTON_TYPE_INTERNAL, BUTTON_TYPE, };
|
|
46
|
+
export { TAG_NAME, DEFAULTS, BUTTON_VARIANTS, PILL_BUTTON_SIZES, ICON_BUTTON_SIZES, BUTTON_COLORS, TERTIARY_BUTTON_COLORS, BUTTON_TYPE_INTERNAL, BUTTON_TYPE, };
|
|
@@ -99,6 +99,28 @@ const styles = css `
|
|
|
99
99
|
--mdc-button-background: var(--mds-color-theme-button-secondary-pressed);
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
:host([color='accent'][variant='tertiary']) {
|
|
103
|
+
--mdc-button-text-color: var(--mds-color-theme-text-accent-normal);
|
|
104
|
+
}
|
|
105
|
+
:host([color='accent'][variant='tertiary']:hover:not([disabled]):not([soft-disabled])) {
|
|
106
|
+
--mdc-button-background: var(--mds-color-theme-button-secondary-hover);
|
|
107
|
+
}
|
|
108
|
+
:host([color='accent'][variant='tertiary']:active:not([disabled]):not([soft-disabled])),
|
|
109
|
+
:host([color='accent'][variant='tertiary'].pressed:not([disabled]):not([soft-disabled])) {
|
|
110
|
+
--mdc-button-background: var(--mds-color-theme-button-secondary-pressed);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
:host([color='negative'][variant='tertiary']) {
|
|
114
|
+
--mdc-button-text-color: var(--mds-color-theme-text-error-normal);
|
|
115
|
+
}
|
|
116
|
+
:host([color='negative'][variant='tertiary']:hover:not([disabled]):not([soft-disabled])) {
|
|
117
|
+
--mdc-button-background: var(--mds-color-theme-button-secondary-hover);
|
|
118
|
+
}
|
|
119
|
+
:host([color='negative'][variant='tertiary']:active:not([disabled]):not([soft-disabled])),
|
|
120
|
+
:host([color='negative'][variant='tertiary'].pressed:not([disabled]):not([soft-disabled])) {
|
|
121
|
+
--mdc-button-background: var(--mds-color-theme-button-secondary-pressed);
|
|
122
|
+
}
|
|
123
|
+
|
|
102
124
|
:host([size='64'][data-btn-type='icon']),
|
|
103
125
|
:host([size='52'][data-btn-type='icon']),
|
|
104
126
|
:host([size='40'][data-btn-type='icon']),
|
|
@@ -3,7 +3,7 @@ import FormfieldWrapper from '../formfieldwrapper';
|
|
|
3
3
|
import type { IconNames } from '../icon/icon.types';
|
|
4
4
|
import { AssociatedFormControl } from '../../utils/mixins/FormInternalsMixin';
|
|
5
5
|
import type { AutoCapitalizeType, AutoCompleteType, InputType } from './input.types';
|
|
6
|
-
declare const Input_base: import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/KeyToActionMixin").KeyToActionInterface> & import("../../utils/mixins/index.types").Constructor<import("../../models").Component & import("../../utils/mixins/AutoFocusOnMountMixin").AutoFocusOnMountMixinInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/FormInternalsMixin").FormInternalsMixinInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/DataAriaLabelMixin").DataAriaLabelMixinInterface> & typeof FormfieldWrapper;
|
|
6
|
+
declare const Input_base: import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/CharacterLimitMixin").CharacterLimitMixinInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/KeyToActionMixin").KeyToActionInterface> & import("../../utils/mixins/index.types").Constructor<import("../../models").Component & import("../../utils/mixins/AutoFocusOnMountMixin").AutoFocusOnMountMixinInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/FormInternalsMixin").FormInternalsMixinInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/DataAriaLabelMixin").DataAriaLabelMixinInterface> & typeof FormfieldWrapper;
|
|
7
7
|
/**
|
|
8
8
|
* mdc-input is a component that allows users to input text.
|
|
9
9
|
* It contains:
|
|
@@ -23,6 +23,8 @@ declare const Input_base: import("../../utils/mixins/index.types").Constructor<i
|
|
|
23
23
|
* @event focus - (React: onFocus) This event is dispatched when the input receives focus.
|
|
24
24
|
* @event blur - (React: onBlur) This event is dispatched when the input loses focus.
|
|
25
25
|
* @event clear - (React: onClear) This event is dispatched when the input text is cleared.
|
|
26
|
+
* @event limitexceeded - (React: onLimitExceeded) This event is dispatched once when the character limit
|
|
27
|
+
* exceeds or restored.
|
|
26
28
|
*
|
|
27
29
|
* @dependency mdc-icon
|
|
28
30
|
* @dependency mdc-text
|
|
@@ -69,6 +71,8 @@ declare const Input_base: import("../../utils/mixins/index.types").Constructor<i
|
|
|
69
71
|
* @csspart input-section - The container for the input field, leading icon, and prefix text elements.
|
|
70
72
|
* @csspart input-text - The input field element.
|
|
71
73
|
* @csspart trailing-button - The trailing button element that is displayed to clear the input field when the `trailingButton` property is set to true.
|
|
74
|
+
* @csspart input-footer - The footer element that contains the helper text and character counter.
|
|
75
|
+
* @csspart character-counter - The character counter element.
|
|
72
76
|
*/
|
|
73
77
|
declare class Input extends Input_base implements AssociatedFormControl {
|
|
74
78
|
/**
|
|
@@ -155,6 +159,7 @@ declare class Input extends Input_base implements AssociatedFormControl {
|
|
|
155
159
|
*/
|
|
156
160
|
attributeChangedCallback(name: string, old: string | null, value: string | null): void;
|
|
157
161
|
private setInputValidity;
|
|
162
|
+
protected updated(changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void;
|
|
158
163
|
/**
|
|
159
164
|
* Updates the value of the input field.
|
|
160
165
|
* Sets the form value.
|
|
@@ -213,6 +218,7 @@ declare class Input extends Input_base implements AssociatedFormControl {
|
|
|
213
218
|
*/
|
|
214
219
|
protected renderTrailingButton(show?: boolean): import("lit-html").TemplateResult<1> | typeof nothing;
|
|
215
220
|
protected renderInputElement(type: InputType, hidePlaceholder?: boolean): import("lit-html").TemplateResult<1>;
|
|
221
|
+
protected renderInputFooter(): import("lit-html").TemplateResult<1> | typeof nothing;
|
|
216
222
|
render(): import("lit-html").TemplateResult<1>;
|
|
217
223
|
static styles: Array<CSSResult>;
|
|
218
224
|
static shadowRootOptions: {
|
|
@@ -12,11 +12,12 @@ import { property } from 'lit/decorators.js';
|
|
|
12
12
|
import { ifDefined } from 'lit/directives/if-defined.js';
|
|
13
13
|
import { live } from 'lit/directives/live.js';
|
|
14
14
|
import FormfieldWrapper from '../formfieldwrapper';
|
|
15
|
-
import { DEFAULTS as FORMFIELD_DEFAULTS } from '../formfieldwrapper/formfieldwrapper.constants';
|
|
15
|
+
import { DEFAULTS as FORMFIELD_DEFAULTS, VALIDATION } from '../formfieldwrapper/formfieldwrapper.constants';
|
|
16
16
|
import { DataAriaLabelMixin } from '../../utils/mixins/DataAriaLabelMixin';
|
|
17
17
|
import { FormInternalsMixin } from '../../utils/mixins/FormInternalsMixin';
|
|
18
18
|
import { AutoFocusOnMountMixin } from '../../utils/mixins/AutoFocusOnMountMixin';
|
|
19
19
|
import { KeyToActionMixin, ACTIONS, NAV_MODES } from '../../utils/mixins/KeyToActionMixin';
|
|
20
|
+
import { CharacterLimitMixin } from '../../utils/mixins/CharacterLimitMixin';
|
|
20
21
|
import { AUTO_CAPITALIZE, AUTO_COMPLETE, DEFAULTS, PREFIX_TEXT_OPTIONS } from './input.constants';
|
|
21
22
|
import styles from './input.styles';
|
|
22
23
|
/**
|
|
@@ -38,6 +39,8 @@ import styles from './input.styles';
|
|
|
38
39
|
* @event focus - (React: onFocus) This event is dispatched when the input receives focus.
|
|
39
40
|
* @event blur - (React: onBlur) This event is dispatched when the input loses focus.
|
|
40
41
|
* @event clear - (React: onClear) This event is dispatched when the input text is cleared.
|
|
42
|
+
* @event limitexceeded - (React: onLimitExceeded) This event is dispatched once when the character limit
|
|
43
|
+
* exceeds or restored.
|
|
41
44
|
*
|
|
42
45
|
* @dependency mdc-icon
|
|
43
46
|
* @dependency mdc-text
|
|
@@ -84,8 +87,10 @@ import styles from './input.styles';
|
|
|
84
87
|
* @csspart input-section - The container for the input field, leading icon, and prefix text elements.
|
|
85
88
|
* @csspart input-text - The input field element.
|
|
86
89
|
* @csspart trailing-button - The trailing button element that is displayed to clear the input field when the `trailingButton` property is set to true.
|
|
90
|
+
* @csspart input-footer - The footer element that contains the helper text and character counter.
|
|
91
|
+
* @csspart character-counter - The character counter element.
|
|
87
92
|
*/
|
|
88
|
-
class Input extends KeyToActionMixin(AutoFocusOnMountMixin(FormInternalsMixin(DataAriaLabelMixin(FormfieldWrapper)))) {
|
|
93
|
+
class Input extends CharacterLimitMixin(KeyToActionMixin(AutoFocusOnMountMixin(FormInternalsMixin(DataAriaLabelMixin(FormfieldWrapper))))) {
|
|
89
94
|
constructor() {
|
|
90
95
|
super(...arguments);
|
|
91
96
|
/**
|
|
@@ -181,8 +186,23 @@ class Input extends KeyToActionMixin(AutoFocusOnMountMixin(FormInternalsMixin(Da
|
|
|
181
186
|
if (!this.inputElement.validity.valid && this.validationMessage) {
|
|
182
187
|
this.inputElement.setCustomValidity(this.validationMessage);
|
|
183
188
|
}
|
|
189
|
+
else if (this.maxCharacterLimit &&
|
|
190
|
+
this.value.length > this.maxCharacterLimit &&
|
|
191
|
+
this.helpTextType === VALIDATION.ERROR &&
|
|
192
|
+
this.helpText) {
|
|
193
|
+
this.inputElement.setCustomValidity(this.helpText);
|
|
194
|
+
}
|
|
184
195
|
this.setValidity();
|
|
185
196
|
}
|
|
197
|
+
updated(changedProperties) {
|
|
198
|
+
super.updated(changedProperties);
|
|
199
|
+
if (changedProperties.has('value')) {
|
|
200
|
+
this.handleCharacterOverflowStateChange();
|
|
201
|
+
}
|
|
202
|
+
if (changedProperties.has('helpText')) {
|
|
203
|
+
this.announceCharacterLimitWarning();
|
|
204
|
+
}
|
|
205
|
+
}
|
|
186
206
|
/**
|
|
187
207
|
* Updates the value of the input field.
|
|
188
208
|
* Sets the form value.
|
|
@@ -191,6 +211,7 @@ class Input extends KeyToActionMixin(AutoFocusOnMountMixin(FormInternalsMixin(Da
|
|
|
191
211
|
updateValue() {
|
|
192
212
|
this.value = this.inputElement.value;
|
|
193
213
|
this.internals.setFormValue(this.inputElement.value);
|
|
214
|
+
this.announceCharacterLimitWarning();
|
|
194
215
|
}
|
|
195
216
|
/**
|
|
196
217
|
* Handles the input event of the input field.
|
|
@@ -342,6 +363,12 @@ class Input extends KeyToActionMixin(AutoFocusOnMountMixin(FormInternalsMixin(Da
|
|
|
342
363
|
@keydown=${this.handleKeyDown}
|
|
343
364
|
/>`;
|
|
344
365
|
}
|
|
366
|
+
renderInputFooter() {
|
|
367
|
+
if (!this.helpText && !this.maxCharacterLimit) {
|
|
368
|
+
return nothing;
|
|
369
|
+
}
|
|
370
|
+
return html ` <div part="input-footer">${this.renderHelperText()} ${this.renderCharacterCounter()}</div> `;
|
|
371
|
+
}
|
|
345
372
|
render() {
|
|
346
373
|
return html `
|
|
347
374
|
${this.renderLabel()}
|
|
@@ -353,7 +380,13 @@ class Input extends KeyToActionMixin(AutoFocusOnMountMixin(FormInternalsMixin(Da
|
|
|
353
380
|
</div>
|
|
354
381
|
<slot name="trailing-button">${this.renderTrailingButton()}</slot>
|
|
355
382
|
</div>
|
|
356
|
-
|
|
383
|
+
<mdc-screenreaderannouncer
|
|
384
|
+
identity="${this.inputId}"
|
|
385
|
+
announcement="${ifDefined(this.characterLimitAriaLiveAnnouncer)}"
|
|
386
|
+
data-aria-live="polite"
|
|
387
|
+
delay="500"
|
|
388
|
+
></mdc-screenreaderannouncer>
|
|
389
|
+
${this.renderInputFooter()}
|
|
357
390
|
`;
|
|
358
391
|
}
|
|
359
392
|
}
|
|
@@ -122,6 +122,26 @@ const styles = [
|
|
|
122
122
|
opacity: 0;
|
|
123
123
|
pointer-events: none;
|
|
124
124
|
}
|
|
125
|
+
|
|
126
|
+
:host::part(input-footer) {
|
|
127
|
+
display: flex;
|
|
128
|
+
justify-content: space-between;
|
|
129
|
+
align-items: center;
|
|
130
|
+
width: 100%;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
:host::part(character-counter) {
|
|
134
|
+
margin-left: auto;
|
|
135
|
+
color: var(--mdc-input-support-text-color);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
:host([help-text-type='error'])::part(character-counter) {
|
|
139
|
+
color: var(--mdc-help-text-color);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
:host([disabled])::part(character-counter) {
|
|
143
|
+
color: var(--mds-color-theme-text-primary-disabled);
|
|
144
|
+
}
|
|
125
145
|
`,
|
|
126
146
|
...hostFocusRingStyles(true),
|
|
127
147
|
];
|
|
@@ -9,11 +9,13 @@ type InputChangeEvent = TypedCustomEvent<Input>;
|
|
|
9
9
|
type InputFocusEvent = OverrideEventTarget<FocusEvent, Input>;
|
|
10
10
|
type InputBlurEvent = OverrideEventTarget<FocusEvent, Input>;
|
|
11
11
|
type InputClearEvent = TypedCustomEvent<Input>;
|
|
12
|
+
type InputLimitExceededEvent = TypedCustomEvent<Input>;
|
|
12
13
|
interface Events {
|
|
13
14
|
onInputEvent: InputInputEvent;
|
|
14
15
|
onChangeEvent: InputChangeEvent;
|
|
15
16
|
onFocusEvent: InputFocusEvent;
|
|
16
17
|
onBlurEvent: InputBlurEvent;
|
|
17
18
|
onClearEvent: InputClearEvent;
|
|
19
|
+
onLimitExceededEvent: InputLimitExceededEvent;
|
|
18
20
|
}
|
|
19
|
-
export type { AutoCapitalizeType, AutoCompleteType, InputType, InputInputEvent, InputChangeEvent, InputFocusEvent, InputBlurEvent, InputClearEvent, Events, };
|
|
21
|
+
export type { AutoCapitalizeType, AutoCompleteType, InputType, InputInputEvent, InputChangeEvent, InputFocusEvent, InputBlurEvent, InputClearEvent, InputLimitExceededEvent, Events, };
|
|
@@ -2,7 +2,7 @@ import { CSSResult, nothing, PropertyValueMap } from 'lit';
|
|
|
2
2
|
import FormfieldWrapper from '../formfieldwrapper';
|
|
3
3
|
import type { AutoCapitalizeType } from '../input/input.types';
|
|
4
4
|
import type { WrapType, AutoCompleteType } from './textarea.types';
|
|
5
|
-
declare const Textarea_base: import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/KeyDownHandledMixin").KeyDownHandledMixinInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/KeyToActionMixin").KeyToActionInterface> & import("../../utils/mixins/index.types").Constructor<import("../../models").Component & import("../../utils/mixins/AutoFocusOnMountMixin").AutoFocusOnMountMixinInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/FormInternalsMixin").FormInternalsMixinInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/DataAriaLabelMixin").DataAriaLabelMixinInterface> & typeof FormfieldWrapper;
|
|
5
|
+
declare const Textarea_base: import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/CharacterLimitMixin").CharacterLimitMixinInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/KeyDownHandledMixin").KeyDownHandledMixinInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/KeyToActionMixin").KeyToActionInterface> & import("../../utils/mixins/index.types").Constructor<import("../../models").Component & import("../../utils/mixins/AutoFocusOnMountMixin").AutoFocusOnMountMixinInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/FormInternalsMixin").FormInternalsMixinInterface> & import("../../utils/mixins/index.types").Constructor<import("../../utils/mixins/DataAriaLabelMixin").DataAriaLabelMixinInterface> & typeof FormfieldWrapper;
|
|
6
6
|
/**
|
|
7
7
|
* mdc-textarea component, which is used to get the multi-line text input from the user.
|
|
8
8
|
* It contains:
|
|
@@ -130,18 +130,6 @@ declare class Textarea extends Textarea_base {
|
|
|
130
130
|
* The minimum number of characters that the textarea field can accept.
|
|
131
131
|
*/
|
|
132
132
|
minlength?: number;
|
|
133
|
-
/**
|
|
134
|
-
* The maximum character limit for the textarea field for character counter.
|
|
135
|
-
*/
|
|
136
|
-
maxCharacterLimit?: number;
|
|
137
|
-
/**
|
|
138
|
-
* Template string for the announcement that will be read by screen readers when the max character limit is set.
|
|
139
|
-
* Consumers must use the placeholders `%{number-of-characters}` and `%{max-character-limit}` in the string,
|
|
140
|
-
* which will be dynamically replaced with the actual values at runtime.
|
|
141
|
-
* For example: `%{number-of-characters} out of %{max-character-limit} characters are typed.`
|
|
142
|
-
* Example output: "93 out of 140 characters are typed."
|
|
143
|
-
*/
|
|
144
|
-
characterLimitAnnouncement?: string;
|
|
145
133
|
/**
|
|
146
134
|
* Controls whether the textarea is resizable via the resize button.
|
|
147
135
|
* When set to false, the resize button will be hidden.
|
|
@@ -160,10 +148,6 @@ declare class Textarea extends Textarea_base {
|
|
|
160
148
|
*/
|
|
161
149
|
inputElement: HTMLTextAreaElement;
|
|
162
150
|
/** @internal */
|
|
163
|
-
private ariaLiveAnnouncer?;
|
|
164
|
-
/** @internal */
|
|
165
|
-
private characterLimitExceedingFired;
|
|
166
|
-
/** @internal */
|
|
167
151
|
private resizeStartY;
|
|
168
152
|
/** @internal */
|
|
169
153
|
private resizeStartRows;
|
|
@@ -182,29 +166,12 @@ declare class Textarea extends Textarea_base {
|
|
|
182
166
|
*/
|
|
183
167
|
handleValueChange(): void;
|
|
184
168
|
protected updated(changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void;
|
|
185
|
-
/**
|
|
186
|
-
* Dispatches the character overflow state change event.
|
|
187
|
-
* @returns void
|
|
188
|
-
*/
|
|
189
|
-
private dispatchCharacterOverflowStateChangeEvent;
|
|
190
|
-
/**
|
|
191
|
-
* Handles the character overflow state change.
|
|
192
|
-
* Dispatches the character overflow state change event if the character limit is exceeded or restored.
|
|
193
|
-
* @returns void
|
|
194
|
-
*/
|
|
195
|
-
private handleCharacterOverflowStateChange;
|
|
196
169
|
/**
|
|
197
170
|
* Updates the value of the textarea field.
|
|
198
171
|
* Sets the form value.
|
|
199
172
|
* @returns void
|
|
200
173
|
*/
|
|
201
174
|
private updateValue;
|
|
202
|
-
/**
|
|
203
|
-
* Announces the character limit warning based on the current value length.
|
|
204
|
-
* If the value length exceeds the max character limit, the help text is announced (if help text is present).
|
|
205
|
-
* If the value length does not exceed the max character limit, then the character limit announcement is announced.
|
|
206
|
-
*/
|
|
207
|
-
private announceMaxLengthWarning;
|
|
208
175
|
/**
|
|
209
176
|
* Handles the change event of the textarea field.
|
|
210
177
|
* Updates the value and sets the validity of the textarea field.
|
|
@@ -216,7 +183,6 @@ declare class Textarea extends Textarea_base {
|
|
|
216
183
|
* @param event - Event which contains information about the value change.
|
|
217
184
|
*/
|
|
218
185
|
private onChange;
|
|
219
|
-
protected renderCharacterCounter(): import("lit-html").TemplateResult<1> | typeof nothing;
|
|
220
186
|
protected renderTextareaFooter(): import("lit-html").TemplateResult<1> | typeof nothing;
|
|
221
187
|
/**
|
|
222
188
|
* Handles the resize button keydown event for keyboard-based resizing.
|
|
@@ -9,7 +9,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
9
9
|
};
|
|
10
10
|
import { html, nothing } from 'lit';
|
|
11
11
|
import { ifDefined } from 'lit/directives/if-defined.js';
|
|
12
|
-
import { property, query
|
|
12
|
+
import { property, query } from 'lit/decorators.js';
|
|
13
13
|
import FormfieldWrapper from '../formfieldwrapper';
|
|
14
14
|
import { DEFAULTS as FORMFIELD_DEFAULTS, VALIDATION } from '../formfieldwrapper/formfieldwrapper.constants';
|
|
15
15
|
import { AUTO_CAPITALIZE } from '../input/input.constants';
|
|
@@ -18,6 +18,7 @@ import { FormInternalsMixin } from '../../utils/mixins/FormInternalsMixin';
|
|
|
18
18
|
import { AutoFocusOnMountMixin } from '../../utils/mixins/AutoFocusOnMountMixin';
|
|
19
19
|
import { ACTIONS, KeyToActionMixin } from '../../utils/mixins/KeyToActionMixin';
|
|
20
20
|
import { KeyDownHandledMixin } from '../../utils/mixins/KeyDownHandledMixin';
|
|
21
|
+
import { CharacterLimitMixin } from '../../utils/mixins/CharacterLimitMixin';
|
|
21
22
|
import { AUTO_COMPLETE, WRAP, DEFAULTS } from './textarea.constants';
|
|
22
23
|
import styles from './textarea.styles';
|
|
23
24
|
/**
|
|
@@ -105,7 +106,7 @@ import styles from './textarea.styles';
|
|
|
105
106
|
* @cssproperty --mdc-textarea-text-line-height - Line height for the textarea field
|
|
106
107
|
* @cssproperty --mdc-textarea-container-background-color - Background color for the textarea container
|
|
107
108
|
*/
|
|
108
|
-
class Textarea extends KeyDownHandledMixin(KeyToActionMixin(AutoFocusOnMountMixin(FormInternalsMixin(DataAriaLabelMixin(FormfieldWrapper))))) {
|
|
109
|
+
class Textarea extends CharacterLimitMixin(KeyDownHandledMixin(KeyToActionMixin(AutoFocusOnMountMixin(FormInternalsMixin(DataAriaLabelMixin(FormfieldWrapper)))))) {
|
|
109
110
|
constructor() {
|
|
110
111
|
super(...arguments);
|
|
111
112
|
/**
|
|
@@ -135,8 +136,6 @@ class Textarea extends KeyDownHandledMixin(KeyToActionMixin(AutoFocusOnMountMixi
|
|
|
135
136
|
*/
|
|
136
137
|
this.resizable = false;
|
|
137
138
|
/** @internal */
|
|
138
|
-
this.characterLimitExceedingFired = false;
|
|
139
|
-
/** @internal */
|
|
140
139
|
this.resizeStartY = 0;
|
|
141
140
|
/** @internal */
|
|
142
141
|
this.resizeStartRows = 0;
|
|
@@ -268,39 +267,7 @@ class Textarea extends KeyDownHandledMixin(KeyToActionMixin(AutoFocusOnMountMixi
|
|
|
268
267
|
}
|
|
269
268
|
// When helpText gets changed, we need to re-announce the max length warning
|
|
270
269
|
if (changedProperties.has('helpText')) {
|
|
271
|
-
this.
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
/**
|
|
275
|
-
* Dispatches the character overflow state change event.
|
|
276
|
-
* @returns void
|
|
277
|
-
*/
|
|
278
|
-
dispatchCharacterOverflowStateChangeEvent() {
|
|
279
|
-
this.dispatchEvent(new CustomEvent('limitexceeded', {
|
|
280
|
-
detail: {
|
|
281
|
-
currentCharacterCount: this.value.length,
|
|
282
|
-
maxCharacterLimit: this.maxCharacterLimit,
|
|
283
|
-
value: this.value,
|
|
284
|
-
},
|
|
285
|
-
bubbles: true,
|
|
286
|
-
composed: true,
|
|
287
|
-
}));
|
|
288
|
-
}
|
|
289
|
-
/**
|
|
290
|
-
* Handles the character overflow state change.
|
|
291
|
-
* Dispatches the character overflow state change event if the character limit is exceeded or restored.
|
|
292
|
-
* @returns void
|
|
293
|
-
*/
|
|
294
|
-
handleCharacterOverflowStateChange() {
|
|
295
|
-
if (this.maxCharacterLimit) {
|
|
296
|
-
if (this.value.length > this.maxCharacterLimit && !this.characterLimitExceedingFired) {
|
|
297
|
-
this.dispatchCharacterOverflowStateChangeEvent();
|
|
298
|
-
this.characterLimitExceedingFired = true;
|
|
299
|
-
}
|
|
300
|
-
else if (this.value.length <= this.maxCharacterLimit && this.characterLimitExceedingFired) {
|
|
301
|
-
this.dispatchCharacterOverflowStateChangeEvent();
|
|
302
|
-
this.characterLimitExceedingFired = false;
|
|
303
|
-
}
|
|
270
|
+
this.announceCharacterLimitWarning();
|
|
304
271
|
}
|
|
305
272
|
}
|
|
306
273
|
/**
|
|
@@ -311,33 +278,7 @@ class Textarea extends KeyDownHandledMixin(KeyToActionMixin(AutoFocusOnMountMixi
|
|
|
311
278
|
updateValue() {
|
|
312
279
|
this.value = this.textarea.value;
|
|
313
280
|
this.internals.setFormValue(this.textarea.value);
|
|
314
|
-
this.
|
|
315
|
-
}
|
|
316
|
-
/**
|
|
317
|
-
* Announces the character limit warning based on the current value length.
|
|
318
|
-
* If the value length exceeds the max character limit, the help text is announced (if help text is present).
|
|
319
|
-
* If the value length does not exceed the max character limit, then the character limit announcement is announced.
|
|
320
|
-
*/
|
|
321
|
-
announceMaxLengthWarning() {
|
|
322
|
-
this.ariaLiveAnnouncer = '';
|
|
323
|
-
if (!this.maxCharacterLimit || this.value.length === 0) {
|
|
324
|
-
return;
|
|
325
|
-
}
|
|
326
|
-
if (this.helpText && this.value.length > this.maxCharacterLimit) {
|
|
327
|
-
// We need to assign the same value multiple times, when the input reaches the max limit,
|
|
328
|
-
// Lit does a `===` strict comparison and doesn't update the value
|
|
329
|
-
// Hence we need to manually wait for the update to complete and then assign the value.
|
|
330
|
-
this.updateComplete
|
|
331
|
-
.then(() => {
|
|
332
|
-
this.ariaLiveAnnouncer = this.helpText;
|
|
333
|
-
})
|
|
334
|
-
.catch(() => { });
|
|
335
|
-
}
|
|
336
|
-
else if (this.characterLimitAnnouncement && this.value.length <= this.maxCharacterLimit) {
|
|
337
|
-
this.ariaLiveAnnouncer = this.characterLimitAnnouncement
|
|
338
|
-
.replace('%{number-of-characters}', this.value.length.toString())
|
|
339
|
-
.replace('%{max-character-limit}', this.maxCharacterLimit.toString());
|
|
340
|
-
}
|
|
281
|
+
this.announceCharacterLimitWarning();
|
|
341
282
|
}
|
|
342
283
|
/**
|
|
343
284
|
* Handles the change event of the textarea field.
|
|
@@ -354,16 +295,6 @@ class Textarea extends KeyDownHandledMixin(KeyToActionMixin(AutoFocusOnMountMixi
|
|
|
354
295
|
const EventConstructor = event.constructor;
|
|
355
296
|
this.dispatchEvent(new EventConstructor(event.type, event));
|
|
356
297
|
}
|
|
357
|
-
renderCharacterCounter() {
|
|
358
|
-
if (!this.maxCharacterLimit) {
|
|
359
|
-
return nothing;
|
|
360
|
-
}
|
|
361
|
-
return html `
|
|
362
|
-
<mdc-text part="character-counter" tagname="span" type=${DEFAULTS.CHARACTER_COUNTER_TYPE}>
|
|
363
|
-
${this.value.length}/${this.maxCharacterLimit}
|
|
364
|
-
</mdc-text>
|
|
365
|
-
`;
|
|
366
|
-
}
|
|
367
298
|
renderTextareaFooter() {
|
|
368
299
|
if (!this.helpText && !this.maxCharacterLimit) {
|
|
369
300
|
return nothing;
|
|
@@ -427,7 +358,7 @@ class Textarea extends KeyDownHandledMixin(KeyToActionMixin(AutoFocusOnMountMixi
|
|
|
427
358
|
></textarea>
|
|
428
359
|
<mdc-screenreaderannouncer
|
|
429
360
|
identity="${this.inputId}"
|
|
430
|
-
announcement="${ifDefined(this.
|
|
361
|
+
announcement="${ifDefined(this.characterLimitAriaLiveAnnouncer)}"
|
|
431
362
|
data-aria-live="polite"
|
|
432
363
|
delay="500"
|
|
433
364
|
></mdc-screenreaderannouncer>
|
|
@@ -488,14 +419,6 @@ __decorate([
|
|
|
488
419
|
property({ type: Number }),
|
|
489
420
|
__metadata("design:type", Number)
|
|
490
421
|
], Textarea.prototype, "minlength", void 0);
|
|
491
|
-
__decorate([
|
|
492
|
-
property({ type: Number, attribute: 'max-character-limit' }),
|
|
493
|
-
__metadata("design:type", Number)
|
|
494
|
-
], Textarea.prototype, "maxCharacterLimit", void 0);
|
|
495
|
-
__decorate([
|
|
496
|
-
property({ type: String, attribute: 'character-limit-announcement' }),
|
|
497
|
-
__metadata("design:type", String)
|
|
498
|
-
], Textarea.prototype, "characterLimitAnnouncement", void 0);
|
|
499
422
|
__decorate([
|
|
500
423
|
property({ type: Boolean, reflect: true }),
|
|
501
424
|
__metadata("design:type", Boolean)
|
|
@@ -508,8 +431,4 @@ __decorate([
|
|
|
508
431
|
query('textarea'),
|
|
509
432
|
__metadata("design:type", HTMLTextAreaElement)
|
|
510
433
|
], Textarea.prototype, "inputElement", void 0);
|
|
511
|
-
__decorate([
|
|
512
|
-
state(),
|
|
513
|
-
__metadata("design:type", String)
|
|
514
|
-
], Textarea.prototype, "ariaLiveAnnouncer", void 0);
|
|
515
434
|
export default Textarea;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import utils from '../../utils/tag-name';
|
|
2
|
-
import { TYPE as FONT_TYPE } from '../text/text.constants';
|
|
3
2
|
const TAG_NAME = utils.constructTagName('textarea');
|
|
4
3
|
const WRAP = {
|
|
5
4
|
HARD: 'hard',
|
|
@@ -10,7 +9,6 @@ const AUTO_COMPLETE = {
|
|
|
10
9
|
ON: 'on',
|
|
11
10
|
};
|
|
12
11
|
const DEFAULTS = {
|
|
13
|
-
CHARACTER_COUNTER_TYPE: FONT_TYPE.BODY_MIDSIZE_REGULAR,
|
|
14
12
|
ROWS: 5,
|
|
15
13
|
COLS: 40,
|
|
16
14
|
WRAP: WRAP.SOFT,
|