@gooddata/sdk-ui-kit 11.40.0-alpha.3 → 11.40.0-alpha.5

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.
@@ -0,0 +1,51 @@
1
+ import { type ReactNode } from "react";
2
+ import { type IUiToast, type IUiToastOptions, type IUseUiToastResult, type UiToastKind } from "./types.js";
3
+ interface IUiToastContextValue {
4
+ /** Currently shown toasts, oldest first. */
5
+ toasts: IUiToast[];
6
+ /**
7
+ * Push a toast onto the queue and return its id. `text` is already
8
+ * resolved by the consumer — see [[useUiToast]] for the wrapper that
9
+ * runs `resolveText` against the consumer's `useIntl()`.
10
+ */
11
+ push: (kind: UiToastKind, text: string, options?: IUiToastOptions) => string;
12
+ /** Dismiss one toast by id. */
13
+ remove: (id: string) => void;
14
+ /** Dismiss all toasts. */
15
+ removeAll: () => void;
16
+ /**
17
+ * Whether this provider is nested inside another `UiToastProvider`. The
18
+ * outermost provider renders the visible container; nested providers
19
+ * forward through context so the topmost-only behaviour is preserved.
20
+ */
21
+ isNested: boolean;
22
+ }
23
+ /**
24
+ * Mount once near the root of your app. Provides the toast queue + dismiss
25
+ * timers consumed by `useUiToast` and `UiToastsContainer`. Nesting is safe
26
+ * — only the outermost `<UiToastsContainer>` renders any visible toasts.
27
+ *
28
+ * Known limitation: if a root provider with in-flight toasts is **re-parented**
29
+ * under a new outer provider mid-flight (e.g. the app rearranges its tree),
30
+ * the inner instance's queue and timers don't migrate to the parent. Mount
31
+ * the provider once at the stable app root to avoid this.
32
+ *
33
+ * @internal
34
+ */
35
+ export declare function UiToastProvider({ children }: {
36
+ children: ReactNode;
37
+ }): import("react/jsx-runtime").JSX.Element;
38
+ /**
39
+ * Consumer hook. Resolves the toast message via the **caller's**
40
+ * `useIntl()` so a consumer rendered under a nested `IntlProvider` formats
41
+ * `MessageDescriptor` content with that subtree's locale, not the
42
+ * provider's. Throws when called outside a `UiToastProvider`.
43
+ *
44
+ * @internal
45
+ */
46
+ export declare function useUiToast(): IUseUiToastResult;
47
+ /**
48
+ * @internal
49
+ */
50
+ export declare const UiToastContextInternal: import("react").Context<IUiToastContextValue | null>;
51
+ export {};
@@ -0,0 +1,193 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // (C) 2026 GoodData Corporation
3
+ import { createContext, useCallback, useContext, useEffect, useId, useMemo, useRef, useState, } from "react";
4
+ import { useIntl } from "react-intl";
5
+ const DEFAULT_DURATION_MS = 4000;
6
+ /**
7
+ * Resolve a `UiToastMessage` to a flat string using the supplied `intl`.
8
+ * `UiToastIntlValues` only accepts `PrimitiveType` interpolation values, so
9
+ * `formatMessage` always returns `string` — no `ReactNode[]` coercion needed.
10
+ *
11
+ * Called from `useUiToast` so resolution uses the **consumer's** `useIntl()`
12
+ * (the locale of the calling subtree) rather than the provider's — a
13
+ * provider mounted at the app root would otherwise format with the root
14
+ * locale even when the caller sits under a nested `IntlProvider`.
15
+ */
16
+ const resolveText = (intl, message, options) => {
17
+ if (typeof message === "string") {
18
+ return options?.values
19
+ ? intl.formatMessage({ id: message, defaultMessage: message }, options.values)
20
+ : message;
21
+ }
22
+ return intl.formatMessage(message.descriptor, message.values);
23
+ };
24
+ const UiToastContext = createContext(null);
25
+ /**
26
+ * Mount once near the root of your app. Provides the toast queue + dismiss
27
+ * timers consumed by `useUiToast` and `UiToastsContainer`. Nesting is safe
28
+ * — only the outermost `<UiToastsContainer>` renders any visible toasts.
29
+ *
30
+ * Known limitation: if a root provider with in-flight toasts is **re-parented**
31
+ * under a new outer provider mid-flight (e.g. the app rearranges its tree),
32
+ * the inner instance's queue and timers don't migrate to the parent. Mount
33
+ * the provider once at the stable app root to avoid this.
34
+ *
35
+ * @internal
36
+ */
37
+ export function UiToastProvider({ children }) {
38
+ const parent = useContext(UiToastContext);
39
+ const [toasts, setToasts] = useState([]);
40
+ // `toastsRef` is the synchronous source of truth for the queue —
41
+ // mutators (`push` / `remove` / `removeAll`) update it FIRST and only
42
+ // then schedule the `setToasts` render. That way a same-tick
43
+ // `add → remove` sequence sees the just-added toast in the ref, and
44
+ // side effects (timers, `onDismiss`) run consistently without depending
45
+ // on React's commit timing. React state mirrors the ref on every render.
46
+ const toastsRef = useRef(toasts);
47
+ const timersRef = useRef(new Map());
48
+ const dismissedRef = useRef(new Set());
49
+ const idPrefix = useId();
50
+ const counterRef = useRef(0);
51
+ const clearTimer = useCallback((id) => {
52
+ const timer = timersRef.current.get(id);
53
+ if (timer) {
54
+ clearTimeout(timer);
55
+ timersRef.current.delete(id);
56
+ }
57
+ }, []);
58
+ // Single mutation point — update the ref synchronously, then sync the
59
+ // React state via the same value. Other mutators call this so the ref
60
+ // and the state stay in lockstep without depending on commit timing.
61
+ const commit = useCallback((next) => {
62
+ toastsRef.current = next;
63
+ setToasts(next);
64
+ }, []);
65
+ const remove = useCallback((id) => {
66
+ // Bail if this id has already been dismissed (auto-dismiss +
67
+ // manual race, or StrictMode's double-invocation). Otherwise
68
+ // tear down synchronously: ref + state in the same tick, side
69
+ // effects (timer cleanup, `onDismiss`) right after.
70
+ if (dismissedRef.current.has(id))
71
+ return;
72
+ const t = toastsRef.current.find((x) => x.id === id);
73
+ if (!t)
74
+ return;
75
+ dismissedRef.current.add(id);
76
+ clearTimer(id);
77
+ commit(toastsRef.current.filter((x) => x.id !== id));
78
+ t.onDismiss?.();
79
+ }, [clearTimer, commit]);
80
+ const removeAll = useCallback(() => {
81
+ // Snapshot first so the loop sees a stable list even if `onDismiss`
82
+ // turns around and calls `add` / `remove` synchronously. Ref +
83
+ // state are cleared together; side effects run after the commit
84
+ // call, so a throwing `onDismiss` can't corrupt the queue.
85
+ const snapshot = toastsRef.current;
86
+ const onDismisses = [];
87
+ for (const t of snapshot) {
88
+ if (!dismissedRef.current.has(t.id)) {
89
+ dismissedRef.current.add(t.id);
90
+ if (t.onDismiss)
91
+ onDismisses.push(t.onDismiss);
92
+ }
93
+ clearTimer(t.id);
94
+ }
95
+ commit([]);
96
+ for (const cb of onDismisses)
97
+ cb();
98
+ }, [clearTimer, commit]);
99
+ const push = useCallback((kind, text, options) => {
100
+ const id = options?.id ?? `${idPrefix}-${counterRef.current++}`;
101
+ const sticky = options?.sticky ?? false;
102
+ const durationMs = options?.durationMs ?? DEFAULT_DURATION_MS;
103
+ const toast = {
104
+ id,
105
+ kind,
106
+ text,
107
+ sticky,
108
+ durationMs,
109
+ action: options?.action,
110
+ accessibilityConfig: options?.accessibilityConfig,
111
+ onDismiss: options?.onDismiss,
112
+ };
113
+ // Reusing an existing id replaces the toast in place and resets
114
+ // its dismiss timer.
115
+ clearTimer(id);
116
+ dismissedRef.current.delete(id);
117
+ const prev = toastsRef.current;
118
+ const existing = prev.findIndex((t) => t.id === id);
119
+ const next = existing >= 0 ? prev.map((t, i) => (i === existing ? toast : t)) : [...prev, toast];
120
+ commit(next);
121
+ if (!sticky) {
122
+ const timer = setTimeout(() => remove(id), durationMs);
123
+ timersRef.current.set(id, timer);
124
+ }
125
+ return id;
126
+ }, [idPrefix, remove, clearTimer, commit]);
127
+ // Cancel pending dismiss timers on unmount.
128
+ useEffect(() => {
129
+ const timers = timersRef.current;
130
+ return () => {
131
+ for (const timer of timers.values())
132
+ clearTimeout(timer);
133
+ timers.clear();
134
+ };
135
+ }, []);
136
+ // Trim `dismissedRef` to ids still in `toasts` once React commits a
137
+ // removal. The ref's only job is to dedupe within a single dispatch
138
+ // (StrictMode double-invocation, auto-dismiss + manual race) — once
139
+ // the toast has left state, no future call can race on the same id,
140
+ // so the ref entry is dead weight. Without this trim the Set would
141
+ // grow monotonically for every auto-generated id in a long-running
142
+ // SPA. Runs after commit, so StrictMode's pre-commit second pass
143
+ // still sees the id during the dispatch that removed it.
144
+ useEffect(() => {
145
+ const liveIds = new Set(toasts.map((t) => t.id));
146
+ for (const id of dismissedRef.current) {
147
+ if (!liveIds.has(id))
148
+ dismissedRef.current.delete(id);
149
+ }
150
+ }, [toasts]);
151
+ const value = useMemo(() => {
152
+ if (parent) {
153
+ // Nested provider: forward to the parent so a single queue is the
154
+ // source of truth. `isNested` flips so any nested
155
+ // `UiToastsContainer` knows to render nothing.
156
+ return { ...parent, isNested: true };
157
+ }
158
+ return { toasts, push, remove, removeAll, isNested: false };
159
+ }, [parent, toasts, push, remove, removeAll]);
160
+ return _jsx(UiToastContext.Provider, { value: value, children: children });
161
+ }
162
+ /**
163
+ * Consumer hook. Resolves the toast message via the **caller's**
164
+ * `useIntl()` so a consumer rendered under a nested `IntlProvider` formats
165
+ * `MessageDescriptor` content with that subtree's locale, not the
166
+ * provider's. Throws when called outside a `UiToastProvider`.
167
+ *
168
+ * @internal
169
+ */
170
+ export function useUiToast() {
171
+ const ctx = useContext(UiToastContext);
172
+ if (!ctx) {
173
+ throw new Error("useUiToast must be used inside <UiToastProvider>");
174
+ }
175
+ const intl = useIntl();
176
+ const { push, remove, removeAll } = ctx;
177
+ return useMemo(() => {
178
+ const add = (kind, message, options) => push(kind, resolveText(intl, message, options), options);
179
+ return {
180
+ addSuccess: (message, options) => add("success", message, options),
181
+ addInfo: (message, options) => add("info", message, options),
182
+ addWarning: (message, options) => add("warning", message, options),
183
+ addError: (message, options) => add("error", message, options),
184
+ add,
185
+ remove,
186
+ removeAll,
187
+ };
188
+ }, [intl, push, remove, removeAll]);
189
+ }
190
+ /**
191
+ * @internal
192
+ */
193
+ export const UiToastContextInternal = UiToastContext;
@@ -0,0 +1,33 @@
1
+ import { type ReactNode } from "react";
2
+ import { type IUiToast } from "./types.js";
3
+ /**
4
+ * @internal
5
+ */
6
+ export interface IUiToastItemProps {
7
+ toast: IUiToast;
8
+ /** Fired when the user dismisses (close X or action click). */
9
+ onClose: (id: string) => void;
10
+ }
11
+ /**
12
+ * Presentational single-toast component. Most consumers use
13
+ * `UiToastsContainer` (which reads queued toasts from the provider), but
14
+ * this can be rendered directly for static demos or one-off composition.
15
+ *
16
+ * @internal
17
+ */
18
+ export declare function UiToastItem({ toast, onClose }: IUiToastItemProps): ReactNode;
19
+ /**
20
+ * @internal
21
+ */
22
+ export interface IUiToastsContainerProps {
23
+ /** Test id forwarded to the root element. */
24
+ dataTestId?: string;
25
+ }
26
+ /**
27
+ * Renders the list of toasts queued by `useUiToast`. Mount once near the app
28
+ * root, inside a `UiToastProvider`. Nested containers render nothing — only
29
+ * the outermost one is visible, preserving the topmost-only behaviour.
30
+ *
31
+ * @internal
32
+ */
33
+ export declare function UiToastsContainer({ dataTestId }: IUiToastsContainerProps): ReactNode;
@@ -0,0 +1,56 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // (C) 2026 GoodData Corporation
3
+ import { useContext, useMemo } from "react";
4
+ import { useIntl } from "react-intl";
5
+ import { commonDialogMessages } from "../../locales.js";
6
+ import { bem } from "../@utils/bem.js";
7
+ import { UiIcon } from "../UiIcon/UiIcon.js";
8
+ import { UiToastContextInternal } from "./UiToastProvider.js";
9
+ const { b, e } = bem("gd-ui-kit-toast");
10
+ // Errors and warnings interrupt screen readers by default; success/info wait
11
+ // for the assistive-tech queue to be free. Callers can override per toast.
12
+ const DEFAULT_ARIA_LIVE = {
13
+ success: "polite",
14
+ info: "polite",
15
+ warning: "assertive",
16
+ error: "assertive",
17
+ };
18
+ /**
19
+ * Presentational single-toast component. Most consumers use
20
+ * `UiToastsContainer` (which reads queued toasts from the provider), but
21
+ * this can be rendered directly for static demos or one-off composition.
22
+ *
23
+ * @internal
24
+ */
25
+ export function UiToastItem({ toast, onClose }) {
26
+ const intl = useIntl();
27
+ const ariaLive = toast.accessibilityConfig?.ariaLive ?? DEFAULT_ARIA_LIVE[toast.kind];
28
+ const role = toast.accessibilityConfig?.role ?? (ariaLive === "assertive" ? "alert" : "status");
29
+ const closeLabel = toast.accessibilityConfig?.closeButtonLabel ?? intl.formatMessage(commonDialogMessages.close);
30
+ return (_jsxs("div", { className: e("item", { kind: toast.kind }), role: role, "aria-live": ariaLive, "aria-label": toast.accessibilityConfig?.ariaLabel, "aria-labelledby": toast.accessibilityConfig?.ariaLabelledBy, "aria-describedby": toast.accessibilityConfig?.ariaDescribedBy, "data-testid": `gd-ui-kit-toast-${toast.kind}-${toast.id}`, children: [
31
+ _jsx("span", { className: e("body"), children: toast.text }), toast.action ? (_jsx("button", { type: "button", className: e("action"), onClick: () => {
32
+ toast.action.onClick();
33
+ onClose(toast.id);
34
+ }, children: toast.action.label })) : null, _jsx("button", { type: "button", className: e("close"), onClick: () => onClose(toast.id), "aria-label": closeLabel, children: _jsx(UiIcon, { type: "cross", size: 14, color: "currentColor" }) })
35
+ ] }));
36
+ }
37
+ /**
38
+ * Renders the list of toasts queued by `useUiToast`. Mount once near the app
39
+ * root, inside a `UiToastProvider`. Nested containers render nothing — only
40
+ * the outermost one is visible, preserving the topmost-only behaviour.
41
+ *
42
+ * @internal
43
+ */
44
+ export function UiToastsContainer({ dataTestId }) {
45
+ const ctx = useContext(UiToastContextInternal);
46
+ // Render newest-first so the most recent notification sits at the top
47
+ // of the stack — matches the legacy `ToastsCenter` overlay
48
+ // (`messages.sort((a, b) => b.createdAt - a.createdAt)`). The queue
49
+ // itself stays in insertion order for `push` / `remove` correctness;
50
+ // only the rendered list is reversed.
51
+ const items = useMemo(() => (ctx?.toasts ? [...ctx.toasts].reverse() : []), [ctx?.toasts]);
52
+ if (!ctx || ctx.isNested) {
53
+ return null;
54
+ }
55
+ return (_jsx("div", { className: b(), "data-testid": dataTestId, children: items.map((toast) => (_jsx(UiToastItem, { toast: toast, onClose: ctx.remove }, toast.id))) }));
56
+ }
@@ -0,0 +1,125 @@
1
+ import { type MessageDescriptor, type PrimitiveType } from "react-intl";
2
+ import { type IAccessibilityConfigBase } from "../../typings/accessibility.js";
3
+ /**
4
+ * Interpolation values accepted by `react-intl`'s `formatMessage`, **narrowed
5
+ * to plain primitives** for toast use. Toast text is plain text by contract,
6
+ * so React-element interpolation values (`<b>name</b>`) are intentionally
7
+ * disallowed — `formatMessage` would otherwise return `ReactNode[]` which our
8
+ * downstream `text: string` would have to stringify, producing
9
+ * `"[object Object]"` for any element. Reject at compile time instead.
10
+ *
11
+ * @internal
12
+ */
13
+ export type UiToastIntlValues = Record<string, PrimitiveType>;
14
+ /**
15
+ * Severity / visual kind of a toast.
16
+ *
17
+ * @internal
18
+ */
19
+ export type UiToastKind = "success" | "info" | "warning" | "error";
20
+ /**
21
+ * Toast text content. Either a plain string or an `intl` message descriptor
22
+ * with optional interpolation values.
23
+ *
24
+ * @internal
25
+ */
26
+ export type UiToastMessage = string | {
27
+ descriptor: MessageDescriptor;
28
+ values?: UiToastIntlValues;
29
+ };
30
+ /**
31
+ * Optional per-toast accessibility overrides. The container is a polite live
32
+ * region by default; `error` and `warning` toasts upgrade to assertive
33
+ * `role="alert"` unless overridden here.
34
+ *
35
+ * @internal
36
+ */
37
+ export interface IUiToastAccessibilityConfig extends Pick<IAccessibilityConfigBase, "ariaLabel" | "ariaLabelledBy" | "ariaDescribedBy" | "role"> {
38
+ ariaLive?: "off" | "polite" | "assertive";
39
+ /**
40
+ * Accessible name for the close button. Defaults to the localized
41
+ * "Close" — pass a context-specific string (e.g. "Dismiss the
42
+ * 'access updated' notification") when a generic label isn't
43
+ * descriptive enough for screen-reader users.
44
+ */
45
+ closeButtonLabel?: string;
46
+ }
47
+ /**
48
+ * Optional inline action rendered next to the toast text (e.g. "Undo").
49
+ *
50
+ * @internal
51
+ */
52
+ export interface IUiToastAction {
53
+ /** Visible label on the action button. */
54
+ label: string;
55
+ /** Fired when the action is activated. */
56
+ onClick: () => void;
57
+ }
58
+ /**
59
+ * Options accepted by `useUiToast`'s `add*` methods (and the generic `add`).
60
+ *
61
+ * @internal
62
+ */
63
+ export interface IUiToastOptions {
64
+ /**
65
+ * Caller-supplied id. When omitted a stable id is generated. Use to
66
+ * dedupe or to remove a specific toast programmatically.
67
+ */
68
+ id?: string;
69
+ /**
70
+ * Skip auto-dismiss — the toast stays until the user closes it or
71
+ * `remove(id)` is called. Defaults to `false`.
72
+ */
73
+ sticky?: boolean;
74
+ /**
75
+ * Auto-dismiss delay in milliseconds. Ignored when `sticky` is true.
76
+ * Defaults to 4000 ms.
77
+ */
78
+ durationMs?: number;
79
+ /** Optional inline action rendered next to the message. */
80
+ action?: IUiToastAction;
81
+ /**
82
+ * Optional intl interpolation values used when `message` is a string —
83
+ * exposed primarily so the kind-specific `add*` helpers can forward
84
+ * intl values supplied alongside a `MessageDescriptor`.
85
+ */
86
+ values?: UiToastIntlValues;
87
+ /** Fires once when the toast is dismissed (auto or user). */
88
+ onDismiss?: () => void;
89
+ /** Per-toast accessibility overrides. */
90
+ accessibilityConfig?: IUiToastAccessibilityConfig;
91
+ }
92
+ /**
93
+ * A toast as the container renders it. Internal — not part of the public API.
94
+ *
95
+ * @internal
96
+ */
97
+ export interface IUiToast {
98
+ id: string;
99
+ kind: UiToastKind;
100
+ /** Resolved display text (already passed through `formatMessage` if needed). */
101
+ text: string;
102
+ sticky: boolean;
103
+ durationMs: number;
104
+ action?: IUiToastAction;
105
+ accessibilityConfig?: IUiToastAccessibilityConfig;
106
+ onDismiss?: () => void;
107
+ }
108
+ /**
109
+ * Public hook surface. Each `add*` returns the toast id, which callers can
110
+ * pass to `remove` to dismiss it programmatically.
111
+ *
112
+ * @internal
113
+ */
114
+ export interface IUseUiToastResult {
115
+ addSuccess: (message: UiToastMessage, options?: IUiToastOptions) => string;
116
+ addInfo: (message: UiToastMessage, options?: IUiToastOptions) => string;
117
+ addWarning: (message: UiToastMessage, options?: IUiToastOptions) => string;
118
+ addError: (message: UiToastMessage, options?: IUiToastOptions) => string;
119
+ /** Generic add — provide your own `kind`. */
120
+ add: (kind: UiToastKind, message: UiToastMessage, options?: IUiToastOptions) => string;
121
+ /** Dismiss a single toast by id. No-op if no toast with that id is showing. */
122
+ remove: (id: string) => void;
123
+ /** Dismiss all currently showing toasts. */
124
+ removeAll: () => void;
125
+ }
@@ -0,0 +1,2 @@
1
+ // (C) 2026 GoodData Corporation
2
+ export {};
@@ -12,6 +12,7 @@ export declare class FlexDimensions extends Component<IFlexDimensionsProps, IFle
12
12
  };
