@kelvininc/ui-components
Version:
Kelvin UI Components
498 lines (497 loc) • 22.1 kB
JavaScript
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"
}];
}
}