@gooddata/sdk-ui-kit 11.40.0-alpha.2 → 11.40.0-alpha.4

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.
@@ -83,6 +83,7 @@ import { OffsetOptions } from '@floating-ui/react';
83
83
  import { OnError } from '@gooddata/sdk-ui';
84
84
  import { OnLoadingChanged } from '@gooddata/sdk-ui';
85
85
  import { Placement } from '@floating-ui/react';
86
+ import { PrimitiveType } from 'react-intl';
86
87
  import { PropsWithChildren } from 'react';
87
88
  import { PropsWithoutRef } from 'react';
88
89
  import { Provider } from 'react';
@@ -1054,6 +1055,7 @@ export declare class FlexDimensions extends Component<IFlexDimensionsProps, IFle
1054
1055
  };
1055
1056
  private wrapperRef;
1056
1057
  private readonly throttledUpdateSize;
1058
+ private readonly resizeObserver;
1057
1059
  constructor(props: IFlexDimensionsProps);
1058
1060
  componentDidMount(): void;
1059
1061
  componentWillUnmount(): void;
@@ -8416,6 +8418,105 @@ export declare interface IUiTextInputProps {
8416
8418
  dataTestId?: string;
8417
8419
  }
8418
8420
 
8421
+ /**
8422
+ * A toast as the container renders it. Internal — not part of the public API.
8423
+ *
8424
+ * @internal
8425
+ */
8426
+ export declare interface IUiToast {
8427
+ id: string;
8428
+ kind: UiToastKind;
8429
+ /** Resolved display text (already passed through `formatMessage` if needed). */
8430
+ text: string;
8431
+ sticky: boolean;
8432
+ durationMs: number;
8433
+ action?: IUiToastAction;
8434
+ accessibilityConfig?: IUiToastAccessibilityConfig;
8435
+ onDismiss?: () => void;
8436
+ }
8437
+
8438
+ /**
8439
+ * Optional per-toast accessibility overrides. The container is a polite live
8440
+ * region by default; `error` and `warning` toasts upgrade to assertive
8441
+ * `role="alert"` unless overridden here.
8442
+ *
8443
+ * @internal
8444
+ */
8445
+ export declare interface IUiToastAccessibilityConfig extends Pick<IAccessibilityConfigBase, "ariaLabel" | "ariaLabelledBy" | "ariaDescribedBy" | "role"> {
8446
+ ariaLive?: "off" | "polite" | "assertive";
8447
+ /**
8448
+ * Accessible name for the close button. Defaults to the localized
8449
+ * "Close" — pass a context-specific string (e.g. "Dismiss the
8450
+ * 'access updated' notification") when a generic label isn't
8451
+ * descriptive enough for screen-reader users.
8452
+ */
8453
+ closeButtonLabel?: string;
8454
+ }
8455
+
8456
+ /**
8457
+ * Optional inline action rendered next to the toast text (e.g. "Undo").
8458
+ *
8459
+ * @internal
8460
+ */
8461
+ export declare interface IUiToastAction {
8462
+ /** Visible label on the action button. */
8463
+ label: string;
8464
+ /** Fired when the action is activated. */
8465
+ onClick: () => void;
8466
+ }
8467
+
8468
+ /**
8469
+ * @internal
8470
+ */
8471
+ export declare interface IUiToastItemProps {
8472
+ toast: IUiToast;
8473
+ /** Fired when the user dismisses (close X or action click). */
8474
+ onClose: (id: string) => void;
8475
+ }
8476
+
8477
+ /**
8478
+ * Options accepted by `useUiToast`'s `add*` methods (and the generic `add`).
8479
+ *
8480
+ * @internal
8481
+ */
8482
+ export declare interface IUiToastOptions {
8483
+ /**
8484
+ * Caller-supplied id. When omitted a stable id is generated. Use to
8485
+ * dedupe or to remove a specific toast programmatically.
8486
+ */
8487
+ id?: string;
8488
+ /**
8489
+ * Skip auto-dismiss — the toast stays until the user closes it or
8490
+ * `remove(id)` is called. Defaults to `false`.
8491
+ */
8492
+ sticky?: boolean;
8493
+ /**
8494
+ * Auto-dismiss delay in milliseconds. Ignored when `sticky` is true.
8495
+ * Defaults to 4000 ms.
8496
+ */
8497
+ durationMs?: number;
8498
+ /** Optional inline action rendered next to the message. */
8499
+ action?: IUiToastAction;
8500
+ /**
8501
+ * Optional intl interpolation values used when `message` is a string —
8502
+ * exposed primarily so the kind-specific `add*` helpers can forward
8503
+ * intl values supplied alongside a `MessageDescriptor`.
8504
+ */
8505
+ values?: UiToastIntlValues;
8506
+ /** Fires once when the toast is dismissed (auto or user). */
8507
+ onDismiss?: () => void;
8508
+ /** Per-toast accessibility overrides. */
8509
+ accessibilityConfig?: IUiToastAccessibilityConfig;
8510
+ }
8511
+
8512
+ /**
8513
+ * @internal
8514
+ */
8515
+ export declare interface IUiToastsContainerProps {
8516
+ /** Test id forwarded to the root element. */
8517
+ dataTestId?: string;
8518
+ }
8519
+
8419
8520
  /**
8420
8521
  * @internal
8421
8522
  */
