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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/esm/@ui/@types/icon.d.ts +1 -1
  2. package/esm/@ui/UiAsyncTable/UiAsyncTable/UiAsyncTableCheckbox.js +7 -1
  3. package/esm/@ui/UiAsyncTable/UiAsyncTable/UiAsyncTableDropdownItem.js +2 -2
  4. package/esm/@ui/UiCheckbox/UiCheckbox.d.ts +13 -1
  5. package/esm/@ui/UiCheckbox/UiCheckbox.js +14 -4
  6. package/esm/@ui/UiGranteeRowControls/UiGranteeRowControls.d.ts +32 -0
  7. package/esm/@ui/UiGranteeRowControls/UiGranteeRowControls.js +31 -0
  8. package/esm/@ui/UiIcon/icons.js +3 -0
  9. package/esm/@ui/UiLabelChecklistRow/UiLabelChecklistRow.d.ts +33 -0
  10. package/esm/@ui/UiLabelChecklistRow/UiLabelChecklistRow.js +26 -0
  11. package/esm/@ui/UiLabelRow/UiLabelRow.d.ts +52 -0
  12. package/esm/@ui/UiLabelRow/UiLabelRow.js +18 -0
  13. package/esm/@ui/UiLabelsList/UiLabelsList.d.ts +30 -0
  14. package/esm/@ui/UiLabelsList/UiLabelsList.js +24 -0
  15. package/esm/@ui/UiLabelsPicker/UiLabelsPicker.d.ts +63 -0
  16. package/esm/@ui/UiLabelsPicker/UiLabelsPicker.js +89 -0
  17. package/esm/@ui/UiPermissionMenu/UiPermissionMenu.d.ts +43 -0
  18. package/esm/@ui/UiPermissionMenu/UiPermissionMenu.js +113 -0
  19. package/esm/@ui/UiPopover/UiPopover.d.ts +14 -2
  20. package/esm/@ui/UiPopover/UiPopover.js +21 -5
  21. package/esm/index.d.ts +6 -0
  22. package/esm/index.js +6 -0
  23. package/esm/locales.d.ts +54 -0
  24. package/esm/locales.js +22 -0
  25. package/esm/sdk-ui-kit.d.ts +289 -3
  26. package/package.json +11 -11
  27. package/src/@ui/UiCheckbox/UiCheckbox.scss +29 -8
  28. package/src/@ui/UiGranteeRowControls/UiGranteeRowControls.scss +8 -0
  29. package/src/@ui/UiLabelRow/UiLabelRow.scss +40 -0
  30. package/src/@ui/UiLabelsList/UiLabelsList.scss +21 -0
  31. package/src/@ui/UiLabelsPicker/UiLabelsPicker.scss +29 -0
  32. package/src/@ui/UiPermissionMenu/UiPermissionMenu.scss +66 -0
  33. package/src/@ui/index.scss +5 -0
  34. package/styles/css/main.css +158 -7
  35. 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" | "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";
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" | "infoCircle" | "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";
@@ -5,11 +5,17 @@ import { e } from "../asyncTableBem.js";
5
5
  import { ASYNC_TABLE_SELECTED_COUNT_ID } from "./constants.js";
6
6
  import { getColumnHeaderId, stopPropagationCallback } from "./utils.js";
7
7
  export function UiAsyncTableCheckbox({ onChange, checked, indeterminate, disabled, ariaLabel, isCellFocused, header, cellRef, cellId, }) {
8
+ // The native input is now overlaid on the visible 14×14 control (kit
9
+ // convention for @ui/UiCheckbox), so the input itself is the click
10
+ // target and `preventDefault` stops the click from bubbling to the
11
+ // cell. Wire `onChange` through `UiCheckbox` so the toggle fires.
12
+ // The cell-div retains keyboard handling (gridcell Space/Enter) and
13
+ // bubbled clicks from any non-input area of the cell.
8
14
  return (_jsx("div", { className: e("cell", { checkbox: true, focused: isCellFocused ?? false }), role: header ? undefined : "gridcell", id: cellId, "aria-labelledby": header ? undefined : getColumnHeaderId("checkbox"), "aria-describedby": header ? ASYNC_TABLE_SELECTED_COUNT_ID : undefined, onClick: (e) => {
9
15
  stopPropagationCallback(e, onChange);
10
16
  }, onKeyDown: (e) => {
11
17
  if (isActionKey(e)) {
12
18
  stopPropagationCallback(e, onChange);
13
19
  }
14
- }, ref: cellRef, children: _jsx(UiCheckbox, { checked: checked ?? false, preventDefault: true, indeterminate: indeterminate, disabled: disabled, accessibilityConfig: ariaLabel ? { ariaLabel } : undefined, tabIndex: header ? 0 : -1 }) }));
20
+ }, ref: cellRef, children: _jsx(UiCheckbox, { checked: checked ?? false, preventDefault: true, onChange: onChange, indeterminate: indeterminate, disabled: disabled, accessibilityConfig: ariaLabel ? { ariaLabel } : undefined, tabIndex: header ? 0 : -1 }) }));
15
21
  }
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- // (C) 2025 GoodData Corporation
2
+ // (C) 2025-2026 GoodData Corporation
3
3
  import { UiCheckbox } from "../../../@ui/UiCheckbox/UiCheckbox.js";
4
4
  import { ContentDivider } from "../../../Dialog/ContentDivider.js";
5
5
  import { accessibilityConfigToAttributes } from "../../../typings/utilities.js";
@@ -9,5 +9,5 @@ export function UiAsyncTableDropdownItem({ label, secondaryLabel, onClick, isSel
9
9
  _jsxs("div", { className: e("dropdown-item", {
10
10
  selected: isSelected ?? false,
11
11
  "multi-select": isMultiSelect ?? false,
12
- }), onClick: onClick, role: "menuitem", "aria-disabled": false, ...accessibilityConfigToAttributes(accessibilityConfig), children: [isMultiSelect ? (_jsx("div", { className: e("dropdown-item-checkbox"), children: _jsx(UiCheckbox, { preventDefault: true, checked: isSelected ?? false, tabIndex: -1 }) })) : null, _jsx("div", { className: e("dropdown-item-label-primary"), children: label }), secondaryLabel ? (_jsx("div", { className: e("dropdown-item-label-secondary"), children: secondaryLabel })) : null] }), isUnderlined ? _jsx(ContentDivider, { className: e("dropdown-item-divider") }) : null] }));
12
+ }), onClick: onClick, role: "menuitem", "aria-disabled": false, ...accessibilityConfigToAttributes(accessibilityConfig), children: [isMultiSelect ? (_jsx("div", { className: e("dropdown-item-checkbox"), children: _jsx(UiCheckbox, { checked: isSelected ?? false, tabIndex: -1 }) })) : null, _jsx("div", { className: e("dropdown-item-label-primary"), children: label }), secondaryLabel ? (_jsx("div", { className: e("dropdown-item-label-secondary"), children: secondaryLabel })) : null] }), isUnderlined ? _jsx(ContentDivider, { className: e("dropdown-item-divider") }) : null] }));
13
13
  }
