diff --git a/packages/ods/react/tests/_app/src/components/ods-input.tsx b/packages/ods/react/tests/_app/src/components/ods-input.tsx index 1dde25a663..059e8335fb 100644 --- a/packages/ods/react/tests/_app/src/components/ods-input.tsx +++ b/packages/ods/react/tests/_app/src/components/ods-input.tsx @@ -2,17 +2,17 @@ import React from 'react-dom/client'; import { OdsInput } from 'ods-components-react'; const Input = () => { - function onOdsValueChange() { - console.log('React input odsValueChange'); + function onOdsChange() { + console.log('React input odsChange'); } return ( <> + onOdsChange={ onOdsChange }/> + onOdsChange={ onOdsChange }/> ); }; diff --git a/packages/ods/react/tests/e2e/ods-input.e2e.ts b/packages/ods/react/tests/e2e/ods-input.e2e.ts index 080f6c6b65..075a40f2e4 100644 --- a/packages/ods/react/tests/e2e/ods-input.e2e.ts +++ b/packages/ods/react/tests/e2e/ods-input.e2e.ts @@ -21,7 +21,7 @@ describe('ods-input react', () => { expect(boundingBox?.width).toBeGreaterThan(0); }); - it('trigger the odsValueChange handler on type', async () => { + it('trigger the odsChange handler on type', async () => { const elem = await page.$('ods-input:not([is-disabled]) >>> input'); let consoleLog = ''; page.on('console', (consoleObj) => { @@ -32,12 +32,11 @@ describe('ods-input react', () => { // Small delay to ensure page console event has been resolved await new Promise((resolve) => setTimeout(resolve, 100)); - expect(consoleLog).toBe('React input odsValueChange'); + expect(consoleLog).toBe('React input odsChange'); }); - it('does not trigger the odsValueChange handler on type if disabled', async () => { + it('does not trigger the odsChange handler on type if disabled', async () => { const elem = await page.$('ods-input[is-disabled] >>> input'); - console.log('elem', elem) let consoleLog = ''; page.on('console', (consoleObj) => { consoleLog = consoleObj.text(); diff --git a/packages/ods/src/components/input/package.json b/packages/ods/src/components/input/package.json index 89b9b8f1f1..a0d6b5380c 100644 --- a/packages/ods/src/components/input/package.json +++ b/packages/ods/src/components/input/package.json @@ -12,7 +12,7 @@ "lint:ts": "eslint '{src,tests}/**/*.{js,ts,tsx}'", "start": "stencil build --dev --watch --serve", "test:e2e": "stencil test --e2e --config stencil.config.ts --max-workers=2", - "test:e2e:ci": "tsc --noEmit && stencil test --e2e --ci --config stencil.config.ts", + "test:e2e:ci": "tsc --noEmit && stencil test --e2e --ci --config stencil.config.ts --max-workers=2", "test:spec": "stencil test --spec --config stencil.config.ts --coverage", "test:spec:ci": "tsc --noEmit && stencil test --config stencil.config.ts --spec --ci --coverage" } diff --git a/packages/ods/src/components/input/src/components/ods-input/ods-input.scss b/packages/ods/src/components/input/src/components/ods-input/ods-input.scss index d9fed3f3a6..7bbaa36625 100644 --- a/packages/ods/src/components/input/src/components/ods-input/ods-input.scss +++ b/packages/ods/src/components/input/src/components/ods-input/ods-input.scss @@ -20,6 +20,7 @@ $ods-input-input-padding-right: calc($ods-input-actions-button-width + $ods-inpu top: 0; right: 0; bottom: 0; + gap: 2px; align-items: center; justify-content: center; padding-right: 4px; @@ -31,6 +32,10 @@ $ods-input-input-padding-right: calc($ods-input-actions-button-width + $ods-inpu cursor: pointer; } + &__icon { + font-size: 16px; + } + &__clearable { color: var(--ods-color-neutral-600); @@ -62,6 +67,8 @@ $ods-input-input-padding-right: calc($ods-input-actions-button-width + $ods-inpu &:focus-visible { @include focus.ods-focus(); + + outline-offset: 0; } } @@ -94,6 +101,7 @@ $ods-input-input-padding-right: calc($ods-input-actions-button-width + $ods-inpu &:disabled { ~ .ods-input__actions { cursor: not-allowed; + pointer-events: none; .ods-input__actions__clearable, .ods-input__actions__toggle-mask { cursor: not-allowed; diff --git a/packages/ods/src/components/input/src/components/ods-input/ods-input.tsx b/packages/ods/src/components/input/src/components/ods-input/ods-input.tsx index 9ad1eb3b58..8754fdb066 100644 --- a/packages/ods/src/components/input/src/components/ods-input/ods-input.tsx +++ b/packages/ods/src/components/input/src/components/ods-input/ods-input.tsx @@ -45,17 +45,16 @@ export class OdsInput { @Event() odsFocus!: EventEmitter; @Event() odsToggleMask!: EventEmitter; @Event() odsReset!: EventEmitter; - @Event() odsValueChange!: EventEmitter; + @Event() odsChange!: EventEmitter; @Method() async clear(): Promise { - if (this.isDisabled) { + if (this.isNotEditable) { return; } this.value = null; this.inputEl?.focus(); this.odsClear.emit(); - return; } @Method() @@ -65,22 +64,20 @@ export class OdsInput { @Method() async toggleMask(): Promise { - if (this.isDisabled) { + if (this.isNotEditable) { return; } this.isMasked = !this.isMasked; this.odsToggleMask.emit(); - return; } @Method() async reset(): Promise { - if (this.isDisabled) { + if (this.isNotEditable) { return; } this.value = this.defaultValue ?? null; this.odsReset.emit(); - return; } @Watch('isMasked') @@ -91,7 +88,7 @@ export class OdsInput { @Watch('value') onValueChange(value: string | number, oldValue?: string | number): void { setFormValue(this.internals, this.value); - this.odsValueChange.emit({ + this.odsChange.emit({ name: this.name, oldValue: oldValue, validity: this.inputEl?.validity, @@ -111,6 +108,10 @@ export class OdsInput { await this.reset(); } + private get isNotEditable(): boolean { + return this.isDisabled || this.isReadonly; + } + private onInput(): void { if (this.isDisabled) { return; @@ -164,7 +165,7 @@ export class OdsInput { disabled={ this.isDisabled } onClick={ this.clear.bind(this) } onKeyUp={ (event: KeyboardEvent): Promise => handleKeySpace(event, this.isDisabled, this.clear.bind(this)) }> - + } @@ -175,7 +176,7 @@ export class OdsInput { disabled={ this.isDisabled } onClick={ this.toggleMask.bind(this) } onKeyUp={ (event: KeyboardEvent): Promise => handleKeySpace(event, this.isDisabled, this.toggleMask.bind(this)) }> - + } diff --git a/packages/ods/src/components/input/src/index.html b/packages/ods/src/components/input/src/index.html index db049e7fdd..aa84f4d037 100644 --- a/packages/ods/src/components/input/src/index.html +++ b/packages/ods/src/components/input/src/index.html @@ -51,6 +51,10 @@ +

Readonly Clearable

+ + +

Custom CSS

diff --git a/packages/ods/src/components/input/tests/behaviour/ods-input.e2e.ts b/packages/ods/src/components/input/tests/behaviour/ods-input.e2e.ts index 32af405604..a98230407f 100644 --- a/packages/ods/src/components/input/tests/behaviour/ods-input.e2e.ts +++ b/packages/ods/src/components/input/tests/behaviour/ods-input.e2e.ts @@ -38,6 +38,16 @@ describe('ods-input behaviour', () => { expect(await el.getProperty('value')).toBe(value); expect(odsClearSpy).not.toHaveReceivedEvent(); }); + + it('should do nothing because of readonly', async() => { + const value = 'value'; + await setup(``); + const odsClearSpy = await page.spyOnEvent('odsClear'); + await el.callMethod('clear'); + await page.waitForChanges(); + expect(await el.getProperty('value')).toBe(value); + expect(odsClearSpy).not.toHaveReceivedEvent(); + }); }); describe('method:reset', () => { @@ -60,6 +70,16 @@ describe('ods-input behaviour', () => { expect(await el.getProperty('value')).toBe(value); expect(odsResetSpy).not.toHaveReceivedEvent(); }); + + it('should do nothing because of readonly', async() => { + const value = 'value'; + await setup(``); + const odsResetSpy = await page.spyOnEvent('odsReset'); + await el.callMethod('reset'); + await page.waitForChanges(); + expect(await el.getProperty('value')).toBe(value); + expect(odsResetSpy).not.toHaveReceivedEvent(); + }); }); describe('method:toggleMask', () => { @@ -85,30 +105,40 @@ describe('ods-input behaviour', () => { expect(await el.getProperty('isMasked')).toBe(true); expect(odsToggleMaskSpy).not.toHaveReceivedEvent(); }); + + it('should do nothing because of readonly', async() => { + await setup(''); + const odsToggleMaskSpy = await page.spyOnEvent('odsToggleMask'); + await el.callMethod('toggleMask'); + await page.waitForChanges(); + + expect(await el.getProperty('isMasked')).toBe(true); + expect(odsToggleMaskSpy).not.toHaveReceivedEvent(); + }); }); - describe('event:odsValueChange', () => { - it('should receive odsValueChange event', async() => { + describe('event:odsChange ', () => { + it('should receive odsChange event', async() => { const typeValue = 'some text'; await setup(''); - const odsValueChangeSpy = await page.spyOnEvent('odsValueChange'); + const odsChangeSpy = await page.spyOnEvent('odsChange'); await part.type(typeValue); await page.waitForChanges(); expect(await el.getProperty('value')).toBe(typeValue); - expect(odsValueChangeSpy).toHaveReceivedEventTimes(typeValue.length); + expect(odsChangeSpy).toHaveReceivedEventTimes(typeValue.length); }); it('should do nothing because of disabled', async() => { await setup(''); - const odsValueChangeSpy = await page.spyOnEvent('odsValueChange'); + const odsChangeSpy = await page.spyOnEvent('odsChange'); await part.type('some text'); await page.waitForChanges(); expect(await el.getProperty('value')).toBe(null); - expect(odsValueChangeSpy).not.toHaveReceivedEvent(); + expect(odsChangeSpy).not.toHaveReceivedEvent(); }); }); }); diff --git a/packages/ods/src/components/input/tests/behaviour/ods-input.spec.ts b/packages/ods/src/components/input/tests/behaviour/ods-input.spec.ts index e0ea722e83..09eccec340 100644 --- a/packages/ods/src/components/input/tests/behaviour/ods-input.spec.ts +++ b/packages/ods/src/components/input/tests/behaviour/ods-input.spec.ts @@ -3,7 +3,7 @@ import type { SpecPage } from '@stencil/core/testing'; import { newSpecPage } from '@stencil/core/testing'; import { OdsInput } from '../../src'; -describe('ods-input rendering', () => { +describe('ods-input behaviour', () => { let page: SpecPage; let root: HTMLElement | undefined; let rootInstance: OdsInput | undefined;