Alerting: Remove react-enable (#77955)

pull/77964/head
Gilles De Mey 2 years ago committed by GitHub
parent 36dba7584d
commit 323ee7c38c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 69
      docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md
  2. 1
      package.json
  3. 2
      packages/grafana-data/src/types/featureToggles.gen.ts
  4. 17
      pkg/services/featuremgmt/registry.go
  5. 2
      pkg/services/featuremgmt/toggles_gen.csv
  6. 8
      pkg/services/featuremgmt/toggles_gen.go
  7. 22
      public/app/features/alerting/unified/RuleViewer.tsx
  8. 29
      public/app/features/alerting/unified/components/AlertingPageWrapper.tsx
  9. 21
      public/app/features/alerting/unified/features.ts
  10. 34
      public/app/features/alerting/unified/useRouteGroupsMatcher.test.tsx
  11. 79
      public/app/features/alerting/unified/useRouteGroupsMatcher.ts
  12. 65
      yarn.lock

@ -19,41 +19,40 @@ This page contains a list of available feature toggles. To learn how to turn on
Some features are enabled by default. You can disable these feature by setting the feature flag to "false" in the configuration.
| Feature toggle name | Description | Enabled by default |
| ------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ |
| `disableEnvelopeEncryption` | Disable envelope encryption (emergency only) | |
| `publicDashboards` | Enables public access to dashboards | Yes |
| `featureHighlights` | Highlight Grafana Enterprise features | |
| `exploreContentOutline` | Content outline sidebar | Yes |
| `newVizTooltips` | New visualizations tooltips UX | |
| `dataConnectionsConsole` | Enables a new top-level page called Connections. This page is an experiment that provides a better experience when you install and configure data sources and other plugins. | Yes |
| `cloudWatchCrossAccountQuerying` | Enables cross-account querying in CloudWatch datasources | Yes |
| `redshiftAsyncQueryDataSupport` | Enable async query data support for Redshift | Yes |
| `athenaAsyncQueryDataSupport` | Enable async query data support for Athena | Yes |
| `nestedFolderPicker` | Enables the new folder picker to work with nested folders. Requires the nestedFolders feature toggle | Yes |
| `accessTokenExpirationCheck` | Enable OAuth access_token expiration check and token refresh using the refresh_token | |
| `emptyDashboardPage` | Enable the redesigned user interface of a dashboard page that includes no panels | Yes |
| `disablePrometheusExemplarSampling` | Disable Prometheus exemplar sampling | |
| `logsContextDatasourceUi` | Allow datasource to provide custom UI for context view | Yes |
| `lokiQuerySplitting` | Split large interval queries into subqueries with smaller time intervals | Yes |
| `gcomOnlyExternalOrgRoleSync` | Prohibits a user from changing organization roles synced with Grafana Cloud auth provider | |
| `prometheusMetricEncyclopedia` | Adds the metrics explorer component to the Prometheus query builder as an option in metric select | Yes |
| `influxdbBackendMigration` | Query InfluxDB InfluxQL without the proxy | Yes |
| `prometheusDataplane` | Changes responses to from Prometheus to be compliant with the dataplane specification. In particular, when this feature toggle is active, the numeric `Field.Name` is set from 'Value' to the value of the `__name__` label. | Yes |
| `lokiMetricDataplane` | Changes metric responses from Loki to be compliant with the dataplane specification. | Yes |
| `dataplaneFrontendFallback` | Support dataplane contract field name change for transformations and field name matchers where the name is different | Yes |
| `alertingNotificationsPoliciesMatchingInstances` | Enables the preview of matching instances for notification policies | Yes |
| `useCachingService` | When active, the new query and resource caching implementation using a wire service inject replaces the previous middleware implementation. | Yes |
| `enableElasticsearchBackendQuerying` | Enable the processing of queries and responses in the Elasticsearch data source through backend | Yes |
| `advancedDataSourcePicker` | Enable a new data source picker with contextual information, recently used order and advanced mode | Yes |
| `cloudWatchLogsMonacoEditor` | Enables the Monaco editor for CloudWatch Logs queries | Yes |
| `recordedQueriesMulti` | Enables writing multiple items from a single query within Recorded Queries | Yes |
| `transformationsRedesign` | Enables the transformations redesign | Yes |
| `prometheusConfigOverhaulAuth` | Update the Prometheus configuration page with the new auth component | Yes |
| `dashgpt` | Enable AI powered features in dashboards | Yes |
| `newBrowseDashboards` | New browse/manage dashboards UI | Yes |
| `alertingInsights` | Show the new alerting insights landing page | Yes |
| `cloudWatchWildCardDimensionValues` | Fetches dimension values from CloudWatch to correctly label wildcard dimensions | Yes |
| Feature toggle name | Description | Enabled by default |
| ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ |
| `disableEnvelopeEncryption` | Disable envelope encryption (emergency only) | |
| `publicDashboards` | Enables public access to dashboards | Yes |
| `featureHighlights` | Highlight Grafana Enterprise features | |
| `exploreContentOutline` | Content outline sidebar | Yes |
| `newVizTooltips` | New visualizations tooltips UX | |
| `dataConnectionsConsole` | Enables a new top-level page called Connections. This page is an experiment that provides a better experience when you install and configure data sources and other plugins. | Yes |
| `cloudWatchCrossAccountQuerying` | Enables cross-account querying in CloudWatch datasources | Yes |
| `redshiftAsyncQueryDataSupport` | Enable async query data support for Redshift | Yes |
| `athenaAsyncQueryDataSupport` | Enable async query data support for Athena | Yes |
| `nestedFolderPicker` | Enables the new folder picker to work with nested folders. Requires the nestedFolders feature toggle | Yes |
| `accessTokenExpirationCheck` | Enable OAuth access_token expiration check and token refresh using the refresh_token | |
| `emptyDashboardPage` | Enable the redesigned user interface of a dashboard page that includes no panels | Yes |
| `disablePrometheusExemplarSampling` | Disable Prometheus exemplar sampling | |
| `logsContextDatasourceUi` | Allow datasource to provide custom UI for context view | Yes |
| `lokiQuerySplitting` | Split large interval queries into subqueries with smaller time intervals | Yes |
| `gcomOnlyExternalOrgRoleSync` | Prohibits a user from changing organization roles synced with Grafana Cloud auth provider | |
| `prometheusMetricEncyclopedia` | Adds the metrics explorer component to the Prometheus query builder as an option in metric select | Yes |
| `influxdbBackendMigration` | Query InfluxDB InfluxQL without the proxy | Yes |
| `prometheusDataplane` | Changes responses to from Prometheus to be compliant with the dataplane specification. In particular, when this feature toggle is active, the numeric `Field.Name` is set from 'Value' to the value of the `__name__` label. | Yes |
| `lokiMetricDataplane` | Changes metric responses from Loki to be compliant with the dataplane specification. | Yes |
| `dataplaneFrontendFallback` | Support dataplane contract field name change for transformations and field name matchers where the name is different | Yes |
| `useCachingService` | When active, the new query and resource caching implementation using a wire service inject replaces the previous middleware implementation. | Yes |
| `enableElasticsearchBackendQuerying` | Enable the processing of queries and responses in the Elasticsearch data source through backend | Yes |
| `advancedDataSourcePicker` | Enable a new data source picker with contextual information, recently used order and advanced mode | Yes |
| `cloudWatchLogsMonacoEditor` | Enables the Monaco editor for CloudWatch Logs queries | Yes |
| `recordedQueriesMulti` | Enables writing multiple items from a single query within Recorded Queries | Yes |
| `transformationsRedesign` | Enables the transformations redesign | Yes |
| `prometheusConfigOverhaulAuth` | Update the Prometheus configuration page with the new auth component | Yes |
| `dashgpt` | Enable AI powered features in dashboards | Yes |
| `newBrowseDashboards` | New browse/manage dashboards UI | Yes |
| `alertingInsights` | Show the new alerting insights landing page | Yes |
| `cloudWatchWildCardDimensionValues` | Fetches dimension values from CloudWatch to correctly label wildcard dimensions | Yes |
## Preview feature toggles

@ -370,7 +370,6 @@
"react-dom": "18.2.0",
"react-draggable": "4.4.5",
"react-dropzone": "^14.2.3",
"react-enable": "^3.1.0",
"react-grid-layout": "1.4.2",
"react-highlight-words": "0.20.0",
"react-hook-form": "7.5.3",

@ -74,7 +74,6 @@ export interface FeatureToggles {
dataplaneFrontendFallback?: boolean;
disableSSEDataplane?: boolean;
alertStateHistoryLokiSecondary?: boolean;
alertingNotificationsPoliciesMatchingInstances?: boolean;
alertStateHistoryLokiPrimary?: boolean;
alertStateHistoryLokiOnly?: boolean;
unifiedRequestLog?: boolean;
@ -161,4 +160,5 @@ export interface FeatureToggles {
ssoSettingsApi?: boolean;
logsInfiniteScrolling?: boolean;
flameGraphItemCollapsing?: boolean;
alertingDetailsViewV2?: boolean;
}

@ -411,15 +411,6 @@ var (
Stage: FeatureStageExperimental,
Owner: grafanaAlertingSquad,
},
{
Name: "alertingNotificationsPoliciesMatchingInstances",
Description: "Enables the preview of matching instances for notification policies",
Stage: FeatureStageGeneralAvailability,
FrontendOnly: true,
Expression: "true", // enabled by default
Owner: grafanaAlertingSquad,
AllowSelfServe: falsePtr,
},
{
Name: "alertStateHistoryLokiPrimary",
Description: "Enable a remote Loki instance as the primary source for state history reads.",
@ -1039,6 +1030,14 @@ var (
FrontendOnly: true,
Owner: grafanaObservabilityTracesAndProfilingSquad,
},
{
Name: "alertingDetailsViewV2",
Description: "Enables the preview of the new alert details view",
Stage: FeatureStageExperimental,
FrontendOnly: true,
Owner: grafanaAlertingSquad,
HideFromDocs: true,
},
}
)

@ -55,7 +55,6 @@ lokiLogsDataplane,experimental,@grafana/observability-logs,false,false,false,fal
dataplaneFrontendFallback,GA,@grafana/observability-metrics,false,false,false,true
disableSSEDataplane,experimental,@grafana/observability-metrics,false,false,false,false
alertStateHistoryLokiSecondary,experimental,@grafana/alerting-squad,false,false,false,false
alertingNotificationsPoliciesMatchingInstances,GA,@grafana/alerting-squad,false,false,false,true
alertStateHistoryLokiPrimary,experimental,@grafana/alerting-squad,false,false,false,false
alertStateHistoryLokiOnly,experimental,@grafana/alerting-squad,false,false,false,false
unifiedRequestLog,experimental,@grafana/backend-platform,false,false,false,false
@ -142,3 +141,4 @@ pdfTables,privatePreview,@grafana/sharing-squad,false,false,false,false
ssoSettingsApi,experimental,@grafana/identity-access-team,true,false,false,false
logsInfiniteScrolling,experimental,@grafana/observability-logs,false,false,false,true
flameGraphItemCollapsing,experimental,@grafana/observability-traces-and-profiling,false,false,false,true
alertingDetailsViewV2,experimental,@grafana/alerting-squad,false,false,false,true

1 Name Stage Owner requiresDevMode RequiresLicense RequiresRestart FrontendOnly
55 dataplaneFrontendFallback GA @grafana/observability-metrics false false false true
56 disableSSEDataplane experimental @grafana/observability-metrics false false false false
57 alertStateHistoryLokiSecondary experimental @grafana/alerting-squad false false false false
alertingNotificationsPoliciesMatchingInstances GA @grafana/alerting-squad false false false true
58 alertStateHistoryLokiPrimary experimental @grafana/alerting-squad false false false false
59 alertStateHistoryLokiOnly experimental @grafana/alerting-squad false false false false
60 unifiedRequestLog experimental @grafana/backend-platform false false false false
141 ssoSettingsApi experimental @grafana/identity-access-team true false false false
142 logsInfiniteScrolling experimental @grafana/observability-logs false false false true
143 flameGraphItemCollapsing experimental @grafana/observability-traces-and-profiling false false false true
144 alertingDetailsViewV2 experimental @grafana/alerting-squad false false false true

@ -231,10 +231,6 @@ const (
// Enable Grafana to write alert state history to an external Loki instance in addition to Grafana annotations.
FlagAlertStateHistoryLokiSecondary = "alertStateHistoryLokiSecondary"
// FlagAlertingNotificationsPoliciesMatchingInstances
// Enables the preview of matching instances for notification policies
FlagAlertingNotificationsPoliciesMatchingInstances = "alertingNotificationsPoliciesMatchingInstances"
// FlagAlertStateHistoryLokiPrimary
// Enable a remote Loki instance as the primary source for state history reads.
FlagAlertStateHistoryLokiPrimary = "alertStateHistoryLokiPrimary"
@ -578,4 +574,8 @@ const (
// FlagFlameGraphItemCollapsing
// Allow collapsing of flame graph items
FlagFlameGraphItemCollapsing = "flameGraphItemCollapsing"
// FlagAlertingDetailsViewV2
// Enables the preview of the new alert details view
FlagAlertingDetailsViewV2 = "alertingDetailsViewV2"
)

@ -1,12 +1,11 @@
import React from 'react';
import { Disable, Enable } from 'react-enable';
import { config } from '@grafana/runtime';
import { withErrorBoundary } from '@grafana/ui';
import { SafeDynamicImport } from 'app/core/components/DynamicImports/SafeDynamicImport';
import { GrafanaRouteComponentProps } from 'app/core/navigation/types';
import { AlertingPageWrapper } from './components/AlertingPageWrapper';
import { AlertingFeature } from './features';
const DetailViewV1 = SafeDynamicImport(() => import('./components/rule-viewer/RuleViewer.v1'));
const DetailViewV2 = SafeDynamicImport(() => import('./components/rule-viewer/v2/RuleViewer.v2'));
@ -16,17 +15,12 @@ type RuleViewerProps = GrafanaRouteComponentProps<{
sourceName: string;
}>;
const RuleViewer = (props: RuleViewerProps): JSX.Element => {
return (
<AlertingPageWrapper>
<Enable feature={AlertingFeature.DetailsViewV2}>
<DetailViewV2 {...props} />
</Enable>
<Disable feature={AlertingFeature.DetailsViewV2}>
<DetailViewV1 {...props} />
</Disable>
</AlertingPageWrapper>
);
};
const newAlertDetailView = Boolean(config.featureToggles.alertingDetailsViewV2) === true;
const RuleViewer = (props: RuleViewerProps): JSX.Element => (
<AlertingPageWrapper>
{newAlertDetailView ? <DetailViewV2 {...props} /> : <DetailViewV1 {...props} />}
</AlertingPageWrapper>
);
export default withErrorBoundary(RuleViewer, { style: 'page' });

@ -1,20 +1,14 @@
import Mousetrap from 'mousetrap';
import React, { PropsWithChildren, useEffect, useState } from 'react';
import { Features, ToggleFeatures } from 'react-enable';
import React, { PropsWithChildren } from 'react';
import { useLocation } from 'react-use';
import { NavModelItem } from '@grafana/data';
import { Page } from 'app/core/components/Page/Page';
import FEATURES from '../features';
import { AlertmanagerProvider, useAlertmanager } from '../state/AlertmanagerContext';
import { AlertManagerPicker } from './AlertManagerPicker';
import { NoAlertManagerWarning } from './NoAlertManagerWarning';
const SHOW_TOGGLES_KEY_COMBO = 'ctrl+1';
const combokeys = new Mousetrap(document.body);
/**
* This is the main alerting page wrapper, used by the alertmanager page wrapper and the alert rules list view
*/
@ -25,25 +19,10 @@ interface AlertingPageWrapperProps extends PropsWithChildren {
actions?: React.ReactNode;
}
export const AlertingPageWrapper = ({ children, pageId, pageNav, actions, isLoading }: AlertingPageWrapperProps) => {
const [showFeatureToggle, setShowFeatureToggles] = useState(false);
useEffect(() => {
combokeys.bind(SHOW_TOGGLES_KEY_COMBO, () => {
setShowFeatureToggles((show) => !show);
});
return () => {
combokeys.unbind(SHOW_TOGGLES_KEY_COMBO);
};
}, []);
return (
<Features features={FEATURES}>
<Page pageNav={pageNav} navId={pageId} actions={actions}>
<Page.Contents isLoading={isLoading}>{children}</Page.Contents>
</Page>
{showFeatureToggle ? <ToggleFeatures defaultOpen={true} /> : null}
</Features>
<Page pageNav={pageNav} navId={pageId} actions={actions}>
<Page.Contents isLoading={isLoading}>{children}</Page.Contents>
</Page>
);
};

@ -1,21 +0,0 @@
import { FeatureDescription } from 'react-enable/dist/FeatureState';
import { config } from '@grafana/runtime';
export enum AlertingFeature {
NotificationPoliciesV2MatchingInstances = 'notification-policies.v2.matching-instances',
DetailsViewV2 = 'details-view.v2',
ContactPointsV2 = 'contact-points.v2',
}
const FEATURES: FeatureDescription[] = [
{
name: AlertingFeature.NotificationPoliciesV2MatchingInstances,
defaultValue: config.featureToggles.alertingNotificationsPoliciesMatchingInstances,
},
{
name: AlertingFeature.DetailsViewV2,
defaultValue: false,
},
];
export default FEATURES;

@ -1,11 +1,7 @@
import { renderHook } from '@testing-library/react';
import * as comlink from 'comlink';
import React from 'react';
import { Features } from 'react-enable';
import { FeatureDescription } from 'react-enable/dist/FeatureState';
import { createWorker } from './createRouteGroupsMatcherWorker';
import { AlertingFeature } from './features';
import { useRouteGroupsMatcher } from './useRouteGroupsMatcher';
jest.mock('./createRouteGroupsMatcherWorker');
@ -20,24 +16,8 @@ beforeEach(() => {
});
describe('useRouteGroupsMatcher', () => {
it('should not load web worker if the feature flag is disabled', function () {
const featureFlag = getInstancePreviewFeature(false);
const { result } = renderHook(() => useRouteGroupsMatcher(), {
wrapper: ({ children }) => <Features features={[featureFlag]}>{children}</Features>,
});
expect(createWorkerMock).not.toHaveBeenCalled();
expect(wrapMock).not.toHaveBeenCalled();
expect(result.current.getRouteGroupsMap).toBeDefined();
});
it('should load web worker if the feature flag is enabled', function () {
const featureFlag = getInstancePreviewFeature(true);
const { result } = renderHook(() => useRouteGroupsMatcher(), {
wrapper: ({ children }) => <Features features={[featureFlag]}>{children}</Features>,
});
const { result } = renderHook(() => useRouteGroupsMatcher());
expect(createWorkerMock).toHaveBeenCalledTimes(1);
expect(wrapMock).toHaveBeenCalledTimes(1);
@ -45,14 +25,11 @@ describe('useRouteGroupsMatcher', () => {
});
it('getMatchedRouteGroups should throw error if loading worker failed', async function () {
const featureFlag = getInstancePreviewFeature(true);
createWorkerMock.mockImplementation(() => {
throw new DOMException('Failed to load worker');
});
const { result } = renderHook(() => useRouteGroupsMatcher(), {
wrapper: ({ children }) => <Features features={[featureFlag]}>{children}</Features>,
});
const { result } = renderHook(() => useRouteGroupsMatcher());
expect(createWorkerMock).toHaveBeenCalledTimes(1);
expect(wrapMock).toHaveBeenCalledTimes(0); // When loading worker failed we shouldn't call wrap
@ -61,10 +38,3 @@ describe('useRouteGroupsMatcher', () => {
}).rejects.toThrowError(Error);
});
});
function getInstancePreviewFeature(enabled: boolean): FeatureDescription {
return {
name: AlertingFeature.NotificationPoliciesV2MatchingInstances,
defaultValue: enabled,
};
}

@ -1,6 +1,5 @@
import * as comlink from 'comlink';
import { useCallback, useEffect } from 'react';
import { useEnabled } from 'react-enable';
import { logError } from '@grafana/runtime';
@ -9,7 +8,6 @@ import { Labels } from '../../../types/unified-alerting-dto';
import { logInfo } from './Analytics';
import { createWorker } from './createRouteGroupsMatcherWorker';
import { AlertingFeature } from './features';
import type { RouteGroupsMatcher } from './routeGroupsMatcher';
let routeMatcher: comlink.Remote<RouteGroupsMatcher> | undefined;
@ -45,74 +43,57 @@ function loadWorker() {
return { disposeWorker };
}
function validateWorker(
toggleEnabled: boolean,
matcher: typeof routeMatcher
): asserts matcher is comlink.Remote<RouteGroupsMatcher> {
if (!toggleEnabled) {
throw new Error('Matching routes preview is disabled');
}
function validateWorker(matcher: typeof routeMatcher): asserts matcher is comlink.Remote<RouteGroupsMatcher> {
if (!routeMatcher) {
throw new Error('Route Matcher has not been initialized');
}
}
export function useRouteGroupsMatcher() {
const workerPreviewEnabled = useEnabled(AlertingFeature.NotificationPoliciesV2MatchingInstances);
useEffect(() => {
if (workerPreviewEnabled) {
const { disposeWorker } = loadWorker();
return disposeWorker;
}
const { disposeWorker } = loadWorker();
return disposeWorker;
return () => null;
}, [workerPreviewEnabled]);
}, []);
const getRouteGroupsMap = useCallback(
async (rootRoute: RouteWithID, alertGroups: AlertmanagerGroup[]) => {
validateWorker(workerPreviewEnabled, routeMatcher);
const getRouteGroupsMap = useCallback(async (rootRoute: RouteWithID, alertGroups: AlertmanagerGroup[]) => {
validateWorker(routeMatcher);
const startTime = performance.now();
const startTime = performance.now();
const result = await routeMatcher.getRouteGroupsMap(rootRoute, alertGroups);
const result = await routeMatcher.getRouteGroupsMap(rootRoute, alertGroups);
const timeSpent = performance.now() - startTime;
const timeSpent = performance.now() - startTime;
logInfo(`Route Groups Matched in ${timeSpent} ms`, {
matchingTime: timeSpent.toString(),
alertGroupsCount: alertGroups.length.toString(),
// Counting all nested routes might be too time-consuming, so we only count the first level
topLevelRoutesCount: rootRoute.routes?.length.toString() ?? '0',
});
logInfo(`Route Groups Matched in ${timeSpent} ms`, {
matchingTime: timeSpent.toString(),
alertGroupsCount: alertGroups.length.toString(),
// Counting all nested routes might be too time-consuming, so we only count the first level
topLevelRoutesCount: rootRoute.routes?.length.toString() ?? '0',
});
return result;
},
[workerPreviewEnabled]
);
return result;
}, []);
const matchInstancesToRoute = useCallback(
async (rootRoute: RouteWithID, instancesToMatch: Labels[]) => {
validateWorker(workerPreviewEnabled, routeMatcher);
const matchInstancesToRoute = useCallback(async (rootRoute: RouteWithID, instancesToMatch: Labels[]) => {
validateWorker(routeMatcher);
const startTime = performance.now();
const startTime = performance.now();
const result = await routeMatcher.matchInstancesToRoute(rootRoute, instancesToMatch);
const result = await routeMatcher.matchInstancesToRoute(rootRoute, instancesToMatch);
const timeSpent = performance.now() - startTime;
const timeSpent = performance.now() - startTime;
logInfo(`Instances Matched in ${timeSpent} ms`, {
matchingTime: timeSpent.toString(),
instancesToMatchCount: instancesToMatch.length.toString(),
// Counting all nested routes might be too time-consuming, so we only count the first level
topLevelRoutesCount: rootRoute.routes?.length.toString() ?? '0',
});
logInfo(`Instances Matched in ${timeSpent} ms`, {
matchingTime: timeSpent.toString(),
instancesToMatchCount: instancesToMatch.length.toString(),
// Counting all nested routes might be too time-consuming, so we only count the first level
topLevelRoutesCount: rootRoute.routes?.length.toString() ?? '0',
});
return result;
},
[workerPreviewEnabled]
);
return result;
}, []);
return { getRouteGroupsMap, matchInstancesToRoute };
}

@ -3520,18 +3520,6 @@ __metadata:
languageName: unknown
linkType: soft
"@headlessui/react@npm:^1.5.0":
version: 1.7.11
resolution: "@headlessui/react@npm:1.7.11"
dependencies:
client-only: "npm:^0.0.1"
peerDependencies:
react: ^16 || ^17 || ^18
react-dom: ^16 || ^17 || ^18
checksum: 683cb302cbcd07bf0b3aa2afbfbf7fd80aac542531b6624788ac1d28b80c66c319f8f29407a83377139e8321454de879fdb48418fe2f7622bf5983e471d06555
languageName: node
linkType: hard
"@humanwhocodes/config-array@npm:^0.11.10, @humanwhocodes/config-array@npm:^0.11.13":
version: 0.11.13
resolution: "@humanwhocodes/config-array@npm:0.11.13"
@ -10272,25 +10260,6 @@ __metadata:
languageName: node
linkType: hard
"@xstate/react@npm:^3.2.1":
version: 3.2.1
resolution: "@xstate/react@npm:3.2.1"
dependencies:
use-isomorphic-layout-effect: "npm:^1.0.0"
use-sync-external-store: "npm:^1.0.0"
peerDependencies:
"@xstate/fsm": ^2.0.0
react: ^16.8.0 || ^17.0.0 || ^18.0.0
xstate: ^4.36.0
peerDependenciesMeta:
"@xstate/fsm":
optional: true
xstate:
optional: true
checksum: a7b2538459ecf2bf94065c1c074b9d8db31cdb2f7b72cb1bf93fb0796191e07e15ebe3b971c038e85853c8ee9516a9eb18f08530ea2635803c832d58d056e847
languageName: node
linkType: hard
"@xtuc/ieee754@npm:^1.2.0":
version: 1.2.0
resolution: "@xtuc/ieee754@npm:1.2.0"
@ -12331,13 +12300,6 @@ __metadata:
languageName: node
linkType: hard
"client-only@npm:^0.0.1":
version: 0.0.1
resolution: "client-only@npm:0.0.1"
checksum: 0c16bf660dadb90610553c1d8946a7fdfb81d624adea073b8440b7d795d5b5b08beb3c950c6a2cf16279365a3265158a236876d92bce16423c485c322d7dfaf8
languageName: node
linkType: hard
"cliui@npm:^7.0.2":
version: 7.0.4
resolution: "cliui@npm:7.0.4"
@ -17600,7 +17562,6 @@ __metadata:
react-dom: "npm:18.2.0"
react-draggable: "npm:4.4.5"
react-dropzone: "npm:^14.2.3"
react-enable: "npm:^3.1.0"
react-grid-layout: "npm:1.4.2"
react-highlight-words: "npm:0.20.0"
react-hook-form: "npm:7.5.3"
@ -25441,21 +25402,6 @@ __metadata:
languageName: node
linkType: hard
"react-enable@npm:^3.1.0":
version: 3.1.1
resolution: "react-enable@npm:3.1.1"
dependencies:
"@headlessui/react": "npm:^1.5.0"
"@xstate/react": "npm:^3.2.1"
tslib: "npm:^1.14.1"
xstate: "npm:^4.37.0"
peerDependencies:
react: ^17 || ^18
react-dom: ^17 || ^18
checksum: 58321c06a9255ed3308d8211a50907e47fccf2f7f2c21ef387e7d83fec6920eea5e82a3c20c656dece922935c5d54bc3d69b08a978afe938bc981b1198622c3b
languageName: node
linkType: hard
"react-error-boundary@npm:^3.1.0":
version: 3.1.4
resolution: "react-error-boundary@npm:3.1.4"
@ -29377,7 +29323,7 @@ __metadata:
languageName: node
linkType: hard
"tslib@npm:^1.10.0, tslib@npm:^1.13.0, tslib@npm:^1.14.1, tslib@npm:^1.8.1":
"tslib@npm:^1.10.0, tslib@npm:^1.13.0, tslib@npm:^1.8.1":
version: 1.14.1
resolution: "tslib@npm:1.14.1"
checksum: 7dbf34e6f55c6492637adb81b555af5e3b4f9cc6b998fb440dac82d3b42bdc91560a35a5fb75e20e24a076c651438234da6743d139e4feabf0783f3cdfe1dddb
@ -29934,7 +29880,7 @@ __metadata:
languageName: node
linkType: hard
"use-isomorphic-layout-effect@npm:^1.0.0, use-isomorphic-layout-effect@npm:^1.1.2":
"use-isomorphic-layout-effect@npm:^1.1.2":
version: 1.1.2
resolution: "use-isomorphic-layout-effect@npm:1.1.2"
peerDependencies:
@ -31039,13 +30985,6 @@ __metadata:
languageName: node
linkType: hard
"xstate@npm:^4.37.0":
version: 4.37.0
resolution: "xstate@npm:4.37.0"
checksum: e302846c99596185cbb72250d21070c05d0f0f171155cbdeb7762c580f5e467725ab4bb4c79feacbf0788e25a6d7da6e219e85fc01b1d7dad2730b8b38eb918e
languageName: node
linkType: hard
"xtend@npm:^4.0.0, xtend@npm:~4.0.0, xtend@npm:~4.0.1":
version: 4.0.2
resolution: "xtend@npm:4.0.2"

Loading…
Cancel
Save