From bd4dc48be6ef88af092e0c0a2211f5eeb8a57e42 Mon Sep 17 00:00:00 2001 From: Leo Largillet Date: Mon, 18 Sep 2023 17:59:41 +0200 Subject: [PATCH] feat(datepicker): addressing changes --- packages/components/datepicker/jest.config.ts | 9 +-- packages/components/datepicker/package.json | 11 ++-- .../components/datepicker/react/package.json | 4 +- .../constants/default-attributes.ts | 2 +- .../osds-datepicker/core/controller.ts | 20 +------ .../osds-datepicker/interfaces/attributes.ts | 2 +- .../osds-datepicker/interfaces/events.ts | 4 +- .../osds-datepicker/osds-datepicker.scss | 26 ++++----- .../osds-datepicker/osds-datepicker.spec.ts | 15 +---- .../osds-datepicker/osds-datepicker.tsx | 57 +++++++------------ 10 files changed, 53 insertions(+), 97 deletions(-) diff --git a/packages/components/datepicker/jest.config.ts b/packages/components/datepicker/jest.config.ts index 9a82cc647d..8520e2620e 100644 --- a/packages/components/datepicker/jest.config.ts +++ b/packages/components/datepicker/jest.config.ts @@ -2,10 +2,11 @@ import { getStencilJestConfig } from '@ovhcloud/ods-common-testing'; const config = getStencilJestConfig({ args: process.argv.slice(2), + options: { + moduleNameMapper: { + 'vanillajs-datepicker': '/src/jestStub.js', + } + } }); -config.moduleNameMapper = { - 'vanillajs-datepicker': '/src/jestStub.js', -} - export default config; diff --git a/packages/components/datepicker/package.json b/packages/components/datepicker/package.json index f54952a976..31659d6e3e 100644 --- a/packages/components/datepicker/package.json +++ b/packages/components/datepicker/package.json @@ -37,16 +37,13 @@ "@ovhcloud/ods-common-core": "16.0.1", "@ovhcloud/ods-common-stencil": "16.0.1", "@ovhcloud/ods-common-theming": "16.0.1", - "@ovhcloud/ods-component-text": "16.0.1", - "@types/vanillajs-datepicker": "^1.2.2", - "vanillajs-datepicker": "^1.3.3" + "@ovhcloud/ods-component-input": "16.0.1", + "@ovhcloud/ods-component-icon": "16.0.1", + "vanillajs-datepicker": "1.3.3" }, "devDependencies": { "@ovhcloud/ods-common-testing": "16.0.1", - "@ovhcloud/ods-component-input": "16.0.1", - "@ovhcloud/ods-component-link": "16.0.1", - "@ovhcloud/ods-component-textarea": "16.0.1", - "@ovhcloud/ods-component-tooltip": "16.0.1", + "@types/vanillajs-datepicker": "1.2.2", "@ovhcloud/ods-stencil-dev": "16.0.1" } } diff --git a/packages/components/datepicker/react/package.json b/packages/components/datepicker/react/package.json index 56c135e8d7..22bf5e5689 100644 --- a/packages/components/datepicker/react/package.json +++ b/packages/components/datepicker/react/package.json @@ -20,13 +20,13 @@ "dist/" ], "dependencies": { - "@ovhcloud/ods-component-datepicker": "^16.0.1" + "@ovhcloud/ods-component-datepicker": "16.0.1" }, "peerDependencies": { "react": ">=16.8.6", "react-dom": ">=16.8.6" }, "devDependencies": { - "@ovhcloud/ods-react-dev": "^16.0.1" + "@ovhcloud/ods-react-dev": "16.0.1" } } diff --git a/packages/components/datepicker/src/components/osds-datepicker/constants/default-attributes.ts b/packages/components/datepicker/src/components/osds-datepicker/constants/default-attributes.ts index 147464c264..aed05269cb 100644 --- a/packages/components/datepicker/src/components/osds-datepicker/constants/default-attributes.ts +++ b/packages/components/datepicker/src/components/osds-datepicker/constants/default-attributes.ts @@ -3,7 +3,7 @@ import { OdsDatepickerAttribute } from '../interfaces/attributes'; const DEFAULT_ATTRIBUTE: OdsDatepickerAttribute = Object.freeze({ clearable: false, disabled: false, - error: '', + error: false, format: 'dd/mm/yyyy', placeholder: '', value: null, diff --git a/packages/components/datepicker/src/components/osds-datepicker/core/controller.ts b/packages/components/datepicker/src/components/osds-datepicker/core/controller.ts index a419abbd68..5060f83763 100644 --- a/packages/components/datepicker/src/components/osds-datepicker/core/controller.ts +++ b/packages/components/datepicker/src/components/osds-datepicker/core/controller.ts @@ -1,5 +1,4 @@ import type { OsdsDatepicker } from '../osds-datepicker'; -import { OdsLogger } from '@ovhcloud/ods-common-core'; /** * common controller logic for input component used by the different implementations. @@ -7,30 +6,24 @@ import { OdsLogger } from '@ovhcloud/ods-common-core'; */ class OdsDatepickerController { private readonly component: OsdsDatepicker; - private readonly logger = new OdsLogger('OdsDatepickerController'); constructor(component: OsdsDatepicker) { this.component = component; } - beforeInit(): void { - this.logger.debug('[datepicker]', 'beforeInit', this.component.value); - this.onChange(this.component.value); - } - onFocus() { this.component.hasFocus = true; this.component.emitFocus(); } - onChange(newValue: Date | undefined | null, value?: Date | null) { - this.logger.debug(`[datepicker=${newValue}]`, 'value changed', { newValue, value }); + onChange(newValue: Date | undefined | null, oldValue?: Date | undefined | null) { if(!this.component.disabled) { if (newValue === undefined || newValue === null || isNaN(newValue.getTime())) { this.component.value = null; } else { this.component.value = newValue; this.component.datepickerInstance?.setDate(newValue); + this.component.emitValueChange(newValue, oldValue); } } } @@ -39,15 +32,6 @@ class OdsDatepickerController { this.component.hasFocus = false; this.component.emitBlur(); } - - onValueChange(value: Date, oldValue?: Date): void { - this.logger.debug(`[datepicker=${this.component.value}]`, 'value changed', { value, oldValue }); - this.validateValue(); - } - - private validateValue() { - return true - } } export { diff --git a/packages/components/datepicker/src/components/osds-datepicker/interfaces/attributes.ts b/packages/components/datepicker/src/components/osds-datepicker/interfaces/attributes.ts index cf5e14e256..6342bdf87e 100644 --- a/packages/components/datepicker/src/components/osds-datepicker/interfaces/attributes.ts +++ b/packages/components/datepicker/src/components/osds-datepicker/interfaces/attributes.ts @@ -10,7 +10,7 @@ interface OdsDatepickerAttribute { /** * Defines if the Datepicker should display an error message */ - error?: string; + error?: boolean; /** * Defines which format the Datepicker should be applying (supported formats: https://mymth.github.io/vanillajs-datepicker/#/date-string+format?id=date-format) */ diff --git a/packages/components/datepicker/src/components/osds-datepicker/interfaces/events.ts b/packages/components/datepicker/src/components/osds-datepicker/interfaces/events.ts index ed0ef880be..0c48461584 100644 --- a/packages/components/datepicker/src/components/osds-datepicker/interfaces/events.ts +++ b/packages/components/datepicker/src/components/osds-datepicker/interfaces/events.ts @@ -1,8 +1,6 @@ import type { EventEmitter } from '@stencil/core'; -import type { OdsValidityState } from '@ovhcloud/ods-common-core'; interface OdsDatepickerValueChangeEventDetail { - validity: OdsValidityState; value: Date | undefined | null; oldValue?: Date | undefined | null; } @@ -15,7 +13,7 @@ interface OdsDatepickerEvent { /** Triggered on focus */ odsDatepickerFocus: EventEmitter; /** Triggered on value change */ - odsValueChange: EventEmitter; + odsDatepickerValueChange: EventEmitter; } export { diff --git a/packages/components/datepicker/src/components/osds-datepicker/osds-datepicker.scss b/packages/components/datepicker/src/components/osds-datepicker/osds-datepicker.scss index 18c0b473b3..c1ce21e533 100644 --- a/packages/components/datepicker/src/components/osds-datepicker/osds-datepicker.scss +++ b/packages/components/datepicker/src/components/osds-datepicker/osds-datepicker.scss @@ -8,31 +8,25 @@ // CSS targeted only for this component // /!\ for theming purposes, it has to be done in theming files // (i.e. packages/libraries/theming/...) -:host { +:host(.osds-datepicker) { display: flex; flex-direction: column; } -:host([inline]) { - width: fit-content; -} - -:host .osds-datepicker__hidden-input { - display: none; -} - -:host .datepicker { - display: none; +.osds-datepicker { + &__hidden-input { + display: none; + } } -:host([hasFocus]) { +:host { .datepicker { + display: none; width: 50%; max-width: clamp(36rem, 50%, 50%); margin-top: var(--ods-size-04); height: 0; position: relative; - display: flex; .datepicker-picker { width: 100%; @@ -43,6 +37,12 @@ } } +:host([hasFocus]) { + .datepicker { + display: flex; + } +} + // apply the theme template for the component @include ods-theme-component() { @include osds-datepicker-theme-color(); diff --git a/packages/components/datepicker/src/components/osds-datepicker/osds-datepicker.spec.ts b/packages/components/datepicker/src/components/osds-datepicker/osds-datepicker.spec.ts index 71fc6b0170..0c8effadfe 100644 --- a/packages/components/datepicker/src/components/osds-datepicker/osds-datepicker.spec.ts +++ b/packages/components/datepicker/src/components/osds-datepicker/osds-datepicker.spec.ts @@ -71,8 +71,8 @@ describe('spec:osds-datepicker', () => { odsUnitTestAttribute({ name: 'error', defaultValue: DEFAULT_ATTRIBUTE.error, - newValue: 'Bip bop, we encountered a problem.', - value: '', + newValue: true, + value: false, setup: (value) => setup({ attributes: { ['error']: value } }), ...config, }); @@ -134,16 +134,5 @@ describe('spec:osds-datepicker', () => { expect(controller.onFocus).toHaveBeenCalledWith(); }); }); - - describe('watchers', () => { - it('should call onValueChange on value change', async () => { - const value = new Date('1999-11-02'); - await setup({ }); - instance.value = value; - - expect(controller.onValueChange).toHaveBeenCalledTimes(1); - expect(controller.onValueChange).toHaveBeenCalledWith(value, null); - }); - }); }); }); diff --git a/packages/components/datepicker/src/components/osds-datepicker/osds-datepicker.tsx b/packages/components/datepicker/src/components/osds-datepicker/osds-datepicker.tsx index be99bcb84c..6b5a7b301c 100644 --- a/packages/components/datepicker/src/components/osds-datepicker/osds-datepicker.tsx +++ b/packages/components/datepicker/src/components/osds-datepicker/osds-datepicker.tsx @@ -1,7 +1,7 @@ import type { EventEmitter } from '@stencil/core'; import type { OdsDatepickerAttribute } from './interfaces/attributes'; import type { OdsDatepickerEvent, OdsDatepickerValueChangeEventDetail } from './interfaces/events'; -import { Component, Element, Event, Host, h, Listen, Prop, State, Watch } from '@stencil/core'; +import { Component, Element, Event, Host, h, Listen, Prop, State } from '@stencil/core'; import { ODS_INPUT_TYPE } from '@ovhcloud/ods-component-input'; import { ODS_THEME_COLOR_INTENT } from '@ovhcloud/ods-common-theming'; import { ODS_ICON_NAME } from '@ovhcloud/ods-component-icon'; @@ -34,7 +34,7 @@ export class OsdsDatepicker implements OdsDatepickerAttribute, OdsDatepickerEven @Prop({ reflect: true }) disabled?: boolean = DEFAULT_ATTRIBUTE.disabled; /** @see OdsDatepickerAttribute.error */ - @Prop({ reflect: true }) error?: string = DEFAULT_ATTRIBUTE.error; + @Prop({ reflect: true }) error?: boolean = DEFAULT_ATTRIBUTE.error; /** @see OdsDatepickerAttribute.format */ @Prop({ reflect: true }) format?: string = DEFAULT_ATTRIBUTE.format; @@ -47,22 +47,16 @@ export class OsdsDatepicker implements OdsDatepickerAttribute, OdsDatepickerEven /** Events */ - /** @see OdsDatepickerEvents.odsValueChange */ - @Event() odsValueChange!: EventEmitter; - - /** @see OdsDatepickerEvents.odsDatepickerBlur */ + /** @see OdsDatepickerEvent.odsDatepickerBlur */ @Event() odsDatepickerBlur!: EventEmitter; - /** @see OdsDatepickerEvents.odsDatepickerFocus */ + /** @see OdsDatepickerEvent.odsDatepickerFocus */ @Event() odsDatepickerFocus!: EventEmitter; - /** Watchers */ - - @Watch('value') - onValueChange(value: Date, oldValue?: Date) { - this.controller.onValueChange(value, oldValue); - } + /** @see OdsDatepickerEvent.odsDatepickerValueChange */ + @Event() odsDatepickerValueChange!: EventEmitter; + /** Listening to user's manual input */ @Listen('odsValueChange') handleInputValueChange(event: CustomEvent) { if (this.format && event.detail.value.length === this.format.length) { @@ -86,6 +80,13 @@ export class OsdsDatepicker implements OdsDatepickerAttribute, OdsDatepickerEven this.odsDatepickerFocus.emit(); } + /** + * @see OdsDatepickerBehavior.emitValueChange + */ + emitValueChange(newValue: Date | undefined | null, oldValue?: Date | undefined | null): void { + this.odsDatepickerValueChange.emit({ value: newValue, oldValue: oldValue }); + } + /** * @see OdsDatepickerBehavior.onBlur */ @@ -107,29 +108,18 @@ export class OsdsDatepicker implements OdsDatepickerAttribute, OdsDatepickerEven this.controller.onFocus(); } - /** - * @see OdsInputBehavior.beforeInit - */ - beforeInit() { - this.controller.beforeInit(); - } - - componentWillLoad() { - this.beforeInit(); - } - componentDidLoad() { if(!this.el.shadowRoot) { return; } - const hiddenInput = this.el.shadowRoot.querySelector('.osds-datepicker__hidden-input') as HTMLInputElement; + const hiddenInput = this.el.shadowRoot.querySelector('#hidden-input') as HTMLInputElement; if (!hiddenInput.getAttribute('initialized')) { this.datepickerInstance = new Datepicker(hiddenInput, { format: this.format, - nextArrow: ``, - prevArrow: ``, + nextArrow: ``, + prevArrow: ``, maxView: 2, }); @@ -143,7 +133,7 @@ export class OsdsDatepicker implements OdsDatepickerAttribute, OdsDatepickerEven } formatDate(date?: Date | undefined | null) { - if (this.format && date && this.el.shadowRoot) { + if (this.format && date) { return Datepicker.formatDate(date, this.format); } else { return ''; @@ -162,25 +152,22 @@ export class OsdsDatepicker implements OdsDatepickerAttribute, OdsDatepickerEven return ( this.onBlur(), onFocus: () => this.onFocus(), }}> 0 ? true : false } + error={error} icon={ODS_ICON_NAME.CALENDAR} placeholder={placeholder} type={ODS_INPUT_TYPE.text} value={this.formatDate(value)} > - - { - error - && error.length > 0 - && {error} - } + ); }