@@ -12,8 +12,20 @@ export interface IUiCheckboxProps {
12
12
  accessibilityConfig?: IAccessibilityConfigBase;
13
13
  tabIndex?: number;
14
14
  label?: string;
15
+ /**
16
+ * Id set on the native input. When omitted a stable id is generated.
17
+ * Pass an explicit id when an ancestor renders its own
18
+ * `<label htmlFor={id}>` so the two stay associated.
19
+ */
20
+ id?: string;
15
21
  }
16
22
  /**
23
+ * Checkbox control — renders a native `<input type="checkbox">` for
24
+ * accessibility and a custom 14px box for the visual. The input is overlaid on
25
+ * the box, so clicking the box toggles it. Renders no wrapping `<label>`: an
26
+ * optional inline label is a sibling associated via `htmlFor`, which lets an
27
+ * ancestor row supply its own label without nesting.
28
+ *
17
29
  * @internal
18
30
  */
19
- export declare function UiCheckbox({ checked, onChange, preventDefault, indeterminate, disabled, accessibilityConfig, tabIndex, label }: IUiCheckboxProps): import("react/jsx-runtime").JSX.Element;
31
+ export declare function UiCheckbox({ checked, onChange, preventDefault, indeterminate, disabled, accessibilityConfig, tabIndex, label, id }: IUiCheckboxProps): import("react/jsx-runtime").JSX.Element;
@@ -1,19 +1,29 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  // (C) 2025-2026 GoodData Corporation
3
- import { useEffect, useRef } from "react";
3
+ import { useEffect, useId, useRef } from "react";
4
4
  import { accessibilityConfigToAttributes } from "../../typings/utilities.js";
5
5
  import { bem } from "../@utils/bem.js";
6
6
  const { b, e } = bem("gd-ui-kit-checkbox");
7
7
  /**
8
+ * Checkbox control — renders a native `<input type="checkbox">` for
9
+ * accessibility and a custom 14px box for the visual. The input is overlaid on
10
+ * the box, so clicking the box toggles it. Renders no wrapping `<label>`: an
11
+ * optional inline label is a sibling associated via `htmlFor`, which lets an
12
+ * ancestor row supply its own label without nesting.
13
+ *
8
14
  * @internal
9
15
  */