13
13
  private wrapperRef;
14
14
  private readonly throttledUpdateSize;
15
+ private readonly resizeObserver;
15
16
  constructor(props: IFlexDimensionsProps);
16
17
  componentDidMount(): void;
17
18
  componentWillUnmount(): void;
@@ -16,6 +16,7 @@ export class FlexDimensions extends Component {
16
16
  };
17
17
  wrapperRef = createRef();
18
18
  throttledUpdateSize;
19
+ resizeObserver;
19
20
  constructor(props) {
20
21
  super(props);
21
22
  this.state = {
@@ -23,14 +24,17 @@ export class FlexDimensions extends Component {
23
24
  height: 0,
24
25
  };
25
26
  this.throttledUpdateSize = throttle(this.updateSize, 250, { leading: false });
27
+ this.resizeObserver = new ResizeObserver(this.throttledUpdateSize);
26
28
  }
27
29
  componentDidMount() {
28
- window.addEventListener("resize", this.throttledUpdateSize);
30
+ if (this.wrapperRef.current) {
31
+ this.resizeObserver.observe(this.wrapperRef.current);
32
+ }
29
33
  this.throttledUpdateSize();
30
34
  }
31
35
  componentWillUnmount() {
32
36
  this.throttledUpdateSize.cancel();
33
- window.removeEventListener("resize", this.throttledUpdateSize);
37
+ this.resizeObserver.disconnect();
34
38
  }
35
39
  getChildrenDimensions() {
36
40
  return pickBy(this.state, (_, key) => {
@@ -65,7 +65,7 @@ function createInsightsItemsGroup(featureFlags, workspaceId, workspacePermission
65
65
  const insightItemsGroup = [];
66
66
  const kpisUrl = kpisItemUrl(baseUrl, workspaceId);
67
67
  pushConditionally(insightItemsGroup, createIHeaderMenuItem(HEADER_ITEM_ID_KPIS_NEW, "s-menu-kpis", kpisUrl), canShowKpisItem(workspacePermissions, hasAnalyticalDashboards));
68
- const analyzeUrl = analyzeItemUrl(baseUrl, workspaceId);
68
+ const analyzeUrl = analyzeItemUrl(baseUrl, workspaceId, featureFlags);
69
69
  pushConditionally(insightItemsGroup, createIHeaderMenuItem(HEADER_ITEM_ID_ANALYZE, "s-menu-analyze", analyzeUrl), canShowAnalyzeItem(workspacePermissions));
70
70
  const measuresUrl = measuresItemUrl(baseUrl, workspaceId, featureFlags);
71
71
  pushConditionally(insightItemsGroup, createIHeaderMenuItem(HEADER_ITEM_ID_METRICS, "s-menu-metrics", measuresUrl), canShowMetricsItem(hasMeasures, workspacePermissions));
@@ -124,7 +124,10 @@ function kpisItemUrl(baseUrl, workspaceId) {
124
124
  function canShowKpisItem(workspacePermissions, hasAnalyticalDashboards) {
125
125
  return Boolean(hasAnalyticalDashboards || workspacePermissions.canCreateAnalyticalDashboard === true);
126
126
  }
127
- function analyzeItemUrl(baseUrl, workspaceId) {
127
+ function analyzeItemUrl(baseUrl, workspaceId, featureFlags) {
128
+ if (featureFlags.enableShellApplication_analyticalDesigner) {
129
+ return withBaseUrl(baseUrl, `/workspace/${workspaceId}/analyze/#/reportId/edit`);
130
+ }
128
131
  return withBaseUrl(baseUrl, `/analyze/#/${workspaceId}/reportId/edit`);
129
132
  }
130
133
  function canShowAnalyzeItem(workspacePermissions) {
@@ -92,13 +92,15 @@ export class ShortenedText extends PureComponent {
92
92
  if (elementWidth > 0 && elementWidth < element.scrollWidth) {
93
93
  this.setState({ title: getShortenedTitle(title, element, ellipsisPosition), customTitle: true });
94
94
  }
95
+ else {
96
+ this.setState({
97
+ title: this.props.children,
98
+ customTitle: false,
99
+ });
100
+ }
95
101
  }
96
102
  recomputeShortening() {
97
- // causes repaint & checkTitle to be called
98
- this.setState({
99
- title: this.props.children,
100
- customTitle: false,
101
- });
103
+ this.checkTitle();
102
104
  }
103
105
  renderTextWithBubble() {
104
106
  return (_jsxs(BubbleHoverTrigger, { showDelay: 0, hideDelay: 0, eventsOnBubble: this.props.tooltipVisibleOnMouseOver, children: [
package/esm/index.d.ts CHANGED
@@ -468,3 +468,6 @@ export { UiLabelsList, type IUiLabelsListProps, type IUiLabelsListItem, } from "
468
468
  export { UiLabelsPicker, isLabelsPickerItemChecked, type IUiLabelsPickerProps, type IUiLabelsPickerItem, } from "./@ui/UiLabelsPicker/UiLabelsPicker.js";
469
469
  export { UiPermissionMenu, type IUiPermissionMenuProps, type PermissionMenuLevel, } from "./@ui/UiPermissionMenu/UiPermissionMenu.js";
470
470
  export { UiGranteeRowControls, type IUiGranteeRowControlsProps, } from "./@ui/UiGranteeRowControls/UiGranteeRowControls.js";
471
+ export { UiToastProvider, useUiToast } from "./@ui/UiToast/UiToastProvider.js";
472
+ export { UiToastItem, UiToastsContainer, type IUiToastItemProps, type IUiToastsContainerProps, } from "./@ui/UiToast/UiToastsContainer.js";
473
+ export { type IUiToast, type IUiToastAccessibilityConfig, type IUiToastAction, type IUiToastOptions, type IUseUiToastResult, type UiToastIntlValues, type UiToastKind, type UiToastMessage, } from "./@ui/UiToast/types.js";
package/esm/index.js CHANGED
@@ -423,3 +423,5 @@ export { UiLabelsList, } from "./@ui/UiLabelsList/UiLabelsList.js";
423
423
  export { UiLabelsPicker, isLabelsPickerItemChecked, } from "./@ui/UiLabelsPicker/UiLabelsPicker.js";
424
424
  export { UiPermissionMenu, } from "./@ui/UiPermissionMenu/UiPermissionMenu.js";
425
425
  export { UiGranteeRowControls, } from "./@ui/UiGranteeRowControls/UiGranteeRowControls.js";
426
+ export { UiToastProvider, useUiToast } from "./@ui/UiToast/UiToastProvider.js";
427
+ export { UiToastItem, UiToastsContainer, } from "./@ui/UiToast/UiToastsContainer.js";