@perses-dev/components 0.53.0 → 0.53.1
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.
- package/dist/ThresholdsEditor/ThresholdsEditor.d.ts.map +1 -1
- package/dist/ThresholdsEditor/ThresholdsEditor.js +10 -13
- package/dist/ThresholdsEditor/ThresholdsEditor.js.map +1 -1
- package/dist/TimeRangeSelector/DateTimeRangePicker.d.ts.map +1 -1
- package/dist/TimeRangeSelector/DateTimeRangePicker.js +15 -18
- package/dist/TimeRangeSelector/DateTimeRangePicker.js.map +1 -1
- package/dist/TimeZoneSelector.js +1 -1
- package/dist/TimeZoneSelector.js.map +1 -1
- package/dist/cjs/ThresholdsEditor/ThresholdsEditor.js +9 -12
- package/dist/cjs/TimeRangeSelector/DateTimeRangePicker.js +14 -17
- package/dist/cjs/TimeZoneSelector.js +1 -1
- package/dist/cjs/utils/format.js +4 -2
- package/dist/utils/format.js +4 -2
- package/dist/utils/format.js.map +1 -1
- package/package.json +5 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThresholdsEditor.d.ts","sourceRoot":"","sources":["../../src/ThresholdsEditor/ThresholdsEditor.tsx"],"names":[],"mappings":"AAaA,OAAc,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"ThresholdsEditor.d.ts","sourceRoot":"","sources":["../../src/ThresholdsEditor/ThresholdsEditor.tsx"],"names":[],"mappings":"AAaA,OAAc,EAAE,YAAY,EAAqB,MAAM,OAAO,CAAC;AAK/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAOpD,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,CAAC,UAAU,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACjD,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAID,wBAAgB,gBAAgB,CAAC,EAC/B,UAAU,EACV,QAAQ,EACR,WAAW,EACX,kBAAkB,GACnB,EAAE,qBAAqB,GAAG,YAAY,CA0LtC"}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
14
|
-
import React, { useEffect, useRef
|
|
14
|
+
import React, { useEffect, useRef } from 'react';
|
|
15
15
|
import { produce } from 'immer';
|
|
16
16
|
import { IconButton, ToggleButton, ToggleButtonGroup, Typography } from '@mui/material';
|
|
17
17
|
import PlusIcon from 'mdi-material-ui/Plus';
|
|
@@ -26,12 +26,7 @@ export function ThresholdsEditor({ thresholds, onChange, hideDefault, disablePer
|
|
|
26
26
|
const chartsTheme = useChartsTheme();
|
|
27
27
|
const { thresholds: { defaultColor, palette } } = chartsTheme;
|
|
28
28
|
const defaultThresholdColor = thresholds?.defaultColor ?? defaultColor;
|
|
29
|
-
const
|
|
30
|
-
useEffect(()=>{
|
|
31
|
-
setSteps(thresholds?.steps);
|
|
32
|
-
}, [
|
|
33
|
-
thresholds?.steps
|
|
34
|
-
]);
|
|
29
|
+
const steps = thresholds?.steps;
|
|
35
30
|
// every time a new threshold is added, we want to focus the recently added input
|
|
36
31
|
const recentlyAddedInputRef = useRef(null);
|
|
37
32
|
const focusRef = useRef(false);
|
|
@@ -43,12 +38,14 @@ export function ThresholdsEditor({ thresholds, onChange, hideDefault, disablePer
|
|
|
43
38
|
steps?.length
|
|
44
39
|
]);
|
|
45
40
|
const handleThresholdValueChange = (e, i)=>{
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
41
|
+
if (thresholds !== undefined) {
|
|
42
|
+
onChange(produce(thresholds, (draft)=>{
|
|
43
|
+
const step = draft.steps?.[i];
|
|
44
|
+
if (step) {
|
|
45
|
+
step.value = Number(e.target.value);
|
|
46
|
+
}
|
|
47
|
+
}));
|
|
48
|
+
}
|
|
52
49
|
};
|
|
53
50
|
const handleThresholdColorChange = (color, i)=>{
|
|
54
51
|
if (thresholds !== undefined) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/ThresholdsEditor/ThresholdsEditor.tsx"],"sourcesContent":["// Copyright 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 React, { ReactElement, useEffect, useRef, useState } from 'react';\nimport { produce } from 'immer';\nimport { IconButton, ToggleButton, ToggleButtonGroup, Typography } from '@mui/material';\nimport PlusIcon from 'mdi-material-ui/Plus';\nimport { Stack } from '@mui/system';\nimport { ThresholdOptions } from '@perses-dev/core';\nimport { useChartsTheme } from '../context/ChartsProvider';\nimport { OptionsEditorControl, OptionsEditorGroup } from '../OptionsEditorLayout';\nimport { InfoTooltip } from '../InfoTooltip';\nimport { OptionsColorPicker } from '../ColorPicker/OptionsColorPicker';\nimport { ThresholdInput } from './ThresholdInput';\n\nexport interface ThresholdsEditorProps {\n onChange: (thresholds: ThresholdOptions) => void;\n thresholds?: ThresholdOptions;\n hideDefault?: boolean;\n disablePercentMode?: boolean;\n}\n\nconst DEFAULT_STEP = 10;\n\nexport function ThresholdsEditor({\n thresholds,\n onChange,\n hideDefault,\n disablePercentMode,\n}: ThresholdsEditorProps): ReactElement {\n const chartsTheme = useChartsTheme();\n const {\n thresholds: { defaultColor, palette },\n } = chartsTheme;\n const defaultThresholdColor = thresholds?.defaultColor ?? defaultColor;\n\n const [steps, setSteps] = useState(thresholds?.steps);\n useEffect(() => {\n setSteps(thresholds?.steps);\n }, [thresholds?.steps]);\n\n // every time a new threshold is added, we want to focus the recently added input\n const recentlyAddedInputRef = useRef<HTMLInputElement | null>(null);\n const focusRef = useRef(false);\n useEffect(() => {\n if (!recentlyAddedInputRef.current || !focusRef.current) return;\n recentlyAddedInputRef.current?.focus();\n focusRef.current = false;\n }, [steps?.length]);\n\n const handleThresholdValueChange = (e: React.ChangeEvent<HTMLInputElement>, i: number): void => {\n setSteps(\n produce(steps, (draft) => {\n const step = draft?.[i];\n if (step) {\n step.value = Number(e.target.value);\n }\n })\n );\n };\n\n const handleThresholdColorChange = (color: string, i: number): void => {\n if (thresholds !== undefined) {\n onChange(\n produce(thresholds, (draft) => {\n if (draft.steps !== undefined) {\n const step = draft.steps[i];\n if (step) {\n step.color = color;\n }\n }\n })\n );\n }\n };\n\n const handleDefaultColorChange = (color: string): void => {\n if (thresholds !== undefined) {\n onChange(\n produce(thresholds, (draft) => {\n draft.defaultColor = color;\n })\n );\n } else {\n onChange({\n defaultColor: color,\n });\n }\n };\n\n // sort thresholds in ascending order every time an input blurs\n const handleThresholdBlur = (): void => {\n if (steps !== undefined) {\n const sortedSteps = [...steps];\n sortedSteps.sort((a, b) => a.value - b.value);\n if (thresholds !== undefined) {\n onChange(\n produce(thresholds, (draft) => {\n draft.steps = sortedSteps;\n })\n );\n }\n }\n };\n\n const deleteThreshold = (i: number): void => {\n if (thresholds !== undefined) {\n const updatedThresholds = produce(thresholds, (draft) => {\n if (draft.steps) {\n draft.steps.splice(i, 1);\n }\n });\n onChange(updatedThresholds);\n }\n };\n\n const addThresholdInput = (): void => {\n focusRef.current = true;\n if (thresholds === undefined) {\n onChange({\n steps: [{ value: DEFAULT_STEP }],\n });\n } else if (thresholds && thresholds.steps === undefined) {\n onChange(\n produce(thresholds, (draft) => {\n draft.steps = [{ value: DEFAULT_STEP }];\n })\n );\n } else {\n onChange(\n produce(thresholds, (draft) => {\n const steps = draft.steps;\n if (steps?.length) {\n const lastStep = steps[steps.length - 1];\n const color = palette[steps.length] ?? getRandomColor(); // we will assign color from the palette first, then generate random color\n steps.push({ color, value: (lastStep?.value ?? 0) + DEFAULT_STEP }); // set new threshold value to last step value + 10\n } else if (steps) {\n steps.push({ value: DEFAULT_STEP });\n }\n })\n );\n }\n };\n\n const handleModeChange = (event: React.MouseEvent, value: string): void => {\n const mode = value === 'percent' ? 'percent' : undefined;\n if (thresholds !== undefined) {\n onChange(\n produce(thresholds, (draft) => {\n draft.mode = mode;\n })\n );\n } else {\n onChange({ mode });\n }\n };\n\n return (\n <OptionsEditorGroup\n title=\"Thresholds\"\n icon={\n <InfoTooltip description=\"Add threshold\">\n <IconButton size=\"small\" aria-label=\"add threshold\" onClick={addThresholdInput}>\n <PlusIcon />\n </IconButton>\n </InfoTooltip>\n }\n >\n <OptionsEditorControl\n label=\"Mode\"\n description=\"Percentage means thresholds relative to min & max\"\n control={\n <ToggleButtonGroup\n exclusive\n disabled={disablePercentMode}\n value={thresholds?.mode ?? 'absolute'}\n onChange={handleModeChange}\n sx={{ height: '36px', marginLeft: 'auto' }}\n >\n <ToggleButton aria-label=\"absolute\" value=\"absolute\" sx={{ fontWeight: 500 }}>\n Absolute\n </ToggleButton>\n <ToggleButton aria-label=\"percent\" value=\"percent\" sx={{ fontWeight: 500 }}>\n Percent\n </ToggleButton>\n </ToggleButtonGroup>\n }\n />\n {steps &&\n steps\n .map((step, i) => (\n <ThresholdInput\n inputRef={i === steps.length - 1 ? recentlyAddedInputRef : undefined}\n key={i}\n label={`T${i + 1}`}\n color={step.color ?? palette[i] ?? defaultThresholdColor}\n value={step.value}\n mode={thresholds?.mode}\n onColorChange={(color) => handleThresholdColorChange(color, i)}\n onChange={(e) => {\n handleThresholdValueChange(e, i);\n }}\n onDelete={() => {\n deleteThreshold(i);\n }}\n onBlur={handleThresholdBlur}\n />\n ))\n .reverse()}\n {!hideDefault && (\n <Stack flex={1} direction=\"row\" alignItems=\"center\" spacing={1}>\n <OptionsColorPicker label=\"default\" color={defaultThresholdColor} onColorChange={handleDefaultColorChange} />\n <Typography>Default</Typography>\n </Stack>\n )}\n </OptionsEditorGroup>\n );\n}\n\n// https://www.paulirish.com/2009/random-hex-color-code-snippets/\nconst getRandomColor = (): string => {\n return (\n '#' +\n Math.floor(Math.random() * 16777216)\n .toString(16)\n .padStart(6, '0')\n );\n};\n"],"names":["React","useEffect","useRef","useState","produce","IconButton","ToggleButton","ToggleButtonGroup","Typography","PlusIcon","Stack","useChartsTheme","OptionsEditorControl","OptionsEditorGroup","InfoTooltip","OptionsColorPicker","ThresholdInput","DEFAULT_STEP","ThresholdsEditor","thresholds","onChange","hideDefault","disablePercentMode","chartsTheme","defaultColor","palette","defaultThresholdColor","steps","setSteps","recentlyAddedInputRef","focusRef","current","focus","length","handleThresholdValueChange","e","i","draft","step","value","Number","target","handleThresholdColorChange","color","undefined","handleDefaultColorChange","handleThresholdBlur","sortedSteps","sort","a","b","deleteThreshold","updatedThresholds","splice","addThresholdInput","lastStep","getRandomColor","push","handleModeChange","event","mode","title","icon","description","size","aria-label","onClick","label","control","exclusive","disabled","sx","height","marginLeft","fontWeight","map","inputRef","onColorChange","onDelete","onBlur","reverse","flex","direction","alignItems","spacing","Math","floor","random","toString","padStart"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/ThresholdsEditor/ThresholdsEditor.tsx"],"sourcesContent":["// Copyright 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 React, { ReactElement, useEffect, useRef } from 'react';\nimport { produce } from 'immer';\nimport { IconButton, ToggleButton, ToggleButtonGroup, Typography } from '@mui/material';\nimport PlusIcon from 'mdi-material-ui/Plus';\nimport { Stack } from '@mui/system';\nimport { ThresholdOptions } from '@perses-dev/core';\nimport { useChartsTheme } from '../context/ChartsProvider';\nimport { OptionsEditorControl, OptionsEditorGroup } from '../OptionsEditorLayout';\nimport { InfoTooltip } from '../InfoTooltip';\nimport { OptionsColorPicker } from '../ColorPicker/OptionsColorPicker';\nimport { ThresholdInput } from './ThresholdInput';\n\nexport interface ThresholdsEditorProps {\n onChange: (thresholds: ThresholdOptions) => void;\n thresholds?: ThresholdOptions;\n hideDefault?: boolean;\n disablePercentMode?: boolean;\n}\n\nconst DEFAULT_STEP = 10;\n\nexport function ThresholdsEditor({\n thresholds,\n onChange,\n hideDefault,\n disablePercentMode,\n}: ThresholdsEditorProps): ReactElement {\n const chartsTheme = useChartsTheme();\n const {\n thresholds: { defaultColor, palette },\n } = chartsTheme;\n const defaultThresholdColor = thresholds?.defaultColor ?? defaultColor;\n\n const steps = thresholds?.steps;\n // every time a new threshold is added, we want to focus the recently added input\n const recentlyAddedInputRef = useRef<HTMLInputElement | null>(null);\n const focusRef = useRef(false);\n useEffect(() => {\n if (!recentlyAddedInputRef.current || !focusRef.current) return;\n recentlyAddedInputRef.current?.focus();\n focusRef.current = false;\n }, [steps?.length]);\n\n const handleThresholdValueChange = (e: React.ChangeEvent<HTMLInputElement>, i: number): void => {\n if (thresholds !== undefined) {\n onChange(\n produce(thresholds, (draft) => {\n const step = draft.steps?.[i];\n if (step) {\n step.value = Number(e.target.value);\n }\n })\n );\n }\n };\n\n const handleThresholdColorChange = (color: string, i: number): void => {\n if (thresholds !== undefined) {\n onChange(\n produce(thresholds, (draft) => {\n if (draft.steps !== undefined) {\n const step = draft.steps[i];\n if (step) {\n step.color = color;\n }\n }\n })\n );\n }\n };\n\n const handleDefaultColorChange = (color: string): void => {\n if (thresholds !== undefined) {\n onChange(\n produce(thresholds, (draft) => {\n draft.defaultColor = color;\n })\n );\n } else {\n onChange({\n defaultColor: color,\n });\n }\n };\n\n // sort thresholds in ascending order every time an input blurs\n const handleThresholdBlur = (): void => {\n if (steps !== undefined) {\n const sortedSteps = [...steps];\n sortedSteps.sort((a, b) => a.value - b.value);\n if (thresholds !== undefined) {\n onChange(\n produce(thresholds, (draft) => {\n draft.steps = sortedSteps;\n })\n );\n }\n }\n };\n\n const deleteThreshold = (i: number): void => {\n if (thresholds !== undefined) {\n const updatedThresholds = produce(thresholds, (draft) => {\n if (draft.steps) {\n draft.steps.splice(i, 1);\n }\n });\n onChange(updatedThresholds);\n }\n };\n\n const addThresholdInput = (): void => {\n focusRef.current = true;\n if (thresholds === undefined) {\n onChange({\n steps: [{ value: DEFAULT_STEP }],\n });\n } else if (thresholds && thresholds.steps === undefined) {\n onChange(\n produce(thresholds, (draft) => {\n draft.steps = [{ value: DEFAULT_STEP }];\n })\n );\n } else {\n onChange(\n produce(thresholds, (draft) => {\n const steps = draft.steps;\n if (steps?.length) {\n const lastStep = steps[steps.length - 1];\n const color = palette[steps.length] ?? getRandomColor(); // we will assign color from the palette first, then generate random color\n steps.push({ color, value: (lastStep?.value ?? 0) + DEFAULT_STEP }); // set new threshold value to last step value + 10\n } else if (steps) {\n steps.push({ value: DEFAULT_STEP });\n }\n })\n );\n }\n };\n\n const handleModeChange = (event: React.MouseEvent, value: string): void => {\n const mode = value === 'percent' ? 'percent' : undefined;\n if (thresholds !== undefined) {\n onChange(\n produce(thresholds, (draft) => {\n draft.mode = mode;\n })\n );\n } else {\n onChange({ mode });\n }\n };\n\n return (\n <OptionsEditorGroup\n title=\"Thresholds\"\n icon={\n <InfoTooltip description=\"Add threshold\">\n <IconButton size=\"small\" aria-label=\"add threshold\" onClick={addThresholdInput}>\n <PlusIcon />\n </IconButton>\n </InfoTooltip>\n }\n >\n <OptionsEditorControl\n label=\"Mode\"\n description=\"Percentage means thresholds relative to min & max\"\n control={\n <ToggleButtonGroup\n exclusive\n disabled={disablePercentMode}\n value={thresholds?.mode ?? 'absolute'}\n onChange={handleModeChange}\n sx={{ height: '36px', marginLeft: 'auto' }}\n >\n <ToggleButton aria-label=\"absolute\" value=\"absolute\" sx={{ fontWeight: 500 }}>\n Absolute\n </ToggleButton>\n <ToggleButton aria-label=\"percent\" value=\"percent\" sx={{ fontWeight: 500 }}>\n Percent\n </ToggleButton>\n </ToggleButtonGroup>\n }\n />\n {steps &&\n steps\n .map((step, i) => (\n <ThresholdInput\n inputRef={i === steps.length - 1 ? recentlyAddedInputRef : undefined}\n key={i}\n label={`T${i + 1}`}\n color={step.color ?? palette[i] ?? defaultThresholdColor}\n value={step.value}\n mode={thresholds?.mode}\n onColorChange={(color) => handleThresholdColorChange(color, i)}\n onChange={(e) => {\n handleThresholdValueChange(e, i);\n }}\n onDelete={() => {\n deleteThreshold(i);\n }}\n onBlur={handleThresholdBlur}\n />\n ))\n .reverse()}\n {!hideDefault && (\n <Stack flex={1} direction=\"row\" alignItems=\"center\" spacing={1}>\n <OptionsColorPicker label=\"default\" color={defaultThresholdColor} onColorChange={handleDefaultColorChange} />\n <Typography>Default</Typography>\n </Stack>\n )}\n </OptionsEditorGroup>\n );\n}\n\n// https://www.paulirish.com/2009/random-hex-color-code-snippets/\nconst getRandomColor = (): string => {\n return (\n '#' +\n Math.floor(Math.random() * 16777216)\n .toString(16)\n .padStart(6, '0')\n );\n};\n"],"names":["React","useEffect","useRef","produce","IconButton","ToggleButton","ToggleButtonGroup","Typography","PlusIcon","Stack","useChartsTheme","OptionsEditorControl","OptionsEditorGroup","InfoTooltip","OptionsColorPicker","ThresholdInput","DEFAULT_STEP","ThresholdsEditor","thresholds","onChange","hideDefault","disablePercentMode","chartsTheme","defaultColor","palette","defaultThresholdColor","steps","recentlyAddedInputRef","focusRef","current","focus","length","handleThresholdValueChange","e","i","undefined","draft","step","value","Number","target","handleThresholdColorChange","color","handleDefaultColorChange","handleThresholdBlur","sortedSteps","sort","a","b","deleteThreshold","updatedThresholds","splice","addThresholdInput","lastStep","getRandomColor","push","handleModeChange","event","mode","title","icon","description","size","aria-label","onClick","label","control","exclusive","disabled","sx","height","marginLeft","fontWeight","map","inputRef","onColorChange","onDelete","onBlur","reverse","flex","direction","alignItems","spacing","Math","floor","random","toString","padStart"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DateTimeRangePicker.d.ts","sourceRoot":"","sources":["../../src/TimeRangeSelector/DateTimeRangePicker.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"DateTimeRangePicker.d.ts","sourceRoot":"","sources":["../../src/TimeRangeSelector/DateTimeRangePicker.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAE,YAAY,EAAY,MAAM,OAAO,CAAC;AAI/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAMrD,UAAU,qBAAqB;IAC7B,gBAAgB,EAAE,iBAAiB,CAAC;IACpC,QAAQ,EAAE,CAAC,SAAS,EAAE,iBAAiB,KAAK,IAAI,CAAC;IACjD,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,wDAK7B,qBAAqB,KAAG,YAsJ1B,CAAC"}
|
|
@@ -11,13 +11,13 @@
|
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
14
|
-
import {
|
|
14
|
+
import { useState } from 'react';
|
|
15
15
|
import { Box, Stack, Typography, Button } from '@mui/material';
|
|
16
16
|
import { DateTimeField, LocalizationProvider, StaticDateTimePicker } from '@mui/x-date-pickers';
|
|
17
17
|
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFnsV3';
|
|
18
|
+
import { TZDate } from '@date-fns/tz';
|
|
18
19
|
import { ErrorBoundary } from '../ErrorBoundary';
|
|
19
20
|
import { ErrorAlert } from '../ErrorAlert';
|
|
20
|
-
import { formatWithTimeZone } from '../utils/format';
|
|
21
21
|
import { DATE_TIME_FORMAT, validateDateRange } from './utils';
|
|
22
22
|
/**
|
|
23
23
|
* Start and End datetime picker, allowing use to select a specific time range selecting two absolute dates and times.
|
|
@@ -28,18 +28,11 @@ import { DATE_TIME_FORMAT, validateDateRange } from './utils';
|
|
|
28
28
|
* @param onCancel event received when user click on cancel
|
|
29
29
|
* @constructor
|
|
30
30
|
*/ export const DateTimeRangePicker = ({ initialTimeRange, onChange, onCancel, timeZone })=>{
|
|
31
|
-
|
|
31
|
+
const stdTimeZone = [
|
|
32
|
+
'local',
|
|
33
|
+
'browser'
|
|
34
|
+
].includes(timeZone.toLowerCase()) ? Intl.DateTimeFormat().resolvedOptions().timeZone : timeZone;
|
|
32
35
|
const [timeRange, setTimeRange] = useState(initialTimeRange);
|
|
33
|
-
const timeRangeInputs = useMemo(()=>{
|
|
34
|
-
return {
|
|
35
|
-
start: formatWithTimeZone(timeRange.start, DATE_TIME_FORMAT, timeZone),
|
|
36
|
-
end: formatWithTimeZone(timeRange.end, DATE_TIME_FORMAT, timeZone)
|
|
37
|
-
};
|
|
38
|
-
}, [
|
|
39
|
-
timeRange.start,
|
|
40
|
-
timeRange.end,
|
|
41
|
-
timeZone
|
|
42
|
-
]);
|
|
43
36
|
const [showStartCalendar, setShowStartCalendar] = useState(true);
|
|
44
37
|
const changeTimeRange = (newTime, segment)=>{
|
|
45
38
|
setTimeRange((prevTimeRange)=>{
|
|
@@ -94,10 +87,11 @@ import { DATE_TIME_FORMAT, validateDateRange } from './utils';
|
|
|
94
87
|
children: "Select Start Time"
|
|
95
88
|
}),
|
|
96
89
|
/*#__PURE__*/ _jsx(StaticDateTimePicker, {
|
|
90
|
+
timezone: stdTimeZone,
|
|
97
91
|
displayStaticWrapperAs: "desktop",
|
|
98
92
|
openTo: "day",
|
|
99
93
|
disableHighlightToday: true,
|
|
100
|
-
value: timeRange.start,
|
|
94
|
+
value: new TZDate(timeRange.start, stdTimeZone),
|
|
101
95
|
onChange: (newValue)=>{
|
|
102
96
|
if (newValue === null) return;
|
|
103
97
|
onChangeStartTime(newValue);
|
|
@@ -122,11 +116,12 @@ import { DATE_TIME_FORMAT, validateDateRange } from './utils';
|
|
|
122
116
|
children: "Select End Time"
|
|
123
117
|
}),
|
|
124
118
|
/*#__PURE__*/ _jsx(StaticDateTimePicker, {
|
|
119
|
+
timezone: stdTimeZone,
|
|
125
120
|
displayStaticWrapperAs: "desktop",
|
|
126
121
|
openTo: "day",
|
|
127
122
|
disableHighlightToday: true,
|
|
128
|
-
value: timeRange.end,
|
|
129
|
-
minDateTime: timeRange.start,
|
|
123
|
+
value: new TZDate(timeRange.end, stdTimeZone),
|
|
124
|
+
minDateTime: new TZDate(timeRange.start, stdTimeZone),
|
|
130
125
|
onChange: (newValue)=>{
|
|
131
126
|
if (newValue === null) return;
|
|
132
127
|
onChangeEndTime(newValue);
|
|
@@ -149,8 +144,9 @@ import { DATE_TIME_FORMAT, validateDateRange } from './utils';
|
|
|
149
144
|
/*#__PURE__*/ _jsx(ErrorBoundary, {
|
|
150
145
|
FallbackComponent: ErrorAlert,
|
|
151
146
|
children: /*#__PURE__*/ _jsx(DateTimeField, {
|
|
147
|
+
timezone: stdTimeZone,
|
|
152
148
|
label: "Start Time",
|
|
153
|
-
value: new
|
|
149
|
+
value: new TZDate(timeRange.start, stdTimeZone),
|
|
154
150
|
onChange: (event)=>{
|
|
155
151
|
if (event) {
|
|
156
152
|
onChangeStartTime(event);
|
|
@@ -163,8 +159,9 @@ import { DATE_TIME_FORMAT, validateDateRange } from './utils';
|
|
|
163
159
|
/*#__PURE__*/ _jsx(ErrorBoundary, {
|
|
164
160
|
FallbackComponent: ErrorAlert,
|
|
165
161
|
children: /*#__PURE__*/ _jsx(DateTimeField, {
|
|
162
|
+
timezone: stdTimeZone,
|
|
166
163
|
label: "End Time",
|
|
167
|
-
value: new
|
|
164
|
+
value: new TZDate(timeRange.end, stdTimeZone),
|
|
168
165
|
onChange: (event)=>{
|
|
169
166
|
if (event) {
|
|
170
167
|
onChangeEndTime(event);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/TimeRangeSelector/DateTimeRangePicker.tsx"],"sourcesContent":["// Copyright 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, useMemo, 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 { ErrorBoundary } from '../ErrorBoundary';\nimport { ErrorAlert } from '../ErrorAlert';\nimport { formatWithTimeZone } from '../utils/format';\nimport { DATE_TIME_FORMAT, validateDateRange } from './utils';\n\ninterface AbsoluteTimeFormProps {\n initialTimeRange: AbsoluteTimeRange;\n onChange: (timeRange: AbsoluteTimeRange) => void;\n onCancel: () => void;\n timeZone: string;\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 = ({\n initialTimeRange,\n onChange,\n onCancel,\n timeZone,\n}: AbsoluteTimeFormProps): ReactElement => {\n // Time range values as dates that can be used as a time range.\n const [timeRange, setTimeRange] = useState<AbsoluteTimeRange>(initialTimeRange);\n const timeRangeInputs = useMemo<AbsoluteTimeRangeInputValue>(() => {\n return {\n start: formatWithTimeZone(timeRange.start, DATE_TIME_FORMAT, timeZone),\n end: formatWithTimeZone(timeRange.end, DATE_TIME_FORMAT, timeZone),\n };\n }, [timeRange.start, timeRange.end, timeZone]);\n\n const [showStartCalendar, setShowStartCalendar] = useState<boolean>(true);\n\n const changeTimeRange = (newTime: Date, segment: keyof AbsoluteTimeRange): void => {\n setTimeRange((prevTimeRange) => {\n return {\n ...prevTimeRange,\n [segment]: newTime,\n };\n });\n };\n\n const onChangeStartTime = (newStartTime: Date): void => {\n changeTimeRange(newStartTime, 'start');\n };\n\n const onChangeEndTime = (newEndTime: Date): void => {\n changeTimeRange(newEndTime, 'end');\n };\n\n const updateDateRange = (): { start: Date; end: Date } | undefined => {\n const newDates = {\n start: timeRange.start,\n end: timeRange.end,\n };\n const isValidDateRange = validateDateRange(newDates.start, newDates.end);\n if (isValidDateRange) {\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={timeRange.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={timeRange.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":["useMemo","useState","Box","Stack","Typography","Button","DateTimeField","LocalizationProvider","StaticDateTimePicker","AdapterDateFns","ErrorBoundary","ErrorAlert","formatWithTimeZone","DATE_TIME_FORMAT","validateDateRange","DateTimeRangePicker","initialTimeRange","onChange","onCancel","timeZone","timeRange","setTimeRange","timeRangeInputs","start","end","showStartCalendar","setShowStartCalendar","changeTimeRange","newTime","segment","prevTimeRange","onChangeStartTime","newStartTime","onChangeEndTime","newEndTime","updateDateRange","newDates","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","Date","event","onBlur","format","onClick","fullWidth"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/TimeRangeSelector/DateTimeRangePicker.tsx"],"sourcesContent":["// Copyright 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 { TZDate } from '@date-fns/tz';\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 timeZone: 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 = ({\n initialTimeRange,\n onChange,\n onCancel,\n timeZone,\n}: AbsoluteTimeFormProps): ReactElement => {\n const stdTimeZone = ['local', 'browser'].includes(timeZone.toLowerCase())\n ? Intl.DateTimeFormat().resolvedOptions().timeZone\n : timeZone;\n const [timeRange, setTimeRange] = useState<AbsoluteTimeRange>(initialTimeRange);\n\n const [showStartCalendar, setShowStartCalendar] = useState<boolean>(true);\n\n const changeTimeRange = (newTime: Date, segment: keyof AbsoluteTimeRange): void => {\n setTimeRange((prevTimeRange) => {\n return {\n ...prevTimeRange,\n [segment]: newTime,\n };\n });\n };\n\n const onChangeStartTime = (newStartTime: Date): void => {\n changeTimeRange(newStartTime, 'start');\n };\n\n const onChangeEndTime = (newEndTime: Date): void => {\n changeTimeRange(newEndTime, 'end');\n };\n\n const updateDateRange = (): { start: Date; end: Date } | undefined => {\n const newDates = {\n start: timeRange.start,\n end: timeRange.end,\n };\n const isValidDateRange = validateDateRange(newDates.start, newDates.end);\n if (isValidDateRange) {\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 timezone={stdTimeZone}\n displayStaticWrapperAs=\"desktop\"\n openTo=\"day\"\n disableHighlightToday={true}\n value={new TZDate(timeRange.start, stdTimeZone)}\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 timezone={stdTimeZone}\n displayStaticWrapperAs=\"desktop\"\n openTo=\"day\"\n disableHighlightToday={true}\n value={new TZDate(timeRange.end, stdTimeZone)}\n minDateTime={new TZDate(timeRange.start, stdTimeZone)}\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 timezone={stdTimeZone}\n label=\"Start Time\"\n value={new TZDate(timeRange.start, stdTimeZone)}\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 timezone={stdTimeZone}\n label=\"End Time\"\n value={new TZDate(timeRange.end, stdTimeZone)}\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","TZDate","ErrorBoundary","ErrorAlert","DATE_TIME_FORMAT","validateDateRange","DateTimeRangePicker","initialTimeRange","onChange","onCancel","timeZone","stdTimeZone","includes","toLowerCase","Intl","DateTimeFormat","resolvedOptions","timeRange","setTimeRange","showStartCalendar","setShowStartCalendar","changeTimeRange","newTime","segment","prevTimeRange","onChangeStartTime","newStartTime","onChangeEndTime","newEndTime","updateDateRange","newDates","start","end","isValidDateRange","onApply","dateAdapter","spacing","sx","theme","padding","backgroundColor","palette","background","default","variant","paddingLeft","timezone","displayStaticWrapperAs","openTo","disableHighlightToday","value","newValue","onAccept","minDateTime","direction","alignItems","gap","pl","pr","FallbackComponent","label","event","onBlur","format","onClick","fullWidth"],"mappings":"AAAA,+BAA+B;AAC/B,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;;AAEjC,SAAuBA,QAAQ,QAAQ,QAAQ;AAC/C,SAASC,GAAG,EAAEC,KAAK,EAAEC,UAAU,EAAEC,MAAM,QAAQ,gBAAgB;AAC/D,SAASC,aAAa,EAAEC,oBAAoB,EAAEC,oBAAoB,QAAQ,sBAAsB;AAChG,SAASC,cAAc,QAAQ,uCAAuC;AAEtE,SAASC,MAAM,QAAQ,eAAe;AACtC,SAASC,aAAa,QAAQ,mBAAmB;AACjD,SAASC,UAAU,QAAQ,gBAAgB;AAC3C,SAASC,gBAAgB,EAAEC,iBAAiB,QAAQ,UAAU;AAS9D;;;;;;;;CAQC,GACD,OAAO,MAAMC,sBAAsB,CAAC,EAClCC,gBAAgB,EAChBC,QAAQ,EACRC,QAAQ,EACRC,QAAQ,EACc;IACtB,MAAMC,cAAc;QAAC;QAAS;KAAU,CAACC,QAAQ,CAACF,SAASG,WAAW,MAClEC,KAAKC,cAAc,GAAGC,eAAe,GAAGN,QAAQ,GAChDA;IACJ,MAAM,CAACO,WAAWC,aAAa,GAAG1B,SAA4Be;IAE9D,MAAM,CAACY,mBAAmBC,qBAAqB,GAAG5B,SAAkB;IAEpE,MAAM6B,kBAAkB,CAACC,SAAeC;QACtCL,aAAa,CAACM;YACZ,OAAO;gBACL,GAAGA,aAAa;gBAChB,CAACD,QAAQ,EAAED;YACb;QACF;IACF;IAEA,MAAMG,oBAAoB,CAACC;QACzBL,gBAAgBK,cAAc;IAChC;IAEA,MAAMC,kBAAkB,CAACC;QACvBP,gBAAgBO,YAAY;IAC9B;IAEA,MAAMC,kBAAkB;QACtB,MAAMC,WAAW;YACfC,OAAOd,UAAUc,KAAK;YACtBC,KAAKf,UAAUe,GAAG;QACpB;QACA,MAAMC,mBAAmB5B,kBAAkByB,SAASC,KAAK,EAAED,SAASE,GAAG;QACvE,IAAIC,kBAAkB;YACpB,OAAOH;QACT;IACF;IAEA,MAAMI,UAAU;QACd,MAAMJ,WAAWD;QACjB,IAAIC,UAAU;YACZtB,SAASsB;QACX;IACF;IAEA,qBACE,KAAChC;QAAqBqC,aAAanC;kBACjC,cAAA,MAACN;YACC0C,SAAS;YACTC,IAAI,CAACC,QAAW,CAAA;oBACdC,SAASD,MAAMF,OAAO,CAAC,GAAG,GAAG;gBAC/B,CAAA;;gBAECjB,mCACC,MAAC1B;oBACC4C,IAAI,CAACC,QAAW,CAAA;4BACd,oDAAoD;4BACpD,oCAAoC;gCAClCE,iBAAiBF,MAAMG,OAAO,CAACC,UAAU,CAACC,OAAO;4BACnD;wBACF,CAAA;;sCAEA,KAAChD;4BAAWiD,SAAQ;4BAAKL,SAAS;4BAAGM,aAAa;sCAAG;;sCAGrD,KAAC9C;4BACC+C,UAAUnC;4BACVoC,wBAAuB;4BACvBC,QAAO;4BACPC,uBAAuB;4BACvBC,OAAO,IAAIjD,OAAOgB,UAAUc,KAAK,EAAEpB;4BACnCH,UAAU,CAAC2C;gCACT,IAAIA,aAAa,MAAM;gCACvB1B,kBAAkB0B;4BACpB;4BACAC,UAAU;gCACRhC,qBAAqB;4BACvB;;;;gBAIL,CAACD,mCACA,MAAC1B;oBACC4C,IAAI,CAACC,QAAW,CAAA;4BACd,oCAAoC;gCAClCE,iBAAiBF,MAAMG,OAAO,CAACC,UAAU,CAACC,OAAO;4BACnD;wBACF,CAAA;;sCAEA,KAAChD;4BAAWiD,SAAQ;4BAAKL,SAAS;4BAAGM,aAAa;sCAAG;;sCAGrD,KAAC9C;4BACC+C,UAAUnC;4BACVoC,wBAAuB;4BACvBC,QAAO;4BACPC,uBAAuB;4BACvBC,OAAO,IAAIjD,OAAOgB,UAAUe,GAAG,EAAErB;4BACjC0C,aAAa,IAAIpD,OAAOgB,UAAUc,KAAK,EAAEpB;4BACzCH,UAAU,CAAC2C;gCACT,IAAIA,aAAa,MAAM;gCACvBxB,gBAAgBwB;4BAClB;4BACAC,UAAU,CAACD;gCACT,IAAIA,aAAa,MAAM;gCACvB/B,qBAAqB;gCACrBO,gBAAgBwB;4BAClB;;;;8BAIN,MAACzD;oBAAM4D,WAAU;oBAAMC,YAAW;oBAASC,KAAK;oBAAGC,IAAI;oBAAGC,IAAI;;sCAC5D,KAACxD;4BAAcyD,mBAAmBxD;sCAChC,cAAA,KAACN;gCACCiD,UAAUnC;gCACViD,OAAM;gCACNV,OAAO,IAAIjD,OAAOgB,UAAUc,KAAK,EAAEpB;gCACnCH,UAAU,CAACqD;oCACT,IAAIA,OAAO;wCACTpC,kBAAkBoC;oCACpB;gCACF;gCACAC,QAAQ,IAAMjC;gCACdkC,QAAQ3D;;;sCAGZ,KAACF;4BAAcyD,mBAAmBxD;sCAChC,cAAA,KAACN;gCACCiD,UAAUnC;gCACViD,OAAM;gCACNV,OAAO,IAAIjD,OAAOgB,UAAUe,GAAG,EAAErB;gCACjCH,UAAU,CAACqD;oCACT,IAAIA,OAAO;wCACTlC,gBAAgBkC;oCAClB;gCACF;gCACAC,QAAQ,IAAMjC;gCACdkC,QAAQ3D;;;;;8BAId,MAACV;oBAAM4D,WAAU;oBAAMjB,IAAI;wBAAEE,SAAS,CAACD,QAAUA,MAAMF,OAAO,CAAC,GAAG;oBAAG;oBAAGoB,KAAK;;sCAC3E,KAAC5D;4BAAOgD,SAAQ;4BAAYoB,SAAS,IAAM9B;4BAAW+B,SAAS;sCAAC;;sCAGhE,KAACrE;4BAAOgD,SAAQ;4BAAWoB,SAAS,IAAMvD;4BAAYwD,SAAS;sCAAC;;;;;;;AAO1E,EAAE"}
|
package/dist/TimeZoneSelector.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/TimeZoneSelector.tsx"],"sourcesContent":["// Copyright
|
|
1
|
+
{"version":3,"sources":["../src/TimeZoneSelector.tsx"],"sourcesContent":["// Copyright 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, ReactNode, useMemo } from 'react';\nimport { Select, MenuItem, SelectProps, SelectChangeEvent } from '@mui/material';\nimport { TimeZoneOption, getTimeZoneOptions } from './model/timeZoneOption';\n\nexport interface TimeZoneSelectorProps extends Omit<SelectProps, 'onChange' | 'variant' | 'value'> {\n value: string;\n onChange?: (timeZoneOption: TimeZoneOption) => void;\n timeZoneOptions?: TimeZoneOption[];\n variant?: 'standard' | 'compact';\n heightPx?: string | number;\n}\n\n/**\n * Timezone selector component\n * Allows users to select a timezone from a dropdown list\n */\nexport function TimeZoneSelector({\n value,\n onChange,\n timeZoneOptions,\n variant = 'standard',\n heightPx,\n ...selectProps\n}: TimeZoneSelectorProps): ReactElement {\n const options = useMemo(() => timeZoneOptions ?? getTimeZoneOptions(), [timeZoneOptions]);\n\n const height = heightPx ? (typeof heightPx === 'number' ? `${heightPx}px` : heightPx) : undefined;\n\n const handleChange = (selectedValue: string): void => {\n const selectedOption = options.find((opt: TimeZoneOption) => opt.value === selectedValue);\n if (selectedOption && onChange) {\n onChange(selectedOption);\n }\n };\n\n const sxStyles = useMemo(\n () => ({\n minWidth: variant === 'compact' ? '80px' : '150px',\n ...(height && { lineHeight: height, paddingY: 0 }),\n ...selectProps.sx,\n }),\n [variant, height, selectProps.sx]\n );\n\n return (\n <Select\n {...selectProps}\n value={value}\n onChange={(event: SelectChangeEvent<unknown>, _child: ReactNode) => {\n handleChange(event.target.value as string);\n }}\n sx={sxStyles}\n size={variant === 'compact' ? 'small' : 'medium'}\n >\n {options.map((option: TimeZoneOption) => (\n <MenuItem key={option.value} value={option.value}>\n {option.display}\n </MenuItem>\n ))}\n </Select>\n );\n}\n"],"names":["useMemo","Select","MenuItem","getTimeZoneOptions","TimeZoneSelector","value","onChange","timeZoneOptions","variant","heightPx","selectProps","options","height","undefined","handleChange","selectedValue","selectedOption","find","opt","sxStyles","minWidth","lineHeight","paddingY","sx","event","_child","target","size","map","option","display"],"mappings":"AAAA,+BAA+B;AAC/B,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;;AAEjC,SAAkCA,OAAO,QAAQ,QAAQ;AACzD,SAASC,MAAM,EAAEC,QAAQ,QAAwC,gBAAgB;AACjF,SAAyBC,kBAAkB,QAAQ,yBAAyB;AAU5E;;;CAGC,GACD,OAAO,SAASC,iBAAiB,EAC/BC,KAAK,EACLC,QAAQ,EACRC,eAAe,EACfC,UAAU,UAAU,EACpBC,QAAQ,EACR,GAAGC,aACmB;IACtB,MAAMC,UAAUX,QAAQ,IAAMO,mBAAmBJ,sBAAsB;QAACI;KAAgB;IAExF,MAAMK,SAASH,WAAY,OAAOA,aAAa,WAAW,GAAGA,SAAS,EAAE,CAAC,GAAGA,WAAYI;IAExF,MAAMC,eAAe,CAACC;QACpB,MAAMC,iBAAiBL,QAAQM,IAAI,CAAC,CAACC,MAAwBA,IAAIb,KAAK,KAAKU;QAC3E,IAAIC,kBAAkBV,UAAU;YAC9BA,SAASU;QACX;IACF;IAEA,MAAMG,WAAWnB,QACf,IAAO,CAAA;YACLoB,UAAUZ,YAAY,YAAY,SAAS;YAC3C,GAAII,UAAU;gBAAES,YAAYT;gBAAQU,UAAU;YAAE,CAAC;YACjD,GAAGZ,YAAYa,EAAE;QACnB,CAAA,GACA;QAACf;QAASI;QAAQF,YAAYa,EAAE;KAAC;IAGnC,qBACE,KAACtB;QACE,GAAGS,WAAW;QACfL,OAAOA;QACPC,UAAU,CAACkB,OAAmCC;YAC5CX,aAAaU,MAAME,MAAM,CAACrB,KAAK;QACjC;QACAkB,IAAIJ;QACJQ,MAAMnB,YAAY,YAAY,UAAU;kBAEvCG,QAAQiB,GAAG,CAAC,CAACC,uBACZ,KAAC3B;gBAA4BG,OAAOwB,OAAOxB,KAAK;0BAC7CwB,OAAOC,OAAO;eADFD,OAAOxB,KAAK;;AAMnC"}
|
|
@@ -82,12 +82,7 @@ function ThresholdsEditor({ thresholds, onChange, hideDefault, disablePercentMod
|
|
|
82
82
|
const chartsTheme = (0, _ChartsProvider.useChartsTheme)();
|
|
83
83
|
const { thresholds: { defaultColor, palette } } = chartsTheme;
|
|
84
84
|
const defaultThresholdColor = thresholds?.defaultColor ?? defaultColor;
|
|
85
|
-
const
|
|
86
|
-
(0, _react.useEffect)(()=>{
|
|
87
|
-
setSteps(thresholds?.steps);
|
|
88
|
-
}, [
|
|
89
|
-
thresholds?.steps
|
|
90
|
-
]);
|
|
85
|
+
const steps = thresholds?.steps;
|
|
91
86
|
// every time a new threshold is added, we want to focus the recently added input
|
|
92
87
|
const recentlyAddedInputRef = (0, _react.useRef)(null);
|
|
93
88
|
const focusRef = (0, _react.useRef)(false);
|
|
@@ -99,12 +94,14 @@ function ThresholdsEditor({ thresholds, onChange, hideDefault, disablePercentMod
|
|
|
99
94
|
steps?.length
|
|
100
95
|
]);
|
|
101
96
|
const handleThresholdValueChange = (e, i)=>{
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
97
|
+
if (thresholds !== undefined) {
|
|
98
|
+
onChange((0, _immer.produce)(thresholds, (draft)=>{
|
|
99
|
+
const step = draft.steps?.[i];
|
|
100
|
+
if (step) {
|
|
101
|
+
step.value = Number(e.target.value);
|
|
102
|
+
}
|
|
103
|
+
}));
|
|
104
|
+
}
|
|
108
105
|
};
|
|
109
106
|
const handleThresholdColorChange = (color, i)=>{
|
|
110
107
|
if (thresholds !== undefined) {
|
|
@@ -25,23 +25,16 @@ const _react = require("react");
|
|
|
25
25
|
const _material = require("@mui/material");
|
|
26
26
|
const _xdatepickers = require("@mui/x-date-pickers");
|
|
27
27
|
const _AdapterDateFnsV3 = require("@mui/x-date-pickers/AdapterDateFnsV3");
|
|
28
|
+
const _tz = require("@date-fns/tz");
|
|
28
29
|
const _ErrorBoundary = require("../ErrorBoundary");
|
|
29
30
|
const _ErrorAlert = require("../ErrorAlert");
|
|
30
|
-
const _format = require("../utils/format");
|
|
31
31
|
const _utils = require("./utils");
|
|
32
32
|
const DateTimeRangePicker = ({ initialTimeRange, onChange, onCancel, timeZone })=>{
|
|
33
|
-
|
|
33
|
+
const stdTimeZone = [
|
|
34
|
+
'local',
|
|
35
|
+
'browser'
|
|
36
|
+
].includes(timeZone.toLowerCase()) ? Intl.DateTimeFormat().resolvedOptions().timeZone : timeZone;
|
|
34
37
|
const [timeRange, setTimeRange] = (0, _react.useState)(initialTimeRange);
|
|
35
|
-
const timeRangeInputs = (0, _react.useMemo)(()=>{
|
|
36
|
-
return {
|
|
37
|
-
start: (0, _format.formatWithTimeZone)(timeRange.start, _utils.DATE_TIME_FORMAT, timeZone),
|
|
38
|
-
end: (0, _format.formatWithTimeZone)(timeRange.end, _utils.DATE_TIME_FORMAT, timeZone)
|
|
39
|
-
};
|
|
40
|
-
}, [
|
|
41
|
-
timeRange.start,
|
|
42
|
-
timeRange.end,
|
|
43
|
-
timeZone
|
|
44
|
-
]);
|
|
45
38
|
const [showStartCalendar, setShowStartCalendar] = (0, _react.useState)(true);
|
|
46
39
|
const changeTimeRange = (newTime, segment)=>{
|
|
47
40
|
setTimeRange((prevTimeRange)=>{
|
|
@@ -96,10 +89,11 @@ const DateTimeRangePicker = ({ initialTimeRange, onChange, onCancel, timeZone })
|
|
|
96
89
|
children: "Select Start Time"
|
|
97
90
|
}),
|
|
98
91
|
/*#__PURE__*/ (0, _jsxruntime.jsx)(_xdatepickers.StaticDateTimePicker, {
|
|
92
|
+
timezone: stdTimeZone,
|
|
99
93
|
displayStaticWrapperAs: "desktop",
|
|
100
94
|
openTo: "day",
|
|
101
95
|
disableHighlightToday: true,
|
|
102
|
-
value: timeRange.start,
|
|
96
|
+
value: new _tz.TZDate(timeRange.start, stdTimeZone),
|
|
103
97
|
onChange: (newValue)=>{
|
|
104
98
|
if (newValue === null) return;
|
|
105
99
|
onChangeStartTime(newValue);
|
|
@@ -124,11 +118,12 @@ const DateTimeRangePicker = ({ initialTimeRange, onChange, onCancel, timeZone })
|
|
|
124
118
|
children: "Select End Time"
|
|
125
119
|
}),
|
|
126
120
|
/*#__PURE__*/ (0, _jsxruntime.jsx)(_xdatepickers.StaticDateTimePicker, {
|
|
121
|
+
timezone: stdTimeZone,
|
|
127
122
|
displayStaticWrapperAs: "desktop",
|
|
128
123
|
openTo: "day",
|
|
129
124
|
disableHighlightToday: true,
|
|
130
|
-
value: timeRange.end,
|
|
131
|
-
minDateTime: timeRange.start,
|
|
125
|
+
value: new _tz.TZDate(timeRange.end, stdTimeZone),
|
|
126
|
+
minDateTime: new _tz.TZDate(timeRange.start, stdTimeZone),
|
|
132
127
|
onChange: (newValue)=>{
|
|
133
128
|
if (newValue === null) return;
|
|
134
129
|
onChangeEndTime(newValue);
|
|
@@ -151,8 +146,9 @@ const DateTimeRangePicker = ({ initialTimeRange, onChange, onCancel, timeZone })
|
|
|
151
146
|
/*#__PURE__*/ (0, _jsxruntime.jsx)(_ErrorBoundary.ErrorBoundary, {
|
|
152
147
|
FallbackComponent: _ErrorAlert.ErrorAlert,
|
|
153
148
|
children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_xdatepickers.DateTimeField, {
|
|
149
|
+
timezone: stdTimeZone,
|
|
154
150
|
label: "Start Time",
|
|
155
|
-
value: new
|
|
151
|
+
value: new _tz.TZDate(timeRange.start, stdTimeZone),
|
|
156
152
|
onChange: (event)=>{
|
|
157
153
|
if (event) {
|
|
158
154
|
onChangeStartTime(event);
|
|
@@ -165,8 +161,9 @@ const DateTimeRangePicker = ({ initialTimeRange, onChange, onCancel, timeZone })
|
|
|
165
161
|
/*#__PURE__*/ (0, _jsxruntime.jsx)(_ErrorBoundary.ErrorBoundary, {
|
|
166
162
|
FallbackComponent: _ErrorAlert.ErrorAlert,
|
|
167
163
|
children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_xdatepickers.DateTimeField, {
|
|
164
|
+
timezone: stdTimeZone,
|
|
168
165
|
label: "End Time",
|
|
169
|
-
value: new
|
|
166
|
+
value: new _tz.TZDate(timeRange.end, stdTimeZone),
|
|
170
167
|
onChange: (event)=>{
|
|
171
168
|
if (event) {
|
|
172
169
|
onChangeEndTime(event);
|
package/dist/cjs/utils/format.js
CHANGED
|
@@ -34,7 +34,7 @@ _export(exports, {
|
|
|
34
34
|
return getFormattedAxisLabel;
|
|
35
35
|
}
|
|
36
36
|
});
|
|
37
|
-
const
|
|
37
|
+
const _tz = require("@date-fns/tz");
|
|
38
38
|
const _datefns = require("date-fns");
|
|
39
39
|
function dateFormatOptionsWithTimeZone(dateFormatOptions, timeZone) {
|
|
40
40
|
/*
|
|
@@ -61,7 +61,9 @@ function formatWithTimeZone(date, formatString, timeZone) {
|
|
|
61
61
|
if (!timeZone || lowerTimeZone === 'local' || lowerTimeZone === 'browser') {
|
|
62
62
|
return (0, _datefns.format)(date, formatString);
|
|
63
63
|
} else {
|
|
64
|
-
return (0,
|
|
64
|
+
return (0, _datefns.format)(date, formatString, {
|
|
65
|
+
in: (0, _tz.tz)(lowerTimeZone === 'utc' ? 'UTC' : timeZone)
|
|
66
|
+
});
|
|
65
67
|
}
|
|
66
68
|
}
|
|
67
69
|
function getFormattedAxisLabel(rangeMs) {
|
package/dist/utils/format.js
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
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 {
|
|
13
|
+
import { tz } from '@date-fns/tz';
|
|
14
14
|
import { format } from 'date-fns';
|
|
15
15
|
export function dateFormatOptionsWithTimeZone(dateFormatOptions, timeZone) {
|
|
16
16
|
/*
|
|
@@ -37,7 +37,9 @@ export function formatWithTimeZone(date, formatString, timeZone) {
|
|
|
37
37
|
if (!timeZone || lowerTimeZone === 'local' || lowerTimeZone === 'browser') {
|
|
38
38
|
return format(date, formatString);
|
|
39
39
|
} else {
|
|
40
|
-
return
|
|
40
|
+
return format(date, formatString, {
|
|
41
|
+
in: tz(lowerTimeZone === 'utc' ? 'UTC' : timeZone)
|
|
42
|
+
});
|
|
41
43
|
}
|
|
42
44
|
}
|
|
43
45
|
// https://echarts.apache.org/en/option.html#xAxis.axisLabel.formatter
|
package/dist/utils/format.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utils/format.ts"],"sourcesContent":["// Copyright 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 {
|
|
1
|
+
{"version":3,"sources":["../../src/utils/format.ts"],"sourcesContent":["// Copyright 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 { tz } from '@date-fns/tz';\nimport { format } from 'date-fns';\n\nexport function dateFormatOptionsWithTimeZone(\n dateFormatOptions: Intl.DateTimeFormatOptions,\n timeZone?: string\n): Intl.DateTimeFormatOptions {\n /*\n * if timeZone is provided, and is not local|browser,\n * then set timeZone option (recognize UTC regardless of uppercase/lowercase)\n * otherwise, default to browser timeZone setting\n */\n if (timeZone) {\n const lowerTimeZone = timeZone.toLowerCase();\n if (lowerTimeZone !== 'local' && lowerTimeZone !== 'browser') {\n return {\n ...dateFormatOptions,\n timeZone: lowerTimeZone === 'utc' ? 'UTC' : timeZone,\n };\n }\n }\n return dateFormatOptions;\n}\n\nexport function formatWithTimeZone(date: Date, formatString: string, timeZone?: string): string {\n /*\n * if timeZone is provided, and is not local|browser,\n * then format using timeZone option (recognize UTC regardless of uppercase/lowercase)\n * otherwise, format without timeZone option, defaulting to browser timeZone setting\n */\n const lowerTimeZone = timeZone?.toLowerCase();\n if (!timeZone || lowerTimeZone === 'local' || lowerTimeZone === 'browser') {\n return format(date, formatString);\n } else {\n return format(date, formatString, { in: tz(lowerTimeZone === 'utc' ? 'UTC' : timeZone) });\n }\n}\n\n// https://echarts.apache.org/en/option.html#xAxis.axisLabel.formatter\nexport function getFormattedAxisLabel(rangeMs: number):\n | string\n | {\n month: '{MMM}';\n year: '{yearStyle|{yyyy}}\\n{monthStyle|{MMM}}';\n day: '{MM}/{dd}';\n } {\n const dayMs = 86400000;\n const monthMs = 2629440000;\n const yearMs = 31536000000;\n\n // more than 5 years\n if (rangeMs > yearMs * 5) {\n return '{yyyy}';\n }\n\n // more than 2 years\n if (rangeMs > yearMs * 2) {\n return '{MMM} {yyyy}';\n }\n\n // between 5 days to 6 months\n if (rangeMs > dayMs * 5 && rangeMs < monthMs * 6) {\n return '{MM}/{dd}'; // 12/01\n }\n\n // between 2 and 5 days\n if (rangeMs > dayMs * 2 && rangeMs <= dayMs * 5) {\n return '{MM}/{dd} {HH}:{mm}'; // 12/01 12:30\n }\n\n return {\n year: '{yearStyle|{yyyy}}\\n{monthStyle|{MMM}}',\n month: '{MMM}', // Jan, Feb, ...\n day: '{MM}/{dd}',\n };\n}\n\ninterface FormattedDateTime {\n formattedDate: string;\n formattedTime: string;\n}\n\nexport const getDateAndTime = (timeMs?: number): FormattedDateTime => {\n if (!timeMs) {\n return { formattedDate: '', formattedTime: '' };\n }\n const date = new Date(timeMs);\n const formattedDate = format(date, 'MMM dd, yyyy - ');\n const formattedTime = format(date, 'HH:mm:ss');\n return {\n formattedDate,\n formattedTime,\n };\n};\n"],"names":["tz","format","dateFormatOptionsWithTimeZone","dateFormatOptions","timeZone","lowerTimeZone","toLowerCase","formatWithTimeZone","date","formatString","in","getFormattedAxisLabel","rangeMs","dayMs","monthMs","yearMs","year","month","day","getDateAndTime","timeMs","formattedDate","formattedTime","Date"],"mappings":"AAAA,+BAA+B;AAC/B,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC,SAASA,EAAE,QAAQ,eAAe;AAClC,SAASC,MAAM,QAAQ,WAAW;AAElC,OAAO,SAASC,8BACdC,iBAA6C,EAC7CC,QAAiB;IAEjB;;;;GAIC,GACD,IAAIA,UAAU;QACZ,MAAMC,gBAAgBD,SAASE,WAAW;QAC1C,IAAID,kBAAkB,WAAWA,kBAAkB,WAAW;YAC5D,OAAO;gBACL,GAAGF,iBAAiB;gBACpBC,UAAUC,kBAAkB,QAAQ,QAAQD;YAC9C;QACF;IACF;IACA,OAAOD;AACT;AAEA,OAAO,SAASI,mBAAmBC,IAAU,EAAEC,YAAoB,EAAEL,QAAiB;IACpF;;;;GAIC,GACD,MAAMC,gBAAgBD,UAAUE;IAChC,IAAI,CAACF,YAAYC,kBAAkB,WAAWA,kBAAkB,WAAW;QACzE,OAAOJ,OAAOO,MAAMC;IACtB,OAAO;QACL,OAAOR,OAAOO,MAAMC,cAAc;YAAEC,IAAIV,GAAGK,kBAAkB,QAAQ,QAAQD;QAAU;IACzF;AACF;AAEA,sEAAsE;AACtE,OAAO,SAASO,sBAAsBC,OAAe;IAOnD,MAAMC,QAAQ;IACd,MAAMC,UAAU;IAChB,MAAMC,SAAS;IAEf,oBAAoB;IACpB,IAAIH,UAAUG,SAAS,GAAG;QACxB,OAAO;IACT;IAEA,oBAAoB;IACpB,IAAIH,UAAUG,SAAS,GAAG;QACxB,OAAO;IACT;IAEA,6BAA6B;IAC7B,IAAIH,UAAUC,QAAQ,KAAKD,UAAUE,UAAU,GAAG;QAChD,OAAO,aAAa,QAAQ;IAC9B;IAEA,uBAAuB;IACvB,IAAIF,UAAUC,QAAQ,KAAKD,WAAWC,QAAQ,GAAG;QAC/C,OAAO,uBAAuB,cAAc;IAC9C;IAEA,OAAO;QACLG,MAAM;QACNC,OAAO;QACPC,KAAK;IACP;AACF;AAOA,OAAO,MAAMC,iBAAiB,CAACC;IAC7B,IAAI,CAACA,QAAQ;QACX,OAAO;YAAEC,eAAe;YAAIC,eAAe;QAAG;IAChD;IACA,MAAMd,OAAO,IAAIe,KAAKH;IACtB,MAAMC,gBAAgBpB,OAAOO,MAAM;IACnC,MAAMc,gBAAgBrB,OAAOO,MAAM;IACnC,OAAO;QACLa;QACAC;IACF;AACF,EAAE"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@perses-dev/components",
|
|
3
|
-
"version": "0.53.
|
|
3
|
+
"version": "0.53.1",
|
|
4
4
|
"description": "Common UI components used across Perses features",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://github.com/perses/perses/blob/main/README.md",
|
|
@@ -31,13 +31,13 @@
|
|
|
31
31
|
"@atlaskit/pragmatic-drag-and-drop": "^1.4.0",
|
|
32
32
|
"@atlaskit/pragmatic-drag-and-drop-hitbox": "^1.0.3",
|
|
33
33
|
"@codemirror/lang-json": "^6.0.1",
|
|
34
|
+
"@date-fns/tz": "^1.4.1",
|
|
34
35
|
"@fontsource/lato": "^4.5.10",
|
|
35
36
|
"@mui/x-date-pickers": "^7.23.1",
|
|
36
|
-
"@perses-dev/core": "0.53.0
|
|
37
|
+
"@perses-dev/core": "0.53.0",
|
|
37
38
|
"@tanstack/react-table": "^8.20.5",
|
|
38
39
|
"@uiw/react-codemirror": "^4.19.1",
|
|
39
40
|
"date-fns": "^4.1.0",
|
|
40
|
-
"date-fns-tz": "^3.2.0",
|
|
41
41
|
"echarts": "5.5.0",
|
|
42
42
|
"immer": "^10.1.1",
|
|
43
43
|
"lodash": "^4.17.21",
|
|
@@ -54,9 +54,9 @@
|
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
56
|
"@mui/material": "^6.1.10",
|
|
57
|
+
"lodash": "^4.17.21",
|
|
57
58
|
"react": "^17.0.2 || ^18.0.0",
|
|
58
|
-
"react-dom": "^17.0.2 || ^18.0.0"
|
|
59
|
-
"lodash": "^4.17.21"
|
|
59
|
+
"react-dom": "^17.0.2 || ^18.0.0"
|
|
60
60
|
},
|
|
61
61
|
"files": [
|
|
62
62
|
"dist"
|