UNPKG

@kelvininc/ui-components

Version:
498 lines (497 loc) 22.1 kB
import { Host, h } from "@stencil/core"; import { CUSTOMIZE_INTERVAL_KEY, CUSTOMIZE_INTERVAL_LABEL, DEFAULT_RELATIVE_TIME_OPTIONS_GROUPS, GROUP_GAP, MAX_HEIGHT, PADDING_SIZE, SELECT_OPTION_HEIGHT, TIMEZONES_PLACEHOLDER, TIMEZONES_SEARCH_PLACEHOLDER, TIME_RANGE_UPDATE_INTERVAL } from "./relative-time-picker.config"; import { EIconName } from "../icon/icon.types"; import { buildTimezoneByOffset, formatTimezoneName, getDefaultTimezone, getTimezoneOffset, getTimezonesNames } from "../../utils/date.helper"; import { buildRelativeTimeSelectOptions, buildTimezonesDropdownOptions, getSelectedKeyRange, hasRangeChanged, isScrollNeeded } from "./relative-time-picker.helper"; import { EComponentSize } from "../../types"; import { isEmpty } from "lodash-es"; import { getClassMap } from "../../utils/css-class.helper"; import { searchDropdownOptions } from "../../utils/select.helper"; export class KvRelativeTimePicker { constructor() { /** @inheritdoc */ this.options = DEFAULT_RELATIVE_TIME_OPTIONS_GROUPS; /** @inheritdoc */ this.timezones = buildTimezoneByOffset(getTimezonesNames()); /** @inheritdoc */ this.customIntervalOptionEnabled = true; /** @inheritdoc */ this.timezoneSelectionEnabled = true; /** @inheritdoc */ this.timezoneContentVisible = false; /** @inheritdoc */ this.disableTimezoneSelection = false; /** @inheritdoc */ this.customClass = ''; /** State that keeps the relative options that are constantly updated if the time * changes */ this.relativeTimeOptions = []; /** Timezone dropdown management states */ this.timezonesSearchTerm = ''; /** State to determine if a scrollbar is needed to display all the options */ this.hasScroll = false; this.onTimezoneSearchTermChange = ({ detail: newSearchTerm }) => { this.timezonesSearchTerm = newSearchTerm; }; this.onTimezoneSelected = ({ detail: newSelectedTimezone }) => { this.timezoneChange.emit({ name: newSelectedTimezone, offset: getTimezoneOffset(newSelectedTimezone) }); }; this.onSelectRelativeOption = ({ detail: newOption }, range) => { this.hasSelectedKeyRangeChanged(range, newOption); }; this.hasSelectedKeyRangeChanged = (newRange, optionSelected) => { if (hasRangeChanged(this.selectedOptionRange, newRange) || optionSelected !== this.selectedTimeKey) { this.selectedOptionRange = newRange; this.selectedRelativeTimeChange.emit({ key: optionSelected, range: newRange }); } }; this.onSelectCustomizeIntervalOption = ({ detail: newOption }) => { this.selectedOptionRange = []; this.customizeIntervalClicked.emit(newOption); }; this.handleShowTimezoneContent = () => { this.timezoneInputClicked.emit(true); }; this.getSelectedTimezone = () => { if (this.selectedTimezone !== undefined) { return this.selectedTimezone; } return getDefaultTimezone(); }; this.getSelectedTimezoneTitle = () => { const timezone = this.getSelectedTimezone(); return timezone ? formatTimezoneName(timezone) : ''; }; this.onTimezoneChange = ({ detail: openState }) => { this.timezoneDropdownStateChange.emit(openState); }; } handleRelativeTimeOptionsChanges() { var _a; const optionsToBuild = (_a = this.options) !== null && _a !== void 0 ? _a : DEFAULT_RELATIVE_TIME_OPTIONS_GROUPS; const dropdownOptions = buildRelativeTimeSelectOptions(optionsToBuild, this.getSelectedTimezone()); this.relativeTimeOptions = dropdownOptions; if (!isEmpty(this.selectedTimeKey) && this.selectedTimeKey !== CUSTOMIZE_INTERVAL_KEY) { const currentRange = getSelectedKeyRange(dropdownOptions, this.selectedTimeKey); this.hasSelectedKeyRangeChanged(currentRange, this.selectedTimeKey); } if (this.relativeTimeOptions && this.relativeTimeOptions.length === 0) return; this.hasScroll = isScrollNeeded(this.options, this.customIntervalOptionEnabled, this.timezoneSelectionEnabled); } onTimezonesChange(timezones) { this.timezoneDropdownOptions = buildTimezonesDropdownOptions(timezones); } onTimezoneSearch(searchTerm) { this.timezoneFilteredDropdownOptions = searchDropdownOptions(searchTerm, this.timezoneDropdownOptions); } onSelectedTimeKeyChange(newKey) { if (newKey !== CUSTOMIZE_INTERVAL_KEY) { this.selectedOptionRange = getSelectedKeyRange(this.relativeTimeOptions, this.selectedTimeKey); } } onSelectedTimezoneChange() { this.handleRelativeTimeOptionsChanges(); } componentWillLoad() { this.handleRelativeTimeOptionsChanges(); } connectedCallback() { this.timezoneDropdownOptions = buildTimezonesDropdownOptions(this.timezones); this.intervalID = window.setInterval(() => { this.handleRelativeTimeOptionsChanges(); }, TIME_RANGE_UPDATE_INTERVAL); } disconnectedCallback() { window.clearInterval(this.intervalID); } render() { return (h(Host, { key: '159ef2bf1c3c804bb4e55830b3a44cb68da5df81' }, h("div", { key: '87e0efe593ace59a3e6ba2c775e0dbad8e3e38db', class: Object.assign(Object.assign({}, getClassMap(this.customClass)), { 'relative-time-container': true }), style: { ['--max-height']: `${MAX_HEIGHT}px`, ['--group-gap']: `${GROUP_GAP}px` } }, h("div", { key: '13a3d0ae03e84d4f511041439f031fb6a321c378', class: { 'relative-time-selector': true, 'relative-time-selector--has-scroll': this.hasScroll }, style: { ['--option-height']: `${SELECT_OPTION_HEIGHT}px`, ['--padding-size']: `${PADDING_SIZE}px` } }, this.relativeTimeOptions.map((group, index) => (h("div", { key: index, class: "relative-time-group" }, group.map(({ label, value, description, range }) => (h("kv-time-picker-select-option", { key: label, label: label, value: value, description: description, selected: value === this.selectedTimeKey, onItemSelected: detail => this.onSelectRelativeOption(detail, range) }))))))), this.customIntervalOptionEnabled && (h("div", { key: 'bb65f776eb7f73ccbe4e3e04a8474a1c16069ed5', class: "selectable" }, h("kv-select-option", { key: CUSTOMIZE_INTERVAL_KEY, label: CUSTOMIZE_INTERVAL_LABEL, value: CUSTOMIZE_INTERVAL_KEY, selected: CUSTOMIZE_INTERVAL_KEY === this.selectedTimeKey, onItemSelected: this.onSelectCustomizeIntervalOption }))), this.timezoneSelectionEnabled && (h("div", { key: 'd0dd57d61c78b2b942fc9887c9ddbed06f65c8d9', class: "selectable" }, h("kv-input-wrapper", { key: '79ca55c922e3ca1737c35bda3f936fdda4115eea', contentVisible: this.timezoneContentVisible, contentHidden: this.disableTimezoneSelection, label: this.getSelectedTimezoneTitle(), icon: EIconName.Edit, onContentClick: this.handleShowTimezoneContent }, h("kv-single-select-dropdown", { key: 'bd31dbb789b3d64cf14432c8758c17b6c30e8e2c', searchable: true, icon: EIconName.Time, placeholder: TIMEZONES_PLACEHOLDER, inputSize: EComponentSize.Small, searchPlaceholder: TIMEZONES_SEARCH_PLACEHOLDER, options: this.timezoneDropdownOptions, filteredOptions: this.timezoneFilteredDropdownOptions, selectedOption: this.getSelectedTimezone(), onSearchChange: this.onTimezoneSearchTermChange, onOptionSelected: this.onTimezoneSelected, onOpenStateChange: this.onTimezoneChange }))))))); } static get is() { return "kv-relative-time-picker"; } static get encapsulation() { return "shadow"; } static get originalStyleUrls() { return { "$": ["relative-time-picker.scss"] }; } static get styleUrls() { return { "$": ["relative-time-picker.css"] }; } static get properties() { return { "selectedTimeKey": { "type": "string", "attribute": "selected-time-key", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "inheritdoc", "text": undefined }], "text": "(optional) Selected time range key" }, "getter": false, "setter": false, "reflect": true }, "options": { "type": "unknown", "attribute": "options", "mutable": false, "complexType": { "original": "IRelativeTimePickerOption[][]", "resolved": "IRelativeTimePickerOption[][]", "references": { "IRelativeTimePickerOption": { "location": "import", "path": "./relative-time-picker.types", "id": "src/components/relative-time-picker/relative-time-picker.types.ts::IRelativeTimePickerOption" } } }, "required": false, "optional": true, "docs": { "tags": [{ "name": "inheritdoc", "text": undefined }], "text": "(optional) Selectable relative time options" }, "getter": false, "setter": false, "defaultValue": "DEFAULT_RELATIVE_TIME_OPTIONS_GROUPS" }, "selectedTimezone": { "type": "string", "attribute": "selected-timezone", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "inheritdoc", "text": undefined }], "text": "(optional) Currently selected timezone name" }, "getter": false, "setter": false, "reflect": false }, "timezones": { "type": "unknown", "attribute": "timezones", "mutable": false, "complexType": { "original": "ITimezoneOffset[]", "resolved": "ITimezoneOffset[]", "references": { "ITimezoneOffset": { "location": "import", "path": "../time-picker/time-picker.types", "id": "src/components/time-picker/time-picker.types.ts::ITimezoneOffset" } } }, "required": false, "optional": true, "docs": { "tags": [{ "name": "inheritdoc", "text": undefined }], "text": "(optional) List of all selectable timezones" }, "getter": false, "setter": false, "defaultValue": "buildTimezoneByOffset(getTimezonesNames())" }, "customIntervalOptionEnabled": { "type": "boolean", "attribute": "custom-interval-option-enabled", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "inheritdoc", "text": undefined }], "text": "(optional) Defines if the customize interval select option is available" }, "getter": false, "setter": false, "reflect": false, "defaultValue": "true" }, "timezoneSelectionEnabled": { "type": "boolean", "attribute": "timezone-selection-enabled", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "inheritdoc", "text": undefined }], "text": "(optional) Defines if the timezone select option is available" }, "getter": false, "setter": false, "reflect": false, "defaultValue": "true" }, "timezoneContentVisible": { "type": "boolean", "attribute": "timezone-content-visible", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "inheritdoc", "text": undefined }], "text": "(optional) Determines if the input wrapper content containing the timezone is visible\nif true, the dropdown will be visible; if false, the content will display the timezone title" }, "getter": false, "setter": false, "reflect": true, "defaultValue": "false" }, "disableTimezoneSelection": { "type": "boolean", "attribute": "disable-timezone-selection", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "inheritdoc", "text": undefined }], "text": "(optional) Lets the timezone visible but doens't let the user change it" }, "getter": false, "setter": false, "reflect": true, "defaultValue": "false" }, "customClass": { "type": "string", "attribute": "custom-class", "mutable": false, "complexType": { "original": "CustomCssClass", "resolved": "CssClassMap | string | string[]", "references": { "CustomCssClass": { "location": "import", "path": "../../types", "id": "src/types.ts::CustomCssClass" } } }, "required": false, "optional": false, "docs": { "tags": [{ "name": "inheritdoc", "text": undefined }], "text": "(optional) Additional classes to apply for custom CSS. If multiple classes are\nprovided they should be separated by spaces. It is also valid to provide\nCssClassMap with boolean logic." }, "getter": false, "setter": false, "reflect": true, "defaultValue": "''" } }; } static get states() { return { "relativeTimeOptions": {}, "timezonesSearchTerm": {}, "timezoneDropdownOptions": {}, "timezoneFilteredDropdownOptions": {}, "hasScroll": {}, "selectedOptionRange": {} }; } static get events() { return [{ "method": "selectedRelativeTimeChange", "name": "selectedRelativeTimeChange", "bubbles": true, "cancelable": true, "composed": true, "docs": { "tags": [{ "name": "inheritdoc", "text": undefined }], "text": "Emitted when the selected time key changes" }, "complexType": { "original": "ITimePickerRelativeTime", "resolved": "{ key: string; range: SelectedTimestamp; }", "references": { "ITimePickerRelativeTime": { "location": "import", "path": "./relative-time-picker.types", "id": "src/components/relative-time-picker/relative-time-picker.types.ts::ITimePickerRelativeTime" } } } }, { "method": "customizeIntervalClicked", "name": "customizeIntervalClicked", "bubbles": true, "cancelable": true, "composed": true, "docs": { "tags": [{ "name": "inheritdoc", "text": undefined }], "text": "Emitted when customize interval is clicked" }, "complexType": { "original": "string", "resolved": "string", "references": {} } }, { "method": "timezoneChange", "name": "timezoneChange", "bubbles": true, "cancelable": true, "composed": true, "docs": { "tags": [{ "name": "inheritdoc", "text": undefined }], "text": "Emitted when selected timezone changes" }, "complexType": { "original": "ITimePickerTimezone", "resolved": "{ name: string; offset: number; }", "references": { "ITimePickerTimezone": { "location": "import", "path": "./relative-time-picker.types", "id": "src/components/relative-time-picker/relative-time-picker.types.ts::ITimePickerTimezone" } } } }, { "method": "timezoneInputClicked", "name": "timezoneInputClicked", "bubbles": true, "cancelable": true, "composed": true, "docs": { "tags": [{ "name": "inheritdoc", "text": undefined }], "text": "Emitted when the input wrapper containing the timezone is clicked" }, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} } }, { "method": "timezoneDropdownStateChange", "name": "timezoneDropdownStateChange", "bubbles": false, "cancelable": true, "composed": true, "docs": { "tags": [{ "name": "inheritdoc", "text": undefined }], "text": "Emitted when the timezone dropdown open state changes" }, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} } }]; } static get watchers() { return [{ "propName": "options", "methodName": "handleRelativeTimeOptionsChanges" }, { "propName": "timezones", "methodName": "onTimezonesChange" }, { "propName": "timezonesSearchTerm", "methodName": "onTimezoneSearch" }, { "propName": "selectedTimeKey", "methodName": "onSelectedTimeKeyChange" }, { "propName": "selectedTimezone", "methodName": "onSelectedTimezoneChange" }]; } }