Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions stencil-workspace/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1743,6 +1743,10 @@ export namespace Components {
* (optional) Disable usage of `tab` key to focus elements inside a tree view. Use `Arrow Up/Down` for focussing a tree item and `Shift + Arrow Right` for focussing a checkbox inside the item.
*/
"disableTabbing": boolean;
/**
* (optional) Sets draggable state to be true to all the children
*/
"enableReordering": boolean;
/**
* (optional) Set expanded tree items
*/
Expand Down Expand Up @@ -2044,6 +2048,7 @@ declare global {
interface HTMLModusAutocompleteElementEventMap {
"optionSelected": string;
"valueChange": string | string[];
"valueError": string;
"selectionsChanged": string[];
}
interface HTMLModusAutocompleteElement extends Components.ModusAutocomplete, HTMLStencilElement {
Expand Down Expand Up @@ -2414,6 +2419,7 @@ declare global {
};
interface HTMLModusNumberInputElementEventMap {
"valueChange": string;
"valueError": string;
}
interface HTMLModusNumberInputElement extends Components.ModusNumberInput, HTMLStencilElement {
addEventListener<K extends keyof HTMLModusNumberInputElementEventMap>(type: K, listener: (this: HTMLModusNumberInputElement, ev: ModusNumberInputCustomEvent<HTMLModusNumberInputElementEventMap[K]>) => any, options?: boolean | AddEventListenerOptions): void;
Expand Down Expand Up @@ -2471,6 +2477,7 @@ declare global {
};
interface HTMLModusSelectElementEventMap {
"valueChange": unknown;
"valueError": string;
"inputBlur": FocusEvent;
}
interface HTMLModusSelectElement extends Components.ModusSelect, HTMLStencilElement {
Expand Down Expand Up @@ -2695,6 +2702,7 @@ declare global {
};
interface HTMLModusTextInputElementEventMap {
"valueChange": string;
"valueError": string;
}
interface HTMLModusTextInputElement extends Components.ModusTextInput, HTMLStencilElement {
addEventListener<K extends keyof HTMLModusTextInputElementEventMap>(type: K, listener: (this: HTMLModusTextInputElement, ev: ModusTextInputCustomEvent<HTMLModusTextInputElementEventMap[K]>) => any, options?: boolean | AddEventListenerOptions): void;
Expand Down Expand Up @@ -3052,6 +3060,10 @@ declare namespace LocalJSX {
* An event that fires when the input value changes. Emits the value string.
*/
"onValueChange"?: (event: ModusAutocompleteCustomEvent<string | string[]>) => void;
/**
* An event that fires on input value error.
*/
"onValueError"?: (event: ModusAutocompleteCustomEvent<string>) => void;
/**
* The autocomplete's options.
*/
Expand Down Expand Up @@ -3919,6 +3931,10 @@ declare namespace LocalJSX {
* An event that fires on input value change.
*/
"onValueChange"?: (event: ModusNumberInputCustomEvent<string>) => void;
/**
* An event that fires on input value error.
*/
"onValueError"?: (event: ModusNumberInputCustomEvent<string>) => void;
/**
* (optional) The input's placeholder text.
*/
Expand Down Expand Up @@ -4058,6 +4074,10 @@ declare namespace LocalJSX {
* An event that fires on input value change.
*/
"onValueChange"?: (event: ModusSelectCustomEvent<unknown>) => void;
/**
* An event that fires on input value error.
*/
"onValueError"?: (event: ModusSelectCustomEvent<string>) => void;
/**
* The options for the dropdown list.
*/
Expand Down Expand Up @@ -4519,6 +4539,10 @@ declare namespace LocalJSX {
* An event that fires on input value change.
*/
"onValueChange"?: (event: ModusTextInputCustomEvent<string>) => void;
/**
* An event that fires on input value error.
*/
"onValueError"?: (event: ModusTextInputCustomEvent<string>) => void;
/**
* (optional) The input's pattern HTML attribute.
*/
Expand Down Expand Up @@ -4803,6 +4827,10 @@ declare namespace LocalJSX {
* (optional) Disable usage of `tab` key to focus elements inside a tree view. Use `Arrow Up/Down` for focussing a tree item and `Shift + Arrow Right` for focussing a checkbox inside the item.
*/
"disableTabbing"?: boolean;
/**
* (optional) Sets draggable state to be true to all the children
*/
"enableReordering"?: boolean;
/**
* (optional) Set expanded tree items
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -958,4 +958,20 @@ describe('modus-autocomplete', () => {
expect(element).toBeDefined();
expect(element).not.toHaveAttribute('aria-label');
});

it('emits valueError event if error message is present', async () => {
const page = await newE2EPage();

await page.setContent('<modus-autocomplete></modus-autocomplete>');
const valueError = await page.spyOnEvent('valueError');
const autocomplete = await page.find('modus-autocomplete >>> div.autocomplete');

autocomplete.setProperty('errorText', 'Error message');
await page.waitForChanges();

const textInput = await page.find('modus-autocomplete >>> modus-text-input');
await textInput.click();
await textInput.type('apple', { delay: 20 });
expect(valueError).toHaveReceivedEvent();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ export class ModusAutocomplete {
this.updateVisibleOptions(this.getValueAsString());
this.updateVisibleCustomOptions(this.getValueAsString());
}
if (this.errorText) {
this.valueError.emit(this.errorText);
}
}

/** An event that fires when a dropdown option is selected. Emits the option id. */
Expand All @@ -119,6 +122,9 @@ export class ModusAutocomplete {
/** An event that fires when the input value changes. Emits the value string. */
@Event() valueChange: EventEmitter<string | string[]>;

/** An event that fires on input value error. */
@Event() valueError: EventEmitter<string>;

/** An event that fires when an option is selected/removed. Emits the option ids. */
@Event() selectionsChanged: EventEmitter<string[]>;

Expand Down Expand Up @@ -317,6 +323,9 @@ export class ModusAutocomplete {
this.updateVisibleCustomOptions(search);
this.value = search;
this.valueChange.emit(search);
if (this.errorText) {
this.valueError.emit(this.errorText);
}
};

handleCloseClick(chipValue: ModusAutocompleteOption) {
Expand All @@ -339,6 +348,9 @@ export class ModusAutocomplete {
event.stopPropagation();
this.disableFiltering = !this.disableCloseOnSelect;
this.handleSearchChange(event.detail);
if (this.errorText) {
this.valueError.emit(this.errorText);
}
};

updateVisibleCustomOptions = (search = '') => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -237,4 +237,17 @@ describe('modus-number-input', () => {

expect(await element.getProperty('value')).toEqual('2');
});

it('emits valueError event if error message is present', async () => {
const page = await newE2EPage();

await page.setContent('<modus-number-input></modus-number-input>');
const valueError = await page.spyOnEvent('valueError');
const numberInput = await page.find('modus-number-input >>> input');

numberInput.setProperty('errorText', 'Error message');
await page.waitForChanges();
await numberInput.type('1', { delay: 20 });
expect(valueError).toHaveReceivedEvent();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ describe('modus-number-input', () => {
<modus-number-input>
<mock:shadow-root>
<div class="modus-number-input">
<div class="input-container medium" part="input-container">
<div class="input-container medium" part="input-container ">
<input class="text-align-left" id="mwc_id_0_number-input" tabindex="0" type="number">
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ export class ModusNumberInput {
/** An event that fires on input value change. */
@Event() valueChange: EventEmitter<string>;

/** An event that fires on input value error. */
@Event() valueError: EventEmitter<string>;

private inputId = generateElementId() + '_number-input';

classBySize: Map<string, string> = new Map([
Expand All @@ -67,6 +70,12 @@ export class ModusNumberInput {
handleOnInput(): void {
this.value = this.numberInput.value;
this.valueChange.emit(this.value);

if (this.errorText) {
this.valueError.emit(this.errorText);
} else {
this.valueError.emit(null);
}
}

/** Focus the input. */
Expand Down Expand Up @@ -122,7 +131,9 @@ export class ModusNumberInput {
{this.helperText ? <label class="sub-text helper">{this.helperText}</label> : null}
</div>
) : null}
<div class={buildInputContainerClassNames()} part="input-container">
<div
class={buildInputContainerClassNames()}
part={`input-container ${this.errorText ? 'error' : this.validText ? 'valid' : ''}`}>
<input
id={this.inputId}
aria-label={this.ariaLabel}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,4 +177,31 @@ describe('modus-select', () => {
expect(element).toBeDefined();
expect(element).not.toHaveAttribute('aria-label');
});

it('emits valueError event if error message is present', async () => {
const page = await newE2EPage();

await page.setContent('<modus-select></modus-select>');
const valueError = await page.spyOnEvent('valueError');
const select = await page.find('modus-select');

const options = [
{ value: '1', label: 'Option 1' },
{ value: '2', label: 'Option 2' },
];
select.setProperty('options', options);
select.setProperty('optionsDisplayProp', 'display');
select.setProperty('errorText', 'Error message');
await page.waitForChanges();

const selectElement = await page.find('modus-select >>> select');
await selectElement.focus();
await page.waitForChanges();

await page.keyboard.press('ArrowDown');
await page.keyboard.press('Enter');
await page.waitForChanges();

expect(valueError).toHaveReceivedEvent();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ describe('modus-select', () => {
<mock:shadow-root>
<div>
<span class="input-container">
<select class="medium" id="mwc_id_0_select" part="input">
<select class="medium" id="mwc_id_0_select" part="input ">
<option disabled="" selected="" value="">
Please Select
</option>
Expand Down
14 changes: 13 additions & 1 deletion stencil-workspace/src/components/modus-select/modus-select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,17 @@ export class ModusSelect {
@Watch('value')
handleValueChange(newValue: unknown): void {
this.internalValue = newValue;
if (this.errorText) {
this.valueError.emit(this.errorText);
}
}

/** An event that fires on input value change. */
@Event() valueChange: EventEmitter<unknown>;

/** An event that fires on input value error. */
@Event() valueError: EventEmitter<string>;

/** An event that fires on input blur. */
@Event() inputBlur: EventEmitter<FocusEvent>;

Expand All @@ -74,10 +80,16 @@ export class ModusSelect {

connectedCallback(): void {
this.internalValue = this.value;
if (this.errorText) {
this.valueError.emit(this.errorText);
}
}

handleOptionSelect(option: unknown): void {
this.valueChange.emit(option);
if (this.errorText) {
this.valueError.emit(this.errorText);
}
}

handleSelectChange(event: Event): void {
Expand Down Expand Up @@ -128,7 +140,7 @@ export class ModusSelect {
{this.renderLabel()}
<span class="input-container">
<select
part="input"
part={`input ${this.errorText ? 'error' : this.validText ? 'valid' : ''}`}
ref={(el) => (this.selectInput = el)}
disabled={this.disabled}
id={this.selectId}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -323,4 +323,17 @@ describe('modus-text-input', () => {
expect(element).toBeDefined();
expect(element).not.toHaveAttribute('aria-label');
});

it('emits valueError event if error message is present', async () => {
const page = await newE2EPage();

await page.setContent('<modus-text-input></modus-text-input>');
const valueError = await page.spyOnEvent('valueError');
const textInput = await page.find('modus-text-input >>> input');

textInput.setProperty('errorText', 'Error message');
await page.waitForChanges();
await textInput.type('test', { delay: 20 });
expect(valueError).toHaveReceivedEvent();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ describe('modus-text-input', () => {
<modus-text-input>
<mock:shadow-root>
<div class="modus-text-input">
<div class="input-container medium" part="input-container">
<div class="input-container medium" part="input-container ">
<input class="text-align-left" id="mwc_id_0_text_input" type="text" tabindex="0">
</div>
</div>
Expand All @@ -29,7 +29,7 @@ describe('modus-text-input', () => {
<modus-text-input type="password">
<mock:shadow-root>
<div class="modus-text-input">
<div class="input-container medium" part="input-container">
<div class="input-container medium" part="input-container ">
<input class="text-align-left" id="mwc_id_1_text_input" tabindex="0" type="password">
</div>
</div>
Expand All @@ -47,7 +47,7 @@ describe('modus-text-input', () => {
<modus-text-input autocapitalize="words">
<mock:shadow-root>
<div class="modus-text-input">
<div class="input-container medium" part="input-container">
<div class="input-container medium" part="input-container ">
<input class="text-align-left" id="mwc_id_2_text_input" tabindex="0" autocapitalize="words" type="text">
</div>
</div>
Expand All @@ -64,8 +64,8 @@ describe('modus-text-input', () => {
expect(page.root).toEqualHtml(`
<modus-text-input autocorrect="on">
<mock:shadow-root>
<div class="modus-text-input">
<div class="input-container medium" part="input-container">
<div class="modus-text-input" >
<div class="input-container medium" part="input-container ">
<input class="text-align-left" id="mwc_id_3_text_input" tabindex="0" autocorrect="on" type="text">
</div>
</div>
Expand All @@ -83,7 +83,7 @@ describe('modus-text-input', () => {
<modus-text-input enterkeyhint="done">
<mock:shadow-root>
<div class="modus-text-input">
<div class="input-container medium" part="input-container">
<div class="input-container medium" part="input-container ">
<input class="text-align-left" id="mwc_id_4_text_input" tabindex="0" enterkeyhint="done" type="text">
</div>
</div>
Expand All @@ -101,7 +101,7 @@ describe('modus-text-input', () => {
<modus-text-input spellcheck>
<mock:shadow-root>
<div class="modus-text-input">
<div class="input-container medium" part="input-container">
<div class="input-container medium" part="input-container ">
<input class="text-align-left" id="mwc_id_5_text_input" tabindex="0" spellcheck type="text">
</div>
</div>
Expand Down
Loading