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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/esm/@ui/UiGranteeRowControls/UiGranteeRowControls.d.ts +5 -2
  2. package/esm/@ui/UiGranteeRowControls/UiGranteeRowControls.d.ts.map +1 -1
  3. package/esm/@ui/UiGranteeRowControls/UiGranteeRowControls.js +16 -4
  4. package/esm/@ui/UiMenu/UiMenu.d.ts.map +1 -1
  5. package/esm/@ui/UiMenu/UiMenu.js +1 -1
  6. package/esm/@ui/UiMoreOptionsMenu/UiMoreOptionsMenu.d.ts +10 -3
  7. package/esm/@ui/UiMoreOptionsMenu/UiMoreOptionsMenu.d.ts.map +1 -1
  8. package/esm/@ui/UiMoreOptionsMenu/UiMoreOptionsMenu.js +18 -4
  9. package/esm/@ui/UiPermissionMenu/UiPermissionMenu.d.ts +3 -1
  10. package/esm/@ui/UiPermissionMenu/UiPermissionMenu.d.ts.map +1 -1
  11. package/esm/@ui/UiPopover/UiPopover.d.ts.map +1 -1
  12. package/esm/@ui/UiPopover/UiPopover.js +1 -1
  13. package/esm/@ui/UiTags/UiTags.d.ts.map +1 -1
  14. package/esm/@ui/UiTags/UiTags.js +3 -4
  15. package/esm/Dropdown/Dropdown.d.ts +1 -1
  16. package/esm/Dropdown/Dropdown.d.ts.map +1 -1
  17. package/esm/List/LegacyList.d.ts +1 -1
  18. package/esm/List/LegacyList.d.ts.map +1 -1
  19. package/esm/List/LegacyList.js +103 -55
  20. package/esm/List/List.d.ts +1 -1
  21. package/esm/List/List.d.ts.map +1 -1
  22. package/esm/List/List.js +95 -53
  23. package/esm/Overlay/Overlay.js +2 -2
  24. package/esm/locales.d.ts +3 -0
  25. package/esm/locales.d.ts.map +1 -1
  26. package/esm/locales.js +1 -0
  27. package/esm/sdk-ui-kit.d.ts +20 -9
  28. package/package.json +12 -13
  29. package/src/@ui/UiGranteeRowControls/UiGranteeRowControls.scss +8 -0
  30. package/src/@ui/UiLabelsChecklist/UiLabelsChecklist.scss +11 -0
  31. package/src/@ui/UiMenu/UiMenu.scss +9 -0
  32. package/styles/css/insightList.css +1 -3
  33. package/styles/css/insightList.css.map +1 -1
  34. package/styles/css/list.css +14 -655
  35. package/styles/css/list.css.map +1 -1
  36. package/styles/css/main.css +33 -658
  37. package/styles/css/main.css.map +1 -1
  38. package/styles/css/menu.css +14 -655
  39. package/styles/css/menu.css.map +1 -1
  40. package/styles/scss/insightList.scss +1 -3
  41. package/styles/scss/list.scss +15 -65
package/esm/List/List.js CHANGED
@@ -1,87 +1,129 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  // (C) 2007-2026 GoodData Corporation
3
- import { useCallback, useEffect, useMemo } from "react";
3
+ import { useCallback, useEffect, useMemo, useRef, } from "react";
4
+ import { useVirtualizer } from "@tanstack/react-virtual";
4
5
  import cx from "classnames";
5
- import { Cell, Column, Table } from "fixed-data-table-2";
6
- import { DROPDOWN_BODY_CLASS } from "../Dropdown/Dropdown.js";
7
6
  // it configures max number of records due to
8
7
  // inefficiency with virtual memory allocation
9
8
  // that causes application crash (TNT-787)
10
9
  const MAX_NUMBER_OF_ROWS = 1000000;
11
- const BORDER_HEIGHT = 1;
12
10
  const HALF_ROW = 0.5;
