@gooddata/sdk-ui-application-header 11.40.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2022-2026 GoodData Corporation
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,16 @@
1
+ # GoodData.UI SDK - Application Header
2
+
3
+ This package is a part of the [GoodData.UI SDK](https://sdk.gooddata.com/gooddata-ui/docs/about_gooddataui.html).
4
+ To learn more, check [the source monorepo](https://github.com/gooddata/gooddata-ui-sdk).
5
+
6
+ This package provides React components for the GoodData application header — the notifications dropdown, the workspace picker, and supporting hooks for paged workspace lookups.
7
+
8
+ ## Stability
9
+
10
+ The API surface is marked `@alpha` and may change between minor releases.
11
+
12
+ ## License
13
+
14
+ (C) 2022-2026 GoodData Corporation
15
+
16
+ This project is under MIT License. See [LICENSE](https://github.com/gooddata/gooddata-ui-sdk/blob/master/libs/sdk-ui-application-header/LICENSE).
@@ -0,0 +1,11 @@
1
+ import { type ILocale } from "@gooddata/sdk-ui";
2
+ /**
3
+ * @alpha
4
+ */
5
+ export declare function AppHeaderNotifications({ isMobile, closeNotificationsOverlay, locale, useAsOfDateParam, enableExportToDocumentStorage }: {
6
+ isMobile?: boolean;
7
+ closeNotificationsOverlay?: () => void;
8
+ locale?: ILocale;
9
+ useAsOfDateParam?: boolean;
10
+ enableExportToDocumentStorage?: boolean;
11
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,22 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { DefaultNotificationsPanelButton, NotificationsPanel } from "@gooddata/sdk-ui-ext";
3
+ import { getDashboardUrl } from "./dashboardUrl.js";
4
+ /**
5
+ * @alpha
6
+ */
7
+ export function AppHeaderNotifications({ isMobile = false, closeNotificationsOverlay, locale, useAsOfDateParam, enableExportToDocumentStorage, }) {
8
+ const onNotificationClick = (notification) => {
9
+ const url = getDashboardUrl(notification, useAsOfDateParam);
10
+ if (url && notification.notificationType === "alertNotification") {
11
+ closeNotificationsOverlay?.();
12
+ // When query params do not change, we want to trigger router with location change manually
13
+ if (window.location.href === url) {
14
+ window.dispatchEvent(new HashChangeEvent("hashchange"));
15
+ }
16
+ else {
17
+ window.location.assign(url);
18
+ }
19
+ }
20
+ };
21
+ return (_jsx(NotificationsPanel, { NotificationsPanelButton: DefaultNotificationsPanelButton, onNotificationClick: onNotificationClick, renderInline: isMobile, enableScheduleNotifications: enableExportToDocumentStorage, locale: locale }));
22
+ }
@@ -0,0 +1,2 @@
1
+ import { type INotification } from "@gooddata/sdk-model";
2
+ export declare function getDashboardUrl(notification: INotification, useAsOfDateParam?: boolean): string | null;
@@ -0,0 +1,36 @@
1
+ // (C) 2025-2026 GoodData Corporation
2
+ import { isAlertNotification } from "@gooddata/sdk-model";
3
+ export function getDashboardUrl(notification, useAsOfDateParam = false) {
4
+ if (!isAlertNotification(notification)) {
5
+ return null;
6
+ }
7
+ const dashboardURL = notification.details.data.automation.dashboardURL;
8
+ const isCustomDashboardURL = notification.details.data.automation.isCustomDashboardURL;
9
+ if (isCustomDashboardURL || !notification.automationId) {
10
+ return dashboardURL;
11
+ }
12
+ const url = new URL(dashboardURL);
13
+ // Add parameters function
14
+ const addParams = (params) => {
15
+ if (!params.has("automationId")) {
16
+ params.append("automationId", notification.automationId);
17
+ }
18
+ if (useAsOfDateParam && !params.has("asOfDate")) {
19
+ params.append("asOfDate", notification.details.timestamp);
20
+ }
21
+ return params;
22
+ };
23
+ // If URL has a hash, add parameters to the hash part
24
+ if (url.hash) {
25
+ const baseUrl = `${url.origin}${url.pathname}${url.search}`;
26
+ const hashPath = url.hash.substring(1);
27
+ // Split hash into route and params if it contains a query string
28
+ const [hashRoute, paramString] = hashPath.includes("?") ? hashPath.split("?", 2) : [hashPath, ""];
29
+ // Add parameters to hash part
30
+ const hashParams = addParams(new URLSearchParams(paramString));
31
+ return `${baseUrl}#${hashRoute}?${hashParams.toString()}`;
32
+ }
33
+ // For URLs without hash, add parameters to the URL search
34
+ url.search = addParams(new URLSearchParams(url.search)).toString();
35
+ return url.toString();
36
+ }
@@ -0,0 +1,17 @@
1
+ import { type MouseEvent } from "react";
2
+ import { type IAnalyticalBackend } from "@gooddata/sdk-backend-spi";
3
+ import { type IHeaderWorkspace } from "@gooddata/sdk-ui-kit";
4
+ /**
5
+ * @alpha
6
+ */
7
+ export interface IWorkspacePickerProps {
8
+ backend: IAnalyticalBackend;
9
+ userId: string;
10
+ selectedWorkspace?: IHeaderWorkspace;
11
+ onWorkspaceSelect: (workspace: IHeaderWorkspace) => void;
12
+ onHomepageLinkClick?: (evt: MouseEvent) => void;
13
+ }
14
+ /**
15
+ * @alpha
16
+ */
17
+ export declare function WorkspacePicker({ backend, userId, selectedWorkspace, onWorkspaceSelect, onHomepageLinkClick }: IWorkspacePickerProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,26 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // (C) 2026 GoodData Corporation
3
+ import { useCallback } from "react";
4
+ import { DomainHomepageLink, HeaderWorkspacePicker } from "@gooddata/sdk-ui-kit";
5
+ import { usePagedWorkspaces } from "./usePagedWorkspaces.js";
6
+ /**
7
+ * @alpha
8
+ */
9
+ export function WorkspacePicker({ backend, userId, selectedWorkspace, onWorkspaceSelect, onHomepageLinkClick, }) {
10
+ const { items, totalItemsCount, isLoading, search, onSearch, loadInitialItems, reset, initialLoadCompleted, hasNextPage, skeletonItemsCount, isNextPageLoading, shouldLoadNextPage, loadNextPage, } = usePagedWorkspaces({
11
+ backend,
12
+ userId,
13
+ });
14
+ const handleOpenStateChanged = useCallback((opened) => {
15
+ if (opened) {
16
+ // Fetch initial items when dropdown opens
17
+ loadInitialItems();
18
+ }
19
+ else {
20
+ reset();
21
+ }
22
+ }, [loadInitialItems, reset]);
23
+ return (_jsx(HeaderWorkspacePicker, { projectPickerFooter: _jsx(DomainHomepageLink, { onClick: onHomepageLinkClick }), workspaces: items, selectedWorkspace: selectedWorkspace, totalWorkspacesCount: totalItemsCount, searchString: search, showSearch: initialLoadCompleted, isLoading: isLoading ? items.length === 0 : false, onSelect: onWorkspaceSelect, onSearch: onSearch, onOpenStateChanged: handleOpenStateChanged,
24
+ //paging props
25
+ loadNextPage: loadNextPage, hasNextPage: hasNextPage, skeletonItemsCount: skeletonItemsCount, isNextPageLoading: isNextPageLoading, shouldLoadNextPage: shouldLoadNextPage }));
26
+ }
@@ -0,0 +1,40 @@
1
+ import { type IAnalyticalBackend, type IAnalyticalWorkspace, type IWorkspaceDescriptor } from "@gooddata/sdk-backend-spi";
2
+ /**
3
+ * Conditional type that resolves workspace items based on resolveWorkspaceDescriptor flag.
4
+ * - When true (default): returns IWorkspaceDescriptor[] (resolved descriptors with id, title, description)
5
+ * - When false: returns IAnalyticalWorkspace[] (workspace handles with service methods)
6
+ *
7
+ * @alpha
8
+ */
9
+ export type WorkspaceItems<TResolve extends boolean> = TResolve extends true ? IWorkspaceDescriptor[] : IAnalyticalWorkspace[];
10
+ /**
11
+ * @alpha
12
+ */
13
+ export interface IPagedWorkspacesConfig<TResolve extends boolean = true> {
14
+ backend: IAnalyticalBackend;
15
+ userId: string;
16
+ resolveWorkspaceDescriptor?: TResolve;
17
+ }
18
+ /**
19
+ * @alpha
20
+ */
21
+ export interface IPagedWorkspacesResult<TResolve extends boolean = true> {
22
+ items: WorkspaceItems<TResolve>;
23
+ totalItemsCount: number | undefined;
24
+ isLoading: boolean;
25
+ isNextPageLoading: boolean;
26
+ initialLoadCompleted: boolean;
27
+ currentPage: number;
28
+ search: string;
29
+ hasNextPage: boolean;
30
+ skeletonItemsCount: number;
31
+ loadNextPage: () => void;
32
+ onSearch: (searchString: string) => void;
33
+ reset: () => void;
34
+ loadInitialItems: () => void;
35
+ shouldLoadNextPage: (lastItemIndex: number, itemsCount: number) => boolean;
36
+ }
37
+ /**
38
+ * @alpha
39
+ */
40
+ export declare function usePagedWorkspaces<TResolve extends boolean = true>({ backend, userId, resolveWorkspaceDescriptor }: IPagedWorkspacesConfig<TResolve>): IPagedWorkspacesResult<TResolve>;
@@ -0,0 +1,149 @@
1
+ // (C) 2026 GoodData Corporation
2
+ import { useCallback, useRef, useState } from "react";
3
+ import { debounce } from "lodash-es";
4
+ const ITEMS_PER_PAGE = 50;
5
+ /**
6
+ * @alpha
7
+ */
8
+ export function usePagedWorkspaces({ backend, userId, resolveWorkspaceDescriptor = true, }) {
9
+ const [items, setItems] = useState([]);
10
+ const [totalItemsCount, setTotalItemsCount] = useState(undefined);
11
+ const [isLoading, setIsLoading] = useState(false);
12
+ const [isNextPageLoading, setIsNextPageLoading] = useState(false);
13
+ const [initialLoadCompleted, setInitialLoadCompleted] = useState(false);
14
+ const [currentPage, setCurrentPage] = useState(0);
15
+ const [search, setSearch] = useState("");
16
+ const initialLoadCompletedRef = useRef(false);
17
+ const abortControllerRef = useRef(null);
18
+ const totalItems = totalItemsCount ?? items.length;
19
+ const hasNextPage = totalItems > items.length;
20
+ const skeletonItemsCount = hasNextPage ? Math.min(ITEMS_PER_PAGE, totalItems - items.length) : 0;
21
+ const fetchItems = useCallback(async (params) => {
22
+ const { page, search, resetItems = false } = params;
23
+ // Cancel any ongoing request
24
+ if (abortControllerRef.current) {
25
+ abortControllerRef.current.abort();
26
+ }
27
+ abortControllerRef.current = new AbortController();
28
+ // Capture the current signal before the await to check the correct one after
29
+ const currentSignal = abortControllerRef.current.signal;
30
+ const isFirstPage = page === 0;
31
+ // Show global loading when resetting items (tab switch, search) or on first page
32
+ if (resetItems || isFirstPage) {
33
+ setIsLoading(true);
34
+ // Clear items immediately to show loading spinner
35
+ if (resetItems) {
36
+ setItems([]);
37
+ setTotalItemsCount(undefined);
38
+ }
39
+ }
40
+ else {
41
+ setIsNextPageLoading(true);
42
+ }
43
+ try {
44
+ const limit = ITEMS_PER_PAGE;
45
+ const offset = page * ITEMS_PER_PAGE;
46
+ const searchValue = search;
47
+ let resultWorkspaces;
48
+ if (searchValue) {
49
+ resultWorkspaces = await backend
50
+ .workspaces()
51
+ .forUser(userId)
52
+ .withLimit(limit)
53
+ .withOffset(offset)
54
+ .withSearch(searchValue)
55
+ .query();
56
+ }
57
+ else {
58
+ resultWorkspaces = await backend
59
+ .workspaces()
60
+ .forUser(userId)
61
+ .withLimit(limit)
62
+ .withOffset(offset)
63
+ .query();
64
+ }
65
+ let fetchedItems;
66
+ if (resolveWorkspaceDescriptor) {
67
+ fetchedItems = (await Promise.all(resultWorkspaces.items.map((workspace) => workspace?.getDescriptor())));
68
+ }
69
+ else {
70
+ fetchedItems = resultWorkspaces.items;
71
+ }
72
+ const totalItemsCount = resultWorkspaces.totalCount;
73
+ // Check if THIS request was aborted (using captured signal, not current ref)
74
+ if (currentSignal.aborted) {
75
+ return;
76
+ }
77
+ setTotalItemsCount(totalItemsCount);
78
+ if (resetItems || isFirstPage) {
79
+ setItems(fetchedItems);
80
+ }
81
+ else {
82
+ setItems((prevItems) => [...prevItems, ...fetchedItems]);
83
+ }
84
+ // Handle initial load completion
85
+ if (!initialLoadCompletedRef.current) {
86
+ initialLoadCompletedRef.current = true;
87
+ setInitialLoadCompleted(true);
88
+ }
89
+ }
90
+ catch (error) {
91
+ // Ignore abort errors
92
+ if (error.name !== "AbortError") {
93
+ console.error("Failed to fetch insights:", error);
94
+ }
95
+ }
96
+ finally {
97
+ // Only update loading state if this request wasn't superseded
98
+ if (!currentSignal.aborted) {
99
+ setIsLoading(false);
100
+ setIsNextPageLoading(false);
101
+ }
102
+ }
103
+ }, [backend, userId, resolveWorkspaceDescriptor]);
104
+ const loadNextPage = useCallback(() => {
105
+ if (!hasNextPage || isNextPageLoading || isLoading) {
106
+ return;
107
+ }
108
+ const nextPage = currentPage + 1;
109
+ setCurrentPage(nextPage);
110
+ void fetchItems({ page: nextPage, search });
111
+ }, [hasNextPage, isNextPageLoading, isLoading, currentPage, search, fetchItems]);
112
+ // eslint-disable-next-line react-hooks/exhaustive-deps
113
+ const onSearch = useCallback(debounce((searchString) => {
114
+ setCurrentPage(0);
115
+ setSearch(searchString);
116
+ void fetchItems({ page: 0, search: searchString, resetItems: true });
117
+ }, 500), [fetchItems]);
118
+ const reset = useCallback(() => {
119
+ if (abortControllerRef.current) {
120
+ abortControllerRef.current.abort();
121
+ }
122
+ setItems([]);
123
+ setTotalItemsCount(undefined);
124
+ setIsLoading(false);
125
+ setIsNextPageLoading(false);
126
+ setCurrentPage(0);
127
+ setSearch("");
128
+ }, []);
129
+ const shouldLoadNextPage = useCallback((lastItemIndex, itemsCount) => lastItemIndex >= itemsCount - 5, []);
130
+ const loadInitialItems = useCallback(() => {
131
+ void fetchItems({ page: 0, search: "", resetItems: true });
132
+ }, [fetchItems]);
133
+ return {
134
+ items,
135
+ totalItemsCount,
136
+ isLoading,
137
+ isNextPageLoading,
138
+ initialLoadCompleted,
139
+ currentPage,
140
+ search,
141
+ hasNextPage,
142
+ skeletonItemsCount,
143
+ loadInitialItems,
144
+ loadNextPage,
145
+ onSearch,
146
+ reset,
147
+ shouldLoadNextPage,
148
+ };
149
+ }
package/esm/index.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ export { AppHeaderNotifications } from "./AppHeaderNotifications/AppHeaderNotifications.js";
2
+ export { WorkspacePicker, type IWorkspacePickerProps } from "./WorkspacePicker/WorkspacePicker.js";
3
+ export { usePagedWorkspaces, type IPagedWorkspacesConfig, type IPagedWorkspacesResult, type WorkspaceItems, } from "./WorkspacePicker/usePagedWorkspaces.js";
package/esm/index.js ADDED
@@ -0,0 +1,5 @@
1
+ // (C) 2022-2026 GoodData Corporation
2
+ /* oxlint-disable no-barrel-files/no-barrel-files */
3
+ export { AppHeaderNotifications } from "./AppHeaderNotifications/AppHeaderNotifications.js";
4
+ export { WorkspacePicker } from "./WorkspacePicker/WorkspacePicker.js";
5
+ export { usePagedWorkspaces, } from "./WorkspacePicker/usePagedWorkspaces.js";
@@ -0,0 +1,79 @@
1
+ import { IAnalyticalBackend } from '@gooddata/sdk-backend-spi';
2
+ import { IAnalyticalWorkspace } from '@gooddata/sdk-backend-spi';
3
+ import { IHeaderWorkspace } from '@gooddata/sdk-ui-kit';
4
+ import { ILocale } from '@gooddata/sdk-ui';
5
+ import { IWorkspaceDescriptor } from '@gooddata/sdk-backend-spi';
6
+ import { JSX } from 'react/jsx-runtime';
7
+ import { MouseEvent as MouseEvent_2 } from 'react';
8
+
9
+ /**
10
+ * @alpha
11
+ */
12
+ export declare function AppHeaderNotifications({ isMobile, closeNotificationsOverlay, locale, useAsOfDateParam, enableExportToDocumentStorage }: {
13
+ isMobile?: boolean;
14
+ closeNotificationsOverlay?: () => void;
15
+ locale?: ILocale;
16
+ useAsOfDateParam?: boolean;
17
+ enableExportToDocumentStorage?: boolean;
18
+ }): JSX.Element;
19
+
20
+ /**
21
+ * @alpha
22
+ */
23
+ export declare interface IPagedWorkspacesConfig<TResolve extends boolean = true> {
24
+ backend: IAnalyticalBackend;
25
+ userId: string;
26
+ resolveWorkspaceDescriptor?: TResolve;
27
+ }
28
+
29
+ /**
30
+ * @alpha
31
+ */
32
+ export declare interface IPagedWorkspacesResult<TResolve extends boolean = true> {
33
+ items: WorkspaceItems<TResolve>;
34
+ totalItemsCount: number | undefined;
35
+ isLoading: boolean;
36
+ isNextPageLoading: boolean;
37
+ initialLoadCompleted: boolean;
38
+ currentPage: number;
39
+ search: string;
40
+ hasNextPage: boolean;
41
+ skeletonItemsCount: number;
42
+ loadNextPage: () => void;
43
+ onSearch: (searchString: string) => void;
44
+ reset: () => void;
45
+ loadInitialItems: () => void;
46
+ shouldLoadNextPage: (lastItemIndex: number, itemsCount: number) => boolean;
47
+ }
48
+
49
+ /**
50
+ * @alpha
51
+ */
52
+ export declare interface IWorkspacePickerProps {
53
+ backend: IAnalyticalBackend;
54
+ userId: string;
55
+ selectedWorkspace?: IHeaderWorkspace;
56
+ onWorkspaceSelect: (workspace: IHeaderWorkspace) => void;
57
+ onHomepageLinkClick?: (evt: MouseEvent_2) => void;
58
+ }
59
+
60
+ /**
61
+ * @alpha
62
+ */
63
+ export declare function usePagedWorkspaces<TResolve extends boolean = true>({ backend, userId, resolveWorkspaceDescriptor }: IPagedWorkspacesConfig<TResolve>): IPagedWorkspacesResult<TResolve>;
64
+
65
+ /**
66
+ * Conditional type that resolves workspace items based on resolveWorkspaceDescriptor flag.
67
+ * - When true (default): returns IWorkspaceDescriptor[] (resolved descriptors with id, title, description)
68
+ * - When false: returns IAnalyticalWorkspace[] (workspace handles with service methods)
69
+ *
70
+ * @alpha
71
+ */
72
+ export declare type WorkspaceItems<TResolve extends boolean> = TResolve extends true ? IWorkspaceDescriptor[] : IAnalyticalWorkspace[];
73
+
74
+ /**
75
+ * @alpha
76
+ */
77
+ export declare function WorkspacePicker({ backend, userId, selectedWorkspace, onWorkspaceSelect, onHomepageLinkClick }: IWorkspacePickerProps): JSX.Element;
78
+
79
+ export { }
@@ -0,0 +1,11 @@
1
+ // This file is read by tools that parse documentation comments conforming to the TSDoc standard.
2
+ // It should be published with your NPM package. It should not be tracked by Git.
3
+ {
4
+ "tsdocVersion": "0.12",
5
+ "toolPackages": [
6
+ {
7
+ "packageName": "@microsoft/api-extractor",
8
+ "packageVersion": "7.55.2"
9
+ }
10
+ ]
11
+ }
package/package.json ADDED
@@ -0,0 +1,102 @@
1
+ {
2
+ "name": "@gooddata/sdk-ui-application-header",
3
+ "version": "11.40.0-alpha.3",
4
+ "description": "GoodData SDK application header components — workspace picker, notifications dropdown",
5
+ "license": "MIT",
6
+ "author": "GoodData Corporation",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/gooddata/gooddata-ui-sdk.git",
10
+ "directory": "libs/sdk-ui-application-header"
11
+ },
12
+ "files": [
13
+ "esm/**/*.js",
14
+ "esm/**/*.json",
15
+ "esm/**/*.d.ts",
16
+ "esm/**/*.map"
17
+ ],
18
+ "type": "module",
19
+ "sideEffects": false,
20
+ "browser": "./esm/index.js",
21
+ "types": "esm/index.d.ts",
22
+ "exports": "./esm/index.js",
23
+ "dependencies": {
24
+ "lodash-es": "^4.17.23",
25
+ "@gooddata/sdk-backend-spi": "11.40.0-alpha.3",
26
+ "@gooddata/sdk-ui": "11.40.0-alpha.3",
27
+ "@gooddata/sdk-model": "11.40.0-alpha.3",
28
+ "@gooddata/sdk-ui-ext": "11.40.0-alpha.3",
29
+ "@gooddata/sdk-ui-kit": "11.40.0-alpha.3",
30
+ "@gooddata/util": "11.40.0-alpha.3"
31
+ },
32
+ "devDependencies": {
33
+ "@microsoft/api-documenter": "^7.17.0",
34
+ "@microsoft/api-extractor": "^7.55.2",
35
+ "@testing-library/dom": "10.4.1",
36
+ "@testing-library/react": "16.3.0",
37
+ "@types/lodash-es": "^4.17.12",
38
+ "@types/node": "24.12.0",
39
+ "@types/react": "19.1.11",
40
+ "@types/react-dom": "19.1.7",
41
+ "@typescript-eslint/eslint-plugin": "8.58.0",
42
+ "@typescript-eslint/parser": "8.58.0",
43
+ "@typescript/native-preview": "7.0.0-dev.20260202.1",
44
+ "@vitest/coverage-v8": "4.1.0",
45
+ "@vitest/eslint-plugin": "1.6.6",
46
+ "eslint": "^9.39.2",
47
+ "eslint-import-resolver-typescript": "4.4.4",
48
+ "eslint-plugin-headers": "1.3.3",
49
+ "eslint-plugin-import-esm": "1.2.1",
50
+ "eslint-plugin-import-x": "4.16.1",
51
+ "eslint-plugin-jsdoc": "62.1.0",
52
+ "eslint-plugin-no-barrel-files": "1.2.2",
53
+ "eslint-plugin-no-only-tests": "3.3.0",
54
+ "eslint-plugin-react": "7.37.5",
55
+ "eslint-plugin-react-hooks": "5.2.0",
56
+ "eslint-plugin-regexp": "1.15.0",
57
+ "eslint-plugin-sonarjs": "3.0.6",
58
+ "eslint-plugin-tsdoc": "0.2.14",
59
+ "happy-dom": "18.0.1",
60
+ "jiti": "2.6.1",
61
+ "npm-run-all": "^4.1.5",
62
+ "oxfmt": "0.45.0",
63
+ "oxlint": "^1.43.0",
64
+ "oxlint-tsgolint": "0.11.4",
65
+ "react": "19.1.1",
66
+ "react-dom": "19.1.1",
67
+ "react-intl": "7.1.11",
68
+ "rolldown": "1.0.0-rc.9",
69
+ "tslib": "2.8.1",
70
+ "typescript": "5.9.3",
71
+ "vite": "8.0.0",
72
+ "vitest": "4.1.0",
73
+ "vitest-dom": "0.1.1",
74
+ "@gooddata/eslint-config": "11.40.0-alpha.3",
75
+ "@gooddata/oxlint-config": "11.40.0-alpha.3",
76
+ "@gooddata/sdk-ui-theme-provider": "11.40.0-alpha.3"
77
+ },
78
+ "peerDependencies": {
79
+ "react": ">=18.3.1",
80
+ "react-dom": ">=18.3.1",
81
+ "react-intl": ">=7"
82
+ },
83
+ "scripts": {
84
+ "_phase:build": "npm run build",
85
+ "_phase:test": "npm run test-once",
86
+ "_phase:validate": "npm run validate",
87
+ "api-extractor": "mkdir -p api && [ -z \"${CI}\" ] && (api-extractor run -l) || (api-extractor run)",
88
+ "build": "npm-run-all -p build-check build-ts && npm run api-extractor",
89
+ "build-check": "tsgo",
90
+ "build-ts": "tsgo -p ./tsconfig.build.json",
91
+ "clean": "../../common/scripts/clean-command-state.sh && rm -rf esm *.log",
92
+ "format-check": "oxfmt --check .",
93
+ "format-write": "oxfmt .",
94
+ "lint": "oxlint . --type-aware --quiet && eslint .",
95
+ "lint-fix": "oxlint . --type-aware --quiet --fix && eslint . --fix",
96
+ "test": "vitest",
97
+ "test-once": "vitest run",
98
+ "validate": "npm run lint && npm run format-check",
99
+ "validate-esm": "node --input-type=module --eval 'import \"@gooddata/sdk-ui-application-header\"'",
100
+ "validate-theming": "node scripts/validateCss.mjs"
101
+ }
102
+ }