Merge remote-tracking branch 'origin/main' into fix-histogram-fraction-first-bucket

This commit is contained in:
György Krajcsovits 2026-04-07 17:50:22 +02:00
commit 2475a932d1
No known key found for this signature in database
GPG key ID: 47A8F9CE80FD7C7F
36 changed files with 215 additions and 1446 deletions

View file

@ -164,7 +164,12 @@ promql/parser/generated_parser.y.go: promql/parser/generated_parser.y
.PHONY: clean-parser
clean-parser:
@echo ">> cleaning generated parser"
ifeq (, $(shell command -v goyacc 2> /dev/null))
@echo "goyacc not installed so skipping"
@echo "To install: \"go install golang.org/x/tools/cmd/goyacc@$(GOYACC_VERSION)\" or run \"make install-goyacc\""
else
@rm -f promql/parser/generated_parser.y.go
endif
.PHONY: check-generated-parser
check-generated-parser: clean-parser promql/parser/generated_parser.y.go

View file

@ -55,7 +55,7 @@ ifneq ($(shell command -v gotestsum 2> /dev/null),)
endif
endif
PROMU_VERSION ?= 0.18.0
PROMU_VERSION ?= 0.18.1
PROMU_URL := https://github.com/prometheus/promu/releases/download/v$(PROMU_VERSION)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM).tar.gz
SKIP_GOLANGCI_LINT :=
@ -91,7 +91,7 @@ $(error DOCKERFILE_PATH is deprecated. Use DOCKERFILE_VARIANTS ?= $(DOCKERFILE_P
endif
DOCKER_ARCHS ?= amd64
DOCKERFILE_VARIANTS ?= Dockerfile $(wildcard Dockerfile.*)
DOCKERFILE_VARIANTS ?= $(wildcard Dockerfile Dockerfile.*)
# Function to extract variant from Dockerfile label.
# Returns the variant name from io.prometheus.image.variant label, or "default" if not found.

View file

@ -180,6 +180,7 @@ func main() {
queryInstantCmd.Arg("server", "Prometheus server to query.").Required().URLVar(&serverURL)
queryInstantExpr := queryInstantCmd.Arg("expr", "PromQL query expression.").Required().String()
queryInstantTime := queryInstantCmd.Flag("time", "Query evaluation time (RFC3339 or Unix timestamp).").String()
queryInstantHeaders := queryInstantCmd.Flag("header", "Extra headers to send to server.").StringMap()
queryRangeCmd := queryCmd.Command("range", "Run range query.")
queryRangeCmd.Arg("server", "Prometheus server to query.").Required().URLVar(&serverURL)
@ -393,7 +394,7 @@ func main() {
os.Exit(PushMetrics(remoteWriteURL, httpRoundTripper, *pushMetricsHeaders, *pushMetricsTimeout, *pushMetricsProtoMsg, *pushMetricsLabels, *metricFiles...))
case queryInstantCmd.FullCommand():
os.Exit(QueryInstant(serverURL, httpRoundTripper, *queryInstantExpr, *queryInstantTime, p))
os.Exit(QueryInstant(serverURL, httpRoundTripper, *queryInstantHeaders, *queryInstantExpr, *queryInstantTime, p))
case queryRangeCmd.FullCommand():
os.Exit(QueryRange(serverURL, httpRoundTripper, *queryRangeHeaders, *queryRangeExpr, *queryRangeBegin, *queryRangeEnd, *queryRangeStep, p))

View file

@ -95,7 +95,7 @@ func TestQueryInstant(t *testing.T) {
require.NoError(t, err)
p := &promqlPrinter{}
exitCode := QueryInstant(urlObject, http.DefaultTransport, "up", "300", p)
exitCode := QueryInstant(urlObject, http.DefaultTransport, map[string]string{}, "up", "300", p)
require.Equal(t, "/api/v1/query", getRequest().URL.Path)
form := getRequest().Form
require.Equal(t, "up", form.Get("query"))
@ -103,6 +103,22 @@ func TestQueryInstant(t *testing.T) {
require.Equal(t, 0, exitCode)
}
func TestQueryInstantHeaders(t *testing.T) {
t.Parallel()
s, getRequest := mockServer(200, `{"status": "success", "data": {"resultType": "vector", "result": []}}`)
defer s.Close()
urlObject, err := url.Parse(s.URL)
require.NoError(t, err)
p := &promqlPrinter{}
headers := map[string]string{"X-Scope-OrgID": "prom", "X-Custom": "value"}
exitCode := QueryInstant(urlObject, http.DefaultTransport, headers, "up", "300", p)
require.Equal(t, 0, exitCode)
require.Equal(t, "prom", getRequest().Header.Get("X-Scope-OrgID"))
require.Equal(t, "value", getRequest().Header.Get("X-Custom"))
}
func mockServer(code int, body string) (*httptest.Server, func() *http.Request) {
var req *http.Request
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

View file

@ -61,8 +61,8 @@ func newAPI(url *url.URL, roundTripper http.RoundTripper, headers map[string]str
}
// QueryInstant performs an instant query against a Prometheus server.
func QueryInstant(url *url.URL, roundTripper http.RoundTripper, query, evalTime string, p printer) int {
api, err := newAPI(url, roundTripper, nil)
func QueryInstant(url *url.URL, roundTripper http.RoundTripper, headers map[string]string, query, evalTime string, p printer) int {
api, err := newAPI(url, roundTripper, headers)
if err != nil {
fmt.Fprintln(os.Stderr, "error creating API client:", err)
return failureExitCode

View file

@ -240,6 +240,7 @@ Run instant query.
| Flag | Description |
| --- | --- |
| <code class="text-nowrap">--time</code> | Query evaluation time (RFC3339 or Unix timestamp). |
| <code class="text-nowrap">--header</code> | Extra headers to send to server. |

View file

@ -16,6 +16,7 @@ package rules
import (
"context"
"errors"
"runtime"
"testing"
"time"
@ -538,8 +539,11 @@ instance: {{ $v.Labels.instance }}, value: {{ printf "%.0f" $v.Value }};
close(startQueryCh)
select {
case <-getDoneCh:
case <-time.After(time.Millisecond * 10):
case <-time.After(20 * time.Millisecond):
// Assert no blocking when template expanding.
buf := make([]byte, 1<<20)
n := runtime.Stack(buf, true)
t.Logf("goroutine dump:\n%s", buf[:n])
require.Fail(t, "unexpected blocking when template expanding.")
}
}

View file

@ -443,7 +443,6 @@ func (api *API) Register(r *route.Router) {
r.Get("/series", wrapAgent(api.series))
r.Post("/series", wrapAgent(api.series))
r.Del("/series", wrapAgent(api.dropSeries))
r.Get("/scrape_pools", wrap(api.scrapePools))
r.Get("/targets", wrap(api.targets))
@ -1047,10 +1046,6 @@ func (api *API) series(r *http.Request) (result apiFuncResult) {
return apiFuncResult{metrics, nil, warnings, closer}
}
func (*API) dropSeries(*http.Request) apiFuncResult {
return apiFuncResult{nil, &apiError{errorInternal, errors.New("not implemented")}, nil, nil}
}
// Target has the information for one target.
type Target struct {
// Labels before any processing.

View file

@ -61,6 +61,7 @@ import (
"github.com/prometheus/prometheus/util/stats"
"github.com/prometheus/prometheus/util/teststorage"
"github.com/prometheus/prometheus/util/testutil"
"github.com/prometheus/prometheus/web/api/testhelpers"
)
var testParser = parser.NewParser(parser.Options{})
@ -1768,10 +1769,6 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, testLabelAPI
endpoint: api.series,
errType: errorBadData,
},
{
endpoint: api.dropSeries,
errType: errorInternal,
},
{
endpoint: api.targets,
response: &TargetDiscovery{
@ -4931,3 +4928,19 @@ func (*fakeQuery) Cancel() {}
func (q *fakeQuery) String() string {
return q.query
}
// TestDeleteSeriesEndpointRemoved verifies that the deprecated DELETE /api/v1/series
// endpoint is no longer registered and does not return HTTP 500 "not implemented".
func TestDeleteSeriesEndpointRemoved(t *testing.T) {
api := newTestAPI(t, testhelpers.APIConfig{})
req := httptest.NewRequest(http.MethodDelete, "/api/v1/series", http.NoBody)
recorder := httptest.NewRecorder()
api.Handler.ServeHTTP(recorder, req)
// The endpoint previously returned HTTP 500 with "not implemented".
// After removal, the router should no longer match DELETE on /series,
// so we must not get the old 500 error.
require.NotEqual(t, http.StatusInternalServerError, recorder.Code,
"DELETE /api/v1/series should no longer return 500; the endpoint has been removed")
}

View file

@ -914,20 +914,6 @@ func cleanTombstonesResponseExamples() *orderedmap.Map[string, *base.Example] {
return examples
}
// seriesDeleteResponseExamples returns examples for DELETE /series response.
func seriesDeleteResponseExamples() *orderedmap.Map[string, *base.Example] {
examples := orderedmap.New[string, *base.Example]()
examples.Set("seriesDeleted", &base.Example{
Summary: "Series marked for deletion",
Value: createYAMLNode(map[string]any{
"status": "success",
}),
})
return examples
}
// snapshotResponseExamples returns examples for /admin/tsdb/snapshot response.
func snapshotResponseExamples() *orderedmap.Map[string, *base.Example] {
examples := orderedmap.New[string, *base.Example]()

View file

@ -224,13 +224,6 @@ func (*OpenAPIBuilder) seriesPath() *v3.PathItem {
RequestBody: formRequestBodyWithExamples("SeriesPostInputBody", seriesPostExamples(), "Submit a series query. This endpoint accepts the same parameters as the GET version."),
Responses: responsesWithErrorExamples("SeriesOutputBody", seriesResponseExamples(), errorResponseExamples(), "Series returned matching the provided label matchers via POST.", "Error retrieving series via POST."),
},
Delete: &v3.Operation{
OperationId: "delete-series",
Summary: "Delete series",
Description: "Delete series matching selectors. Note: This is deprecated, use POST /admin/tsdb/delete_series instead.",
Tags: []string{"series"},
Responses: responsesWithErrorExamples("SeriesDeleteOutputBody", seriesDeleteResponseExamples(), errorResponseExamples(), "Series marked for deletion.", "Error deleting series."),
},
}
}

View file

@ -58,7 +58,6 @@ func (b *OpenAPIBuilder) buildComponents() *v3.Components {
// Series schemas.
schemas.Set("SeriesOutputBody", b.labelsArrayResponseBodySchema())
schemas.Set("SeriesPostInputBody", b.seriesPostInputBodySchema())
schemas.Set("SeriesDeleteOutputBody", b.simpleResponseBodySchema())
// Metadata schemas.
schemas.Set("Metadata", b.metadataSchema())

View file

@ -1182,37 +1182,6 @@ paths:
error: TSDB not ready
errorType: internal
status: error
delete:
tags:
- series
summary: Delete series
description: 'Delete series matching selectors. Note: This is deprecated, use POST /admin/tsdb/delete_series instead.'
operationId: delete-series
responses:
"200":
description: Series marked for deletion.
content:
application/json:
schema:
$ref: '#/components/schemas/SeriesDeleteOutputBody'
examples:
seriesDeleted:
summary: Series marked for deletion
value:
status: success
default:
description: Error deleting series.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
examples:
tsdbNotReady:
summary: TSDB not ready
value:
error: TSDB not ready
errorType: internal
status: error
/metadata:
get:
tags:
@ -3224,35 +3193,6 @@ components:
- match[]
additionalProperties: false
description: POST request body for series query.
SeriesDeleteOutputBody:
type: object
properties:
status:
type: string
enum:
- success
- error
description: Response status.
example: success
data:
description: Response data (structure varies by endpoint).
example:
result: ok
warnings:
type: array
items:
type: string
description: Only set if there were warnings while executing the request. There will still be data in the data field.
infos:
type: array
items:
type: string
description: Only set if there were info-level annotations while executing the request.
required:
- status
- data
additionalProperties: false
description: Generic response body.
Metadata:
type: object
properties:

View file

@ -1182,37 +1182,6 @@ paths:
error: TSDB not ready
errorType: internal
status: error
delete:
tags:
- series
summary: Delete series
description: 'Delete series matching selectors. Note: This is deprecated, use POST /admin/tsdb/delete_series instead.'
operationId: delete-series
responses:
"200":
description: Series marked for deletion.
content:
application/json:
schema:
$ref: '#/components/schemas/SeriesDeleteOutputBody'
examples:
seriesDeleted:
summary: Series marked for deletion
value:
status: success
default:
description: Error deleting series.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
examples:
tsdbNotReady:
summary: TSDB not ready
value:
error: TSDB not ready
errorType: internal
status: error
/metadata:
get:
tags:
@ -3262,35 +3231,6 @@ components:
- match[]
additionalProperties: false
description: POST request body for series query.
SeriesDeleteOutputBody:
type: object
properties:
status:
type: string
enum:
- success
- error
description: Response status.
example: success
data:
description: Response data (structure varies by endpoint).
example:
result: ok
warnings:
type: array
items:
type: string
description: Only set if there were warnings while executing the request. There will still be data in the data field.
infos:
type: array
items:
type: string
description: Only set if there were info-level annotations while executing the request.
required:
- status
- data
additionalProperties: false
description: Generic response body.
Metadata:
type: object
properties:

View file

@ -20,11 +20,11 @@
"@floating-ui/dom": "^1.7.6",
"@lezer/common": "^1.5.1",
"@lezer/highlight": "^1.2.3",
"@mantine/code-highlight": "^8.3.18",
"@mantine/core": "^8.3.18",
"@mantine/dates": "^8.3.18",
"@mantine/hooks": "^8.3.18",
"@mantine/notifications": "^8.3.18",
"@mantine/code-highlight": "^9.0.1",
"@mantine/core": "^9.0.1",
"@mantine/dates": "^9.0.1",
"@mantine/hooks": "^9.0.1",
"@mantine/notifications": "^9.0.1",
"@microsoft/fetch-event-source": "^2.0.1",
"@nexucis/fuzzy": "^0.5.1",
"@nexucis/kvsearch": "^0.9.1",

View file

@ -167,6 +167,8 @@ const serverStatusPages = [
const allStatusPages = [...monitoringStatusPages, ...serverStatusPages];
const theme = createTheme({
// Preserve v8 default border-radius for now (was 'sm' in v8, changed to 'md' in v9).
defaultRadius: "sm",
colors: {
"codebox-bg": [
"#f5f5f5",

View file

@ -1,56 +0,0 @@
/*
* Some parts of this file are derived from Mantine UI (https://github.com/mantinedev/mantine)
* which is distributed under the MIT license:
*
* MIT License
*
* Copyright (c) 2021 Vitaly Rtishchev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Modifications to this file are licensed under the Apache License, Version 2.0.
*/
import { createSafeContext, GetStylesApi } from "@mantine/core";
import type { AccordionFactory } from "./Accordion";
import {
AccordionChevronPosition,
AccordionHeadingOrder,
} from "./Accordion.types";
interface AccordionContext {
loop: boolean | undefined;
transitionDuration: number | undefined;
disableChevronRotation: boolean | undefined;
chevronPosition: AccordionChevronPosition | undefined;
order: AccordionHeadingOrder | undefined;
chevron: React.ReactNode;
onChange: (value: string) => void;
isItemActive: (value: string) => boolean;
getControlId: (value: string) => string;
getRegionId: (value: string) => string;
getStyles: GetStylesApi<AccordionFactory>;
variant: string | undefined;
unstyled: boolean | undefined;
}
export const [AccordionProvider, useAccordionContext] =
createSafeContext<AccordionContext>(
"Accordion component was not found in the tree"
);

View file

@ -1,204 +0,0 @@
/*
* Some parts of this file are derived from Mantine UI (https://github.com/mantinedev/mantine)
* which is distributed under the MIT license:
*
* MIT License
*
* Copyright (c) 2021 Vitaly Rtishchev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Modifications to this file are licensed under the Apache License, Version 2.0.
*/
.root {
--accordion-radius: var(--mantine-radius-default);
}
.panel {
overflow-wrap: break-word;
}
.content {
padding: var(--mantine-spacing-md);
padding-top: calc(var(--mantine-spacing-xs) / 2);
}
.itemTitle {
margin: 0;
padding: 0;
}
.control {
width: 100%;
display: flex;
align-items: center;
flex-direction: row-reverse;
padding-inline: var(--mantine-spacing-md);
opacity: 1;
cursor: pointer;
background-color: transparent;
color: var(--mantine-color-bright);
&:where([data-chevron-position="left"]) {
flex-direction: row;
padding-inline-start: 0;
}
&:where(:disabled, [data-disabled]) {
opacity: 0.4;
cursor: not-allowed;
}
}
.control--default,
.control--contained {
&:where(:not(:disabled, [data-disabled])) {
@mixin hover {
@mixin where-light {
background-color: var(--mantine-color-gray-0);
}
@mixin where-dark {
background-color: var(--mantine-color-dark-6);
}
}
}
}
.label {
color: inherit;
font-weight: 400;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
padding-top: var(--mantine-spacing-sm);
padding-bottom: var(--mantine-spacing-sm);
}
.chevron {
display: flex;
align-items: center;
justify-content: flex-start;
transition: transform var(--accordion-transition-duration, 200ms) ease;
width: var(--accordion-chevron-size, rem(15px));
min-width: var(--accordion-chevron-size, rem(15px));
transform: rotate(0deg);
&:where([data-rotate]) {
transform: rotate(180deg);
}
&:where([data-position="left"]) {
margin-inline-end: var(--mantine-spacing-md);
margin-inline-start: var(--mantine-spacing-md);
}
}
.icon {
display: flex;
align-items: center;
justify-content: center;
margin-inline-end: var(--mantine-spacing-sm);
&:where([data-chevron-position="left"]) {
margin-inline-end: 0;
margin-inline-start: var(--mantine-spacing-lg);
}
}
.item {
@mixin where-light {
--item-border-color: var(--mantine-color-gray-3);
--item-filled-color: var(--mantine-color-gray-0);
}
@mixin where-dark {
--item-border-color: var(--mantine-color-dark-4);
--item-filled-color: var(--mantine-color-dark-6);
}
}
.item--default {
border-bottom: 1px solid var(--item-border-color);
}
.item--contained {
border: 1px solid var(--item-border-color);
transition: background-color 150ms ease;
&:where([data-active]) {
background-color: var(--item-filled-color);
}
&:first-of-type {
border-start-start-radius: var(--accordion-radius);
border-start-end-radius: var(--accordion-radius);
& > [data-accordion-control] {
border-start-start-radius: var(--accordion-radius);
border-start-end-radius: var(--accordion-radius);
}
}
&:last-of-type {
border-end-start-radius: var(--accordion-radius);
border-end-end-radius: var(--accordion-radius);
& > [data-accordion-control] {
border-end-start-radius: var(--accordion-radius);
border-end-end-radius: var(--accordion-radius);
}
}
& + & {
border-top: 0;
}
}
.item--filled {
border-radius: var(--accordion-radius);
&:where([data-active]) {
background-color: var(--item-filled-color);
}
}
.item--separated {
background-color: var(--item-filled-color);
border-radius: var(--accordion-radius);
border: 1px solid transparent;
transition: background-color 150ms ease;
&[data-active] {
border-color: var(--item-border-color);
@mixin where-light {
background-color: var(--mantine-color-white);
}
@mixin where-dark {
background-color: var(--mantine-color-dark-7);
}
}
& + & {
margin-top: var(--mantine-spacing-md);
}
}

View file

@ -1,280 +0,0 @@
/*
* Some parts of this file are derived from Mantine UI (https://github.com/mantinedev/mantine)
* which is distributed under the MIT license:
*
* MIT License
*
* Copyright (c) 2021 Vitaly Rtishchev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Modifications to this file are licensed under the Apache License, Version 2.0.
*/
import { useId, useUncontrolled } from "@mantine/hooks";
import {
Box,
BoxProps,
createVarsResolver,
ElementProps,
ExtendComponent,
Factory,
getRadius,
getSafeId,
getWithProps,
MantineRadius,
MantineThemeComponent,
rem,
StylesApiProps,
useProps,
useStyles,
} from "@mantine/core";
import { AccordionProvider } from "./Accordion.context";
import {
AccordionChevronPosition,
AccordionHeadingOrder,
AccordionValue,
} from "./Accordion.types";
import { AccordionChevron } from "./AccordionChevron";
import { AccordionControl } from "./AccordionControl/AccordionControl";
import { AccordionItem } from "./AccordionItem/AccordionItem";
import { AccordionPanel } from "./AccordionPanel/AccordionPanel";
import classes from "./Accordion.module.css";
export type AccordionStylesNames =
| "root"
| "content"
| "item"
| "panel"
| "icon"
| "chevron"
| "label"
| "itemTitle"
| "control";
export type AccordionVariant = "default" | "contained" | "filled" | "separated";
export type AccordionCssVariables = {
root:
| "--accordion-transition-duration"
| "--accordion-chevron-size"
| "--accordion-radius";
};
export interface AccordionProps<Multiple extends boolean = false>
extends BoxProps,
StylesApiProps<AccordionFactory>,
ElementProps<"div", "value" | "defaultValue" | "onChange"> {
/** If set, multiple items can be opened at the same time */
multiple?: Multiple;
/** Controlled component value */
value?: AccordionValue<Multiple>;
/** Uncontrolled component default value */
defaultValue?: AccordionValue<Multiple>;
/** Called when value changes, payload type depends on `multiple` prop */
onChange?: (value: AccordionValue<Multiple>) => void;
/** If set, arrow keys loop though items (first to last and last to first) @default `true` */
loop?: boolean;
/** Transition duration in ms @default `200` */
transitionDuration?: number;
/** If set, chevron rotation is disabled */
disableChevronRotation?: boolean;
/** Position of the chevron relative to the item label @default `right` */
chevronPosition?: AccordionChevronPosition;
/** Size of the chevron icon container @default `auto` */
chevronSize?: number | string;
/** Size of the default chevron icon. Ignored when `chevron` prop is set. @default `16` */
chevronIconSize?: number | string;
/** Heading order, has no effect on visuals */
order?: AccordionHeadingOrder;
/** Custom chevron icon */
chevron?: React.ReactNode;
/** Key of `theme.radius` or any valid CSS value to set border-radius. Numbers are converted to rem. @default `theme.defaultRadius` */
radius?: MantineRadius;
}
export type AccordionFactory = Factory<{
props: AccordionProps;
ref: HTMLDivElement;
stylesNames: AccordionStylesNames;
vars: AccordionCssVariables;
variant: AccordionVariant;
}>;
const defaultProps = {
multiple: false,
disableChevronRotation: false,
chevronPosition: "right",
variant: "default",
chevronSize: "auto",
chevronIconSize: 16,
} satisfies Partial<AccordionProps>;
const varsResolver = createVarsResolver<AccordionFactory>(
(_, { transitionDuration, chevronSize, radius }) => ({
root: {
"--accordion-transition-duration":
transitionDuration === undefined
? undefined
: `${transitionDuration}ms`,
"--accordion-chevron-size":
chevronSize === undefined ? undefined : rem(chevronSize),
"--accordion-radius":
radius === undefined ? undefined : getRadius(radius),
},
})
);
export function Accordion<Multiple extends boolean = false>(
_props: AccordionProps<Multiple>
) {
const props = useProps(
"Accordion",
defaultProps as AccordionProps<Multiple>,
_props
);
const {
classNames,
className,
style,
styles,
unstyled,
vars,
children,
multiple,
value,
defaultValue,
onChange,
id,
loop,
transitionDuration,
disableChevronRotation,
chevronPosition,
chevronSize,
order,
chevron,
variant,
radius,
chevronIconSize,
attributes,
...others
} = props;
const uid = useId(id);
const [_value, handleChange] = useUncontrolled({
value,
defaultValue,
finalValue: multiple ? ([] as any) : null,
onChange,
});
const isItemActive = (itemValue: string) =>
Array.isArray(_value) ? _value.includes(itemValue) : itemValue === _value;
const handleItemChange = (itemValue: string) => {
const nextValue: AccordionValue<Multiple> = Array.isArray(_value)
? _value.includes(itemValue)
? _value.filter((selectedValue) => selectedValue !== itemValue)
: [..._value, itemValue]
: itemValue === _value
? null
: (itemValue as any);
handleChange(nextValue);
};
const getStyles = useStyles<AccordionFactory>({
name: "Accordion",
classes,
props: props as AccordionProps,
className,
style,
classNames,
styles,
unstyled,
attributes,
vars,
varsResolver,
});
return (
<AccordionProvider
value={{
isItemActive,
onChange: handleItemChange,
getControlId: getSafeId(
`${uid}-control`,
"Accordion.Item component was rendered with invalid value or without value"
),
getRegionId: getSafeId(
`${uid}-panel`,
"Accordion.Item component was rendered with invalid value or without value"
),
chevron:
chevron === null
? null
: chevron || <AccordionChevron size={chevronIconSize} />,
transitionDuration,
disableChevronRotation,
chevronPosition,
order,
loop,
getStyles,
variant,
unstyled,
}}
>
<Box
{...getStyles("root")}
id={uid}
{...others}
variant={variant}
data-accordion
>
{children}
</Box>
</AccordionProvider>
);
}
const extendAccordion = (
c: ExtendComponent<AccordionFactory>
): MantineThemeComponent => c;
Accordion.extend = extendAccordion;
Accordion.withProps = getWithProps<AccordionProps, AccordionProps>(
Accordion as any
);
Accordion.classes = classes;
Accordion.displayName = "@mantine/core/Accordion";
Accordion.Item = AccordionItem;
Accordion.Panel = AccordionPanel;
Accordion.Control = AccordionControl;
Accordion.Chevron = AccordionChevron;

View file

@ -1,35 +0,0 @@
/*
* Some parts of this file are derived from Mantine UI (https://github.com/mantinedev/mantine)
* which is distributed under the MIT license:
*
* MIT License
*
* Copyright (c) 2021 Vitaly Rtishchev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Modifications to this file are licensed under the Apache License, Version 2.0.
*/
export type AccordionValue<Multiple extends boolean> = Multiple extends true
? string[]
: string | null;
export type AccordionHeadingOrder = 2 | 3 | 4 | 5 | 6;
export type AccordionChevronPosition = "left" | "right";

View file

@ -1,66 +0,0 @@
/*
* Some parts of this file are derived from Mantine UI (https://github.com/mantinedev/mantine)
* which is distributed under the MIT license:
*
* MIT License
*
* Copyright (c) 2021 Vitaly Rtishchev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Modifications to this file are licensed under the Apache License, Version 2.0.
*/
import { rem } from "@mantine/core";
export interface AccordionChevronProps
extends React.ComponentPropsWithoutRef<"svg"> {
/** Controls `width` and `height` of the icon, `16` by default */
size?: number | string;
}
export function AccordionChevron({
style,
size = 16,
...others
}: AccordionChevronProps) {
return (
<svg
viewBox="0 0 15 15"
fill="none"
xmlns="http://www.w3.org/2000/svg"
style={{
...style,
width: rem(size),
height: rem(size),
display: "block",
}}
{...others}
>
<path
d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z"
fill="currentColor"
fillRule="evenodd"
clipRule="evenodd"
/>
</svg>
);
}
AccordionChevron.displayName = "@mantine/core/AccordionChevron";

View file

@ -1,175 +0,0 @@
/*
* Some parts of this file are derived from Mantine UI (https://github.com/mantinedev/mantine)
* which is distributed under the MIT license:
*
* MIT License
*
* Copyright (c) 2021 Vitaly Rtishchev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Modifications to this file are licensed under the Apache License, Version 2.0.
*/
import {
Box,
BoxProps,
CompoundStylesApiProps,
createScopedKeydownHandler,
ElementProps,
factory,
Factory,
UnstyledButton,
useProps,
} from "@mantine/core";
import { useAccordionContext } from "../Accordion.context";
import { useAccordionItemContext } from "../AccordionItem.context";
import classes from "../Accordion.module.css";
export type AccordionControlStylesNames =
| "control"
| "chevron"
| "label"
| "itemTitle"
| "icon";
export interface AccordionControlProps
extends BoxProps,
CompoundStylesApiProps<AccordionControlFactory>,
ElementProps<"button"> {
/** Sets `disabled` attribute, prevents interactions */
disabled?: boolean;
/** Custom chevron icon */
chevron?: React.ReactNode;
/** Control label */
children?: React.ReactNode;
/** Icon displayed next to the label */
icon?: React.ReactNode;
}
export type AccordionControlFactory = Factory<{
props: AccordionControlProps;
ref: HTMLButtonElement;
stylesNames: AccordionControlStylesNames;
compound: true;
}>;
export const AccordionControl = factory<AccordionControlFactory>(
(props, ref) => {
const {
classNames,
className,
style,
styles,
vars,
chevron,
icon,
onClick,
onKeyDown,
children,
disabled,
mod,
...others
} = useProps("AccordionControl", null, props);
const { value } = useAccordionItemContext();
const ctx = useAccordionContext();
const isActive = ctx.isItemActive(value);
const shouldWrapWithHeading = typeof ctx.order === "number";
const Heading = `h${ctx.order!}` as const;
const content = (
<UnstyledButton<"button">
{...others}
{...ctx.getStyles("control", {
className,
classNames,
style,
styles,
variant: ctx.variant,
})}
unstyled={ctx.unstyled}
mod={[
"accordion-control",
{
active: isActive,
"chevron-position": ctx.chevronPosition,
disabled,
},
mod,
]}
ref={ref}
onClick={(event) => {
onClick?.(event);
ctx.onChange(value);
}}
type="button"
disabled={disabled}
aria-expanded={isActive}
aria-controls={ctx.getRegionId(value)}
id={ctx.getControlId(value)}
onKeyDown={createScopedKeydownHandler({
siblingSelector: "[data-accordion-control]",
parentSelector: "[data-accordion]",
activateOnFocus: false,
loop: ctx.loop,
orientation: "vertical",
onKeyDown,
})}
>
<Box
component="span"
mod={{
rotate: !ctx.disableChevronRotation && isActive,
position: ctx.chevronPosition,
}}
{...ctx.getStyles("chevron", { classNames, styles })}
>
{chevron || ctx.chevron}
</Box>
<span {...ctx.getStyles("label", { classNames, styles })}>
{children}
</span>
{icon && (
<Box
component="span"
mod={{ "chevron-position": ctx.chevronPosition }}
{...ctx.getStyles("icon", { classNames, styles })}
>
{icon}
</Box>
)}
</UnstyledButton>
);
return shouldWrapWithHeading ? (
<Heading {...ctx.getStyles("itemTitle", { classNames, styles })}>
{content}
</Heading>
) : (
content
);
}
);
AccordionControl.displayName = "@mantine/core/AccordionControl";
AccordionControl.classes = classes;

View file

@ -1,39 +0,0 @@
/*
* Some parts of this file are derived from Mantine UI (https://github.com/mantinedev/mantine)
* which is distributed under the MIT license:
*
* MIT License
*
* Copyright (c) 2021 Vitaly Rtishchev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Modifications to this file are licensed under the Apache License, Version 2.0.
*/
import { createSafeContext } from "@mantine/core";
interface AccordionItemContext {
value: string;
}
export const [AccordionItemProvider, useAccordionItemContext] =
createSafeContext<AccordionItemContext>(
"Accordion.Item component was not found in the tree"
);

View file

@ -1,84 +0,0 @@
/*
* Some parts of this file are derived from Mantine UI (https://github.com/mantinedev/mantine)
* which is distributed under the MIT license:
*
* MIT License
*
* Copyright (c) 2021 Vitaly Rtishchev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Modifications to this file are licensed under the Apache License, Version 2.0.
*/
import {
Box,
BoxProps,
CompoundStylesApiProps,
ElementProps,
factory,
Factory,
useProps,
} from "@mantine/core";
import { useAccordionContext } from "../Accordion.context";
import { AccordionItemProvider } from "../AccordionItem.context";
import classes from "../Accordion.module.css";
export type AccordionItemStylesNames = "item";
export interface AccordionItemProps
extends BoxProps,
CompoundStylesApiProps<AccordionItemFactory>,
ElementProps<"div"> {
/** Value that is used to manage the accordion state */
value: string;
}
export type AccordionItemFactory = Factory<{
props: AccordionItemProps;
ref: HTMLDivElement;
stylesNames: AccordionItemStylesNames;
compound: true;
}>;
export const AccordionItem = factory<AccordionItemFactory>((props, ref) => {
const { classNames, className, style, styles, vars, value, mod, ...others } =
useProps("AccordionItem", null, props);
const ctx = useAccordionContext();
return (
<AccordionItemProvider value={{ value }}>
<Box
ref={ref}
mod={[{ active: ctx.isItemActive(value) }, mod]}
{...ctx.getStyles("item", {
className,
classNames,
styles,
style,
variant: ctx.variant,
})}
{...others}
/>
</AccordionItemProvider>
);
});
AccordionItem.displayName = "@mantine/core/AccordionItem";
AccordionItem.classes = classes;

View file

@ -1,106 +0,0 @@
/*
* Some parts of this file are derived from Mantine UI (https://github.com/mantinedev/mantine)
* which is distributed under the MIT license:
*
* MIT License
*
* Copyright (c) 2021 Vitaly Rtishchev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Modifications to this file are licensed under the Apache License, Version 2.0.
*/
import {
BoxProps,
Collapse,
CompoundStylesApiProps,
ElementProps,
factory,
Factory,
useProps,
} from "@mantine/core";
import { useAccordionContext } from "../Accordion.context";
import { useAccordionItemContext } from "../AccordionItem.context";
import classes from "../Accordion.module.css";
import { useEffect, useState } from "react";
export type AccordionPanelStylesNames = "panel" | "content";
export interface AccordionPanelProps
extends BoxProps,
CompoundStylesApiProps<AccordionPanelFactory>,
ElementProps<"div"> {
/** Called when the panel animation completes */
onTransitionEnd?: () => void;
}
export type AccordionPanelFactory = Factory<{
props: AccordionPanelProps;
ref: HTMLDivElement;
stylesNames: AccordionPanelStylesNames;
compound: true;
}>;
export const AccordionPanel = factory<AccordionPanelFactory>((props, ref) => {
const { classNames, className, style, styles, vars, children, ...others } =
useProps("AccordionPanel", null, props);
const { value } = useAccordionItemContext();
const ctx = useAccordionContext();
const isActive = ctx.isItemActive(value);
// Prometheus-specific Accordion modification: unmount children when panel is closed.
const [showChildren, setShowChildren] = useState(isActive);
// Hide children from DOM 200ms after collapsing the panel
// to give the animation time to finish.
useEffect(() => {
let timeout: ReturnType<typeof setTimeout>;
if (isActive) {
setShowChildren(true);
} else {
timeout = setTimeout(() => setShowChildren(false), 200);
}
return () => clearTimeout(timeout);
}, [isActive]);
return (
<Collapse
ref={ref}
{...ctx.getStyles("panel", { className, classNames, style, styles })}
{...others}
in={isActive}
transitionDuration={ctx.transitionDuration ?? 200}
role="region"
id={ctx.getRegionId(value)}
aria-labelledby={ctx.getControlId(value)}
>
<div {...ctx.getStyles("content", { classNames, styles })}>
{/* Prometheus-specific Accordion modification: unmount children when panel is closed. */}
{showChildren && children}
</div>
</Collapse>
);
});
AccordionPanel.displayName = "@mantine/core/AccordionPanel";
AccordionPanel.classes = classes;

View file

@ -1,10 +0,0 @@
This is a temporary fork of the Accordion component from Mantine UI v8.3.6 with modifications specific to Prometheus.
The component has been modified to unmount children of collapsed panels to reduce page rendering times and
resource usage.
According to Mantine author Vitaly, a similar feature has now been added to Mantine itself, but will only be
available in version 9.0.0 and later, quote from https://discord.com/channels/854810300876062770/1006447791498870784/threads/1428787320546525336:
> I've managed to implement it, but only in 9.0 since it requires some breaking changes. Will be available next year
So this Accordion fork can be removed once Prometheus upgrades to Mantine v9 or later.

View file

@ -1,47 +0,0 @@
/*
* Some parts of this file are derived from Mantine UI (https://github.com/mantinedev/mantine)
* which is distributed under the MIT license:
*
* MIT License
*
* Copyright (c) 2021 Vitaly Rtishchev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Modifications to this file are licensed under the Apache License, Version 2.0.
*/
export { Accordion } from "./Accordion";
export { AccordionChevron } from "./AccordionChevron";
export { AccordionItem } from "./AccordionItem/AccordionItem";
export { AccordionPanel } from "./AccordionPanel/AccordionPanel";
export { AccordionControl } from "./AccordionControl/AccordionControl";
export type {
AccordionProps,
AccordionStylesNames,
AccordionCssVariables,
AccordionFactory,
AccordionVariant,
} from "./Accordion";
export type { AccordionControlProps } from "./AccordionControl/AccordionControl";
export type { AccordionItemProps } from "./AccordionItem/AccordionItem";
export type { AccordionPanelProps } from "./AccordionPanel/AccordionPanel";
export type { AccordionChevronProps } from "./AccordionChevron";
export type { AccordionValue, AccordionHeadingOrder } from "./Accordion.types";

View file

@ -1,4 +1,5 @@
import {
Accordion,
Card,
Group,
Table,
@ -38,7 +39,6 @@ import { KVSearch } from "@nexucis/kvsearch";
import { inputIconStyle } from "../styles";
import CustomInfiniteScroll from "../components/CustomInfiniteScroll";
import classes from "./AlertsPage.module.css";
import { Accordion } from "../components/Accordion";
type AlertsPageData = {
// How many rules are in each state across all groups.
@ -287,7 +287,7 @@ export default function AlertsPage() {
<CustomInfiniteScroll
allItems={g.rules}
child={({ items }) => (
<Accordion multiple variant="separated" classNames={classes}>
<Accordion multiple variant="separated" keepMounted={false} classNames={classes}>
{items.map((r, j) => {
return (
<Accordion.Item

View file

@ -1,4 +1,5 @@
import {
Accordion,
Alert,
Anchor,
Badge,
@ -45,7 +46,6 @@ import classes from "./RulesPage.module.css";
import { useDebouncedValue, useLocalStorage } from "@mantine/hooks";
import { KVSearch } from "@nexucis/kvsearch";
import { StateMultiSelect } from "../components/StateMultiSelect";
import { Accordion } from "../components/Accordion";
const kvSearch = new KVSearch<Rule>({
shouldSort: true,
@ -231,7 +231,7 @@ export default function RulesPage() {
<CustomInfiniteScroll
allItems={g.rules}
child={({ items }) => (
<Accordion multiple variant="separated" classNames={classes}>
<Accordion multiple variant="separated" keepMounted={false} classNames={classes}>
{items.map((r, j) => (
<Accordion.Item
mt={rem(5)}

View file

@ -273,7 +273,7 @@ const QueryPanel: FC<PanelProps> = ({ idx, metricNames }) => {
{
value: GraphDisplayMode.Lines,
label: (
<Center>
<Center fw={500}>
<IconChartLine style={iconStyle} />
<Box ml={10}>Unstacked</Box>
</Center>
@ -282,7 +282,7 @@ const QueryPanel: FC<PanelProps> = ({ idx, metricNames }) => {
{
value: GraphDisplayMode.Stacked,
label: (
<Center>
<Center fw={500}>
<IconChartAreaFilled style={iconStyle} />
<Box ml={10}>Stacked</Box>
</Center>

View file

@ -1,4 +1,5 @@
import {
Accordion,
Alert,
Anchor,
Box,
@ -32,7 +33,6 @@ import { targetPoolDisplayLimit } from "./ServiceDiscoveryPage";
import { LabelBadges } from "../../components/LabelBadges";
import ErrorBoundary from "../../components/ErrorBoundary";
import RelabelSteps from "./RelabelSteps";
import { Accordion } from "../../components/Accordion";
type TargetLabels = {
discoveredLabels: Labels;
@ -238,6 +238,7 @@ const ScrapePoolList: FC<ScrapePoolListProp> = ({
<Accordion
multiple
variant="separated"
keepMounted={false}
value={allPoolNames.filter((p) => !collapsedPools.includes(p))}
onChange={(value) =>
dispatch(

View file

@ -1,4 +1,5 @@
import {
Accordion,
Alert,
Anchor,
Badge,
@ -27,7 +28,6 @@ import panelClasses from "../../Panel.module.css";
import TargetLabels from "./TargetLabels";
import ScrapeTimingDetails from "./ScrapeTimingDetails";
import { targetPoolDisplayLimit } from "./TargetsPage";
import { Accordion } from "../../components/Accordion";
type ScrapePool = {
targets: Target[];
@ -209,6 +209,7 @@ const ScrapePoolList: FC<ScrapePoolListProp> = memo(
<Accordion
multiple
variant="separated"
keepMounted={false}
value={allPoolNames.filter((p) => !collapsedPools.includes(p))}
onChange={(value) =>
dispatch(

View file

@ -67,7 +67,7 @@ const ScrapeTimingDetails: FC<ScrapeTimingDetailsProps> = ({ target }) => {
</ActionIcon>
</Group>
<Collapse in={showDetails}>
<Collapse expanded={showDetails}>
{/* Additionally remove DOM elements when not expanded (helps performance) */}
{showDetails && (
<Group gap="xs" wrap="wrap">

View file

@ -34,7 +34,7 @@ const TargetLabels: FC<TargetLabelsProps> = ({ discoveredLabels, labels }) => {
</ActionIcon>
</Group>
<Collapse in={showDiscovered}>
<Collapse expanded={showDiscovered}>
{/* Additionally remove DOM elements when not expanded (helps performance) */}
{showDiscovered && (
<>

314
web/ui/package-lock.json generated
View file

@ -34,11 +34,11 @@
"@floating-ui/dom": "^1.7.6",
"@lezer/common": "^1.5.1",
"@lezer/highlight": "^1.2.3",
"@mantine/code-highlight": "^8.3.18",
"@mantine/core": "^8.3.18",
"@mantine/dates": "^8.3.18",
"@mantine/hooks": "^8.3.18",
"@mantine/notifications": "^8.3.18",
"@mantine/code-highlight": "^9.0.1",
"@mantine/core": "^9.0.1",
"@mantine/dates": "^9.0.1",
"@mantine/hooks": "^9.0.1",
"@mantine/notifications": "^9.0.1",
"@microsoft/fetch-event-source": "^2.0.1",
"@nexucis/fuzzy": "^0.5.1",
"@nexucis/kvsearch": "^0.9.1",
@ -86,90 +86,6 @@
"vitest": "^3.2.4"
}
},
"mantine-ui/node_modules/@mantine/code-highlight": {
"version": "8.3.18",
"resolved": "https://registry.npmjs.org/@mantine/code-highlight/-/code-highlight-8.3.18.tgz",
"integrity": "sha512-/KAxx+H9YfzKK8jv10XB/tJNV8IWCY3axbTmyij4VnLp1ivAInU7GLv9NzdXPHTx4JazIGxMwrrVANQD4QaQjA==",
"license": "MIT",
"dependencies": {
"clsx": "^2.1.1"
},
"peerDependencies": {
"@mantine/core": "8.3.18",
"@mantine/hooks": "8.3.18",
"react": "^18.x || ^19.x",
"react-dom": "^18.x || ^19.x"
}
},
"mantine-ui/node_modules/@mantine/core": {
"version": "8.3.18",
"resolved": "https://registry.npmjs.org/@mantine/core/-/core-8.3.18.tgz",
"integrity": "sha512-9tph1lTVogKPjTx02eUxDUOdXacPzK62UuSqb4TdGliI54/Xgxftq0Dfqu6XuhCxn9J5MDJaNiLDvL/1KRkYqA==",
"license": "MIT",
"dependencies": {
"@floating-ui/react": "^0.27.16",
"clsx": "^2.1.1",
"react-number-format": "^5.4.4",
"react-remove-scroll": "^2.7.1",
"react-textarea-autosize": "8.5.9",
"type-fest": "^4.41.0"
},
"peerDependencies": {
"@mantine/hooks": "8.3.18",
"react": "^18.x || ^19.x",
"react-dom": "^18.x || ^19.x"
}
},
"mantine-ui/node_modules/@mantine/dates": {
"version": "8.3.18",
"resolved": "https://registry.npmjs.org/@mantine/dates/-/dates-8.3.18.tgz",
"integrity": "sha512-FHx5teJOhupI0gO2o5evtVYQEdqOjayOkLRhEQfB5Nc5DvcysfPfmNILGkc1Nrp9ZQeQWKLT9qr+CkcCXwHOaw==",
"license": "MIT",
"dependencies": {
"clsx": "^2.1.1"
},
"peerDependencies": {
"@mantine/core": "8.3.18",
"@mantine/hooks": "8.3.18",
"dayjs": ">=1.0.0",
"react": "^18.x || ^19.x",
"react-dom": "^18.x || ^19.x"
}
},
"mantine-ui/node_modules/@mantine/hooks": {
"version": "8.3.18",
"resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-8.3.18.tgz",
"integrity": "sha512-QoWr9+S8gg5050TQ06aTSxtlpGjYOpIllRbjYYXlRvZeTsUqiTbVfvQROLexu4rEaK+yy9Wwriwl9PMRgbLqPw==",
"license": "MIT",
"peerDependencies": {
"react": "^18.x || ^19.x"
}
},
"mantine-ui/node_modules/@mantine/notifications": {
"version": "8.3.18",
"resolved": "https://registry.npmjs.org/@mantine/notifications/-/notifications-8.3.18.tgz",
"integrity": "sha512-IpQ0lmwbigTBbZCR6iSYWqIOKEx1tlcd7PcEJ5M5X1qeVSY/N3mmDQt1eJmObvcyDeL5cTJMbSA9UPqhRqo9jw==",
"license": "MIT",
"dependencies": {
"@mantine/store": "8.3.18",
"react-transition-group": "4.4.5"
},
"peerDependencies": {
"@mantine/core": "8.3.18",
"@mantine/hooks": "8.3.18",
"react": "^18.x || ^19.x",
"react-dom": "^18.x || ^19.x"
}
},
"mantine-ui/node_modules/@mantine/store": {
"version": "8.3.18",
"resolved": "https://registry.npmjs.org/@mantine/store/-/store-8.3.18.tgz",
"integrity": "sha512-i+QRTLmZzLldea0egtUVnGALd6UMIu8jd44nrNWBSNIXJU/8B6rMlC6gyX+l4szopZSuOaaNJIXkqRdC1gQsVg==",
"license": "MIT",
"peerDependencies": {
"react": "^18.x || ^19.x"
}
},
"module/codemirror-promql": {
"name": "@prometheus-io/codemirror-promql",
"version": "0.311.0",
@ -1521,12 +1437,13 @@
}
},
"node_modules/@floating-ui/react": {
"version": "0.27.16",
"resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.27.16.tgz",
"integrity": "sha512-9O8N4SeG2z++TSM8QA/KTeKFBVCNEz/AGS7gWPJf6KFRzmRWixFRnCnkPHRDwSVZW6QPDO6uT0P2SpWNKCc9/g==",
"version": "0.27.19",
"resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.27.19.tgz",
"integrity": "sha512-31B8h5mm8YxotlE7/AU/PhNAl8eWxAmjL/v2QOxroDNkTFLk3Uu82u63N3b6TXa4EGJeeZLVcd/9AlNlVqzeog==",
"license": "MIT",
"dependencies": {
"@floating-ui/react-dom": "^2.1.6",
"@floating-ui/utils": "^0.2.10",
"@floating-ui/react-dom": "^2.1.8",
"@floating-ui/utils": "^0.2.11",
"tabbable": "^6.0.0"
},
"peerDependencies": {
@ -1535,11 +1452,12 @@
}
},
"node_modules/@floating-ui/react-dom": {
"version": "2.1.6",
"resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.6.tgz",
"integrity": "sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==",
"version": "2.1.8",
"resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.8.tgz",
"integrity": "sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==",
"license": "MIT",
"dependencies": {
"@floating-ui/dom": "^1.7.4"
"@floating-ui/dom": "^1.7.6"
},
"peerDependencies": {
"react": ">=16.8.0",
@ -2169,6 +2087,104 @@
"@lezer/common": "^1.0.0"
}
},
"node_modules/@mantine/code-highlight": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/@mantine/code-highlight/-/code-highlight-9.0.1.tgz",
"integrity": "sha512-ZIZDOvQzz475GNRAbNaBQCrpXLPwAekj6vaAcnbqrFjKKACVnZPJqkELm40gM9RtBCYvMFL01fmiWZfJLUT+ag==",
"license": "MIT",
"dependencies": {
"clsx": "^2.1.1"
},
"peerDependencies": {
"@mantine/core": "9.0.1",
"@mantine/hooks": "9.0.1",
"react": "^19.2.0",
"react-dom": "^19.2.0"
}
},
"node_modules/@mantine/core": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/@mantine/core/-/core-9.0.1.tgz",
"integrity": "sha512-kSYm8g7p8FTDysOsz9BN14TSqp10O0yAmo9HOZfwe6c08gGKQSytnSCPgnTe2h5DMfpbhTg+krROrT8WQy37fA==",
"license": "MIT",
"dependencies": {
"@floating-ui/react": "^0.27.19",
"clsx": "^2.1.1",
"react-number-format": "^5.4.5",
"react-remove-scroll": "^2.7.2",
"type-fest": "^5.5.0"
},
"peerDependencies": {
"@mantine/hooks": "9.0.1",
"react": "^19.2.0",
"react-dom": "^19.2.0"
}
},
"node_modules/@mantine/core/node_modules/type-fest": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.5.0.tgz",
"integrity": "sha512-PlBfpQwiUvGViBNX84Yxwjsdhd1TUlXr6zjX7eoirtCPIr08NAmxwa+fcYBTeRQxHo9YC9wwF3m9i700sHma8g==",
"license": "(MIT OR CC0-1.0)",
"dependencies": {
"tagged-tag": "^1.0.0"
},
"engines": {
"node": ">=20"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@mantine/dates": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/@mantine/dates/-/dates-9.0.1.tgz",
"integrity": "sha512-+zwqqQ4D2I8o/GiEStF66Mheo3abKmS0KaL3XDtDp1D7AVhKmSH3Rz27m48aqW/Kzqb2g2t3VgPzAkpuRsWdBA==",
"license": "MIT",
"dependencies": {
"clsx": "^2.1.1"
},
"peerDependencies": {
"@mantine/core": "9.0.1",
"@mantine/hooks": "9.0.1",
"dayjs": ">=1.0.0",
"react": "^19.2.0",
"react-dom": "^19.2.0"
}
},
"node_modules/@mantine/hooks": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-9.0.1.tgz",
"integrity": "sha512-WM/GbSD8MxZoy3X2IdrbxLq0/0ca4zMA5m7lGw9k1Vecqt1dC/nBed0IJd/w2HGs6avGs9CPlvQ8C4yBEcSnLA==",
"license": "MIT",
"peerDependencies": {
"react": "^19.2.0"
}
},
"node_modules/@mantine/notifications": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/@mantine/notifications/-/notifications-9.0.1.tgz",
"integrity": "sha512-og/RfURurEwTISUmgN/wcjlIE1+OxkCgcmUDZ1Jinfm1efJ8ywXl1zf/fa7/VVN4O/xZl+HMhN46OoCnW3+/bw==",
"license": "MIT",
"dependencies": {
"@mantine/store": "9.0.1",
"react-transition-group": "4.4.5"
},
"peerDependencies": {
"@mantine/core": "9.0.1",
"@mantine/hooks": "9.0.1",
"react": "^19.2.0",
"react-dom": "^19.2.0"
}
},
"node_modules/@mantine/store": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/@mantine/store/-/store-9.0.1.tgz",
"integrity": "sha512-7jn/tX6qC71zd8Hcr/m/kQT7wCp87nvUM3p9OoJ2qX13oNCrMEXRtimYwqkOBK5Vx2hNApQY5KF183+arHU6NA==",
"license": "MIT",
"peerDependencies": {
"react": "^19.2.0"
}
},
"node_modules/@marijn/find-cluster-break": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz",
@ -4451,7 +4467,8 @@
"node_modules/detect-node-es": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
"integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="
"integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==",
"license": "MIT"
},
"node_modules/diff-sequences": {
"version": "29.6.3",
@ -5232,6 +5249,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz",
"integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==",
"license": "MIT",
"engines": {
"node": ">=6"
}
@ -7963,9 +7981,9 @@
"peer": true
},
"node_modules/react-number-format": {
"version": "5.4.4",
"resolved": "https://registry.npmjs.org/react-number-format/-/react-number-format-5.4.4.tgz",
"integrity": "sha512-wOmoNZoOpvMminhifQYiYSTCLUDOiUbBunrMrMjA+dV52sY+vck1S4UhR6PkgnoCquvvMSeJjErXZ4qSaWCliA==",
"version": "5.4.5",
"resolved": "https://registry.npmjs.org/react-number-format/-/react-number-format-5.4.5.tgz",
"integrity": "sha512-y8O2yHHj3w0aE9XO8d2BCcUOOdQTRSVq+WIuMlLVucAm5XNjJAy+BoOJiuQMldVYVOKTMyvVNfnbl2Oqp+YxGw==",
"license": "MIT",
"peerDependencies": {
"react": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
@ -8006,9 +8024,9 @@
}
},
"node_modules/react-remove-scroll": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.1.tgz",
"integrity": "sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==",
"version": "2.7.2",
"resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.2.tgz",
"integrity": "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==",
"license": "MIT",
"dependencies": {
"react-remove-scroll-bar": "^2.3.7",
@ -8034,6 +8052,7 @@
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz",
"integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==",
"license": "MIT",
"dependencies": {
"react-style-singleton": "^2.2.2",
"tslib": "^2.0.0"
@ -8093,6 +8112,7 @@
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz",
"integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==",
"license": "MIT",
"dependencies": {
"get-nonce": "^1.0.0",
"tslib": "^2.0.0"
@ -8110,23 +8130,6 @@
}
}
},
"node_modules/react-textarea-autosize": {
"version": "8.5.9",
"resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.5.9.tgz",
"integrity": "sha512-U1DGlIQN5AwgjTyOEnI1oCcMuEr1pv1qOtklB2l4nyMGbHzWrI0eFsYK0zos2YWqAolJyG0IWJaqWmWj5ETh0A==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.20.13",
"use-composed-ref": "^1.3.0",
"use-latest": "^1.2.1"
},
"engines": {
"node": ">=10"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.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",
@ -8700,9 +8703,22 @@
}
},
"node_modules/tabbable": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.3.0.tgz",
"integrity": "sha512-EIHvdY5bPLuWForiR/AN2Bxngzpuwn1is4asboytXtpTgsArc+WmSJKVLlhdh71u7jFcryDqB2A8lQvj78MkyQ=="
"version": "6.4.0",
"resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz",
"integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==",
"license": "MIT"
},
"node_modules/tagged-tag": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/tagged-tag/-/tagged-tag-1.0.0.tgz",
"integrity": "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==",
"license": "MIT",
"engines": {
"node": ">=20"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/test-exclude": {
"version": "6.0.0",
@ -8985,6 +9001,7 @@
"version": "4.41.0",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz",
"integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==",
"dev": true,
"license": "(MIT OR CC0-1.0)",
"engines": {
"node": ">=16"
@ -9092,6 +9109,7 @@
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz",
"integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==",
"license": "MIT",
"dependencies": {
"tslib": "^2.0.0"
},
@ -9108,51 +9126,6 @@
}
}
},
"node_modules/use-composed-ref": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.4.0.tgz",
"integrity": "sha512-djviaxuOOh7wkj0paeO1Q/4wMZ8Zrnag5H6yBvzN7AKKe8beOaED9SF5/ByLqsku8NP4zQqsvM2u3ew/tJK8/w==",
"license": "MIT",
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/use-isomorphic-layout-effect": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.2.1.tgz",
"integrity": "sha512-tpZZ+EX0gaghDAiFR37hj5MgY6ZN55kLiPkJsKxBMZ6GZdOSPJXiOzPM984oPYZ5AnehYx5WQp1+ME8I/P/pRA==",
"license": "MIT",
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/use-latest": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/use-latest/-/use-latest-1.3.0.tgz",
"integrity": "sha512-mhg3xdm9NaM8q+gLT8KryJPnRFOz1/5XPBhmDEVZK1webPzDjrPk7f/mbpeLqTgB9msytYWANxgALOCJKnLvcQ==",
"license": "MIT",
"dependencies": {
"use-isomorphic-layout-effect": "^1.1.1"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/use-query-params": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/use-query-params/-/use-query-params-2.2.2.tgz",
@ -9180,6 +9153,7 @@
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz",
"integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==",
"license": "MIT",
"dependencies": {
"detect-node-es": "^1.1.0",
"tslib": "^2.0.0"

View file

@ -578,7 +578,7 @@ func TestAgentAPIEndPoints(t *testing.T) {
for path, methods := range map[string][]string{
"/labels": {http.MethodGet, http.MethodPost},
"/label/:name/values": {http.MethodGet},
"/series": {http.MethodGet, http.MethodPost, http.MethodDelete},
"/series": {http.MethodGet, http.MethodPost},
"/alertmanagers": {http.MethodGet},
"/query": {http.MethodGet, http.MethodPost},
"/query_range": {http.MethodGet, http.MethodPost},