10
- export function UiCheckbox({ checked, onChange = () => { }, preventDefault = false, indeterminate = false, disabled = false, accessibilityConfig, tabIndex, label, }) {
16
+ export function UiCheckbox({ checked, onChange = () => { }, preventDefault = false, indeterminate = false, disabled = false, accessibilityConfig, tabIndex, label, id, }) {
11
17
  const inputRef = useRef(null);
18
+ const generatedId = useId();
19
+ const inputId = id ?? generatedId;
12
20
  useEffect(() => {
13
21
  if (inputRef.current) {
14
22
  inputRef.current.indeterminate = indeterminate;
15
23
  }
16
24
  }, [indeterminate]);
17
- return (_jsxs("label", { className: b(), children: [
18
- _jsx("input", { ref: inputRef, type: "checkbox", className: e("input"), checked: checked, onChange: onChange, disabled: disabled, onClick: (e) => preventDefault && e.stopPropagation(), tabIndex: tabIndex, ...accessibilityConfigToAttributes(accessibilityConfig) }), _jsx("span", { className: e("box", { checked, indeterminate, disabled }) }), label ? _jsx("span", { className: e("label") + " gd-label", children: label }) : null] }));
25
+ return (_jsxs("span", { className: b(), children: [
26
+ _jsxs("span", { className: e("control"), children: [
27
+ _jsx("input", { ref: inputRef, id: inputId, type: "checkbox", className: e("input"), checked: checked, onChange: onChange, disabled: disabled, onClick: (e) => preventDefault && e.stopPropagation(), tabIndex: tabIndex, ...accessibilityConfigToAttributes(accessibilityConfig) }), _jsx("span", { className: e("box", { checked, indeterminate, disabled }), "aria-hidden": "true" })
28
+ ] }), label ? (_jsx("label", { className: e("label") + " gd-label", htmlFor: inputId, children: label })) : null] }));
19
29
  }
@@ -0,0 +1,32 @@
1
+ import { type IUiLabelsPickerItem } from "../UiLabelsPicker/UiLabelsPicker.js";
2
+ import { type PermissionMenuLevel } from "../UiPermissionMenu/UiPermissionMenu.js";
3
+ /**
4
+ * @internal
5
+ */
6
+ export interface IUiGranteeRowControlsProps {
7
+ /** All labels available on the parent attribute. */
8
+ labels: ReadonlyArray<IUiLabelsPickerItem>;
9
+ /** Currently selected label ids. Locked items are always treated as selected. */
10
+ selectedLabelIds: ReadonlyArray<string>;
11
+ /** Current permission level for the grantee. */
12
+ permissionLevel: PermissionMenuLevel;
13
+ /** Fires when the labels picker commits a new selection. */
14
+ onLabelsChange: (selectedIds: string[]) => void;
15
+ /** Fires when the user picks a new permission level. */
16
+ onPermissionChange: (level: PermissionMenuLevel) => void;
17
+ /** Fires when the user picks Transfer ownership in the permission menu. */
18
+ onTransferOwnership?: () => void;
19
+ /** Fires when the user picks Remove access in the permission menu. */
20
+ onRemoveAccess?: () => void;
21
+ /** Test id forwarded to the root element. */
22
+ dataTestId?: string;
23
+ }
24
+ /**
25
+ * Pair of controls shown on every grantee row in the OLP share dialog:
26
+ * a labels-picker trigger and a permission-menu trigger. Both triggers are
27
+ * Tertiary `small` `UiButton`s with `chevronDown`
28
+ * and open their respective popovers on click.
29
+ *
30
+ * @internal
31
+ */
32
+ export declare function UiGranteeRowControls({ labels, selectedLabelIds, permissionLevel, onLabelsChange, onPermissionChange, onTransferOwnership, onRemoveAccess, dataTestId }: IUiGranteeRowControlsProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,31 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // (C) 2026 GoodData Corporation
3
+ import { useIntl } from "react-intl";
4
+ import { olpGranteeControlsMessages, olpPermissionMessages } from "../../locales.js";
5
+ import { bem } from "../@utils/bem.js";
6
+ import { UiButton } from "../UiButton/UiButton.js";
7
+ import { UiLabelsPicker, isLabelsPickerItemChecked, } from "../UiLabelsPicker/UiLabelsPicker.js";
8
+ import { UiPermissionMenu } from "../UiPermissionMenu/UiPermissionMenu.js";
9
+ const { b } = bem("gd-ui-kit-grantee-row-controls");
10
+ /**
11
+ * Pair of controls shown on every grantee row in the OLP share dialog:
12
+ * a labels-picker trigger and a permission-menu trigger. Both triggers are
13
+ * Tertiary `small` `UiButton`s with `chevronDown`
14
+ * and open their respective popovers on click.
15
+ *
16
+ * @internal
17
+ */
18
+ export function UiGranteeRowControls({ labels, selectedLabelIds, permissionLevel, onLabelsChange, onPermissionChange, onTransferOwnership, onRemoveAccess, dataTestId, }) {
19
+ const intl = useIntl();
20
+ const total = labels.length;
21
+ // Locked labels always count as selected. Reuse the picker's predicate so the
22
+ // trigger never shows "N-1 of N" when a locked id is omitted from selectedLabelIds.
23
+ const selected = labels.filter((label) => isLabelsPickerItemChecked(label, selectedLabelIds)).length;
24
+ const labelsTriggerText = selected === total
25
+ ? intl.formatMessage(olpGranteeControlsMessages.allLabels)
26
+ : intl.formatMessage(olpGranteeControlsMessages.labelsCount, { selected, total });
27
+ const permissionTriggerText = intl.formatMessage(permissionLevel === "SHARE" ? olpPermissionMessages.canViewAndShare : olpPermissionMessages.canView);
28
+ return (_jsxs("div", { className: b(), "data-testid": dataTestId, children: [
29
+ _jsx(UiLabelsPicker, { anchor: _jsx(UiButton, { label: labelsTriggerText, size: "small", variant: "tertiary", iconAfter: "chevronDown" }), items: labels, defaultSelectedIds: selectedLabelIds, onApply: onLabelsChange }), _jsx(UiPermissionMenu, { anchor: _jsx(UiButton, { label: permissionTriggerText, size: "small", variant: "tertiary", iconAfter: "chevronDown" }), selectedLevel: permissionLevel, onPermissionChange: onPermissionChange, onTransferOwnership: onTransferOwnership, onRemoveAccess: onRemoveAccess })
30
+ ] }));
31
+ }
@@ -121,6 +121,9 @@ export const iconPaths = {
121
121
  ldmAttribute: (_jsx("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M3.79195 7.00251L6.53195 13.6414C6.53195 13.642 6.53223 13.6425 6.5325 13.6431C6.53278 13.6436 6.53306 13.6442 6.53306 13.6447C6.56084 13.7136 6.57417 13.7847 6.57417 13.8558C6.57417 13.9325 6.55862 14.0047 6.52861 14.0725C6.50195 14.1336 6.46528 14.1892 6.41973 14.2381C6.3675 14.2936 6.30417 14.337 6.23084 14.367C6.21417 14.3736 6.17195 14.387 6.15306 14.3903C6.1375 14.3936 6.04417 14.4081 6.0275 14.4081C5.9675 14.4081 5.90862 14.3981 5.85417 14.3781C5.80862 14.3614 5.76862 14.3414 5.72973 14.3181C5.68306 14.2881 5.64306 14.2536 5.60973 14.2158C5.56861 14.1703 5.53639 14.117 5.51417 14.057L4.7475 12.1936H1.82417L1.05417 14.0647C1.02528 14.1358 0.98306 14.1992 0.927504 14.2525C0.878615 14.2981 0.824171 14.3347 0.76306 14.3625C0.634171 14.4214 0.480838 14.4236 0.339727 14.367C0.267504 14.337 0.204171 14.2936 0.151949 14.2381C0.101949 14.1847 0.0652822 14.1236 0.0397266 14.0581C0.0163933 13.997 0.00305995 13.9325 0.000837725 13.8692C-0.00360672 13.7925 0.00972661 13.717 0.0386155 13.6447L2.77862 7.00474C2.79973 6.95363 2.82862 6.90696 2.86306 6.86474C2.89639 6.82363 2.93639 6.78696 2.98084 6.75807C3.0275 6.72474 3.07973 6.7014 3.13639 6.68585C3.23306 6.6614 3.33084 6.65918 3.43528 6.68585C3.49195 6.7014 3.54417 6.72474 3.59084 6.75807C3.63528 6.78696 3.67528 6.82363 3.70862 6.86474C3.74306 6.90696 3.77195 6.95363 3.79195 7.00251ZM3.28749 8.65697L2.28193 11.0903H4.29082L3.28749 8.65697ZM12.952 11.107C12.8831 10.9492 12.7931 10.807 12.6842 10.6825C12.5775 10.5603 12.4553 10.4558 12.3153 10.3681L12.222 10.3136C12.3131 10.1947 12.3931 10.0603 12.4564 9.91362C12.522 9.76473 12.5686 9.60029 12.5953 9.4214C12.6208 9.25695 12.6353 9.07695 12.6397 8.87362C12.6353 8.50584 12.5831 8.1814 12.4831 7.90917C12.3786 7.61917 12.2097 7.37695 11.9831 7.18918C11.7642 7.00695 11.4897 6.87251 11.1675 6.78806C10.8597 6.70806 10.4886 6.66695 10.0664 6.66695H8.14751C8.07085 6.66695 7.99974 6.68251 7.93751 6.71251C7.88085 6.74029 7.82862 6.77695 7.78418 6.82251C7.72974 6.87695 7.68974 6.94029 7.66529 7.0114C7.64529 7.06806 7.63307 7.12806 7.62529 7.21917L7.63196 13.8281C7.62307 13.9147 7.63751 14.0003 7.67307 14.0803C7.69862 14.1392 7.73196 14.1914 7.77085 14.2381C7.81751 14.2925 7.8764 14.337 7.9464 14.367C8.01085 14.3947 8.0764 14.4081 8.14307 14.4081H10.3275C10.5664 14.4081 10.7797 14.4003 10.9675 14.3858C11.1597 14.3703 11.3353 14.3492 11.4964 14.3203C11.6664 14.2914 11.8175 14.2503 11.9486 14.2014C12.082 14.1503 12.2053 14.0903 12.322 14.0192C12.4553 13.9347 12.5775 13.8303 12.6842 13.7092C12.7931 13.5847 12.8831 13.4425 12.952 13.2847C13.0164 13.1336 13.0675 12.9636 13.1008 12.7814C13.1342 12.6003 13.1497 12.4003 13.1464 12.1981C13.1497 11.9892 13.1342 11.7914 13.1008 11.6092C13.0675 11.427 13.0164 11.2581 12.952 11.107ZM11.5375 8.34141C11.5197 8.28585 11.4964 8.23585 11.4664 8.19363C11.4319 8.14363 11.393 8.1003 11.3519 8.06363C11.3008 8.01919 11.2364 7.97808 11.1653 7.94363C11.0864 7.90585 10.9953 7.87474 10.893 7.8503C10.783 7.82474 10.6608 7.80474 10.5264 7.79141C10.3875 7.77697 10.2342 7.7703 10.0664 7.7703H8.65971L8.65638 9.98252H10.0664C10.2342 9.98252 10.3875 9.97697 10.5264 9.96252C10.6608 9.94919 10.783 9.92919 10.893 9.90252C10.9953 9.87919 11.0864 9.84697 11.1653 9.80919C11.2364 9.77585 11.3008 9.73474 11.3542 9.68808C11.393 9.65252 11.4319 9.60919 11.4664 9.5603C11.4964 9.51697 11.5197 9.46808 11.5375 9.41252C11.5608 9.33919 11.5786 9.25919 11.593 9.1703C11.6075 9.08363 11.613 8.98808 11.6097 8.88585C11.613 8.76585 11.6075 8.6703 11.593 8.58252C11.5786 8.49474 11.5608 8.41363 11.5375 8.34141ZM10.3219 13.2992H8.65638L8.65971 11.087H10.2642C10.2674 11.087 10.2742 11.0864 10.2829 11.0856L10.293 11.0847C10.4044 11.0932 10.5154 11.0944 10.62 11.0956C10.7074 11.0966 10.7904 11.0975 10.8653 11.1025C11.0175 11.1125 11.1564 11.1292 11.2808 11.1503C11.3975 11.1714 11.4997 11.197 11.5864 11.227C11.6675 11.2559 11.7419 11.2892 11.7997 11.3225C11.8386 11.3481 11.8808 11.3814 11.923 11.4214C11.953 11.4481 11.9808 11.4892 12.0075 11.5425C12.0386 11.6092 12.0664 11.6959 12.0908 11.7992C12.1142 11.9014 12.1242 12.0325 12.1208 12.1992C12.1242 12.3581 12.1142 12.4903 12.0908 12.5914C12.0675 12.6947 12.0397 12.7803 12.0075 12.8447C11.9819 12.8981 11.9519 12.9403 11.9197 12.9714C11.8775 13.0114 11.8375 13.0436 11.8086 13.0625C11.7419 13.1014 11.6675 13.1359 11.5864 13.1636C11.4997 13.1947 11.3975 13.2203 11.2808 13.2403C11.1575 13.2625 11.0197 13.277 10.8675 13.2859C10.7097 13.2947 10.5275 13.2992 10.3219 13.2992ZM19.8175 13.3458C19.8275 13.2747 19.8242 13.2014 19.8086 13.1292C19.792 13.057 19.7642 12.9914 19.7353 12.947C19.6942 12.877 19.642 12.8214 19.5797 12.7825C19.5264 12.7492 19.4697 12.727 19.4131 12.7158C19.3553 12.707 19.2964 12.7081 19.2364 12.7203C19.1675 12.7358 19.1031 12.7703 19.0531 12.8147C18.9575 12.8925 18.852 12.9614 18.7375 13.0225C18.6231 13.0847 18.4975 13.1358 18.3631 13.1758C18.2242 13.217 18.0753 13.2481 17.9153 13.2681C17.5597 13.3125 17.1431 13.3092 16.802 13.2558C16.6186 13.227 16.4497 13.1836 16.2997 13.127C16.1486 13.0692 16.0108 12.9992 15.8875 12.9158C15.7653 12.8336 15.6553 12.7381 15.5642 12.637C15.472 12.5281 15.3875 12.4025 15.3153 12.2636C15.2431 12.1225 15.182 11.9647 15.132 11.7925C15.082 11.6214 15.0431 11.4281 15.0186 11.2181C14.9931 11.0081 14.9808 10.7781 14.9808 10.5347C14.9808 10.2914 14.9931 10.0614 15.0186 9.8514C15.0431 9.64251 15.082 9.44918 15.132 9.27696C15.182 9.10473 15.2431 8.94696 15.3153 8.80696C15.3864 8.66918 15.4697 8.54584 15.562 8.44029C15.6575 8.3314 15.7675 8.23473 15.8875 8.15362C16.0108 8.0714 16.1486 8.00029 16.2997 7.94251C16.4497 7.88584 16.6186 7.84251 16.802 7.81362C17.142 7.7614 17.5575 7.75584 17.9142 7.80362C18.0742 7.82584 18.2231 7.85807 18.3631 7.89918C18.4997 7.94029 18.6242 7.99029 18.7408 8.0514C18.852 8.10918 18.9564 8.17807 19.0586 8.26473C19.1097 8.30362 19.1653 8.3314 19.2231 8.34807C19.2875 8.36584 19.3508 8.36918 19.4131 8.35918C19.4753 8.34807 19.5342 8.32251 19.5897 8.28362C19.6442 8.24473 19.6897 8.19696 19.7353 8.12807C19.7686 8.07029 19.7931 8.00696 19.8086 7.94029C19.8242 7.86807 19.8275 7.79473 19.8175 7.72362C19.8075 7.65029 19.7842 7.58251 19.7486 7.51918C19.7197 7.46807 19.6842 7.4214 19.6242 7.36251C19.4842 7.24473 19.3286 7.1414 19.162 7.05362C18.9997 6.96918 18.8231 6.89584 18.6375 6.83807C18.4531 6.7814 18.2553 6.73807 18.0497 6.70918C17.6031 6.64696 17.0753 6.65362 16.6375 6.72584C16.3975 6.76584 16.1697 6.82696 15.9597 6.90807C15.7475 6.98918 15.5486 7.09362 15.3697 7.21696C15.1897 7.3414 15.0253 7.48918 14.8797 7.65473C14.7342 7.8214 14.6042 8.0114 14.4953 8.21918C14.3875 8.42362 14.2964 8.64918 14.2253 8.8914C14.1553 9.12918 14.1008 9.38807 14.0642 9.6614C14.0275 9.93473 14.0097 10.2281 14.0097 10.5347C14.0097 10.8414 14.0275 11.1358 14.0642 11.4081C14.1008 11.6803 14.1542 11.9403 14.2253 12.1814C14.2964 12.4236 14.3875 12.6503 14.4964 12.8547C14.6042 13.0592 14.7342 13.2481 14.8797 13.4147C15.0253 13.5814 15.1897 13.7281 15.3697 13.8525C15.5486 13.9758 15.7464 14.0814 15.9586 14.1636C16.1697 14.247 16.3975 14.3092 16.6375 14.3492C16.8753 14.3881 17.132 14.4081 17.4008 14.4081C17.6286 14.4081 17.8453 14.3947 18.0497 14.3658C18.2553 14.3381 18.4531 14.2936 18.6375 14.237C18.8231 14.1792 18.9997 14.1058 19.1631 14.0181C19.3286 13.9292 19.4842 13.8247 19.6275 13.7047C19.6764 13.6614 19.7175 13.6092 19.752 13.5481C19.7853 13.4847 19.8075 13.417 19.8175 13.3458Z" })),
122
122
  sharp: (_jsx("path", { d: "M16.084 6.12733C16.2402 6.12733 16.3704 6.17942 16.4746 6.28358C16.5918 6.38775 16.6504 6.51796 16.6504 6.67421C16.6504 6.83046 16.5918 6.96067 16.4746 7.06483C16.3704 7.169 16.2402 7.22108 16.084 7.22108H13.7988L12.8613 12.768H14.9902C15.1335 12.768 15.2572 12.8266 15.3613 12.9437C15.4785 13.0479 15.5371 13.1716 15.5371 13.3148C15.5371 13.4711 15.4785 13.6078 15.3613 13.725C15.2572 13.8292 15.1335 13.8812 14.9902 13.8812H12.6855L12.1973 16.7328C12.1842 16.876 12.1257 16.9932 12.0215 17.0844C11.9173 17.1625 11.8001 17.2016 11.6699 17.2016C11.6439 17.2016 11.6243 17.2016 11.6113 17.2016C11.5983 17.2016 11.5853 17.2016 11.5723 17.2016C11.416 17.1755 11.2923 17.1039 11.2012 16.9867C11.123 16.8565 11.097 16.7133 11.123 16.557L11.5527 13.8812H7.13867L6.66992 16.7328C6.64388 16.876 6.57878 16.9932 6.47461 17.0844C6.37044 17.1625 6.25326 17.2016 6.12305 17.2016C6.11003 17.2016 6.09049 17.2016 6.06445 17.2016C6.05143 17.2016 6.03841 17.2016 6.02539 17.2016C5.88216 17.1755 5.76497 17.1039 5.67383 16.9867C5.58268 16.8565 5.55013 16.7133 5.57617 16.557L6.02539 13.8812H3.89648C3.75326 13.8812 3.62305 13.8292 3.50586 13.725C3.40169 13.6078 3.34961 13.4711 3.34961 13.3148C3.34961 13.1716 3.40169 13.0479 3.50586 12.9437C3.62305 12.8266 3.75326 12.768 3.89648 12.768H6.20117L7.11914 7.22108H5.00977C4.85352 7.22108 4.72331 7.169 4.61914 7.06483C4.51497 6.96067 4.46289 6.83046 4.46289 6.67421C4.46289 6.51796 4.51497 6.38775 4.61914 6.28358C4.72331 6.17942 4.85352 6.12733 5.00977 6.12733H7.31445L7.7832 3.25624C7.80924 3.11301 7.88086 2.99582 7.99805 2.90468C8.12826 2.81353 8.27148 2.78098 8.42773 2.80702C8.58398 2.83306 8.70117 2.91119 8.7793 3.0414C8.87044 3.15858 8.90299 3.2953 8.87695 3.45155L8.42773 6.12733H12.8613L13.3301 3.25624C13.3561 3.11301 13.4277 2.99582 13.5449 2.90468C13.6751 2.81353 13.8184 2.78098 13.9746 2.80702C14.1178 2.83306 14.235 2.91119 14.3262 3.0414C14.4173 3.15858 14.4499 3.2953 14.4238 3.45155L13.9746 6.12733H16.084ZM11.748 12.768L12.666 7.22108H8.25195L7.33398 12.768H11.748Z" })),
123
123
  attribute: (_jsx("path", { d: "M15.752 16.1035C15.804 16.2467 15.804 16.3835 15.752 16.5137C15.6999 16.6439 15.6087 16.7415 15.4785 16.8066C15.4395 16.8197 15.4004 16.8327 15.3613 16.8457C15.3353 16.8457 15.3027 16.8457 15.2637 16.8457C15.1595 16.8457 15.0618 16.8197 14.9707 16.7676C14.8926 16.7025 14.8275 16.6178 14.7754 16.5137L13.1543 12.627H6.8457L5.22461 16.5137C5.17253 16.6439 5.07487 16.7415 4.93164 16.8066C4.80143 16.8587 4.67122 16.8587 4.54102 16.8066C4.41081 16.7415 4.31315 16.6439 4.24805 16.5137C4.19596 16.3835 4.19596 16.2467 4.24805 16.1035L9.52148 3.48633C9.56055 3.38216 9.62565 3.30404 9.7168 3.25195C9.80794 3.18685 9.9056 3.1543 10.0098 3.1543C10.1139 3.1543 10.2116 3.18685 10.3027 3.25195C10.3939 3.30404 10.459 3.38216 10.498 3.48633L15.752 16.1035ZM7.29492 11.5723H12.7246L10.0098 5.04883L7.29492 11.5723Z" })),
124
+ infoCircle: (_jsxs("g", { transform: "translate(2.05, 2.05) scale(1.4)", children: [
125
+ _jsx("path", { d: "M6.11719 9.48574H5.28281V4.48066H6.11719V9.48574Z" }), _jsx("path", { d: "M5.7 1.91426C5.87112 1.91426 6.01365 1.97469 6.12773 2.0959C6.24894 2.21711 6.30937 2.35965 6.30937 2.52363C6.30937 2.70187 6.25236 2.84784 6.13828 2.96191C6.0242 3.07599 5.87824 3.13301 5.7 3.13301C5.52176 3.13301 5.3758 3.07599 5.26172 2.96191C5.14764 2.84784 5.09063 2.70187 5.09062 2.52363C5.09062 2.35964 5.14764 2.21711 5.26172 2.0959C5.38291 1.97473 5.52891 1.91426 5.7 1.91426Z" }), _jsx("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M5.7 0C8.84802 0 11.4 2.55198 11.4 5.7C11.4 8.84802 8.84802 11.4 5.7 11.4C2.55198 11.4 0 8.84802 0 5.7C0 2.55198 2.55198 0 5.7 0ZM5.7 0.6C2.88335 0.6 0.6 2.88335 0.6 5.7C0.6 8.51665 2.88335 10.8 5.7 10.8C8.51665 10.8 10.8 8.51665 10.8 5.7C10.8 2.88335 8.51665 0.6 5.7 0.6Z" })
126
+ ] })),
124
127
  ldmKey: (_jsx("g", { transform: "translate(3.5, 3)", children: _jsx("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M7.81198 0.877486C8.98204 -0.29257 10.8855 -0.292214 12.0548 0.876865C13.225 2.04699 13.225 3.95021 12.0548 5.12033C11.03 6.14502 9.44298 6.27231 8.27872 5.50192L2.29696 11.4837L3.56976 12.7565C3.80395 12.9907 3.80395 13.3712 3.56976 13.6054C3.33556 13.8396 2.95501 13.8396 2.72081 13.6054L1.44802 12.3326L1.02417 12.7565C0.789979 12.9907 0.409424 12.9907 0.17523 12.7565C-0.0587544 12.5223 -0.0582723 12.1423 0.175852 11.9081L7.43039 4.6536C6.66042 3.48975 6.7873 1.90236 7.81198 0.877486ZM8.6603 1.72581C7.95885 2.4275 7.95883 3.56972 8.6603 4.27139C9.36197 4.97305 10.5041 4.97291 11.2059 4.27139C11.9076 3.56966 11.9076 2.42754 11.2059 1.72581C10.5041 1.02426 9.36198 1.02414 8.6603 1.72581Z" }) })),
