@gooddata/sdk-ui-kit 11.39.0-alpha.3 → 11.39.0

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.
Files changed (46) hide show
  1. package/esm/@ui/@types/icon.d.ts +1 -1
  2. package/esm/@ui/UiAddGranteeDialog/UiAddGranteeDialog.d.ts +39 -0
  3. package/esm/@ui/UiAddGranteeDialog/UiAddGranteeDialog.js +30 -0
  4. package/esm/@ui/UiAvatar/UiAvatar.d.ts +40 -0
  5. package/esm/@ui/UiAvatar/UiAvatar.js +19 -0
  6. package/esm/@ui/UiButton/UiButton.d.ts +1 -1
  7. package/esm/@ui/UiDialogShell/UiDialogFooter.d.ts +1 -1
  8. package/esm/@ui/UiDialogShell/UiDialogHeader.d.ts +1 -1
  9. package/esm/@ui/UiDialogShell/UiDialogShell.d.ts +10 -10
  10. package/esm/@ui/UiDialogShell/UiDialogShell.js +2 -2
  11. package/esm/@ui/UiGeneralAccessRadio/UiGeneralAccessRadio.d.ts +32 -0
  12. package/esm/@ui/UiGeneralAccessRadio/UiGeneralAccessRadio.js +22 -0
  13. package/esm/@ui/UiGranteeAvatar/UiGranteeAvatar.d.ts +30 -0
  14. package/esm/@ui/UiGranteeAvatar/UiGranteeAvatar.js +25 -0
  15. package/esm/@ui/UiGranteeRow/UiGranteeRow.d.ts +26 -0
  16. package/esm/@ui/UiGranteeRow/UiGranteeRow.js +19 -0
  17. package/esm/@ui/UiIcon/icons.js +1 -0
  18. package/esm/@ui/UiMenu/hooks.js +2 -4
  19. package/esm/@ui/UiObjectShareDialog/UiObjectShareDialog.d.ts +57 -0
  20. package/esm/@ui/UiObjectShareDialog/UiObjectShareDialog.js +28 -0
  21. package/esm/@ui/UiRadio/UiRadio.d.ts +40 -0
  22. package/esm/@ui/UiRadio/UiRadio.js +23 -0
  23. package/esm/@ui/UiRadioRow/UiRadioRow.d.ts +33 -0
  24. package/esm/@ui/UiRadioRow/UiRadioRow.js +19 -0
  25. package/esm/@ui/UiTextInput/UiTextInput.d.ts +55 -0
  26. package/esm/@ui/UiTextInput/UiTextInput.js +24 -0
  27. package/esm/index.d.ts +9 -0
  28. package/esm/index.js +9 -0
  29. package/esm/locales.d.ts +61 -0
  30. package/esm/locales.js +27 -0
  31. package/esm/sdk-ui-kit.d.ts +374 -14
  32. package/package.json +11 -11
  33. package/src/@ui/UiAddGranteeDialog/UiAddGranteeDialog.scss +22 -0
  34. package/src/@ui/UiAvatar/UiAvatar.scss +22 -0
  35. package/src/@ui/UiDialogShell/UiDialogShell.scss +0 -1
  36. package/src/@ui/UiGeneralAccessRadio/UiGeneralAccessRadio.scss +8 -0
  37. package/src/@ui/UiGranteeRow/UiGranteeRow.scss +36 -0
  38. package/src/@ui/UiObjectShareDialog/UiObjectShareDialog.scss +12 -0
  39. package/src/@ui/UiRadio/UiRadio.scss +63 -0
  40. package/src/@ui/UiRadioRow/UiRadioRow.scss +44 -0
  41. package/src/@ui/UiSectionHeading/UiSectionHeading.scss +0 -1
  42. package/src/@ui/UiTextInput/UiTextInput.scss +68 -0
  43. package/src/@ui/index.scss +17 -0
  44. package/src/FilterGroupItem/FilterGroupItem.scss +13 -24
  45. package/styles/css/main.css +285 -20
  46. package/styles/css/main.css.map +1 -1
@@ -1,4 +1,4 @@
1
1
  /**
2
2
  * @internal
3
3
  */