@@ -8699,6 +8800,25 @@ export declare interface IUseToastMessageType {
8699
8800
  removeAllMessages: () => void;
8700
8801
  }
8701
8802
 
8803
+ /**
8804
+ * Public hook surface. Each `add*` returns the toast id, which callers can
8805
+ * pass to `remove` to dismiss it programmatically.
8806
+ *
8807
+ * @internal
8808
+ */
8809
+ export declare interface IUseUiToastResult {
8810
+ addSuccess: (message: UiToastMessage, options?: IUiToastOptions) => string;
8811
+ addInfo: (message: UiToastMessage, options?: IUiToastOptions) => string;
8812
+ addWarning: (message: UiToastMessage, options?: IUiToastOptions) => string;
8813
+ addError: (message: UiToastMessage, options?: IUiToastOptions) => string;
8814
+ /** Generic add — provide your own `kind`. */
8815
+ add: (kind: UiToastKind, message: UiToastMessage, options?: IUiToastOptions) => string;
8816
+ /** Dismiss a single toast by id. No-op if no toast with that id is showing. */
8817
+ remove: (id: string) => void;
8818
+ /** Dismiss all currently showing toasts. */
8819
+ removeAll: () => void;
8820
+ }
8821
+
8702
8822
  /**
8703
8823
  * @internal
8704
8824
  */
