-
Notifications
You must be signed in to change notification settings - Fork 44
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-authored-by: Alex <alex-ju@users.noreply.github.com> Co-authored-by: Lee White <leewhite128@gmail.com> Co-authored-by: Andrew Gendel <124841193+andgen404@users.noreply.github.com> Co-authored-by: Jory Tindall <jory.tindall@hashicorp.com> Co-authored-by: Majed <156002572+majedelass@users.noreply.github.com>
- Loading branch information
1 parent
c173c84
commit b25a458
Showing
38 changed files
with
5,536 additions
and
5,386 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
--- | ||
"@hashicorp/design-system-components": minor | ||
--- | ||
|
||
`Time` - Added Time component, Time service, and related libraries including: | ||
- luxon (2.x or 3.x) | ||
- ember-concurrency (4.x) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
{{! | ||
Copyright (c) HashiCorp, Inc. | ||
SPDX-License-Identifier: MPL-2.0 | ||
}} | ||
{{! IMPORTANT: we need to add "squishies" here (~) because otherwise the whitespace added by Ember causes extra space around the time element - See https://handlebarsjs.com/guide/expressions.html#whitespace-control }} | ||
{{~#let this.display as |display|~}} | ||
{{~#if this.isValidDate~}} | ||
{{~#if this.hasTooltip~}} | ||
<Hds::TooltipButton | ||
class="hds-time-wrapper" | ||
@text={{if | ||
display.options.tooltipFormat | ||
(hds-format-date this.date display.options.tooltipFormat) | ||
this.isoUtcString | ||
}} | ||
@placement="bottom" | ||
@extraTippyOptions={{hash showOnCreate=this.isOpen}} | ||
> | ||
<Hds::Time::Single | ||
@date={{this.date}} | ||
@isoUtcString={{this.isoUtcString}} | ||
@display={{this.display}} | ||
@register={{this.didInsertNode}} | ||
@unregister={{this.willDestroyNode}} | ||
...attributes | ||
/> | ||
</Hds::TooltipButton> | ||
{{~else~}} | ||
<Hds::Time::Single | ||
@date={{this.date}} | ||
@isoUtcString={{this.isoUtcString}} | ||
@display={{this.display}} | ||
@register={{this.didInsertNode}} | ||
@unregister={{this.willDestroyNode}} | ||
...attributes | ||
/> | ||
{{~/if~}} | ||
{{~else if this.isValidDateRange~}} | ||
{{~#if this.hasTooltip~}} | ||
<Hds::TooltipButton | ||
class="hds-time-wrapper" | ||
@text={{if | ||
display.options.tooltipFormat | ||
(concat | ||
(hds-format-date this.startDate display.options.tooltipFormat) | ||
(hds-format-date this.endDate display.options.tooltipFormat) | ||
) | ||
this.rangeIsoUtcString | ||
}} | ||
@placement="bottom" | ||
@extraTippyOptions={{hash showOnCreate=this.isOpen}} | ||
> | ||
<Hds::Time::Range @startDate={{this.startDate}} @endDate={{this.endDate}} ...attributes /> | ||
</Hds::TooltipButton> | ||
{{~else~}} | ||
<Hds::Time::Range @startDate={{this.startDate}} @endDate={{this.endDate}} ...attributes /> | ||
{{~/if~}} | ||
{{~/if~}} | ||
{{~/let~}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
/** | ||
* Copyright (c) HashiCorp, Inc. | ||
* SPDX-License-Identifier: MPL-2.0 | ||
*/ | ||
|
||
import Component from '@glimmer/component'; | ||
import { typeOf } from '@ember/utils'; | ||
import { inject as service } from '@ember/service'; | ||
import { action } from '@ember/object'; | ||
import type { DisplayType } from '../../../services/hds-time-types.ts'; | ||
|
||
import type TimeService from '../../../services/hds-time'; | ||
|
||
export interface HdsTimeSignature { | ||
Args: { | ||
date?: Date | string; | ||
startDate?: Date | string; | ||
endDate?: Date | string; | ||
display?: | ||
| 'utc' | ||
| 'relative' | ||
| 'friendly-only' | ||
| 'friendly-local' | ||
| 'friendly-relative'; | ||
isOpen?: boolean; | ||
hasTooltip?: boolean; | ||
isoUtcString?: string; | ||
}; | ||
Element: HTMLElement; | ||
} | ||
|
||
const dateIsValid = (date?: Date | string): date is Date => | ||
date instanceof Date && !isNaN(+date); | ||
|
||
export default class HdsTime extends Component<HdsTimeSignature> { | ||
@service declare readonly hdsTime: TimeService; | ||
|
||
get date(): Date | undefined { | ||
const { date } = this.args; | ||
|
||
// Sometimes an ISO date string might be passed in instead of a JS Date. | ||
if (date) { | ||
if (typeOf(date) === 'string') { | ||
return new Date(date); | ||
} else if (date instanceof Date) { | ||
return date; | ||
} | ||
} | ||
} | ||
|
||
get startDate(): Date | undefined { | ||
const { startDate } = this.args; | ||
|
||
if (startDate) { | ||
if (typeOf(startDate) === 'string') { | ||
return new Date(startDate); | ||
} else if (startDate instanceof Date) { | ||
return startDate; | ||
} | ||
} | ||
} | ||
|
||
get endDate(): Date | undefined { | ||
const { endDate } = this.args; | ||
|
||
if (endDate) { | ||
if (typeOf(endDate) === 'string') { | ||
return new Date(endDate); | ||
} else if (endDate instanceof Date) { | ||
return endDate; | ||
} | ||
} | ||
} | ||
|
||
get isValidDate(): boolean { | ||
return dateIsValid(this.date); | ||
} | ||
|
||
get isValidDateRange(): boolean { | ||
if (dateIsValid(this.startDate) && dateIsValid(this.endDate)) { | ||
return this.startDate <= this.endDate; | ||
} | ||
return false; | ||
} | ||
|
||
get hasTooltip(): boolean { | ||
return this.args.hasTooltip ?? true; | ||
} | ||
|
||
get isoUtcString(): string | undefined { | ||
const date = this.date; | ||
|
||
if (dateIsValid(date)) { | ||
return this.hdsTime.toIsoUtcString(date); | ||
} | ||
|
||
return undefined; | ||
} | ||
|
||
get rangeIsoUtcString(): string { | ||
const startDate = this.startDate; | ||
const endDate = this.endDate; | ||
|
||
if (dateIsValid(startDate) && dateIsValid(endDate)) { | ||
return `${this.hdsTime.toIsoUtcString(startDate)}–${this.hdsTime.toIsoUtcString(endDate)}`; | ||
} | ||
return ''; | ||
} | ||
|
||
get display(): DisplayType { | ||
const date = this.date; | ||
const { display } = this.args; | ||
|
||
if (dateIsValid(date)) { | ||
const nextDiff = this.hdsTime.timeDifference(this.hdsTime.now, date); | ||
return this.hdsTime.format(nextDiff, display); | ||
} | ||
return { | ||
options: undefined, | ||
difference: { absValueInMs: 0, valueInMs: 0 }, | ||
relative: { value: 0, unit: '' }, | ||
}; | ||
} | ||
|
||
get isOpen(): boolean { | ||
return this.args.isOpen ?? false; | ||
} | ||
|
||
@action | ||
didInsertNode(): void { | ||
const date = this.date; | ||
|
||
if (dateIsValid(date)) { | ||
this.hdsTime.register(date); | ||
} | ||
} | ||
|
||
@action | ||
willDestroyNode(): void { | ||
const date = this.date; | ||
|
||
if (dateIsValid(date)) { | ||
this.hdsTime.unregister(date); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{{! | ||
Copyright (c) HashiCorp, Inc. | ||
SPDX-License-Identifier: MPL-2.0 | ||
}} | ||
{{! IMPORTANT: we need to add "squishies" here (~) because otherwise the whitespace added by Ember causes extra space around the time element - See https://handlebarsjs.com/guide/expressions.html#whitespace-control }} | ||
<span class="hds-time hds-time--range" ...attributes> | ||
<time datetime={{this.startDateIsoUtcString}}> | ||
{{~hds-format-date @startDate this.startDateDisplayFormat~}} | ||
</time> | ||
– | ||
<time datetime={{this.endDateIsoUtcString}}> | ||
{{~hds-format-date @endDate this.endDateDisplayFormat~}} | ||
</time> | ||
</span> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
/** | ||
* Copyright (c) HashiCorp, Inc. | ||
* SPDX-License-Identifier: MPL-2.0 | ||
*/ | ||
|
||
import Component from '@glimmer/component'; | ||
import { inject as service } from '@ember/service'; | ||
import type TimeService from '../../../services/hds-time'; | ||
|
||
export interface HdsTimeRangeSignature { | ||
Args: { | ||
startDate?: Date; | ||
endDate?: Date; | ||
}; | ||
Element: HTMLElement; | ||
} | ||
|
||
export default class HdsTimeRange extends Component<HdsTimeRangeSignature> { | ||
@service declare readonly hdsTime: TimeService; | ||
|
||
get startDateIsoUtcString(): string | undefined { | ||
const { startDate } = this.args; | ||
if (startDate) { | ||
return this.hdsTime.toIsoUtcString(startDate); | ||
} | ||
} | ||
|
||
get endDateIsoUtcString(): string | undefined { | ||
const { endDate } = this.args; | ||
if (endDate) { | ||
return this.hdsTime.toIsoUtcString(endDate); | ||
} | ||
} | ||
|
||
get startDateDisplayFormat(): { | ||
month: Intl.DateTimeFormatOptions['month']; | ||
day: Intl.DateTimeFormatOptions['day']; | ||
year?: Intl.DateTimeFormatOptions['year']; | ||
hour?: Intl.DateTimeFormatOptions['hour']; | ||
minute?: Intl.DateTimeFormatOptions['minute']; | ||
second?: Intl.DateTimeFormatOptions['second']; | ||
} { | ||
const { startDate, endDate } = this.args; | ||
|
||
if (startDate?.getFullYear() !== endDate?.getFullYear()) { | ||
return { | ||
month: 'short', | ||
day: 'numeric', | ||
year: 'numeric', | ||
}; | ||
} else { | ||
return { | ||
month: 'short', | ||
day: 'numeric', | ||
year: undefined, | ||
}; | ||
} | ||
} | ||
|
||
get endDateDisplayFormat(): { | ||
month: Intl.DateTimeFormatOptions['month']; | ||
day: Intl.DateTimeFormatOptions['day']; | ||
year?: Intl.DateTimeFormatOptions['year']; | ||
hour?: Intl.DateTimeFormatOptions['hour']; | ||
minute?: Intl.DateTimeFormatOptions['minute']; | ||
second?: Intl.DateTimeFormatOptions['second']; | ||
} { | ||
return { | ||
month: 'short', | ||
day: 'numeric', | ||
year: 'numeric', | ||
}; | ||
} | ||
} |
Oops, something went wrong.