4
- export type IconType = "aiAgent" | "aiAgentDisabled" | "brain" | "brainDisabled" | "check" | "checkCircle" | "certification" | "plus" | "plusCircle" | "sync" | "alert" | "alertPaused" | "close" | "cross" | "edit" | "crossCircle" | "question" | "chevronUp" | "chevronRight" | "chevronDown" | "chevronLeft" | "date" | "navigateUp" | "navigateDown" | "navigateRight" | "navigateLeft" | "download" | "slack" | "expand" | "exclamationCircle" | "book" | "visible" | "invisible" | "lock" | "unlock" | "ai" | "aiFill" | "drawer" | "drawerEmpty" | "prohibited" | "dropDown" | "dropRight" | "clock" | "clockPaused" | "questionMark" | "upload" | "expandRectangle" | "file" | "number" | "code" | "user" | "userPlus" | "users" | "magic" | "tab" | "pauseCircle" | "filter" | "timer" | "mail" | "envelope" | "copy" | "rain" | "earth" | "geoCollection" | "geoCollectionUpload" | "minimize" | "shrink" | "copyright" | "ellipsis" | "pencil" | "folder" | "folderPlus" | "trash" | "arrowUp" | "arrowRight" | "arrowDown" | "arrowLeft" | "undo" | "redo" | "trendDown" | "trendUp" | "save" | "minus" | "minusCircle" | "percent" | "enter" | "enterRight" | "money" | "ghost" | "warning" | "home" | "settings" | "search" | "university" | "printer" | "picture" | "visualization" | "dashboard" | "metric" | "fact" | "ldmAttribute" | "ldmKey" | "ldmLabel" | "sharp" | "attribute" | "horn" | "cw" | "ccw" | "table" | "directionColumn" | "directionRow" | "header" | "genai" | "genai2" | "explainai" | "hiddenForAi" | "box" | "ellipsisVertical" | "list" | "drillTo" | "hierarchy" | "history" | "history2" | "thumbsUp" | "thumbsDown" | "send" | "visualizationArea" | "visualizationTable" | "visualizationTreemap" | "visualizationScatter" | "visualizationDonut" | "visualizationHeadline" | "visualizationColumn" | "visualizationLine" | "visualizationPyramid" | "visualizationFunnel" | "visualizationHeatmap" | "visualizationBubble" | "visualizationPie" | "visualizationBar" | "visualizationCombo" | "visualizationBullet" | "visualizationWaterfall" | "visualizationDependencywheel" | "visualizationSankey" | "visualizationPushpin" | "visualizationRepeater" | "visualizationXirr" | "link" | "externalLink" | "click" | "fileXlsx" | "filePptx" | "filePdf" | "fileImage" | "fileCsvFormatted" | "fileCsvRaw" | "aiDocument" | "recommendation" | "streamUp" | "streamDown" | "stream" | "density" | "parameter" | "pin" | "unpin";
4
+ export type IconType = "aiAgent" | "aiAgentDisabled" | "brain" | "brainDisabled" | "check" | "checkCircle" | "certification" | "plus" | "plusCircle" | "sync" | "alert" | "alertPaused" | "close" | "cross" | "edit" | "crossCircle" | "question" | "chevronUp" | "chevronRight" | "chevronDown" | "chevronLeft" | "date" | "navigateUp" | "navigateDown" | "navigateRight" | "navigateLeft" | "download" | "slack" | "expand" | "exclamationCircle" | "book" | "visible" | "invisible" | "lock" | "unlock" | "ai" | "aiFill" | "drawer" | "drawerEmpty" | "prohibited" | "dropDown" | "dropRight" | "clock" | "clockPaused" | "questionMark" | "upload" | "expandRectangle" | "file" | "number" | "code" | "user" | "userPlus" | "users" | "magic" | "tab" | "pauseCircle" | "filter" | "timer" | "mail" | "envelope" | "copy" | "rain" | "earth" | "geoCollection" | "geoCollectionUpload" | "minimize" | "shrink" | "copyright" | "ellipsis" | "pencil" | "folder" | "folderSmall" | "folderPlus" | "trash" | "arrowUp" | "arrowRight" | "arrowDown" | "arrowLeft" | "undo" | "redo" | "trendDown" | "trendUp" | "save" | "minus" | "minusCircle" | "percent" | "enter" | "enterRight" | "money" | "ghost" | "warning" | "home" | "settings" | "search" | "university" | "printer" | "picture" | "visualization" | "dashboard" | "metric" | "fact" | "ldmAttribute" | "ldmKey" | "ldmLabel" | "sharp" | "attribute" | "horn" | "cw" | "ccw" | "table" | "directionColumn" | "directionRow" | "header" | "genai" | "genai2" | "explainai" | "hiddenForAi" | "box" | "ellipsisVertical" | "list" | "drillTo" | "hierarchy" | "history" | "history2" | "thumbsUp" | "thumbsDown" | "send" | "visualizationArea" | "visualizationTable" | "visualizationTreemap" | "visualizationScatter" | "visualizationDonut" | "visualizationHeadline" | "visualizationColumn" | "visualizationLine" | "visualizationPyramid" | "visualizationFunnel" | "visualizationHeatmap" | "visualizationBubble" | "visualizationPie" | "visualizationBar" | "visualizationCombo" | "visualizationBullet" | "visualizationWaterfall" | "visualizationDependencywheel" | "visualizationSankey" | "visualizationPushpin" | "visualizationRepeater" | "visualizationXirr" | "link" | "externalLink" | "click" | "fileXlsx" | "filePptx" | "filePdf" | "fileImage" | "fileCsvFormatted" | "fileCsvRaw" | "aiDocument" | "recommendation" | "streamUp" | "streamDown" | "stream" | "density" | "parameter" | "pin" | "unpin";
@@ -0,0 +1,39 @@
1
+ import { type ReactNode } from "react";
2
+ /**
3
+ * @internal
4
+ */
5
+ export interface IUiAddGranteeDialogProps {
6
+ /** Object title shown in the header — wrapped into `Share "\{title\}"`. */
7
+ objectTitle: string;
8
+ /** Current search query. */
9
+ searchQuery: string;
10
+ /** Fires when the user edits the search query. */
11
+ onSearchQueryChange: (next: string) => void;
12
+ /**
13
+ * Optional slot rendered between the search input and the bottom divider.
14
+ * When empty, the screen falls back to a "No user or group selected"
15
+ * placeholder. Callers typically render a single `UiGranteeRow`
16
+ * here to preview the grantee they've picked from the search dropdown.
17
+ */
18
+ selectedGrantee?: ReactNode;
19
+ /** Fires when the user clicks the header back-arrow button. */
20
+ onBack: () => void;
21
+ /** Fires when the user clicks the header X close button. */
22
+ onClose: () => void;
23
+ /** Fires when the user clicks Cancel in the footer. */
24
+ onCancel: () => void;
25
+ /** Fires when the user clicks the primary Add button in the footer. */
26
+ onAdd: () => void;
27
+ /** When true, the primary Add button is disabled. */
28
+ isAddDisabled?: boolean;
29
+ /** Test id forwarded to the root element. */
30
+ dataTestId?: string;
31
+ }
32
+ /**
33
+ * Standalone dialog for adding a grantee, opened from the share dialog's
34
+ * "+ Add" action. Lets the author search for a user or group, preview the
35
+ * grantee they picked, and confirm adding them with the footer Add button.
36
+ *
37
+ * @internal
38
+ */
39
+ export declare function UiAddGranteeDialog({ objectTitle, searchQuery, onSearchQueryChange, selectedGrantee, onBack, onClose, onCancel, onAdd, isAddDisabled, dataTestId }: IUiAddGranteeDialogProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,30 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useIntl } from "react-intl";
3
+ import { commonDialogMessages, olpAddGranteeDialogMessages, olpObjectShareDialogMessages, } from "../../locales.js";
4
+ import { bem } from "../@utils/bem.js";
5
+ import { UiButton } from "../UiButton/UiButton.js";
6
+ import { UiDialogFooter } from "../UiDialogShell/UiDialogFooter.js";
7
+ import { UiDialogHeader } from "../UiDialogShell/UiDialogHeader.js";
8
+ import { UiDialogShell } from "../UiDialogShell/UiDialogShell.js";
9
+ import { UiIconButton } from "../UiIconButton/UiIconButton.js";
10
+ import { UiTextInput } from "../UiTextInput/UiTextInput.js";
11
+ const { b, e } = bem("gd-ui-kit-add-grantee-dialog");
12
+ /**
13
+ * Standalone dialog for adding a grantee, opened from the share dialog's
14
+ * "+ Add" action. Lets the author search for a user or group, preview the
15
+ * grantee they picked, and confirm adding them with the footer Add button.
16
+ *
17
+ * @internal
18
+ */
19
+ export function UiAddGranteeDialog({ objectTitle, searchQuery, onSearchQueryChange, selectedGrantee, onBack, onClose, onCancel, onAdd, isAddDisabled, dataTestId, }) {
20
+ const intl = useIntl();
21
+ const dialogTitle = intl.formatMessage(olpObjectShareDialogMessages.title, { title: objectTitle });
22
+ const backButton = (_jsx(UiIconButton, { icon: "chevronLeft", variant: "tertiary", size: "small", onClick: onBack, accessibilityConfig: { ariaLabel: intl.formatMessage(olpAddGranteeDialogMessages.back) } }));
23
+ return (_jsxs(UiDialogShell, { dataTestId: dataTestId, children: [
24
+ _jsx(UiDialogHeader, { title: dialogTitle, titleSize: "large", onClose: onClose, leading: backButton }), _jsxs("div", { className: b(), children: [
25
+ _jsx(UiTextInput, { type: "search", value: searchQuery, onChange: onSearchQueryChange, label: intl.formatMessage(olpAddGranteeDialogMessages.userOrGroup), placeholder: intl.formatMessage(olpAddGranteeDialogMessages.searchPlaceholder) }), _jsx("div", { className: e("preview"), children: selectedGrantee ?? (_jsx("span", { className: e("empty-state"), children: intl.formatMessage(olpAddGranteeDialogMessages.emptyState) })) })
26
+ ] }), _jsxs(UiDialogFooter, { divider: true, children: [
27
+ _jsx(UiButton, { label: intl.formatMessage(commonDialogMessages.cancel), variant: "secondary", size: "medium", onClick: onCancel }), _jsx(UiButton, { label: intl.formatMessage(olpAddGranteeDialogMessages.add), variant: "primary", size: "medium", onClick: onAdd, isDisabled: isAddDisabled })
28
+ ] })
29
+ ] }));
30
+ }
@@ -0,0 +1,40 @@
1
+ import { type IconType } from "../@types/icon.js";
2
+ import { type ThemeColor } from "../@types/themeColors.js";
3
+ /**
4
+ * @internal
5
+ */
6
+ export interface IUiAvatarProps {
7
+ /** Icon rendered inside the circle. */
8
+ icon: IconType;
9
+ /** Outer circle size in px. Defaults to 32. */
10
+ size?: number;
11
+ /** Background tone of the circle. Defaults to `complementary-2`. */
12
+ backgroundColor?: ThemeColor;
13
+ /** Icon tone. Defaults to `complementary-5`. */
14
+ iconColor?: ThemeColor;
15
+ /**
16
+ * Icon size in px. Defaults to `Math.round(size * ICON_TO_AVATAR_RATIO)`,
17
+ * which mirrors the 14/32 proportion used across the kit's avatars.
18
+ */
19
+ iconSize?: number;
20
+ /**
21
+ * Accessibility config for the avatar. Provide an `ariaLabel`
22
+ * when the avatar carries meaning (e.g. a stand-alone "who" indicator).
23
+ * Use `ariaHidden: true` when the avatar sits next to a visible
24
+ * name and would only duplicate that name for screen-reader users.
25
+ */
26
+ accessibilityConfig?: {
27
+ ariaLabel?: string;
28
+ ariaHidden?: boolean;
29
+ };
30
+ /** Test id forwarded to the root element. */
31
+ dataTestId?: string;
32
+ }
33
+ /**
34
+ * Circle avatar with a centered icon. Generic small "who" indicator
35
+ * (grantees, presence, audit log, activity feed, ...). Wrap in a
36
+ * domain-specific component to pick the right icon + label per kind.
37
+ *
38
+ * @internal
39
+ */
40
+ export declare function UiAvatar({ icon, size, backgroundColor, iconColor, iconSize, accessibilityConfig, dataTestId }: IUiAvatarProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { bem } from "../@utils/bem.js";
3
+ import { UiIcon } from "../UiIcon/UiIcon.js";
4
+ const { b } = bem("gd-ui-kit-avatar");
5
+ const DEFAULT_SIZE = 32;
6
+ const DEFAULT_BACKGROUND = "complementary-2";
7
+ const DEFAULT_ICON_COLOR = "complementary-5";
8
+ const ICON_TO_AVATAR_RATIO = 0.44;
9
+ /**
10
+ * Circle avatar with a centered icon. Generic small "who" indicator
11
+ * (grantees, presence, audit log, activity feed, ...). Wrap in a
12
+ * domain-specific component to pick the right icon + label per kind.
13
+ *
14
+ * @internal
15
+ */
16
+ export function UiAvatar({ icon, size = DEFAULT_SIZE, backgroundColor = DEFAULT_BACKGROUND, iconColor = DEFAULT_ICON_COLOR, iconSize, accessibilityConfig, dataTestId, }) {
17
+ const resolvedIconSize = iconSize ?? Math.round(size * ICON_TO_AVATAR_RATIO);
18
+ return (_jsx("span", { className: b({ background: backgroundColor }), "data-testid": dataTestId, style: { "--gd-avatar-size": `${size}px` }, children: _jsx(UiIcon, { type: icon, size: resolvedIconSize, color: iconColor, accessibilityConfig: accessibilityConfig }) }));
19
+ }
@@ -36,7 +36,7 @@ export interface IUiButtonProps {
36
36
  tabIndex?: number;
37
37
  /**
38
38
  * When true, the button is focused on mount via the native HTML
39
- * <code>autofocus</code> attribute. Use sparingly — best fit is the safest
39
+ * `autofocus` attribute. Use sparingly — best fit is the safest
40
40
  * action in a confirmation dialog so accidental Enter presses cancel
41
41
  * rather than confirm a destructive action.
42
42
  */
@@ -7,7 +7,7 @@ export interface IUiDialogFooterProps {
7
7
  children: ReactNode;
8
8
  /**
9
9
  * When true, draws a 1px complementary-3 divider above the footer and adds
10
- * matching top padding. ObjectShareDialog and AddGranteeScreen want this;
10
+ * matching top padding. ObjectShareDialog and AddGranteeDialog want this;
11
11
  * ConfirmDialog does not.
12
12
  */
13
13
  divider?: boolean;
@@ -11,7 +11,7 @@ export type DialogHeaderTitleSize = "default" | "large";
11
11
  export interface IUiDialogHeaderProps {
12
12
  /** Title shown in the header. */
13
13
  title: string;
14
- /** Title size — <code>"default"</code> = 18/26, <code>"large"</code> = 20/26. */
14
+ /** Title size — `"default"` = 18/26, `"large"` = 20/26. */
15
15
  titleSize?: DialogHeaderTitleSize;
16
16
  /** Fires when the user clicks the X close button. Omit to hide the X. */
17
17
  onClose?: () => void;
@@ -1,10 +1,10 @@
1
1
  import { type ReactNode } from "react";
2
2
  /**
3
3
  * Accessibility config for a dialog. By default the shell wires
4
- * <code>aria-labelledby</code> to the <code>UiDialogHeader</code> title via
4
+ * `aria-labelledby` to the `UiDialogHeader` title via
5
5
  * context — no config is needed when a header is present. For headerless
6
- * dialogs, pass <code>ariaLabel</code>; to point at an external title
7
- * element, pass <code>ariaLabelledBy</code>.
6
+ * dialogs, pass `ariaLabel`; to point at an external title
7
+ * element, pass `ariaLabelledBy`.
8
8
  *
9
9
  * @internal
10
10
  */
@@ -23,16 +23,16 @@ export interface IUiDialogShellProps {
23
23
  width?: number;
24
24
  /**
25
25
  * When true, the dialog acts as a modal: focus is trapped inside,
26
- * autofocus + return-focus-on-unmount apply, ESC fires <code>onClose</code>,
27
- * and <code>aria-modal="true"</code> is set. Leave off for inline
26
+ * autofocus + return-focus-on-unmount apply, ESC fires `onClose`,
27
+ * and `aria-modal="true"` is set. Leave off for inline
28
28
  * non-blocking dialog cards.
29
29
  */
30
30
  isModal?: boolean;
31
- /** Fires when the user dismisses via ESC. Only active when <code>isModal</code>. */
31
+ /** Fires when the user dismisses via ESC. Only active when `isModal`. */
32
32
  onClose?: () => void;
33
33
  /**
34
- * Accessibility config. Usually unnecessary — when <code>UiDialogHeader</code>
35
- * is used as a child the shell auto-wires <code>aria-labelledby</code> to
34
+ * Accessibility config. Usually unnecessary — when `UiDialogHeader`
35
+ * is used as a child the shell auto-wires `aria-labelledby` to
36
36
  * the header's title.
37
37
  */
38
38
  accessibilityConfig?: IUiDialogShellAccessibilityConfig;
@@ -49,8 +49,8 @@ export declare function useUiDialogContext(): IUiDialogContext | null;
49
49
  /**
50
50
  * Plain dialog card chrome — 4px radius, soft shadow, complementary-0 fill,
51
51
  * 20px padding. Holds whatever the caller composes inside. Set
52
- * <code>isModal</code> for blocking dialogs (adds focus trap, autofocus,
53
- * return-focus, ESC handling and <code>aria-modal</code>).
52
+ * `isModal` for blocking dialogs (adds focus trap, autofocus,
53
+ * return-focus, ESC handling and `aria-modal`).
54
54
  *
55
55
  * @internal
56
56
  */
@@ -14,8 +14,8 @@ export function useUiDialogContext() {
14
14
  /**
15
15
  * Plain dialog card chrome — 4px radius, soft shadow, complementary-0 fill,
16
16
  * 20px padding. Holds whatever the caller composes inside. Set
17
- * <code>isModal</code> for blocking dialogs (adds focus trap, autofocus,
18
- * return-focus, ESC handling and <code>aria-modal</code>).
17
+ * `isModal` for blocking dialogs (adds focus trap, autofocus,
18
+ * return-focus, ESC handling and `aria-modal`).
19
19
  *
20
20
  * @internal
21
21
  */
@@ -0,0 +1,32 @@
1
+ import { type ReactNode } from "react";
2
+ /**
3
+ * Which general-access option is currently selected.
4
+ *
5
+ * @internal
6
+ */
7
+ export type GeneralAccessValue = "RESTRICTED" | "WORKSPACE";
8
+ /**
9
+ * @internal
10
+ */
11
+ export interface IUiGeneralAccessRadioProps {
12
+ /** Selected option. */
13
+ value: GeneralAccessValue;
14
+ /** Fired when the user picks a different option. */
15
+ onChange: (value: GeneralAccessValue) => void;
16
+ /**
17
+ * Optional slot rendered to the right of the `All workspace members`
18
+ * row — typically the `UiGranteeRowControls` pair that lets the
19
+ * author pick labels and the workspace-wide permission level.
20
+ */
21
+ workspaceControls?: ReactNode;
22
+ /** Test id forwarded to the root element. */
23
+ dataTestId?: string;
24
+ }
25
+ /**
26
+ * Two-row radio used by the OLP share dialog to choose between restricting
27
+ * access to the listed grantees and granting access to every workspace
28
+ * member. Composes `UiRadioRow` for each option.
29
+ *
30
+ * @internal
31
+ */
32
+ export declare function UiGeneralAccessRadio({ value, onChange, workspaceControls, dataTestId }: IUiGeneralAccessRadioProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,22 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // (C) 2026 GoodData Corporation
3
+ import { useId } from "react";
4
+ import { useIntl } from "react-intl";
5
+ import { olpGeneralAccessMessages } from "../../locales.js";
6
+ import { bem } from "../@utils/bem.js";
7
+ import { UiRadioRow } from "../UiRadioRow/UiRadioRow.js";
8
+ const { b } = bem("gd-ui-kit-general-access-radio");
9
+ /**
10
+ * Two-row radio used by the OLP share dialog to choose between restricting
11
+ * access to the listed grantees and granting access to every workspace
12
+ * member. Composes `UiRadioRow` for each option.
13
+ *
14
+ * @internal
15
+ */
16
+ export function UiGeneralAccessRadio({ value, onChange, workspaceControls, dataTestId, }) {
17
+ const intl = useIntl();
18
+ const name = useId();
19
+ return (_jsxs("div", { className: b(), "data-testid": dataTestId, role: "radiogroup", "aria-label": intl.formatMessage(olpGeneralAccessMessages.groupLabel), children: [
20
+ _jsx(UiRadioRow, { name: name, value: "RESTRICTED", checked: value === "RESTRICTED", title: intl.formatMessage(olpGeneralAccessMessages.restrictedTitle), description: intl.formatMessage(olpGeneralAccessMessages.restrictedDescription), onChange: () => onChange("RESTRICTED") }), _jsx(UiRadioRow, { name: name, value: "WORKSPACE", checked: value === "WORKSPACE", title: intl.formatMessage(olpGeneralAccessMessages.workspaceTitle), description: intl.formatMessage(olpGeneralAccessMessages.workspaceDescription), onChange: () => onChange("WORKSPACE"), trailing: workspaceControls })
21
+ ] }));
22
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Visual variant of a grantee avatar.
3
+ *
4
+ * @internal
5
+ */
6
+ export type GranteeAvatarKind = "user" | "group";
7
+ /**
8
+ * @internal
9
+ */
10
+ export interface IUiGranteeAvatarProps {
11
+ /** Visual kind — drives which silhouette is rendered. */
12
+ kind: GranteeAvatarKind;
13
+ /**
14
+ * When true, the avatar is hidden from assistive tech. Use when the
15
+ * avatar sits next to a visible name and would only duplicate that name
16
+ * for screen-reader users (e.g. inside `UiGranteeRow`).
17
+ */
18
+ decorative?: boolean;
19
+ /** Test id forwarded to the root element. */
20
+ dataTestId?: string;
21
+ }
22
+ /**
23
+ * 32×32 circle avatar used by the OLP share-dialog grantee list. Thin wrapper
24
+ * over `UiAvatar` that picks the right silhouette and i18n
25
+ * accessibility label per grantee kind. Pass `decorative` when
26
+ * the avatar is paired with a visible name in the same row.
27
+ *
28
+ * @internal
29
+ */
30
+ export declare function UiGranteeAvatar({ kind, decorative, dataTestId }: IUiGranteeAvatarProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,25 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // (C) 2026 GoodData Corporation
3
+ import { useIntl } from "react-intl";
4
+ import { olpGranteeAvatarMessages } from "../../locales.js";
5
+ import { UiAvatar } from "../UiAvatar/UiAvatar.js";
6
+ const ICON_BY_KIND = {
7
+ user: "user",
8
+ group: "users",
9
+ };
10
+ /**
11
+ * 32×32 circle avatar used by the OLP share-dialog grantee list. Thin wrapper
12
+ * over `UiAvatar` that picks the right silhouette and i18n
13
+ * accessibility label per grantee kind. Pass `decorative` when
14
+ * the avatar is paired with a visible name in the same row.
15
+ *
16
+ * @internal
17
+ */
18
+ export function UiGranteeAvatar({ kind, decorative, dataTestId }) {
19
+ const intl = useIntl();
20
+ if (decorative) {
21
+ return (_jsx(UiAvatar, { icon: ICON_BY_KIND[kind], accessibilityConfig: { ariaHidden: true }, dataTestId: dataTestId }));
22
+ }
23
+ const ariaLabel = intl.formatMessage(kind === "group" ? olpGranteeAvatarMessages.group : olpGranteeAvatarMessages.user);
24
+ return _jsx(UiAvatar, { icon: ICON_BY_KIND[kind], accessibilityConfig: { ariaLabel }, dataTestId: dataTestId });
25
+ }
@@ -0,0 +1,26 @@
1
+ import { type ReactNode } from "react";
2
+ import { type GranteeAvatarKind } from "../UiGranteeAvatar/UiGranteeAvatar.js";
3
+ /**
4
+ * @internal
5
+ */
6
+ export interface IUiGranteeRowProps {
7
+ /** Visual kind — drives the avatar silhouette. */
8
+ kind: GranteeAvatarKind;
9
+ /** Display name shown on the first line. */
10
+ name: string;
11
+ /** Optional email subline shown below the name. */
12
+ email?: string;
13
+ /** When true, an "Owner" tag is rendered between the text block and the controls slot. */
14
+ isOwner?: boolean;
15
+ /** Trailing controls slot — typically the `UiGranteeRowControls` trigger pair. */
16
+ controls?: ReactNode;
17
+ /** Test id forwarded to the root element. */
18
+ dataTestId?: string;
19
+ }
20
+ /**
21
+ * Grantee row used by the OLP share dialog. Renders avatar + name + optional
22
+ * email subline + optional "Owner" tag + trailing controls slot.
23
+ *
24
+ * @internal
25
+ */
26
+ export declare function UiGranteeRow({ kind, name, email, isOwner, controls, dataTestId }: IUiGranteeRowProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useIntl } from "react-intl";
3
+ import { olpGranteeRowMessages } from "../../locales.js";
4
+ import { bem } from "../@utils/bem.js";
5
+ import { UiGranteeAvatar } from "../UiGranteeAvatar/UiGranteeAvatar.js";
6
+ import { UiTag } from "../UiTag/UiTag.js";
7
+ const { b, e } = bem("gd-ui-kit-grantee-row");
8
+ /**
9
+ * Grantee row used by the OLP share dialog. Renders avatar + name + optional
10
+ * email subline + optional "Owner" tag + trailing controls slot.
11
+ *
12
+ * @internal
13
+ */
14
+ export function UiGranteeRow({ kind, name, email, isOwner, controls, dataTestId }) {
15
+ const intl = useIntl();
16
+ return (_jsxs("div", { className: b(), "data-testid": dataTestId, children: [
17
+ _jsx(UiGranteeAvatar, { kind: kind, decorative: true }), _jsxs("div", { className: e("text"), children: [
18
+ _jsx("span", { className: e("name"), title: name, children: name }), email ? (_jsx("span", { className: e("email"), title: email, children: email })) : null] }), isOwner ? (_jsx(UiTag, { label: intl.formatMessage(olpGranteeRowMessages.ownerTag), size: "small", variant: "solid" })) : null, controls] }));
19
+ }
@@ -86,6 +86,7 @@ export const iconPaths = {
86
86
  ellipsis: (_jsx("path", { d: "M5.2998 8.75C5.99016 8.75 6.5498 9.30964 6.5498 10C6.5498 10.6904 5.99016 11.25 5.2998 11.25C4.60954 11.2499 4.0498 10.6903 4.0498 10C4.0498 9.30971 4.60954 8.75011 5.2998 8.75ZM10 8.75C10.6904 8.75 11.25 9.30964 11.25 10C11.25 10.6904 10.6904 11.25 10 11.25C9.30965 11.25 8.75 10.6904 8.75 10C8.75 9.30965 9.30965 8.75 10 8.75ZM14.7002 8.75C15.3905 8.7501 15.9502 9.30971 15.9502 10C15.9502 10.6903 15.3905 11.2499 14.7002 11.25C14.0098 11.25 13.4502 10.6904 13.4502 10C13.4502 9.30964 14.0098 8.75 14.7002 8.75Z" })),
87
87
  pencil: (_jsx("path", { d: "M17.0173 0.0146484C17.4144 0.0146638 17.7921 0.0895336 18.1501 0.239258C18.5147 0.388996 18.837 0.603868 19.1169 0.883789C19.3969 1.16372 19.6117 1.48603 19.7615 1.85059C19.9112 2.21516 19.9861 2.59604 19.9861 2.99316C19.9861 3.39028 19.9112 3.77117 19.7615 4.13574C19.6117 4.49379 19.3969 4.81284 19.1169 5.09277L6.3728 17.8467C6.34679 17.8727 6.31743 17.8955 6.28491 17.915C6.2524 17.9345 6.21977 17.9509 6.18726 17.9639L0.689209 19.9561C0.656708 19.9691 0.627329 19.9756 0.601318 19.9756C0.575309 19.9821 0.545931 19.9853 0.513428 19.9854C0.448359 19.9854 0.383184 19.9723 0.318115 19.9463C0.259544 19.9268 0.207426 19.8909 0.161865 19.8389C0.0902564 19.7738 0.0446803 19.6924 0.0251465 19.5947C0.00561523 19.5036 0.0121257 19.4124 0.0446777 19.3213L2.04663 13.8232C2.05965 13.7842 2.07593 13.7516 2.09546 13.7256C2.11498 13.6931 2.13779 13.6637 2.16382 13.6377L14.908 0.883789C15.1944 0.603871 15.5167 0.388987 15.8748 0.239258C16.2393 0.0895468 16.6202 0.0146484 17.0173 0.0146484ZM2.94507 14.2627L1.35327 18.6572L5.73804 17.0557L16.8123 5.99121L14.0193 3.19824L2.94507 14.2627ZM17.0173 1.01074C16.7504 1.01074 16.4965 1.06286 16.2556 1.16699C16.0148 1.26464 15.8031 1.40791 15.6208 1.59668L14.7224 2.48535L17.5154 5.27832L18.4138 4.38965C18.5961 4.20086 18.7361 3.98598 18.8337 3.74512C18.9379 3.50425 18.99 3.25356 18.99 2.99316C18.99 2.72625 18.9379 2.47232 18.8337 2.23145C18.7361 1.99059 18.5961 1.77896 18.4138 1.59668C18.225 1.4079 18.0101 1.26465 17.7693 1.16699C17.5284 1.06284 17.2777 1.01076 17.0173 1.01074Z" })),
88
88
  folder: (_jsx("path", { d: "M18.4961 4.49219C18.9128 4.49219 19.2676 4.63867 19.5605 4.93164C19.8535 5.22461 20 5.57943 20 5.99609V15.9961C20 16.4128 19.8535 16.7676 19.5605 17.0605C19.2676 17.3535 18.9128 17.5 18.4961 17.5H1.50391C1.08724 17.5 0.732422 17.3535 0.439453 17.0605C0.146484 16.7676 0 16.4128 0 15.9961V5.49805C0 5.32227 0.0260417 5.1237 0.078125 4.90234C0.130208 4.67448 0.195312 4.48242 0.273438 4.32617L0.830078 3.22266C0.934245 3.01432 1.09701 2.8418 1.31836 2.70508C1.53971 2.56836 1.76758 2.5 2.00195 2.5H9.00391C9.23177 2.5 9.45638 2.56836 9.67773 2.70508C9.9056 2.8418 10.0684 3.01432 10.166 3.22266L10.7227 4.32617C10.7422 4.36523 10.7812 4.4043 10.8398 4.44336C10.9049 4.47591 10.957 4.49219 10.9961 4.49219H18.4961ZM19.0039 15.9961V5.99609C19.0039 5.85938 18.9551 5.74219 18.8574 5.64453C18.7598 5.54688 18.6393 5.49805 18.4961 5.49805H10.9961C10.7682 5.49805 10.5404 5.42969 10.3125 5.29297C10.0911 5.14974 9.93164 4.97721 9.83398 4.77539L9.27734 3.66211C9.25781 3.62956 9.2155 3.59375 9.15039 3.55469C9.0918 3.51562 9.04297 3.49609 9.00391 3.49609H2.00195C1.95638 3.49609 1.90104 3.51562 1.83594 3.55469C1.77734 3.59375 1.73828 3.62956 1.71875 3.66211L1.17188 4.77539C1.1263 4.86003 1.08398 4.97721 1.04492 5.12695C1.01237 5.27669 0.996094 5.40039 0.996094 5.49805V15.9961C0.996094 16.1328 1.04492 16.25 1.14258 16.3477C1.24023 16.4453 1.36068 16.4941 1.50391 16.4941H18.4961C18.6393 16.4941 18.7598 16.4453 18.8574 16.3477C18.9551 16.25 19.0039 16.1328 19.0039 15.9961Z" })),
89
+ folderSmall: (_jsx("g", { transform: "translate(0, 4.75)", children: _jsx("path", { d: "M0 13.3029V3.14325C5.18532e-05 2.72641 0.105494 2.27402 0.293141 1.90165L0.836428 0.832579C1.08628 0.337779 1.64437 0 2.19758 0H9.02873C9.30209 9.74704e-05 9.56477 0.0823512 9.81337 0.234557L9.81239 0.235526C10.0664 0.387142 10.2602 0.584694 10.3791 0.832579L10.9224 1.90068C10.9261 1.90439 10.9125 1.887 10.9205 1.89487C10.9293 1.90361 10.9647 1.92366 10.9781 1.92782H18.289C18.7596 1.92794 19.168 2.09503 19.4997 2.42408C19.8315 2.75324 20 3.15898 20 3.62594V13.3029C19.9999 13.7696 19.8314 14.1747 19.4997 14.5037C19.168 14.8328 18.7596 14.9999 18.289 15H1.71194C1.24118 15 0.832135 14.8329 0.500293 14.5037C0.168566 14.1747 0.000116317 13.7696 0 13.3029ZM1.45984 13.3029C1.45994 13.37 1.48132 13.422 1.53117 13.4715C1.57884 13.5188 1.63422 13.5423 1.71194 13.5423H18.289C18.3665 13.5422 18.4213 13.5187 18.4688 13.4715C18.5187 13.422 18.5401 13.37 18.5402 13.3029V3.62594C18.5402 3.55858 18.5188 3.50593 18.4688 3.45632C18.4213 3.40913 18.3665 3.38566 18.289 3.38556H10.9722C10.6907 3.38556 10.4105 3.29596 10.172 3.1481C9.92596 2.99013 9.73782 2.79187 9.61989 2.55105L9.08833 1.49942C9.06641 1.46875 9.05078 1.44805 9.00723 1.44805H2.20442C2.16406 1.44805 2.15234 1.44805 2.12918 1.49554L1.60641 2.55105L1.6025 2.5588C1.5711 2.61665 1.53569 2.70961 1.4999 2.8457C1.47161 2.97694 1.45987 3.07462 1.45984 3.14325V13.3029Z" }) })),
89
90
  folderPlus: (_jsx("path", { d: "M18.4961 17.5H1.50391C1.08724 17.5 0.732422 17.3535 0.439453 17.0605C0.146484 16.7676 0 16.4128 0 15.9961V5.49805C0 5.32227 0.0260417 5.1237 0.078125 4.90234C0.130208 4.67448 0.195312 4.48242 0.273438 4.32617L0.830078 3.22266C0.934245 3.01432 1.09701 2.8418 1.31836 2.70508C1.53971 2.56836 1.76758 2.5 2.00195 2.5H9.00391C9.23177 2.5 9.45638 2.56836 9.67773 2.70508C9.9056 2.8418 10.0684 3.01432 10.166 3.22266L10.7227 4.32617C10.7422 4.36523 10.7812 4.4043 10.8398 4.44336C10.9049 4.47591 10.957 4.49219 10.9961 4.49219H18.4961C18.9128 4.49219 19.2676 4.63867 19.5605 4.93164C19.8535 5.22461 20 5.57943 20 5.99609V15.9961C20 16.4128 19.8535 16.7676 19.5605 17.0605C19.2676 17.3535 18.9128 17.5 18.4961 17.5ZM2.00195 3.49609C1.95638 3.49609 1.90104 3.51562 1.83594 3.55469C1.77734 3.59375 1.74154 3.62956 1.72852 3.66211L1.17188 4.77539C1.1263 4.86003 1.08398 4.97721 1.04492 5.12695C1.01237 5.27669 0.996094 5.40039 0.996094 5.49805V15.9961C0.996094 16.1328 1.04492 16.25 1.14258 16.3477C1.24023 16.4453 1.36068 16.4941 1.50391 16.4941H18.4961C18.6393 16.4941 18.7598 16.4453 18.8574 16.3477C18.9551 16.25 19.0039 16.1328 19.0039 15.9961V5.99609C19.0039 5.85938 18.9551 5.74219 18.8574 5.64453C18.7598 5.54688 18.6393 5.49805 18.4961 5.49805H10.9961C10.7682 5.49805 10.5404 5.42969 10.3125 5.29297C10.0911 5.14974 9.93164 4.97721 9.83398 4.77539L9.27734 3.66211C9.25781 3.62956 9.2155 3.59375 9.15039 3.55469C9.0918 3.51562 9.04297 3.49609 9.00391 3.49609H2.00195ZM12.5 10.498H10V7.99805C10 7.86133 9.95117 7.74414 9.85352 7.64648C9.75586 7.54883 9.63867 7.5 9.50195 7.5C9.36523 7.5 9.24805 7.54883 9.15039 7.64648C9.05273 7.74414 9.00391 7.86133 9.00391 7.99805V10.498H6.50391C6.36068 10.498 6.24023 10.5469 6.14258 10.6445C6.04492 10.7422 5.99609 10.8594 5.99609 10.9961C5.99609 11.1328 6.04492 11.25 6.14258 11.3477C6.24023 11.4453 6.36068 11.4941 6.50391 11.4941H9.00391V13.9941C9.00391 14.1309 9.05273 14.248 9.15039 14.3457C9.24805 14.4434 9.36523 14.4922 9.50195 14.4922C9.63867 14.4922 9.75586 14.4434 9.85352 14.3457C9.95117 14.248 10 14.1309 10 13.9941V11.4941H12.5C12.6367 11.4941 12.7539 11.4453 12.8516 11.3477C12.9492 11.25 12.998 11.1328 12.998 10.9961C12.998 10.8594 12.9492 10.7422 12.8516 10.6445C12.7539 10.5469 12.6367 10.498 12.5 10.498Z" })),
90
91
  trash: (_jsx("path", { d: "M16.0156 2.01172C16.4193 2.01172 16.7643 2.16146 17.0508 2.46094C17.3503 2.7474 17.5 3.09245 17.5 3.49609V4.51172C17.5 4.83724 17.4089 5.13021 17.2266 5.39062C17.0443 5.63802 16.8034 5.8138 16.5039 5.91797V18.4961C16.5039 18.9128 16.3542 19.2643 16.0547 19.5508C15.7682 19.8503 15.4167 20 15 20H5C4.59635 20 4.24479 19.8503 3.94531 19.5508C3.65885 19.2643 3.51562 18.9128 3.51562 18.4961V5.91797C3.21615 5.8138 2.96875 5.63802 2.77344 5.39062C2.59115 5.13021 2.5 4.83724 2.5 4.51172V3.49609C2.5 3.09245 2.64323 2.7474 2.92969 2.46094C3.22917 2.16146 3.58724 2.01172 4.00391 2.01172H7.5V1.50391C7.5 1.08724 7.64323 0.735677 7.92969 0.449219C8.22917 0.14974 8.58724 0 9.00391 0H11.0156C11.4193 0 11.7643 0.14974 12.0508 0.449219C12.3503 0.735677 12.5 1.08724 12.5 1.50391V2.01172H16.0156ZM8.51562 1.50391V2.01172H11.5039V1.50391C11.5039 1.36068 11.4518 1.24349 11.3477 1.15234C11.2565 1.04818 11.1458 0.996094 11.0156 0.996094H9.00391C8.8737 0.996094 8.75651 1.04818 8.65234 1.15234C8.5612 1.24349 8.51562 1.36068 8.51562 1.50391ZM15 19.0039C15.1432 19.0039 15.2604 18.9583 15.3516 18.8672C15.4557 18.763 15.5078 18.6393 15.5078 18.4961V5.99609H4.51172V18.4961C4.51172 18.6393 4.55729 18.763 4.64844 18.8672C4.7526 18.9583 4.86979 19.0039 5 19.0039H15ZM16.5039 4.51172V3.49609C16.5039 3.36589 16.4518 3.25521 16.3477 3.16406C16.2565 3.0599 16.1458 3.00781 16.0156 3.00781H4.00391C3.8737 3.00781 3.75651 3.0599 3.65234 3.16406C3.5612 3.25521 3.51562 3.36589 3.51562 3.49609V4.51172C3.51562 4.64193 3.5612 4.75911 3.65234 4.86328C3.75651 4.95443 3.8737 5 4.00391 5H16.0156C16.1458 5 16.2565 4.95443 16.3477 4.86328C16.4518 4.75911 16.5039 4.64193 16.5039 4.51172ZM13.0078 7.01172C13.151 7.01172 13.2682 7.0638 13.3594 7.16797C13.4635 7.25911 13.5156 7.36979 13.5156 7.5V17.5C13.5156 17.6432 13.4635 17.7669 13.3594 17.8711C13.2682 17.9622 13.151 18.0078 13.0078 18.0078C12.8646 18.0078 12.7409 17.9622 12.6367 17.8711C12.5456 17.7669 12.5 17.6432 12.5 17.5V7.5C12.5 7.36979 12.5456 7.25911 12.6367 7.16797C12.7409 7.0638 12.8646 7.01172 13.0078 7.01172ZM10 7.01172C10.1432 7.01172 10.2604 7.0638 10.3516 7.16797C10.4557 7.25911 10.5078 7.36979 10.5078 7.5V17.5C10.5078 17.6432 10.4557 17.7669 10.3516 17.8711C10.2604 17.9622 10.1432 18.0078 10 18.0078C9.86979 18.0078 9.7526 17.9622 9.64844 17.8711C9.55729 17.7669 9.51172 17.6432 9.51172 17.5V7.5C9.51172 7.36979 9.55729 7.25911 9.64844 7.16797C9.7526 7.0638 9.86979 7.01172 10 7.01172ZM7.01172 7.01172C7.14193 7.01172 7.2526 7.0638 7.34375 7.16797C7.44792 7.25911 7.5 7.36979 7.5 7.5V17.5C7.5 17.6432 7.44792 17.7669 7.34375 17.8711C7.2526 17.9622 7.14193 18.0078 7.01172 18.0078C6.86849 18.0078 6.74479 17.9622 6.64062 17.8711C6.54948 17.7669 6.50391 17.6432 6.50391 17.5V7.5C6.50391 7.36979 6.54948 7.25911 6.64062 7.16797C6.74479 7.0638 6.86849 7.01172 7.01172 7.01172Z" })),
91
92
  arrowUp: (_jsx("path", { d: "M9.65332 0.898438C9.75098 0.800781 9.86816 0.751953 10.0049 0.751953C10.1416 0.751953 10.2588 0.800781 10.3564 0.898438L16.3525 6.89453C16.4046 6.9401 16.4404 6.99544 16.46 7.06055C16.486 7.11914 16.499 7.18099 16.499 7.24609C16.499 7.3112 16.486 7.3763 16.46 7.44141C16.4404 7.5 16.4046 7.55208 16.3525 7.59766C16.2549 7.69531 16.1377 7.74414 16.001 7.74414C15.8643 7.74414 15.7471 7.69531 15.6494 7.59766L10.5029 2.45117V18.75C10.5029 18.8867 10.4541 19.0039 10.3564 19.1016C10.2588 19.1992 10.1416 19.248 10.0049 19.248C9.86816 19.248 9.75098 19.1992 9.65332 19.1016C9.55566 19.0039 9.50684 18.8867 9.50684 18.75V2.45117L4.36035 7.59766C4.2627 7.69531 4.14225 7.74414 3.99902 7.74414C3.8623 7.74414 3.74512 7.69531 3.64746 7.59766C3.5498 7.5 3.50098 7.38281 3.50098 7.24609C3.50098 7.10938 3.5498 6.99219 3.64746 6.89453L9.65332 0.898438Z" })),
@@ -49,7 +49,7 @@ export function useUiMenuContextValue(props, menuComponentRef, itemsContainerRef
49
49
  const setFocusedId = useCallback((...args) => {
50
50
  setFocusedId_internal(...args);
51
51
  // Focus is lost when clicking on an item that opens a submenu. We need to refocus the menu.
52
- menuComponentRef.current?.focus();
52
+ menuComponentRef.current?.focus({ preventScroll: true });
53
53
  }, [menuComponentRef]);
54
54
  const focusedItem = focusedId === undefined ? undefined : getFocusableItem(items, focusedId);
55
55
  const parentItemId = useMemo(() => {
@@ -108,9 +108,7 @@ export function useUiMenuContextValue(props, menuComponentRef, itemsContainerRef
108
108
  if (!element) {
109
109
  return;
110
110
  }
111
- if (controlType === "keyboard" &&
112
- itemsContainerRef.current &&
113
- itemsContainerRef.current.scrollHeight > itemsContainerRef.current.clientHeight) {
111
+ if (controlType === "keyboard" && itemsContainerRef.current) {
114
112
  element.scrollIntoView({ block: "nearest", behavior: "smooth" });
115
113
  }
116
114
  }, [controlType, itemsContainerRef]);
@@ -0,0 +1,57 @@
1
+ import { type ReactNode } from "react";
2
+ import { type GeneralAccessValue } from "../UiGeneralAccessRadio/UiGeneralAccessRadio.js";
3
+ import { type GranteeAvatarKind } from "../UiGranteeAvatar/UiGranteeAvatar.js";
4
+ /**
5
+ * Visual data for a single grantee row inside the dialog. The `controls`
6
+ * slot lets the caller plug in the per-row controls (typically
7
+ * `UiGranteeRowControls`).
8
+ *
9
+ * @internal
10
+ */
11
+ export interface IUiObjectShareDialogGrantee {
12
+ /** Stable identifier — used as the React key for the row. */
13
+ id: string;
14
+ /** Avatar variant. */
15
+ kind: GranteeAvatarKind;
16
+ /** Display name. */
17
+ name: string;
18
+ /** Optional email subline. */
19
+ email?: string;
20
+ /** When true, the row is rendered with the "Owner" tag instead of controls. */
21
+ isOwner?: boolean;
22
+ /** Per-row controls — usually `UiGranteeRowControls`. Owner rows leave this empty. */
23
+ controls?: ReactNode;
24
+ }
25
+ /**
26
+ * @internal
27
+ */
28
+ export interface IUiObjectShareDialogProps {
29
+ /** Object title shown in the header — wrapped into `Share "\{title\}"`. */
30
+ objectTitle: string;
31
+ /** Fires when the user clicks the header X button OR the footer Close button. */
32
+ onClose: () => void;
33
+ /** Grantee rows shown inside the SHARED WITH section, in render order. */
34
+ grantees: IUiObjectShareDialogGrantee[];
35
+ /** Fires when the user clicks the + Add link in the SHARED WITH heading. */
36
+ onAddClick: () => void;
37
+ /** Selected general-access option. */
38
+ generalAccess: GeneralAccessValue;
39
+ /** Fires when the user picks a different general-access option. */
40
+ onGeneralAccessChange: (value: GeneralAccessValue) => void;
41
+ /**
42
+ * Optional slot rendered next to the "All workspace members" row — typically a
43
+ * `UiGranteeRowControls` pair for the workspace-wide labels picker
44
+ * and permission level.
45
+ */
46
+ workspaceControls?: ReactNode;
47
+ /** Test id forwarded to the root element. */
48
+ dataTestId?: string;
49
+ }
50
+ /**
51
+ * Root component for the OLP share dialog — composes the header, the grantee
52
+ * list (with its `+ Add` action), the general-access radio, and the
53
+ * footer Close button.
54
+ *
55
+ * @internal
56
+ */
57
+ export declare function UiObjectShareDialog({ objectTitle, onClose, grantees, onAddClick, generalAccess, onGeneralAccessChange, workspaceControls, dataTestId }: IUiObjectShareDialogProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,28 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useIntl } from "react-intl";
3
+ import { commonDialogMessages, olpObjectShareDialogMessages } from "../../locales.js";
4
+ import { bem } from "../@utils/bem.js";
5
+ import { UiButton } from "../UiButton/UiButton.js";
6
+ import { UiDialogFooter } from "../UiDialogShell/UiDialogFooter.js";
7
+ import { UiDialogHeader } from "../UiDialogShell/UiDialogHeader.js";
8
+ import { UiDialogShell } from "../UiDialogShell/UiDialogShell.js";
9
+ import { UiGeneralAccessRadio, } from "../UiGeneralAccessRadio/UiGeneralAccessRadio.js";
10
+ import { UiGranteeRow } from "../UiGranteeRow/UiGranteeRow.js";
11
+ import { UiSectionHeading } from "../UiSectionHeading/UiSectionHeading.js";
12
+ const { b, e } = bem("gd-ui-kit-object-share-dialog");
13
+ /**
14
+ * Root component for the OLP share dialog — composes the header, the grantee
15
+ * list (with its `+ Add` action), the general-access radio, and the
16
+ * footer Close button.
17
+ *
18
+ * @internal
19
+ */
20
+ export function UiObjectShareDialog({ objectTitle, onClose, grantees, onAddClick, generalAccess, onGeneralAccessChange, workspaceControls, dataTestId, }) {
21
+ const intl = useIntl();
22
+ const dialogTitle = intl.formatMessage(olpObjectShareDialogMessages.title, { title: objectTitle });
23
+ return (_jsxs(UiDialogShell, { dataTestId: dataTestId, children: [
24
+ _jsx(UiDialogHeader, { title: dialogTitle, onClose: onClose }), _jsxs("div", { className: b(), children: [
25
+ _jsx(UiSectionHeading, { label: intl.formatMessage(olpObjectShareDialogMessages.sharedWith), action: _jsx(UiButton, { label: intl.formatMessage(olpObjectShareDialogMessages.add), variant: "popout", size: "small", iconBefore: "plus", onClick: onAddClick }) }), _jsx("div", { className: e("grantees"), children: grantees.map((grantee) => (_jsx(UiGranteeRow, { kind: grantee.kind, name: grantee.name, email: grantee.email, isOwner: grantee.isOwner, controls: grantee.controls }, grantee.id))) }), _jsx(UiSectionHeading, { label: intl.formatMessage(olpObjectShareDialogMessages.generalAccess) }), _jsx(UiGeneralAccessRadio, { value: generalAccess, onChange: onGeneralAccessChange, workspaceControls: workspaceControls })
26
+ ] }), _jsx(UiDialogFooter, { divider: true, children: _jsx(UiButton, { label: intl.formatMessage(commonDialogMessages.close), variant: "secondary", size: "medium", onClick: onClose }) })
27
+ ] }));
28
+ }
@@ -0,0 +1,40 @@
1
+ import { type ChangeEvent } from "react";
2
+ import { type IAccessibilityConfigBase } from "../../typings/accessibility.js";
3
+ /**
4
+ * @internal
5
+ */
6
+ export interface IUiRadioProps {
7
+ /** Whether this radio is selected. */
8
+ checked: boolean;
9
+ /** Fires when the user toggles the radio. */
10
+ onChange?: (e: ChangeEvent<HTMLInputElement>) => void;
11
+ /**
12
+ * `name` attribute shared by a group of mutually exclusive radios —
13
+ * required by HTML radios.
14
+ */
15
+ name?: string;
16
+ /** Value sent with the change event — the picked option's identifier. */
17
+ value?: string;
18
+ disabled?: boolean;
19
+ accessibilityConfig?: IAccessibilityConfigBase;
20
+ tabIndex?: number;
21
+ /** Optional inline label rendered next to the radio circle. */
22
+ label?: string;
23
+ /**
24
+ * Id set on the native input. When omitted a stable id is generated.
25
+ * Pass an explicit id when an ancestor renders its own
26
+ * `<label htmlFor={id}>` (e.g. `UiRadioRow`) so the two stay associated.
27
+ */
28
+ id?: string;
29
+ dataTestId?: string;
30
+ }
31
+ /**
32
+ * Standalone radio control — renders a native `<input type="radio">` for
33
+ * accessibility and a custom 14px circle for the visual. The input is overlaid
34
+ * on the circle, so clicking the circle toggles it. Renders no wrapping
35
+ * `<label>`: an optional inline label is a sibling associated via `htmlFor`,
36
+ * which lets `UiRadioRow` supply its own label without nesting.
37
+ *
38
+ * @internal
39
+ */
40
+ export declare function UiRadio({ checked, onChange, name, value, disabled, accessibilityConfig, tabIndex, label, id, dataTestId }: IUiRadioProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,23 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // (C) 2026 GoodData Corporation
3
+ import { useId } from "react";
4
+ import { accessibilityConfigToAttributes } from "../../typings/utilities.js";
5
+ import { bem } from "../@utils/bem.js";
6
+ const { b, e } = bem("gd-ui-kit-radio");
7
+ /**
8
+ * Standalone radio control — renders a native `<input type="radio">` for
9
+ * accessibility and a custom 14px circle for the visual. The input is overlaid
10
+ * on the circle, so clicking the circle toggles it. Renders no wrapping
11
+ * `<label>`: an optional inline label is a sibling associated via `htmlFor`,
12
+ * which lets `UiRadioRow` supply its own label without nesting.
13
+ *
14
+ * @internal
15
+ */
16
+ export function UiRadio({ checked, onChange = () => { }, name, value, disabled = false, accessibilityConfig, tabIndex, label, id, dataTestId, }) {
17
+ const generatedId = useId();
18
+ const inputId = id ?? generatedId;
19
+ return (_jsxs("span", { className: b(), children: [
20
+ _jsxs("span", { className: e("control"), children: [
21
+ _jsx("input", { id: inputId, type: "radio", className: e("input"), checked: checked, onChange: onChange, disabled: disabled, name: name, value: value, tabIndex: tabIndex, "data-testid": dataTestId, ...accessibilityConfigToAttributes(accessibilityConfig) }), _jsx("span", { className: e("circle", { checked, disabled }), "aria-hidden": "true" })
22
+ ] }), label ? (_jsx("label", { className: e("label"), htmlFor: inputId, children: label })) : null] }));
23
+ }