@perses-dev/components 0.51.0-beta.0 → 0.51.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/dist/BarChart/BarChart.js.map +1 -1
  2. package/dist/ColorPicker/ColorPicker.js.map +1 -1
  3. package/dist/ColorPicker/OptionsColorPicker.js.map +1 -1
  4. package/dist/ContentWithLegend/ContentWithLegend.js.map +1 -1
  5. package/dist/DragAndDrop/DropIndicator.js.map +1 -1
  6. package/dist/Drawer/Drawer.js.map +1 -1
  7. package/dist/EChart/EChart.d.ts +3 -2
  8. package/dist/EChart/EChart.d.ts.map +1 -1
  9. package/dist/EChart/EChart.js +22 -4
  10. package/dist/EChart/EChart.js.map +1 -1
  11. package/dist/GaugeChart/GaugeChart.js.map +1 -1
  12. package/dist/InfoTooltip/InfoTooltip.js.map +1 -1
  13. package/dist/JSONEditor.d.ts.map +1 -1
  14. package/dist/JSONEditor.js +5 -6
  15. package/dist/JSONEditor.js.map +1 -1
  16. package/dist/OptionsEditorLayout/OptionsEditorControl.js.map +1 -1
  17. package/dist/Overlay/Overlay.js.map +1 -1
  18. package/dist/RefreshIntervalPicker/RefreshIntervalPicker.js.map +1 -1
  19. package/dist/SettingsAutocomplete/SettingsAutocomplete.js.map +1 -1
  20. package/dist/StatChart/StatChart.d.ts.map +1 -1
  21. package/dist/StatChart/StatChart.js +6 -2
  22. package/dist/StatChart/StatChart.js.map +1 -1
  23. package/dist/StatChart/calculateFontSize.js.map +1 -1
  24. package/dist/StatusHistoryChart/utils/get-color.js.map +1 -1
  25. package/dist/Table/Table.d.ts +1 -1
  26. package/dist/Table/Table.d.ts.map +1 -1
  27. package/dist/Table/Table.js +15 -4
  28. package/dist/Table/Table.js.map +1 -1
  29. package/dist/Table/TableCell.d.ts +2 -1
  30. package/dist/Table/TableCell.d.ts.map +1 -1
  31. package/dist/Table/TableCell.js +4 -2
  32. package/dist/Table/TableCell.js.map +1 -1
  33. package/dist/Table/TableFoot.d.ts +4 -0
  34. package/dist/Table/TableFoot.d.ts.map +1 -0
  35. package/dist/Table/TableFoot.js +23 -0
  36. package/dist/Table/TableFoot.js.map +1 -0
  37. package/dist/Table/TableHeaderCell.js.map +1 -1
  38. package/dist/Table/VirtualizedTable.d.ts +3 -2
  39. package/dist/Table/VirtualizedTable.d.ts.map +1 -1
  40. package/dist/Table/VirtualizedTable.js +33 -2
  41. package/dist/Table/VirtualizedTable.js.map +1 -1
  42. package/dist/Table/model/table-model.d.ts +18 -2
  43. package/dist/Table/model/table-model.d.ts.map +1 -1
  44. package/dist/Table/model/table-model.js +4 -2
  45. package/dist/Table/model/table-model.js.map +1 -1
  46. package/dist/ThresholdsEditor/ThresholdInput.js.map +1 -1
  47. package/dist/ThresholdsEditor/ThresholdsEditor.js +1 -1
  48. package/dist/ThresholdsEditor/ThresholdsEditor.js.map +1 -1
  49. package/dist/TimeChart/TimeChart.js +4 -4
  50. package/dist/TimeChart/TimeChart.js.map +1 -1
  51. package/dist/TimeRangeSelector/DateTimeRangePicker.js +1 -1
  52. package/dist/TimeRangeSelector/DateTimeRangePicker.js.map +1 -1
  53. package/dist/TimeRangeSelector/TimeRangeSelector.d.ts +1 -1
  54. package/dist/TimeRangeSelector/TimeRangeSelector.js.map +1 -1
  55. package/dist/TimeRangeSelector/utils.js.map +1 -1
  56. package/dist/TimeSeriesTooltip/LineChartTooltip.d.ts.map +1 -1
  57. package/dist/TimeSeriesTooltip/LineChartTooltip.js +2 -5
  58. package/dist/TimeSeriesTooltip/LineChartTooltip.js.map +1 -1
  59. package/dist/TimeSeriesTooltip/SeriesInfo.js.map +1 -1
  60. package/dist/TimeSeriesTooltip/SeriesLabelsStack.js.map +1 -1
  61. package/dist/TimeSeriesTooltip/TimeChartTooltip.d.ts.map +1 -1
  62. package/dist/TimeSeriesTooltip/TimeChartTooltip.js +2 -5
  63. package/dist/TimeSeriesTooltip/TimeChartTooltip.js.map +1 -1
  64. package/dist/TimeSeriesTooltip/tooltip-model.d.ts +1 -8
  65. package/dist/TimeSeriesTooltip/tooltip-model.d.ts.map +1 -1
  66. package/dist/TimeSeriesTooltip/tooltip-model.js +6 -16
  67. package/dist/TimeSeriesTooltip/tooltip-model.js.map +1 -1
  68. package/dist/TimeSeriesTooltip/utils.d.ts +1 -1
  69. package/dist/TimeSeriesTooltip/utils.d.ts.map +1 -1
  70. package/dist/TimeSeriesTooltip/utils.js +27 -23
  71. package/dist/TimeSeriesTooltip/utils.js.map +1 -1
  72. package/dist/TransformsEditor/TransformEditorContainer.js.map +1 -1
  73. package/dist/cjs/EChart/EChart.js +21 -3
  74. package/dist/cjs/JSONEditor.js +4 -5
  75. package/dist/cjs/StatChart/StatChart.js +6 -2
  76. package/dist/cjs/Table/Table.js +14 -3
  77. package/dist/cjs/Table/TableCell.js +4 -2
  78. package/dist/cjs/Table/TableFoot.js +31 -0
  79. package/dist/cjs/Table/VirtualizedTable.js +32 -1
  80. package/dist/cjs/Table/model/table-model.js +7 -2
  81. package/dist/cjs/ThresholdsEditor/ThresholdsEditor.js +9 -9
  82. package/dist/cjs/TimeChart/TimeChart.js +3 -3
  83. package/dist/cjs/TimeRangeSelector/DateTimeRangePicker.js +2 -2
  84. package/dist/cjs/TimeSeriesTooltip/LineChartTooltip.js +1 -4
  85. package/dist/cjs/TimeSeriesTooltip/TimeChartTooltip.js +1 -4
  86. package/dist/cjs/TimeSeriesTooltip/tooltip-model.js +6 -25
  87. package/dist/cjs/TimeSeriesTooltip/utils.js +26 -22
  88. package/dist/context/SnackbarProvider.js.map +1 -1
  89. package/dist/model/timeOption.js.map +1 -1
  90. package/dist/theme/component-overrides/alert.js.map +1 -1
  91. package/dist/utils/component-ids.js.map +1 -1
  92. package/package.json +5 -8
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/TimeRangeSelector/DateTimeRangePicker.tsx"],"sourcesContent":["// Copyright 2024 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { ReactElement, useState } from 'react';\nimport { Box, Stack, Typography, Button } from '@mui/material';\nimport { DateTimeField, LocalizationProvider, StaticDateTimePicker } from '@mui/x-date-pickers';\nimport { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';\nimport { AbsoluteTimeRange } from '@perses-dev/core';\nimport { useTimeZone } from '../context';\nimport { ErrorBoundary } from '../ErrorBoundary';\nimport { ErrorAlert } from '../ErrorAlert';\nimport { DATE_TIME_FORMAT, validateDateRange } from './utils';\n\ninterface AbsoluteTimeFormProps {\n initialTimeRange: AbsoluteTimeRange;\n onChange: (timeRange: AbsoluteTimeRange) => void;\n onCancel: () => void;\n}\n\ntype AbsoluteTimeRangeInputValue = {\n [Property in keyof AbsoluteTimeRange]: string;\n};\n\n/**\n * Start and End datetime picker, allowing use to select a specific time range selecting two absolute dates and times.\n * TODO: Use directly the MUI X ``DateTimePicker`` for datetime selection which is better. https://next.mui.com/x/react-date-pickers/date-time-picker/\n * Use ``DateTimeRangePicker`` directly would be cool but paid https://next.mui.com/x/react-date-pickers/date-time-range-picker/\n * @param initialTimeRange initial time range to pre-select.\n * @param onChange event received when start and end has been selected (click on apply)\n * @param onCancel event received when user click on cancel\n * @constructor\n */\nexport const DateTimeRangePicker = ({ initialTimeRange, onChange, onCancel }: AbsoluteTimeFormProps): ReactElement => {\n const { formatWithUserTimeZone } = useTimeZone();\n\n // Time range values as dates that can be used as a time range.\n const [timeRange, setTimeRange] = useState<AbsoluteTimeRange>(initialTimeRange);\n\n // Time range values as strings used to populate the text inputs. May not\n // be valid as dates when the user is typing.\n const [timeRangeInputs, setTimeRangeInputs] = useState<AbsoluteTimeRangeInputValue>({\n start: formatWithUserTimeZone(initialTimeRange.start, DATE_TIME_FORMAT),\n end: formatWithUserTimeZone(initialTimeRange.end, DATE_TIME_FORMAT),\n });\n\n const [showStartCalendar, setShowStartCalendar] = useState<boolean>(true);\n\n const changeTimeRange = (newTime: string | Date, segment: keyof AbsoluteTimeRange): void => {\n const isInputChange = typeof newTime === 'string';\n const newInputTime = isInputChange ? newTime : formatWithUserTimeZone(newTime, DATE_TIME_FORMAT);\n\n setTimeRangeInputs((prevTimeRangeInputs) => {\n return {\n ...prevTimeRangeInputs,\n [segment]: newInputTime,\n };\n });\n\n // When the change is a string from an input, do not try to convert it to\n // a date because there are likely to be interim stages of editing where it\n // is not valid as a date. When the change is a Date from the calendar/clock\n // interface, we can be sure it is a date.\n if (!isInputChange) {\n setTimeRange((prevTimeRange) => {\n return {\n ...prevTimeRange,\n [segment]: newTime,\n };\n });\n }\n };\n\n const onChangeStartTime = (newStartTime: string | Date): void => {\n changeTimeRange(newStartTime, 'start');\n };\n\n const onChangeEndTime = (newEndTime: string | Date): void => {\n changeTimeRange(newEndTime, 'end');\n };\n\n const updateDateRange = (): { start: Date; end: Date } | undefined => {\n const newDates = {\n start: new Date(timeRangeInputs.start),\n end: new Date(timeRangeInputs.end),\n };\n const isValidDateRange = validateDateRange(newDates.start, newDates.end);\n if (isValidDateRange) {\n setTimeRange(newDates);\n return newDates;\n }\n };\n\n const onApply = (): void => {\n const newDates = updateDateRange();\n if (newDates) {\n onChange(newDates);\n }\n };\n\n return (\n <LocalizationProvider dateAdapter={AdapterDateFns}>\n <Stack\n spacing={2}\n sx={(theme) => ({\n padding: theme.spacing(1, 0, 2),\n })}\n >\n {showStartCalendar && (\n <Box\n sx={(theme) => ({\n // TODO: create separate reusable calendar component\n '.MuiPickersLayout-contentWrapper': {\n backgroundColor: theme.palette.background.default,\n },\n })}\n >\n <Typography variant=\"h3\" padding={1} paddingLeft={2}>\n Select Start Time\n </Typography>\n <StaticDateTimePicker\n displayStaticWrapperAs=\"desktop\"\n openTo=\"day\"\n disableHighlightToday={true}\n value={initialTimeRange.start}\n onChange={(newValue) => {\n if (newValue === null) return;\n onChangeStartTime(newValue);\n }}\n onAccept={() => {\n setShowStartCalendar(false);\n }}\n />\n </Box>\n )}\n {!showStartCalendar && (\n <Box\n sx={(theme) => ({\n '.MuiPickersLayout-contentWrapper': {\n backgroundColor: theme.palette.background.default,\n },\n })}\n >\n <Typography variant=\"h3\" padding={1} paddingLeft={2}>\n Select End Time\n </Typography>\n <StaticDateTimePicker\n displayStaticWrapperAs=\"desktop\"\n openTo=\"day\"\n disableHighlightToday={true}\n value={initialTimeRange.end}\n minDateTime={timeRange.start}\n onChange={(newValue) => {\n if (newValue === null) return;\n onChangeEndTime(newValue);\n }}\n onAccept={(newValue) => {\n if (newValue === null) return;\n setShowStartCalendar(true);\n onChangeEndTime(newValue);\n }}\n />\n </Box>\n )}\n <Stack direction=\"row\" alignItems=\"center\" gap={1} pl={1} pr={1}>\n <ErrorBoundary FallbackComponent={ErrorAlert}>\n <DateTimeField\n label=\"Start Time\"\n value={new Date(timeRangeInputs.start)}\n onChange={(event: Date | null) => {\n if (event) {\n onChangeStartTime(event);\n }\n }}\n onBlur={() => updateDateRange()}\n format={DATE_TIME_FORMAT}\n />\n </ErrorBoundary>\n <ErrorBoundary FallbackComponent={ErrorAlert}>\n <DateTimeField\n label=\"End Time\"\n value={new Date(timeRangeInputs.end)}\n onChange={(event: Date | null) => {\n if (event) {\n onChangeEndTime(event);\n }\n }}\n onBlur={() => updateDateRange()}\n format={DATE_TIME_FORMAT}\n />\n </ErrorBoundary>\n </Stack>\n <Stack direction=\"row\" sx={{ padding: (theme) => theme.spacing(0, 1) }} gap={1}>\n <Button variant=\"contained\" onClick={() => onApply()} fullWidth>\n Apply\n </Button>\n <Button variant=\"outlined\" onClick={() => onCancel()} fullWidth>\n Cancel\n </Button>\n </Stack>\n </Stack>\n </LocalizationProvider>\n );\n};\n"],"names":["useState","Box","Stack","Typography","Button","DateTimeField","LocalizationProvider","StaticDateTimePicker","AdapterDateFns","useTimeZone","ErrorBoundary","ErrorAlert","DATE_TIME_FORMAT","validateDateRange","DateTimeRangePicker","initialTimeRange","onChange","onCancel","formatWithUserTimeZone","timeRange","setTimeRange","timeRangeInputs","setTimeRangeInputs","start","end","showStartCalendar","setShowStartCalendar","changeTimeRange","newTime","segment","isInputChange","newInputTime","prevTimeRangeInputs","prevTimeRange","onChangeStartTime","newStartTime","onChangeEndTime","newEndTime","updateDateRange","newDates","Date","isValidDateRange","onApply","dateAdapter","spacing","sx","theme","padding","backgroundColor","palette","background","default","variant","paddingLeft","displayStaticWrapperAs","openTo","disableHighlightToday","value","newValue","onAccept","minDateTime","direction","alignItems","gap","pl","pr","FallbackComponent","label","event","onBlur","format","onClick","fullWidth"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/TimeRangeSelector/DateTimeRangePicker.tsx"],"sourcesContent":["// Copyright 2024 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { ReactElement, useState } from 'react';\nimport { Box, Stack, Typography, Button } from '@mui/material';\nimport { DateTimeField, LocalizationProvider, StaticDateTimePicker } from '@mui/x-date-pickers';\nimport { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFnsV3';\nimport { AbsoluteTimeRange } from '@perses-dev/core';\nimport { useTimeZone } from '../context';\nimport { ErrorBoundary } from '../ErrorBoundary';\nimport { ErrorAlert } from '../ErrorAlert';\nimport { DATE_TIME_FORMAT, validateDateRange } from './utils';\n\ninterface AbsoluteTimeFormProps {\n initialTimeRange: AbsoluteTimeRange;\n onChange: (timeRange: AbsoluteTimeRange) => void;\n onCancel: () => void;\n}\n\ntype AbsoluteTimeRangeInputValue = {\n [Property in keyof AbsoluteTimeRange]: string;\n};\n\n/**\n * Start and End datetime picker, allowing use to select a specific time range selecting two absolute dates and times.\n * TODO: Use directly the MUI X ``DateTimePicker`` for datetime selection which is better. https://next.mui.com/x/react-date-pickers/date-time-picker/\n * Use ``DateTimeRangePicker`` directly would be cool but paid https://next.mui.com/x/react-date-pickers/date-time-range-picker/\n * @param initialTimeRange initial time range to pre-select.\n * @param onChange event received when start and end has been selected (click on apply)\n * @param onCancel event received when user click on cancel\n * @constructor\n */\nexport const DateTimeRangePicker = ({ initialTimeRange, onChange, onCancel }: AbsoluteTimeFormProps): ReactElement => {\n const { formatWithUserTimeZone } = useTimeZone();\n\n // Time range values as dates that can be used as a time range.\n const [timeRange, setTimeRange] = useState<AbsoluteTimeRange>(initialTimeRange);\n\n // Time range values as strings used to populate the text inputs. May not\n // be valid as dates when the user is typing.\n const [timeRangeInputs, setTimeRangeInputs] = useState<AbsoluteTimeRangeInputValue>({\n start: formatWithUserTimeZone(initialTimeRange.start, DATE_TIME_FORMAT),\n end: formatWithUserTimeZone(initialTimeRange.end, DATE_TIME_FORMAT),\n });\n\n const [showStartCalendar, setShowStartCalendar] = useState<boolean>(true);\n\n const changeTimeRange = (newTime: string | Date, segment: keyof AbsoluteTimeRange): void => {\n const isInputChange = typeof newTime === 'string';\n const newInputTime = isInputChange ? newTime : formatWithUserTimeZone(newTime, DATE_TIME_FORMAT);\n\n setTimeRangeInputs((prevTimeRangeInputs) => {\n return {\n ...prevTimeRangeInputs,\n [segment]: newInputTime,\n };\n });\n\n // When the change is a string from an input, do not try to convert it to\n // a date because there are likely to be interim stages of editing where it\n // is not valid as a date. When the change is a Date from the calendar/clock\n // interface, we can be sure it is a date.\n if (!isInputChange) {\n setTimeRange((prevTimeRange) => {\n return {\n ...prevTimeRange,\n [segment]: newTime,\n };\n });\n }\n };\n\n const onChangeStartTime = (newStartTime: string | Date): void => {\n changeTimeRange(newStartTime, 'start');\n };\n\n const onChangeEndTime = (newEndTime: string | Date): void => {\n changeTimeRange(newEndTime, 'end');\n };\n\n const updateDateRange = (): { start: Date; end: Date } | undefined => {\n const newDates = {\n start: new Date(timeRangeInputs.start),\n end: new Date(timeRangeInputs.end),\n };\n const isValidDateRange = validateDateRange(newDates.start, newDates.end);\n if (isValidDateRange) {\n setTimeRange(newDates);\n return newDates;\n }\n };\n\n const onApply = (): void => {\n const newDates = updateDateRange();\n if (newDates) {\n onChange(newDates);\n }\n };\n\n return (\n <LocalizationProvider dateAdapter={AdapterDateFns}>\n <Stack\n spacing={2}\n sx={(theme) => ({\n padding: theme.spacing(1, 0, 2),\n })}\n >\n {showStartCalendar && (\n <Box\n sx={(theme) => ({\n // TODO: create separate reusable calendar component\n '.MuiPickersLayout-contentWrapper': {\n backgroundColor: theme.palette.background.default,\n },\n })}\n >\n <Typography variant=\"h3\" padding={1} paddingLeft={2}>\n Select Start Time\n </Typography>\n <StaticDateTimePicker\n displayStaticWrapperAs=\"desktop\"\n openTo=\"day\"\n disableHighlightToday={true}\n value={initialTimeRange.start}\n onChange={(newValue) => {\n if (newValue === null) return;\n onChangeStartTime(newValue);\n }}\n onAccept={() => {\n setShowStartCalendar(false);\n }}\n />\n </Box>\n )}\n {!showStartCalendar && (\n <Box\n sx={(theme) => ({\n '.MuiPickersLayout-contentWrapper': {\n backgroundColor: theme.palette.background.default,\n },\n })}\n >\n <Typography variant=\"h3\" padding={1} paddingLeft={2}>\n Select End Time\n </Typography>\n <StaticDateTimePicker\n displayStaticWrapperAs=\"desktop\"\n openTo=\"day\"\n disableHighlightToday={true}\n value={initialTimeRange.end}\n minDateTime={timeRange.start}\n onChange={(newValue) => {\n if (newValue === null) return;\n onChangeEndTime(newValue);\n }}\n onAccept={(newValue) => {\n if (newValue === null) return;\n setShowStartCalendar(true);\n onChangeEndTime(newValue);\n }}\n />\n </Box>\n )}\n <Stack direction=\"row\" alignItems=\"center\" gap={1} pl={1} pr={1}>\n <ErrorBoundary FallbackComponent={ErrorAlert}>\n <DateTimeField\n label=\"Start Time\"\n value={new Date(timeRangeInputs.start)}\n onChange={(event: Date | null) => {\n if (event) {\n onChangeStartTime(event);\n }\n }}\n onBlur={() => updateDateRange()}\n format={DATE_TIME_FORMAT}\n />\n </ErrorBoundary>\n <ErrorBoundary FallbackComponent={ErrorAlert}>\n <DateTimeField\n label=\"End Time\"\n value={new Date(timeRangeInputs.end)}\n onChange={(event: Date | null) => {\n if (event) {\n onChangeEndTime(event);\n }\n }}\n onBlur={() => updateDateRange()}\n format={DATE_TIME_FORMAT}\n />\n </ErrorBoundary>\n </Stack>\n <Stack direction=\"row\" sx={{ padding: (theme) => theme.spacing(0, 1) }} gap={1}>\n <Button variant=\"contained\" onClick={() => onApply()} fullWidth>\n Apply\n </Button>\n <Button variant=\"outlined\" onClick={() => onCancel()} fullWidth>\n Cancel\n </Button>\n </Stack>\n </Stack>\n </LocalizationProvider>\n );\n};\n"],"names":["useState","Box","Stack","Typography","Button","DateTimeField","LocalizationProvider","StaticDateTimePicker","AdapterDateFns","useTimeZone","ErrorBoundary","ErrorAlert","DATE_TIME_FORMAT","validateDateRange","DateTimeRangePicker","initialTimeRange","onChange","onCancel","formatWithUserTimeZone","timeRange","setTimeRange","timeRangeInputs","setTimeRangeInputs","start","end","showStartCalendar","setShowStartCalendar","changeTimeRange","newTime","segment","isInputChange","newInputTime","prevTimeRangeInputs","prevTimeRange","onChangeStartTime","newStartTime","onChangeEndTime","newEndTime","updateDateRange","newDates","Date","isValidDateRange","onApply","dateAdapter","spacing","sx","theme","padding","backgroundColor","palette","background","default","variant","paddingLeft","displayStaticWrapperAs","openTo","disableHighlightToday","value","newValue","onAccept","minDateTime","direction","alignItems","gap","pl","pr","FallbackComponent","label","event","onBlur","format","onClick","fullWidth"],"mappings":"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"}
@@ -8,7 +8,7 @@ interface TimeRangeSelectorProps {
8
8
  value: TimeRangeValue;
9
9
  /**
10
10
  * The list of time options to display in the dropdown.
11
- * The component will automatically add the last option as a custom absolute time range.
11
+ * The component will automatically add the last two options as a zoom out x2 and a custom absolute time range.
12
12
  */
13
13
  timeOptions: TimeOption[];
14
14
  /**
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/TimeRangeSelector/TimeRangeSelector.tsx"],"sourcesContent":["// Copyright 2024 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { Box, MenuItem, Popover, Select } from '@mui/material';\nimport Calendar from 'mdi-material-ui/Calendar';\nimport { TimeRangeValue, isRelativeTimeRange, AbsoluteTimeRange, toAbsoluteTimeRange } from '@perses-dev/core';\nimport { ReactElement, useMemo, useRef, useState } from 'react';\nimport { useTimeZone } from '../context';\nimport { TimeOption } from '../model';\nimport { DateTimeRangePicker } from './DateTimeRangePicker';\nimport { buildCustomTimeOption, formatTimeRange } from './utils';\n\ninterface TimeRangeSelectorProps {\n /**\n * The current value of the time range.\n */\n value: TimeRangeValue;\n /**\n * The list of time options to display in the dropdown.\n * The component will automatically add the last option as a custom absolute time range.\n */\n timeOptions: TimeOption[];\n /**\n * The callback to call when the time range changes.\n */\n onChange: (value: TimeRangeValue) => void;\n /**\n * Custom line height for the select component.\n */\n height?: string;\n /**\n * Whether to show the custom time range option.\n * Defaults to true.\n */\n showCustomTimeRange?: boolean;\n}\n\n/**\n * Date & time selection component to customize what data renders on dashboard.\n * This includes relative shortcuts and the ability to pick absolute start and end times.\n * @param props\n * @constructor\n */\nexport function TimeRangeSelector({\n value,\n timeOptions,\n onChange,\n height,\n showCustomTimeRange = true,\n}: TimeRangeSelectorProps): ReactElement {\n const { timeZone } = useTimeZone();\n\n const anchorEl = useRef(); // Used to position the absolute time range picker\n\n // Control the open state of the absolute time range picker\n const [showCustomDateSelector, setShowCustomDateSelector] = useState(false);\n\n // Build the initial value of the absolute time range picker\n const convertedTimeRange = useMemo(() => {\n return isRelativeTimeRange(value) ? toAbsoluteTimeRange(value) : value;\n }, [value]);\n\n // Last option is the absolute time range option (custom)\n // If the value is an absolute time range, we display this time range\n // If the value is a relative time range, we make a default CustomTimeOption built from undefined value\n const lastOption = useMemo(\n () => buildCustomTimeOption(isRelativeTimeRange(value) ? undefined : value, timeZone),\n [value, timeZone]\n );\n\n // Control the open state of the select component to prevent the menu from closing when the custom date picker is\n // opened.\n //\n // Note that the value state of the select is here for display only. The real value (the one from props) is managed\n // by click events on each menu item.\n // This is a trick to get around the limitation of select with menu item that doesn't support objects as value...\n const [open, setOpen] = useState(false);\n\n return (\n <>\n <Popover\n anchorEl={anchorEl.current}\n anchorOrigin={{\n vertical: 'bottom',\n horizontal: 'center',\n }}\n open={showCustomDateSelector}\n onClose={() => setShowCustomDateSelector(false)}\n sx={(theme) => ({\n padding: theme.spacing(2),\n })}\n >\n <DateTimeRangePicker\n initialTimeRange={convertedTimeRange}\n onChange={(value: AbsoluteTimeRange) => {\n onChange(value);\n setShowCustomDateSelector(false);\n setOpen(false);\n }}\n onCancel={() => setShowCustomDateSelector(false)}\n />\n </Popover>\n <Box ref={anchorEl}>\n <Select\n open={open}\n value={formatTimeRange(value, timeZone)}\n onClick={() => setOpen(!open)}\n IconComponent={Calendar}\n inputProps={{\n 'aria-label': `Select time range. Currently set to ${value}`,\n }}\n sx={{\n // `transform: none` prevents calendar icon from flipping over when menu is open\n '.MuiSelect-icon': {\n marginTop: '1px',\n transform: 'none',\n },\n // paddingRight creates more space for the calendar icon (it's a bigger icon)\n '.MuiSelect-select.MuiSelect-outlined.MuiInputBase-input': {\n paddingRight: '36px',\n },\n '.MuiSelect-select': height ? { lineHeight: height, paddingY: 0 } : {},\n }}\n >\n {timeOptions.map((item, idx) => (\n <MenuItem\n key={idx}\n value={formatTimeRange(item.value, timeZone)}\n onClick={() => {\n onChange(item.value);\n }}\n >\n {item.display}\n </MenuItem>\n ))}\n {showCustomTimeRange && (\n <MenuItem\n value={formatTimeRange(lastOption.value, timeZone)}\n onClick={() => setShowCustomDateSelector(true)}\n >\n {lastOption.display}\n </MenuItem>\n )}\n </Select>\n </Box>\n </>\n );\n}\n"],"names":["Box","MenuItem","Popover","Select","Calendar","isRelativeTimeRange","toAbsoluteTimeRange","useMemo","useRef","useState","useTimeZone","DateTimeRangePicker","buildCustomTimeOption","formatTimeRange","TimeRangeSelector","value","timeOptions","onChange","height","showCustomTimeRange","timeZone","anchorEl","showCustomDateSelector","setShowCustomDateSelector","convertedTimeRange","lastOption","undefined","open","setOpen","current","anchorOrigin","vertical","horizontal","onClose","sx","theme","padding","spacing","initialTimeRange","onCancel","ref","onClick","IconComponent","inputProps","marginTop","transform","paddingRight","lineHeight","paddingY","map","item","idx","display"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;;AAEjC,SAASA,GAAG,EAAEC,QAAQ,EAAEC,OAAO,EAAEC,MAAM,QAAQ,gBAAgB;AAC/D,OAAOC,cAAc,2BAA2B;AAChD,SAAyBC,mBAAmB,EAAqBC,mBAAmB,QAAQ,mBAAmB;AAC/G,SAAuBC,OAAO,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,QAAQ;AAChE,SAASC,WAAW,QAAQ,aAAa;AAEzC,SAASC,mBAAmB,QAAQ,wBAAwB;AAC5D,SAASC,qBAAqB,EAAEC,eAAe,QAAQ,UAAU;AA2BjE;;;;;CAKC,GACD,OAAO,SAASC,kBAAkB,EAChCC,KAAK,EACLC,WAAW,EACXC,QAAQ,EACRC,MAAM,EACNC,sBAAsB,IAAI,EACH;IACvB,MAAM,EAAEC,QAAQ,EAAE,GAAGV;IAErB,MAAMW,WAAWb,UAAU,kDAAkD;IAE7E,2DAA2D;IAC3D,MAAM,CAACc,wBAAwBC,0BAA0B,GAAGd,SAAS;IAErE,4DAA4D;IAC5D,MAAMe,qBAAqBjB,QAAQ;QACjC,OAAOF,oBAAoBU,SAAST,oBAAoBS,SAASA;IACnE,GAAG;QAACA;KAAM;IAEV,yDAAyD;IACzD,qEAAqE;IACrE,uGAAuG;IACvG,MAAMU,aAAalB,QACjB,IAAMK,sBAAsBP,oBAAoBU,SAASW,YAAYX,OAAOK,WAC5E;QAACL;QAAOK;KAAS;IAGnB,iHAAiH;IACjH,UAAU;IACV,EAAE;IACF,mHAAmH;IACnH,qCAAqC;IACrC,iHAAiH;IACjH,MAAM,CAACO,MAAMC,QAAQ,GAAGnB,SAAS;IAEjC,qBACE;;0BACE,KAACP;gBACCmB,UAAUA,SAASQ,OAAO;gBAC1BC,cAAc;oBACZC,UAAU;oBACVC,YAAY;gBACd;gBACAL,MAAML;gBACNW,SAAS,IAAMV,0BAA0B;gBACzCW,IAAI,CAACC,QAAW,CAAA;wBACdC,SAASD,MAAME,OAAO,CAAC;oBACzB,CAAA;0BAEA,cAAA,KAAC1B;oBACC2B,kBAAkBd;oBAClBP,UAAU,CAACF;wBACTE,SAASF;wBACTQ,0BAA0B;wBAC1BK,QAAQ;oBACV;oBACAW,UAAU,IAAMhB,0BAA0B;;;0BAG9C,KAACvB;gBAAIwC,KAAKnB;0BACR,cAAA,MAAClB;oBACCwB,MAAMA;oBACNZ,OAAOF,gBAAgBE,OAAOK;oBAC9BqB,SAAS,IAAMb,QAAQ,CAACD;oBACxBe,eAAetC;oBACfuC,YAAY;wBACV,cAAc,CAAC,oCAAoC,EAAE5B,MAAM,CAAC;oBAC9D;oBACAmB,IAAI;wBACF,gFAAgF;wBAChF,mBAAmB;4BACjBU,WAAW;4BACXC,WAAW;wBACb;wBACA,6EAA6E;wBAC7E,2DAA2D;4BACzDC,cAAc;wBAChB;wBACA,qBAAqB5B,SAAS;4BAAE6B,YAAY7B;4BAAQ8B,UAAU;wBAAE,IAAI,CAAC;oBACvE;;wBAEChC,YAAYiC,GAAG,CAAC,CAACC,MAAMC,oBACtB,KAAClD;gCAECc,OAAOF,gBAAgBqC,KAAKnC,KAAK,EAAEK;gCACnCqB,SAAS;oCACPxB,SAASiC,KAAKnC,KAAK;gCACrB;0CAECmC,KAAKE,OAAO;+BANRD;wBASRhC,qCACC,KAAClB;4BACCc,OAAOF,gBAAgBY,WAAWV,KAAK,EAAEK;4BACzCqB,SAAS,IAAMlB,0BAA0B;sCAExCE,WAAW2B,OAAO;;;;;;;AAOjC"}
1
+ {"version":3,"sources":["../../src/TimeRangeSelector/TimeRangeSelector.tsx"],"sourcesContent":["// Copyright 2024 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { Box, MenuItem, Popover, Select } from '@mui/material';\nimport Calendar from 'mdi-material-ui/Calendar';\nimport { TimeRangeValue, isRelativeTimeRange, AbsoluteTimeRange, toAbsoluteTimeRange } from '@perses-dev/core';\nimport { ReactElement, useMemo, useRef, useState } from 'react';\nimport { useTimeZone } from '../context';\nimport { TimeOption } from '../model';\nimport { DateTimeRangePicker } from './DateTimeRangePicker';\nimport { buildCustomTimeOption, formatTimeRange } from './utils';\n\ninterface TimeRangeSelectorProps {\n /**\n * The current value of the time range.\n */\n value: TimeRangeValue;\n /**\n * The list of time options to display in the dropdown.\n * The component will automatically add the last two options as a zoom out x2 and a custom absolute time range.\n */\n timeOptions: TimeOption[];\n /**\n * The callback to call when the time range changes.\n */\n onChange: (value: TimeRangeValue) => void;\n /**\n * Custom line height for the select component.\n */\n height?: string;\n /**\n * Whether to show the custom time range option.\n * Defaults to true.\n */\n showCustomTimeRange?: boolean;\n}\n\n/**\n * Date & time selection component to customize what data renders on dashboard.\n * This includes relative shortcuts and the ability to pick absolute start and end times.\n * @param props\n * @constructor\n */\nexport function TimeRangeSelector({\n value,\n timeOptions,\n onChange,\n height,\n showCustomTimeRange = true,\n}: TimeRangeSelectorProps): ReactElement {\n const { timeZone } = useTimeZone();\n\n const anchorEl = useRef(); // Used to position the absolute time range picker\n\n // Control the open state of the absolute time range picker\n const [showCustomDateSelector, setShowCustomDateSelector] = useState(false);\n\n // Build the initial value of the absolute time range picker\n const convertedTimeRange = useMemo(() => {\n return isRelativeTimeRange(value) ? toAbsoluteTimeRange(value) : value;\n }, [value]);\n\n // Last option is the absolute time range option (custom)\n // If the value is an absolute time range, we display this time range\n // If the value is a relative time range, we make a default CustomTimeOption built from undefined value\n const lastOption = useMemo(\n () => buildCustomTimeOption(isRelativeTimeRange(value) ? undefined : value, timeZone),\n [value, timeZone]\n );\n\n // Control the open state of the select component to prevent the menu from closing when the custom date picker is\n // opened.\n //\n // Note that the value state of the select is here for display only. The real value (the one from props) is managed\n // by click events on each menu item.\n // This is a trick to get around the limitation of select with menu item that doesn't support objects as value...\n const [open, setOpen] = useState(false);\n\n return (\n <>\n <Popover\n anchorEl={anchorEl.current}\n anchorOrigin={{\n vertical: 'bottom',\n horizontal: 'center',\n }}\n open={showCustomDateSelector}\n onClose={() => setShowCustomDateSelector(false)}\n sx={(theme) => ({\n padding: theme.spacing(2),\n })}\n >\n <DateTimeRangePicker\n initialTimeRange={convertedTimeRange}\n onChange={(value: AbsoluteTimeRange) => {\n onChange(value);\n setShowCustomDateSelector(false);\n setOpen(false);\n }}\n onCancel={() => setShowCustomDateSelector(false)}\n />\n </Popover>\n <Box ref={anchorEl}>\n <Select\n open={open}\n value={formatTimeRange(value, timeZone)}\n onClick={() => setOpen(!open)}\n IconComponent={Calendar}\n inputProps={{\n 'aria-label': `Select time range. Currently set to ${value}`,\n }}\n sx={{\n // `transform: none` prevents calendar icon from flipping over when menu is open\n '.MuiSelect-icon': {\n marginTop: '1px',\n transform: 'none',\n },\n // paddingRight creates more space for the calendar icon (it's a bigger icon)\n '.MuiSelect-select.MuiSelect-outlined.MuiInputBase-input': {\n paddingRight: '36px',\n },\n '.MuiSelect-select': height ? { lineHeight: height, paddingY: 0 } : {},\n }}\n >\n {timeOptions.map((item, idx) => (\n <MenuItem\n key={idx}\n value={formatTimeRange(item.value, timeZone)}\n onClick={() => {\n onChange(item.value);\n }}\n >\n {item.display}\n </MenuItem>\n ))}\n {showCustomTimeRange && (\n <MenuItem\n value={formatTimeRange(lastOption.value, timeZone)}\n onClick={() => setShowCustomDateSelector(true)}\n >\n {lastOption.display}\n </MenuItem>\n )}\n </Select>\n </Box>\n </>\n );\n}\n"],"names":["Box","MenuItem","Popover","Select","Calendar","isRelativeTimeRange","toAbsoluteTimeRange","useMemo","useRef","useState","useTimeZone","DateTimeRangePicker","buildCustomTimeOption","formatTimeRange","TimeRangeSelector","value","timeOptions","onChange","height","showCustomTimeRange","timeZone","anchorEl","showCustomDateSelector","setShowCustomDateSelector","convertedTimeRange","lastOption","undefined","open","setOpen","current","anchorOrigin","vertical","horizontal","onClose","sx","theme","padding","spacing","initialTimeRange","onCancel","ref","onClick","IconComponent","inputProps","marginTop","transform","paddingRight","lineHeight","paddingY","map","item","idx","display"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;;AAEjC,SAASA,GAAG,EAAEC,QAAQ,EAAEC,OAAO,EAAEC,MAAM,QAAQ,gBAAgB;AAC/D,OAAOC,cAAc,2BAA2B;AAChD,SAAyBC,mBAAmB,EAAqBC,mBAAmB,QAAQ,mBAAmB;AAC/G,SAAuBC,OAAO,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,QAAQ;AAChE,SAASC,WAAW,QAAQ,aAAa;AAEzC,SAASC,mBAAmB,QAAQ,wBAAwB;AAC5D,SAASC,qBAAqB,EAAEC,eAAe,QAAQ,UAAU;AA2BjE;;;;;CAKC,GACD,OAAO,SAASC,kBAAkB,EAChCC,KAAK,EACLC,WAAW,EACXC,QAAQ,EACRC,MAAM,EACNC,sBAAsB,IAAI,EACH;IACvB,MAAM,EAAEC,QAAQ,EAAE,GAAGV;IAErB,MAAMW,WAAWb,UAAU,kDAAkD;IAE7E,2DAA2D;IAC3D,MAAM,CAACc,wBAAwBC,0BAA0B,GAAGd,SAAS;IAErE,4DAA4D;IAC5D,MAAMe,qBAAqBjB,QAAQ;QACjC,OAAOF,oBAAoBU,SAAST,oBAAoBS,SAASA;IACnE,GAAG;QAACA;KAAM;IAEV,yDAAyD;IACzD,qEAAqE;IACrE,uGAAuG;IACvG,MAAMU,aAAalB,QACjB,IAAMK,sBAAsBP,oBAAoBU,SAASW,YAAYX,OAAOK,WAC5E;QAACL;QAAOK;KAAS;IAGnB,iHAAiH;IACjH,UAAU;IACV,EAAE;IACF,mHAAmH;IACnH,qCAAqC;IACrC,iHAAiH;IACjH,MAAM,CAACO,MAAMC,QAAQ,GAAGnB,SAAS;IAEjC,qBACE;;0BACE,KAACP;gBACCmB,UAAUA,SAASQ,OAAO;gBAC1BC,cAAc;oBACZC,UAAU;oBACVC,YAAY;gBACd;gBACAL,MAAML;gBACNW,SAAS,IAAMV,0BAA0B;gBACzCW,IAAI,CAACC,QAAW,CAAA;wBACdC,SAASD,MAAME,OAAO,CAAC;oBACzB,CAAA;0BAEA,cAAA,KAAC1B;oBACC2B,kBAAkBd;oBAClBP,UAAU,CAACF;wBACTE,SAASF;wBACTQ,0BAA0B;wBAC1BK,QAAQ;oBACV;oBACAW,UAAU,IAAMhB,0BAA0B;;;0BAG9C,KAACvB;gBAAIwC,KAAKnB;0BACR,cAAA,MAAClB;oBACCwB,MAAMA;oBACNZ,OAAOF,gBAAgBE,OAAOK;oBAC9BqB,SAAS,IAAMb,QAAQ,CAACD;oBACxBe,eAAetC;oBACfuC,YAAY;wBACV,cAAc,CAAC,oCAAoC,EAAE5B,OAAO;oBAC9D;oBACAmB,IAAI;wBACF,gFAAgF;wBAChF,mBAAmB;4BACjBU,WAAW;4BACXC,WAAW;wBACb;wBACA,6EAA6E;wBAC7E,2DAA2D;4BACzDC,cAAc;wBAChB;wBACA,qBAAqB5B,SAAS;4BAAE6B,YAAY7B;4BAAQ8B,UAAU;wBAAE,IAAI,CAAC;oBACvE;;wBAEChC,YAAYiC,GAAG,CAAC,CAACC,MAAMC,oBACtB,KAAClD;gCAECc,OAAOF,gBAAgBqC,KAAKnC,KAAK,EAAEK;gCACnCqB,SAAS;oCACPxB,SAASiC,KAAKnC,KAAK;gCACrB;0CAECmC,KAAKE,OAAO;+BANRD;wBASRhC,qCACC,KAAClB;4BACCc,OAAOF,gBAAgBY,WAAWV,KAAK,EAAEK;4BACzCqB,SAAS,IAAMlB,0BAA0B;sCAExCE,WAAW2B,OAAO;;;;;;;AAOjC"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/TimeRangeSelector/utils.ts"],"sourcesContent":["// Copyright 2024 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { isBefore, isValid } from 'date-fns';\nimport { AbsoluteTimeRange, isRelativeTimeRange, TimeRangeValue } from '@perses-dev/core';\nimport { formatWithTimeZone } from '../utils';\n\nexport const DATE_TIME_FORMAT = 'yyyy-MM-dd HH:mm:ss';\n\nexport interface CustomTimeOption {\n value: TimeRangeValue | undefined;\n display: string;\n}\n\nexport function buildCustomTimeOption(value: AbsoluteTimeRange | undefined, timeZone: string): CustomTimeOption {\n return { value, display: formatTimeRange(value, timeZone) };\n}\n\n/**\n * Date validation and check if end is after start\n */\nexport function validateDateRange(startDate: Date, endDate: Date): boolean {\n // TODO: display error as helperText\n if (!isValid(startDate) || !isValid(endDate)) {\n console.error('Invalid Date');\n return false;\n }\n if (!isBefore(startDate, endDate)) {\n console.error('End Time is before Start Time');\n return false;\n }\n return true;\n}\n\n/**\n * Format start and end time based on provided date format\n * @param timeRange absolute time range with a start and end datetime\n * @param dateFormat date format string\n * @param timeZone\n */\nexport function formatAbsoluteRange(timeRange: AbsoluteTimeRange, dateFormat: string, timeZone?: string): string {\n const formattedStart = formatWithTimeZone(timeRange.start, dateFormat, timeZone);\n const formattedEnd = formatWithTimeZone(timeRange.end, dateFormat, timeZone);\n return `${formattedStart} - ${formattedEnd}`;\n}\n\n/**\n * Format the time range for display purpose only (e.g. in the selector)\n * @param value\n * @param timeZone\n */\nexport function formatTimeRange(value: TimeRangeValue | undefined, timeZone: string): string {\n if (!value) {\n return 'Custom Time Range';\n }\n return !isRelativeTimeRange(value) ? formatAbsoluteRange(value, DATE_TIME_FORMAT, timeZone) : value.pastDuration;\n}\n"],"names":["isBefore","isValid","isRelativeTimeRange","formatWithTimeZone","DATE_TIME_FORMAT","buildCustomTimeOption","value","timeZone","display","formatTimeRange","validateDateRange","startDate","endDate","console","error","formatAbsoluteRange","timeRange","dateFormat","formattedStart","start","formattedEnd","end","pastDuration"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC,SAASA,QAAQ,EAAEC,OAAO,QAAQ,WAAW;AAC7C,SAA4BC,mBAAmB,QAAwB,mBAAmB;AAC1F,SAASC,kBAAkB,QAAQ,WAAW;AAE9C,OAAO,MAAMC,mBAAmB,sBAAsB;AAOtD,OAAO,SAASC,sBAAsBC,KAAoC,EAAEC,QAAgB;IAC1F,OAAO;QAAED;QAAOE,SAASC,gBAAgBH,OAAOC;IAAU;AAC5D;AAEA;;CAEC,GACD,OAAO,SAASG,kBAAkBC,SAAe,EAAEC,OAAa;IAC9D,oCAAoC;IACpC,IAAI,CAACX,QAAQU,cAAc,CAACV,QAAQW,UAAU;QAC5CC,QAAQC,KAAK,CAAC;QACd,OAAO;IACT;IACA,IAAI,CAACd,SAASW,WAAWC,UAAU;QACjCC,QAAQC,KAAK,CAAC;QACd,OAAO;IACT;IACA,OAAO;AACT;AAEA;;;;;CAKC,GACD,OAAO,SAASC,oBAAoBC,SAA4B,EAAEC,UAAkB,EAAEV,QAAiB;IACrG,MAAMW,iBAAiBf,mBAAmBa,UAAUG,KAAK,EAAEF,YAAYV;IACvE,MAAMa,eAAejB,mBAAmBa,UAAUK,GAAG,EAAEJ,YAAYV;IACnE,OAAO,CAAC,EAAEW,eAAe,GAAG,EAAEE,aAAa,CAAC;AAC9C;AAEA;;;;CAIC,GACD,OAAO,SAASX,gBAAgBH,KAAiC,EAAEC,QAAgB;IACjF,IAAI,CAACD,OAAO;QACV,OAAO;IACT;IACA,OAAO,CAACJ,oBAAoBI,SAASS,oBAAoBT,OAAOF,kBAAkBG,YAAYD,MAAMgB,YAAY;AAClH"}
1
+ {"version":3,"sources":["../../src/TimeRangeSelector/utils.ts"],"sourcesContent":["// Copyright 2024 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { isBefore, isValid } from 'date-fns';\nimport { AbsoluteTimeRange, isRelativeTimeRange, TimeRangeValue } from '@perses-dev/core';\nimport { formatWithTimeZone } from '../utils';\n\nexport const DATE_TIME_FORMAT = 'yyyy-MM-dd HH:mm:ss';\n\nexport interface CustomTimeOption {\n value: TimeRangeValue | undefined;\n display: string;\n}\n\nexport function buildCustomTimeOption(value: AbsoluteTimeRange | undefined, timeZone: string): CustomTimeOption {\n return { value, display: formatTimeRange(value, timeZone) };\n}\n\n/**\n * Date validation and check if end is after start\n */\nexport function validateDateRange(startDate: Date, endDate: Date): boolean {\n // TODO: display error as helperText\n if (!isValid(startDate) || !isValid(endDate)) {\n console.error('Invalid Date');\n return false;\n }\n if (!isBefore(startDate, endDate)) {\n console.error('End Time is before Start Time');\n return false;\n }\n return true;\n}\n\n/**\n * Format start and end time based on provided date format\n * @param timeRange absolute time range with a start and end datetime\n * @param dateFormat date format string\n * @param timeZone\n */\nexport function formatAbsoluteRange(timeRange: AbsoluteTimeRange, dateFormat: string, timeZone?: string): string {\n const formattedStart = formatWithTimeZone(timeRange.start, dateFormat, timeZone);\n const formattedEnd = formatWithTimeZone(timeRange.end, dateFormat, timeZone);\n return `${formattedStart} - ${formattedEnd}`;\n}\n\n/**\n * Format the time range for display purpose only (e.g. in the selector)\n * @param value\n * @param timeZone\n */\nexport function formatTimeRange(value: TimeRangeValue | undefined, timeZone: string): string {\n if (!value) {\n return 'Custom Time Range';\n }\n return !isRelativeTimeRange(value) ? formatAbsoluteRange(value, DATE_TIME_FORMAT, timeZone) : value.pastDuration;\n}\n"],"names":["isBefore","isValid","isRelativeTimeRange","formatWithTimeZone","DATE_TIME_FORMAT","buildCustomTimeOption","value","timeZone","display","formatTimeRange","validateDateRange","startDate","endDate","console","error","formatAbsoluteRange","timeRange","dateFormat","formattedStart","start","formattedEnd","end","pastDuration"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC,SAASA,QAAQ,EAAEC,OAAO,QAAQ,WAAW;AAC7C,SAA4BC,mBAAmB,QAAwB,mBAAmB;AAC1F,SAASC,kBAAkB,QAAQ,WAAW;AAE9C,OAAO,MAAMC,mBAAmB,sBAAsB;AAOtD,OAAO,SAASC,sBAAsBC,KAAoC,EAAEC,QAAgB;IAC1F,OAAO;QAAED;QAAOE,SAASC,gBAAgBH,OAAOC;IAAU;AAC5D;AAEA;;CAEC,GACD,OAAO,SAASG,kBAAkBC,SAAe,EAAEC,OAAa;IAC9D,oCAAoC;IACpC,IAAI,CAACX,QAAQU,cAAc,CAACV,QAAQW,UAAU;QAC5CC,QAAQC,KAAK,CAAC;QACd,OAAO;IACT;IACA,IAAI,CAACd,SAASW,WAAWC,UAAU;QACjCC,QAAQC,KAAK,CAAC;QACd,OAAO;IACT;IACA,OAAO;AACT;AAEA;;;;;CAKC,GACD,OAAO,SAASC,oBAAoBC,SAA4B,EAAEC,UAAkB,EAAEV,QAAiB;IACrG,MAAMW,iBAAiBf,mBAAmBa,UAAUG,KAAK,EAAEF,YAAYV;IACvE,MAAMa,eAAejB,mBAAmBa,UAAUK,GAAG,EAAEJ,YAAYV;IACnE,OAAO,GAAGW,eAAe,GAAG,EAAEE,cAAc;AAC9C;AAEA;;;;CAIC,GACD,OAAO,SAASX,gBAAgBH,KAAiC,EAAEC,QAAgB;IACjF,IAAI,CAACD,OAAO;QACV,OAAO;IACT;IACA,OAAO,CAACJ,oBAAoBI,SAASS,oBAAoBT,OAAOF,kBAAkBG,YAAYD,MAAMgB,YAAY;AAClH"}
@@ -1 +1 @@
1
- {"version":3,"file":"LineChartTooltip.d.ts","sourceRoot":"","sources":["../../src/TimeSeriesTooltip/LineChartTooltip.tsx"],"names":[],"mappings":"AAcA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAQ,gBAAgB,EAAkC,MAAM,OAAO,CAAC;AAE/E,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAI7C,OAAO,EACL,iBAAiB,EAOlB,MAAM,iBAAiB,CAAC;AAGzB,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,gBAAgB,CAAC,eAAe,GAAG,SAAS,CAAC,CAAC;IACxD,SAAS,EAAE,iBAAiB,CAAC;IAC7B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,SAAS,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACpC;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,gBAAgB,8DA6F3B,CAAC"}
1
+ {"version":3,"file":"LineChartTooltip.d.ts","sourceRoot":"","sources":["../../src/TimeSeriesTooltip/LineChartTooltip.tsx"],"names":[],"mappings":"AAcA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAQ,gBAAgB,EAAkC,MAAM,OAAO,CAAC;AAE/E,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAI7C,OAAO,EACL,iBAAiB,EAMlB,MAAM,iBAAiB,CAAC;AAGzB,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,gBAAgB,CAAC,eAAe,GAAG,SAAS,CAAC,CAAC;IACxD,SAAS,EAAE,iBAAiB,CAAC;IAC7B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,SAAS,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACpC;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,gBAAgB,8DA2F3B,CAAC"}
@@ -17,7 +17,7 @@ import useResizeObserver from 'use-resize-observer';
17
17
  import { TooltipContent } from './TooltipContent';
18
18
  import { TooltipHeader } from './TooltipHeader';
19
19
  import { legacyGetNearbySeriesData } from './nearby-series';
20
- import { FALLBACK_CHART_WIDTH, TOOLTIP_BG_COLOR_FALLBACK, TOOLTIP_MAX_HEIGHT, TOOLTIP_MAX_WIDTH, TOOLTIP_MIN_WIDTH, useMousePosition } from './tooltip-model';
20
+ import { TOOLTIP_BG_COLOR_FALLBACK, TOOLTIP_MAX_HEIGHT, TOOLTIP_MAX_WIDTH, TOOLTIP_MIN_WIDTH, useMousePosition } from './tooltip-model';
21
21
  import { assembleTransform } from './utils';
22
22
  export const LineChartTooltip = /*#__PURE__*/ memo(function LineChartTooltip({ chartRef, chartData, enablePinning = true, wrapLabels, format, onUnpinClick, pinnedPos, containerId }) {
23
23
  const [showAllSeries, setShowAllSeries] = useState(false);
@@ -29,7 +29,6 @@ export const LineChartTooltip = /*#__PURE__*/ memo(function LineChartTooltip({ c
29
29
  // Ensure user is hovering over a chart before checking for nearby series.
30
30
  if (pinnedPos === null && mousePos.target.tagName !== 'CANVAS') return null;
31
31
  const chart = chartRef.current;
32
- const chartWidth = chart?.getWidth() ?? FALLBACK_CHART_WIDTH; // Fallback width not likely to ever be needed.
33
32
  // Get series nearby the cursor and pass into tooltip content children.
34
33
  const nearbySeries = legacyGetNearbySeriesData({
35
34
  mousePos,
@@ -46,9 +45,7 @@ export const LineChartTooltip = /*#__PURE__*/ memo(function LineChartTooltip({ c
46
45
  const containerElement = containerId ? document.querySelector(containerId) : undefined;
47
46
  // if tooltip is attached to a container, set max height to the height of the container so tooltip does not get cut off
48
47
  const maxHeight = containerElement ? containerElement.getBoundingClientRect().height : undefined;
49
- if (!isTooltipPinned) {
50
- transform.current = assembleTransform(mousePos, chartWidth, pinnedPos, height ?? 0, width ?? 0, containerElement);
51
- }
48
+ transform.current = assembleTransform(mousePos, pinnedPos, height ?? 0, width ?? 0, containerElement);
52
49
  return /*#__PURE__*/ _jsx(Portal, {
53
50
  container: containerElement,
54
51
  children: /*#__PURE__*/ _jsx(Box, {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/TimeSeriesTooltip/LineChartTooltip.tsx"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { Box, Portal, Stack } from '@mui/material';\nimport { FormatOptions } from '@perses-dev/core';\nimport { ECharts as EChartsInstance } from 'echarts/core';\nimport { memo, MutableRefObject, ReactElement, useRef, useState } from 'react';\nimport useResizeObserver from 'use-resize-observer';\nimport { EChartsDataFormat } from '../model';\nimport { TooltipContent } from './TooltipContent';\nimport { TooltipHeader } from './TooltipHeader';\nimport { legacyGetNearbySeriesData } from './nearby-series';\nimport {\n CursorCoordinates,\n FALLBACK_CHART_WIDTH,\n TOOLTIP_BG_COLOR_FALLBACK,\n TOOLTIP_MAX_HEIGHT,\n TOOLTIP_MAX_WIDTH,\n TOOLTIP_MIN_WIDTH,\n useMousePosition,\n} from './tooltip-model';\nimport { assembleTransform } from './utils';\n\nexport interface TimeSeriesTooltipProps {\n chartRef: MutableRefObject<EChartsInstance | undefined>;\n chartData: EChartsDataFormat;\n enablePinning?: boolean;\n wrapLabels?: boolean;\n format?: FormatOptions;\n onUnpinClick?: () => void;\n pinnedPos: CursorCoordinates | null;\n /**\n * The id of the container that will have the chart tooltip appended to it.\n * By default, the chart tooltip is attached to document.body.\n */\n containerId?: string;\n}\n\nexport const LineChartTooltip = memo(function LineChartTooltip({\n chartRef,\n chartData,\n enablePinning = true,\n wrapLabels,\n format,\n onUnpinClick,\n pinnedPos,\n containerId,\n}: TimeSeriesTooltipProps): ReactElement | null {\n const [showAllSeries, setShowAllSeries] = useState(false);\n const mousePos = useMousePosition();\n const { height, width, ref: tooltipRef } = useResizeObserver();\n const transform = useRef<string | undefined>();\n\n const isTooltipPinned = pinnedPos !== null && enablePinning;\n\n if (mousePos === null || mousePos.target === null) return null;\n\n // Ensure user is hovering over a chart before checking for nearby series.\n if (pinnedPos === null && (mousePos.target as HTMLElement).tagName !== 'CANVAS') return null;\n\n const chart = chartRef.current;\n const chartWidth = chart?.getWidth() ?? FALLBACK_CHART_WIDTH; // Fallback width not likely to ever be needed.\n\n // Get series nearby the cursor and pass into tooltip content children.\n const nearbySeries = legacyGetNearbySeriesData({\n mousePos,\n chartData,\n pinnedPos,\n chart,\n format,\n showAllSeries,\n });\n if (nearbySeries.length === 0) {\n return null;\n }\n\n const totalSeries = chartData.timeSeries.length;\n\n const containerElement = containerId ? document.querySelector(containerId) : undefined;\n // if tooltip is attached to a container, set max height to the height of the container so tooltip does not get cut off\n const maxHeight = containerElement ? containerElement.getBoundingClientRect().height : undefined;\n if (!isTooltipPinned) {\n transform.current = assembleTransform(mousePos, chartWidth, pinnedPos, height ?? 0, width ?? 0, containerElement);\n }\n\n return (\n <Portal container={containerElement}>\n <Box\n ref={tooltipRef}\n sx={(theme) => ({\n minWidth: TOOLTIP_MIN_WIDTH,\n maxWidth: TOOLTIP_MAX_WIDTH,\n maxHeight: maxHeight ?? TOOLTIP_MAX_HEIGHT,\n padding: 0,\n position: 'absolute',\n top: 0,\n left: 0,\n backgroundColor: theme.palette.designSystem?.grey[800] ?? TOOLTIP_BG_COLOR_FALLBACK,\n borderRadius: '6px',\n color: '#fff',\n fontSize: '11px',\n visibility: 'visible',\n opacity: 1,\n transition: 'all 0.1s ease-out',\n // Ensure pinned tooltip shows behind edit panel drawer and sticky header\n zIndex: pinnedPos !== null ? 'auto' : theme.zIndex.tooltip,\n overflow: 'hidden',\n '&:hover': {\n overflowY: 'auto',\n },\n })}\n style={{\n transform: transform.current,\n display: transform.current ? 'block' : 'none',\n }}\n >\n <Stack spacing={0.5}>\n <TooltipHeader\n nearbySeries={nearbySeries}\n totalSeries={totalSeries}\n enablePinning={enablePinning}\n isTooltipPinned={isTooltipPinned}\n showAllSeries={showAllSeries}\n onShowAllClick={(checked) => setShowAllSeries(checked)}\n onUnpinClick={onUnpinClick}\n />\n <TooltipContent series={nearbySeries} wrapLabels={wrapLabels} />\n </Stack>\n </Box>\n </Portal>\n );\n});\n"],"names":["Box","Portal","Stack","memo","useRef","useState","useResizeObserver","TooltipContent","TooltipHeader","legacyGetNearbySeriesData","FALLBACK_CHART_WIDTH","TOOLTIP_BG_COLOR_FALLBACK","TOOLTIP_MAX_HEIGHT","TOOLTIP_MAX_WIDTH","TOOLTIP_MIN_WIDTH","useMousePosition","assembleTransform","LineChartTooltip","chartRef","chartData","enablePinning","wrapLabels","format","onUnpinClick","pinnedPos","containerId","showAllSeries","setShowAllSeries","mousePos","height","width","ref","tooltipRef","transform","isTooltipPinned","target","tagName","chart","current","chartWidth","getWidth","nearbySeries","length","totalSeries","timeSeries","containerElement","document","querySelector","undefined","maxHeight","getBoundingClientRect","container","sx","theme","minWidth","maxWidth","padding","position","top","left","backgroundColor","palette","designSystem","grey","borderRadius","color","fontSize","visibility","opacity","transition","zIndex","tooltip","overflow","overflowY","style","display","spacing","onShowAllClick","checked","series"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/TimeSeriesTooltip/LineChartTooltip.tsx"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { Box, Portal, Stack } from '@mui/material';\nimport { FormatOptions } from '@perses-dev/core';\nimport { ECharts as EChartsInstance } from 'echarts/core';\nimport { memo, MutableRefObject, ReactElement, useRef, useState } from 'react';\nimport useResizeObserver from 'use-resize-observer';\nimport { EChartsDataFormat } from '../model';\nimport { TooltipContent } from './TooltipContent';\nimport { TooltipHeader } from './TooltipHeader';\nimport { legacyGetNearbySeriesData } from './nearby-series';\nimport {\n CursorCoordinates,\n TOOLTIP_BG_COLOR_FALLBACK,\n TOOLTIP_MAX_HEIGHT,\n TOOLTIP_MAX_WIDTH,\n TOOLTIP_MIN_WIDTH,\n useMousePosition,\n} from './tooltip-model';\nimport { assembleTransform } from './utils';\n\nexport interface TimeSeriesTooltipProps {\n chartRef: MutableRefObject<EChartsInstance | undefined>;\n chartData: EChartsDataFormat;\n enablePinning?: boolean;\n wrapLabels?: boolean;\n format?: FormatOptions;\n onUnpinClick?: () => void;\n pinnedPos: CursorCoordinates | null;\n /**\n * The id of the container that will have the chart tooltip appended to it.\n * By default, the chart tooltip is attached to document.body.\n */\n containerId?: string;\n}\n\nexport const LineChartTooltip = memo(function LineChartTooltip({\n chartRef,\n chartData,\n enablePinning = true,\n wrapLabels,\n format,\n onUnpinClick,\n pinnedPos,\n containerId,\n}: TimeSeriesTooltipProps): ReactElement | null {\n const [showAllSeries, setShowAllSeries] = useState(false);\n const mousePos = useMousePosition();\n const { height, width, ref: tooltipRef } = useResizeObserver();\n const transform = useRef<string | undefined>();\n\n const isTooltipPinned = pinnedPos !== null && enablePinning;\n\n if (mousePos === null || mousePos.target === null) return null;\n\n // Ensure user is hovering over a chart before checking for nearby series.\n if (pinnedPos === null && (mousePos.target as HTMLElement).tagName !== 'CANVAS') return null;\n\n const chart = chartRef.current;\n\n // Get series nearby the cursor and pass into tooltip content children.\n const nearbySeries = legacyGetNearbySeriesData({\n mousePos,\n chartData,\n pinnedPos,\n chart,\n format,\n showAllSeries,\n });\n if (nearbySeries.length === 0) {\n return null;\n }\n\n const totalSeries = chartData.timeSeries.length;\n\n const containerElement = containerId ? document.querySelector(containerId) : undefined;\n // if tooltip is attached to a container, set max height to the height of the container so tooltip does not get cut off\n const maxHeight = containerElement ? containerElement.getBoundingClientRect().height : undefined;\n\n transform.current = assembleTransform(mousePos, pinnedPos, height ?? 0, width ?? 0, containerElement);\n\n return (\n <Portal container={containerElement}>\n <Box\n ref={tooltipRef}\n sx={(theme) => ({\n minWidth: TOOLTIP_MIN_WIDTH,\n maxWidth: TOOLTIP_MAX_WIDTH,\n maxHeight: maxHeight ?? TOOLTIP_MAX_HEIGHT,\n padding: 0,\n position: 'absolute',\n top: 0,\n left: 0,\n backgroundColor: theme.palette.designSystem?.grey[800] ?? TOOLTIP_BG_COLOR_FALLBACK,\n borderRadius: '6px',\n color: '#fff',\n fontSize: '11px',\n visibility: 'visible',\n opacity: 1,\n transition: 'all 0.1s ease-out',\n // Ensure pinned tooltip shows behind edit panel drawer and sticky header\n zIndex: pinnedPos !== null ? 'auto' : theme.zIndex.tooltip,\n overflow: 'hidden',\n '&:hover': {\n overflowY: 'auto',\n },\n })}\n style={{\n transform: transform.current,\n display: transform.current ? 'block' : 'none',\n }}\n >\n <Stack spacing={0.5}>\n <TooltipHeader\n nearbySeries={nearbySeries}\n totalSeries={totalSeries}\n enablePinning={enablePinning}\n isTooltipPinned={isTooltipPinned}\n showAllSeries={showAllSeries}\n onShowAllClick={(checked) => setShowAllSeries(checked)}\n onUnpinClick={onUnpinClick}\n />\n <TooltipContent series={nearbySeries} wrapLabels={wrapLabels} />\n </Stack>\n </Box>\n </Portal>\n );\n});\n"],"names":["Box","Portal","Stack","memo","useRef","useState","useResizeObserver","TooltipContent","TooltipHeader","legacyGetNearbySeriesData","TOOLTIP_BG_COLOR_FALLBACK","TOOLTIP_MAX_HEIGHT","TOOLTIP_MAX_WIDTH","TOOLTIP_MIN_WIDTH","useMousePosition","assembleTransform","LineChartTooltip","chartRef","chartData","enablePinning","wrapLabels","format","onUnpinClick","pinnedPos","containerId","showAllSeries","setShowAllSeries","mousePos","height","width","ref","tooltipRef","transform","isTooltipPinned","target","tagName","chart","current","nearbySeries","length","totalSeries","timeSeries","containerElement","document","querySelector","undefined","maxHeight","getBoundingClientRect","container","sx","theme","minWidth","maxWidth","padding","position","top","left","backgroundColor","palette","designSystem","grey","borderRadius","color","fontSize","visibility","opacity","transition","zIndex","tooltip","overflow","overflowY","style","display","spacing","onShowAllClick","checked","series"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/TimeSeriesTooltip/SeriesInfo.tsx"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { Box } from '@mui/material';\nimport { ReactElement } from 'react';\nimport { SeriesMarker } from './SeriesMarker';\nimport { SeriesLabelsStack } from './SeriesLabelsStack';\nimport { TOOLTIP_LABELS_MAX_WIDTH, EMPHASIZED_SERIES_DESCRIPTION, NEARBY_SERIES_DESCRIPTION } from './tooltip-model';\n\nexport interface SeriesInfoProps {\n seriesName: string;\n y: number;\n formattedY: string;\n markerColor: string;\n totalSeries: number;\n emphasizeText?: boolean;\n wrapLabels?: boolean;\n}\n\nexport function SeriesInfo(props: SeriesInfoProps): ReactElement {\n const { seriesName, formattedY, markerColor, totalSeries, emphasizeText = false, wrapLabels = true } = props;\n\n // metric __name__ comes before opening curly brace, ignore if not populated\n // ex with metric name: node_load15{env=\"demo\",job=\"node\"}\n // ex without metric name: {env=\"demo\",job=\"node\"}\n const splitName = seriesName.split('{');\n const seriesLabels = splitName[1] ?? seriesName;\n\n // remove curly braces that wrap labels\n const formattedSeriesLabels = seriesLabels.replace(/[{}]/g, '');\n\n // determine whether to show labels on separate lines\n const splitLabels = formattedSeriesLabels.split(',');\n if (totalSeries === 1 && splitLabels.length > 1) {\n const metricName = splitName[0] ? `${splitName[0]}:` : 'value:';\n return (\n <SeriesLabelsStack\n formattedY={formattedY}\n metricName={metricName}\n metricLabels={splitLabels}\n markerColor={markerColor}\n />\n );\n }\n\n // add space after commas so wrapLabels works\n const formattedSeriesInfo = seriesName.replace(/[,]/g, ', ');\n\n return (\n <Box\n sx={{\n display: 'table-row',\n paddingTop: 0.5,\n }}\n >\n <Box\n sx={{\n display: 'table-cell',\n maxWidth: '520px',\n }}\n >\n <SeriesMarker markerColor={markerColor} sx={{ marginTop: 0.5 }} />\n <Box\n component=\"span\"\n sx={(theme) => ({\n display: 'inline-block',\n width: 'calc(100% - 20px)',\n minWidth: 150,\n maxWidth: TOOLTIP_LABELS_MAX_WIDTH,\n overflow: 'hidden',\n color: theme.palette.common.white,\n fontWeight: emphasizeText ? theme.typography.fontWeightBold : theme.typography.fontWeightRegular,\n textOverflow: 'ellipsis',\n whiteSpace: wrapLabels ? 'normal' : 'nowrap',\n })}\n aria-label={emphasizeText ? EMPHASIZED_SERIES_DESCRIPTION : NEARBY_SERIES_DESCRIPTION}\n >\n {formattedSeriesInfo}\n </Box>\n </Box>\n <Box\n sx={(theme) => ({\n display: 'table-cell',\n paddingLeft: 1.5,\n textAlign: 'right',\n verticalAlign: 'top',\n fontWeight: emphasizeText ? theme.typography.fontWeightBold : theme.typography.fontWeightRegular,\n })}\n >\n {formattedY}\n </Box>\n </Box>\n );\n}\n"],"names":["Box","SeriesMarker","SeriesLabelsStack","TOOLTIP_LABELS_MAX_WIDTH","EMPHASIZED_SERIES_DESCRIPTION","NEARBY_SERIES_DESCRIPTION","SeriesInfo","props","seriesName","formattedY","markerColor","totalSeries","emphasizeText","wrapLabels","splitName","split","seriesLabels","formattedSeriesLabels","replace","splitLabels","length","metricName","metricLabels","formattedSeriesInfo","sx","display","paddingTop","maxWidth","marginTop","component","theme","width","minWidth","overflow","color","palette","common","white","fontWeight","typography","fontWeightBold","fontWeightRegular","textOverflow","whiteSpace","aria-label","paddingLeft","textAlign","verticalAlign"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;;AAEjC,SAASA,GAAG,QAAQ,gBAAgB;AAEpC,SAASC,YAAY,QAAQ,iBAAiB;AAC9C,SAASC,iBAAiB,QAAQ,sBAAsB;AACxD,SAASC,wBAAwB,EAAEC,6BAA6B,EAAEC,yBAAyB,QAAQ,kBAAkB;AAYrH,OAAO,SAASC,WAAWC,KAAsB;IAC/C,MAAM,EAAEC,UAAU,EAAEC,UAAU,EAAEC,WAAW,EAAEC,WAAW,EAAEC,gBAAgB,KAAK,EAAEC,aAAa,IAAI,EAAE,GAAGN;IAEvG,4EAA4E;IAC5E,0DAA0D;IAC1D,kDAAkD;IAClD,MAAMO,YAAYN,WAAWO,KAAK,CAAC;IACnC,MAAMC,eAAeF,SAAS,CAAC,EAAE,IAAIN;IAErC,uCAAuC;IACvC,MAAMS,wBAAwBD,aAAaE,OAAO,CAAC,SAAS;IAE5D,qDAAqD;IACrD,MAAMC,cAAcF,sBAAsBF,KAAK,CAAC;IAChD,IAAIJ,gBAAgB,KAAKQ,YAAYC,MAAM,GAAG,GAAG;QAC/C,MAAMC,aAAaP,SAAS,CAAC,EAAE,GAAG,CAAC,EAAEA,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG;QACvD,qBACE,KAACZ;YACCO,YAAYA;YACZY,YAAYA;YACZC,cAAcH;YACdT,aAAaA;;IAGnB;IAEA,6CAA6C;IAC7C,MAAMa,sBAAsBf,WAAWU,OAAO,CAAC,QAAQ;IAEvD,qBACE,MAAClB;QACCwB,IAAI;YACFC,SAAS;YACTC,YAAY;QACd;;0BAEA,MAAC1B;gBACCwB,IAAI;oBACFC,SAAS;oBACTE,UAAU;gBACZ;;kCAEA,KAAC1B;wBAAaS,aAAaA;wBAAac,IAAI;4BAAEI,WAAW;wBAAI;;kCAC7D,KAAC5B;wBACC6B,WAAU;wBACVL,IAAI,CAACM,QAAW,CAAA;gCACdL,SAAS;gCACTM,OAAO;gCACPC,UAAU;gCACVL,UAAUxB;gCACV8B,UAAU;gCACVC,OAAOJ,MAAMK,OAAO,CAACC,MAAM,CAACC,KAAK;gCACjCC,YAAY1B,gBAAgBkB,MAAMS,UAAU,CAACC,cAAc,GAAGV,MAAMS,UAAU,CAACE,iBAAiB;gCAChGC,cAAc;gCACdC,YAAY9B,aAAa,WAAW;4BACtC,CAAA;wBACA+B,cAAYhC,gBAAgBR,gCAAgCC;kCAE3DkB;;;;0BAGL,KAACvB;gBACCwB,IAAI,CAACM,QAAW,CAAA;wBACdL,SAAS;wBACToB,aAAa;wBACbC,WAAW;wBACXC,eAAe;wBACfT,YAAY1B,gBAAgBkB,MAAMS,UAAU,CAACC,cAAc,GAAGV,MAAMS,UAAU,CAACE,iBAAiB;oBAClG,CAAA;0BAEChC;;;;AAIT"}
1
+ {"version":3,"sources":["../../src/TimeSeriesTooltip/SeriesInfo.tsx"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { Box } from '@mui/material';\nimport { ReactElement } from 'react';\nimport { SeriesMarker } from './SeriesMarker';\nimport { SeriesLabelsStack } from './SeriesLabelsStack';\nimport { TOOLTIP_LABELS_MAX_WIDTH, EMPHASIZED_SERIES_DESCRIPTION, NEARBY_SERIES_DESCRIPTION } from './tooltip-model';\n\nexport interface SeriesInfoProps {\n seriesName: string;\n y: number;\n formattedY: string;\n markerColor: string;\n totalSeries: number;\n emphasizeText?: boolean;\n wrapLabels?: boolean;\n}\n\nexport function SeriesInfo(props: SeriesInfoProps): ReactElement {\n const { seriesName, formattedY, markerColor, totalSeries, emphasizeText = false, wrapLabels = true } = props;\n\n // metric __name__ comes before opening curly brace, ignore if not populated\n // ex with metric name: node_load15{env=\"demo\",job=\"node\"}\n // ex without metric name: {env=\"demo\",job=\"node\"}\n const splitName = seriesName.split('{');\n const seriesLabels = splitName[1] ?? seriesName;\n\n // remove curly braces that wrap labels\n const formattedSeriesLabels = seriesLabels.replace(/[{}]/g, '');\n\n // determine whether to show labels on separate lines\n const splitLabels = formattedSeriesLabels.split(',');\n if (totalSeries === 1 && splitLabels.length > 1) {\n const metricName = splitName[0] ? `${splitName[0]}:` : 'value:';\n return (\n <SeriesLabelsStack\n formattedY={formattedY}\n metricName={metricName}\n metricLabels={splitLabels}\n markerColor={markerColor}\n />\n );\n }\n\n // add space after commas so wrapLabels works\n const formattedSeriesInfo = seriesName.replace(/[,]/g, ', ');\n\n return (\n <Box\n sx={{\n display: 'table-row',\n paddingTop: 0.5,\n }}\n >\n <Box\n sx={{\n display: 'table-cell',\n maxWidth: '520px',\n }}\n >\n <SeriesMarker markerColor={markerColor} sx={{ marginTop: 0.5 }} />\n <Box\n component=\"span\"\n sx={(theme) => ({\n display: 'inline-block',\n width: 'calc(100% - 20px)',\n minWidth: 150,\n maxWidth: TOOLTIP_LABELS_MAX_WIDTH,\n overflow: 'hidden',\n color: theme.palette.common.white,\n fontWeight: emphasizeText ? theme.typography.fontWeightBold : theme.typography.fontWeightRegular,\n textOverflow: 'ellipsis',\n whiteSpace: wrapLabels ? 'normal' : 'nowrap',\n })}\n aria-label={emphasizeText ? EMPHASIZED_SERIES_DESCRIPTION : NEARBY_SERIES_DESCRIPTION}\n >\n {formattedSeriesInfo}\n </Box>\n </Box>\n <Box\n sx={(theme) => ({\n display: 'table-cell',\n paddingLeft: 1.5,\n textAlign: 'right',\n verticalAlign: 'top',\n fontWeight: emphasizeText ? theme.typography.fontWeightBold : theme.typography.fontWeightRegular,\n })}\n >\n {formattedY}\n </Box>\n </Box>\n );\n}\n"],"names":["Box","SeriesMarker","SeriesLabelsStack","TOOLTIP_LABELS_MAX_WIDTH","EMPHASIZED_SERIES_DESCRIPTION","NEARBY_SERIES_DESCRIPTION","SeriesInfo","props","seriesName","formattedY","markerColor","totalSeries","emphasizeText","wrapLabels","splitName","split","seriesLabels","formattedSeriesLabels","replace","splitLabels","length","metricName","metricLabels","formattedSeriesInfo","sx","display","paddingTop","maxWidth","marginTop","component","theme","width","minWidth","overflow","color","palette","common","white","fontWeight","typography","fontWeightBold","fontWeightRegular","textOverflow","whiteSpace","aria-label","paddingLeft","textAlign","verticalAlign"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;;AAEjC,SAASA,GAAG,QAAQ,gBAAgB;AAEpC,SAASC,YAAY,QAAQ,iBAAiB;AAC9C,SAASC,iBAAiB,QAAQ,sBAAsB;AACxD,SAASC,wBAAwB,EAAEC,6BAA6B,EAAEC,yBAAyB,QAAQ,kBAAkB;AAYrH,OAAO,SAASC,WAAWC,KAAsB;IAC/C,MAAM,EAAEC,UAAU,EAAEC,UAAU,EAAEC,WAAW,EAAEC,WAAW,EAAEC,gBAAgB,KAAK,EAAEC,aAAa,IAAI,EAAE,GAAGN;IAEvG,4EAA4E;IAC5E,0DAA0D;IAC1D,kDAAkD;IAClD,MAAMO,YAAYN,WAAWO,KAAK,CAAC;IACnC,MAAMC,eAAeF,SAAS,CAAC,EAAE,IAAIN;IAErC,uCAAuC;IACvC,MAAMS,wBAAwBD,aAAaE,OAAO,CAAC,SAAS;IAE5D,qDAAqD;IACrD,MAAMC,cAAcF,sBAAsBF,KAAK,CAAC;IAChD,IAAIJ,gBAAgB,KAAKQ,YAAYC,MAAM,GAAG,GAAG;QAC/C,MAAMC,aAAaP,SAAS,CAAC,EAAE,GAAG,GAAGA,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG;QACvD,qBACE,KAACZ;YACCO,YAAYA;YACZY,YAAYA;YACZC,cAAcH;YACdT,aAAaA;;IAGnB;IAEA,6CAA6C;IAC7C,MAAMa,sBAAsBf,WAAWU,OAAO,CAAC,QAAQ;IAEvD,qBACE,MAAClB;QACCwB,IAAI;YACFC,SAAS;YACTC,YAAY;QACd;;0BAEA,MAAC1B;gBACCwB,IAAI;oBACFC,SAAS;oBACTE,UAAU;gBACZ;;kCAEA,KAAC1B;wBAAaS,aAAaA;wBAAac,IAAI;4BAAEI,WAAW;wBAAI;;kCAC7D,KAAC5B;wBACC6B,WAAU;wBACVL,IAAI,CAACM,QAAW,CAAA;gCACdL,SAAS;gCACTM,OAAO;gCACPC,UAAU;gCACVL,UAAUxB;gCACV8B,UAAU;gCACVC,OAAOJ,MAAMK,OAAO,CAACC,MAAM,CAACC,KAAK;gCACjCC,YAAY1B,gBAAgBkB,MAAMS,UAAU,CAACC,cAAc,GAAGV,MAAMS,UAAU,CAACE,iBAAiB;gCAChGC,cAAc;gCACdC,YAAY9B,aAAa,WAAW;4BACtC,CAAA;wBACA+B,cAAYhC,gBAAgBR,gCAAgCC;kCAE3DkB;;;;0BAGL,KAACvB;gBACCwB,IAAI,CAACM,QAAW,CAAA;wBACdL,SAAS;wBACToB,aAAa;wBACbC,WAAW;wBACXC,eAAe;wBACfT,YAAY1B,gBAAgBkB,MAAMS,UAAU,CAACC,cAAc,GAAGV,MAAMS,UAAU,CAACE,iBAAiB;oBAClG,CAAA;0BAEChC;;;;AAIT"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/TimeSeriesTooltip/SeriesLabelsStack.tsx"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { Box, Divider, Stack, Typography } from '@mui/material';\nimport { ReactElement } from 'react';\nimport { SeriesMarker } from './SeriesMarker';\n\nexport interface SeriesLabelsStackProps {\n formattedY: string;\n metricName: string;\n metricLabels: string[];\n markerColor: string;\n}\n\nexport function SeriesLabelsStack(props: SeriesLabelsStackProps): ReactElement {\n const { formattedY, markerColor, metricName, metricLabels } = props;\n return (\n <Stack spacing={0.5}>\n <Box\n sx={(theme) => ({\n display: 'flex',\n height: '16px',\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'left',\n color: theme.palette.common.white,\n fontSize: '11px',\n })}\n >\n <SeriesMarker markerColor={markerColor} sx={{ marginTop: 0.25 }} />\n <Box component=\"span\">\n {metricName}\n <Box\n component=\"span\"\n sx={(theme) => ({\n color: theme.palette.common.white,\n fontWeight: 700,\n paddingLeft: '2px',\n })}\n >\n {formattedY}\n </Box>\n </Box>\n </Box>\n <Divider\n sx={(theme) => ({\n borderColor: theme.palette.grey['500'],\n })}\n />\n <Box\n sx={(theme) => ({\n color: theme.palette.common.white,\n })}\n >\n {metricLabels.map((label) => {\n // show labels on separate lines when many labels and only one focused series\n if (label) {\n const [name, value] = label.split('=');\n const formattedName = value !== undefined ? `${name}: ` : name;\n const formattedValue = value !== undefined ? value.replace(/(^\"|\"$)/g, '') : value;\n return (\n <Box key={label} sx={{ display: 'flex', gap: '4px' }}>\n <Typography sx={{ fontSize: '11px' }}>{formattedName}</Typography>\n <Typography\n sx={(theme) => ({\n color: theme.palette.common.white,\n fontWeight: 700,\n fontSize: '11px',\n })}\n >\n {formattedValue}\n </Typography>\n </Box>\n );\n }\n })}\n </Box>\n </Stack>\n );\n}\n"],"names":["Box","Divider","Stack","Typography","SeriesMarker","SeriesLabelsStack","props","formattedY","markerColor","metricName","metricLabels","spacing","sx","theme","display","height","flexDirection","alignItems","justifyContent","color","palette","common","white","fontSize","marginTop","component","fontWeight","paddingLeft","borderColor","grey","map","label","name","value","split","formattedName","undefined","formattedValue","replace","gap"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;;AAEjC,SAASA,GAAG,EAAEC,OAAO,EAAEC,KAAK,EAAEC,UAAU,QAAQ,gBAAgB;AAEhE,SAASC,YAAY,QAAQ,iBAAiB;AAS9C,OAAO,SAASC,kBAAkBC,KAA6B;IAC7D,MAAM,EAAEC,UAAU,EAAEC,WAAW,EAAEC,UAAU,EAAEC,YAAY,EAAE,GAAGJ;IAC9D,qBACE,MAACJ;QAAMS,SAAS;;0BACd,MAACX;gBACCY,IAAI,CAACC,QAAW,CAAA;wBACdC,SAAS;wBACTC,QAAQ;wBACRC,eAAe;wBACfC,YAAY;wBACZC,gBAAgB;wBAChBC,OAAON,MAAMO,OAAO,CAACC,MAAM,CAACC,KAAK;wBACjCC,UAAU;oBACZ,CAAA;;kCAEA,KAACnB;wBAAaI,aAAaA;wBAAaI,IAAI;4BAAEY,WAAW;wBAAK;;kCAC9D,MAACxB;wBAAIyB,WAAU;;4BACZhB;0CACD,KAACT;gCACCyB,WAAU;gCACVb,IAAI,CAACC,QAAW,CAAA;wCACdM,OAAON,MAAMO,OAAO,CAACC,MAAM,CAACC,KAAK;wCACjCI,YAAY;wCACZC,aAAa;oCACf,CAAA;0CAECpB;;;;;;0BAIP,KAACN;gBACCW,IAAI,CAACC,QAAW,CAAA;wBACde,aAAaf,MAAMO,OAAO,CAACS,IAAI,CAAC,MAAM;oBACxC,CAAA;;0BAEF,KAAC7B;gBACCY,IAAI,CAACC,QAAW,CAAA;wBACdM,OAAON,MAAMO,OAAO,CAACC,MAAM,CAACC,KAAK;oBACnC,CAAA;0BAECZ,aAAaoB,GAAG,CAAC,CAACC;oBACjB,6EAA6E;oBAC7E,IAAIA,OAAO;wBACT,MAAM,CAACC,MAAMC,MAAM,GAAGF,MAAMG,KAAK,CAAC;wBAClC,MAAMC,gBAAgBF,UAAUG,YAAY,CAAC,EAAEJ,KAAK,EAAE,CAAC,GAAGA;wBAC1D,MAAMK,iBAAiBJ,UAAUG,YAAYH,MAAMK,OAAO,CAAC,YAAY,MAAML;wBAC7E,qBACE,MAACjC;4BAAgBY,IAAI;gCAAEE,SAAS;gCAAQyB,KAAK;4BAAM;;8CACjD,KAACpC;oCAAWS,IAAI;wCAAEW,UAAU;oCAAO;8CAAIY;;8CACvC,KAAChC;oCACCS,IAAI,CAACC,QAAW,CAAA;4CACdM,OAAON,MAAMO,OAAO,CAACC,MAAM,CAACC,KAAK;4CACjCI,YAAY;4CACZH,UAAU;wCACZ,CAAA;8CAECc;;;2BATKN;oBAad;gBACF;;;;AAIR"}
1
+ {"version":3,"sources":["../../src/TimeSeriesTooltip/SeriesLabelsStack.tsx"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { Box, Divider, Stack, Typography } from '@mui/material';\nimport { ReactElement } from 'react';\nimport { SeriesMarker } from './SeriesMarker';\n\nexport interface SeriesLabelsStackProps {\n formattedY: string;\n metricName: string;\n metricLabels: string[];\n markerColor: string;\n}\n\nexport function SeriesLabelsStack(props: SeriesLabelsStackProps): ReactElement {\n const { formattedY, markerColor, metricName, metricLabels } = props;\n return (\n <Stack spacing={0.5}>\n <Box\n sx={(theme) => ({\n display: 'flex',\n height: '16px',\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'left',\n color: theme.palette.common.white,\n fontSize: '11px',\n })}\n >\n <SeriesMarker markerColor={markerColor} sx={{ marginTop: 0.25 }} />\n <Box component=\"span\">\n {metricName}\n <Box\n component=\"span\"\n sx={(theme) => ({\n color: theme.palette.common.white,\n fontWeight: 700,\n paddingLeft: '2px',\n })}\n >\n {formattedY}\n </Box>\n </Box>\n </Box>\n <Divider\n sx={(theme) => ({\n borderColor: theme.palette.grey['500'],\n })}\n />\n <Box\n sx={(theme) => ({\n color: theme.palette.common.white,\n })}\n >\n {metricLabels.map((label) => {\n // show labels on separate lines when many labels and only one focused series\n if (label) {\n const [name, value] = label.split('=');\n const formattedName = value !== undefined ? `${name}: ` : name;\n const formattedValue = value !== undefined ? value.replace(/(^\"|\"$)/g, '') : value;\n return (\n <Box key={label} sx={{ display: 'flex', gap: '4px' }}>\n <Typography sx={{ fontSize: '11px' }}>{formattedName}</Typography>\n <Typography\n sx={(theme) => ({\n color: theme.palette.common.white,\n fontWeight: 700,\n fontSize: '11px',\n })}\n >\n {formattedValue}\n </Typography>\n </Box>\n );\n }\n })}\n </Box>\n </Stack>\n );\n}\n"],"names":["Box","Divider","Stack","Typography","SeriesMarker","SeriesLabelsStack","props","formattedY","markerColor","metricName","metricLabels","spacing","sx","theme","display","height","flexDirection","alignItems","justifyContent","color","palette","common","white","fontSize","marginTop","component","fontWeight","paddingLeft","borderColor","grey","map","label","name","value","split","formattedName","undefined","formattedValue","replace","gap"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;;AAEjC,SAASA,GAAG,EAAEC,OAAO,EAAEC,KAAK,EAAEC,UAAU,QAAQ,gBAAgB;AAEhE,SAASC,YAAY,QAAQ,iBAAiB;AAS9C,OAAO,SAASC,kBAAkBC,KAA6B;IAC7D,MAAM,EAAEC,UAAU,EAAEC,WAAW,EAAEC,UAAU,EAAEC,YAAY,EAAE,GAAGJ;IAC9D,qBACE,MAACJ;QAAMS,SAAS;;0BACd,MAACX;gBACCY,IAAI,CAACC,QAAW,CAAA;wBACdC,SAAS;wBACTC,QAAQ;wBACRC,eAAe;wBACfC,YAAY;wBACZC,gBAAgB;wBAChBC,OAAON,MAAMO,OAAO,CAACC,MAAM,CAACC,KAAK;wBACjCC,UAAU;oBACZ,CAAA;;kCAEA,KAACnB;wBAAaI,aAAaA;wBAAaI,IAAI;4BAAEY,WAAW;wBAAK;;kCAC9D,MAACxB;wBAAIyB,WAAU;;4BACZhB;0CACD,KAACT;gCACCyB,WAAU;gCACVb,IAAI,CAACC,QAAW,CAAA;wCACdM,OAAON,MAAMO,OAAO,CAACC,MAAM,CAACC,KAAK;wCACjCI,YAAY;wCACZC,aAAa;oCACf,CAAA;0CAECpB;;;;;;0BAIP,KAACN;gBACCW,IAAI,CAACC,QAAW,CAAA;wBACde,aAAaf,MAAMO,OAAO,CAACS,IAAI,CAAC,MAAM;oBACxC,CAAA;;0BAEF,KAAC7B;gBACCY,IAAI,CAACC,QAAW,CAAA;wBACdM,OAAON,MAAMO,OAAO,CAACC,MAAM,CAACC,KAAK;oBACnC,CAAA;0BAECZ,aAAaoB,GAAG,CAAC,CAACC;oBACjB,6EAA6E;oBAC7E,IAAIA,OAAO;wBACT,MAAM,CAACC,MAAMC,MAAM,GAAGF,MAAMG,KAAK,CAAC;wBAClC,MAAMC,gBAAgBF,UAAUG,YAAY,GAAGJ,KAAK,EAAE,CAAC,GAAGA;wBAC1D,MAAMK,iBAAiBJ,UAAUG,YAAYH,MAAMK,OAAO,CAAC,YAAY,MAAML;wBAC7E,qBACE,MAACjC;4BAAgBY,IAAI;gCAAEE,SAAS;gCAAQyB,KAAK;4BAAM;;8CACjD,KAACpC;oCAAWS,IAAI;wCAAEW,UAAU;oCAAO;8CAAIY;;8CACvC,KAAChC;oCACCS,IAAI,CAACC,QAAW,CAAA;4CACdM,OAAON,MAAMO,OAAO,CAACC,MAAM,CAACC,KAAK;4CACjCI,YAAY;4CACZH,UAAU;wCACZ,CAAA;8CAECc;;;2BATKN;oBAad;gBACF;;;;AAIR"}
@@ -1 +1 @@
1
- {"version":3,"file":"TimeChartTooltip.d.ts","sourceRoot":"","sources":["../../src/TimeSeriesTooltip/TimeChartTooltip.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAQ,gBAAgB,EAAoB,MAAM,OAAO,CAAC;AAEjE,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAA0C,MAAM,iBAAiB,CAAC;AAM5F,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,gBAAgB,CAAC,eAAe,GAAG,SAAS,CAAC,CAAC;IACxD,IAAI,EAAE,UAAU,EAAE,CAAC;IACnB,aAAa,EAAE,sBAAsB,CAAC;IACtC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,SAAS,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACpC;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,gBAAgB,6DA2E3B,CAAC"}
1
+ {"version":3,"file":"TimeChartTooltip.d.ts","sourceRoot":"","sources":["../../src/TimeSeriesTooltip/TimeChartTooltip.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAQ,gBAAgB,EAAoB,MAAM,OAAO,CAAC;AAEjE,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAoB,MAAM,iBAAiB,CAAC;AAMtE,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,gBAAgB,CAAC,eAAe,GAAG,SAAS,CAAC,CAAC;IACxD,IAAI,EAAE,UAAU,EAAE,CAAC;IACnB,aAAa,EAAE,sBAAsB,CAAC;IACtC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,SAAS,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACpC;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,gBAAgB,6DAwE3B,CAAC"}
@@ -14,7 +14,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
14
14
  import { memo, useRef, useState } from 'react';
15
15
  import { Box, Portal, Stack } from '@mui/material';
16
16
  import useResizeObserver from 'use-resize-observer';
17
- import { FALLBACK_CHART_WIDTH, useMousePosition } from './tooltip-model';
17
+ import { useMousePosition } from './tooltip-model';
18
18
  import { assembleTransform, getTooltipStyles } from './utils';
19
19
  import { getNearbySeriesData } from './nearby-series';
20
20
  import { TooltipHeader } from './TooltipHeader';
@@ -29,13 +29,10 @@ export const TimeChartTooltip = /*#__PURE__*/ memo(function TimeChartTooltip({ c
29
29
  // Ensure user is hovering over a chart before checking for nearby series.
30
30
  if (pinnedPos === null && mousePos.target.tagName !== 'CANVAS') return null;
31
31
  const chart = chartRef.current;
32
- const chartWidth = chart?.getWidth() ?? FALLBACK_CHART_WIDTH; // Fallback width not likely to ever be needed.
33
32
  const containerElement = containerId ? document.querySelector(containerId) : undefined;
34
33
  // if tooltip is attached to a container, set max height to the height of the container so tooltip does not get cut off
35
34
  const maxHeight = containerElement ? containerElement.getBoundingClientRect().height : undefined;
36
- if (!isTooltipPinned) {
37
- transform.current = assembleTransform(mousePos, chartWidth, pinnedPos, height ?? 0, width ?? 0, containerElement);
38
- }
35
+ transform.current = assembleTransform(mousePos, pinnedPos, height ?? 0, width ?? 0, containerElement);
39
36
  // Get series nearby the cursor and pass into tooltip content children.
40
37
  const nearbySeries = getNearbySeriesData({
41
38
  mousePos,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/TimeSeriesTooltip/TimeChartTooltip.tsx"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { memo, MutableRefObject, useRef, useState } from 'react';\nimport { Box, Portal, Stack } from '@mui/material';\nimport { ECharts as EChartsInstance } from 'echarts/core';\nimport { FormatOptions, TimeSeries } from '@perses-dev/core';\nimport useResizeObserver from 'use-resize-observer';\nimport { TimeChartSeriesMapping } from '../model';\nimport { CursorCoordinates, FALLBACK_CHART_WIDTH, useMousePosition } from './tooltip-model';\nimport { assembleTransform, getTooltipStyles } from './utils';\nimport { getNearbySeriesData } from './nearby-series';\nimport { TooltipHeader } from './TooltipHeader';\nimport { TooltipContent } from './TooltipContent';\n\nexport interface TimeChartTooltipProps {\n chartRef: MutableRefObject<EChartsInstance | undefined>;\n data: TimeSeries[];\n seriesMapping: TimeChartSeriesMapping;\n enablePinning?: boolean;\n pinnedPos: CursorCoordinates | null;\n /**\n * The id of the container that will have the chart tooltip appended to it.\n * By default, the chart tooltip is attached to document.body.\n */\n containerId?: string;\n onUnpinClick?: () => void;\n format?: FormatOptions;\n wrapLabels?: boolean;\n}\n\nexport const TimeChartTooltip = memo(function TimeChartTooltip({\n containerId,\n chartRef,\n data,\n seriesMapping,\n enablePinning = true,\n wrapLabels,\n format,\n onUnpinClick,\n pinnedPos,\n}: TimeChartTooltipProps) {\n const [showAllSeries, setShowAllSeries] = useState(false);\n const transform = useRef<string | undefined>();\n\n const mousePos = useMousePosition();\n const { height, width, ref: tooltipRef } = useResizeObserver();\n\n const isTooltipPinned = pinnedPos !== null && enablePinning;\n\n if (mousePos === null || mousePos.target === null || data === null) return null;\n\n // Ensure user is hovering over a chart before checking for nearby series.\n if (pinnedPos === null && (mousePos.target as HTMLElement).tagName !== 'CANVAS') return null;\n\n const chart = chartRef.current;\n const chartWidth = chart?.getWidth() ?? FALLBACK_CHART_WIDTH; // Fallback width not likely to ever be needed.\n\n const containerElement = containerId ? document.querySelector(containerId) : undefined;\n // if tooltip is attached to a container, set max height to the height of the container so tooltip does not get cut off\n const maxHeight = containerElement ? containerElement.getBoundingClientRect().height : undefined;\n\n if (!isTooltipPinned) {\n transform.current = assembleTransform(mousePos, chartWidth, pinnedPos, height ?? 0, width ?? 0, containerElement);\n }\n\n // Get series nearby the cursor and pass into tooltip content children.\n const nearbySeries = getNearbySeriesData({\n mousePos,\n data,\n seriesMapping,\n pinnedPos,\n chart,\n format,\n showAllSeries,\n });\n if (nearbySeries.length === 0) {\n return null;\n }\n\n const totalSeries = data.length;\n\n return (\n <Portal container={containerElement}>\n <Box\n ref={tooltipRef}\n sx={(theme) => getTooltipStyles(theme, pinnedPos, maxHeight)}\n style={{\n transform: transform.current,\n }}\n >\n <Stack spacing={0.5}>\n <TooltipHeader\n nearbySeries={nearbySeries}\n totalSeries={totalSeries}\n enablePinning={enablePinning}\n isTooltipPinned={isTooltipPinned}\n showAllSeries={showAllSeries}\n onShowAllClick={(checked) => setShowAllSeries(checked)}\n onUnpinClick={onUnpinClick}\n />\n <TooltipContent series={nearbySeries} wrapLabels={wrapLabels} />\n </Stack>\n </Box>\n </Portal>\n );\n});\n"],"names":["memo","useRef","useState","Box","Portal","Stack","useResizeObserver","FALLBACK_CHART_WIDTH","useMousePosition","assembleTransform","getTooltipStyles","getNearbySeriesData","TooltipHeader","TooltipContent","TimeChartTooltip","containerId","chartRef","data","seriesMapping","enablePinning","wrapLabels","format","onUnpinClick","pinnedPos","showAllSeries","setShowAllSeries","transform","mousePos","height","width","ref","tooltipRef","isTooltipPinned","target","tagName","chart","current","chartWidth","getWidth","containerElement","document","querySelector","undefined","maxHeight","getBoundingClientRect","nearbySeries","length","totalSeries","container","sx","theme","style","spacing","onShowAllClick","checked","series"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;;AAEjC,SAASA,IAAI,EAAoBC,MAAM,EAAEC,QAAQ,QAAQ,QAAQ;AACjE,SAASC,GAAG,EAAEC,MAAM,EAAEC,KAAK,QAAQ,gBAAgB;AAGnD,OAAOC,uBAAuB,sBAAsB;AAEpD,SAA4BC,oBAAoB,EAAEC,gBAAgB,QAAQ,kBAAkB;AAC5F,SAASC,iBAAiB,EAAEC,gBAAgB,QAAQ,UAAU;AAC9D,SAASC,mBAAmB,QAAQ,kBAAkB;AACtD,SAASC,aAAa,QAAQ,kBAAkB;AAChD,SAASC,cAAc,QAAQ,mBAAmB;AAkBlD,OAAO,MAAMC,iCAAmBd,KAAK,SAASc,iBAAiB,EAC7DC,WAAW,EACXC,QAAQ,EACRC,IAAI,EACJC,aAAa,EACbC,gBAAgB,IAAI,EACpBC,UAAU,EACVC,MAAM,EACNC,YAAY,EACZC,SAAS,EACa;IACtB,MAAM,CAACC,eAAeC,iBAAiB,GAAGvB,SAAS;IACnD,MAAMwB,YAAYzB;IAElB,MAAM0B,WAAWnB;IACjB,MAAM,EAAEoB,MAAM,EAAEC,KAAK,EAAEC,KAAKC,UAAU,EAAE,GAAGzB;IAE3C,MAAM0B,kBAAkBT,cAAc,QAAQJ;IAE9C,IAAIQ,aAAa,QAAQA,SAASM,MAAM,KAAK,QAAQhB,SAAS,MAAM,OAAO;IAE3E,0EAA0E;IAC1E,IAAIM,cAAc,QAAQ,AAACI,SAASM,MAAM,CAAiBC,OAAO,KAAK,UAAU,OAAO;IAExF,MAAMC,QAAQnB,SAASoB,OAAO;IAC9B,MAAMC,aAAaF,OAAOG,cAAc/B,sBAAsB,+CAA+C;IAE7G,MAAMgC,mBAAmBxB,cAAcyB,SAASC,aAAa,CAAC1B,eAAe2B;IAC7E,uHAAuH;IACvH,MAAMC,YAAYJ,mBAAmBA,iBAAiBK,qBAAqB,GAAGhB,MAAM,GAAGc;IAEvF,IAAI,CAACV,iBAAiB;QACpBN,UAAUU,OAAO,GAAG3B,kBAAkBkB,UAAUU,YAAYd,WAAWK,UAAU,GAAGC,SAAS,GAAGU;IAClG;IAEA,uEAAuE;IACvE,MAAMM,eAAelC,oBAAoB;QACvCgB;QACAV;QACAC;QACAK;QACAY;QACAd;QACAG;IACF;IACA,IAAIqB,aAAaC,MAAM,KAAK,GAAG;QAC7B,OAAO;IACT;IAEA,MAAMC,cAAc9B,KAAK6B,MAAM;IAE/B,qBACE,KAAC1C;QAAO4C,WAAWT;kBACjB,cAAA,KAACpC;YACC2B,KAAKC;YACLkB,IAAI,CAACC,QAAUxC,iBAAiBwC,OAAO3B,WAAWoB;YAClDQ,OAAO;gBACLzB,WAAWA,UAAUU,OAAO;YAC9B;sBAEA,cAAA,MAAC/B;gBAAM+C,SAAS;;kCACd,KAACxC;wBACCiC,cAAcA;wBACdE,aAAaA;wBACb5B,eAAeA;wBACfa,iBAAiBA;wBACjBR,eAAeA;wBACf6B,gBAAgB,CAACC,UAAY7B,iBAAiB6B;wBAC9ChC,cAAcA;;kCAEhB,KAACT;wBAAe0C,QAAQV;wBAAczB,YAAYA;;;;;;AAK5D,GAAG"}
1
+ {"version":3,"sources":["../../src/TimeSeriesTooltip/TimeChartTooltip.tsx"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { memo, MutableRefObject, useRef, useState } from 'react';\nimport { Box, Portal, Stack } from '@mui/material';\nimport { ECharts as EChartsInstance } from 'echarts/core';\nimport { FormatOptions, TimeSeries } from '@perses-dev/core';\nimport useResizeObserver from 'use-resize-observer';\nimport { TimeChartSeriesMapping } from '../model';\nimport { CursorCoordinates, useMousePosition } from './tooltip-model';\nimport { assembleTransform, getTooltipStyles } from './utils';\nimport { getNearbySeriesData } from './nearby-series';\nimport { TooltipHeader } from './TooltipHeader';\nimport { TooltipContent } from './TooltipContent';\n\nexport interface TimeChartTooltipProps {\n chartRef: MutableRefObject<EChartsInstance | undefined>;\n data: TimeSeries[];\n seriesMapping: TimeChartSeriesMapping;\n enablePinning?: boolean;\n pinnedPos: CursorCoordinates | null;\n /**\n * The id of the container that will have the chart tooltip appended to it.\n * By default, the chart tooltip is attached to document.body.\n */\n containerId?: string;\n onUnpinClick?: () => void;\n format?: FormatOptions;\n wrapLabels?: boolean;\n}\n\nexport const TimeChartTooltip = memo(function TimeChartTooltip({\n containerId,\n chartRef,\n data,\n seriesMapping,\n enablePinning = true,\n wrapLabels,\n format,\n onUnpinClick,\n pinnedPos,\n}: TimeChartTooltipProps) {\n const [showAllSeries, setShowAllSeries] = useState(false);\n const transform = useRef<string | undefined>();\n\n const mousePos = useMousePosition();\n const { height, width, ref: tooltipRef } = useResizeObserver();\n\n const isTooltipPinned = pinnedPos !== null && enablePinning;\n\n if (mousePos === null || mousePos.target === null || data === null) return null;\n\n // Ensure user is hovering over a chart before checking for nearby series.\n if (pinnedPos === null && (mousePos.target as HTMLElement).tagName !== 'CANVAS') return null;\n\n const chart = chartRef.current;\n\n const containerElement = containerId ? document.querySelector(containerId) : undefined;\n // if tooltip is attached to a container, set max height to the height of the container so tooltip does not get cut off\n const maxHeight = containerElement ? containerElement.getBoundingClientRect().height : undefined;\n\n transform.current = assembleTransform(mousePos, pinnedPos, height ?? 0, width ?? 0, containerElement);\n\n // Get series nearby the cursor and pass into tooltip content children.\n const nearbySeries = getNearbySeriesData({\n mousePos,\n data,\n seriesMapping,\n pinnedPos,\n chart,\n format,\n showAllSeries,\n });\n if (nearbySeries.length === 0) {\n return null;\n }\n\n const totalSeries = data.length;\n\n return (\n <Portal container={containerElement}>\n <Box\n ref={tooltipRef}\n sx={(theme) => getTooltipStyles(theme, pinnedPos, maxHeight)}\n style={{\n transform: transform.current,\n }}\n >\n <Stack spacing={0.5}>\n <TooltipHeader\n nearbySeries={nearbySeries}\n totalSeries={totalSeries}\n enablePinning={enablePinning}\n isTooltipPinned={isTooltipPinned}\n showAllSeries={showAllSeries}\n onShowAllClick={(checked) => setShowAllSeries(checked)}\n onUnpinClick={onUnpinClick}\n />\n <TooltipContent series={nearbySeries} wrapLabels={wrapLabels} />\n </Stack>\n </Box>\n </Portal>\n );\n});\n"],"names":["memo","useRef","useState","Box","Portal","Stack","useResizeObserver","useMousePosition","assembleTransform","getTooltipStyles","getNearbySeriesData","TooltipHeader","TooltipContent","TimeChartTooltip","containerId","chartRef","data","seriesMapping","enablePinning","wrapLabels","format","onUnpinClick","pinnedPos","showAllSeries","setShowAllSeries","transform","mousePos","height","width","ref","tooltipRef","isTooltipPinned","target","tagName","chart","current","containerElement","document","querySelector","undefined","maxHeight","getBoundingClientRect","nearbySeries","length","totalSeries","container","sx","theme","style","spacing","onShowAllClick","checked","series"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;;AAEjC,SAASA,IAAI,EAAoBC,MAAM,EAAEC,QAAQ,QAAQ,QAAQ;AACjE,SAASC,GAAG,EAAEC,MAAM,EAAEC,KAAK,QAAQ,gBAAgB;AAGnD,OAAOC,uBAAuB,sBAAsB;AAEpD,SAA4BC,gBAAgB,QAAQ,kBAAkB;AACtE,SAASC,iBAAiB,EAAEC,gBAAgB,QAAQ,UAAU;AAC9D,SAASC,mBAAmB,QAAQ,kBAAkB;AACtD,SAASC,aAAa,QAAQ,kBAAkB;AAChD,SAASC,cAAc,QAAQ,mBAAmB;AAkBlD,OAAO,MAAMC,iCAAmBb,KAAK,SAASa,iBAAiB,EAC7DC,WAAW,EACXC,QAAQ,EACRC,IAAI,EACJC,aAAa,EACbC,gBAAgB,IAAI,EACpBC,UAAU,EACVC,MAAM,EACNC,YAAY,EACZC,SAAS,EACa;IACtB,MAAM,CAACC,eAAeC,iBAAiB,GAAGtB,SAAS;IACnD,MAAMuB,YAAYxB;IAElB,MAAMyB,WAAWnB;IACjB,MAAM,EAAEoB,MAAM,EAAEC,KAAK,EAAEC,KAAKC,UAAU,EAAE,GAAGxB;IAE3C,MAAMyB,kBAAkBT,cAAc,QAAQJ;IAE9C,IAAIQ,aAAa,QAAQA,SAASM,MAAM,KAAK,QAAQhB,SAAS,MAAM,OAAO;IAE3E,0EAA0E;IAC1E,IAAIM,cAAc,QAAQ,AAACI,SAASM,MAAM,CAAiBC,OAAO,KAAK,UAAU,OAAO;IAExF,MAAMC,QAAQnB,SAASoB,OAAO;IAE9B,MAAMC,mBAAmBtB,cAAcuB,SAASC,aAAa,CAACxB,eAAeyB;IAC7E,uHAAuH;IACvH,MAAMC,YAAYJ,mBAAmBA,iBAAiBK,qBAAqB,GAAGd,MAAM,GAAGY;IAEvFd,UAAUU,OAAO,GAAG3B,kBAAkBkB,UAAUJ,WAAWK,UAAU,GAAGC,SAAS,GAAGQ;IAEpF,uEAAuE;IACvE,MAAMM,eAAehC,oBAAoB;QACvCgB;QACAV;QACAC;QACAK;QACAY;QACAd;QACAG;IACF;IACA,IAAImB,aAAaC,MAAM,KAAK,GAAG;QAC7B,OAAO;IACT;IAEA,MAAMC,cAAc5B,KAAK2B,MAAM;IAE/B,qBACE,KAACvC;QAAOyC,WAAWT;kBACjB,cAAA,KAACjC;YACC0B,KAAKC;YACLgB,IAAI,CAACC,QAAUtC,iBAAiBsC,OAAOzB,WAAWkB;YAClDQ,OAAO;gBACLvB,WAAWA,UAAUU,OAAO;YAC9B;sBAEA,cAAA,MAAC9B;gBAAM4C,SAAS;;kCACd,KAACtC;wBACC+B,cAAcA;wBACdE,aAAaA;wBACb1B,eAAeA;wBACfa,iBAAiBA;wBACjBR,eAAeA;wBACf2B,gBAAgB,CAACC,UAAY3B,iBAAiB2B;wBAC9C9B,cAAcA;;kCAEhB,KAACT;wBAAewC,QAAQV;wBAAcvB,YAAYA;;;;;;AAK5D,GAAG"}
@@ -57,14 +57,7 @@ type ZREventProperties = {
57
57
  zrEventControl?: 'no_globalout' | 'only_globalout';
58
58
  zrByTouch?: boolean;
59
59
  };
60
- export type ZRRawMouseEvent = (MouseEvent | PointerEvent) & ZREventProperties;
61
- type ZRBrowser = {
62
- ie: RegExpMatchArray | null;
63
- edge: RegExpMatchArray | null;
64
- };
65
- export declare const browser: ZRBrowser;
66
- export declare const pointerEventsSupported: boolean | "" | RegExpMatchArray | null | undefined;
67
- export declare const trackingEventName: string;
60
+ export type ZRRawMouseEvent = MouseEvent & ZREventProperties;
68
61
  export declare const useMousePosition: () => CursorData['coords'];
69
62
  export type TooltipConfig = {
70
63
  wrapLabels: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"tooltip-model.d.ts","sourceRoot":"","sources":["../../src/TimeSeriesTooltip/tooltip-model.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEpD,eAAO,MAAM,iBAAiB,MAAM,CAAC;AACrC,eAAO,MAAM,iBAAiB,MAAM,CAAC;AACrC,eAAO,MAAM,kBAAkB,MAAM,CAAC;AACtC,eAAO,MAAM,wBAAwB,QAA0B,CAAC;AAChE,eAAO,MAAM,+BAA+B,OAAO,CAAC;AACpD,eAAO,MAAM,eAAe,IAAI,CAAC;AAEjC,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAExC,eAAO,MAAM,yBAAyB,qCAAqC,CAAC;AAC5E,eAAO,MAAM,6BAA6B,iDAAiD,CAAC;AAE5F,eAAO,MAAM,yBAAyB,YAAY,CAAC;AAEnD,eAAO,MAAM,mBAAmB,qBAQ9B,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;CAa7B,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,iBAAsB,CAAC;AAExD;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,CAAC,CAAC,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,UAAU;IACzB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,UAAU,CAAC;IACnB,UAAU,EAAE,YAAY,CAAC;IACzB,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,aAAa,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACxC,MAAM,EAAE,UAAU,CAAC;CACpB;AAED,KAAK,iBAAiB,GAAG;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,cAAc,GAAG,gBAAgB,CAAC;IACnD,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,CAAC,UAAU,GAAG,YAAY,CAAC,GAAG,iBAAiB,CAAC;AAE9E,KAAK,SAAS,GAAG;IACf,EAAE,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC5B,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAAC;CAC/B,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,SAKrB,CAAC;AAEF,eAAO,MAAM,sBAAsB,oDACmE,CAAC;AAEvG,eAAO,MAAM,iBAAiB,QAAuD,CAAC;AAEtF,eAAO,MAAM,gBAAgB,QAAO,UAAU,CAAC,QAAQ,CAqCtD,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,aAGpC,CAAC;AAEF,eAAO,MAAM,qBAAqB,uBAAuB,CAAC;AAE1D,eAAO,MAAM,uBAAuB,yBAAyB,CAAC"}
1
+ {"version":3,"file":"tooltip-model.d.ts","sourceRoot":"","sources":["../../src/TimeSeriesTooltip/tooltip-model.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEpD,eAAO,MAAM,iBAAiB,MAAM,CAAC;AACrC,eAAO,MAAM,iBAAiB,MAAM,CAAC;AACrC,eAAO,MAAM,kBAAkB,MAAM,CAAC;AACtC,eAAO,MAAM,wBAAwB,QAA0B,CAAC;AAChE,eAAO,MAAM,+BAA+B,OAAO,CAAC;AACpD,eAAO,MAAM,eAAe,IAAI,CAAC;AAEjC,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAExC,eAAO,MAAM,yBAAyB,qCAAqC,CAAC;AAC5E,eAAO,MAAM,6BAA6B,iDAAiD,CAAC;AAE5F,eAAO,MAAM,yBAAyB,YAAY,CAAC;AAEnD,eAAO,MAAM,mBAAmB,qBAQ9B,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;CAa7B,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,iBAAsB,CAAC;AAExD;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,CAAC,CAAC,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,UAAU;IACzB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,UAAU,CAAC;IACnB,UAAU,EAAE,YAAY,CAAC;IACzB,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,aAAa,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACxC,MAAM,EAAE,UAAU,CAAC;CACpB;AAED,KAAK,iBAAiB,GAAG;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,cAAc,GAAG,gBAAgB,CAAC;IACnD,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,iBAAiB,CAAC;AAE7D,eAAO,MAAM,gBAAgB,QAAO,UAAU,CAAC,QAAQ,CAkCtD,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,aAGpC,CAAC;AAEF,eAAO,MAAM,qBAAqB,uBAAuB,CAAC;AAE1D,eAAO,MAAM,uBAAuB,yBAAyB,CAAC"}
@@ -45,14 +45,6 @@ export const defaultCursorData = {
45
45
  chartWidth: 0
46
46
  };
47
47
  export const EMPTY_TOOLTIP_DATA = [];
48
- export const browser = {
49
- // IE 11 Trident/7.0; rv:11.0
50
- ie: navigator.userAgent.match(/MSIE\s([\d.]+)/) || navigator.userAgent.match(/Trident\/.+?rv:(([\d.]+))/),
51
- // IE 12 and 12+
52
- edge: navigator.userAgent.match(/Edge?\/([\d.]+)/)
53
- };
54
- export const pointerEventsSupported = 'onpointerdown' in window && (browser.edge || browser.ie && browser.ie[1] && +browser.ie[1] >= 11);
55
- export const trackingEventName = pointerEventsSupported ? 'pointermove' : 'mousemove';
56
48
  export const useMousePosition = ()=>{
57
49
  const [coords, setCoords] = useState(null);
58
50
  useEffect(()=>{
@@ -67,22 +59,20 @@ export const useMousePosition = ()=>{
67
59
  y: e.clientY
68
60
  },
69
61
  plotCanvas: {
70
- // Always use zrender mousemove coords since they handle browser inconsistencies for us
62
+ // Default to zrender mousemove coords since they handle browser inconsistencies for us
71
63
  // ex: Firefox and Chrome have slightly different implementations of offsetX and offsetY
72
64
  // more info: https://github.com/ecomfe/zrender/blob/5.5.0/src/core/event.ts#L46-L120
73
- x: e.zrX,
74
- y: e.zrY
65
+ // Fallback to offsetX and offsetY to ensure tooltip works correctly in Edge
66
+ x: e.zrX ?? e.offsetX,
67
+ y: e.zrY ?? e.offsetY
75
68
  },
76
69
  // necessary to check whether cursor target matches correct chart canvas (since each chart has its own mousemove listener)
77
70
  target: e.target
78
71
  });
79
72
  };
80
- // Devices that both enabled touch and mouse don't trigger touch events correctly
81
- // which leads to missing zrender mousemove coordinates
82
- // {@link https://github.com/ecomfe/zrender/blob/ae8cfaae186e6c1bf66b5dc431b2cdda5e67dacf/src/dom/HandlerProxy.ts#L423-L428 }
83
- window.addEventListener(trackingEventName, setFromEvent);
73
+ window.addEventListener('mousemove', setFromEvent);
84
74
  return ()=>{
85
- window.removeEventListener(trackingEventName, setFromEvent);
75
+ window.removeEventListener('mousemove', setFromEvent);
86
76
  };
87
77
  }, []);
88
78
  return coords;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/TimeSeriesTooltip/tooltip-model.ts"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { useEffect, useState } from 'react';\nimport { NearbySeriesArray } from './nearby-series';\n\nexport const TOOLTIP_MIN_WIDTH = 375;\nexport const TOOLTIP_MAX_WIDTH = 650;\nexport const TOOLTIP_MAX_HEIGHT = 650;\nexport const TOOLTIP_LABELS_MAX_WIDTH = TOOLTIP_MAX_WIDTH - 150;\nexport const TOOLTIP_ADJUST_Y_POS_MULTIPLIER = 0.75;\nexport const TOOLTIP_PADDING = 8;\n\nexport const FALLBACK_CHART_WIDTH = 750;\n\nexport const NEARBY_SERIES_DESCRIPTION = 'nearby series showing in tooltip';\nexport const EMPHASIZED_SERIES_DESCRIPTION = 'emphasized series showing as bold in tooltip';\n\nexport const TOOLTIP_BG_COLOR_FALLBACK = '#2E313E';\n\nexport const TOOLTIP_DATE_FORMAT = new Intl.DateTimeFormat(undefined, {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n hour: 'numeric',\n minute: 'numeric',\n second: 'numeric',\n hour12: true,\n});\n\nexport const defaultCursorData = {\n coords: {\n plotCanvas: {\n x: 0,\n y: 0,\n },\n zrender: {\n x: 0,\n y: 0,\n },\n target: null,\n },\n chartWidth: 0,\n};\n\nexport const EMPTY_TOOLTIP_DATA: NearbySeriesArray = [];\n\n/**\n * ECharts is built with zrender, zrX and zrY are undefined when not hovering over a chart canvas\n */\nexport interface ZRCoordinate {\n x?: number;\n y?: number;\n}\n\nexport interface Coordinate {\n x: number;\n y: number;\n}\n\nexport interface CursorCoordinates {\n page: Coordinate;\n client: Coordinate;\n plotCanvas: ZRCoordinate;\n target: EventTarget | null;\n}\n\nexport interface CursorData {\n coords: CursorCoordinates | null;\n chartWidth?: number;\n}\n\nexport interface TooltipData {\n focusedSeries: NearbySeriesArray | null;\n cursor: CursorData;\n}\n\ntype ZREventProperties = {\n zrX?: number;\n zrY?: number;\n zrDelta?: number;\n zrEventControl?: 'no_globalout' | 'only_globalout';\n zrByTouch?: boolean;\n};\n\nexport type ZRRawMouseEvent = (MouseEvent | PointerEvent) & ZREventProperties;\n\ntype ZRBrowser = {\n ie: RegExpMatchArray | null;\n edge: RegExpMatchArray | null;\n};\n\nexport const browser: ZRBrowser = {\n // IE 11 Trident/7.0; rv:11.0\n ie: navigator.userAgent.match(/MSIE\\s([\\d.]+)/) || navigator.userAgent.match(/Trident\\/.+?rv:(([\\d.]+))/),\n // IE 12 and 12+\n edge: navigator.userAgent.match(/Edge?\\/([\\d.]+)/),\n};\n\nexport const pointerEventsSupported =\n 'onpointerdown' in window && (browser.edge || (browser.ie && browser.ie[1] && +browser.ie[1] >= 11));\n\nexport const trackingEventName = pointerEventsSupported ? 'pointermove' : 'mousemove';\n\nexport const useMousePosition = (): CursorData['coords'] => {\n const [coords, setCoords] = useState<CursorData['coords']>(null);\n\n useEffect(() => {\n const setFromEvent = (e: ZRRawMouseEvent): void => {\n return setCoords({\n page: {\n x: e.pageX,\n y: e.pageY,\n },\n client: {\n x: e.clientX,\n y: e.clientY,\n },\n plotCanvas: {\n // Always use zrender mousemove coords since they handle browser inconsistencies for us\n // ex: Firefox and Chrome have slightly different implementations of offsetX and offsetY\n // more info: https://github.com/ecomfe/zrender/blob/5.5.0/src/core/event.ts#L46-L120\n x: e.zrX,\n y: e.zrY,\n },\n // necessary to check whether cursor target matches correct chart canvas (since each chart has its own mousemove listener)\n target: e.target,\n });\n };\n\n // Devices that both enabled touch and mouse don't trigger touch events correctly\n // which leads to missing zrender mousemove coordinates\n // {@link https://github.com/ecomfe/zrender/blob/ae8cfaae186e6c1bf66b5dc431b2cdda5e67dacf/src/dom/HandlerProxy.ts#L423-L428 }\n window.addEventListener(trackingEventName, setFromEvent);\n\n return (): void => {\n window.removeEventListener(trackingEventName, setFromEvent);\n };\n }, []);\n\n return coords;\n};\n\nexport type TooltipConfig = {\n wrapLabels: boolean;\n hidden?: boolean;\n enablePinning?: boolean;\n};\n\nexport const DEFAULT_TOOLTIP_CONFIG: TooltipConfig = {\n wrapLabels: true,\n enablePinning: true,\n};\n\nexport const PIN_TOOLTIP_HELP_TEXT = 'Click chart to pin';\n\nexport const UNPIN_TOOLTIP_HELP_TEXT = 'Click chart to unpin';\n"],"names":["useEffect","useState","TOOLTIP_MIN_WIDTH","TOOLTIP_MAX_WIDTH","TOOLTIP_MAX_HEIGHT","TOOLTIP_LABELS_MAX_WIDTH","TOOLTIP_ADJUST_Y_POS_MULTIPLIER","TOOLTIP_PADDING","FALLBACK_CHART_WIDTH","NEARBY_SERIES_DESCRIPTION","EMPHASIZED_SERIES_DESCRIPTION","TOOLTIP_BG_COLOR_FALLBACK","TOOLTIP_DATE_FORMAT","Intl","DateTimeFormat","undefined","year","month","day","hour","minute","second","hour12","defaultCursorData","coords","plotCanvas","x","y","zrender","target","chartWidth","EMPTY_TOOLTIP_DATA","browser","ie","navigator","userAgent","match","edge","pointerEventsSupported","window","trackingEventName","useMousePosition","setCoords","setFromEvent","e","page","pageX","pageY","client","clientX","clientY","zrX","zrY","addEventListener","removeEventListener","DEFAULT_TOOLTIP_CONFIG","wrapLabels","enablePinning","PIN_TOOLTIP_HELP_TEXT","UNPIN_TOOLTIP_HELP_TEXT"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC,SAASA,SAAS,EAAEC,QAAQ,QAAQ,QAAQ;AAG5C,OAAO,MAAMC,oBAAoB,IAAI;AACrC,OAAO,MAAMC,oBAAoB,IAAI;AACrC,OAAO,MAAMC,qBAAqB,IAAI;AACtC,OAAO,MAAMC,2BAA2BF,oBAAoB,IAAI;AAChE,OAAO,MAAMG,kCAAkC,KAAK;AACpD,OAAO,MAAMC,kBAAkB,EAAE;AAEjC,OAAO,MAAMC,uBAAuB,IAAI;AAExC,OAAO,MAAMC,4BAA4B,mCAAmC;AAC5E,OAAO,MAAMC,gCAAgC,+CAA+C;AAE5F,OAAO,MAAMC,4BAA4B,UAAU;AAEnD,OAAO,MAAMC,sBAAsB,IAAIC,KAAKC,cAAc,CAACC,WAAW;IACpEC,MAAM;IACNC,OAAO;IACPC,KAAK;IACLC,MAAM;IACNC,QAAQ;IACRC,QAAQ;IACRC,QAAQ;AACV,GAAG;AAEH,OAAO,MAAMC,oBAAoB;IAC/BC,QAAQ;QACNC,YAAY;YACVC,GAAG;YACHC,GAAG;QACL;QACAC,SAAS;YACPF,GAAG;YACHC,GAAG;QACL;QACAE,QAAQ;IACV;IACAC,YAAY;AACd,EAAE;AAEF,OAAO,MAAMC,qBAAwC,EAAE,CAAC;AA+CxD,OAAO,MAAMC,UAAqB;IAChC,6BAA6B;IAC7BC,IAAIC,UAAUC,SAAS,CAACC,KAAK,CAAC,qBAAqBF,UAAUC,SAAS,CAACC,KAAK,CAAC;IAC7E,gBAAgB;IAChBC,MAAMH,UAAUC,SAAS,CAACC,KAAK,CAAC;AAClC,EAAE;AAEF,OAAO,MAAME,yBACX,mBAAmBC,UAAWP,CAAAA,QAAQK,IAAI,IAAKL,QAAQC,EAAE,IAAID,QAAQC,EAAE,CAAC,EAAE,IAAI,CAACD,QAAQC,EAAE,CAAC,EAAE,IAAI,EAAE,EAAG;AAEvG,OAAO,MAAMO,oBAAoBF,yBAAyB,gBAAgB,YAAY;AAEtF,OAAO,MAAMG,mBAAmB;IAC9B,MAAM,CAACjB,QAAQkB,UAAU,GAAGzC,SAA+B;IAE3DD,UAAU;QACR,MAAM2C,eAAe,CAACC;YACpB,OAAOF,UAAU;gBACfG,MAAM;oBACJnB,GAAGkB,EAAEE,KAAK;oBACVnB,GAAGiB,EAAEG,KAAK;gBACZ;gBACAC,QAAQ;oBACNtB,GAAGkB,EAAEK,OAAO;oBACZtB,GAAGiB,EAAEM,OAAO;gBACd;gBACAzB,YAAY;oBACV,uFAAuF;oBACvF,wFAAwF;oBACxF,qFAAqF;oBACrFC,GAAGkB,EAAEO,GAAG;oBACRxB,GAAGiB,EAAEQ,GAAG;gBACV;gBACA,0HAA0H;gBAC1HvB,QAAQe,EAAEf,MAAM;YAClB;QACF;QAEA,iFAAiF;QACjF,uDAAuD;QACvD,6HAA6H;QAC7HU,OAAOc,gBAAgB,CAACb,mBAAmBG;QAE3C,OAAO;YACLJ,OAAOe,mBAAmB,CAACd,mBAAmBG;QAChD;IACF,GAAG,EAAE;IAEL,OAAOnB;AACT,EAAE;AAQF,OAAO,MAAM+B,yBAAwC;IACnDC,YAAY;IACZC,eAAe;AACjB,EAAE;AAEF,OAAO,MAAMC,wBAAwB,qBAAqB;AAE1D,OAAO,MAAMC,0BAA0B,uBAAuB"}
1
+ {"version":3,"sources":["../../src/TimeSeriesTooltip/tooltip-model.ts"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { useEffect, useState } from 'react';\nimport { NearbySeriesArray } from './nearby-series';\n\nexport const TOOLTIP_MIN_WIDTH = 375;\nexport const TOOLTIP_MAX_WIDTH = 650;\nexport const TOOLTIP_MAX_HEIGHT = 650;\nexport const TOOLTIP_LABELS_MAX_WIDTH = TOOLTIP_MAX_WIDTH - 150;\nexport const TOOLTIP_ADJUST_Y_POS_MULTIPLIER = 0.75;\nexport const TOOLTIP_PADDING = 8;\n\nexport const FALLBACK_CHART_WIDTH = 750;\n\nexport const NEARBY_SERIES_DESCRIPTION = 'nearby series showing in tooltip';\nexport const EMPHASIZED_SERIES_DESCRIPTION = 'emphasized series showing as bold in tooltip';\n\nexport const TOOLTIP_BG_COLOR_FALLBACK = '#2E313E';\n\nexport const TOOLTIP_DATE_FORMAT = new Intl.DateTimeFormat(undefined, {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n hour: 'numeric',\n minute: 'numeric',\n second: 'numeric',\n hour12: true,\n});\n\nexport const defaultCursorData = {\n coords: {\n plotCanvas: {\n x: 0,\n y: 0,\n },\n zrender: {\n x: 0,\n y: 0,\n },\n target: null,\n },\n chartWidth: 0,\n};\n\nexport const EMPTY_TOOLTIP_DATA: NearbySeriesArray = [];\n\n/**\n * ECharts is built with zrender, zrX and zrY are undefined when not hovering over a chart canvas\n */\nexport interface ZRCoordinate {\n x?: number;\n y?: number;\n}\n\nexport interface Coordinate {\n x: number;\n y: number;\n}\n\nexport interface CursorCoordinates {\n page: Coordinate;\n client: Coordinate;\n plotCanvas: ZRCoordinate;\n target: EventTarget | null;\n}\n\nexport interface CursorData {\n coords: CursorCoordinates | null;\n chartWidth?: number;\n}\n\nexport interface TooltipData {\n focusedSeries: NearbySeriesArray | null;\n cursor: CursorData;\n}\n\ntype ZREventProperties = {\n zrX?: number;\n zrY?: number;\n zrDelta?: number;\n zrEventControl?: 'no_globalout' | 'only_globalout';\n zrByTouch?: boolean;\n};\n\nexport type ZRRawMouseEvent = MouseEvent & ZREventProperties;\n\nexport const useMousePosition = (): CursorData['coords'] => {\n const [coords, setCoords] = useState<CursorData['coords']>(null);\n\n useEffect(() => {\n const setFromEvent = (e: ZRRawMouseEvent): void => {\n return setCoords({\n page: {\n x: e.pageX,\n y: e.pageY,\n },\n client: {\n x: e.clientX,\n y: e.clientY,\n },\n plotCanvas: {\n // Default to zrender mousemove coords since they handle browser inconsistencies for us\n // ex: Firefox and Chrome have slightly different implementations of offsetX and offsetY\n // more info: https://github.com/ecomfe/zrender/blob/5.5.0/src/core/event.ts#L46-L120\n // Fallback to offsetX and offsetY to ensure tooltip works correctly in Edge\n x: e.zrX ?? e.offsetX,\n y: e.zrY ?? e.offsetY,\n },\n // necessary to check whether cursor target matches correct chart canvas (since each chart has its own mousemove listener)\n target: e.target,\n });\n };\n window.addEventListener('mousemove', setFromEvent);\n\n return (): void => {\n window.removeEventListener('mousemove', setFromEvent);\n };\n }, []);\n\n return coords;\n};\n\nexport type TooltipConfig = {\n wrapLabels: boolean;\n hidden?: boolean;\n enablePinning?: boolean;\n};\n\nexport const DEFAULT_TOOLTIP_CONFIG: TooltipConfig = {\n wrapLabels: true,\n enablePinning: true,\n};\n\nexport const PIN_TOOLTIP_HELP_TEXT = 'Click chart to pin';\n\nexport const UNPIN_TOOLTIP_HELP_TEXT = 'Click chart to unpin';\n"],"names":["useEffect","useState","TOOLTIP_MIN_WIDTH","TOOLTIP_MAX_WIDTH","TOOLTIP_MAX_HEIGHT","TOOLTIP_LABELS_MAX_WIDTH","TOOLTIP_ADJUST_Y_POS_MULTIPLIER","TOOLTIP_PADDING","FALLBACK_CHART_WIDTH","NEARBY_SERIES_DESCRIPTION","EMPHASIZED_SERIES_DESCRIPTION","TOOLTIP_BG_COLOR_FALLBACK","TOOLTIP_DATE_FORMAT","Intl","DateTimeFormat","undefined","year","month","day","hour","minute","second","hour12","defaultCursorData","coords","plotCanvas","x","y","zrender","target","chartWidth","EMPTY_TOOLTIP_DATA","useMousePosition","setCoords","setFromEvent","e","page","pageX","pageY","client","clientX","clientY","zrX","offsetX","zrY","offsetY","window","addEventListener","removeEventListener","DEFAULT_TOOLTIP_CONFIG","wrapLabels","enablePinning","PIN_TOOLTIP_HELP_TEXT","UNPIN_TOOLTIP_HELP_TEXT"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC,SAASA,SAAS,EAAEC,QAAQ,QAAQ,QAAQ;AAG5C,OAAO,MAAMC,oBAAoB,IAAI;AACrC,OAAO,MAAMC,oBAAoB,IAAI;AACrC,OAAO,MAAMC,qBAAqB,IAAI;AACtC,OAAO,MAAMC,2BAA2BF,oBAAoB,IAAI;AAChE,OAAO,MAAMG,kCAAkC,KAAK;AACpD,OAAO,MAAMC,kBAAkB,EAAE;AAEjC,OAAO,MAAMC,uBAAuB,IAAI;AAExC,OAAO,MAAMC,4BAA4B,mCAAmC;AAC5E,OAAO,MAAMC,gCAAgC,+CAA+C;AAE5F,OAAO,MAAMC,4BAA4B,UAAU;AAEnD,OAAO,MAAMC,sBAAsB,IAAIC,KAAKC,cAAc,CAACC,WAAW;IACpEC,MAAM;IACNC,OAAO;IACPC,KAAK;IACLC,MAAM;IACNC,QAAQ;IACRC,QAAQ;IACRC,QAAQ;AACV,GAAG;AAEH,OAAO,MAAMC,oBAAoB;IAC/BC,QAAQ;QACNC,YAAY;YACVC,GAAG;YACHC,GAAG;QACL;QACAC,SAAS;YACPF,GAAG;YACHC,GAAG;QACL;QACAE,QAAQ;IACV;IACAC,YAAY;AACd,EAAE;AAEF,OAAO,MAAMC,qBAAwC,EAAE,CAAC;AA0CxD,OAAO,MAAMC,mBAAmB;IAC9B,MAAM,CAACR,QAAQS,UAAU,GAAGhC,SAA+B;IAE3DD,UAAU;QACR,MAAMkC,eAAe,CAACC;YACpB,OAAOF,UAAU;gBACfG,MAAM;oBACJV,GAAGS,EAAEE,KAAK;oBACVV,GAAGQ,EAAEG,KAAK;gBACZ;gBACAC,QAAQ;oBACNb,GAAGS,EAAEK,OAAO;oBACZb,GAAGQ,EAAEM,OAAO;gBACd;gBACAhB,YAAY;oBACV,uFAAuF;oBACvF,wFAAwF;oBACxF,qFAAqF;oBACrF,4EAA4E;oBAC5EC,GAAGS,EAAEO,GAAG,IAAIP,EAAEQ,OAAO;oBACrBhB,GAAGQ,EAAES,GAAG,IAAIT,EAAEU,OAAO;gBACvB;gBACA,0HAA0H;gBAC1HhB,QAAQM,EAAEN,MAAM;YAClB;QACF;QACAiB,OAAOC,gBAAgB,CAAC,aAAab;QAErC,OAAO;YACLY,OAAOE,mBAAmB,CAAC,aAAad;QAC1C;IACF,GAAG,EAAE;IAEL,OAAOV;AACT,EAAE;AAQF,OAAO,MAAMyB,yBAAwC;IACnDC,YAAY;IACZC,eAAe;AACjB,EAAE;AAEF,OAAO,MAAMC,wBAAwB,qBAAqB;AAE1D,OAAO,MAAMC,0BAA0B,uBAAuB"}
@@ -3,7 +3,7 @@ import { CursorCoordinates, CursorData } from './tooltip-model';
3
3
  /**
4
4
  * Determine position of tooltip depending on chart dimensions and the number of focused series
5
5
  */
6
- export declare function assembleTransform(mousePos: CursorData['coords'], chartWidth: number, pinnedPos: CursorCoordinates | null, tooltipHeight: number, tooltipWidth: number, containerElement?: Element | null): string | undefined;
6
+ export declare function assembleTransform(mousePos: CursorData['coords'], pinnedPos: CursorCoordinates | null, tooltipHeight: number, tooltipWidth: number, containerElement?: Element | null): string | undefined;
7
7
  /**
8
8
  * Helper for tooltip positioning styles
9
9
  */
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/TimeSeriesTooltip/utils.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EACL,iBAAiB,EACjB,UAAU,EAOX,MAAM,iBAAiB,CAAC;AAEzB;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,UAAU,CAAC,QAAQ,CAAC,EAC9B,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,iBAAiB,GAAG,IAAI,EACnC,aAAa,EAAE,MAAM,EACrB,YAAY,EAAE,MAAM,EACpB,gBAAgB,CAAC,EAAE,OAAO,GAAG,IAAI,GAChC,MAAM,GAAG,SAAS,CAgDpB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,iBAAiB,GAAG,IAAI,EACnC,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAwBzB"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/TimeSeriesTooltip/utils.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EACL,iBAAiB,EACjB,UAAU,EAMX,MAAM,iBAAiB,CAAC;AAEzB;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,UAAU,CAAC,QAAQ,CAAC,EAC9B,SAAS,EAAE,iBAAiB,GAAG,IAAI,EACnC,aAAa,EAAE,MAAM,EACrB,YAAY,EAAE,MAAM,EACpB,gBAAgB,CAAC,EAAE,OAAO,GAAG,IAAI,GAChC,MAAM,GAAG,SAAS,CAmDpB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,iBAAiB,GAAG,IAAI,EACnC,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAwBzB"}
@@ -10,10 +10,10 @@
10
10
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
- import { TOOLTIP_MAX_WIDTH, TOOLTIP_MAX_HEIGHT, TOOLTIP_MIN_WIDTH, TOOLTIP_ADJUST_Y_POS_MULTIPLIER, TOOLTIP_BG_COLOR_FALLBACK, TOOLTIP_PADDING } from './tooltip-model';
13
+ import { TOOLTIP_MAX_WIDTH, TOOLTIP_MAX_HEIGHT, TOOLTIP_MIN_WIDTH, TOOLTIP_BG_COLOR_FALLBACK, TOOLTIP_PADDING } from './tooltip-model';
14
14
  /**
15
15
  * Determine position of tooltip depending on chart dimensions and the number of focused series
16
- */ export function assembleTransform(mousePos, chartWidth, pinnedPos, tooltipHeight, tooltipWidth, containerElement) {
16
+ */ export function assembleTransform(mousePos, pinnedPos, tooltipHeight, tooltipWidth, containerElement) {
17
17
  if (mousePos === null) {
18
18
  return undefined;
19
19
  }
@@ -23,33 +23,37 @@ import { TOOLTIP_MAX_WIDTH, TOOLTIP_MAX_HEIGHT, TOOLTIP_MIN_WIDTH, TOOLTIP_ADJUS
23
23
  mousePos = pinnedPos;
24
24
  }
25
25
  if (mousePos.plotCanvas.x === undefined) return undefined;
26
- // By default, tooltip is located in a Portal attached to the body.
27
- // Using page coordinates instead of viewport ensures the tooltip is
28
- // absolutely positioned correctly as the user scrolls
29
- let x = mousePos.page.x;
26
+ let x = mousePos.page.x + cursorPaddingX; // Default to right side of the cursor
30
27
  let y = mousePos.page.y + cursorPaddingY;
31
- // If containerElement is defined, tooltip is attached to the containerElement instead.
32
- let containerRect;
28
+ // If containerElement is defined, adjust coordinates relative to the container
33
29
  if (containerElement) {
34
- // get the container's position relative to viewport
35
- containerRect = containerElement.getBoundingClientRect();
36
- // calculate the mouse position relative to container
30
+ const containerRect = containerElement.getBoundingClientRect();
37
31
  x = x - containerRect.left + containerElement.scrollLeft;
38
32
  y = y - containerRect.top + containerElement.scrollTop;
39
- }
40
- if (mousePos.client.y + tooltipHeight + cursorPaddingY > window.innerHeight) {
41
- // adjust so tooltip does not get cut off at bottom of chart
42
- // multiplier ensures tooltip isn't overly adjusted and gets cut off at the top of the viewport
43
- y = y - tooltipHeight * TOOLTIP_ADJUST_Y_POS_MULTIPLIER;
44
- // If y is now above of the top of containerElement, set y close to 0 so tooltip does not get cut off
45
- if (containerRect && y < containerRect.top) {
46
- y = TOOLTIP_PADDING / 2; // leaves room for some padding around tooltip
33
+ // Ensure tooltip does not go out of the container's bottom
34
+ const containerBottom = containerRect.top + containerElement.scrollHeight;
35
+ if (y + tooltipHeight > containerBottom) {
36
+ y = Math.max(containerBottom - tooltipHeight - cursorPaddingY, TOOLTIP_PADDING / 2);
37
+ }
38
+ } else {
39
+ // Ensure tooltip does not go out of the screen on the bottom
40
+ if (y + tooltipHeight > window.innerHeight + window.scrollY) {
41
+ y = Math.max(window.innerHeight + window.scrollY - tooltipHeight - cursorPaddingY, TOOLTIP_PADDING / 2);
47
42
  }
48
43
  }
49
- // use tooltip width to determine when to repos from right to left
50
- const xPosAdjustThreshold = chartWidth - tooltipWidth * 0.9;
51
- // reposition so tooltip is never too close to right side of chart or left side of browser window
52
- return mousePos.plotCanvas.x > xPosAdjustThreshold && x > TOOLTIP_MAX_WIDTH ? `translate3d(${x - cursorPaddingX}px, ${y}px, 0) translateX(-100%)` : `translate3d(${x + cursorPaddingX}px, ${y}px, 0)`;
44
+ // Ensure tooltip does not go out of the screen on the right
45
+ if (x + tooltipWidth > window.innerWidth) {
46
+ x = mousePos.page.x - tooltipWidth - cursorPaddingX; // Move to the left of the cursor
47
+ }
48
+ // Ensure tooltip does not go out of the screen on the left
49
+ if (x < cursorPaddingX) {
50
+ x = cursorPaddingX;
51
+ }
52
+ // Ensure tooltip does not go out of the screen on the top
53
+ if (y < TOOLTIP_PADDING / 2) {
54
+ y = TOOLTIP_PADDING / 2;
55
+ }
56
+ return `translate3d(${x}px, ${y}px, 0)`;
53
57
  }
54
58
  /**
55
59
  * Helper for tooltip positioning styles