From aad579cc625e33d7604e6984ca70c28ecb62ac50 Mon Sep 17 00:00:00 2001 From: Jani Bolkvadze Date: Tue, 15 Dec 2020 19:49:22 +0100 Subject: [PATCH 1/7] [FSPE-3448] Implemented Time Web Component --- .../src/components/time/time.scss | 0 .../src/components/time/time.tsx | 394 ++++++++++++++++++ .../components/time-picker/_examples.pug | 19 + 3 files changed, 413 insertions(+) create mode 100644 src/custom-elements/src/components/time/time.scss create mode 100644 src/custom-elements/src/components/time/time.tsx diff --git a/src/custom-elements/src/components/time/time.scss b/src/custom-elements/src/components/time/time.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/custom-elements/src/components/time/time.tsx b/src/custom-elements/src/components/time/time.tsx new file mode 100644 index 000000000..34935e508 --- /dev/null +++ b/src/custom-elements/src/components/time/time.tsx @@ -0,0 +1,394 @@ +import { + Component, + Event, + EventEmitter, + Method, + Prop, + Watch, + h +} from '@stencil/core'; + +const TIME_CLASSES = { + TIME: 'chi-time-picker', + CONTENT: 'chi-time-picker__content', + HOURS: 'chi-time-picker__hours', + HOUR: 'chi-time-picker__hour', + MINUTES: 'chi-time-picker__minutes', + MINUTE: 'chi-time-picker__minute', + SECONDS: 'chi-time-picker__seconds', + SECOND: 'chi-time-picker__second', + PERIODS: 'chi-time-picker__periods', + PERIOD: 'chi-time-picker__period', +}; + +@Component({ + tag: 'chi-time', + styleUrl: 'time.scss', + scoped: true +}) +export class Time { + /** + * Selected time in the time picker + */ + @Prop({ reflect: true, mutable: true }) value: string; + + /** + * Minimum eligible time + */ + @Prop({ reflect: true }) min: string; + + /** + * Maximum eligible time + */ + @Prop({ reflect: true }) max: string; + + /** + * Seconds + */ + @Prop({ reflect: true }) displaySeconds = false; + + /** + * To specify which days of week to disable + */ + @Prop({ reflect: true }) excludedWeekdays: string; + + /** + * To render Time Picker in 24 hours format + */ + @Prop({ reflect: true }) extended = false; + + /** + * Steps + */ + @Prop({ reflect: true }) stepped: boolean; + + _hour: string; + _minute: string; + _second: string; + _period: string; + + excludedTimesArray = []; + + @Watch('excludedDates') + updateExcludedHours() { + } + + @Watch('value') + timeChanged(newValue: string, oldValue: string) { + if (newValue !== oldValue) { + this.calculateTimePeriods(); + this.value = newValue; + } + } + + // @Watch('min') + // minChanged(newValue: string) { + // } + + // @Watch('max') + // maxChanged(newValue: string) { + // } + + /** + * Sets date + */ + @Method() + async setTime(time: string) { + this.value = time; + } + + /** + * Gets date + */ + @Method() + getTime() { + return Promise.resolve(this.value); + } + + /** + * Time change value event + */ + @Event({ eventName: 'chiTimeChange' }) eventChange: EventEmitter; + + calculateTimePeriods() { + if (!this.value) { + if (this.min) { + this.value = this.min; + this._period = parseInt(this.min.split(':')[0]) < 12 ? 'am' : 'pm'; + } else { + this.value = '00:00:00'; + } + } + + const time = this.value.split(':'); + + this._hour = time[0]; + this._minute = time[1]; + this._second = time[2] ? time[2] : '00'; + this._period = !this.extended && parseInt(time[0]) < 12 ? 'am' : 'pm'; + } + + connectedCallback() { + this.calculateTimePeriods(); + } + + hours() { + const startHour = this.extended ? 24 : 12; + let hourToSet: string; + const setHour = (hour: string) => { + if (this.extended) { + if (hour === '24') { + hourToSet = '00'; + } else { + hourToSet = hour; + } + } else { + if (hour === '12') { + if (this._period === 'am') { + hourToSet = '00'; + } else if (this._period === 'pm') { + hourToSet = hour; + } else { + hourToSet = hour; + } + } else { + if (this._period === 'am') { + hourToSet = hour; + } else if (this._period === 'pm') { + hourToSet = (parseInt(hour) + 12).toString(); + } else { + hourToSet = hour; + } + } + } + + this._hour = hour; + this.value = `${hourToSet}:${this._minute}:${this._second}`; + }; + const hourStatus = (hour: string) => { + let hourStatus = ''; + + if (parseInt(this._hour) === parseInt(hour) || + (!this.extended && + this._period === 'pm' && + parseInt(hour) + 12 === parseInt(this.value.split(':')[0]) + ) || + (!this.extended && + parseInt(hour) + 12 === 24 && parseInt(this.value.split(':')[0]) === 0 + ) || + (this.extended && + parseInt(hour) === 24 && parseInt(this.value.split(':')[0]) === 0 + ) + ) { + hourStatus = '-active'; + } else { + const hourToCompare = this._period === 'pm' ? parseInt(hour) + 12 : parseInt(hour); + + if (this.min) { + const minHour = this.min ? parseInt(this.min.split(':')[0]) : null; + + if (hourToCompare < minHour) { + hourStatus += ' -disabled'; + } + } + + if (this.max) { + const maxHour = this.max ? parseInt(this.max.split(':')[0]) : null; + + if (hourToCompare > maxHour) { + hourStatus += ' -disabled'; + } + } + } + + return hourStatus; + }; + + const hoursToDisplay = [ +
setHour(startHour.toString())}>{startHour}
+ ]; + + Array.from(Array(startHour), (_, i) => { + const hour = (i).toString().length > 1 ? (i).toString() : `0${i}`; + + if (i > 0) { + hoursToDisplay.push( +
setHour(hour)}> + {hour} +
+ ); + } + }); + + return ( +
+ {hoursToDisplay} +
+ ); + } + + minutes() { + const minutesToDisplay = [ +
setMinute('00')}>00
+ ]; + const setMinute = (minute: string) => { + this._minute = minute; + this.value = `${this._hour}:${this._minute}:${this._second}`; + }; + + Array.from(Array(60), (_, i) => { + const minute = (i).toString().length > 1 ? (i).toString() : `0${i}`; + const displayminute = () => { + minutesToDisplay.push(
setMinute(minute)}>{minute}
); + }; + + if (i > 0) { + if (this.stepped) { + if (i % 15 === 0) { + displayminute(); + } + } else { + displayminute(); + } + } + }); + + return ( +
{ + minutesToDisplay + }
+ ); + } + + seconds() { + const secondsToDisplay = [ +
setSecond('00')}>00
+ ]; + const setSecond = (second: string) => { + this._second = second; + this.value = `${this._hour}:${this._minute}:${this._second}`; + }; + + Array.from(Array(60), (_, i) => { + const second = (i).toString().length > 1 ? (i).toString() : `0${i}`; + const displaySecond = () => { + secondsToDisplay.push(
setSecond(second)}>{second}
); + }; + + if (i > 0) { + if (this.stepped) { + if (i % 10 === 0) { + displaySecond(); + } + } else { + displaySecond(); + } + } + }); + + if (this.displaySeconds) { + return ( +
{ + secondsToDisplay + }
+ ); + } return; + } + + periods() { + const hour = parseInt(this.value.split(':')[0]); + if (!this.extended) { + const periodlasses = (period: 'am' | 'pm') => { + let periodStatus = TIME_CLASSES.PERIOD; + + if (period === this._period) { + periodStatus += ' -active'; + } + + return periodStatus; + }; + + const setPeriod = (period: string) => { + this._period = period; + let currentHour = hour; + + if (period === 'am') { + if (currentHour > 12) { + currentHour = currentHour - 12; + } + if (currentHour === 12) { + currentHour = 0; + } + } else if (period === 'pm') { + if (currentHour < 12) { + currentHour = currentHour + 12; + } + if (currentHour === 12) { + currentHour = 12; + } + } + + this._hour = currentHour.toString(); + this.value = `${currentHour}:${this._minute}:${this._second}`; + }; + + return ( +
+
setPeriod('am')}>AM
+
setPeriod('pm')}>PM
+
+ ); + } return; + } + + render() { + const hours = this.hours(); + const minutes = this.minutes(); + const seconds = this.seconds(); + const periods = this.periods(); + + console.log(this._period); + console.log(this.value); + + return ( +
+
+ {hours} + {minutes} + {seconds} + {periods} +
+
+ ); + } +} diff --git a/src/website/views/components/time-picker/_examples.pug b/src/website/views/components/time-picker/_examples.pug index 261dbdde8..aac8e4dba 100644 --- a/src/website/views/components/time-picker/_examples.pug +++ b/src/website/views/components/time-picker/_examples.pug @@ -233,6 +233,25 @@ h4 Base .chi-time-picker__periods .chi-time-picker__period AM .chi-time-picker__period PM + .chi-grid + .chi-col.-w--6 + .-text--h3 12 hours format + chi-time + .chi-col.-w--6 + .-text--h3 24 hours format + chi-time(extended) + .chi-col.-w--6 + .-text--h3 Active time + chi-time(value='11:00') + .chi-col.-w--6 + .-text--h3 Min & MAX + chi-time(min='14:00:00', max='20:00:00') + .chi-col.-w--6 + .-text--h3 Seconds + chi-time(display-seconds) + .chi-col.-w--6 + .-text--h3 Stepped + chi-time(stepped, display-seconds) .example-tabs.-pl--2 ul.chi-tabs#example-time li.-active From 04ba9b30de8b4f12ff4407cf029c5a19339b0a77 Mon Sep 17 00:00:00 2001 From: Jani Bolkvadze Date: Wed, 16 Dec 2020 00:25:03 +0100 Subject: [PATCH 2/7] Implemented Time Picker Web Component --- .../components/time-picker/time-picker.scss | 0 .../components/time-picker/time-picker.tsx | 153 +++++ .../src/components/time/time.tsx | 76 +-- .../components/time-picker/_examples.pug | 602 +----------------- 4 files changed, 207 insertions(+), 624 deletions(-) create mode 100644 src/custom-elements/src/components/time-picker/time-picker.scss create mode 100644 src/custom-elements/src/components/time-picker/time-picker.tsx diff --git a/src/custom-elements/src/components/time-picker/time-picker.scss b/src/custom-elements/src/components/time-picker/time-picker.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/custom-elements/src/components/time-picker/time-picker.tsx b/src/custom-elements/src/components/time-picker/time-picker.tsx new file mode 100644 index 000000000..f6b52b75a --- /dev/null +++ b/src/custom-elements/src/components/time-picker/time-picker.tsx @@ -0,0 +1,153 @@ +import { Component, Element, Listen, Method, Prop, h } from '@stencil/core'; +import { contains, uuid4 } from '../../utils/utils'; +import { ESCAPE_KEYCODE } from '../../constants/constants'; + +@Component({ + tag: 'chi-time-picker', + scoped: true +}) +export class TimePicker { + /** + * Selected time of Time Picker + */ + @Prop({ reflect: true, mutable: true }) value: string; + + /** + * Minimum eligible time + */ + @Prop({ reflect: true }) min: string; + + /** + * Maximum eligible time + */ + @Prop({ reflect: true }) max: string; + + /** + * To disable chi-time-picker. + */ + @Prop({ reflect: true }) disabled = false; + + /** + * To specify excluded hours. + */ + @Prop({ reflect: true }) excludedHours: string; + + /** + * Indicates whether the time picker dropdown is open or closed + */ + @Prop({ reflect: true, mutable: true }) active = false; + + @Element() el: HTMLElement; + + private _input: HTMLInputElement; + private _uuid: string; + + _onFocusIn(e) { + if (e.target !== document.body && e.target !== null) { + this.active = contains(this.el, e.target); + } + } + + _onClick(e) { + if ( + e.target !== document.body && + e.target !== null + ) { + this.active = contains(this.el, e.target); + } + } + + _onKeyUp(e) { + if ( + 'key' in e && + (e.key === 'Escape' || e.key === 'Esc' || e.key === ESCAPE_KEYCODE) + ) { + this.active = false; + this._input.blur(); + } + } + + /** + * Sets time + */ + @Method() + async setTime(time: string) { + this.value = time; + } + + /** + * Gets time + */ + @Method() + getTime() { + return Promise.resolve(this.value); + } + + @Listen('chiTimeChange') + handleTimeChange(ev) { + ev.stopPropagation(); + this._input.value = ev.detail; + this.value = ev.detail; + this.active = false; + this._input.blur(); + } + + componentWillLoad(): void { + this._onFocusIn = this._onFocusIn.bind(this); + this._onClick = this._onClick.bind(this); + this._onKeyUp = this._onKeyUp.bind(this); + this._uuid = this.el.id ? this.el.id : `tp-${uuid4()}`; + } + + componentDidLoad(): void { + document.body.addEventListener('focusin', this._onFocusIn); + document.body.addEventListener('click', this._onClick); + document.body.addEventListener('keyup', this._onKeyUp); + } + + componentDidUnload(): void { + document.body.removeEventListener('focusin', this._onFocusIn); + document.body.removeEventListener('click', this._onClick); + document.body.removeEventListener('keyup', this._onKeyUp); + } + + render() { + const chiPopover = ( + + + + ); + + return ( +
+
+ (this._input = el as HTMLInputElement)} + value={this.value} + disabled={this.disabled} + /> + +
+ {!this.disabled && chiPopover} +
+ ); + } +} diff --git a/src/custom-elements/src/components/time/time.tsx b/src/custom-elements/src/components/time/time.tsx index 34935e508..c4ede2c93 100644 --- a/src/custom-elements/src/components/time/time.tsx +++ b/src/custom-elements/src/components/time/time.tsx @@ -2,7 +2,6 @@ import { Component, Event, EventEmitter, - Method, Prop, Watch, h @@ -43,34 +42,39 @@ export class Time { @Prop({ reflect: true }) max: string; /** - * Seconds + * Displaying seconds column */ @Prop({ reflect: true }) displaySeconds = false; - /** - * To specify which days of week to disable - */ - @Prop({ reflect: true }) excludedWeekdays: string; - /** * To render Time Picker in 24 hours format */ @Prop({ reflect: true }) extended = false; /** - * Steps + * To render Minutes and Seconds columns in stepped format */ @Prop({ reflect: true }) stepped: boolean; + /** + * To disable specific hours + */ + @Prop({ reflect: true }) excludedHours: string; + _hour: string; _minute: string; _second: string; _period: string; - excludedTimesArray = []; + excludedHoursArray = []; - @Watch('excludedDates') + @Watch('excluded-hours') updateExcludedHours() { + if (this.excludedHours) { + this.excludedHours.split(',').map(time => { + this.excludedHoursArray.push(time.trim()); + }); + } } @Watch('value') @@ -81,30 +85,6 @@ export class Time { } } - // @Watch('min') - // minChanged(newValue: string) { - // } - - // @Watch('max') - // maxChanged(newValue: string) { - // } - - /** - * Sets date - */ - @Method() - async setTime(time: string) { - this.value = time; - } - - /** - * Gets date - */ - @Method() - getTime() { - return Promise.resolve(this.value); - } - /** * Time change value event */ @@ -130,6 +110,11 @@ export class Time { connectedCallback() { this.calculateTimePeriods(); + if (this.excludedHours) { + this.excludedHours.split(',').map(time => { + this.excludedHoursArray.push(time.trim()); + }); + } } hours() { @@ -146,15 +131,11 @@ export class Time { if (hour === '12') { if (this._period === 'am') { hourToSet = '00'; - } else if (this._period === 'pm') { - hourToSet = hour; } else { hourToSet = hour; } } else { - if (this._period === 'am') { - hourToSet = hour; - } else if (this._period === 'pm') { + if (this._period === 'pm') { hourToSet = (parseInt(hour) + 12).toString(); } else { hourToSet = hour; @@ -166,19 +147,15 @@ export class Time { this.value = `${hourToSet}:${this._minute}:${this._second}`; }; const hourStatus = (hour: string) => { + const valueHour = parseInt(this.value.split(':')[0]); let hourStatus = ''; if (parseInt(this._hour) === parseInt(hour) || (!this.extended && this._period === 'pm' && - parseInt(hour) + 12 === parseInt(this.value.split(':')[0]) - ) || - (!this.extended && - parseInt(hour) + 12 === 24 && parseInt(this.value.split(':')[0]) === 0 + parseInt(hour) + 12 === valueHour ) || - (this.extended && - parseInt(hour) === 24 && parseInt(this.value.split(':')[0]) === 0 - ) + (parseInt(hour) === 12 && valueHour === 0) ) { hourStatus = '-active'; } else { @@ -199,6 +176,12 @@ export class Time { hourStatus += ' -disabled'; } } + + const formattedHour = parseInt(hour) < 10 ? (parseInt(hour) + 12).toString() : hour; + + if (this.excludedHoursArray.includes(formattedHour)) { + hourStatus += ' -disabled'; + } } return hourStatus; @@ -375,7 +358,6 @@ export class Time { const seconds = this.seconds(); const periods = this.periods(); - console.log(this._period); console.log(this.value); return ( diff --git a/src/website/views/components/time-picker/_examples.pug b/src/website/views/components/time-picker/_examples.pug index aac8e4dba..c3c046e0f 100644 --- a/src/website/views/components/time-picker/_examples.pug +++ b/src/website/views/components/time-picker/_examples.pug @@ -5,11 +5,8 @@ p.-text .example.-mb--3 .-p--3 div.chi-form__item(style="max-width: 14rem;") - label.chi-label(for='unique-id-ba1') - | Time - div.chi-input__wrapper.-icon--right - input.chi-input(type="time" id="unique-id-ba1") - i.chi-icon.icon-circle-clock-outline.-icon--muted + chi-label(for="time-picker-base") Label + chi-time-picker(id="time-picker-base") .example-tabs.-pl--2 ul.chi-tabs#example-with-label li.-active @@ -18,14 +15,9 @@ p.-text a(href=`#html-with-label`) HTML Blueprint #webcomponent-with-label.chi-tabs-panel.-active :code(lang="html",style="height:20rem") - Time - + Label + #html-with-label.chi-tabs-panel - .chi-tab__description - span.-text--grey - | This HTML Blueprint requires JavaScript. - | You may use your own solution, or use Chi's vanilla JavaScript solution, - | Chi.js. :code(lang="html")
@@ -35,8 +27,6 @@ p.-text
- - h3 Disabled p.-text | Use the disabled boolean attribute to prevent users from interacting with an input. @@ -45,11 +35,8 @@ p.-text .example.-mb--3(style="z-index: 1;") .-p--3 div.chi-form__item(style="max-width: 14rem;") - label.chi-label(for='unique-id-di1') - | Time - div.chi-input__wrapper.-icon--right - input.chi-input(type="time" id="unique-id-di1" disabled) - i.chi-icon.icon-circle-clock-outline.-icon--muted + chi-label(for="time-picker-disabled") Label + chi-time-picker(id="time-picker-disabled" disabled) .example-tabs.-pl--2 ul.chi-tabs#example-disabled li.-active @@ -58,8 +45,8 @@ p.-text a(href=`#html-disabled`) HTML Blueprint #webcomponent-disabled.chi-tabs-panel.-active :code(lang="html") - Time - + Label + #html-disabled.chi-tabs-panel .chi-tab__description span.-text--grey @@ -75,17 +62,12 @@ p.-text - - h3 Value, min and max options .example.-mb--3 .-p--3 div.chi-form__item(style="max-width: 14rem;") - label.chi-label(for='unique-id-va1') - | Time - div.chi-input__wrapper.-icon--right - input.chi-input(type="time" id="unique-id-va1") - i.chi-icon.icon-circle-clock-outline.-icon--muted + chi-label(for='unique-id-va1') Time + chi-time-picker#unique-id-va1(value='09:00:00', min='09:00:00', max='18:00:00') .example-tabs.-pl--2 ul.chi-tabs#example-min-max-value li.-active @@ -111,30 +93,14 @@ h3 Value, min and max options - - - - - -h3 Excluded times +h3 Excluded hours p.-text - | Specify which times to disable by using the excluded-times attribute. + | Specify which hours to disable by using the excluded-hours attribute. .example.-mb--3 .-p--3 div.chi-form__item(style="max-width: 14rem;") - label.chi-label(for='unique-id-et1') - | Time - div.chi-input__wrapper.-icon--right - input.chi-input(type="time" id="unique-id-et1") - i.chi-icon.icon-circle-clock-outline.-icon--muted + chi-label(for="time-picker-excluded-hours") Label + chi-time-picker(id="time-picker-excluded-hours", excluded-hours="14, 15") .example-tabs.-pl--2 ul.chi-tabs#example-excluded-times li.-active @@ -144,114 +110,16 @@ p.-text #webcomponent-excluded-times.chi-tabs-panel.-active :code(lang="html",style="height:20rem") Time - + #html-excluded-times.chi-tabs-panel - h3 Time p.-text | An example of a time picker not attached to any element. h4 Base .example.-mb--3 .-p--3 - .chi-time-picker - .chi-time-picker__content - .chi-time-picker__hours - .chi-time-picker__hour 12 - .chi-time-picker__hour 01 - .chi-time-picker__hour 02 - .chi-time-picker__hour 03 - .chi-time-picker__hour 04 - .chi-time-picker__hour 05 - .chi-time-picker__hour 06 - .chi-time-picker__hour 07 - .chi-time-picker__hour 08 - .chi-time-picker__hour 09 - .chi-time-picker__hour 10 - .chi-time-picker__hour 11 - .chi-time-picker__minutes - .chi-time-picker__minute 00 - .chi-time-picker__minute 01 - .chi-time-picker__minute 02 - .chi-time-picker__minute 03 - .chi-time-picker__minute 04 - .chi-time-picker__minute 05 - .chi-time-picker__minute 06 - .chi-time-picker__minute 07 - .chi-time-picker__minute 08 - .chi-time-picker__minute 09 - .chi-time-picker__minute 10 - .chi-time-picker__minute 11 - .chi-time-picker__minute 12 - .chi-time-picker__minute 13 - .chi-time-picker__minute 14 - .chi-time-picker__minute 15 - .chi-time-picker__minute 16 - .chi-time-picker__minute 17 - .chi-time-picker__minute 18 - .chi-time-picker__minute 19 - .chi-time-picker__minute 20 - .chi-time-picker__minute 21 - .chi-time-picker__minute 22 - .chi-time-picker__minute 23 - .chi-time-picker__minute 24 - .chi-time-picker__minute 25 - .chi-time-picker__minute 26 - .chi-time-picker__minute 27 - .chi-time-picker__minute 28 - .chi-time-picker__minute 29 - .chi-time-picker__minute 30 - .chi-time-picker__minute 31 - .chi-time-picker__minute 32 - .chi-time-picker__minute 33 - .chi-time-picker__minute 34 - .chi-time-picker__minute 35 - .chi-time-picker__minute 36 - .chi-time-picker__minute 37 - .chi-time-picker__minute 38 - .chi-time-picker__minute 39 - .chi-time-picker__minute 40 - .chi-time-picker__minute 41 - .chi-time-picker__minute 42 - .chi-time-picker__minute 43 - .chi-time-picker__minute 44 - .chi-time-picker__minute 45 - .chi-time-picker__minute 46 - .chi-time-picker__minute 47 - .chi-time-picker__minute 48 - .chi-time-picker__minute 49 - .chi-time-picker__minute 50 - .chi-time-picker__minute 51 - .chi-time-picker__minute 52 - .chi-time-picker__minute 53 - .chi-time-picker__minute 54 - .chi-time-picker__minute 55 - .chi-time-picker__minute 56 - .chi-time-picker__minute 57 - .chi-time-picker__minute 58 - .chi-time-picker__minute 59 - .chi-time-picker__periods - .chi-time-picker__period AM - .chi-time-picker__period PM - .chi-grid - .chi-col.-w--6 - .-text--h3 12 hours format - chi-time - .chi-col.-w--6 - .-text--h3 24 hours format - chi-time(extended) - .chi-col.-w--6 - .-text--h3 Active time - chi-time(value='11:00') - .chi-col.-w--6 - .-text--h3 Min & MAX - chi-time(min='14:00:00', max='20:00:00') - .chi-col.-w--6 - .-text--h3 Seconds - chi-time(display-seconds) - .chi-col.-w--6 - .-text--h3 Stepped - chi-time(stepped, display-seconds) + chi-time .example-tabs.-pl--2 ul.chi-tabs#example-time li.-active @@ -272,85 +140,7 @@ h4 Base h4 Active .example.-mb--3 .-p--3 - .chi-time-picker - .chi-time-picker__content - .chi-time-picker__hours - .chi-time-picker__hour.-active 12 - .chi-time-picker__hour 01 - .chi-time-picker__hour 02 - .chi-time-picker__hour 03 - .chi-time-picker__hour 04 - .chi-time-picker__hour 05 - .chi-time-picker__hour 06 - .chi-time-picker__hour 07 - .chi-time-picker__hour 08 - .chi-time-picker__hour 09 - .chi-time-picker__hour 10 - .chi-time-picker__hour 11 - .chi-time-picker__minutes - .chi-time-picker__minute.-active 00 - .chi-time-picker__minute 01 - .chi-time-picker__minute 02 - .chi-time-picker__minute 03 - .chi-time-picker__minute 04 - .chi-time-picker__minute 05 - .chi-time-picker__minute 06 - .chi-time-picker__minute 07 - .chi-time-picker__minute 08 - .chi-time-picker__minute 09 - .chi-time-picker__minute 10 - .chi-time-picker__minute 11 - .chi-time-picker__minute 12 - .chi-time-picker__minute 13 - .chi-time-picker__minute 14 - .chi-time-picker__minute 15 - .chi-time-picker__minute 16 - .chi-time-picker__minute 17 - .chi-time-picker__minute 18 - .chi-time-picker__minute 19 - .chi-time-picker__minute 20 - .chi-time-picker__minute 21 - .chi-time-picker__minute 22 - .chi-time-picker__minute 23 - .chi-time-picker__minute 24 - .chi-time-picker__minute 25 - .chi-time-picker__minute 26 - .chi-time-picker__minute 27 - .chi-time-picker__minute 28 - .chi-time-picker__minute 29 - .chi-time-picker__minute 30 - .chi-time-picker__minute 31 - .chi-time-picker__minute 32 - .chi-time-picker__minute 33 - .chi-time-picker__minute 34 - .chi-time-picker__minute 35 - .chi-time-picker__minute 36 - .chi-time-picker__minute 37 - .chi-time-picker__minute 38 - .chi-time-picker__minute 39 - .chi-time-picker__minute 40 - .chi-time-picker__minute 41 - .chi-time-picker__minute 42 - .chi-time-picker__minute 43 - .chi-time-picker__minute 44 - .chi-time-picker__minute 45 - .chi-time-picker__minute 46 - .chi-time-picker__minute 47 - .chi-time-picker__minute 48 - .chi-time-picker__minute 49 - .chi-time-picker__minute 50 - .chi-time-picker__minute 51 - .chi-time-picker__minute 52 - .chi-time-picker__minute 53 - .chi-time-picker__minute 54 - .chi-time-picker__minute 55 - .chi-time-picker__minute 56 - .chi-time-picker__minute 57 - .chi-time-picker__minute 58 - .chi-time-picker__minute 59 - .chi-time-picker__periods - .chi-time-picker__period.-active AM - .chi-time-picker__period PM + chi-time(value="14:00:00") .example-tabs.-pl--2 ul.chi-tabs#example-active li.-active @@ -359,7 +149,7 @@ h4 Active a(href=`#html-active`) HTML Blueprint #webcomponent-active.chi-tabs-panel.-active :code(lang="html") - + #html-active.chi-tabs-panel .chi-tab__description span.-text--grey @@ -371,85 +161,7 @@ h4 Active h4 Min and Max .example.-mb--3 .-p--3 - .chi-time-picker - .chi-time-picker__content - .chi-time-picker__hours - .chi-time-picker__hour.-active 12 - .chi-time-picker__hour 01 - .chi-time-picker__hour 02 - .chi-time-picker__hour.-disabled 03 - .chi-time-picker__hour.-disabled 04 - .chi-time-picker__hour.-disabled 05 - .chi-time-picker__hour.-disabled 06 - .chi-time-picker__hour.-disabled 07 - .chi-time-picker__hour.-disabled 08 - .chi-time-picker__hour.-disabled 09 - .chi-time-picker__hour.-disabled 10 - .chi-time-picker__hour.-disabled 11 - .chi-time-picker__minutes - .chi-time-picker__minute.-active 00 - .chi-time-picker__minute 01 - .chi-time-picker__minute 02 - .chi-time-picker__minute 03 - .chi-time-picker__minute 04 - .chi-time-picker__minute 05 - .chi-time-picker__minute 06 - .chi-time-picker__minute 07 - .chi-time-picker__minute 08 - .chi-time-picker__minute 09 - .chi-time-picker__minute 10 - .chi-time-picker__minute 11 - .chi-time-picker__minute 12 - .chi-time-picker__minute 13 - .chi-time-picker__minute 14 - .chi-time-picker__minute 15 - .chi-time-picker__minute 16 - .chi-time-picker__minute 17 - .chi-time-picker__minute 18 - .chi-time-picker__minute 19 - .chi-time-picker__minute 20 - .chi-time-picker__minute 21 - .chi-time-picker__minute 22 - .chi-time-picker__minute 23 - .chi-time-picker__minute 24 - .chi-time-picker__minute 25 - .chi-time-picker__minute 26 - .chi-time-picker__minute 27 - .chi-time-picker__minute 28 - .chi-time-picker__minute 29 - .chi-time-picker__minute 30 - .chi-time-picker__minute 31 - .chi-time-picker__minute 32 - .chi-time-picker__minute 33 - .chi-time-picker__minute 34 - .chi-time-picker__minute 35 - .chi-time-picker__minute 36 - .chi-time-picker__minute 37 - .chi-time-picker__minute 38 - .chi-time-picker__minute 39 - .chi-time-picker__minute 40 - .chi-time-picker__minute 41 - .chi-time-picker__minute 42 - .chi-time-picker__minute 43 - .chi-time-picker__minute 44 - .chi-time-picker__minute 45 - .chi-time-picker__minute 46 - .chi-time-picker__minute 47 - .chi-time-picker__minute 48 - .chi-time-picker__minute 49 - .chi-time-picker__minute 50 - .chi-time-picker__minute 51 - .chi-time-picker__minute 52 - .chi-time-picker__minute 53 - .chi-time-picker__minute 54 - .chi-time-picker__minute 55 - .chi-time-picker__minute 56 - .chi-time-picker__minute 57 - .chi-time-picker__minute 58 - .chi-time-picker__minute 59 - .chi-time-picker__periods - .chi-time-picker__period.-active AM - .chi-time-picker__period.-disabled PM + chi-time(min="14:00:00", value="17:00:00", max="20:00:00") .example-tabs.-pl--2 ul.chi-tabs#example-min-max li.-active @@ -458,7 +170,7 @@ h4 Min and Max a(href=`#html-min-max`) HTML Blueprint #webcomponent-min-max.chi-tabs-panel.-active :code(lang="html") - + #html-min-max.chi-tabs-panel .chi-tab__description span.-text--grey @@ -470,146 +182,7 @@ h4 Min and Max h4 Seconds .example.-mb--3 .-p--3 - .chi-time-picker - .chi-time-picker__content - .chi-time-picker__hours - .chi-time-picker__hour 12 - .chi-time-picker__hour 01 - .chi-time-picker__hour 02 - .chi-time-picker__hour 03 - .chi-time-picker__hour 04 - .chi-time-picker__hour 05 - .chi-time-picker__hour 06 - .chi-time-picker__hour 07 - .chi-time-picker__hour 08 - .chi-time-picker__hour 09 - .chi-time-picker__hour 10 - .chi-time-picker__hour 11 - .chi-time-picker__minutes - .chi-time-picker__minute 00 - .chi-time-picker__minute 01 - .chi-time-picker__minute 02 - .chi-time-picker__minute 03 - .chi-time-picker__minute 04 - .chi-time-picker__minute 05 - .chi-time-picker__minute 06 - .chi-time-picker__minute 07 - .chi-time-picker__minute 08 - .chi-time-picker__minute 09 - .chi-time-picker__minute 10 - .chi-time-picker__minute 11 - .chi-time-picker__minute 12 - .chi-time-picker__minute 13 - .chi-time-picker__minute 14 - .chi-time-picker__minute 15 - .chi-time-picker__minute 16 - .chi-time-picker__minute 17 - .chi-time-picker__minute 18 - .chi-time-picker__minute 19 - .chi-time-picker__minute 20 - .chi-time-picker__minute 21 - .chi-time-picker__minute 22 - .chi-time-picker__minute 23 - .chi-time-picker__minute 24 - .chi-time-picker__minute 25 - .chi-time-picker__minute 26 - .chi-time-picker__minute 27 - .chi-time-picker__minute 28 - .chi-time-picker__minute 29 - .chi-time-picker__minute 30 - .chi-time-picker__minute 31 - .chi-time-picker__minute 32 - .chi-time-picker__minute 33 - .chi-time-picker__minute 34 - .chi-time-picker__minute 35 - .chi-time-picker__minute 36 - .chi-time-picker__minute 37 - .chi-time-picker__minute 38 - .chi-time-picker__minute 39 - .chi-time-picker__minute 40 - .chi-time-picker__minute 41 - .chi-time-picker__minute 42 - .chi-time-picker__minute 43 - .chi-time-picker__minute 44 - .chi-time-picker__minute 45 - .chi-time-picker__minute 46 - .chi-time-picker__minute 47 - .chi-time-picker__minute 48 - .chi-time-picker__minute 49 - .chi-time-picker__minute 50 - .chi-time-picker__minute 51 - .chi-time-picker__minute 52 - .chi-time-picker__minute 53 - .chi-time-picker__minute 54 - .chi-time-picker__minute 55 - .chi-time-picker__minute 56 - .chi-time-picker__minute 57 - .chi-time-picker__minute 58 - .chi-time-picker__minute 59 - .chi-time-picker__seconds - .chi-time-picker__second 00 - .chi-time-picker__second 01 - .chi-time-picker__second 02 - .chi-time-picker__second 03 - .chi-time-picker__second 04 - .chi-time-picker__second 05 - .chi-time-picker__second 06 - .chi-time-picker__second 07 - .chi-time-picker__second 08 - .chi-time-picker__second 09 - .chi-time-picker__second 10 - .chi-time-picker__second 11 - .chi-time-picker__second 12 - .chi-time-picker__second 13 - .chi-time-picker__second 14 - .chi-time-picker__second 15 - .chi-time-picker__second 16 - .chi-time-picker__second 17 - .chi-time-picker__second 18 - .chi-time-picker__second 19 - .chi-time-picker__second 20 - .chi-time-picker__second 21 - .chi-time-picker__second 22 - .chi-time-picker__second 23 - .chi-time-picker__second 24 - .chi-time-picker__second 25 - .chi-time-picker__second 26 - .chi-time-picker__second 27 - .chi-time-picker__second 28 - .chi-time-picker__second 29 - .chi-time-picker__second 30 - .chi-time-picker__second 31 - .chi-time-picker__second 32 - .chi-time-picker__second 33 - .chi-time-picker__second 34 - .chi-time-picker__second 35 - .chi-time-picker__second 36 - .chi-time-picker__second 37 - .chi-time-picker__second 38 - .chi-time-picker__second 39 - .chi-time-picker__second 40 - .chi-time-picker__second 41 - .chi-time-picker__second 42 - .chi-time-picker__second 43 - .chi-time-picker__second 44 - .chi-time-picker__second 45 - .chi-time-picker__second 46 - .chi-time-picker__second 47 - .chi-time-picker__second 48 - .chi-time-picker__second 49 - .chi-time-picker__second 50 - .chi-time-picker__second 51 - .chi-time-picker__second 52 - .chi-time-picker__second 53 - .chi-time-picker__second 54 - .chi-time-picker__second 55 - .chi-time-picker__second 56 - .chi-time-picker__second 57 - .chi-time-picker__second 58 - .chi-time-picker__second 59 - .chi-time-picker__periods - .chi-time-picker__period AM - .chi-time-picker__period PM + chi-time(display-seconds) .example-tabs.-pl--2 ul.chi-tabs#example-seconds li.-active @@ -630,94 +203,7 @@ h4 Seconds h4 24-hour format .example.-mb--3 .-p--3 - .chi-time-picker - .chi-time-picker__content - .chi-time-picker__hours - .chi-time-picker__hour 00 - .chi-time-picker__hour 01 - .chi-time-picker__hour 02 - .chi-time-picker__hour 03 - .chi-time-picker__hour 04 - .chi-time-picker__hour 05 - .chi-time-picker__hour 06 - .chi-time-picker__hour 07 - .chi-time-picker__hour 08 - .chi-time-picker__hour 09 - .chi-time-picker__hour 10 - .chi-time-picker__hour 11 - .chi-time-picker__hour 12 - .chi-time-picker__hour 13 - .chi-time-picker__hour 14 - .chi-time-picker__hour 15 - .chi-time-picker__hour 16 - .chi-time-picker__hour 17 - .chi-time-picker__hour 18 - .chi-time-picker__hour 19 - .chi-time-picker__hour 20 - .chi-time-picker__hour 21 - .chi-time-picker__hour 22 - .chi-time-picker__hour 23 - .chi-time-picker__minutes - .chi-time-picker__minute 00 - .chi-time-picker__minute 01 - .chi-time-picker__minute 02 - .chi-time-picker__minute 03 - .chi-time-picker__minute 04 - .chi-time-picker__minute 05 - .chi-time-picker__minute 06 - .chi-time-picker__minute 07 - .chi-time-picker__minute 08 - .chi-time-picker__minute 09 - .chi-time-picker__minute 10 - .chi-time-picker__minute 11 - .chi-time-picker__minute 12 - .chi-time-picker__minute 13 - .chi-time-picker__minute 14 - .chi-time-picker__minute 15 - .chi-time-picker__minute 16 - .chi-time-picker__minute 17 - .chi-time-picker__minute 18 - .chi-time-picker__minute 19 - .chi-time-picker__minute 20 - .chi-time-picker__minute 21 - .chi-time-picker__minute 22 - .chi-time-picker__minute 23 - .chi-time-picker__minute 24 - .chi-time-picker__minute 25 - .chi-time-picker__minute 26 - .chi-time-picker__minute 27 - .chi-time-picker__minute 28 - .chi-time-picker__minute 29 - .chi-time-picker__minute 30 - .chi-time-picker__minute 31 - .chi-time-picker__minute 32 - .chi-time-picker__minute 33 - .chi-time-picker__minute 34 - .chi-time-picker__minute 35 - .chi-time-picker__minute 36 - .chi-time-picker__minute 37 - .chi-time-picker__minute 38 - .chi-time-picker__minute 39 - .chi-time-picker__minute 40 - .chi-time-picker__minute 41 - .chi-time-picker__minute 42 - .chi-time-picker__minute 43 - .chi-time-picker__minute 44 - .chi-time-picker__minute 45 - .chi-time-picker__minute 46 - .chi-time-picker__minute 47 - .chi-time-picker__minute 48 - .chi-time-picker__minute 49 - .chi-time-picker__minute 50 - .chi-time-picker__minute 51 - .chi-time-picker__minute 52 - .chi-time-picker__minute 53 - .chi-time-picker__minute 54 - .chi-time-picker__minute 55 - .chi-time-picker__minute 56 - .chi-time-picker__minute 57 - .chi-time-picker__minute 58 - .chi-time-picker__minute 59 + chi-time(extended) .example-tabs.-pl--2 ul.chi-tabs#example-24hour li.-active @@ -726,7 +212,7 @@ h4 24-hour format a(href=`#html-24hour`) HTML Blueprint #webcomponent-24hour.chi-tabs-panel.-active :code(lang="html") - + extended #html-24hour.chi-tabs-panel .chi-tab__description span.-text--grey @@ -738,45 +224,7 @@ h4 24-hour format h4 Step .example.-mb--3 .-p--3 - .chi-time-picker - .chi-time-picker__content - .chi-time-picker__hours - .chi-time-picker__hour 00 - .chi-time-picker__hour 01 - .chi-time-picker__hour 02 - .chi-time-picker__hour 03 - .chi-time-picker__hour 04 - .chi-time-picker__hour 05 - .chi-time-picker__hour 06 - .chi-time-picker__hour 07 - .chi-time-picker__hour 08 - .chi-time-picker__hour 09 - .chi-time-picker__hour 10 - .chi-time-picker__hour 11 - .chi-time-picker__hour 12 - .chi-time-picker__hour 13 - .chi-time-picker__hour 14 - .chi-time-picker__hour 15 - .chi-time-picker__hour 16 - .chi-time-picker__hour 17 - .chi-time-picker__hour 18 - .chi-time-picker__hour 19 - .chi-time-picker__hour 20 - .chi-time-picker__hour 21 - .chi-time-picker__hour 22 - .chi-time-picker__hour 23 - .chi-time-picker__minutes - .chi-time-picker__minute 00 - .chi-time-picker__minute 15 - .chi-time-picker__minute 30 - .chi-time-picker__minute 45 - .chi-time-picker__seconds - .chi-time-picker__second 00 - .chi-time-picker__second 10 - .chi-time-picker__second 20 - .chi-time-picker__second 30 - .chi-time-picker__second 40 - .chi-time-picker__second 50 + chi-time(stepped, display-seconds) .example-tabs.-pl--2 ul.chi-tabs#example-step li.-active @@ -785,7 +233,7 @@ h4 Step a(href=`#html-step`) HTML Blueprint #webcomponent-step.chi-tabs-panel.-active :code(lang="html") - + #html-step.chi-tabs-panel .chi-tab__description span.-text--grey From 840ca8e4d24d33f665c8ffb5390c3c38bc583881 Mon Sep 17 00:00:00 2001 From: Jani Bolkvadze Date: Thu, 17 Dec 2020 02:44:09 +0100 Subject: [PATCH 3/7] Added support of updating Time Picker input value --- .../components/time-picker/time-picker.scss | 1 + .../components/time-picker/time-picker.tsx | 78 ++++++++---- .../src/components/time/time.tsx | 114 ++++++++++-------- src/custom-elements/src/constants/classes.ts | 12 ++ .../components/time-picker/_examples.pug | 16 +-- 5 files changed, 139 insertions(+), 82 deletions(-) create mode 100644 src/custom-elements/src/constants/classes.ts diff --git a/src/chi/components/time-picker/time-picker.scss b/src/chi/components/time-picker/time-picker.scss index c2abebbd2..0049be644 100644 --- a/src/chi/components/time-picker/time-picker.scss +++ b/src/chi/components/time-picker/time-picker.scss @@ -54,6 +54,7 @@ background-color: $color-background-primary; color: $color-text-white; font-weight: $font-weight-semi-bold; + pointer-events: none; } &.-disabled { diff --git a/src/custom-elements/src/components/time-picker/time-picker.tsx b/src/custom-elements/src/components/time-picker/time-picker.tsx index f6b52b75a..2c3cb4bcc 100644 --- a/src/custom-elements/src/components/time-picker/time-picker.tsx +++ b/src/custom-elements/src/components/time-picker/time-picker.tsx @@ -1,6 +1,7 @@ import { Component, Element, Listen, Method, Prop, h } from '@stencil/core'; import { contains, uuid4 } from '../../utils/utils'; import { ESCAPE_KEYCODE } from '../../constants/constants'; +import { TIME_CLASSES } from '../../constants/classes'; @Component({ tag: 'chi-time-picker', @@ -13,27 +14,27 @@ export class TimePicker { @Prop({ reflect: true, mutable: true }) value: string; /** - * Minimum eligible time + * To disable chi-time-picker. */ - @Prop({ reflect: true }) min: string; + @Prop({ reflect: true }) disabled = false; /** - * Maximum eligible time + * Displaying seconds column */ - @Prop({ reflect: true }) max: string; + @Prop({ reflect: true }) displaySeconds = false; /** - * To disable chi-time-picker. + * To specify excluded hours. */ - @Prop({ reflect: true }) disabled = false; + @Prop({ reflect: true }) excludedHours: string; /** - * To specify excluded hours. + * To render Time Picker in 24 hour format. */ - @Prop({ reflect: true }) excludedHours: string; + @Prop({ reflect: true }) extended: boolean; /** - * Indicates whether the time picker dropdown is open or closed + * Indicates whether the time picker popover is open or closed */ @Prop({ reflect: true, mutable: true }) active = false; @@ -83,15 +84,6 @@ export class TimePicker { return Promise.resolve(this.value); } - @Listen('chiTimeChange') - handleTimeChange(ev) { - ev.stopPropagation(); - this._input.value = ev.detail; - this.value = ev.detail; - this.active = false; - this._input.blur(); - } - componentWillLoad(): void { this._onFocusIn = this._onFocusIn.bind(this); this._onClick = this._onClick.bind(this); @@ -111,6 +103,50 @@ export class TimePicker { document.body.removeEventListener('keyup', this._onKeyUp); } + @Listen('chiPopoverShow') + handlePopoverOpen(ev) { + ev.stopPropagation(); + const hoursColumn = this.el.querySelector(`.${TIME_CLASSES.HOURS}`) as HTMLElement; + const minutesColumn = this.el.querySelector(`.${TIME_CLASSES.MINUTES}`) as HTMLElement; + const secondsColumn = this.el.querySelector(`.${TIME_CLASSES.SECONDS}`) as HTMLElement; + + setTimeout(() => { + if (hoursColumn) { + const activeHour = hoursColumn.querySelector(`.${TIME_CLASSES.HOUR}.-active`) as HTMLElement; + + if (activeHour) { + hoursColumn.scrollTop = activeHour.offsetTop - 4; + } + } + if (minutesColumn) { + const activeMinute = minutesColumn.querySelector(`.${TIME_CLASSES.MINUTE}.-active`) as HTMLElement; + + if (activeMinute) { + minutesColumn.scrollTop = activeMinute.offsetTop - 4; + } + } + if (secondsColumn) { + const activeSecond = secondsColumn.querySelector(`.${TIME_CLASSES.SECOND}.-active`) as HTMLElement; + + if (activeSecond) { + secondsColumn.scrollTop = activeSecond.offsetTop - 4; + } + } + }, 100); + } + + @Listen('chiTimeChange') + handleTimeChange(ev) { + // console.log(ev); + const timePickerInput = document.getElementById(this._uuid) as HTMLInputElement; + const formatTimePeriod = (period: number) => { + return period.toString().length > 1 ? period.toString() : `0${period}`; + }; + const hour = !this.extended && ev.detail.hour > 12 ? ev.detail.hour - 12 : ev.detail.hour; + + timePickerInput.value = `${formatTimePeriod(hour)}:${formatTimePeriod(ev.detail.minute)}:${formatTimePeriod(ev.detail.second)} ${formatTimePeriod(ev.detail.period)}`; + } + render() { const chiPopover = ( @@ -139,7 +175,7 @@ export class TimePicker { class={`chi-input ${this.active ? '-focus' : ''}`} type={`text`} - placeholder={`00:00:00`} + placeholder={`--:-- --`} ref={el => (this._input = el as HTMLInputElement)} value={this.value} disabled={this.disabled} diff --git a/src/custom-elements/src/components/time/time.tsx b/src/custom-elements/src/components/time/time.tsx index c4ede2c93..b06e07220 100644 --- a/src/custom-elements/src/components/time/time.tsx +++ b/src/custom-elements/src/components/time/time.tsx @@ -6,19 +6,7 @@ import { Watch, h } from '@stencil/core'; - -const TIME_CLASSES = { - TIME: 'chi-time-picker', - CONTENT: 'chi-time-picker__content', - HOURS: 'chi-time-picker__hours', - HOUR: 'chi-time-picker__hour', - MINUTES: 'chi-time-picker__minutes', - MINUTE: 'chi-time-picker__minute', - SECONDS: 'chi-time-picker__seconds', - SECOND: 'chi-time-picker__second', - PERIODS: 'chi-time-picker__periods', - PERIOD: 'chi-time-picker__period', -}; +import { TIME_CLASSES } from '../../constants/classes'; @Component({ tag: 'chi-time', @@ -31,16 +19,6 @@ export class Time { */ @Prop({ reflect: true, mutable: true }) value: string; - /** - * Minimum eligible time - */ - @Prop({ reflect: true }) min: string; - - /** - * Maximum eligible time - */ - @Prop({ reflect: true }) max: string; - /** * Displaying seconds column */ @@ -61,12 +39,25 @@ export class Time { */ @Prop({ reflect: true }) excludedHours: string; + /** + * To disable specific minutes + */ + @Prop({ reflect: true }) excludedMinutes: string; + + /** + * To disable specific seconds + */ + @Prop({ reflect: true }) excludedSeconds: string; + _hour: string; _minute: string; _second: string; _period: string; + _uuid: string; excludedHoursArray = []; + excludedMinutesArray = []; + excludedSecondsArray = []; @Watch('excluded-hours') updateExcludedHours() { @@ -77,10 +68,27 @@ export class Time { } } + @Watch('excluded-minutes') + updateExcludedMinutes() { + if (this.excludedMinutes) { + this.excludedMinutes.split(',').map(time => { + this.excludedMinutesArray.push(time.trim()); + }); + } + } + + @Watch('excluded-seconds') + updateExcludedSeconds() { + if (this.excludedSeconds) { + this.excludedSeconds.split(',').map(time => { + this.excludedSecondsArray.push(time.trim()); + }); + } + } + @Watch('value') timeChanged(newValue: string, oldValue: string) { if (newValue !== oldValue) { - this.calculateTimePeriods(); this.value = newValue; } } @@ -91,13 +99,16 @@ export class Time { @Event({ eventName: 'chiTimeChange' }) eventChange: EventEmitter; calculateTimePeriods() { + const currentTime = new Date(); + let hours = currentTime.getHours(); + const minutes = currentTime.getMinutes(); + const seconds = currentTime.getSeconds(); + const formatTimePeriod = (period: number) => { + return period.toString().length > 1 ? period.toString() : `0${period}`; + }; + if (!this.value) { - if (this.min) { - this.value = this.min; - this._period = parseInt(this.min.split(':')[0]) < 12 ? 'am' : 'pm'; - } else { - this.value = '00:00:00'; - } + this.value = `${formatTimePeriod(hours)}:${formatTimePeriod(minutes)}:${formatTimePeriod(seconds)}`; } const time = this.value.split(':'); @@ -105,7 +116,7 @@ export class Time { this._hour = time[0]; this._minute = time[1]; this._second = time[2] ? time[2] : '00'; - this._period = !this.extended && parseInt(time[0]) < 12 ? 'am' : 'pm'; + this._period = !this.extended && hours < 12 ? 'am' : 'pm'; } connectedCallback() { @@ -145,6 +156,7 @@ export class Time { this._hour = hour; this.value = `${hourToSet}:${this._minute}:${this._second}`; + this.emitTimeValueEvent(); }; const hourStatus = (hour: string) => { const valueHour = parseInt(this.value.split(':')[0]); @@ -159,24 +171,6 @@ export class Time { ) { hourStatus = '-active'; } else { - const hourToCompare = this._period === 'pm' ? parseInt(hour) + 12 : parseInt(hour); - - if (this.min) { - const minHour = this.min ? parseInt(this.min.split(':')[0]) : null; - - if (hourToCompare < minHour) { - hourStatus += ' -disabled'; - } - } - - if (this.max) { - const maxHour = this.max ? parseInt(this.max.split(':')[0]) : null; - - if (hourToCompare > maxHour) { - hourStatus += ' -disabled'; - } - } - const formattedHour = parseInt(hour) < 10 ? (parseInt(hour) + 12).toString() : hour; if (this.excludedHoursArray.includes(formattedHour)) { @@ -188,7 +182,7 @@ export class Time { }; const hoursToDisplay = [ -
0) { hoursToDisplay.push( -
{ this._minute = minute; this.value = `${this._hour}:${this._minute}:${this._second}`; + this.emitTimeValueEvent(); }; Array.from(Array(60), (_, i) => { @@ -270,6 +265,7 @@ export class Time { const setSecond = (second: string) => { this._second = second; this.value = `${this._hour}:${this._minute}:${this._second}`; + this.emitTimeValueEvent(); }; Array.from(Array(60), (_, i) => { @@ -335,8 +331,9 @@ export class Time { } } - this._hour = currentHour.toString(); + console.log(this._period, this._hour); this.value = `${currentHour}:${this._minute}:${this._second}`; + this.emitTimeValueEvent(); }; return ( @@ -352,13 +349,24 @@ export class Time { } return; } + emitTimeValueEvent() { + this.eventChange.emit({ + hour: this._hour, + minute: this._minute, + second: this._second, + period: this._period, + value: this.value + }); + } + render() { const hours = this.hours(); const minutes = this.minutes(); const seconds = this.seconds(); const periods = this.periods(); - console.log(this.value); + // console.log(this._second); + // console.log(this.value); return (
-h3 Value, min and max options +h3 Value option .example.-mb--3 .-p--3 div.chi-form__item(style="max-width: 14rem;") chi-label(for='unique-id-va1') Time - chi-time-picker#unique-id-va1(value='09:00:00', min='09:00:00', max='18:00:00') + chi-time-picker#unique-id-va1(value='09:00:00') .example-tabs.-pl--2 ul.chi-tabs#example-min-max-value li.-active @@ -77,7 +77,7 @@ h3 Value, min and max options #webcomponent-min-max-value.chi-tabs-panel.-active :code(lang="html") Time - + #html-min-max-value.chi-tabs-panel .chi-tab__description span.-text--grey @@ -93,14 +93,14 @@ h3 Value, min and max options
-h3 Excluded hours +h3 Excluded hours, minutes and seconds p.-text | Specify which hours to disable by using the excluded-hours attribute. .example.-mb--3 .-p--3 div.chi-form__item(style="max-width: 14rem;") - chi-label(for="time-picker-excluded-hours") Label - chi-time-picker(id="time-picker-excluded-hours", excluded-hours="14, 15") + chi-label(for="time-picker-excluded") Label + chi-time-picker(id="time-picker-excluded", excluded-hours="14, 15", excluded-minutes="00, 01, 02, 03, 04, 05", excluded-seconds="00, 01, 02, 03, 04, 05", display-seconds) .example-tabs.-pl--2 ul.chi-tabs#example-excluded-times li.-active @@ -212,7 +212,7 @@ h4 24-hour format a(href=`#html-24hour`) HTML Blueprint #webcomponent-24hour.chi-tabs-panel.-active :code(lang="html") - extended + #html-24hour.chi-tabs-panel .chi-tab__description span.-text--grey From 14c99c627fa358dda81734a96c73b183694306d0 Mon Sep 17 00:00:00 2001 From: Jani Bolkvadze Date: Thu, 17 Dec 2020 17:27:55 +0100 Subject: [PATCH 4/7] Added Time Picker feature to Date Picker web component --- .../components/date-picker/date-picker.scss | 14 + src/custom-elements/docs/docs.json | 368 +++++++++++++++++- .../components/date-picker/date-picker.tsx | 125 ++++-- .../components/time-picker/time-picker.tsx | 15 +- .../src/components/time/time.tsx | 181 ++++++--- .../components/date-picker/_examples.pug | 35 ++ .../components/time-picker/_examples.pug | 21 - .../components/time-picker/_properties.pug | 12 +- 8 files changed, 653 insertions(+), 118 deletions(-) diff --git a/src/chi/components/date-picker/date-picker.scss b/src/chi/components/date-picker/date-picker.scss index d9cf7aec2..0634f96cb 100644 --- a/src/chi/components/date-picker/date-picker.scss +++ b/src/chi/components/date-picker/date-picker.scss @@ -167,6 +167,20 @@ $monday-starting-week: ( } } +.-time { + section { + &.chi-popover { + max-width: 30rem; + } + + .chi-time-picker { + box-shadow: inset 0.0625rem 0 0 0 $color-border-base; + margin-left: 0.75rem; + padding: 0.5rem; + } + } +} + .chi-popover { .chi-datepicker { padding: 0.5rem 1rem; diff --git a/src/custom-elements/docs/docs.json b/src/custom-elements/docs/docs.json index b3baa3245..7cfbe99df 100644 --- a/src/custom-elements/docs/docs.json +++ b/src/custom-elements/docs/docs.json @@ -882,6 +882,22 @@ "optional": false, "required": false }, + { + "name": "time", + "type": "boolean", + "mutable": false, + "attr": "time", + "reflectToAttr": true, + "docs": "To render Date Picker with Time Picker", + "docsTags": [], + "values": [ + { + "type": "boolean" + } + ], + "optional": false, + "required": false + }, { "name": "value", "type": "string", @@ -939,14 +955,16 @@ "slots": [], "dependents": [], "dependencies": [ - "chi-popover", "chi-date", + "chi-time", + "chi-popover", "chi-icon" ], "dependencyGraph": { "chi-date-picker": [ - "chi-popover", "chi-date", + "chi-time", + "chi-popover", "chi-icon" ], "chi-date": [ @@ -1383,7 +1401,8 @@ "chi-drawer", "chi-number-input", "chi-text-input", - "chi-textarea" + "chi-textarea", + "chi-time-picker" ], "dependencies": [], "dependencyGraph": { @@ -1410,6 +1429,9 @@ ], "chi-textarea": [ "chi-icon" + ], + "chi-time-picker": [ + "chi-icon" ] } }, @@ -2172,12 +2194,16 @@ "styles": [], "slots": [], "dependents": [ - "chi-date-picker" + "chi-date-picker", + "chi-time-picker" ], "dependencies": [], "dependencyGraph": { "chi-date-picker": [ "chi-popover" + ], + "chi-time-picker": [ + "chi-popover" ] } }, @@ -3173,6 +3199,338 @@ "chi-icon" ] } + }, + { + "filePath": "src/components/time/time.tsx", + "encapsulation": "scoped", + "tag": "chi-time", + "docs": "", + "docsTags": [], + "usage": {}, + "props": [ + { + "name": "displaySeconds", + "type": "boolean", + "mutable": false, + "attr": "display-seconds", + "reflectToAttr": true, + "docs": "Displaying seconds column", + "docsTags": [], + "default": "false", + "values": [ + { + "type": "boolean" + } + ], + "optional": false, + "required": false + }, + { + "name": "excludedHours", + "type": "string", + "mutable": false, + "attr": "excluded-hours", + "reflectToAttr": true, + "docs": "To disable specific hours", + "docsTags": [], + "values": [ + { + "type": "string" + } + ], + "optional": false, + "required": false + }, + { + "name": "excludedMinutes", + "type": "string", + "mutable": false, + "attr": "excluded-minutes", + "reflectToAttr": true, + "docs": "To disable specific minutes", + "docsTags": [], + "values": [ + { + "type": "string" + } + ], + "optional": false, + "required": false + }, + { + "name": "excludedSeconds", + "type": "string", + "mutable": false, + "attr": "excluded-seconds", + "reflectToAttr": true, + "docs": "To disable specific seconds", + "docsTags": [], + "values": [ + { + "type": "string" + } + ], + "optional": false, + "required": false + }, + { + "name": "extended", + "type": "boolean", + "mutable": false, + "attr": "extended", + "reflectToAttr": true, + "docs": "To render Time Picker in 24 hours format", + "docsTags": [], + "default": "false", + "values": [ + { + "type": "boolean" + } + ], + "optional": false, + "required": false + }, + { + "name": "stepped", + "type": "boolean", + "mutable": false, + "attr": "stepped", + "reflectToAttr": true, + "docs": "To render Minutes and Seconds columns in stepped format", + "docsTags": [], + "values": [ + { + "type": "boolean" + } + ], + "optional": false, + "required": false + }, + { + "name": "value", + "type": "string", + "mutable": true, + "attr": "value", + "reflectToAttr": true, + "docs": "Selected time in the time picker", + "docsTags": [], + "values": [ + { + "type": "string" + } + ], + "optional": false, + "required": false + } + ], + "methods": [], + "events": [ + { + "event": "chiTimeChange", + "detail": "any", + "bubbles": true, + "cancelable": true, + "composed": true, + "docs": "Time change value event", + "docsTags": [] + } + ], + "styles": [], + "slots": [], + "dependents": [ + "chi-date-picker", + "chi-time-picker" + ], + "dependencies": [], + "dependencyGraph": { + "chi-date-picker": [ + "chi-time" + ], + "chi-time-picker": [ + "chi-time" + ] + } + }, + { + "filePath": "src/components/time-picker/time-picker.tsx", + "encapsulation": "scoped", + "tag": "chi-time-picker", + "docs": "", + "docsTags": [], + "usage": {}, + "props": [ + { + "name": "active", + "type": "boolean", + "mutable": true, + "attr": "active", + "reflectToAttr": true, + "docs": "Indicates whether the time picker popover is open or closed", + "docsTags": [], + "default": "false", + "values": [ + { + "type": "boolean" + } + ], + "optional": false, + "required": false + }, + { + "name": "disabled", + "type": "boolean", + "mutable": false, + "attr": "disabled", + "reflectToAttr": true, + "docs": "To disable chi-time-picker.", + "docsTags": [], + "default": "false", + "values": [ + { + "type": "boolean" + } + ], + "optional": false, + "required": false + }, + { + "name": "displaySeconds", + "type": "boolean", + "mutable": false, + "attr": "display-seconds", + "reflectToAttr": true, + "docs": "Displaying seconds column", + "docsTags": [], + "default": "false", + "values": [ + { + "type": "boolean" + } + ], + "optional": false, + "required": false + }, + { + "name": "excludedHours", + "type": "string", + "mutable": false, + "attr": "excluded-hours", + "reflectToAttr": true, + "docs": "To specify excluded hours.", + "docsTags": [], + "values": [ + { + "type": "string" + } + ], + "optional": false, + "required": false + }, + { + "name": "excludedMinutes", + "type": "string", + "mutable": false, + "attr": "excluded-minutes", + "reflectToAttr": true, + "docs": "To specify excluded minutes.", + "docsTags": [], + "values": [ + { + "type": "string" + } + ], + "optional": false, + "required": false + }, + { + "name": "excludedSeconds", + "type": "string", + "mutable": false, + "attr": "excluded-seconds", + "reflectToAttr": true, + "docs": "To specify excluded seconds.", + "docsTags": [], + "values": [ + { + "type": "string" + } + ], + "optional": false, + "required": false + }, + { + "name": "extended", + "type": "boolean", + "mutable": false, + "attr": "extended", + "reflectToAttr": true, + "docs": "To render Time Picker in 24 hour format.", + "docsTags": [], + "values": [ + { + "type": "boolean" + } + ], + "optional": false, + "required": false + }, + { + "name": "value", + "type": "string", + "mutable": true, + "attr": "value", + "reflectToAttr": true, + "docs": "Selected time of Time Picker", + "docsTags": [], + "values": [ + { + "type": "string" + } + ], + "optional": false, + "required": false + } + ], + "methods": [ + { + "name": "getTime", + "returns": { + "type": "Promise", + "docs": "" + }, + "signature": "getTime() => Promise", + "parameters": [], + "docs": "Gets time", + "docsTags": [] + }, + { + "name": "setTime", + "returns": { + "type": "Promise", + "docs": "" + }, + "signature": "setTime(time: string) => Promise", + "parameters": [], + "docs": "Sets time", + "docsTags": [] + } + ], + "events": [], + "styles": [], + "slots": [], + "dependents": [], + "dependencies": [ + "chi-popover", + "chi-time", + "chi-icon" + ], + "dependencyGraph": { + "chi-time-picker": [ + "chi-popover", + "chi-time", + "chi-icon" + ] + } } ] -} \ No newline at end of file +} diff --git a/src/custom-elements/src/components/date-picker/date-picker.tsx b/src/custom-elements/src/components/date-picker/date-picker.tsx index db38f0c27..4eca17eec 100644 --- a/src/custom-elements/src/components/date-picker/date-picker.tsx +++ b/src/custom-elements/src/components/date-picker/date-picker.tsx @@ -2,6 +2,7 @@ import { Component, Element, Listen, Method, Prop, Watch, h } from '@stencil/cor import { contains, uuid4 } from '../../utils/utils'; import { ESCAPE_KEYCODE } from '../../constants/constants'; import dayjs, { Dayjs } from 'dayjs'; +import { TIME_CLASSES } from '../../constants/classes'; @Component({ tag: 'chi-date-picker', @@ -53,6 +54,11 @@ export class DatePicker { */ @Prop({ reflect: true }) excludedDates: string; + /** + * To render Date Picker with Time Picker + */ + @Prop({ reflect: true }) time: boolean; + @Element() el: HTMLElement; private _input: HTMLInputElement; @@ -64,15 +70,15 @@ export class DatePicker { @Watch('excludedDates') updateExcludedDates() { this.excludedDatesArray = this.excludedDates - ? this.excludedDates.split(',').map(date => date.trim()) - : []; + ? this.excludedDates.split(',').map(date => date.trim()) + : []; } @Watch('excludedWeekdays') updateExcludedWeekdays() { this.excludedWeekdaysArray = this.excludedWeekdays - ? this.excludedWeekdays.split(',').map(weekDay => parseInt(weekDay)) - : []; + ? this.excludedWeekdays.split(',').map(weekDay => parseInt(weekDay)) + : []; } _onFocusIn(e) { @@ -85,7 +91,7 @@ export class DatePicker { if ( e.target !== document.body && e.target !== null && - !(new RegExp('(\\s|^)' + 'chi-datepicker__day' + '(\\s|$)').test(e.target.getAttribute('class'))) + !(!this.time && new RegExp('(\\s|^)' + 'chi-datepicker__day' + '(\\s|$)').test(e.target.getAttribute('class'))) // This hack is necessary because currently IE11 doesn't support .classList on SVG elements ) { this.active = contains(this.el, e.target); @@ -119,9 +125,9 @@ export class DatePicker { } _checkDate() { - const inputDate = dayjs(this._input.value); - const minDate = dayjs(this.min); - const maxDate = dayjs(this.max); + const inputDate = dayjs(this._input.value), + minDate = dayjs(this.min), + maxDate = dayjs(this.max); if (dayjs(this._input.value).isValid() && !this.checkIfExcluded(inputDate)) { if ( @@ -175,11 +181,72 @@ export class DatePicker { handleDateChange(ev) { ev.stopPropagation(); this._input.value = ev.detail; - this.value = ev.detail; + if (this.time) { + const chiTime = this.el.querySelector('.chi-popover__content chi-time') as HTMLElement; + const valueTime = chiTime.getAttribute('value'); + + if (valueTime) { + const time = valueTime.split(':'); + const period = parseInt(time[0]) >= 12 ? 'pm' : 'am'; + const hours = parseInt(time[0]) >= 12 ? parseInt(time[0]) - 12 : parseInt(time[0]); + const hoursCalculated = this.formatTimePeriod(hours); + const minutes = this.formatTimePeriod(parseInt(time[1])); + + this.value = `${ev.detail}, ${hoursCalculated}:${minutes} ${period}`; + } + } else { + this.value = ev.detail; + } this.active = false; this._input.blur(); } + @Listen('chiPopoverShow') + handlePopoverOpen(ev) { + ev.stopPropagation(); + const hoursColumn = this.el.querySelector(`.${TIME_CLASSES.HOURS}`) as HTMLElement; + const minutesColumn = this.el.querySelector(`.${TIME_CLASSES.MINUTES}`) as HTMLElement; + + setTimeout(() => { + if (hoursColumn) { + const activeHour = hoursColumn.querySelector(`.${TIME_CLASSES.HOUR}.-active`) as HTMLElement; + + if (activeHour) { + hoursColumn.scrollTop = activeHour.offsetTop - 12; + } + } + if (minutesColumn) { + const activeMinute = minutesColumn.querySelector(`.${TIME_CLASSES.MINUTE}.-active`) as HTMLElement; + + if (activeMinute) { + minutesColumn.scrollTop = activeMinute.offsetTop - 12; + } + } + }, 50); + } + + @Listen('chiTimeChange') + handleTimeChange(ev) { + const currentTime = new Date(); + const chiDate = this.el.querySelector('.chi-popover__content chi-date') as HTMLElement; + const valueDate = chiDate.getAttribute('value'); + const hour = ev.detail.hour > 12 ? ev.detail.hour - 12 : ev.detail.hour; + let activeDate: string; + + if (valueDate) { + activeDate = valueDate; + } else { + activeDate = `${currentTime.getMonth()+1}/${currentTime.getDate()}/${currentTime.getFullYear()}`; + } + + chiDate.setAttribute('value', activeDate); + this.value = `${activeDate}, ${this.formatTimePeriod(hour)}:${this.formatTimePeriod(ev.detail.minute)} ${this.formatTimePeriod(ev.detail.period)}`; + } + + formatTimePeriod(period: number) { + return period.toString().length > 1 ? period.toString() : `0${period}`; + }; + componentWillLoad(): void { this.updateExcludedDates(); this.updateExcludedWeekdays(); @@ -202,39 +269,53 @@ export class DatePicker { } render() { + const chiDateValue = this.time ? + this.value ? this.value.split(',')[0] : null + : this.value; + + const date = ; + const time = this.time ? : null; + const popoverContent = this.time ? +
+ {date} + {time} +
: date; const chiPopover = ( - + {popoverContent} ); return [ // TODO: This input should be chi-input in the future and will pass through // some of its configuration attributes. -
+
(this._input = el as HTMLInputElement)} value={this.value} onChange={() => { diff --git a/src/custom-elements/src/components/time-picker/time-picker.tsx b/src/custom-elements/src/components/time-picker/time-picker.tsx index 2c3cb4bcc..f9f2cd36c 100644 --- a/src/custom-elements/src/components/time-picker/time-picker.tsx +++ b/src/custom-elements/src/components/time-picker/time-picker.tsx @@ -28,6 +28,16 @@ export class TimePicker { */ @Prop({ reflect: true }) excludedHours: string; + /** + * To specify excluded minutes. + */ + @Prop({ reflect: true }) excludedMinutes: string; + + /** + * To specify excluded seconds. + */ + @Prop({ reflect: true }) excludedSeconds: string; + /** * To render Time Picker in 24 hour format. */ @@ -132,12 +142,11 @@ export class TimePicker { secondsColumn.scrollTop = activeSecond.offsetTop - 4; } } - }, 100); + }, 50); } @Listen('chiTimeChange') handleTimeChange(ev) { - // console.log(ev); const timePickerInput = document.getElementById(this._uuid) as HTMLInputElement; const formatTimePeriod = (period: number) => { return period.toString().length > 1 ? period.toString() : `0${period}`; @@ -159,6 +168,8 @@ export class TimePicker { diff --git a/src/custom-elements/src/components/time/time.tsx b/src/custom-elements/src/components/time/time.tsx index b06e07220..8b463d34b 100644 --- a/src/custom-elements/src/components/time/time.tsx +++ b/src/custom-elements/src/components/time/time.tsx @@ -4,7 +4,7 @@ import { EventEmitter, Prop, Watch, - h + h, Element } from '@stencil/core'; import { TIME_CLASSES } from '../../constants/classes'; @@ -49,11 +49,12 @@ export class Time { */ @Prop({ reflect: true }) excludedSeconds: string; + @Element() el: HTMLElement; + _hour: string; _minute: string; _second: string; _period: string; - _uuid: string; excludedHoursArray = []; excludedMinutesArray = []; @@ -93,22 +94,24 @@ export class Time { } } + // ToDo Validate Value + // validateTime(time: string) { + // return /^([0-1]?[0-9]|2[0-4]):([0-5][0-9])(:[0-5][0-9])?$/.test(time); + // } + /** * Time change value event */ @Event({ eventName: 'chiTimeChange' }) eventChange: EventEmitter; calculateTimePeriods() { - const currentTime = new Date(); - let hours = currentTime.getHours(); - const minutes = currentTime.getMinutes(); - const seconds = currentTime.getSeconds(); - const formatTimePeriod = (period: number) => { - return period.toString().length > 1 ? period.toString() : `0${period}`; - }; + const currentTime = new Date(), + hours = currentTime.getHours(), + minutes = currentTime.getMinutes(), + seconds = currentTime.getSeconds(); if (!this.value) { - this.value = `${formatTimePeriod(hours)}:${formatTimePeriod(minutes)}:${formatTimePeriod(seconds)}`; + this.value = `${this.formatTimePeriod(hours)}:${this.formatTimePeriod(minutes)}:${this.formatTimePeriod(seconds)}`; } const time = this.value.split(':'); @@ -116,18 +119,20 @@ export class Time { this._hour = time[0]; this._minute = time[1]; this._second = time[2] ? time[2] : '00'; - this._period = !this.extended && hours < 12 ? 'am' : 'pm'; + this._period = !this.extended && parseInt(this._hour) < 12 ? 'am' : 'pm'; } connectedCallback() { this.calculateTimePeriods(); - if (this.excludedHours) { - this.excludedHours.split(',').map(time => { - this.excludedHoursArray.push(time.trim()); - }); - } + this.updateExcludedHours(); + this.updateExcludedMinutes(); + this.updateExcludedSeconds(); } + formatTimePeriod(period: number) { + return period.toString().length > 1 ? period.toString() : `0${period}`; + }; + hours() { const startHour = this.extended ? 24 : 12; let hourToSet: string; @@ -162,7 +167,7 @@ export class Time { const valueHour = parseInt(this.value.split(':')[0]); let hourStatus = ''; - if (parseInt(this._hour) === parseInt(hour) || + if (this._hour === hour || (!this.extended && this._period === 'pm' && parseInt(hour) + 12 === valueHour @@ -171,9 +176,7 @@ export class Time { ) { hourStatus = '-active'; } else { - const formattedHour = parseInt(hour) < 10 ? (parseInt(hour) + 12).toString() : hour; - - if (this.excludedHoursArray.includes(formattedHour)) { + if (this.excludedHoursArray.includes(this.formatTimePeriod(parseInt(hour)))) { hourStatus += ' -disabled'; } } @@ -186,11 +189,11 @@ export class Time { ${TIME_CLASSES.HOUR} ${hourStatus(startHour.toString())} `} - onClick={() => setHour(startHour.toString())}>{startHour}
+ onClick={() => setHour(startHour.toString())}>{startHour}
]; Array.from(Array(startHour), (_, i) => { - const hour = (i).toString().length > 1 ? (i).toString() : `0${i}`; + const hour = this.formatTimePeriod(i); if (i > 0) { hoursToDisplay.push( @@ -213,36 +216,49 @@ export class Time { } minutes() { - const minutesToDisplay = [ -
setMinute('00')}>00
- ]; const setMinute = (minute: string) => { this._minute = minute; this.value = `${this._hour}:${this._minute}:${this._second}`; this.emitTimeValueEvent(); }; + const minuteState = (minute: string) => { + let minuteState = ''; + + if (parseInt(this._minute) === parseInt(minute)) { + minuteState = '-active'; + } else { + if (this.excludedMinutesArray.includes(minute)) { + minuteState += ' -disabled'; + } + } + + return minuteState; + }; + const minutesToDisplay = [ +
setMinute('00')}>00
+ ]; Array.from(Array(60), (_, i) => { - const minute = (i).toString().length > 1 ? (i).toString() : `0${i}`; - const displayminute = () => { + const minute = this.formatTimePeriod(i); + const displayMinute = () => { minutesToDisplay.push(
setMinute(minute)}>{minute}
); + onClick={() => setMinute(minute)}>{minute}
); }; if (i > 0) { if (this.stepped) { if (i % 15 === 0) { - displayminute(); + displayMinute(); } } else { - displayminute(); + displayMinute(); } } }); @@ -255,27 +271,40 @@ export class Time { } seconds() { - const secondsToDisplay = [ -
setSecond('00')}>00
- ]; const setSecond = (second: string) => { this._second = second; this.value = `${this._hour}:${this._minute}:${this._second}`; this.emitTimeValueEvent(); }; + const secondsState = (second: string) => { + let secondState = ''; + + if (parseInt(this._second) === parseInt(second)) { + secondState = '-active'; + } else { + if (this.excludedMinutesArray.includes(second)) { + secondState += ' -disabled'; + } + } + + return secondState; + }; + const secondsToDisplay = [ +
setSecond('00')}>00
+ ]; Array.from(Array(60), (_, i) => { - const second = (i).toString().length > 1 ? (i).toString() : `0${i}`; + const second = this.formatTimePeriod(i); const displaySecond = () => { secondsToDisplay.push(
setSecond(second)}>{second}
); + ${TIME_CLASSES.SECOND} + ${secondsState(second)} + `} + onClick={() => setSecond(second)}>{second}); }; if (i > 0) { @@ -295,13 +324,14 @@ export class Time { secondsToDisplay } ); - } return; + } + return; } periods() { const hour = parseInt(this.value.split(':')[0]); if (!this.extended) { - const periodlasses = (period: 'am' | 'pm') => { + const periodClasses = (period: 'am' | 'pm') => { let periodStatus = TIME_CLASSES.PERIOD; if (period === this._period) { @@ -331,7 +361,6 @@ export class Time { } } - console.log(this._period, this._hour); this.value = `${currentHour}:${this._minute}:${this._second}`; this.emitTimeValueEvent(); }; @@ -339,14 +368,17 @@ export class Time { return (
setPeriod('am')}>AM
+ class={periodClasses('am')} + onClick={() => setPeriod('am')}>AM +
setPeriod('pm')}>PM
+ class={periodClasses('pm')} + onClick={() => setPeriod('pm')}>PM + ); - } return; + } + return; } emitTimeValueEvent() { @@ -359,14 +391,39 @@ export class Time { }); } - render() { - const hours = this.hours(); - const minutes = this.minutes(); - const seconds = this.seconds(); - const periods = this.periods(); + componentDidLoad() { + const hoursColumn = this.el.querySelector(`.${TIME_CLASSES.HOURS}`) as HTMLElement, + minutesColumn = this.el.querySelector(`.${TIME_CLASSES.MINUTES}`) as HTMLElement, + secondsColumn = this.el.querySelector(`.${TIME_CLASSES.SECONDS}`) as HTMLElement; + + if (hoursColumn) { + const activeHour = hoursColumn.querySelector(`.${TIME_CLASSES.HOUR}.-active`) as HTMLElement; - // console.log(this._second); - // console.log(this.value); + if (activeHour) { + hoursColumn.scrollTop = activeHour.offsetTop - 28; + } + } + if (minutesColumn) { + const activeMinute = minutesColumn.querySelector(`.${TIME_CLASSES.MINUTE}.-active`) as HTMLElement; + + if (activeMinute) { + minutesColumn.scrollTop = activeMinute.offsetTop - 28; + } + } + if (secondsColumn) { + const activeSecond = secondsColumn.querySelector(`.${TIME_CLASSES.SECOND}.-active`) as HTMLElement; + + if (activeSecond) { + secondsColumn.scrollTop = activeSecond.offsetTop - 28; + } + } + } + + render() { + const hours = this.hours(), + minutes = this.minutes(), + seconds = this.seconds(), + periods = this.periods(); return (
#html-excluded-days-dates.chi-tabs-panel +h3 Date Time +p.-text +.example.-mb--3 + .-p--3 + div(style="max-width: 14rem;") + chi-label(for='date-time') + | Date Time + chi-date-picker(id="date-time" time) + .example-tabs.-pl--2 + ul.chi-tabs#example-datetime + li.-active + a(href=`#webcomponent-datetime`) Web Component + li + a(href=`#html-datetime`) HTML Blueprint + #webcomponent-with-label.chi-tabs-panel.-active + :code(lang="html",style="height:20rem") + Date + + #html-with-label.chi-tabs-panel + .chi-tab__description + span.-text--grey + | This HTML Blueprint requires JavaScript. + | You may use your own solution, or use Chi's vanilla JavaScript solution, + | Chi.js. + :code(lang="html") +
+ +
+ + +
+
+ + + h3 Calendar p.-text | An example of a date picker calendar not attached to any element. diff --git a/src/website/views/components/time-picker/_examples.pug b/src/website/views/components/time-picker/_examples.pug index bb58669b7..4fa380f53 100644 --- a/src/website/views/components/time-picker/_examples.pug +++ b/src/website/views/components/time-picker/_examples.pug @@ -158,27 +158,6 @@ h4 Active | Chi.js. :code(lang="html") -h4 Min and Max -.example.-mb--3 - .-p--3 - chi-time(min="14:00:00", value="17:00:00", max="20:00:00") - .example-tabs.-pl--2 - ul.chi-tabs#example-min-max - li.-active - a(href=`#webcomponent-min-max`) Web Component - li - a(href=`#html-min-max`) HTML Blueprint - #webcomponent-min-max.chi-tabs-panel.-active - :code(lang="html") - - #html-min-max.chi-tabs-panel - .chi-tab__description - span.-text--grey - | This HTML Blueprint requires JavaScript. - | You may use your own solution, or use Chi's vanilla JavaScript solution, - | Chi.js. - :code(lang="html") - h4 Seconds .example.-mb--3 .-p--3 diff --git a/src/website/views/components/time-picker/_properties.pug b/src/website/views/components/time-picker/_properties.pug index 0e0e9a578..104efbc5f 100644 --- a/src/website/views/components/time-picker/_properties.pug +++ b/src/website/views/components/time-picker/_properties.pug @@ -1,6 +1,6 @@ -h2 Web Component -h3 Properties -.chi-card.-align--center.-empty - .chi-card__content - .chi-card__caption - | Web component coming soon +h2 chi-time-picker +:stencilDoc(name='chi-time-picker') +.chi-divider.-my--5 +h2 chi-time +:stencilDoc(name='chi-time') +.chi-divider.-my--5 From 3c0cb0a85ef0dafe1e38dace3b9f56ad46fbe22d Mon Sep 17 00:00:00 2001 From: Matt Nickles Date: Mon, 21 Dec 2020 10:03:47 -0800 Subject: [PATCH 5/7] Disabled HTML blueprint tab code snippets --- .../components/date-picker/_examples.pug | 202 +----------------- .../components/time-picker/_examples.pug | 84 +------- 2 files changed, 19 insertions(+), 267 deletions(-) diff --git a/src/website/views/components/date-picker/_examples.pug b/src/website/views/components/date-picker/_examples.pug index 45f2fb2f3..572045dd0 100644 --- a/src/website/views/components/date-picker/_examples.pug +++ b/src/website/views/components/date-picker/_examples.pug @@ -194,28 +194,13 @@ p.-text ul.chi-tabs#example-datetime li.-active a(href=`#webcomponent-datetime`) Web Component - li + li.-disabled a(href=`#html-datetime`) HTML Blueprint - #webcomponent-with-label.chi-tabs-panel.-active + #webcomponent-datetime.chi-tabs-panel.-active :code(lang="html",style="height:20rem") Date - #html-with-label.chi-tabs-panel - .chi-tab__description - span.-text--grey - | This HTML Blueprint requires JavaScript. - | You may use your own solution, or use Chi's vanilla JavaScript solution, - | Chi.js. - :code(lang="html") -
- -
- - -
-
- - + #html-datetime.chi-tabs-panel h3 Calendar p.-text @@ -604,185 +589,16 @@ h4 Date and Time .chi-time-picker__period AM .chi-time-picker__period PM .example-tabs.-pl--2 - ul.chi-tabs#example-datetime + ul.chi-tabs#example-calendar-datetime li.-active - a(href=`#webcomponent-datetime`) Web Component - li - a(href=`#html-datetime`) HTML Blueprint - #webcomponent-datetime.chi-tabs-panel.-active + a(href=`#webcomponent-calendar-datetime`) Web Component + li.-disabled + a(href=`#html-calendar-datetime`) HTML Blueprint + #webcomponent-calendar-datetime.chi-tabs-panel.-active :code(lang="html") - #html-datetime.chi-tabs-panel - .chi-tab__description - span.-text--grey - | This HTML Blueprint requires JavaScript. - | You may use your own solution, or use Chi's vanilla JavaScript solution, - | Chi.js. - br - br - | Use the classes -month-starts-on-sun, - | -month-starts-on-mon, -month-starts-on-tue, -month-starts-on-wed, - | -month-starts-on-thu, -month-starts-on-fri and -month-starts-on-sat to - | locate the first day in the correct cell. - br - | Use the classes -week-starts-on-sun or -week-starts-on-mon to fit the week definition - | of the desired locale. - br - | Use the class -today for the current date - :code(lang="html") -
-
- -
- November 2018 -
- -
-
-
- S -
-
- M -
-
- T -
-
- W -
-
- T -
-
- F -
-
- S -
-
-
-
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
-
-
-
-
-
-
12
-
01
-
02
-
03
-
04
-
05
-
06
-
07
-
08
-
09
-
10
-
11
-
-
-
00
-
01
-
02
-
03
-
04
-
05
-
06
-
07
-
08
-
09
-
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
-
-
-
AM
-
PM
-
-
-
+ #html-calendar-datetime.chi-tabs-panel script. document.addEventListener( 'DOMContentLoaded', diff --git a/src/website/views/components/time-picker/_examples.pug b/src/website/views/components/time-picker/_examples.pug index 4fa380f53..67b3832f0 100644 --- a/src/website/views/components/time-picker/_examples.pug +++ b/src/website/views/components/time-picker/_examples.pug @@ -11,21 +11,13 @@ p.-text ul.chi-tabs#example-with-label li.-active a(href=`#webcomponent-with-label`) Web Component - li + li.-disabled a(href=`#html-with-label`) HTML Blueprint #webcomponent-with-label.chi-tabs-panel.-active :code(lang="html",style="height:20rem") Label #html-with-label.chi-tabs-panel - :code(lang="html") -
- -
- - -
-
h3 Disabled p.-text @@ -41,26 +33,13 @@ p.-text ul.chi-tabs#example-disabled li.-active a(href=`#webcomponent-disabled`) Web Component - li + li.-disabled a(href=`#html-disabled`) HTML Blueprint #webcomponent-disabled.chi-tabs-panel.-active :code(lang="html") Label #html-disabled.chi-tabs-panel - .chi-tab__description - span.-text--grey - | This HTML Blueprint requires JavaScript. - | You may use your own solution, or use Chi's vanilla JavaScript solution, - | Chi.js. - :code(lang="html") -
- -
- - -
-
h3 Value option .example.-mb--3 @@ -72,26 +51,13 @@ h3 Value option ul.chi-tabs#example-min-max-value li.-active a(href=`#webcomponent-min-max-value`) Web Component - li + li.-disabled a(href=`#html-min-max-value`) HTML Blueprint #webcomponent-min-max-value.chi-tabs-panel.-active :code(lang="html") Time #html-min-max-value.chi-tabs-panel - .chi-tab__description - span.-text--grey - | This HTML Blueprint requires JavaScript. - | You may use your own solution, or use Chi's vanilla JavaScript solution, - | Chi.js. - :code(lang="html") -
- -
- - -
-
h3 Excluded hours, minutes and seconds p.-text @@ -124,18 +90,12 @@ h4 Base ul.chi-tabs#example-time li.-active a(href=`#webcomponent-time`) Web Component - li + li.-disabled a(href=`#html-time`) HTML Blueprint #webcomponent-time.chi-tabs-panel.-active :code(lang="html") #html-time.chi-tabs-panel - .chi-tab__description - span.-text--grey - | This HTML Blueprint requires JavaScript. - | You may use your own solution, or use Chi's vanilla JavaScript solution, - | Chi.js. - :code(lang="html") h4 Active .example.-mb--3 @@ -145,18 +105,12 @@ h4 Active ul.chi-tabs#example-active li.-active a(href=`#webcomponent-active`) Web Component - li + li.-disabled a(href=`#html-active`) HTML Blueprint #webcomponent-active.chi-tabs-panel.-active :code(lang="html") #html-active.chi-tabs-panel - .chi-tab__description - span.-text--grey - | This HTML Blueprint requires JavaScript. - | You may use your own solution, or use Chi's vanilla JavaScript solution, - | Chi.js. - :code(lang="html") h4 Seconds .example.-mb--3 @@ -166,18 +120,12 @@ h4 Seconds ul.chi-tabs#example-seconds li.-active a(href=`#webcomponent-seconds`) Web Component - li + li.-disabled a(href=`#html-seconds`) HTML Blueprint - #webcomponent.chi-tabs-panel.-active + #webcomponent-seconds.chi-tabs-panel.-active :code(lang="html") - #html.chi-tabs-panel - .chi-tab__description - span.-text--grey - | This HTML Blueprint requires JavaScript. - | You may use your own solution, or use Chi's vanilla JavaScript solution, - | Chi.js. - :code(lang="html") + #html-seconds.chi-tabs-panel h4 24-hour format .example.-mb--3 @@ -187,18 +135,12 @@ h4 24-hour format ul.chi-tabs#example-24hour li.-active a(href=`#webcomponent-24hour`) Web Component - li + li.-disabled a(href=`#html-24hour`) HTML Blueprint #webcomponent-24hour.chi-tabs-panel.-active :code(lang="html") #html-24hour.chi-tabs-panel - .chi-tab__description - span.-text--grey - | This HTML Blueprint requires JavaScript. - | You may use your own solution, or use Chi's vanilla JavaScript solution, - | Chi.js. - :code(lang="html") h4 Step .example.-mb--3 @@ -208,18 +150,12 @@ h4 Step ul.chi-tabs#example-step li.-active a(href=`#webcomponent-step`) Web Component - li + li.-disabled a(href=`#html-step`) HTML Blueprint #webcomponent-step.chi-tabs-panel.-active :code(lang="html") #html-step.chi-tabs-panel - .chi-tab__description - span.-text--grey - | This HTML Blueprint requires JavaScript. - | You may use your own solution, or use Chi's vanilla JavaScript solution, - | Chi.js. - :code(lang="html") script. document.addEventListener( From ae7d679d911b4b2e3376818a0049832302415f58 Mon Sep 17 00:00:00 2001 From: Jani Bolkvadze Date: Mon, 21 Dec 2020 21:57:40 +0100 Subject: [PATCH 6/7] Added support of date and datetime modes to Date Picker wc --- src/custom-elements/docs/docs.json | 30 +++++----- .../components/date-picker/date-picker.tsx | 30 +++++----- .../components/time-picker/time-picker.tsx | 14 +++-- .../src/components/time/time.tsx | 20 ++++--- .../src/constants/constants.ts | 9 +++ .../components/date-picker/_examples.pug | 2 +- .../components/time-picker/_examples.pug | 58 +++++++++---------- 7 files changed, 89 insertions(+), 74 deletions(-) diff --git a/src/custom-elements/docs/docs.json b/src/custom-elements/docs/docs.json index 7cfbe99df..fa6f00f76 100644 --- a/src/custom-elements/docs/docs.json +++ b/src/custom-elements/docs/docs.json @@ -883,16 +883,17 @@ "required": false }, { - "name": "time", - "type": "boolean", + "name": "mode", + "type": "string", "mutable": false, - "attr": "time", + "attr": "mode", "reflectToAttr": true, "docs": "To render Date Picker with Time Picker", "docsTags": [], + "default": "'date'", "values": [ { - "type": "boolean" + "type": "string" } ], "optional": false, @@ -3274,17 +3275,17 @@ "required": false }, { - "name": "extended", - "type": "boolean", + "name": "format", + "type": "string", "mutable": false, - "attr": "extended", + "attr": "format", "reflectToAttr": true, "docs": "To render Time Picker in 24 hours format", "docsTags": [], - "default": "false", + "default": "'12hr'", "values": [ { - "type": "boolean" + "type": "string" } ], "optional": false, @@ -3459,16 +3460,17 @@ "required": false }, { - "name": "extended", - "type": "boolean", + "name": "format", + "type": "string", "mutable": false, - "attr": "extended", + "attr": "format", "reflectToAttr": true, - "docs": "To render Time Picker in 24 hour format.", + "docs": "To define format of Time Picker.", "docsTags": [], + "default": "'12hr'", "values": [ { - "type": "boolean" + "type": "string" } ], "optional": false, diff --git a/src/custom-elements/src/components/date-picker/date-picker.tsx b/src/custom-elements/src/components/date-picker/date-picker.tsx index 4eca17eec..78fa4ce29 100644 --- a/src/custom-elements/src/components/date-picker/date-picker.tsx +++ b/src/custom-elements/src/components/date-picker/date-picker.tsx @@ -3,6 +3,7 @@ import { contains, uuid4 } from '../../utils/utils'; import { ESCAPE_KEYCODE } from '../../constants/constants'; import dayjs, { Dayjs } from 'dayjs'; import { TIME_CLASSES } from '../../constants/classes'; +import { CHI_TIME_AUTO_SCROLL_DELAY, DatePickerModes } from '../../constants/constants'; @Component({ tag: 'chi-date-picker', @@ -57,7 +58,7 @@ export class DatePicker { /** * To render Date Picker with Time Picker */ - @Prop({ reflect: true }) time: boolean; + @Prop({ reflect: true }) mode: DatePickerModes = 'date'; @Element() el: HTMLElement; @@ -91,7 +92,7 @@ export class DatePicker { if ( e.target !== document.body && e.target !== null && - !(!this.time && new RegExp('(\\s|^)' + 'chi-datepicker__day' + '(\\s|$)').test(e.target.getAttribute('class'))) + !(!(this.mode === 'datetime') && new RegExp('(\\s|^)' + 'chi-datepicker__day' + '(\\s|$)').test(e.target.getAttribute('class'))) // This hack is necessary because currently IE11 doesn't support .classList on SVG elements ) { this.active = contains(this.el, e.target); @@ -181,14 +182,14 @@ export class DatePicker { handleDateChange(ev) { ev.stopPropagation(); this._input.value = ev.detail; - if (this.time) { + if (this.mode === 'datetime') { const chiTime = this.el.querySelector('.chi-popover__content chi-time') as HTMLElement; const valueTime = chiTime.getAttribute('value'); if (valueTime) { const time = valueTime.split(':'); const period = parseInt(time[0]) >= 12 ? 'pm' : 'am'; - const hours = parseInt(time[0]) >= 12 ? parseInt(time[0]) - 12 : parseInt(time[0]); + const hours = parseInt(time[0]) > 12 ? parseInt(time[0]) - 12 : parseInt(time[0]); const hoursCalculated = this.formatTimePeriod(hours); const minutes = this.formatTimePeriod(parseInt(time[1])); @@ -222,7 +223,7 @@ export class DatePicker { minutesColumn.scrollTop = activeMinute.offsetTop - 12; } } - }, 50); + }, CHI_TIME_AUTO_SCROLL_DELAY); } @Listen('chiTimeChange') @@ -236,14 +237,14 @@ export class DatePicker { if (valueDate) { activeDate = valueDate; } else { - activeDate = `${currentTime.getMonth()+1}/${currentTime.getDate()}/${currentTime.getFullYear()}`; + activeDate = `${currentTime.getMonth() + 1}/${currentTime.getDate()}/${currentTime.getFullYear()}`; } chiDate.setAttribute('value', activeDate); this.value = `${activeDate}, ${this.formatTimePeriod(hour)}:${this.formatTimePeriod(ev.detail.minute)} ${this.formatTimePeriod(ev.detail.period)}`; } - formatTimePeriod(period: number) { + formatTimePeriod(period: number): string { return period.toString().length > 1 ? period.toString() : `0${period}`; }; @@ -269,7 +270,7 @@ export class DatePicker { } render() { - const chiDateValue = this.time ? + const chiDateValue = this.mode === 'datetime' ? this.value ? this.value.split(',')[0] : null : this.value; @@ -282,8 +283,8 @@ export class DatePicker { excluded-weekdays={this.excludedWeekdays} excluded-dates={this.excludedDates} />; - const time = this.time ? : null; - const popoverContent = this.time ? + const time = this.mode === 'datetime' ? : null; + const popoverContent = this.mode === 'datetime' ?
{date} {time} @@ -291,7 +292,7 @@ export class DatePicker { const chiPopover = ( + ${this.mode === 'datetime' ? '-time' : ''}`}>
(this._input = el as HTMLInputElement)} value={this.value} onChange={() => { diff --git a/src/custom-elements/src/components/time-picker/time-picker.tsx b/src/custom-elements/src/components/time-picker/time-picker.tsx index f9f2cd36c..5ea7ba5ae 100644 --- a/src/custom-elements/src/components/time-picker/time-picker.tsx +++ b/src/custom-elements/src/components/time-picker/time-picker.tsx @@ -1,6 +1,8 @@ import { Component, Element, Listen, Method, Prop, h } from '@stencil/core'; import { contains, uuid4 } from '../../utils/utils'; -import { ESCAPE_KEYCODE } from '../../constants/constants'; +import { CHI_TIME_AUTO_SCROLL_DELAY, + ESCAPE_KEYCODE, + DatePickerFormats} from '../../constants/constants'; import { TIME_CLASSES } from '../../constants/classes'; @Component({ @@ -39,9 +41,9 @@ export class TimePicker { @Prop({ reflect: true }) excludedSeconds: string; /** - * To render Time Picker in 24 hour format. + * To define format of Time Picker. */ - @Prop({ reflect: true }) extended: boolean; + @Prop({ reflect: true }) format: DatePickerFormats = '12hr'; /** * Indicates whether the time picker popover is open or closed @@ -142,7 +144,7 @@ export class TimePicker { secondsColumn.scrollTop = activeSecond.offsetTop - 4; } } - }, 50); + }, CHI_TIME_AUTO_SCROLL_DELAY); } @Listen('chiTimeChange') @@ -151,7 +153,7 @@ export class TimePicker { const formatTimePeriod = (period: number) => { return period.toString().length > 1 ? period.toString() : `0${period}`; }; - const hour = !this.extended && ev.detail.hour > 12 ? ev.detail.hour - 12 : ev.detail.hour; + const hour = !(this.format === '24hr') && ev.detail.hour > 12 ? ev.detail.hour - 12 : ev.detail.hour; timePickerInput.value = `${formatTimePeriod(hour)}:${formatTimePeriod(ev.detail.minute)}:${formatTimePeriod(ev.detail.second)} ${formatTimePeriod(ev.detail.period)}`; } @@ -170,7 +172,7 @@ export class TimePicker { excluded-hours={this.excludedHours} excluded-minutes={this.excludedMinutes} excluded-seconds={this.excludedSeconds} - extended={this.extended} + format={this.format} value={this.value} /> diff --git a/src/custom-elements/src/components/time/time.tsx b/src/custom-elements/src/components/time/time.tsx index 8b463d34b..b8c784440 100644 --- a/src/custom-elements/src/components/time/time.tsx +++ b/src/custom-elements/src/components/time/time.tsx @@ -7,6 +7,7 @@ import { h, Element } from '@stencil/core'; import { TIME_CLASSES } from '../../constants/classes'; +import { CHI_TIME_SCROLL_ADJUSTMENT, DatePickerFormats } from '../../constants/constants'; @Component({ tag: 'chi-time', @@ -27,7 +28,7 @@ export class Time { /** * To render Time Picker in 24 hours format */ - @Prop({ reflect: true }) extended = false; + @Prop({ reflect: true }) format: DatePickerFormats = '12hr'; /** * To render Minutes and Seconds columns in stepped format @@ -119,7 +120,7 @@ export class Time { this._hour = time[0]; this._minute = time[1]; this._second = time[2] ? time[2] : '00'; - this._period = !this.extended && parseInt(this._hour) < 12 ? 'am' : 'pm'; + this._period = !(this.format === '24hr') && parseInt(this._hour) < 12 ? 'am' : 'pm'; } connectedCallback() { @@ -134,10 +135,10 @@ export class Time { }; hours() { - const startHour = this.extended ? 24 : 12; + const startHour = (this.format === '24hr') ? 24 : 12; let hourToSet: string; const setHour = (hour: string) => { - if (this.extended) { + if (this.format === '24hr') { if (hour === '24') { hourToSet = '00'; } else { @@ -168,7 +169,7 @@ export class Time { let hourStatus = ''; if (this._hour === hour || - (!this.extended && + (!(this.format === '24hr') && this._period === 'pm' && parseInt(hour) + 12 === valueHour ) || @@ -330,7 +331,7 @@ export class Time { periods() { const hour = parseInt(this.value.split(':')[0]); - if (!this.extended) { + if (!(this.format === '24hr')) { const periodClasses = (period: 'am' | 'pm') => { let periodStatus = TIME_CLASSES.PERIOD; @@ -362,6 +363,7 @@ export class Time { } this.value = `${currentHour}:${this._minute}:${this._second}`; + this._hour = this.formatTimePeriod(currentHour); this.emitTimeValueEvent(); }; @@ -400,21 +402,21 @@ export class Time { const activeHour = hoursColumn.querySelector(`.${TIME_CLASSES.HOUR}.-active`) as HTMLElement; if (activeHour) { - hoursColumn.scrollTop = activeHour.offsetTop - 28; + hoursColumn.scrollTop = activeHour.offsetTop - CHI_TIME_SCROLL_ADJUSTMENT; } } if (minutesColumn) { const activeMinute = minutesColumn.querySelector(`.${TIME_CLASSES.MINUTE}.-active`) as HTMLElement; if (activeMinute) { - minutesColumn.scrollTop = activeMinute.offsetTop - 28; + minutesColumn.scrollTop = activeMinute.offsetTop - CHI_TIME_SCROLL_ADJUSTMENT; } } if (secondsColumn) { const activeSecond = secondsColumn.querySelector(`.${TIME_CLASSES.SECOND}.-active`) as HTMLElement; if (activeSecond) { - secondsColumn.scrollTop = activeSecond.offsetTop - 28; + secondsColumn.scrollTop = activeSecond.offsetTop - CHI_TIME_SCROLL_ADJUSTMENT; } } } diff --git a/src/custom-elements/src/constants/constants.ts b/src/custom-elements/src/constants/constants.ts index cf4648b16..97609b27f 100644 --- a/src/custom-elements/src/constants/constants.ts +++ b/src/custom-elements/src/constants/constants.ts @@ -35,3 +35,12 @@ export const TEXT_INPUT_TYPES = [ 'week' ] as const; export type TextInputTypes = typeof TEXT_INPUT_TYPES[number]; + +export const DATE_PICKER_MODES = ['date', 'datetime']; +export type DatePickerModes = typeof DATE_PICKER_MODES[number]; + +export const CHI_TIME_AUTO_SCROLL_DELAY = 50; +export const CHI_TIME_SCROLL_ADJUSTMENT = 28; + +export const TIME_PICKER_FORMATS = ['12hours', '24hours']; +export type DatePickerFormats = typeof TIME_PICKER_FORMATS[number]; diff --git a/src/website/views/components/date-picker/_examples.pug b/src/website/views/components/date-picker/_examples.pug index 572045dd0..8973e3396 100644 --- a/src/website/views/components/date-picker/_examples.pug +++ b/src/website/views/components/date-picker/_examples.pug @@ -189,7 +189,7 @@ p.-text div(style="max-width: 14rem;") chi-label(for='date-time') | Date Time - chi-date-picker(id="date-time" time) + chi-date-picker(id="date-time" mode="datetime") .example-tabs.-pl--2 ul.chi-tabs#example-datetime li.-active diff --git a/src/website/views/components/time-picker/_examples.pug b/src/website/views/components/time-picker/_examples.pug index 67b3832f0..ed67648ed 100644 --- a/src/website/views/components/time-picker/_examples.pug +++ b/src/website/views/components/time-picker/_examples.pug @@ -6,7 +6,7 @@ p.-text .-p--3 div.chi-form__item(style="max-width: 14rem;") chi-label(for="time-picker-base") Label - chi-time-picker(id="time-picker-base" display-seconds) + chi-time-picker(id="time-picker-base") .example-tabs.-pl--2 ul.chi-tabs#example-with-label li.-active @@ -37,8 +37,8 @@ p.-text a(href=`#html-disabled`) HTML Blueprint #webcomponent-disabled.chi-tabs-panel.-active :code(lang="html") - Label - + Label + #html-disabled.chi-tabs-panel h3 Value option @@ -46,7 +46,7 @@ h3 Value option .-p--3 div.chi-form__item(style="max-width: 14rem;") chi-label(for='unique-id-va1') Time - chi-time-picker#unique-id-va1(value='09:00:00') + chi-time-picker#unique-id-va1(value='09:00') .example-tabs.-pl--2 ul.chi-tabs#example-min-max-value li.-active @@ -56,28 +56,28 @@ h3 Value option #webcomponent-min-max-value.chi-tabs-panel.-active :code(lang="html") Time - + #html-min-max-value.chi-tabs-panel -h3 Excluded hours, minutes and seconds -p.-text - | Specify which hours to disable by using the excluded-hours attribute. -.example.-mb--3 - .-p--3 - div.chi-form__item(style="max-width: 14rem;") - chi-label(for="time-picker-excluded") Label - chi-time-picker(id="time-picker-excluded", excluded-hours="14, 15", excluded-minutes="00, 01, 02, 03, 04, 05", excluded-seconds="00, 01, 02, 03, 04, 05", display-seconds) - .example-tabs.-pl--2 - ul.chi-tabs#example-excluded-times - li.-active - a(href=`#webcomponent-excluded-times`) Web Component - li.-disabled - a(href=`#html-excluded-times`) HTML Blueprint - #webcomponent-excluded-times.chi-tabs-panel.-active - :code(lang="html",style="height:20rem") - Time - - #html-excluded-times.chi-tabs-panel +//h3 Excluded hours, minutes and seconds +//p.-text +// | Specify which times to exclude by using the excluded-hours attribute to exclude hours, excluded-minutes to exclude minutes, and excluded-seconds to exclude seconds. +//.example.-mb--3 +// .-p--3 +// div.chi-form__item(style="max-width: 14rem;") +// chi-label(for="time-picker-excluded") Label +// chi-time-picker(id="time-picker-excluded", excluded-hours="14, 15", excluded-minutes="00, 01, 02, 03, 04, 05", excluded-seconds="00, 01, 02, 03, 04, 05", display-seconds) +// .example-tabs.-pl--2 +// ul.chi-tabs#example-excluded-times +// li.-active +// a(href=`#webcomponent-excluded-times`) Web Component +// li.-disabled +// a(href=`#html-excluded-times`) HTML Blueprint +// #webcomponent-excluded-times.chi-tabs-panel.-active +// :code(lang="html",style="height:20rem") +// Time +// +// #html-excluded-times.chi-tabs-panel h3 Time p.-text @@ -100,7 +100,7 @@ h4 Base h4 Active .example.-mb--3 .-p--3 - chi-time(value="14:00:00") + chi-time(value="14:00") .example-tabs.-pl--2 ul.chi-tabs#example-active li.-active @@ -109,7 +109,7 @@ h4 Active a(href=`#html-active`) HTML Blueprint #webcomponent-active.chi-tabs-panel.-active :code(lang="html") - + #html-active.chi-tabs-panel h4 Seconds @@ -124,13 +124,13 @@ h4 Seconds a(href=`#html-seconds`) HTML Blueprint #webcomponent-seconds.chi-tabs-panel.-active :code(lang="html") - + #html-seconds.chi-tabs-panel h4 24-hour format .example.-mb--3 .-p--3 - chi-time(extended) + chi-time(format='24hr') .example-tabs.-pl--2 ul.chi-tabs#example-24hour li.-active @@ -139,7 +139,7 @@ h4 24-hour format a(href=`#html-24hour`) HTML Blueprint #webcomponent-24hour.chi-tabs-panel.-active :code(lang="html") - + #html-24hour.chi-tabs-panel h4 Step From 6a2a85e0e6f9d9c2b35c2f7095923774ebd95f2e Mon Sep 17 00:00:00 2001 From: Jani Bolkvadze Date: Tue, 22 Dec 2020 12:49:36 +0100 Subject: [PATCH 7/7] Hid Time and Chi Picker wc excluded time periods props --- CHANGELOG.md | 1 + src/custom-elements/docs/docs.json | 96 ------------------- .../components/time-picker/time-picker.tsx | 12 +-- .../src/components/time/time.tsx | 18 ++-- .../components/date-picker/_examples.pug | 4 +- .../views/getting-started/whats-new.pug | 1 + 6 files changed, 19 insertions(+), 113 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1011db138..766d24eb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### Components #### Added * Added: Time picker and Datetime picker components to allow users to enter a time through text input or choose a time from a picker. +* Added: Date Picker web component now supports resetDate method. #### Changed * Changed: Modal components with theme `-portal` now align buttons in `chi-modal__footer` to the right (Chi's default) instead of center. * Changed: Picker group components with theme `-portal` now include a text color change on hover. diff --git a/src/custom-elements/docs/docs.json b/src/custom-elements/docs/docs.json index fa6f00f76..9a635e44c 100644 --- a/src/custom-elements/docs/docs.json +++ b/src/custom-elements/docs/docs.json @@ -3226,54 +3226,6 @@ "optional": false, "required": false }, - { - "name": "excludedHours", - "type": "string", - "mutable": false, - "attr": "excluded-hours", - "reflectToAttr": true, - "docs": "To disable specific hours", - "docsTags": [], - "values": [ - { - "type": "string" - } - ], - "optional": false, - "required": false - }, - { - "name": "excludedMinutes", - "type": "string", - "mutable": false, - "attr": "excluded-minutes", - "reflectToAttr": true, - "docs": "To disable specific minutes", - "docsTags": [], - "values": [ - { - "type": "string" - } - ], - "optional": false, - "required": false - }, - { - "name": "excludedSeconds", - "type": "string", - "mutable": false, - "attr": "excluded-seconds", - "reflectToAttr": true, - "docs": "To disable specific seconds", - "docsTags": [], - "values": [ - { - "type": "string" - } - ], - "optional": false, - "required": false - }, { "name": "format", "type": "string", @@ -3411,54 +3363,6 @@ "optional": false, "required": false }, - { - "name": "excludedHours", - "type": "string", - "mutable": false, - "attr": "excluded-hours", - "reflectToAttr": true, - "docs": "To specify excluded hours.", - "docsTags": [], - "values": [ - { - "type": "string" - } - ], - "optional": false, - "required": false - }, - { - "name": "excludedMinutes", - "type": "string", - "mutable": false, - "attr": "excluded-minutes", - "reflectToAttr": true, - "docs": "To specify excluded minutes.", - "docsTags": [], - "values": [ - { - "type": "string" - } - ], - "optional": false, - "required": false - }, - { - "name": "excludedSeconds", - "type": "string", - "mutable": false, - "attr": "excluded-seconds", - "reflectToAttr": true, - "docs": "To specify excluded seconds.", - "docsTags": [], - "values": [ - { - "type": "string" - } - ], - "optional": false, - "required": false - }, { "name": "format", "type": "string", diff --git a/src/custom-elements/src/components/time-picker/time-picker.tsx b/src/custom-elements/src/components/time-picker/time-picker.tsx index 5ea7ba5ae..b2fd0bb73 100644 --- a/src/custom-elements/src/components/time-picker/time-picker.tsx +++ b/src/custom-elements/src/components/time-picker/time-picker.tsx @@ -28,17 +28,17 @@ export class TimePicker { /** * To specify excluded hours. */ - @Prop({ reflect: true }) excludedHours: string; + @Prop({ reflect: true }) _excludedHours: string; /** * To specify excluded minutes. */ - @Prop({ reflect: true }) excludedMinutes: string; + @Prop({ reflect: true }) _excludedMinutes: string; /** * To specify excluded seconds. */ - @Prop({ reflect: true }) excludedSeconds: string; + @Prop({ reflect: true }) _excludedSeconds: string; /** * To define format of Time Picker. @@ -169,9 +169,9 @@ export class TimePicker { > diff --git a/src/custom-elements/src/components/time/time.tsx b/src/custom-elements/src/components/time/time.tsx index b8c784440..98073c920 100644 --- a/src/custom-elements/src/components/time/time.tsx +++ b/src/custom-elements/src/components/time/time.tsx @@ -38,17 +38,17 @@ export class Time { /** * To disable specific hours */ - @Prop({ reflect: true }) excludedHours: string; + @Prop({ reflect: true }) _excludedHours: string; /** * To disable specific minutes */ - @Prop({ reflect: true }) excludedMinutes: string; + @Prop({ reflect: true }) _excludedMinutes: string; /** * To disable specific seconds */ - @Prop({ reflect: true }) excludedSeconds: string; + @Prop({ reflect: true }) _excludedSeconds: string; @Element() el: HTMLElement; @@ -63,8 +63,8 @@ export class Time { @Watch('excluded-hours') updateExcludedHours() { - if (this.excludedHours) { - this.excludedHours.split(',').map(time => { + if (this._excludedHours) { + this._excludedHours.split(',').map(time => { this.excludedHoursArray.push(time.trim()); }); } @@ -72,8 +72,8 @@ export class Time { @Watch('excluded-minutes') updateExcludedMinutes() { - if (this.excludedMinutes) { - this.excludedMinutes.split(',').map(time => { + if (this._excludedMinutes) { + this._excludedMinutes.split(',').map(time => { this.excludedMinutesArray.push(time.trim()); }); } @@ -81,8 +81,8 @@ export class Time { @Watch('excluded-seconds') updateExcludedSeconds() { - if (this.excludedSeconds) { - this.excludedSeconds.split(',').map(time => { + if (this._excludedSeconds) { + this._excludedSeconds.split(',').map(time => { this.excludedSecondsArray.push(time.trim()); }); } diff --git a/src/website/views/components/date-picker/_examples.pug b/src/website/views/components/date-picker/_examples.pug index 8973e3396..188272ff3 100644 --- a/src/website/views/components/date-picker/_examples.pug +++ b/src/website/views/components/date-picker/_examples.pug @@ -198,8 +198,8 @@ p.-text a(href=`#html-datetime`) HTML Blueprint #webcomponent-datetime.chi-tabs-panel.-active :code(lang="html",style="height:20rem") - Date - + Date + #html-datetime.chi-tabs-panel h3 Calendar diff --git a/src/website/views/getting-started/whats-new.pug b/src/website/views/getting-started/whats-new.pug index c7776a4ff..83e488199 100644 --- a/src/website/views/getting-started/whats-new.pug +++ b/src/website/views/getting-started/whats-new.pug @@ -13,6 +13,7 @@ script(nomodule='' src='../../js/ce/ux-chi-ce/ux-chi-ce.js') h4.-text--h4.-text--bold Added ul.-text.-pl--2 li Added: Time picker and Datetime picker components to allow users to enter a time through text input or choose a time from a picker. + li Added: Date Picker web component now supports resetDate method. h4.-text--h4.-text--bold Changed ul.-text.-pl--2 li Changed: Modal components with theme -portal now align buttons in chi-modal__footer to the right (Chi's default) instead of center.