@grafana/ui
Version:
Grafana Components Library
138 lines (135 loc) • 4.11 kB
JavaScript
import { jsx } from 'react/jsx-runtime';
import { isString, toLower, isEmpty } from 'lodash';
import { useCallback, useMemo } from 'react';
import { getTimeZoneGroups, getTimeZoneInfo, InternalTimeZones } from '@grafana/data';
import { t } from '@grafana/i18n';
import { Select } from '../Select/Select.mjs';
import { TimeZoneGroup } from './TimeZonePicker/TimeZoneGroup.mjs';
import { formatUtcOffset } from './TimeZonePicker/TimeZoneOffset.mjs';
import { CompactTimeZoneOption, WideTimeZoneOption } from './TimeZonePicker/TimeZoneOption.mjs';
const TimeZonePicker = (props) => {
const {
onChange,
width,
autoFocus = false,
onBlur,
value,
includeInternal = false,
disabled = false,
inputId,
menuShouldPortal = true,
openMenuOnFocus = true
} = props;
const groupedTimeZones = useTimeZones(includeInternal);
const selected = useSelectedTimeZone(groupedTimeZones, value);
const filterBySearchIndex = useFilterBySearchIndex();
const TimeZoneOption = width && width <= 45 ? CompactTimeZoneOption : WideTimeZoneOption;
const onChangeTz = useCallback(
(selectable) => {
if (!selectable || !isString(selectable.value)) {
return onChange(value);
}
onChange(selectable.value);
},
[onChange, value]
);
return /* @__PURE__ */ jsx(
Select,
{
inputId,
value: selected,
placeholder: t("time-picker.zone.select-search-input", "Type to search (country, city, abbreviation)"),
autoFocus,
menuShouldPortal,
openMenuOnFocus,
width,
filterOption: filterBySearchIndex,
options: groupedTimeZones,
onChange: onChangeTz,
onBlur,
components: { Option: TimeZoneOption, Group: TimeZoneGroup },
disabled,
"aria-label": t("time-picker.zone.select-aria-label", "Time zone picker")
}
);
};
const useTimeZones = (includeInternal) => {
const now = Date.now();
const timeZoneGroups = useMemo(() => {
return getTimeZoneGroups(includeInternal).map((group) => {
const options = group.zones.reduce((options2, zone) => {
const info = getTimeZoneInfo(zone, now);
if (!info) {
return options2;
}
const name = info.name.replace(/_/g, " ");
options2.push({
label: name,
value: info.zone,
searchIndex: getSearchIndex(name, info, now)
});
return options2;
}, []);
return {
label: group.name,
options
};
});
}, [includeInternal, now]);
return timeZoneGroups;
};
const useSelectedTimeZone = (groups, timeZone) => {
return useMemo(() => {
if (timeZone === void 0) {
return void 0;
}
const tz = toLower(timeZone);
const group = groups.find((group2) => {
if (!group2.label) {
return isInternal(tz);
}
return tz.startsWith(toLower(group2.label));
});
return group == null ? void 0 : group.options.find((option) => {
if (isEmpty(tz)) {
return option.value === InternalTimeZones.default;
}
return toLower(option.value) === tz;
});
}, [groups, timeZone]);
};
const isInternal = (timeZone) => {
switch (timeZone) {
case InternalTimeZones.default:
case InternalTimeZones.localBrowserTime:
case InternalTimeZones.utc:
return true;
default:
return false;
}
};
const useFilterBySearchIndex = () => {
return useCallback((option, searchQuery) => {
if (!searchQuery || !option.data || !option.data.searchIndex) {
return true;
}
return option.data.searchIndex.indexOf(toLower(searchQuery)) > -1;
}, []);
};
const getSearchIndex = (label, info, timestamp) => {
const parts = [
toLower(info.zone),
toLower(info.abbreviation),
toLower(formatUtcOffset(timestamp, info.zone))
];
if (label !== info.zone) {
parts.push(toLower(label));
}
for (const country of info.countries) {
parts.push(toLower(country.name));
parts.push(toLower(country.code));
}
return parts.join("|");
};
export { TimeZonePicker };
//# sourceMappingURL=TimeZonePicker.mjs.map