= ({ labels, format }) => {
+ const clipboard = useClipboard();
+
+ const renderFormatted = (): React.ReactElement => {
+ const labelNodes: React.ReactElement[] = [];
+ let first = true;
+ for (const label in labels) {
+ if (label === "__name__") {
+ continue;
+ }
+
+ labelNodes.push(
+
+ {!first && ", "}
+ {
+ const text = e.currentTarget.innerText;
+ clipboard.copy(text);
+ notifications.show({
+ title: "Copied matcher!",
+ message: `Label matcher ${text} copied to clipboard`,
+ });
+ }}
+ title="Click to copy label matcher"
+ >
+ {label}=
+
+ "{escapeString(labels[label])}"
+
+
+
+ );
+
+ if (first) {
+ first = false;
+ }
+ }
+
+ return (
+
+
+ {labels ? labels.__name__ : ""}
+
+ {"{"}
+ {labelNodes}
+ {"}"}
+
+ );
+ };
+
+ if (labels === null) {
+ return <>scalar>;
+ }
+
+ if (format) {
+ return renderFormatted();
+ }
+ // Return a simple text node. This is much faster to scroll through
+ // for longer lists (hundreds of items).
+ return <>{formatSeries(labels)}>;
+};
+
+export default SeriesName;
diff --git a/web/ui/mantine-ui/src/pages/query/TimeInput.tsx b/web/ui/mantine-ui/src/pages/query/TimeInput.tsx
new file mode 100644
index 0000000000..5d74043a7c
--- /dev/null
+++ b/web/ui/mantine-ui/src/pages/query/TimeInput.tsx
@@ -0,0 +1,64 @@
+import { Group, ActionIcon } from "@mantine/core";
+import { DatesProvider, DateTimePicker } from "@mantine/dates";
+import { IconChevronLeft, IconChevronRight } from "@tabler/icons-react";
+import { FC } from "react";
+
+interface TimeInputProps {
+ time: number | null; // Timestamp in milliseconds.
+ range: number; // Range in seconds.
+ description: string;
+ onChangeTime: (time: number | null) => void;
+}
+
+const iconStyle = { width: "0.9rem", height: "0.9rem" };
+
+const TimeInput: FC = ({
+ time,
+ range,
+ description,
+ onChangeTime,
+}) => {
+ const baseTime = () => (time !== null ? time : Date.now().valueOf());
+
+ return (
+
+ onChangeTime(baseTime() - range / 2)}
+ >
+
+
+
+ onChangeTime(value ? value.getTime() : null)}
+ aria-label={description}
+ placeholder={description}
+ onClick={() => {
+ if (time === null) {
+ onChangeTime(baseTime());
+ }
+ }}
+ />
+
+ onChangeTime(baseTime() + range / 2)}
+ >
+
+
+
+ );
+};
+
+export default TimeInput;
diff --git a/web/ui/mantine-ui/src/pages/service-discovery.tsx b/web/ui/mantine-ui/src/pages/service-discovery.tsx
deleted file mode 100644
index fff68c3a9e..0000000000
--- a/web/ui/mantine-ui/src/pages/service-discovery.tsx
+++ /dev/null
@@ -1,3 +0,0 @@
-export default function ServiceDiscovery() {
- return <>ServiceDiscovery page>;
-}
diff --git a/web/ui/mantine-ui/src/pages/targets.tsx b/web/ui/mantine-ui/src/pages/targets.tsx
deleted file mode 100644
index 7668cbc6e9..0000000000
--- a/web/ui/mantine-ui/src/pages/targets.tsx
+++ /dev/null
@@ -1,3 +0,0 @@
-export default function Targets() {
- return <>Targets page>;
-}
diff --git a/web/ui/mantine-ui/src/state/api.ts b/web/ui/mantine-ui/src/state/api.ts
new file mode 100644
index 0000000000..c5c411c6b1
--- /dev/null
+++ b/web/ui/mantine-ui/src/state/api.ts
@@ -0,0 +1,49 @@
+import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
+import { ErrorAPIResponse, SuccessAPIResponse } from "../api/api";
+import { InstantQueryResult } from "../api/responseTypes/query";
+
+// Define a service using a base URL and expected endpoints
+export const prometheusApi = createApi({
+ reducerPath: "prometheusApi",
+ baseQuery: fetchBaseQuery({ baseUrl: "/api/v1/" }),
+ keepUnusedDataFor: 0, // Turn off caching.
+ endpoints: (builder) => ({
+ instantQuery: builder.query<
+ SuccessAPIResponse,
+ { query: string; time: number }
+ >({
+ query: ({ query, time }) => {
+ return {
+ url: `query`,
+ params: {
+ query,
+ time,
+ },
+ };
+ //`query?query=${encodeURIComponent(query)}&time=${time}`,
+ },
+ transformErrorResponse: (error): string => {
+ if (!error.data) {
+ return "Failed to fetch data";
+ }
+
+ return (error.data as ErrorAPIResponse).error;
+ },
+ // transformResponse: (
+ // response: APIResponse
+ // ): SuccessAPIResponse => {
+ // if (!response.status) {
+ // throw new Error("Invalid response");
+ // }
+ // if (response.status === "error") {
+ // throw new Error(response.error);
+ // }
+ // return response;
+ // },
+ }),
+ }),
+});
+
+// Export hooks for usage in functional components, which are
+// auto-generated based on the defined endpoints
+export const { useInstantQueryQuery, useLazyInstantQueryQuery } = prometheusApi;
diff --git a/web/ui/mantine-ui/src/state/hooks.ts b/web/ui/mantine-ui/src/state/hooks.ts
new file mode 100644
index 0000000000..04a59b244d
--- /dev/null
+++ b/web/ui/mantine-ui/src/state/hooks.ts
@@ -0,0 +1,6 @@
+import { useDispatch, useSelector } from "react-redux";
+import type { RootState, AppDispatch } from "./store";
+
+// Use throughout your app instead of plain `useDispatch` and `useSelector`
+export const useAppDispatch = useDispatch.withTypes();
+export const useAppSelector = useSelector.withTypes();
diff --git a/web/ui/mantine-ui/src/state/queryPageSlice.ts b/web/ui/mantine-ui/src/state/queryPageSlice.ts
new file mode 100644
index 0000000000..39cfe55f36
--- /dev/null
+++ b/web/ui/mantine-ui/src/state/queryPageSlice.ts
@@ -0,0 +1,83 @@
+import { randomId } from "@mantine/hooks";
+import { PayloadAction, createSlice } from "@reduxjs/toolkit";
+
+export enum GraphDisplayMode {
+ Lines = "lines",
+ Stacked = "stacked",
+ Heatmap = "heatmap",
+}
+
+// NOTE: This is not represented as a discriminated union type
+// because we want to preserve and partially share settings while
+// switching between display modes.
+export interface Visualizer {
+ activeTab: "table" | "graph" | "explain";
+ endTime: number | null; // Timestamp in milliseconds.
+ range: number; // Range in seconds.
+ resolution: number | null; // Resolution step in seconds.
+ displayMode: GraphDisplayMode;
+ showExemplars: boolean;
+}
+
+export type Panel = {
+ // The id is helpful as a stable key for React.
+ id: string;
+ expr: string;
+ exprStale: boolean;
+ showMetricsExplorer: boolean;
+ visualizer: Visualizer;
+};
+
+interface QueryPageState {
+ panels: Panel[];
+}
+
+const newDefaultPanel = (): Panel => ({
+ id: randomId(),
+ expr: "",
+ exprStale: false,
+ showMetricsExplorer: false,
+ visualizer: {
+ activeTab: "table",
+ endTime: null,
+ // endTime: 1709414194000,
+ range: 3600 * 1000,
+ resolution: null,
+ displayMode: GraphDisplayMode.Lines,
+ showExemplars: false,
+ },
+});
+
+const initialState: QueryPageState = {
+ panels: [newDefaultPanel()],
+};
+
+export const queryPageSlice = createSlice({
+ name: "queryPage",
+ initialState,
+ reducers: {
+ addPanel: (state) => {
+ state.panels.push(newDefaultPanel());
+ },
+ removePanel: (state, { payload }: PayloadAction) => {
+ state.panels.splice(payload, 1);
+ },
+ setExpr: (
+ state,
+ { payload }: PayloadAction<{ idx: number; expr: string }>
+ ) => {
+ state.panels[payload.idx].expr = payload.expr;
+ },
+ setVisualizer: (
+ state,
+ { payload }: PayloadAction<{ idx: number; visualizer: Visualizer }>
+ ) => {
+ state.panels[payload.idx].visualizer = payload.visualizer;
+ },
+ },
+});
+
+export const { addPanel, removePanel, setExpr, setVisualizer } =
+ queryPageSlice.actions;
+
+export default queryPageSlice.reducer;
diff --git a/web/ui/mantine-ui/src/state/store.ts b/web/ui/mantine-ui/src/state/store.ts
new file mode 100644
index 0000000000..fe16347ea0
--- /dev/null
+++ b/web/ui/mantine-ui/src/state/store.ts
@@ -0,0 +1,19 @@
+import { configureStore } from "@reduxjs/toolkit";
+import queryPageSlice from "./queryPageSlice";
+import { prometheusApi } from "./api";
+
+const store = configureStore({
+ reducer: {
+ queryPage: queryPageSlice,
+ [prometheusApi.reducerPath]: prometheusApi.reducer,
+ },
+ middleware: (getDefaultMiddleware) =>
+ getDefaultMiddleware().concat(prometheusApi.middleware),
+});
+
+// Infer the `RootState` and `AppDispatch` types from the store itself
+export type RootState = ReturnType;
+// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
+export type AppDispatch = typeof store.dispatch;
+
+export default store;
diff --git a/web/ui/mantine-ui/src/theme-selector.tsx b/web/ui/mantine-ui/src/theme-selector.tsx
deleted file mode 100644
index f01aa91f7c..0000000000
--- a/web/ui/mantine-ui/src/theme-selector.tsx
+++ /dev/null
@@ -1,67 +0,0 @@
-import {
- useMantineColorScheme,
- Group,
- SegmentedControl,
- rem,
- MantineColorScheme,
- Tooltip,
-} from "@mantine/core";
-import {
- IconMoonFilled,
- IconSunFilled,
- IconUserFilled,
-} from "@tabler/icons-react";
-import { FC } from "react";
-
-export const ThemeSelector: FC = () => {
- const { colorScheme, setColorScheme } = useMantineColorScheme();
- const iconProps = {
- style: { width: rem(20), height: rem(20), display: "block" },
- stroke: 1.5,
- };
-
- return (
-
- setColorScheme(v as MantineColorScheme)}
- data={[
- {
- value: "light",
- label: (
-
-
-
- ),
- },
- {
- value: "dark",
- label: (
-
-
-
- ),
- },
- {
- value: "auto",
- label: (
-
-
-
- ),
- },
- ]}
- />
-
- );
-};
diff --git a/web/ui/package-lock.json b/web/ui/package-lock.json
index ef8b467a9d..dffee20813 100644
--- a/web/ui/package-lock.json
+++ b/web/ui/package-lock.json
@@ -115,17 +115,20 @@
"@codemirror/view": "^6.24.0",
"@lezer/common": "^1.2.1",
"@lezer/highlight": "^1.2.0",
- "@mantine/code-highlight": "^7.5.3",
- "@mantine/core": "^7.5.3",
- "@mantine/dates": "^7.5.3",
- "@mantine/hooks": "^7.5.3",
+ "@mantine/code-highlight": "^7.6.1",
+ "@mantine/core": "^7.6.1",
+ "@mantine/dates": "^7.6.1",
+ "@mantine/hooks": "^7.6.1",
+ "@mantine/notifications": "^7.6.1",
"@prometheus-io/codemirror-promql": "^0.50.0-rc.1",
+ "@reduxjs/toolkit": "^2.2.1",
"@tabler/icons-react": "^2.47.0",
"@tanstack/react-query": "^5.22.2",
"@uiw/react-codemirror": "^4.21.22",
"dayjs": "^1.11.10",
"react": "^18.2.0",
"react-dom": "^18.2.0",
+ "react-redux": "^9.1.0",
"react-router-dom": "^6.22.1"
},
"devDependencies": {
@@ -143,6 +146,91 @@
"vite": "^5.1.0"
}
},
+ "mantine-ui/node_modules/@floating-ui/react": {
+ "version": "0.26.9",
+ "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.9.tgz",
+ "integrity": "sha512-p86wynZJVEkEq2BBjY/8p2g3biQ6TlgT4o/3KgFKyTWoJLU1GZ8wpctwRqtkEl2tseYA+kw7dBAIDFcednfI5w==",
+ "dependencies": {
+ "@floating-ui/react-dom": "^2.0.8",
+ "@floating-ui/utils": "^0.2.1",
+ "tabbable": "^6.0.1"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0"
+ }
+ },
+ "mantine-ui/node_modules/@mantine/code-highlight": {
+ "version": "7.6.1",
+ "resolved": "https://registry.npmjs.org/@mantine/code-highlight/-/code-highlight-7.6.1.tgz",
+ "integrity": "sha512-FDgbDQzlB+ldJzkWEscCtNyE5hqE1DgBjlrw3EeOhdK0FRijzXrUpABjnmZZPuoMAbxBaBPaguL4VwrHCzEOmg==",
+ "dependencies": {
+ "clsx": "2.1.0",
+ "highlight.js": "^11.9.0"
+ },
+ "peerDependencies": {
+ "@mantine/core": "7.6.1",
+ "@mantine/hooks": "7.6.1",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0"
+ }
+ },
+ "mantine-ui/node_modules/@mantine/core": {
+ "version": "7.6.1",
+ "resolved": "https://registry.npmjs.org/@mantine/core/-/core-7.6.1.tgz",
+ "integrity": "sha512-52BgYXAMD+E6vDiGIGOJlLBc0pdT2+gzrB0g+v7c7xeiNXqHEG5cEplLErfNBHh9kMQHiDHCiCb5Su9jqoUlXw==",
+ "dependencies": {
+ "@floating-ui/react": "^0.26.9",
+ "clsx": "2.1.0",
+ "react-number-format": "^5.3.1",
+ "react-remove-scroll": "^2.5.7",
+ "react-textarea-autosize": "8.5.3",
+ "type-fest": "^3.13.1"
+ },
+ "peerDependencies": {
+ "@mantine/hooks": "7.6.1",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0"
+ }
+ },
+ "mantine-ui/node_modules/@mantine/dates": {
+ "version": "7.6.1",
+ "resolved": "https://registry.npmjs.org/@mantine/dates/-/dates-7.6.1.tgz",
+ "integrity": "sha512-xHe5sINtFuqptmZCXfp0aeurC8wjiycBzHvk87CqfhLIGWBTSAkrCKk3KzdUeEKfVsLY1l21cFb7Sv7mr4lfTw==",
+ "dependencies": {
+ "clsx": "2.1.0"
+ },
+ "peerDependencies": {
+ "@mantine/core": "7.6.1",
+ "@mantine/hooks": "7.6.1",
+ "dayjs": ">=1.0.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0"
+ }
+ },
+ "mantine-ui/node_modules/@mantine/hooks": {
+ "version": "7.6.1",
+ "resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-7.6.1.tgz",
+ "integrity": "sha512-zsOGzFRcQZuER2rzAjfrAqp98W7WCFA43nF1QZUKV7AHTq8q1mtr3DOhFfO3/CA+t1lai68gp1guVcIhP4lrwQ==",
+ "peerDependencies": {
+ "react": "^18.2.0"
+ }
+ },
+ "mantine-ui/node_modules/@mantine/notifications": {
+ "version": "7.6.1",
+ "resolved": "https://registry.npmjs.org/@mantine/notifications/-/notifications-7.6.1.tgz",
+ "integrity": "sha512-Aiui/faUBVQVgDPW9poCe8WdRZkXmIe9aFTnmf+WTopMWK/zfLBp02IjLY1f59zs5NeF/vfXaMxiuQq+KH2hTQ==",
+ "dependencies": {
+ "@mantine/store": "7.6.1",
+ "react-transition-group": "4.4.5"
+ },
+ "peerDependencies": {
+ "@mantine/core": "7.6.1",
+ "@mantine/hooks": "7.6.1",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0"
+ }
+ },
"mantine-ui/node_modules/@prometheus-io/codemirror-promql": {
"version": "0.50.0-rc.1",
"resolved": "https://registry.npmjs.org/@prometheus-io/codemirror-promql/-/codemirror-promql-0.50.0-rc.1.tgz",
@@ -172,6 +260,14 @@
"@lezer/lr": "^1.2.3"
}
},
+ "mantine-ui/node_modules/clsx": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz",
+ "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"mantine-ui/node_modules/lru-cache": {
"version": "7.18.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
@@ -180,6 +276,17 @@
"node": ">=12"
}
},
+ "mantine-ui/node_modules/type-fest": {
+ "version": "3.13.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz",
+ "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==",
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"module/codemirror-promql": {
"name": "@prometheus-io/codemirror-promql",
"version": "0.49.1",
@@ -1527,20 +1634,6 @@
"@floating-ui/utils": "^0.2.0"
}
},
- "node_modules/@floating-ui/react": {
- "version": "0.24.8",
- "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.24.8.tgz",
- "integrity": "sha512-AuYeDoaR8jtUlUXtZ1IJ/6jtBkGnSpJXbGNzokBL87VDJ8opMq1Bgrc0szhK482ReQY6KZsMoZCVSb4xwalkBA==",
- "dependencies": {
- "@floating-ui/react-dom": "^2.0.1",
- "aria-hidden": "^1.2.3",
- "tabbable": "^6.0.1"
- },
- "peerDependencies": {
- "react": ">=16.8.0",
- "react-dom": ">=16.8.0"
- }
- },
"node_modules/@floating-ui/react-dom": {
"version": "2.0.8",
"resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.8.tgz",
@@ -2101,69 +2194,10 @@
"@lezer/common": "^1.0.0"
}
},
- "node_modules/@mantine/code-highlight": {
- "version": "7.5.3",
- "resolved": "https://registry.npmjs.org/@mantine/code-highlight/-/code-highlight-7.5.3.tgz",
- "integrity": "sha512-TLZSkVAfX3KH9XKjJl965KX6TjpMKtNzObjI6Uvo/J/5Rvqhe7xbhBPJDT7yhSD+wjnTMsEWEb68rmQa3M/cEA==",
- "dependencies": {
- "clsx": "2.0.0",
- "highlight.js": "^11.9.0"
- },
- "peerDependencies": {
- "@mantine/core": "7.5.3",
- "@mantine/hooks": "7.5.3",
- "react": "^18.2.0",
- "react-dom": "^18.2.0"
- }
- },
- "node_modules/@mantine/core": {
- "version": "7.5.3",
- "resolved": "https://registry.npmjs.org/@mantine/core/-/core-7.5.3.tgz",
- "integrity": "sha512-Wvv6DJXI+GX9mmKG5HITTh/24sCZ0RoYQHdTHh0tOfGnEy+RleyhA82UjnMsp0n2NjfCISBwbiKgfya6b2iaFw==",
- "dependencies": {
- "@floating-ui/react": "^0.24.8",
- "clsx": "2.0.0",
- "react-number-format": "^5.3.1",
- "react-remove-scroll": "^2.5.7",
- "react-textarea-autosize": "8.5.3",
- "type-fest": "^3.13.1"
- },
- "peerDependencies": {
- "@mantine/hooks": "7.5.3",
- "react": "^18.2.0",
- "react-dom": "^18.2.0"
- }
- },
- "node_modules/@mantine/core/node_modules/type-fest": {
- "version": "3.13.1",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz",
- "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==",
- "engines": {
- "node": ">=14.16"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/@mantine/dates": {
- "version": "7.5.3",
- "resolved": "https://registry.npmjs.org/@mantine/dates/-/dates-7.5.3.tgz",
- "integrity": "sha512-v6fFdW+7HAd7XsZFMJVMuFE2RHbQAVnsUNeP0/5h+H4qEj0soTmMvHPP8wXEed5v85r9CcEMGOGq1n6RFRpWHA==",
- "dependencies": {
- "clsx": "2.0.0"
- },
- "peerDependencies": {
- "@mantine/core": "7.5.3",
- "@mantine/hooks": "7.5.3",
- "dayjs": ">=1.0.0",
- "react": "^18.2.0",
- "react-dom": "^18.2.0"
- }
- },
- "node_modules/@mantine/hooks": {
- "version": "7.5.3",
- "resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-7.5.3.tgz",
- "integrity": "sha512-mFI448mAs12v8FrgSVhytqlhTVrEjIfd/PqPEfwJu5YcZIq4YZdqpzJIUbANnRrFSvmoQpDb1PssdKx7Ds35hw==",
+ "node_modules/@mantine/store": {
+ "version": "7.6.1",
+ "resolved": "https://registry.npmjs.org/@mantine/store/-/store-7.6.1.tgz",
+ "integrity": "sha512-UqSsJLlAL53OSSUNK/aTXpkss9DX0TppTbtBKXPyflYfq0B9vKwQKumxEsg3UGVC4cjiQq2VD4mjGT94r+deug==",
"peerDependencies": {
"react": "^18.2.0"
}
@@ -2215,6 +2249,29 @@
"resolved": "mantine-ui",
"link": true
},
+ "node_modules/@reduxjs/toolkit": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.2.1.tgz",
+ "integrity": "sha512-8CREoqJovQW/5I4yvvijm/emUiCCmcs4Ev4XPWd4mizSO+dD3g5G6w34QK5AGeNrSH7qM8Fl66j4vuV7dpOdkw==",
+ "dependencies": {
+ "immer": "^10.0.3",
+ "redux": "^5.0.1",
+ "redux-thunk": "^3.1.0",
+ "reselect": "^5.0.1"
+ },
+ "peerDependencies": {
+ "react": "^16.9.0 || ^17.0.0 || ^18",
+ "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "react": {
+ "optional": true
+ },
+ "react-redux": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@remix-run/router": {
"version": "1.15.1",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.1.tgz",
@@ -2670,6 +2727,11 @@
"integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==",
"dev": true
},
+ "node_modules/@types/use-sync-external-store": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
+ "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA=="
+ },
"node_modules/@types/yargs": {
"version": "17.0.32",
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz",
@@ -3061,17 +3123,6 @@
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"dev": true
},
- "node_modules/aria-hidden": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.3.tgz",
- "integrity": "sha512-xcLxITLe2HYa1cnYnwCjkOO1PqUHQpozB8x9AR0OgWN2woOBi5kSDVxKfd0b7sb1hw5qFeJhXm9H1nu3xSfLeQ==",
- "dependencies": {
- "tslib": "^2.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/array-union": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
@@ -3415,14 +3466,6 @@
"node": ">=12"
}
},
- "node_modules/clsx": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz",
- "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==",
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/co": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
@@ -3541,8 +3584,7 @@
"node_modules/csstype": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
- "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
- "devOptional": true
+ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
},
"node_modules/dayjs": {
"version": "1.11.10",
@@ -3644,6 +3686,15 @@
"node": ">=6.0.0"
}
},
+ "node_modules/dom-helpers": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
+ "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
+ "dependencies": {
+ "@babel/runtime": "^7.8.7",
+ "csstype": "^3.0.2"
+ }
+ },
"node_modules/electron-to-chromium": {
"version": "1.4.678",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.678.tgz",
@@ -4354,6 +4405,15 @@
"node": ">= 4"
}
},
+ "node_modules/immer": {
+ "version": "10.0.3",
+ "resolved": "https://registry.npmjs.org/immer/-/immer-10.0.3.tgz",
+ "integrity": "sha512-pwupu3eWfouuaowscykeckFmVTpqbzW+rXFCX8rQLkZzM9ftBmU/++Ra+o+L27mz03zJTlyV4UUr+fdKNffo4A==",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/immer"
+ }
+ },
"node_modules/import-fresh": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
@@ -6107,6 +6167,32 @@
"react-dom": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0"
}
},
+ "node_modules/react-redux": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.1.0.tgz",
+ "integrity": "sha512-6qoDzIO+gbrza8h3hjMA9aq4nwVFCKFtY2iLxCtVT38Swyy2C/dJCGBXHeHLtx6qlg/8qzc2MrhOeduf5K32wQ==",
+ "dependencies": {
+ "@types/use-sync-external-store": "^0.0.3",
+ "use-sync-external-store": "^1.0.0"
+ },
+ "peerDependencies": {
+ "@types/react": "^18.2.25",
+ "react": "^18.0",
+ "react-native": ">=0.69",
+ "redux": "^5.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "react-native": {
+ "optional": true
+ },
+ "redux": {
+ "optional": true
+ }
+ }
+ },
"node_modules/react-refresh": {
"version": "0.14.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz",
@@ -6229,6 +6315,34 @@
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
+ "node_modules/react-transition-group": {
+ "version": "4.4.5",
+ "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
+ "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
+ "dependencies": {
+ "@babel/runtime": "^7.5.5",
+ "dom-helpers": "^5.0.1",
+ "loose-envify": "^1.4.0",
+ "prop-types": "^15.6.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.6.0",
+ "react-dom": ">=16.6.0"
+ }
+ },
+ "node_modules/redux": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
+ "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w=="
+ },
+ "node_modules/redux-thunk": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz",
+ "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==",
+ "peerDependencies": {
+ "redux": "^5.0.0"
+ }
+ },
"node_modules/regenerator-runtime": {
"version": "0.14.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
@@ -6244,6 +6358,11 @@
"node": ">=0.10.0"
}
},
+ "node_modules/reselect": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.0.tgz",
+ "integrity": "sha512-aw7jcGLDpSgNDyWBQLv2cedml85qd95/iszJjN988zX1t7AVRJi19d9kto5+W7oCfQ94gyo40dVbT6g2k4/kXg=="
+ },
"node_modules/resolve": {
"version": "1.22.8",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
@@ -6940,6 +7059,14 @@
}
}
},
+ "node_modules/use-sync-external-store": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
+ "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",