11
+ // delay (ms) after the last scroll event before onScrollEnd is fired
12
+ const SCROLL_END_DELAY = 100;
13
13
  export const MAX_VISIBLE_ITEMS_COUNT = 10;
14
14
  export const DEFAULT_ITEM_HEIGHT = 28;
15
15
  /**
16
16
  * @internal
17
17
  */
18
- export function List({ id, className = "", compensateBorder = true, width = 200, height, maxHeight, items = [], itemsCount = items.length, itemHeight = DEFAULT_ITEM_HEIGHT, itemHeightGetter = null, maxVisibleItemsCount = MAX_VISIBLE_ITEMS_COUNT, renderItem, onScrollStart, onScrollEnd, scrollToItem, scrollDirection, accessibilityConfig, }) {
18
+ export function List({ id, className = "", width = 200, height, maxHeight, items = [], itemsCount = items.length, itemHeight = DEFAULT_ITEM_HEIGHT, itemHeightGetter = null, maxVisibleItemsCount = MAX_VISIBLE_ITEMS_COUNT, renderItem, onScrollStart, onScrollEnd, scrollToItem, scrollDirection, accessibilityConfig, }) {
19
+ const scrollContainerRef = useRef(null);
20
+ const rowsCount = Math.min(itemsCount, MAX_NUMBER_OF_ROWS);
21
+ // when there are more items than fit, show half of the next row to hint scrollability
19
22
  const currentItemsCount = itemsCount > maxVisibleItemsCount ? maxVisibleItemsCount + HALF_ROW : itemsCount;
20
23
  const listHeight = height || currentItemsCount * itemHeight;
21
- const listHeightWithBorder = compensateBorder ? listHeight + BORDER_HEIGHT * 2 : listHeight;
24
+ // the visible viewport height; the list is prop-sized so this is deterministic
25
+ const viewportHeight = maxHeight ? Math.min(maxHeight, listHeight) : listHeight;
26
+ const estimateSize = useCallback((index) => (itemHeightGetter ? itemHeightGetter(index) : itemHeight), [itemHeightGetter, itemHeight]);
27
+ // Report the viewport size to the virtualizer from the known props, falling back from a real
28
+ // measurement when the DOM has no layout (e.g. jsdom in tests). Keeps virtualization correct
29
+ // without depending on layout being available.
30
+ const observeElementRect = useCallback((_instance, cb) => {
31
+ const el = scrollContainerRef.current;
32
+ if (!el) {
33
+ return undefined;
34
+ }
35
+ const report = () => {
36
+ const rect = el.getBoundingClientRect();
37
+ cb({ width: rect.width || width, height: rect.height || viewportHeight });
38
+ };
39
+ report();
40
+ if (typeof ResizeObserver === "undefined") {
41
+ return undefined;
42
+ }
43
+ const resizeObserver = new ResizeObserver(report);
44
+ resizeObserver.observe(el);
45
+ return () => resizeObserver.disconnect();
46
+ }, [width, viewportHeight]);
47
+ const rowVirtualizer = useVirtualizer({
48
+ count: rowsCount,
49
+ getScrollElement: () => scrollContainerRef.current,
50
+ estimateSize,
51
+ observeElementRect,
52
+ overscan: 5,
53
+ });
54
+ const virtualItems = rowVirtualizer.getVirtualItems();
55
+ // scroll the requested item into view (preserves the legacy +scrollDirection offset)
22
56
  const scrollToItemRowIndex = useMemo(() => {
23
57
  if (!scrollToItem) {
24
58
  return undefined;
25
59
  }
26
- return items.indexOf(scrollToItem) + (scrollDirection ?? 1);
60
+ const index = items.indexOf(scrollToItem);
61
+ if (index < 0) {
62
+ return undefined;
63
+ }
64
+ return index + (scrollDirection ?? 1);
27
65
  }, [items, scrollToItem, scrollDirection]);
66
+ useEffect(() => {
67
+ if (scrollToItemRowIndex === undefined || rowsCount === 0) {
68
+ return;
69
+ }
70
+ rowVirtualizer.scrollToIndex(Math.min(Math.max(scrollToItemRowIndex, 0), rowsCount - 1));
71
+ // rowVirtualizer identity is stable; intentionally only react to the target index changing
72
+ // eslint-disable-next-line react-hooks/exhaustive-deps
73
+ }, [scrollToItemRowIndex, rowsCount]);
74
+ // converts vertical scroll position to the [first, last] visible item index range,
75
+ // matching the legacy fixed-data-table-based behavior consumers (e.g. AsyncList) depend on
28
76
  const getVisibleScrollRange = useCallback((scrollY) => {
29
77
  const rowIndex = Math.floor(scrollY / itemHeight);
30
78
  const visibleRange = Math.ceil(listHeight / itemHeight);
31
79
  return [rowIndex, rowIndex + visibleRange];
32
80
  }, [itemHeight, listHeight]);
33
- const handleScrollStart = useCallback((_, y) => {
34
- if (onScrollStart) {
35
- const [startIndex, endIndex] = getVisibleScrollRange(y);
36
- onScrollStart(startIndex, endIndex);
81
+ const isScrollingRef = useRef(false);
82
+ const scrollEndTimerRef = useRef(undefined);
83
+ const handleScroll = useCallback((event) => {
84
+ const scrollY = event.currentTarget.scrollTop;
85
+ const [startIndex, endIndex] = getVisibleScrollRange(scrollY);
86
+ if (!isScrollingRef.current) {
87
+ isScrollingRef.current = true;
88
+ onScrollStart?.(startIndex, endIndex);
37
89
  }
38
- }, [onScrollStart, getVisibleScrollRange]);
39
- const handleScrollEnd = useCallback((_, y) => {
40
- if (onScrollEnd) {
41
- const [startIndex, endIndex] = getVisibleScrollRange(y);
42
- onScrollEnd(startIndex, endIndex);
90
+ if (scrollEndTimerRef.current) {
91
+ clearTimeout(scrollEndTimerRef.current);
43
92
  }
44
- }, [onScrollEnd, getVisibleScrollRange]);
93
+ scrollEndTimerRef.current = setTimeout(() => {
94
+ isScrollingRef.current = false;
95
+ onScrollEnd?.(startIndex, endIndex);
96
+ }, SCROLL_END_DELAY);
97
+ }, [getVisibleScrollRange, onScrollStart, onScrollEnd]);
98
+ // clear any pending scroll-end timer on unmount so callbacks don't fire on an unmounted tree
45
99
  useEffect(() => {
46
100
  return () => {
47
- enablePageScrolling();
101
+ if (scrollEndTimerRef.current) {
102
+ clearTimeout(scrollEndTimerRef.current);
103
+ }
48
104
  };
49
105
  }, []);
50
- const styles = useMemo(() => {
51
- return {
52
- width,
53
- };
54
- }, [width]);
55
- return (_jsx("div", { id: id, "data-testid": "gd-list", className: cx("gd-list gd-infinite-list", className), style: styles, onMouseOver: disablePageScrolling, onMouseOut: enablePageScrolling, role: accessibilityConfig?.role, "aria-labelledby": accessibilityConfig?.ariaLabelledBy, children: _jsx(Table, { width: width,
56
- // compensates for https://github.com/facebook/fixed-data-table/blob/5373535d98b08b270edd84d7ce12833a4478c6b6/src/FixedDataTableNew.react.js#L872
57
- height: maxHeight ? undefined : listHeightWithBorder, maxHeight: maxHeight, headerHeight: 0, rowHeight: itemHeight, rowHeightGetter: itemHeightGetter, rowsCount: Math.min(itemsCount, MAX_NUMBER_OF_ROWS), onScrollStart: handleScrollStart, onScrollEnd: handleScrollEnd, scrollToRow: scrollToItemRowIndex, touchScrollEnabled: isTouchDevice(), keyboardScrollEnabled: true, children: _jsx(Column, { flexGrow: 1, width: 1, cell: ({ columnKey, height, width, rowIndex, }) => {
58
- const item = items[rowIndex];
59
- return (_jsx(Cell, { width: width, height: height, rowIndex: rowIndex, columnKey: columnKey, children: renderItem({
60
- rowIndex,
106
+ const containerStyle = useMemo(() => ({
107
+ width,
108
+ height: maxHeight ? undefined : listHeight,
109
+ maxHeight,
110
+ }), [width, maxHeight, listHeight]);
111
+ return (_jsx("div", { id: id, "data-testid": "gd-list", className: cx("gd-list gd-infinite-list", className), style: { width }, role: accessibilityConfig?.role, "aria-labelledby": accessibilityConfig?.ariaLabelledBy, children: _jsx("div", { ref: scrollContainerRef, className: "gd-infinite-list-scroll-container", style: containerStyle, onScroll: handleScroll, children: _jsx("div", { className: "gd-infinite-list-sizer", style: { height: rowVirtualizer.getTotalSize(), width: "100%", position: "relative" }, children: virtualItems.map((virtualRow) => {
112
+ const item = items[virtualRow.index];
113
+ return (_jsx("div", { className: "gd-infinite-list-item", style: {
114
+ position: "absolute",
115
+ top: 0,
116
+ left: 0,
117
+ width: "100%",
118
+ height: virtualRow.size,
119
+ transform: `translateY(${virtualRow.start}px)`,
120
+ }, children: renderItem({
121
+ rowIndex: virtualRow.index,
61
122
  item,
62
123
  width,
63
- height,
64
- isFirst: rowIndex === 0,
65
- isLast: rowIndex === itemsCount - 1,
66
- }) }));
67
- } }) }) }));
68
- }
69
- function preventDefault(e) {
70
- const wheelEvent = e;
71
- const target = wheelEvent.target;
72
- const isDropdownBodyScroll = target?.closest?.(`.${DROPDOWN_BODY_CLASS}`);
73
- if (isDropdownBodyScroll) {
74
- // allow to scroll another lists placed in dropdowns (e.g. in Filter Groups)
75
- return;
76
- }
77
- e.preventDefault();
78
- }
79
- function isTouchDevice() {
80
- return "ontouchstart" in document.documentElement;
81
- }
82
- function disablePageScrolling() {
83
- document.body.addEventListener("wheel", preventDefault, { passive: false });
84
- }
85
- function enablePageScrolling() {
86
- document.body.removeEventListener("wheel", preventDefault);
124
+ height: virtualRow.size,
125
+ isFirst: virtualRow.index === 0,
126
+ isLast: virtualRow.index === itemsCount - 1,
127
+ }) }, virtualRow.key));
128
+ }) }) }) }));
87
129
  }
@@ -50,8 +50,8 @@ function alignExceedsThreshold(firstAlignment, secondAlignment) {
50
50
  * Stops React synthetic event propagation but re-dispatches native events
51
51
  * to document and documentElement so that:
52
52
  * - Other Overlays can detect outside clicks and close themselves
53
- * - Libraries listening on document.documentElement (like fixed-data-table-2's
54
- * DOMMouseMoveTracker for scrollbar drag release) receive the events
53
+ * - Libraries listening on document / document.documentElement (e.g. for drag/scroll
54
+ * release tracking) still receive the events
55
55
  */
56
56
  const stopPropagation = (e) => {
57
57
  e.stopPropagation();
package/esm/locales.d.ts CHANGED
@@ -175,6 +175,9 @@ export declare const olpPermissionMessages: {
175
175
  canView: {
176
176
  id: string;
177
177
  };
178
+ canEdit: {
179
+ id: string;
180
+ };
178
181
  canViewAndShareTooltip: {
179
182
  id: string;
180
183
  };
@@ -1 +1 @@
1
- {"version":3,"file":"locales.d.ts","sourceRoot":"","sources":["../src/locales.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,oBAAoB;;;;CAE/B,CAAC;AAEH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;CAMpC,CAAC;AAEH,eAAO,MAAM,+BAA+B;;;;;;;CAG1C,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;;;;;CAG/B,CAAC;AAEH,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;CAK1C,CAAC;AAEH,eAAO,MAAM,iCAAiC;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgB5C,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;;;;;;;;CAI/B,CAAC;AAEH,eAAO,MAAM,wBAAwB;;;;;;;CAGnC,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;;CAEhC,CAAC;AAEH,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;CAKvC,CAAC;AAEH,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;CAMtC,CAAC;AAEH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;CAMnC,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;CAM3B,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAchC,CAAC;AAEH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;CAMjC,CAAC;AAEH,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;CAMvC,CAAC"}
1
+ {"version":3,"file":"locales.d.ts","sourceRoot":"","sources":["../src/locales.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,oBAAoB;;;;CAE/B,CAAC;AAEH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;CAMpC,CAAC;AAEH,eAAO,MAAM,+BAA+B;;;;;;;CAG1C,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;;;;;CAG/B,CAAC;AAEH,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;CAK1C,CAAC;AAEH,eAAO,MAAM,iCAAiC;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgB5C,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;;;;;;;;CAI/B,CAAC;AAEH,eAAO,MAAM,wBAAwB;;;;;;;CAGnC,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;;CAEhC,CAAC;AAEH,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;CAKvC,CAAC;AAEH,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;CAMtC,CAAC;AAEH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;CAMnC,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;CAM3B,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAehC,CAAC;AAEH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;CAMjC,CAAC;AAEH,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;CAMvC,CAAC"}
package/esm/locales.js CHANGED
@@ -84,6 +84,7 @@ export const olpLabelMessages = defineMessages({
84
84
  export const olpPermissionMessages = defineMessages({
85
85
  canViewAndShare: { id: "shareDialog.share.granular.grantee.permission.share" },
86
86
  canView: { id: "shareDialog.share.granular.grantee.permission.view" },
87
+ canEdit: { id: "shareDialog.olp.permission.edit" },
87
88
  canViewAndShareTooltip: { id: "shareDialog.olp.permission.tooltip.share" },
88
89
  canViewTooltip: { id: "shareDialog.olp.permission.tooltip.view" },
89
90
  transferOwnership: { id: "shareDialog.olp.permission.transferOwnership" },
@@ -3065,7 +3065,7 @@ export declare interface IDropdownButtonRenderProps {
3065
3065
  /**
3066
3066
  * Props supporting accessibility that can be passed down to a <Button/>
3067
3067
  */
3068
- accessibilityConfig: Pick<IButtonAccessibilityConfig, "role" | "isExpanded" | "popupId" | "ariaLabel" | "ariaDescribedBy" | "ariaControls" | "ariaExpanded" | "ariaHaspopup" | "ariaPressed">;
3068
+ accessibilityConfig: Pick<IButtonAccessibilityConfig, "role" | "isExpanded" | "popupId" | "popupType" | "ariaLabel" | "ariaDescribedBy" | "ariaControls" | "ariaExpanded" | "ariaHaspopup" | "ariaPressed">;
3069
3069
  }
3070
3070
 
3071
3071
  /**
@@ -7371,13 +7371,15 @@ export declare interface IUiGranteeRowControlsProps {
7371
7371
  /** Locked items are always treated as selected. */
7372
7372
  labels: ReadonlyArray<IUiLabelsChecklistItem>;
7373
7373
  selectedLabelIds: ReadonlyArray<string>;
7374
- permissionLevel: PermissionMenuLevel;
7374
+ /** The level to display. `EDIT` renders read-only; VIEW/SHARE are selectable. */
7375
+ permissionLevel: AccessGranularPermission;
7375
7376
  /**
7376
7377
  * Set only when the grantee inherits a higher permission than `permissionLevel`
7377
7378
  * (e.g. from a group); drives the warning badge. Undefined when not elevated.
7378
7379
  */
7379
- effectivePermission?: PermissionMenuLevel;
7380
+ effectivePermission?: AccessGranularPermission;
7380
7381
  onLabelsChange: (selectedIds: string[]) => void;
7382
+ /** Fires only for selectable rows (VIEW/SHARE); EDIT rows have no level control. */
7381
7383
  onPermissionChange: (level: PermissionMenuLevel) => void;
7382
7384
  onTransferOwnership?: () => void;
7383
7385
  onRemoveAccess?: () => void;
@@ -7975,6 +7977,11 @@ export declare interface IUiMoreOptionsMenuProps {
7975
7977
  onLabelsChange?: (selectedIds: string[]) => void;
7976
7978
  /** Omit to hide the row (Transfer ownership is gated until wired). */
7977
7979
  onTransferOwnership?: () => void;
7980
+ /**
7981
+ * Omit to hide the row. Used for read-only permission rows (e.g. EDIT), whose
7982
+ * level control has no dropdown to host Remove access — so the action lives here.
7983
+ */
7984
+ onRemoveAccess?: () => void;
7978
7985
  isDisabled?: boolean;
7979
7986
  dataTestId?: string;
7980
7987
  }
@@ -9246,7 +9253,7 @@ export declare function LegacyInvertableList<T>({ className, filteredItemsCount,
9246
9253
  * @deprecated This component is deprecated use List instead
9247
9254
  * @internal
9248
9255
  */
9249
- export declare function LegacyList({ className, onScroll, onScrollStart, onSelect, width, height, itemHeight, itemHeightGetter, compensateBorder, scrollToSelected, dataSource, rowItem }: ILegacyListProps): JSX.Element;
9256
+ export declare function LegacyList({ className, onScroll, onScrollStart, onSelect, width, height, itemHeight, itemHeightGetter, scrollToSelected, dataSource, rowItem }: ILegacyListProps): JSX.Element;
9250
9257
 
9251
9258
  /**
9252
9259
  * @internal
@@ -9286,7 +9293,7 @@ export declare type LevelTypesUnion<Levels extends unknown[]> = Levels[number];
9286
9293
  /**
9287
9294
  * @internal
9288
9295
  */
9289
- export declare function List<T>({ id, className, compensateBorder, width, height, maxHeight, items, itemsCount, itemHeight, itemHeightGetter, maxVisibleItemsCount, renderItem, onScrollStart, onScrollEnd, scrollToItem, scrollDirection, accessibilityConfig }: IListProps<T>): ReactElement;
9296
+ export declare function List<T>({ id, className, width, height, maxHeight, items, itemsCount, itemHeight, itemHeightGetter, maxVisibleItemsCount, renderItem, onScrollStart, onScrollEnd, scrollToItem, scrollDirection, accessibilityConfig }: IListProps<T>): ReactElement;
9290
9297
 
9291
9298
  /**
9292
9299
  * @internal
@@ -9649,7 +9656,9 @@ export declare function ParameterControlDropdown({ name, value, resetValue, cons
9649
9656
  export declare function ParameterPicker({ parameters, excludedKeys, isLoading, maxListHeight, onAdd, onCancel }: IParameterPickerProps): JSX.Element;
9650
9657
 
9651
9658
  /**
9652
- * Permission level offered by the menu.
9659
+ * Selectable permission level. The menu and the add-grantee picker only ever
9660
+ * assign VIEW or SHARE — EDIT is shown as a read-only row (via the model's
9661
+ * `AccessGranularPermission`) and is never selectable from the UI.
9653
9662
  *
9654
9663
  * @internal
9655
9664
  */
@@ -10785,12 +10794,14 @@ export declare function UiMenu<T extends IUiMenuItemData = object, M extends obj
10785
10794
  export declare function UiModalDialog({ children, isOpen, onClose, width, accessibilityConfig, dataTestId }: IUiModalDialogProps): JSX.Element | null;
10786
10795
 
10787
10796
  /**
10788
- * Per-grantee "⋯" menu: "Manage labels access" (drills into {@link UiLabelsChecklist})
10789
- * and "Transfer ownership". Each row shows only when its data/handler is given.
10797
+ * Per-grantee "⋯" menu: "Manage labels access" (drills into {@link UiLabelsChecklist}),
10798
+ * "Transfer ownership" and "Remove access". Each row shows only when its data/handler
10799
+ * is given. Remove access appears here for read-only permission rows whose level control
10800
+ * has no dropdown to host it.
10790
10801
  *
10791
10802
  * @internal
10792
10803
  */
10793
- export declare function UiMoreOptionsMenu({ labels, selectedLabelIds, onLabelsChange, onTransferOwnership, isDisabled, dataTestId }: IUiMoreOptionsMenuProps): JSX.Element;
10804
+ export declare function UiMoreOptionsMenu({ labels, selectedLabelIds, onLabelsChange, onTransferOwnership, onRemoveAccess, isDisabled, dataTestId }: IUiMoreOptionsMenuProps): JSX.Element;
10794
10805
 
10795
10806
  /**
10796
10807
  * @internal
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gooddata/sdk-ui-kit",
3
- "version": "11.43.0-alpha.3",
3
+ "version": "11.43.0-alpha.5",
4
4
  "description": "GoodData SDK - UI Building Components",
5
5
  "license": "MIT",
6
6
  "author": "GoodData Corporation",
@@ -56,7 +56,6 @@
56
56
  "date-fns-tz": "^3.2.0",
57
57
  "debounce-promise": "^3.1.2",
58
58
  "default-import": "1.1.5",
59
- "fixed-data-table-2": "2.0.22",
60
59
  "lodash-es": "^4.17.23",
61
60
  "moment": "^2.29.4",
62
61
  "react-content-loader": "^7.1.1",
@@ -75,11 +74,11 @@
75
74
  "tslib": "2.8.1",
76
75
  "unified": "^11.0.5",
77
76
  "uuid": "11.1.1",
78
- "@gooddata/sdk-backend-spi": "11.43.0-alpha.3",
79
- "@gooddata/sdk-ui": "11.43.0-alpha.3",
80
- "@gooddata/sdk-ui-theme-provider": "11.43.0-alpha.3",
81
- "@gooddata/util": "11.43.0-alpha.3",
82
- "@gooddata/sdk-model": "11.43.0-alpha.3"
77
+ "@gooddata/sdk-backend-spi": "11.43.0-alpha.5",
78
+ "@gooddata/sdk-ui": "11.43.0-alpha.5",
79
+ "@gooddata/sdk-model": "11.43.0-alpha.5",
80
+ "@gooddata/sdk-ui-theme-provider": "11.43.0-alpha.5",
81
+ "@gooddata/util": "11.43.0-alpha.5"
83
82
  },
84
83
  "devDependencies": {
85
84
  "@microsoft/api-documenter": "^7.17.0",
@@ -128,11 +127,11 @@
128
127
  "typescript": "5.9.3",
129
128
  "vitest": "4.1.8",
130
129
  "vitest-dom": "0.1.1",
131
- "@gooddata/eslint-config": "11.43.0-alpha.3",
132
- "@gooddata/oxlint-config": "11.43.0-alpha.3",
133
- "@gooddata/reference-workspace": "11.43.0-alpha.3",
134
- "@gooddata/stylelint-config": "11.43.0-alpha.3",
135
- "@gooddata/sdk-backend-mockingbird": "11.43.0-alpha.3"
130
+ "@gooddata/eslint-config": "11.43.0-alpha.5",
131
+ "@gooddata/oxlint-config": "11.43.0-alpha.5",
132
+ "@gooddata/reference-workspace": "11.43.0-alpha.5",
133
+ "@gooddata/stylelint-config": "11.43.0-alpha.5",
134
+ "@gooddata/sdk-backend-mockingbird": "11.43.0-alpha.5"
136
135
  },
137
136
  "peerDependencies": {
138
137
  "react": "^18.0.0 || ^19.0.0",
@@ -153,7 +152,7 @@
153
152
  "generate-theme": "node scripts/generateDefaultThemeScss.js && oxfmt --no-error-on-unmatched-pattern ./src/@ui/defaultTheme.scss",
154
153
  "lint": "oxlint . --quiet && eslint .",
155
154
  "lint-fix": "oxlint . --quiet --fix && eslint . --fix",
156
- "scss": "sass --load-path=node_modules --load-path=node_modules/fixed-data-table-2/dist styles/scss:styles/css",
155
+ "scss": "sass --load-path=node_modules styles/scss:styles/css",
157
156
  "stylelint": "stylelint '**/*.scss'",
158
157
  "stylelint-fix": "stylelint '**/*.scss' --fix",
159
158
  "test": "vitest watch",
@@ -12,4 +12,12 @@
12
12
  align-items: center;
13
13
  cursor: default;
14
14
  }
15
+
16
+ // Static label for a display-only level (EDIT): the grant can't be managed
17
+ // from this dialog, so it reads as plain text with no dropdown affordance.
18
+ &__readonly-permission {
19
+ font-size: 12px;
20
+ color: var(--gd-palette-complementary-6);
21
+ white-space: nowrap;
22
+ }
15
23
  }
@@ -7,22 +7,33 @@
7
7
  align-self: stretch;
8
8
  display: flex;
9
9
  flex-direction: column;
10
+ // Fill the menu's bounded height so the header and actions stay pinned while
11
+ // only the rows scroll (see &__items).
12
+ min-height: 0;
13
+ flex: 1 1 auto;
10
14
 
11
15
  // The submenu header is width:100% + content-box, so its 10px side padding
12
16
  // would overflow the column by 20px. Make it border-box so it lines up with
13
17
  // the rows and the actions strip below.
14
18
  .gd-ui-kit-submenu-header {
15
19
  box-sizing: border-box;
20
+ flex: none;
16
21
  }
17
22
 
18
23
  &__items {
19
24
  display: flex;
20
25
  flex-direction: column;
21
26
  padding: var(--gd-spacing-5px) 0;
27
+ // Scroll the rows when the label list is taller than the menu, keeping the
28
+ // header and Cancel/Apply footer always visible.
29
+ overflow-y: auto;
30
+ overscroll-behavior: contain;
31
+ min-height: 0;
22
32
  }
23
33
 
24
34
  &__actions {
25
35
  display: flex;
36
+ flex: none;
26
37
  justify-content: flex-end;
27
38
  gap: var(--gd-spacing-10px);
28
39
  padding: var(--gd-spacing-10px);
@@ -33,6 +33,15 @@
33
33
  display: contents;
34
34
  }
35
35
 
36
+ // Wraps custom (drill-in) content. Becomes a flex child so its content is
37
+ // bounded by the menu's max-height and can scroll instead of overflowing.
38
+ &__content-wrapper {
39
+ display: flex;
40
+ flex-direction: column;
41
+ flex: 1 1 auto;
42
+ min-height: 0;
43
+ }
44
+
36
45
  &__items-container {
37
46
  width: 100%;
38
47
  height: 100%;
@@ -504,9 +504,7 @@
504
504
  background-image: url("@gooddata/sdk-ui-kit/styles/images/visualization-types/pushpin.svg"), url("@gooddata/sdk-ui-kit/styles/images/visualization-types/pushpin-active.svg");
505
505
  }
506
506
 
507
- .gd-visualizations-list .public_fixedDataTableRow_main,
508
- .gd-visualizations-list .public_fixedDataTableCell_main,
509
- .gd-visualizations-list .fixedDataTableCellGroupLayout_cellGroup {
507
+ .gd-visualizations-list .gd-infinite-list-item {
510
508
  overflow: visible;
511
509
  }
512
510
 
@@ -1 +1 @@
1
- {"version":3,"sourceRoot":"","sources":["../scss/Button/_variables.scss","../scss/indigoFont.scss","../scss/insightList.scss","../scss/variables.scss"],"names":[],"mappings":"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","file":"insightList.css"}
1
+ {"version":3,"sourceRoot":"","sources":["../scss/Button/_variables.scss","../scss/indigoFont.scss","../scss/insightList.scss","../scss/variables.scss"],"names":[],"mappings":"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","file":"insightList.css"}