@@ -10480,6 +10600,70 @@ export declare function UiTags({ tags, tagOptions, addLabel, nameLabel, cancelLa
10480
10600
  */
10481
10601
  export declare function UiTextInput({ type, value, onChange, label, placeholder, iconBefore, iconAfter, onIconAfter, accessibilityConfig, disabled, autoFocus, dataTestId }: IUiTextInputProps): JSX.Element;
10482
10602
 
10603
+ /**
10604
+ * Interpolation values accepted by `react-intl`'s `formatMessage`, **narrowed
10605
+ * to plain primitives** for toast use. Toast text is plain text by contract,
10606
+ * so React-element interpolation values (`<b>name</b>`) are intentionally
10607
+ * disallowed — `formatMessage` would otherwise return `ReactNode[]` which our
10608
+ * downstream `text: string` would have to stringify, producing
10609
+ * `"[object Object]"` for any element. Reject at compile time instead.
10610
+ *
10611
+ * @internal
10612
+ */
10613
+ export declare type UiToastIntlValues = Record<string, PrimitiveType>;
10614
+
10615
+ /**
10616
+ * Presentational single-toast component. Most consumers use
10617
+ * `UiToastsContainer` (which reads queued toasts from the provider), but
10618
+ * this can be rendered directly for static demos or one-off composition.
10619
+ *
10620
+ * @internal
10621
+ */
10622
+ export declare function UiToastItem({ toast, onClose }: IUiToastItemProps): ReactNode;
10623
+
10624
+ /**
10625
+ * Severity / visual kind of a toast.
10626
+ *
10627
+ * @internal
10628
+ */
10629
+ export declare type UiToastKind = "success" | "info" | "warning" | "error";
10630
+
10631
+ /**
10632
+ * Toast text content. Either a plain string or an `intl` message descriptor
10633
+ * with optional interpolation values.
10634
+ *
10635
+ * @internal
10636
+ */
10637
+ export declare type UiToastMessage = string | {
10638
+ descriptor: MessageDescriptor;
10639
+ values?: UiToastIntlValues;
10640
+ };
10641
+
10642
+ /**
10643
+ * Mount once near the root of your app. Provides the toast queue + dismiss
10644
+ * timers consumed by `useUiToast` and `UiToastsContainer`. Nesting is safe
10645
+ * — only the outermost `<UiToastsContainer>` renders any visible toasts.
10646
+ *
10647
+ * Known limitation: if a root provider with in-flight toasts is **re-parented**
10648
+ * under a new outer provider mid-flight (e.g. the app rearranges its tree),
10649
+ * the inner instance's queue and timers don't migrate to the parent. Mount
10650
+ * the provider once at the stable app root to avoid this.
10651
+ *
10652
+ * @internal
10653
+ */
10654
+ export declare function UiToastProvider({ children }: {
10655
+ children: ReactNode;
10656
+ }): JSX.Element;
10657
+
10658
+ /**
10659
+ * Renders the list of toasts queued by `useUiToast`. Mount once near the app
10660
+ * root, inside a `UiToastProvider`. Nested containers render nothing — only
10661
+ * the outermost one is visible, preserving the topmost-only behaviour.
10662
+ *
10663
+ * @internal
10664
+ */
10665
+ export declare function UiToastsContainer({ dataTestId }: IUiToastsContainerProps): ReactNode;
10666
+
10483
10667
  /**
10484
10668
  * @internal
10485
10669
  */
@@ -10951,6 +11135,16 @@ export declare const useUiTabOutHandlerConnectors: <T extends HTMLElement = HTML
10951
11135
  */
10952
11136
  export declare function useUiTabsContextStoreValue<TTabProps extends Record<any, any> = EmptyObject, TTabActionProps extends Record<any, any> = EmptyObject>({ tabs, selectedTabId, onTabSelect, onTabDoubleClick, size, maxLabelLength, accessibilityConfig: accessibilityConfigProp, disableBottomBorder, Container, Tab, TabValue, TabActions, TabActionsButton, AllTabs, AllTabsButton }: IUiTabsProps<TTabProps, TTabActionProps>): IUiTabContext<TTabProps, TTabActionProps>;
10953
11137
 
11138
+ /**
11139
+ * Consumer hook. Resolves the toast message via the **caller's**
11140
+ * `useIntl()` so a consumer rendered under a nested `IntlProvider` formats
11141
+ * `MessageDescriptor` content with that subtree's locale, not the
11142
+ * provider's. Throws when called outside a `UiToastProvider`.
11143
+ *
11144
+ * @internal
11145
+ */
11146
+ export declare function useUiToast(): IUseUiToastResult;
11147
+
10954
11148
  /**
10955
11149
  * @internal
10956
11150
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gooddata/sdk-ui-kit",
3
- "version": "11.40.0-alpha.2",
3
+ "version": "11.40.0-alpha.4",
4
4
  "description": "GoodData SDK - UI Building Components",
5
5
  "license": "MIT",
6
6
  "author": "GoodData Corporation",
@@ -75,11 +75,11 @@
75
75
  "tslib": "2.8.1",
76
76
  "unified": "^11.0.5",
77
77
  "uuid": "11.1.0",
78
- "@gooddata/sdk-backend-spi": "11.40.0-alpha.2",
79
- "@gooddata/sdk-ui": "11.40.0-alpha.2",
80
- "@gooddata/sdk-model": "11.40.0-alpha.2",
81
- "@gooddata/util": "11.40.0-alpha.2",
82
- "@gooddata/sdk-ui-theme-provider": "11.40.0-alpha.2"
78
+ "@gooddata/sdk-backend-spi": "11.40.0-alpha.4",
79
+ "@gooddata/sdk-model": "11.40.0-alpha.4",
80
+ "@gooddata/sdk-ui-theme-provider": "11.40.0-alpha.4",
81
+ "@gooddata/util": "11.40.0-alpha.4",
82
+ "@gooddata/sdk-ui": "11.40.0-alpha.4"
83
83
  },
84
84
  "devDependencies": {
85
85
  "@microsoft/api-documenter": "^7.17.0",
@@ -116,9 +116,9 @@
116
116
  "happy-dom": "18.0.1",
117
117
  "kefir": "^3.8.8",
118
118
  "npm-run-all": "^4.1.5",
119
- "oxfmt": "0.45.0",
120
- "oxlint": "^1.43.0",
121
- "oxlint-tsgolint": "0.11.4",
119
+ "oxfmt": "0.52.0",
120
+ "oxlint": "1.51.0",
121
+ "oxlint-tsgolint": "0.15.0",
122
122
  "raf": "3.4.1",
123
123
  "react": "19.1.1",
124
124
  "react-dom": "19.1.1",
@@ -126,13 +126,13 @@
126
126
  "stylelint": "^16.26.1",
127
127
  "svgo": "^2.8.0",
128
128
  "typescript": "5.9.3",
129
- "vitest": "4.1.0",
129
+ "vitest": "4.1.8",
130
130
  "vitest-dom": "0.1.1",
131
- "@gooddata/oxlint-config": "11.40.0-alpha.2",
132
- "@gooddata/eslint-config": "11.40.0-alpha.2",
133
- "@gooddata/reference-workspace": "11.40.0-alpha.2",
134
- "@gooddata/sdk-backend-mockingbird": "11.40.0-alpha.2",
135
- "@gooddata/stylelint-config": "11.40.0-alpha.2"
131
+ "@gooddata/eslint-config": "11.40.0-alpha.4",
132
+ "@gooddata/reference-workspace": "11.40.0-alpha.4",
133
+ "@gooddata/sdk-backend-mockingbird": "11.40.0-alpha.4",
134
+ "@gooddata/oxlint-config": "11.40.0-alpha.4",
135
+ "@gooddata/stylelint-config": "11.40.0-alpha.4"
136
136
  },
137
137
  "peerDependencies": {
138
138
  "react": "^18.0.0 || ^19.0.0",
@@ -0,0 +1,114 @@
1
+ // (C) 2026 GoodData Corporation
2
+
3
+ // `UiToast` reuses the existing `--gd-toastMessage-{variant}-*` theme variables
4
+ // (registered in sdk-ui-theme-provider, defaulted in defaultTheme.scss) so it
5
+ // matches the look of the legacy `<Message>` overlay and any theme overrides
6
+ // without introducing new theme tokens. Each kind maps to one of the four
7
+ // theme variants — note that `info` maps to the legacy `information` set.
8
+
9
+ @mixin kind-vars($variant) {
10
+ --local-text-color: var(--gd-toastMessage-#{$variant}-textColor);
11
+ --local-background-color: var(--gd-toastMessage-#{$variant}-backgroundColor);
12
+ --local-border-color: var(--gd-toastMessage-#{$variant}-borderColor);
13
+ --local-border-width: var(--gd-toastMessage-#{$variant}-borderWidth);
14
+ --local-border-radius: var(--gd-toastMessage-#{$variant}-borderRadius);
15
+ --local-close-color: var(--gd-toastMessage-#{$variant}-closeButtonColor);
16
+ --local-link-color: var(--gd-toastMessage-#{$variant}-linkButtonColor);
17
+ }
18
+
19
+ .gd-ui-kit-toast {
20
+ position: fixed;
21
+ left: 50%;
22
+ top: var(--gd-spacing-20px);
23
+ transform: translateX(-50%);
24
+ display: flex;
25
+ flex-direction: column;
26
+ align-items: center;
27
+ gap: var(--gd-spacing-10px);
28
+ z-index: 9000;
29
+ pointer-events: none;
30
+ max-width: 620px;
31
+ width: 90%;
32
+
33
+ &__item {
34
+ pointer-events: auto;
35
+ display: inline-flex;
36
+ align-items: center;
37
+ gap: var(--gd-spacing-10px);
38
+ padding: var(--gd-spacing-5px) var(--gd-spacing-10px);
39
+ max-width: 100%;
40
+ font-size: 14px;
41
+ line-height: 20px;
42
+ text-align: left;
43
+ color: var(--local-text-color);
44
+ background-color: var(--local-background-color);
45
+ border-style: solid;
46
+ border-color: var(--local-border-color);
47
+ border-width: var(--local-border-width);
48
+ border-radius: var(--local-border-radius);
49
+ box-shadow: 0 4px 4px 0 var(--gd-shadow-color);
50
+
51
+ &--kind-success {
52
+ @include kind-vars(success);
53
+ }
54
+
55
+ &--kind-info {
56
+ @include kind-vars(information);
57
+ }
58
+
59
+ &--kind-warning {
60
+ @include kind-vars(warning);
61
+ }
62
+
63
+ &--kind-error {
64
+ @include kind-vars(error);
65
+ }
66
+ }
67
+
68
+ &__body {
69
+ flex: 1 1 auto;
70
+ min-width: 0;
71
+ }
72
+
73
+ &__action {
74
+ flex-shrink: 0;
75
+ border: none;
76
+ background: transparent;
77
+ padding: 0;
78
+ font: inherit;
79
+ color: var(--local-link-color);
80
+ cursor: pointer;
81
+ text-decoration: underline;
82
+ opacity: 0.85;
83
+
84
+ &:hover {
85
+ opacity: 1;
86
+ }
87
+
88
+ &:focus-visible {
89
+ outline: 2px solid var(--gd-palette-primary-focus);
90
+ outline-offset: 2px;
91
+ }
92
+ }
93
+
94
+ &__close {
95
+ flex-shrink: 0;
96
+ display: inline-flex;
97
+ align-items: center;
98
+ padding: 0;
99
+ border: none;
100
+ background: transparent;
101
+ cursor: pointer;
102
+ color: var(--local-close-color);
103
+ opacity: 0.85;
104
+
105
+ &:hover {
106
+ opacity: 1;
107
+ }
108
+
109
+ &:focus-visible {
110
+ outline: 2px solid var(--gd-palette-primary-focus);
111
+ outline-offset: 2px;
112
+ }
113
+ }
114
+ }
@@ -46,6 +46,7 @@
46
46
  @use "./UiLabelsPicker/UiLabelsPicker.scss";
47
47
  @use "./UiPermissionMenu/UiPermissionMenu.scss";
48
48
  @use "./UiGranteeRowControls/UiGranteeRowControls.scss";
49
+ @use "./UiToast/UiToast.scss";
49
50
 
50
51
  // `--gd-font-family` is a `:root` variable only; there is no global `body` font
51
52
  // declaration. Apply it once to every kit root so standalone components don't
@@ -3824,6 +3824,115 @@
3824
3824
  flex-shrink: 0;
3825
3825
  }
3826
3826
 
3827
+ .gd-ui-kit-toast {
3828
+ position: fixed;
3829
+ left: 50%;
3830
+ top: var(--gd-spacing-20px);
3831
+ transform: translateX(-50%);
3832
+ display: flex;
3833
+ flex-direction: column;
3834
+ align-items: center;
3835
+ gap: var(--gd-spacing-10px);
3836
+ z-index: 9000;
3837
+ pointer-events: none;
3838
+ max-width: 620px;
3839
+ width: 90%;
3840
+ }
3841
+ .gd-ui-kit-toast__item {
3842
+ pointer-events: auto;
3843
+ display: inline-flex;
3844
+ align-items: center;
3845
+ gap: var(--gd-spacing-10px);
3846
+ padding: var(--gd-spacing-5px) var(--gd-spacing-10px);
3847
+ max-width: 100%;
3848
+ font-size: 14px;
3849
+ line-height: 20px;
3850
+ text-align: left;
3851
+ color: var(--local-text-color);
3852
+ background-color: var(--local-background-color);
3853
+ border-style: solid;
3854
+ border-color: var(--local-border-color);
3855
+ border-width: var(--local-border-width);
3856
+ border-radius: var(--local-border-radius);
3857
+ box-shadow: 0 4px 4px 0 var(--gd-shadow-color);
3858
+ }
3859
+ .gd-ui-kit-toast__item--kind-success {
3860
+ --local-text-color: var(--gd-toastMessage-success-textColor);
3861
+ --local-background-color: var(--gd-toastMessage-success-backgroundColor);
3862
+ --local-border-color: var(--gd-toastMessage-success-borderColor);
3863
+ --local-border-width: var(--gd-toastMessage-success-borderWidth);
3864
+ --local-border-radius: var(--gd-toastMessage-success-borderRadius);
3865
+ --local-close-color: var(--gd-toastMessage-success-closeButtonColor);
3866
+ --local-link-color: var(--gd-toastMessage-success-linkButtonColor);
3867
+ }
3868
+ .gd-ui-kit-toast__item--kind-info {
3869
+ --local-text-color: var(--gd-toastMessage-information-textColor);
3870
+ --local-background-color: var(--gd-toastMessage-information-backgroundColor);
3871
+ --local-border-color: var(--gd-toastMessage-information-borderColor);
3872
+ --local-border-width: var(--gd-toastMessage-information-borderWidth);
3873
+ --local-border-radius: var(--gd-toastMessage-information-borderRadius);
3874
+ --local-close-color: var(--gd-toastMessage-information-closeButtonColor);
3875
+ --local-link-color: var(--gd-toastMessage-information-linkButtonColor);
3876
+ }
3877
+ .gd-ui-kit-toast__item--kind-warning {
3878
+ --local-text-color: var(--gd-toastMessage-warning-textColor);
3879
+ --local-background-color: var(--gd-toastMessage-warning-backgroundColor);
3880
+ --local-border-color: var(--gd-toastMessage-warning-borderColor);
3881
+ --local-border-width: var(--gd-toastMessage-warning-borderWidth);
3882
+ --local-border-radius: var(--gd-toastMessage-warning-borderRadius);
3883
+ --local-close-color: var(--gd-toastMessage-warning-closeButtonColor);
3884
+ --local-link-color: var(--gd-toastMessage-warning-linkButtonColor);
3885
+ }
3886
+ .gd-ui-kit-toast__item--kind-error {
3887
+ --local-text-color: var(--gd-toastMessage-error-textColor);
3888
+ --local-background-color: var(--gd-toastMessage-error-backgroundColor);
3889
+ --local-border-color: var(--gd-toastMessage-error-borderColor);
3890
+ --local-border-width: var(--gd-toastMessage-error-borderWidth);
3891
+ --local-border-radius: var(--gd-toastMessage-error-borderRadius);
3892
+ --local-close-color: var(--gd-toastMessage-error-closeButtonColor);
3893
+ --local-link-color: var(--gd-toastMessage-error-linkButtonColor);
3894
+ }
3895
+ .gd-ui-kit-toast__body {
3896
+ flex: 1 1 auto;
3897
+ min-width: 0;
3898
+ }
3899
+ .gd-ui-kit-toast__action {
3900
+ flex-shrink: 0;
3901
+ border: none;
3902
+ background: transparent;
3903
+ padding: 0;
3904
+ font: inherit;
3905
+ color: var(--local-link-color);
3906
+ cursor: pointer;
3907
+ text-decoration: underline;
3908
+ opacity: 0.85;
3909
+ }
3910
+ .gd-ui-kit-toast__action:hover {
3911
+ opacity: 1;
3912
+ }
3913
+ .gd-ui-kit-toast__action:focus-visible {
3914
+ outline: 2px solid var(--gd-palette-primary-focus);
3915
+ outline-offset: 2px;
3916
+ }
3917
+ .gd-ui-kit-toast__close {
3918
+ flex-shrink: 0;
3919
+ display: inline-flex;
3920
+ align-items: center;
3921
+ padding: 0;
3922
+ border: none;
3923
+ background: transparent;
3924
+ cursor: pointer;
3925
+ color: var(--local-close-color);
3926
+ opacity: 0.85;
3927
+ }
3928
+ .gd-ui-kit-toast__close:hover {
3929
+ opacity: 1;
3930
+ }
3931
+ .gd-ui-kit-toast__close:focus-visible {
3932
+ outline: 2px solid var(--gd-palette-primary-focus);
3933
+ outline-offset: 2px;
3934
+ }
3935
+
3827
3936
  [class^=gd-ui-kit-],
3828
3937
  [class*=" gd-ui-kit-"] {
3829
3938
  font-family: var(--gd-font-family);