125
128
  ldmLabel: (_jsxs("g", { transform: "translate(2.1, 2.1)", children: [
126
129
  _jsx("path", { d: "M8.07329 8.09529C8.26848 7.90013 8.58466 7.90026 8.77993 8.09529C8.9535 8.26886 8.97293 8.53851 8.83794 8.73338L8.77993 8.80281L5.78022 11.8025C5.58502 11.9976 5.26882 11.9975 5.07358 11.8025C4.90001 11.629 4.88058 11.3593 5.01557 11.1644L5.07358 11.095L8.07329 8.09529Z" }), _jsx("path", { d: "M7.57319 5.59568C7.76845 5.40042 8.08545 5.40042 8.28071 5.59568C8.45395 5.76925 8.47273 6.03815 8.33784 6.23289L8.28071 6.30232L4.28081 10.3022C4.08555 10.4975 3.76855 10.4975 3.57329 10.3022C3.3998 10.1287 3.38031 9.85897 3.51528 9.66414L3.57329 9.59558L7.57319 5.59568Z" }), _jsx("path", { d: "M11.9888 2.87722C12.541 2.87736 12.9881 3.32526 12.9881 3.87742C12.9881 4.42962 12.541 4.87748 11.9888 4.87761C11.4365 4.87761 10.9886 4.4297 10.9886 3.87742C10.9887 3.32518 11.4366 2.87722 11.9888 2.87722Z" }), _jsx("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M9.76255 0.00495774L14.7125 0.712477C14.9324 0.743938 15.1047 0.916279 15.1362 1.13611L15.8437 6.08611C15.8658 6.24181 15.8134 6.39941 15.7022 6.51062L6.50971 15.7022C6.31445 15.8975 5.99833 15.8975 5.80307 15.7022L0.146432 10.0456C-0.0488081 9.85032 -0.0488134 9.5342 0.146432 9.33894L9.33891 0.146462C9.45008 0.0353866 9.60696 -0.0171295 9.76255 0.00495774ZM1.20727 9.69226L6.15639 14.6414L14.8189 5.97976L14.1993 1.64939L9.86889 1.02976L1.20727 9.69226Z" })
@@ -0,0 +1,33 @@
1
+ import { type LabelRowKind } from "../UiLabelRow/UiLabelRow.js";
2
+ /**
3
+ * @internal
4
+ */
5
+ export interface IUiLabelChecklistRowProps {
6
+ /** Label text. */
7
+ label: string;
8
+ /** Determines the leading icon. Omit for a generic label icon. */
9
+ kind?: LabelRowKind;
10
+ /** Optional trailing suffix passed through to `UiLabelRow`. */
11
+ suffix?: string;
12
+ /** Whether the label is selected for inclusion. */
13
+ checked: boolean;
14
+ /**
15
+ * When true the row is rendered but cannot be toggled. Use for the primary
16
+ * key row, which is always included.
17
+ */
18
+ disabled?: boolean;
19
+ /** Fires when the user toggles the checkbox. */
20
+ onChange?: (checked: boolean) => void;
21
+ /** Test id forwarded to the root element. */
22
+ dataTestId?: string;
23
+ }
24
+ /**
25
+ * Selectable label row used inside the Labels picker. The row delegates row
26
+ * clicks to the inner checkbox and binds the checkbox's accessible name to
27
+ * the row's label span via `aria-labelledby` — instead of wrapping the row
28
+ * in a `<label>` element (which is invalid HTML around the row's `<div>`).
29
+ * `disabled` locks the row for the primary-key case.
30
+ *
31
+ * @internal
32
+ */
33
+ export declare function UiLabelChecklistRow({ label, kind, suffix, checked, disabled, onChange, dataTestId }: IUiLabelChecklistRowProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,26 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // (C) 2026 GoodData Corporation
3
+ import { useId } from "react";
4
+ import { UiCheckbox } from "../UiCheckbox/UiCheckbox.js";
5
+ import { UiLabelRow } from "../UiLabelRow/UiLabelRow.js";
6
+ /**
7
+ * Selectable label row used inside the Labels picker. The row delegates row
8
+ * clicks to the inner checkbox and binds the checkbox's accessible name to
9
+ * the row's label span via `aria-labelledby` — instead of wrapping the row
10
+ * in a `<label>` element (which is invalid HTML around the row's `<div>`).
11
+ * `disabled` locks the row for the primary-key case.
12
+ *
13
+ * @internal
14
+ */
15
+ export function UiLabelChecklistRow({ label, kind, suffix, checked, disabled = false, onChange, dataTestId, }) {
16
+ const inputId = useId();
17
+ const labelId = `${inputId}-label`;
18
+ const handleChange = (event) => {
19
+ onChange?.(event.target.checked);
20
+ };
21
+ // Row click delegates to the checkbox toggle. The native input also
22
+ // receives the click directly when the user clicks the checkbox itself —
23
+ // `preventDefault` on the input stops the row handler from re-toggling.
24
+ const handleRowClick = disabled ? undefined : () => onChange?.(!checked);
25
+ return (_jsx(UiLabelRow, { label: label, kind: kind, suffix: suffix, dataTestId: dataTestId, labelId: labelId, onClick: handleRowClick, leading: _jsx(UiCheckbox, { id: inputId, checked: checked, disabled: disabled, onChange: handleChange, preventDefault: true, accessibilityConfig: { ariaLabelledBy: labelId } }) }));
26
+ }
@@ -0,0 +1,52 @@
1
+ import { type ReactNode } from "react";
2
+ /**
3
+ * Display-form kind. Drives the icon only — the trailing suffix text is
4
+ * supplied by the caller via `suffix`. Omit for a regular label.
5
+ *
6
+ * @internal
7
+ */
8
+ export type LabelRowKind = "primary" | "default";
9
+ /**
10
+ * @internal
11
+ */
12
+ export interface IUiLabelRowProps {
13
+ /** Label text. */
14
+ label: string;
15
+ /** Determines the leading icon. Omit for a generic label icon. */
16
+ kind?: LabelRowKind;
17
+ /**
18
+ * Optional trailing suffix text rendered after the label (e.g.
19
+ * "Primary key", "Default label"). The kit primitive does not format
20
+ * domain-specific copy — callers translate and pass the string.
21
+ */
22
+ suffix?: string;
23
+ /**
24
+ * Optional content rendered before the kind icon. Used by
25
+ * `UiLabelChecklistRow` to inject the row's checkbox.
26
+ */
27
+ leading?: ReactNode;
28
+ /**
29
+ * Optional id set on the inner label `<span>` so an interactive ancestor
30
+ * can use it as `aria-labelledby` — e.g. `UiLabelChecklistRow` binds the
31
+ * row checkbox's accessible name to this id instead of wrapping the row
32
+ * in a `<label>` (which is invalid HTML around a `<div>`).
33
+ */
34
+ labelId?: string;
35
+ /**
36
+ * Optional row click handler. Used by `UiLabelChecklistRow` to delegate
37
+ * clicks anywhere on the row to the inner checkbox without nesting the
38
+ * row inside a `<label>`. Not fired when the click originates inside an
39
+ * interactive descendant.
40
+ */
41
+ onClick?: () => void;
42
+ /** Test id forwarded to the root element. */
43
+ dataTestId?: string;
44
+ }
45
+ /**
46
+ * Read-only label row — icon + label + optional caller-supplied suffix. Used
47
+ * inside the Labels list and (via `UiLabelChecklistRow`) the
48
+ * Labels picker.
49
+ *
50
+ * @internal
51
+ */
52
+ export declare function UiLabelRow({ label, kind, suffix, leading, labelId, onClick, dataTestId }: IUiLabelRowProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,18 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { bem } from "../@utils/bem.js";
3
+ import { UiIcon } from "../UiIcon/UiIcon.js";
4
+ const { b, e } = bem("gd-ui-kit-label-row");
5
+ const ICON_BY_KIND = {
6
+ primary: "ldmKey",
7
+ default: "ldmLabel",
8
+ };
9
+ /**
10
+ * Read-only label row — icon + label + optional caller-supplied suffix. Used
11
+ * inside the Labels list and (via `UiLabelChecklistRow`) the
12
+ * Labels picker.
13
+ *
14
+ * @internal
15
+ */
16
+ export function UiLabelRow({ label, kind, suffix, leading, labelId, onClick, dataTestId }) {
17
+ return (_jsxs("div", { className: b(), "data-testid": dataTestId, onClick: onClick, children: [leading ? _jsx("span", { className: e("leading"), children: leading }) : null, _jsx("span", { className: e("icon"), children: _jsx(UiIcon, { type: kind ? ICON_BY_KIND[kind] : "ldmLabel", size: 18, color: "warning" }) }), _jsx("span", { className: e("label"), id: labelId, children: label }), suffix ? _jsx("span", { className: e("suffix"), children: suffix }) : null] }));
18
+ }
@@ -0,0 +1,30 @@
1
+ import { type LabelRowKind } from "../UiLabelRow/UiLabelRow.js";
2
+ /**
3
+ * One label entry in the list.
4
+ *
5
+ * @internal
6
+ */
7
+ export interface IUiLabelsListItem {
8
+ /** Stable identifier for React keys. */
9
+ id: string;
10
+ /** Label text. */
11
+ label: string;
12
+ /** Drives the icon + suffix. Omit for a regular label. */
13
+ kind?: LabelRowKind;
14
+ }
15
+ /**
16
+ * @internal
17
+ */
18
+ export interface IUiLabelsListProps {
19
+ /** Label items to render in source order. */
20
+ items: ReadonlyArray<IUiLabelsListItem>;
21
+ /** Test id forwarded to the root element. */
22
+ dataTestId?: string;
23
+ }
24
+ /**
25
+ * Read-only list of labels — uppercase heading + N `UiLabelRow`s.
26
+ * Renders only the panel content; whoever needs a popover wraps it.
27
+ *
28
+ * @internal
29
+ */
30
+ export declare function UiLabelsList({ items, dataTestId }: IUiLabelsListProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,24 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // (C) 2026 GoodData Corporation
3
+ import { useIntl } from "react-intl";
4
+ import { olpLabelMessages } from "../../locales.js";
5
+ import { bem } from "../@utils/bem.js";
6
+ import { UiLabelRow } from "../UiLabelRow/UiLabelRow.js";
7
+ const { b, e } = bem("gd-ui-kit-labels-list");
8
+ /**
9
+ * Read-only list of labels — uppercase heading + N `UiLabelRow`s.
10
+ * Renders only the panel content; whoever needs a popover wraps it.
11
+ *
12
+ * @internal
13
+ */
14
+ export function UiLabelsList({ items, dataTestId }) {
15
+ const intl = useIntl();
16
+ const suffixFor = (kind) => {
17
+ if (!kind)
18
+ return undefined;
19
+ return intl.formatMessage(kind === "primary" ? olpLabelMessages.suffixPrimary : olpLabelMessages.suffixDefault);
20
+ };
21
+ return (_jsxs("div", { className: b(), "data-testid": dataTestId, children: [
22
+ _jsx("div", { className: e("heading"), children: intl.formatMessage(olpLabelMessages.listHeading) }), _jsx("div", { className: e("items"), role: "list", children: items.map((item) => (_jsx("div", { role: "listitem", children: _jsx(UiLabelRow, { label: item.label, kind: item.kind, suffix: suffixFor(item.kind) }) }, item.id))) })
23
+ ] }));
24
+ }
@@ -0,0 +1,63 @@
1
+ import { type ReactElement } from "react";
2
+ import { type LabelRowKind } from "../UiLabelRow/UiLabelRow.js";
3
+ /**
4
+ * One label entry in the picker.
5
+ *
6
+ * @internal
7
+ */
8
+ export interface IUiLabelsPickerItem {
9
+ /** Stable identifier — used as the React key and in selection state. */
10
+ id: string;
11
+ /** Label text. */
12
+ label: string;
13
+ /** Drives the icon + suffix. Omit for a regular label. */
14
+ kind?: LabelRowKind;
15
+ /**
16
+ * When true the item is rendered locked (checked + disabled). Used for
17
+ * the primary-key row, which is always included.
18
+ */
19
+ locked?: boolean;
20
+ }
21
+ /**
22
+ * Predicate the picker uses to decide whether an item is effectively selected:
23
+ * locked items always count as selected, otherwise membership in the staged
24
+ * `selected` set. Exported so consumers (e.g. the grantee row counter) can
25
+ * apply the same rule without re-encoding it.
26
+ *
27
+ * @internal
28
+ */
29
+ export declare const isLabelsPickerItemChecked: (item: IUiLabelsPickerItem, selectedIds: readonly string[]) => boolean;
30
+ /**
31
+ * @internal
32
+ */
33
+ export interface IUiLabelsPickerProps {
34
+ /** Element that opens the picker on click. */
35
+ anchor: ReactElement<any>;
36
+ /** All available label items, in source order. */
37
+ items: ReadonlyArray<IUiLabelsPickerItem>;
38
+ /**
39
+ * Initial set of selected item ids. Locked items are always treated as
40
+ * selected regardless of what's passed here. Consumers that need to
41
+ * reset the staged state when switching contexts (e.g. picking labels
42
+ * for a different grantee) should pass `key={contextId}` so React
43
+ * remounts the picker body.
44
+ */
45
+ defaultSelectedIds: ReadonlyArray<string>;
46
+ /**
47
+ * Fires when the user clicks Apply with the (locked-augmented) set of
48
+ * selected ids. The picker keeps its own staged state — the caller is
49
+ * notified only on commit.
50
+ */
51
+ onApply: (selectedIds: string[]) => void;
52
+ /** Test id forwarded to the picker body. */
53
+ dataTestId?: string;
54
+ }
55
+ /**
56
+ * Per-label picker popover. Anchored on a click target; stages selection
57
+ * internally and commits via `onApply`. Locked items are always included
58
+ * — at render time via {@link isLabelsPickerItemChecked} and again at
59
+ * commit via the locked-aware filter.
60
+ *
61
+ * @internal
62
+ */
63
+ export declare function UiLabelsPicker({ anchor, items, defaultSelectedIds, onApply, dataTestId }: IUiLabelsPickerProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,89 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // (C) 2026 GoodData Corporation
3
+ import { useCallback, useId, useMemo, useState } from "react";
4
+ import { useIntl } from "react-intl";
5
+ import { commonDialogMessages, olpLabelMessages } from "../../locales.js";
6
+ import { bem } from "../@utils/bem.js";
7
+ import { UiButton } from "../UiButton/UiButton.js";
8
+ import { UiLabelChecklistRow } from "../UiLabelChecklistRow/UiLabelChecklistRow.js";
9
+ import { UiPopover } from "../UiPopover/UiPopover.js";
10
+ const { b, e } = bem("gd-ui-kit-labels-picker");
11
+ /**
12
+ * Predicate the picker uses to decide whether an item is effectively selected:
13
+ * locked items always count as selected, otherwise membership in the staged
14
+ * `selected` set. Exported so consumers (e.g. the grantee row counter) can
15
+ * apply the same rule without re-encoding it.
16
+ *
17
+ * @internal
18
+ */
19
+ export const isLabelsPickerItemChecked = (item, selectedIds) => item.locked === true || selectedIds.includes(item.id);
20
+ /**
21
+ * Per-label picker popover. Anchored on a click target; stages selection
22
+ * internally and commits via `onApply`. Locked items are always included
23
+ * — at render time via {@link isLabelsPickerItemChecked} and again at
24
+ * commit via the locked-aware filter.
25
+ *
26
+ * @internal
27
+ */
28
+ export function UiLabelsPicker({ anchor, items, defaultSelectedIds, onApply, dataTestId, }) {
29
+ const intl = useIntl();
30
+ const groupId = useId();
31
+ return (_jsx(UiPopover, { anchor: anchor, anchorAccessibilityConfig: { ariaHaspopup: "dialog", ariaControls: groupId }, title: intl.formatMessage(olpLabelMessages.popoverTitle), width: 245, content: ({ onClose }) => (_jsx(PickerBody, { items: items, defaultSelectedIds: defaultSelectedIds, onApply: onApply, onClose: onClose, dataTestId: dataTestId, groupId: groupId })) }));
32
+ }
33
+ function PickerBody({ items, defaultSelectedIds, onApply, onClose, dataTestId, groupId }) {
34
+ const intl = useIntl();
35
+ // The user's staged toggles. We never merge locked ids into here — the
36
+ // locked-aware predicate handles that at render and at commit. The body
37
+ // only mounts when the popover opens, so this captures the initial
38
+ // selection once; parent rerenders don't disturb staged edits.
39
+ const [selected, setSelected] = useState(() => [...defaultSelectedIds]);
40
+ const toggle = useCallback((id, next) => {
41
+ setSelected((prev) => next ? (prev.includes(id) ? prev : [...prev, id]) : prev.filter((x) => x !== id));
42
+ }, []);
43
+ const handleApply = useCallback(() => {
44
+ onApply(items.filter((item) => isLabelsPickerItemChecked(item, selected)).map((item) => item.id));
45
+ onClose();
46
+ }, [items, selected, onApply, onClose]);
47
+ const isDirty = useMemo(() => {
48
+ // Compare against the locked-aware initial set so re-Apply on an
49
+ // unchanged selection stays disabled even when defaultSelectedIds
50
+ // omits a locked id (the picker silently includes it).
51
+ const initial = new Set();
52
+ for (const id of defaultSelectedIds)
53
+ initial.add(id);
54
+ for (const item of items)
55
+ if (item.locked)
56
+ initial.add(item.id);
57
+ const current = new Set();
58
+ for (const item of items) {
59
+ if (isLabelsPickerItemChecked(item, selected))
60
+ current.add(item.id);
61
+ }
62
+ if (initial.size !== current.size)
63
+ return true;
64
+ for (const id of initial) {
65
+ if (!current.has(id))
66
+ return true;
67
+ }
68
+ return false;
69
+ }, [items, defaultSelectedIds, selected]);
70
+ const handleKeyDown = (event) => {
71
+ // Enter commits when something has changed — scoped to the items
72
+ // group only so Enter on the footer Cancel/Apply buttons keeps its
73
+ // native semantics.
74
+ if (event.key === "Enter" && isDirty) {
75
+ event.preventDefault();
76
+ handleApply();
77
+ }
78
+ };
79
+ const suffixFor = (kind) => {
80
+ if (!kind)
81
+ return undefined;
82
+ return intl.formatMessage(kind === "primary" ? olpLabelMessages.suffixPrimary : olpLabelMessages.suffixDefault);
83
+ };
84
+ return (_jsxs("div", { className: b(), "data-testid": dataTestId, children: [
85
+ _jsx("div", { id: groupId, className: e("items"), role: "group", "aria-label": intl.formatMessage(olpLabelMessages.popoverTitle), onKeyDown: handleKeyDown, children: items.map((item) => (_jsx(UiLabelChecklistRow, { label: item.label, kind: item.kind, suffix: suffixFor(item.kind), checked: isLabelsPickerItemChecked(item, selected), disabled: item.locked, onChange: (next) => toggle(item.id, next) }, item.id))) }), _jsxs("div", { className: e("actions"), children: [
86
+ _jsx(UiButton, { variant: "secondary", size: "small", label: intl.formatMessage(commonDialogMessages.cancel), onClick: onClose }), _jsx(UiButton, { variant: "primary", size: "small", label: intl.formatMessage(commonDialogMessages.apply), onClick: handleApply, isDisabled: !isDirty })
87
+ ] })
88
+ ] }));
89
+ }
@@ -0,0 +1,43 @@
1
+ import { type ReactElement } from "react";
2
+ /**
3
+ * Permission level offered by the menu.
4
+ *
5
+ * @internal
6
+ */
7
+ export type PermissionMenuLevel = "VIEW" | "SHARE";
8
+ /**
9
+ * @internal
10
+ */
11
+ export interface IUiPermissionMenuProps {
12
+ /** Element that opens the menu on click. */
13
+ anchor: ReactElement<any>;
14
+ /** Currently selected permission level — drives `aria-checked`. */
15
+ selectedLevel?: PermissionMenuLevel;
16
+ /** Fires when the user picks a permission level. */
17
+ onPermissionChange: (level: PermissionMenuLevel) => void;
18
+ /** Fires when the user picks Transfer ownership. */
19
+ onTransferOwnership?: () => void;
20
+ /**
21
+ * Fires when the user picks the Labels entry. Display the count via
22
+ * `labelsCounter`.
23
+ */
24
+ onLabelsClick?: () => void;
25
+ /**
26
+ * Counter shown next to the Labels row (e.g. `"4/4"`). Hidden
27
+ * if omitted.
28
+ */
29
+ labelsCounter?: string;
30
+ /** Fires when the user picks Remove access. */
31
+ onRemoveAccess?: () => void;
32
+ /** Test id forwarded to the menu body. */
33
+ dataTestId?: string;
34
+ }
35
+ /**
36
+ * Per-grantee permission popover. Renders a fixed set of rows — two
37
+ * permission levels (Can view & share / Can view), an optional divider,
38
+ * and optional Transfer ownership / Labels / Remove access action rows.
39
+ * Each level row carries an `infoCircle` tooltip.
40
+ *
41
+ * @internal
42
+ */
43
+ export declare function UiPermissionMenu({ anchor, selectedLevel, onPermissionChange, onTransferOwnership, onLabelsClick, labelsCounter, onRemoveAccess, dataTestId }: IUiPermissionMenuProps): import("react/jsx-runtime").JSX.Element;