@gooddata/sdk-ui-kit 11.57.0-alpha.2 → 11.57.0-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/@ui/@utils/keyboardNavigation.d.ts +10 -0
- package/esm/@ui/@utils/keyboardNavigation.d.ts.map +1 -1
- package/esm/@ui/@utils/keyboardNavigation.js +9 -0
- package/esm/@ui/UiAddGranteeDialog/UiAddGranteeDialogCard.d.ts +4 -6
- package/esm/@ui/UiAddGranteeDialog/UiAddGranteeDialogCard.d.ts.map +1 -1
- package/esm/@ui/UiAddGranteeDialog/UiAddGranteeDialogCard.js +10 -8
- package/esm/@ui/UiAutocomplete/useAsyncListSource.js +1 -1
- package/esm/@ui/UiGranteeAsyncPicker/UiGranteeAsyncPicker.d.ts +8 -1
- package/esm/@ui/UiGranteeAsyncPicker/UiGranteeAsyncPicker.d.ts.map +1 -1
- package/esm/@ui/UiGranteeAsyncPicker/UiGranteeAsyncPicker.js +10 -6
- package/esm/@ui/UiListbox/defaults/DefaultUiListboxInteractiveItemComponent.d.ts.map +1 -1
- package/esm/@ui/UiListbox/defaults/DefaultUiListboxInteractiveItemComponent.js +6 -2
- package/esm/@ui/UiMenu/components/defaults/DefaultUiMenuContentItem.d.ts.map +1 -1
- package/esm/@ui/UiMenu/components/defaults/DefaultUiMenuContentItem.js +7 -2
- package/esm/@ui/UiMenu/components/defaults/DefaultUiMenuInteractiveItem.d.ts.map +1 -1
- package/esm/@ui/UiMenu/components/defaults/DefaultUiMenuInteractiveItem.js +7 -2
- package/esm/@ui/UiModalDialog/UiDialogHeader.d.ts.map +1 -1
- package/esm/@ui/UiModalDialog/UiDialogHeader.js +6 -3
- package/esm/@ui/UiObjectShareDialog/UiObjectShareDialogCard.d.ts +16 -3
- package/esm/@ui/UiObjectShareDialog/UiObjectShareDialogCard.d.ts.map +1 -1
- package/esm/@ui/UiObjectShareDialog/UiObjectShareDialogCard.js +2 -3
- package/esm/@ui/UiPermissionMenu/UiPermissionMenu.d.ts +9 -4
- package/esm/@ui/UiPermissionMenu/UiPermissionMenu.d.ts.map +1 -1
- package/esm/@ui/UiPermissionMenu/UiPermissionMenu.js +20 -29
- package/esm/@ui/UiTags/hooks/useResponsiveTags.js +1 -1
- package/esm/@ui/UiToolbar/UiToolbar.d.ts +52 -0
- package/esm/@ui/UiToolbar/UiToolbar.d.ts.map +1 -0
- package/esm/@ui/UiToolbar/UiToolbar.js +44 -0
- package/esm/@ui/UiToolbar/UiToolbarChevron.d.ts +8 -0
- package/esm/@ui/UiToolbar/UiToolbarChevron.d.ts.map +1 -0
- package/esm/@ui/UiToolbar/UiToolbarChevron.js +12 -0
- package/esm/@ui/UiToolbar/UiToolbarItemTooltip.d.ts +14 -0
- package/esm/@ui/UiToolbar/UiToolbarItemTooltip.d.ts.map +1 -0
- package/esm/@ui/UiToolbar/UiToolbarItemTooltip.js +11 -0
- package/esm/@ui/UiToolbar/constants.d.ts +5 -0
- package/esm/@ui/UiToolbar/constants.d.ts.map +1 -0
- package/esm/@ui/UiToolbar/constants.js +6 -0
- package/esm/@ui/UiToolbar/context.d.ts +23 -0
- package/esm/@ui/UiToolbar/context.d.ts.map +1 -0
- package/esm/@ui/UiToolbar/context.js +6 -0
- package/esm/@ui/UiToolbar/rovingFocusUtils.d.ts +55 -0
- package/esm/@ui/UiToolbar/rovingFocusUtils.d.ts.map +1 -0
- package/esm/@ui/UiToolbar/rovingFocusUtils.js +220 -0
- package/esm/@ui/UiToolbar/toolbarItemProps.d.ts +35 -0
- package/esm/@ui/UiToolbar/toolbarItemProps.d.ts.map +1 -0
- package/esm/@ui/UiToolbar/toolbarItemProps.js +2 -0
- package/esm/@ui/UiToolbar/useToolbarRovingFocus.d.ts +19 -0
- package/esm/@ui/UiToolbar/useToolbarRovingFocus.d.ts.map +1 -0
- package/esm/@ui/UiToolbar/useToolbarRovingFocus.js +172 -0
- package/esm/@ui/UiToolbarButton/UiToolbarButton.d.ts +19 -0
- package/esm/@ui/UiToolbarButton/UiToolbarButton.d.ts.map +1 -0
- package/esm/@ui/UiToolbarButton/UiToolbarButton.js +29 -0
- package/esm/@ui/UiToolbarButton/useToolbarItemRole.d.ts +38 -0
- package/esm/@ui/UiToolbarButton/useToolbarItemRole.d.ts.map +1 -0
- package/esm/@ui/UiToolbarButton/useToolbarItemRole.js +67 -0
- package/esm/@ui/UiToolbarColorSwatch/UiToolbarColorSwatch.d.ts +38 -0
- package/esm/@ui/UiToolbarColorSwatch/UiToolbarColorSwatch.d.ts.map +1 -0
- package/esm/@ui/UiToolbarColorSwatch/UiToolbarColorSwatch.js +13 -0
- package/esm/@ui/UiToolbarDivider/UiToolbarDivider.d.ts +7 -0
- package/esm/@ui/UiToolbarDivider/UiToolbarDivider.d.ts.map +1 -0
- package/esm/@ui/UiToolbarDivider/UiToolbarDivider.js +12 -0
- package/esm/@ui/UiToolbarIconButton/UiToolbarIconButton.d.ts +34 -0
- package/esm/@ui/UiToolbarIconButton/UiToolbarIconButton.d.ts.map +1 -0
- package/esm/@ui/UiToolbarIconButton/UiToolbarIconButton.js +34 -0
- package/esm/@ui/UiToolbarIconSelect/UiToolbarIconSelect.d.ts +54 -0
- package/esm/@ui/UiToolbarIconSelect/UiToolbarIconSelect.d.ts.map +1 -0
- package/esm/@ui/UiToolbarIconSelect/UiToolbarIconSelect.js +26 -0
- package/esm/@ui/UiToolbarMoreButton/UiToolbarMoreButton.d.ts +41 -0
- package/esm/@ui/UiToolbarMoreButton/UiToolbarMoreButton.d.ts.map +1 -0
- package/esm/@ui/UiToolbarMoreButton/UiToolbarMoreButton.js +12 -0
- package/esm/@ui/UiToolbarSegmentedControl/UiToolbarSegmentedControl.d.ts +37 -0
- package/esm/@ui/UiToolbarSegmentedControl/UiToolbarSegmentedControl.d.ts.map +1 -0
- package/esm/@ui/UiToolbarSegmentedControl/UiToolbarSegmentedControl.js +145 -0
- package/esm/@ui/UiToolbarSegmentedControl/context.d.ts +12 -0
- package/esm/@ui/UiToolbarSegmentedControl/context.d.ts.map +1 -0
- package/esm/@ui/UiToolbarSegmentedControl/context.js +3 -0
- package/esm/@ui/UiToolbarSelect/UiToolbarSelect.d.ts +51 -0
- package/esm/@ui/UiToolbarSelect/UiToolbarSelect.d.ts.map +1 -0
- package/esm/@ui/UiToolbarSelect/UiToolbarSelect.js +24 -0
- package/esm/@ui/UiToolbarStepper/UiToolbarStepper.d.ts +75 -0
- package/esm/@ui/UiToolbarStepper/UiToolbarStepper.d.ts.map +1 -0
- package/esm/@ui/UiToolbarStepper/UiToolbarStepper.js +85 -0
- package/esm/@ui/UiTooltip/UiTooltip.d.ts +1 -1
- package/esm/@ui/UiTooltip/UiTooltip.d.ts.map +1 -1
- package/esm/@ui/UiTooltip/UiTooltip.js +30 -8
- package/esm/@ui/UiTooltip/types.d.ts +17 -1
- package/esm/@ui/UiTooltip/types.d.ts.map +1 -1
- package/esm/@ui/hooks/useElementSize.d.ts.map +1 -1
- package/esm/@ui/hooks/useElementSize.js +2 -1
- package/esm/@ui/hooks/useIsTextTruncated.d.ts +12 -0
- package/esm/@ui/hooks/useIsTextTruncated.d.ts.map +1 -0
- package/esm/@ui/hooks/useIsTextTruncated.js +29 -0
- package/esm/Dropdown/Dropdown.js +1 -1
- package/esm/EditableLabel/EditableLabel.js +1 -1
- package/esm/List/LegacyList.js +1 -1
- package/esm/List/List.js +1 -1
- package/esm/Menu/positioning/PositionedMenuContent.d.ts.map +1 -1
- package/esm/Menu/positioning/PositionedMenuContent.js +3 -0
- package/esm/Messages/toasts/NonContextToastsInterop.js +1 -1
- package/esm/Messages/toasts/ToastsCenterMessage.d.ts.map +1 -1
- package/esm/Messages/toasts/ToastsCenterMessage.js +1 -1
- package/esm/ResponsiveText/ResponsiveText.js +3 -3
- package/esm/ShortenedText/ShortenedText.js +1 -1
- package/esm/index.d.ts +15 -1
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +12 -1
- package/esm/locales.d.ts +4 -16
- package/esm/locales.d.ts.map +1 -1
- package/esm/locales.js +2 -6
- package/esm/sdk-ui-kit.d.ts +518 -16
- package/esm/syntaxHighlightingInput/hooks/useCodemirror.js +1 -1
- package/esm/utils/domUtilities.d.ts +4 -0
- package/esm/utils/domUtilities.d.ts.map +1 -1
- package/esm/utils/domUtilities.js +11 -3
- package/esm/utils/events.d.ts +3 -0
- package/esm/utils/events.d.ts.map +1 -1
- package/esm/utils/events.js +4 -1
- package/package.json +13 -14
- package/src/@ui/UiAddGranteeDialog/UiAddGranteeDialog.scss +8 -0
- package/src/@ui/UiGranteeAsyncPicker/UiGranteeAsyncPicker.scss +0 -6
- package/src/@ui/UiGranteeRow/UiGranteeRow.scss +5 -0
- package/src/@ui/UiListbox/UiListbox.scss +4 -0
- package/src/@ui/UiMenu/UiMenu.scss +3 -0
- package/src/@ui/UiModalDialog/UiModalDialog.scss +16 -3
- package/src/@ui/UiObjectShareDialog/UiObjectShareDialog.scss +40 -1
- package/src/@ui/UiPermissionMenu/UiPermissionMenu.scss +7 -3
- package/src/@ui/UiToolbar/UiToolbar.scss +15 -0
- package/src/@ui/UiToolbar/UiToolbarChevron.scss +11 -0
- package/src/@ui/UiToolbar/toolbarItem.scss +133 -0
- package/src/@ui/UiToolbarButton/UiToolbarButton.scss +15 -0
- package/src/@ui/UiToolbarColorSwatch/UiToolbarColorSwatch.scss +66 -0
- package/src/@ui/UiToolbarDivider/UiToolbarDivider.scss +11 -0
- package/src/@ui/UiToolbarIconButton/UiToolbarIconButton.scss +30 -0
- package/src/@ui/UiToolbarIconSelect/UiToolbarIconSelect.scss +12 -0
- package/src/@ui/UiToolbarSegmentedControl/UiToolbarSegmentedControl.scss +10 -0
- package/src/@ui/UiToolbarSelect/UiToolbarSelect.scss +29 -0
- package/src/@ui/UiToolbarStepper/UiToolbarStepper.scss +53 -0
- package/src/@ui/UiTooltip/UiTooltip.scss +5 -0
- package/src/@ui/defaultTheme.scss +8 -3
- package/src/@ui/index.scss +10 -0
- package/styles/css/main.css +573 -11
- package/styles/css/main.css.map +1 -1
|
@@ -105,4 +105,14 @@ export declare const makeLinearKeyboardNavigationWithConfirm: <T extends Keyboar
|
|
|
105
105
|
onSelect?: ((event: T) => void) | undefined;
|
|
106
106
|
onUnhandledKeyDown?: ((event: T) => void) | undefined;
|
|
107
107
|
}, options?: IHandleActionOptions) => (event: T) => void;
|
|
108
|
+
/**
|
|
109
|
+
* Home and End are left out so they reach an enclosing toolbar.
|
|
110
|
+
*
|
|
111
|
+
* @internal
|
|
112
|
+
*/
|
|
113
|
+
export declare const makeRadioGroupKeyboardNavigation: <T extends KeyboardEvent = KeyboardEvent<Element>>(handlers: {
|
|
114
|
+
onFocusNext?: ((event: T) => void) | undefined;
|
|
115
|
+
onFocusPrevious?: ((event: T) => void) | undefined;
|
|
116
|
+
onUnhandledKeyDown?: ((event: T) => void) | undefined;
|
|
117
|
+
}, options?: IHandleActionOptions) => (event: T) => void;
|
|
108
118
|
//# sourceMappingURL=keyboardNavigation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keyboardNavigation.d.ts","sourceRoot":"","sources":["../../../src/@ui/@utils/keyboardNavigation.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,WAAW,EAAE,MAAM,OAAO,CAAC;AAE7D;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACjC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACnC;AAqBD;;GAEG;AACH,eAAO,MAAM,eAAe,EAAG,GAAY,CAAC;AAC5C;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,WAAW,GAAG,GAAG,OAAO,eAAe,GAAG,WAAW,EAAE,CAAC;AAEhF;;GAEG;AACH,eAAO,MAAM,sBAAsB,GAC9B,aAAa,SAAS;IAAE,CAAC,MAAM,EAAE,MAAM,GAAG,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;QAAC,SAAS,CAAC,EAAE,SAAS,EAAE,CAAA;KAAE,CAAC,CAAA;CAAE,iBACrF,aAAa,MAE/B,CAAC,SAAS,aAAa,GAAG,aAAa,YAC1B,GAAG,MAAM,IAAI,MAAM,aAAa,GAAG,oBAAoB,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,GAAE,YAChF,oBAAoB,aAEd,CAAC,SAmCnB,CAAC;AAEN;;GAEG;AACH,eAAO,MAAM,0BAA0B,GA5ClC,CAAC,SAAS,aAAa;6BAC+D,IAAI;;;;;;;;;aAC9E,oBAAoB,uBAmDnC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,0BAA0B,GA1DlC,CAAC,SAAS,aAAa;iCAC+D,IAAI;;;;;;;;aAC9E,oBAAoB,uBAgEnC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,4BAA4B,GAvEpC,CAAC,SAAS,aAAa;6BAC+D,IAAI;;;;;;;aAC9E,oBAAoB,uBA4EnC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,4BAA4B,GAnFpC,CAAC,SAAS,aAAa;6BAC+D,IAAI;;;;aAC9E,oBAAoB,uBAqFnC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,0BAA0B,GA5FlC,CAAC,SAAS,aAAa;kCAC+D,IAAI;;;;;;aAC9E,oBAAoB,uBAgGnC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,gCAAgC,GAvGxC,CAAC,SAAS,aAAa;kCAC+D,IAAI;;;;;aAC9E,oBAAoB,uBA0GnC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,uCAAuC,GAjH/C,CAAC,SAAS,aAAa;6BAC+D,IAAI;;;;;;;;aAC9E,oBAAoB,uBAuHnC,CAAC"}
|
|
1
|
+
{"version":3,"file":"keyboardNavigation.d.ts","sourceRoot":"","sources":["../../../src/@ui/@utils/keyboardNavigation.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,WAAW,EAAE,MAAM,OAAO,CAAC;AAE7D;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACjC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACnC;AAqBD;;GAEG;AACH,eAAO,MAAM,eAAe,EAAG,GAAY,CAAC;AAC5C;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,WAAW,GAAG,GAAG,OAAO,eAAe,GAAG,WAAW,EAAE,CAAC;AAEhF;;GAEG;AACH,eAAO,MAAM,sBAAsB,GAC9B,aAAa,SAAS;IAAE,CAAC,MAAM,EAAE,MAAM,GAAG,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;QAAC,SAAS,CAAC,EAAE,SAAS,EAAE,CAAA;KAAE,CAAC,CAAA;CAAE,iBACrF,aAAa,MAE/B,CAAC,SAAS,aAAa,GAAG,aAAa,YAC1B,GAAG,MAAM,IAAI,MAAM,aAAa,GAAG,oBAAoB,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,GAAE,YAChF,oBAAoB,aAEd,CAAC,SAmCnB,CAAC;AAEN;;GAEG;AACH,eAAO,MAAM,0BAA0B,GA5ClC,CAAC,SAAS,aAAa;6BAC+D,IAAI;;;;;;;;;aAC9E,oBAAoB,uBAmDnC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,0BAA0B,GA1DlC,CAAC,SAAS,aAAa;iCAC+D,IAAI;;;;;;;;aAC9E,oBAAoB,uBAgEnC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,4BAA4B,GAvEpC,CAAC,SAAS,aAAa;6BAC+D,IAAI;;;;;;;aAC9E,oBAAoB,uBA4EnC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,4BAA4B,GAnFpC,CAAC,SAAS,aAAa;6BAC+D,IAAI;;;;aAC9E,oBAAoB,uBAqFnC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,0BAA0B,GA5FlC,CAAC,SAAS,aAAa;kCAC+D,IAAI;;;;;;aAC9E,oBAAoB,uBAgGnC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,gCAAgC,GAvGxC,CAAC,SAAS,aAAa;kCAC+D,IAAI;;;;;aAC9E,oBAAoB,uBA0GnC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,uCAAuC,GAjH/C,CAAC,SAAS,aAAa;6BAC+D,IAAI;;;;;;;;aAC9E,oBAAoB,uBAuHnC,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,gCAAgC,GAhIxC,CAAC,SAAS,aAAa;iCAC+D,IAAI;;;aAC9E,oBAAoB,uBAiInC,CAAC"}
|
|
@@ -119,3 +119,12 @@ export const makeLinearKeyboardNavigationWithConfirm = makeKeyboardNavigation({
|
|
|
119
119
|
onConfirm: [{ code: "Enter" }],
|
|
120
120
|
onClose: [{ code: "Escape" }],
|
|
121
121
|
});
|
|
122
|
+
/**
|
|
123
|
+
* Home and End are left out so they reach an enclosing toolbar.
|
|
124
|
+
*
|
|
125
|
+
* @internal
|
|
126
|
+
*/
|
|
127
|
+
export const makeRadioGroupKeyboardNavigation = makeKeyboardNavigation({
|
|
128
|
+
onFocusPrevious: [{ code: ["ArrowLeft", "ArrowUp"] }],
|
|
129
|
+
onFocusNext: [{ code: ["ArrowRight", "ArrowDown"] }],
|
|
130
|
+
});
|
|
@@ -5,8 +5,6 @@ import { type PermissionMenuLevel } from "../UiPermissionMenu/UiPermissionMenu.j
|
|
|
5
5
|
* @internal
|
|
6
6
|
*/
|
|
7
7
|
export interface IUiAddGranteeDialogCardProps {
|
|
8
|
-
/** Object title shown in the header — wrapped into `Share "\{title\}"`. */
|
|
9
|
-
objectTitle: string;
|
|
10
8
|
/** Loader passed straight through to the embedded `UiGranteeAsyncPicker`. */
|
|
11
9
|
loadOptions: (search: string) => Promise<IUiGranteeAsyncOptions>;
|
|
12
10
|
/**
|
|
@@ -54,9 +52,9 @@ export interface IUiAddGranteeDialogCardProps {
|
|
|
54
52
|
dataTestId?: string;
|
|
55
53
|
}
|
|
56
54
|
/**
|
|
57
|
-
* Add-grantee dialog card — header
|
|
58
|
-
*
|
|
59
|
-
* and
|
|
55
|
+
* Add-grantee dialog card — header ("Add users or groups", which also names the
|
|
56
|
+
* search input) + grantee picker (search input with sectioned Groups/Users
|
|
57
|
+
* dropdown and picked-rows list) + footer with Cancel and Add. Renders inline as a plain card. For modal behavior (portal,
|
|
60
58
|
* backdrop, focus trap, dismiss), use `UiAddGranteeDialog` which wraps this
|
|
61
59
|
* in `UiModalDialog`.
|
|
62
60
|
*
|
|
@@ -66,5 +64,5 @@ export interface IUiAddGranteeDialogCardProps {
|
|
|
66
64
|
*
|
|
67
65
|
* @internal
|
|
68
66
|
*/
|
|
69
|
-
export declare function UiAddGranteeDialogCard({
|
|
67
|
+
export declare function UiAddGranteeDialogCard({ loadOptions, disabledLevels, disabledTooltip, selectedGrantees, onSelectedGranteesChange, initialPermissionLevel, labels, onBack, onClose, onCancel, onShare, dataTestId, }: IUiAddGranteeDialogCardProps): import("react/jsx-runtime").JSX.Element;
|
|
70
68
|
//# sourceMappingURL=UiAddGranteeDialogCard.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UiAddGranteeDialogCard.d.ts","sourceRoot":"","sources":["../../../src/@ui/UiAddGranteeDialog/UiAddGranteeDialogCard.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"UiAddGranteeDialogCard.d.ts","sourceRoot":"","sources":["../../../src/@ui/UiAddGranteeDialog/UiAddGranteeDialogCard.tsx"],"names":[],"mappings":"AAOA,OAAO,EACH,KAAK,sBAAsB,EAC3B,KAAK,gBAAgB,EAExB,MAAM,iDAAiD,CAAC;AAEzD,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,2CAA2C,CAAC;AAGxF,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AAMnF;;GAEG;AACH,MAAM,WAAW,4BAA4B;IACzC,6EAA6E;IAC7E,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACjE;;;OAGG;IACH,cAAc,CAAC,EAAE,aAAa,CAAC,mBAAmB,CAAC,CAAC;IACpD,8CAA8C;IAC9C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,gBAAgB,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;IAClD;;;;OAIG;IACH,wBAAwB,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IAC7D;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,mBAAmB,CAAC;IAC7C;;;;OAIG;IACH,MAAM,CAAC,EAAE,aAAa,CAAC,sBAAsB,CAAC,CAAC;IAE/C,+DAA+D;IAC/D,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,4DAA4D;IAC5D,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,uDAAuD;IACvD,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB;;;OAGG;IACH,OAAO,EAAE,MAAM,IAAI,CAAC;IAEpB,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CAAC,EACnC,WAAW,EACX,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,wBAAwB,EACxB,sBAA+B,EAC/B,MAAM,EACN,MAAM,EACN,OAAO,EACP,QAAQ,EACR,OAAO,EACP,UAAU,GACb,EAAE,4BAA4B,2CAuD9B"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
// (C) 2026 GoodData Corporation
|
|
3
3
|
import { useIntl } from "react-intl";
|
|
4
|
-
import { commonDialogMessages, olpAddGranteeDialogMessages
|
|
4
|
+
import { commonDialogMessages, olpAddGranteeDialogMessages } from "../../locales.js";
|
|
5
5
|
import { bem } from "../@utils/bem.js";
|
|
6
6
|
import { UiButton } from "../UiButton/UiButton.js";
|
|
7
7
|
import { UiGranteeAsyncPicker, } from "../UiGranteeAsyncPicker/UiGranteeAsyncPicker.js";
|
|
@@ -11,9 +11,9 @@ import { UiDialogHeader } from "../UiModalDialog/UiDialogHeader.js";
|
|
|
11
11
|
import { useGranteeSelection } from "./useGranteeSelection.js";
|
|
12
12
|
const { b } = bem("gd-ui-kit-add-grantee-dialog");
|
|
13
13
|
/**
|
|
14
|
-
* Add-grantee dialog card — header
|
|
15
|
-
*
|
|
16
|
-
* and
|
|
14
|
+
* Add-grantee dialog card — header ("Add users or groups", which also names the
|
|
15
|
+
* search input) + grantee picker (search input with sectioned Groups/Users
|
|
16
|
+
* dropdown and picked-rows list) + footer with Cancel and Add. Renders inline as a plain card. For modal behavior (portal,
|
|
17
17
|
* backdrop, focus trap, dismiss), use `UiAddGranteeDialog` which wraps this
|
|
18
18
|
* in `UiModalDialog`.
|
|
19
19
|
*
|
|
@@ -23,14 +23,16 @@ const { b } = bem("gd-ui-kit-add-grantee-dialog");
|
|
|
23
23
|
*
|
|
24
24
|
* @internal
|
|
25
25
|
*/
|
|
26
|
-
export function UiAddGranteeDialogCard({
|
|
26
|
+
export function UiAddGranteeDialogCard({ loadOptions, disabledLevels, disabledTooltip, selectedGrantees, onSelectedGranteesChange, initialPermissionLevel = "VIEW", labels, onBack, onClose, onCancel, onShare, dataTestId, }) {
|
|
27
27
|
const intl = useIntl();
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
// The title doubles as the accessible name of the picker's search input, which has
|
|
29
|
+
// no visible label of its own.
|
|
30
|
+
const dialogTitle = intl.formatMessage(olpAddGranteeDialogMessages.title);
|
|
31
|
+
const backButton = (_jsx(UiIconButton, { icon: "chevronLeft", variant: "secondary", size: "small", onClick: onBack, accessibilityConfig: { ariaLabel: intl.formatMessage(olpAddGranteeDialogMessages.back) } }));
|
|
30
32
|
const { select, changePermission, changeLabels, remove } = useGranteeSelection({
|
|
31
33
|
selectedGrantees,
|
|
32
34
|
onSelectedGranteesChange,
|
|
33
35
|
initialPermissionLevel,
|
|
34
36
|
});
|
|
35
|
-
return (_jsxs("div", { className: b(), "data-testid": dataTestId, children: [_jsx(UiDialogHeader, { title: dialogTitle,
|
|
37
|
+
return (_jsxs("div", { className: b(), "data-testid": dataTestId, children: [_jsx(UiDialogHeader, { title: dialogTitle, onClose: onClose, leading: backButton }), _jsx(UiGranteeAsyncPicker, { accessibilityConfig: { ariaLabel: dialogTitle }, loadOptions: loadOptions, disabledLevels: disabledLevels, disabledTooltip: disabledTooltip, selectedGrantees: selectedGrantees, onSelect: select, onPermissionChange: changePermission, labels: labels, onLabelsChange: changeLabels, onRemove: remove }), _jsxs(UiDialogFooter, { divider: true, children: [_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: onShare, isDisabled: selectedGrantees.length === 0 })] })] }));
|
|
36
38
|
}
|
|
@@ -83,7 +83,7 @@ export function useAsyncListSource(loadOptions, { debounceMs }) {
|
|
|
83
83
|
const reset = useCallback(() => {
|
|
84
84
|
setInputValueImmediate("");
|
|
85
85
|
setPagination(null);
|
|
86
|
-
//
|
|
86
|
+
// oxlint-disable-next-line react-hooks/exhaustive-deps
|
|
87
87
|
}, []);
|
|
88
88
|
return useMemo(() => ({
|
|
89
89
|
inputValue,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type ObjRef } from "@gooddata/sdk-model";
|
|
2
|
+
import { type IAccessibilityConfigBase } from "../../typings/accessibility.js";
|
|
2
3
|
import { type GranteeAvatarKind } from "../UiGranteeAvatar/UiGranteeAvatar.js";
|
|
3
4
|
import { type IUiLabelsChecklistItem } from "../UiLabelsChecklist/UiLabelsChecklist.js";
|
|
4
5
|
import { type PermissionMenuLevel } from "../UiPermissionMenu/UiPermissionMenu.js";
|
|
@@ -84,6 +85,12 @@ export interface IUiGranteeAsyncPickerProps {
|
|
|
84
85
|
* stays hidden rather than offering an Apply that discards it.
|
|
85
86
|
*/
|
|
86
87
|
labels?: ReadonlyArray<IUiLabelsChecklistItem>;
|
|
88
|
+
/**
|
|
89
|
+
* Accessible name of the search input, which has no visible label of its own — the
|
|
90
|
+
* surrounding dialog's title names it, so pass that title here. Defaults to the
|
|
91
|
+
* add-grantee dialog title.
|
|
92
|
+
*/
|
|
93
|
+
accessibilityConfig?: Pick<IAccessibilityConfigBase, "ariaLabel">;
|
|
87
94
|
/** Fires with the applied label scope of a picked row. Enables `labels`. */
|
|
88
95
|
onLabelsChange?: (grantee: IUiPickedGrantee, selectedLabelIds: string[]) => void;
|
|
89
96
|
/** Test id forwarded to the root element. */
|
|
@@ -98,5 +105,5 @@ export interface IUiGranteeAsyncPickerProps {
|
|
|
98
105
|
*
|
|
99
106
|
* @internal
|
|
100
107
|
*/
|
|
101
|
-
export declare function UiGranteeAsyncPicker({ loadOptions, selectedGrantees, onSelect, onPermissionChange, disabledLevels, disabledTooltip, onRemove, labels, onLabelsChange, dataTestId, }: IUiGranteeAsyncPickerProps): import("react/jsx-runtime").JSX.Element;
|
|
108
|
+
export declare function UiGranteeAsyncPicker({ loadOptions, selectedGrantees, onSelect, onPermissionChange, disabledLevels, disabledTooltip, onRemove, labels, onLabelsChange, accessibilityConfig, dataTestId, }: IUiGranteeAsyncPickerProps): import("react/jsx-runtime").JSX.Element;
|
|
102
109
|
//# sourceMappingURL=UiGranteeAsyncPicker.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UiGranteeAsyncPicker.d.ts","sourceRoot":"","sources":["../../../src/@ui/UiGranteeAsyncPicker/UiGranteeAsyncPicker.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"UiGranteeAsyncPicker.d.ts","sourceRoot":"","sources":["../../../src/@ui/UiGranteeAsyncPicker/UiGranteeAsyncPicker.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAGlD,OAAO,EAAE,KAAK,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAK/E,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAE/E,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,2CAA2C,CAAC;AACxF,OAAO,EACH,KAAK,mBAAmB,EAG3B,MAAM,yCAAyC,CAAC;AAIjD;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IAClC,uFAAuF;IACvF,EAAE,EAAE,MAAM,CAAC;IACX;;yBAEqB;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,sBAAsB;IACtB,IAAI,EAAE,iBAAiB,CAAC;IACxB,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAiB,SAAQ,qBAAqB;IAC3D,gGAAgG;IAChG,eAAe,EAAE,mBAAmB,CAAC;IACrC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACpC;AAED;;;;;GAKG;AACH,MAAM,WAAW,sBAAsB;IACnC,MAAM,EAAE,qBAAqB,EAAE,CAAC;IAChC,KAAK,EAAE,qBAAqB,EAAE,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACvC;;;;;OAKG;IACH,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACjE;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;IACnD,6DAA6D;IAC7D,QAAQ,EAAE,CAAC,MAAM,EAAE,qBAAqB,KAAK,IAAI,CAAC;IAClD,wEAAwE;IACxE,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACpF;;;OAGG;IACH,cAAc,CAAC,EAAE,aAAa,CAAC,mBAAmB,CAAC,CAAC;IACpD,8CAA8C;IAC9C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC/C;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,aAAa,CAAC,sBAAsB,CAAC,CAAC;IAC/C;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,IAAI,CAAC,wBAAwB,EAAE,WAAW,CAAC,CAAC;IAClE,4EAA4E;IAC5E,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACjF,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAOD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,EACjC,WAAW,EACX,gBAAqB,EACrB,QAAQ,EACR,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,QAAQ,EACR,MAAM,EACN,cAAc,EACd,mBAAmB,EACnB,UAAU,GACb,EAAE,0BAA0B,2CA+H5B"}
|
|
@@ -18,7 +18,7 @@ const { b, e } = bem("gd-ui-kit-grantee-async-picker");
|
|
|
18
18
|
*
|
|
19
19
|
* @internal
|
|
20
20
|
*/
|
|
21
|
-
export function UiGranteeAsyncPicker({ loadOptions, selectedGrantees = [], onSelect, onPermissionChange, disabledLevels, disabledTooltip, onRemove, labels, onLabelsChange, dataTestId, }) {
|
|
21
|
+
export function UiGranteeAsyncPicker({ loadOptions, selectedGrantees = [], onSelect, onPermissionChange, disabledLevels, disabledTooltip, onRemove, labels, onLabelsChange, accessibilityConfig, dataTestId, }) {
|
|
22
22
|
const intl = useIntl();
|
|
23
23
|
const groupsLabel = intl.formatMessage(uiGranteeAsyncPickerMessages.sectionGroups);
|
|
24
24
|
const usersLabel = intl.formatMessage(uiGranteeAsyncPickerMessages.sectionUsers);
|
|
@@ -57,16 +57,20 @@ export function UiGranteeAsyncPicker({ loadOptions, selectedGrantees = [], onSel
|
|
|
57
57
|
stateError: intl.formatMessage(uiGranteeAsyncPickerMessages.stateError),
|
|
58
58
|
stateNoMatch: intl.formatMessage(uiGranteeAsyncPickerMessages.stateNoMatch),
|
|
59
59
|
}), [intl]);
|
|
60
|
-
|
|
60
|
+
// `||`, not `??`: an empty custom label must not leave the combobox unnamed.
|
|
61
|
+
const fieldLabel = accessibilityConfig?.ariaLabel || intl.formatMessage(olpAddGranteeDialogMessages.title);
|
|
61
62
|
// A row with no scope of its own covers every label (see `labelIds`). The drill-in is
|
|
62
63
|
// offered only when the pick has somewhere to go — otherwise Apply would silently
|
|
63
64
|
// discard it.
|
|
64
65
|
const scopeLabels = onLabelsChange ? labels : undefined;
|
|
65
66
|
const allLabelIds = useMemo(() => (scopeLabels ?? []).map((l) => l.id), [scopeLabels]);
|
|
66
|
-
return (_jsxs("div", { className: b(), "data-testid": dataTestId, children: [
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
return (_jsxs("div", { className: b(), "data-testid": dataTestId, children: [_jsx("div", { className: e("field"), children: _jsx(UiAutocomplete, { loadOptions: adaptedLoadOptions, selectedIds: selectedIds, onSelect: handleSelect, messages: autocompleteMessages, accessibilityConfig: {
|
|
68
|
+
ariaLabel: fieldLabel,
|
|
69
|
+
} }) }), selectedGrantees.length === 0 ? (_jsx("div", { className: e("empty-state"), children: intl.formatMessage(olpAddGranteeDialogMessages.emptyState) })) : null, selectedGrantees.length > 0 ? (_jsx("ul", { className: e("picked-list"), children: selectedGrantees.map((g) => {
|
|
69
70
|
const triggerLabel = intl.formatMessage(permissionLevelMessage(g.permissionLevel));
|
|
70
|
-
return (_jsx("li", { className: e("picked-item"), children: _jsx(UiGranteeRow, { kind: g.kind, name: g.name, email: g.email, controls: _jsx(UiPermissionMenu, { selectedLevel: g.permissionLevel, onPermissionChange: (next) => onPermissionChange?.(g, next), disabledLevels: disabledLevels, disabledTooltip: disabledTooltip, labels: scopeLabels, selectedLabelIds: g.labelIds ?? allLabelIds, onLabelsChange: (ids) => onLabelsChange?.(g, ids), onRemoveAccess: onRemove ? () => onRemove(g) : undefined,
|
|
71
|
+
return (_jsx("li", { className: e("picked-item"), children: _jsx(UiGranteeRow, { kind: g.kind, name: g.name, email: g.email, controls: _jsx(UiPermissionMenu, { selectedLevel: g.permissionLevel, onPermissionChange: (next) => onPermissionChange?.(g, next), disabledLevels: disabledLevels, disabledTooltip: disabledTooltip, labels: scopeLabels, selectedLabelIds: g.labelIds ?? allLabelIds, onLabelsChange: (ids) => onLabelsChange?.(g, ids), onRemoveAccess: onRemove ? () => onRemove(g) : undefined,
|
|
72
|
+
// Nothing is granted yet, so the row drops the
|
|
73
|
+
// candidate rather than revoking access.
|
|
74
|
+
removeAccessLabel: intl.formatMessage(olpAddGranteeDialogMessages.remove), anchor: _jsx(UiButton, { label: triggerLabel, variant: "dropdownInline", size: "small", iconAfter: "navigateDown" }) }) }) }, g.id));
|
|
71
75
|
}) })) : null] }));
|
|
72
76
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DefaultUiListboxInteractiveItemComponent.d.ts","sourceRoot":"","sources":["../../../../src/@ui/UiListbox/defaults/DefaultUiListboxInteractiveItemComponent.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAMvC,OAAO,EAAE,KAAK,8BAA8B,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"DefaultUiListboxInteractiveItemComponent.d.ts","sourceRoot":"","sources":["../../../../src/@ui/UiListbox/defaults/DefaultUiListboxInteractiveItemComponent.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAMvC,OAAO,EAAE,KAAK,8BAA8B,EAAE,MAAM,aAAa,CAAC;AAKlE;;GAEG;AACH,wBAAgB,wCAAwC,CAAC,CAAC,EAAE,EACxD,IAAI,EACJ,SAAS,EACT,UAAU,EACV,SAAS,EACT,QAAQ,GACX,EAAE,8BAA8B,CAAC,CAAC,CAAC,GAAG,SAAS,CA0D/C"}
|
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { useIsTextTruncated } from "../../hooks/useIsTextTruncated.js";
|
|
3
3
|
import { UiIcon } from "../../UiIcon/UiIcon.js";
|
|
4
4
|
import { UiTooltip } from "../../UiTooltip/UiTooltip.js";
|
|
5
5
|
import { e } from "../listboxBem.js";
|
|
6
|
+
// The tooltip anchor wrapper defaults to fit-content; the title must be allowed to shrink and clip.
|
|
7
|
+
const TITLE_ANCHOR_STYLE = { display: "block", minWidth: 0, flex: "1 1 0%" };
|
|
6
8
|
/**
|
|
7
9
|
* @internal
|
|
8
10
|
*/
|
|
9
11
|
export function DefaultUiListboxInteractiveItemComponent({ item, isFocused, isSelected, isCompact, onSelect, }) {
|
|
12
|
+
const title = useIsTextTruncated(item.stringTitle);
|
|
13
|
+
const titleElement = (_jsx("span", { ref: title.ref, className: e("item-title"), children: item.stringTitle }));
|
|
10
14
|
return (_jsxs("div", { className: e("item", {
|
|
11
15
|
isFocused,
|
|
12
16
|
isSelected,
|
|
13
17
|
isCompact,
|
|
14
18
|
isDisabled: !!item.isDisabled,
|
|
15
|
-
}), onClick: item.isDisabled ? undefined : onSelect, children: [item.icon ? _jsx(UiIcon, { type: item.icon, size: 14, color: "complementary-7" }) : null, _jsx(
|
|
19
|
+
}), onClick: item.isDisabled ? undefined : onSelect, children: [item.icon ? _jsx(UiIcon, { type: item.icon, size: 14, color: "complementary-7" }) : null, title.isTruncated ? (_jsx(UiTooltip, { anchor: titleElement, content: item.stringTitle, triggerBy: ["hover"], accessibilityHidden: true, arrowPlacement: "left", optimalPlacement: true, offset: 10, component: "span", anchorWrapperStyles: TITLE_ANCHOR_STYLE })) : (titleElement), item.tooltip ? (_jsxs(_Fragment, { children: [_jsx(UiTooltip, { anchor: _jsx("div", { className: e("item-explanation"), children: _jsx(UiIcon, { type: "question", size: 14, color: "complementary-7" }) }), content: item.tooltip, triggerBy: ["hover"], accessibilityHidden: true, arrowPlacement: "left", optimalPlacement: true, width: 200, offset: 10 }), _jsx("span", { className: "sr-only", children: item.tooltip })] })) : null] }));
|
|
16
20
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DefaultUiMenuContentItem.d.ts","sourceRoot":"","sources":["../../../../../src/@ui/UiMenu/components/defaults/DefaultUiMenuContentItem.tsx"],"names":[],"mappings":"AAEA,OAAO,EAIH,KAAK,SAAS,EAGjB,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"DefaultUiMenuContentItem.d.ts","sourceRoot":"","sources":["../../../../../src/@ui/UiMenu/components/defaults/DefaultUiMenuContentItem.tsx"],"names":[],"mappings":"AAEA,OAAO,EAIH,KAAK,SAAS,EAGjB,MAAM,OAAO,CAAC;AAWf,OAAO,EACH,KAAK,uBAAuB,EAC5B,KAAK,8BAA8B,EACnC,KAAK,eAAe,EACvB,MAAM,gBAAgB,CAAC;AACxB;;;GAGG;AACH,eAAO,MAAM,+BAA+B,8EAgF3C,CAAC;AAEF;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,SAAS,eAAe,GAAG,MAAM,EAAE,EACzE,IAAI,EACJ,SAAS,GACZ,EAAE,uBAAuB,CAAC,CAAC,CAAC,GAAG,SAAS,CAmCxC"}
|
|
@@ -2,7 +2,10 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
// (C) 2025-2026 GoodData Corporation
|
|
3
3
|
import { memo, useCallback, } from "react";
|
|
4
4
|
import cx from "classnames";
|
|
5
|
-
|
|
5
|
+
// The tooltip anchor wrapper defaults to fit-content; the title must be allowed to shrink and clip.
|
|
6
|
+
const TITLE_ANCHOR_STYLE = { display: "block", minWidth: 0, flex: "1 1 0%" };
|
|
7
|
+
import { useIsTextTruncated } from "../../../hooks/useIsTextTruncated.js";
|
|
8
|
+
import { UiTooltip } from "../../../UiTooltip/UiTooltip.js";
|
|
6
9
|
import { typedUiMenuContextStore } from "../../context.js";
|
|
7
10
|
import { e } from "../../menuBem.js";
|
|
8
11
|
/**
|
|
@@ -52,8 +55,10 @@ export const DefaultUiMenuContentItemWrapper = memo(function DefaultUiMenuConten
|
|
|
52
55
|
* @internal
|
|
53
56
|
*/
|
|
54
57
|
export function DefaultUiMenuContentItem({ item, isFocused, }) {
|
|
58
|
+
const title = useIsTextTruncated(item.stringTitle);
|
|
59
|
+
const titleElement = (_jsx("span", { ref: title.ref, className: e("item-title"), children: item.stringTitle }));
|
|
55
60
|
return (_jsxs("div", { className: e("item", {
|
|
56
61
|
isFocused,
|
|
57
62
|
isDisabled: !!item.isDisabled,
|
|
58
|
-
}), children: [item.iconLeft ? item.iconLeft : null, _jsx(
|
|
63
|
+
}), children: [item.iconLeft ? item.iconLeft : null, title.isTruncated ? (_jsx(UiTooltip, { anchor: titleElement, content: item.stringTitle, triggerBy: ["hover"], accessibilityHidden: true, arrowPlacement: "left", optimalPlacement: true, offset: 10, component: "span", anchorWrapperStyles: TITLE_ANCHOR_STYLE })) : (titleElement), !!item.Component && _jsx("i", { className: "gd-icon-navigateright" })] }));
|
|
59
64
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DefaultUiMenuInteractiveItem.d.ts","sourceRoot":"","sources":["../../../../../src/@ui/UiMenu/components/defaults/DefaultUiMenuInteractiveItem.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAuC,KAAK,SAAS,EAAyB,MAAM,OAAO,CAAC;AASnG,OAAO,EAEH,KAAK,2BAA2B,EAChC,KAAK,kCAAkC,EACvC,KAAK,eAAe,EACvB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"DefaultUiMenuInteractiveItem.d.ts","sourceRoot":"","sources":["../../../../../src/@ui/UiMenu/components/defaults/DefaultUiMenuInteractiveItem.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAuC,KAAK,SAAS,EAAyB,MAAM,OAAO,CAAC;AASnG,OAAO,EAEH,KAAK,2BAA2B,EAChC,KAAK,kCAAkC,EACvC,KAAK,eAAe,EACvB,MAAM,gBAAgB,CAAC;AAsBxB;;GAEG;AACH,wBAAgB,mCAAmC,CAAC,CAAC,SAAS,eAAe,GAAG,MAAM,EAAE,EACpF,IAAI,EACJ,SAAS,GACZ,EAAE,kCAAkC,CAAC,CAAC,CAAC,GAAG,SAAS,CA0GnD;AAED;;GAEG;AACH,wBAAgB,4BAA4B,CAAC,CAAC,SAAS,eAAe,GAAG,MAAM,EAAE,EAC7E,IAAI,EACJ,SAAS,EACT,aAAa,GAChB,EAAE,2BAA2B,CAAC,CAAC,CAAC,GAAG,SAAS,CAuE5C"}
|
|
@@ -2,11 +2,13 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
// (C) 2025-2026 GoodData Corporation
|
|
3
3
|
import { useCallback, useState } from "react";
|
|
4
4
|
import cx from "classnames";
|
|
5
|
-
import { ShortenedText } from "../../../../ShortenedText/ShortenedText.js";
|
|
6
5
|
import { useCloseOnEscape } from "../../../hooks/useCloseOnEscape.js";
|
|
6
|
+
import { useIsTextTruncated } from "../../../hooks/useIsTextTruncated.js";
|
|
7
7
|
import { UiTooltip } from "../../../UiTooltip/UiTooltip.js";
|
|
8
8
|
import { typedUiMenuContextStore } from "../../context.js";
|
|
9
9
|
import { e } from "../../menuBem.js";
|
|
10
|
+
// The tooltip anchor wrapper defaults to fit-content; the title must be allowed to shrink and clip.
|
|
11
|
+
const TITLE_ANCHOR_STYLE = { display: "block", minWidth: 0, flex: "1 1 0%" };
|
|
10
12
|
function hasIconTooltip(item) {
|
|
11
13
|
return !!item.tooltip && !!item.iconRight;
|
|
12
14
|
}
|
|
@@ -85,12 +87,15 @@ export function DefaultUiMenuInteractiveItemWrapper({ item, Component, }) {
|
|
|
85
87
|
*/
|
|
86
88
|
export function DefaultUiMenuInteractiveItem({ item, isFocused, isTooltipOpen, }) {
|
|
87
89
|
const useIconTooltip = hasIconTooltip(item);
|
|
90
|
+
const isRowTooltip = !!item.tooltip && !useIconTooltip;
|
|
91
|
+
const title = useIsTextTruncated(item.stringTitle);
|
|
92
|
+
const titleElement = (_jsx("span", { ref: title.ref, className: e("item-title"), children: item.stringTitle }));
|
|
88
93
|
const itemInner = (_jsxs("div", { className: e("item", {
|
|
89
94
|
isFocused,
|
|
90
95
|
isSelected: !!item.isSelected,
|
|
91
96
|
isDisabled: !!item.isDisabled,
|
|
92
97
|
isDestructive: !!item.isDestructive,
|
|
93
|
-
}), children: [item.iconLeft ? item.iconLeft : null, _jsx(
|
|
98
|
+
}), children: [item.iconLeft ? item.iconLeft : null, title.isTruncated && !isRowTooltip ? (_jsx(UiTooltip, { anchor: titleElement, content: item.stringTitle, triggerBy: ["hover"], accessibilityHidden: true, arrowPlacement: "left", optimalPlacement: true, offset: 10, component: "span", anchorWrapperStyles: TITLE_ANCHOR_STYLE })) : (titleElement), !!item.subItems && _jsx("i", { className: "gd-icon-navigateright" }), useIconTooltip ? (_jsx(UiTooltip, { anchor: item.iconRight, content: item.tooltip, optimalPlacement: true, triggerBy: ["hover"], inlineAnchor: true, accessibilityHidden: true, arrowPlacement: "bottom-end", width: item.tooltipWidth })) : item.iconRight ? (item.iconRight) : null, item.tooltip ? _jsx("span", { className: "sr-only", children: item.tooltip }) : null] }));
|
|
94
99
|
if (!item.tooltip) {
|
|
95
100
|
return itemInner;
|
|
96
101
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UiDialogHeader.d.ts","sourceRoot":"","sources":["../../../src/@ui/UiModalDialog/UiDialogHeader.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAYvC;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAAG,SAAS,GAAG,OAAO,CAAC;AAExD;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACjC,iCAAiC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,SAAS,CAAC,EAAE,qBAAqB,CAAC;IAClC,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,4EAA4E;IAC5E,OAAO,CAAC,EAAE,SAAS,CAAC;CACvB;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,EAAE,KAAK,EAAE,SAAqB,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,oBAAoB,
|
|
1
|
+
{"version":3,"file":"UiDialogHeader.d.ts","sourceRoot":"","sources":["../../../src/@ui/UiModalDialog/UiDialogHeader.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAYvC;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAAG,SAAS,GAAG,OAAO,CAAC;AAExD;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACjC,iCAAiC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,SAAS,CAAC,EAAE,qBAAqB,CAAC;IAClC,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,4EAA4E;IAC5E,OAAO,CAAC,EAAE,SAAS,CAAC;CACvB;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,EAAE,KAAK,EAAE,SAAqB,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,oBAAoB,2CA2BtG"}
|
|
@@ -13,7 +13,10 @@ const { b, e } = bem("gd-ui-kit-dialog-header");
|
|
|
13
13
|
export function UiDialogHeader({ title, titleSize = "default", onClose, leading }) {
|
|
14
14
|
const intl = useIntl();
|
|
15
15
|
const dialogContext = useUiDialogContext();
|
|
16
|
-
return (_jsxs("div", { className: b(), children: [leading ? _jsx("span", { className: e("leading"), children: leading }) : null, _jsx("h2", { id: dialogContext?.titleId, className: e("title", { size: titleSize }), children: title }), onClose ? (_jsx(
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
return (_jsxs("div", { className: b(), children: [leading ? _jsx("span", { className: e("leading"), children: leading }) : null, _jsx("h2", { id: dialogContext?.titleId, className: e("title", { size: titleSize }), children: title }), onClose ? (_jsx("span", { className: e("close"), children: _jsx(UiIconButton, { icon: "cross", variant: "tertiary",
|
|
17
|
+
// 18px cross, matching the design; the tertiary box has no fill or
|
|
18
|
+
// border of its own, so only the icon size shows.
|
|
19
|
+
size: "medium", onClick: onClose, accessibilityConfig: {
|
|
20
|
+
ariaLabel: intl.formatMessage(commonDialogMessages.close),
|
|
21
|
+
} }) })) : null] }));
|
|
19
22
|
}
|
|
@@ -29,12 +29,25 @@ export interface IUiObjectShareDialogGrantee {
|
|
|
29
29
|
* @internal
|
|
30
30
|
*/
|
|
31
31
|
export interface IUiObjectShareDialogCardProps {
|
|
32
|
-
/**
|
|
33
|
-
|
|
32
|
+
/**
|
|
33
|
+
* Dialog heading, composed by the caller — it names the shared object's type
|
|
34
|
+
* ("Share attribute"), which only the caller knows.
|
|
35
|
+
*/
|
|
36
|
+
title: string;
|
|
34
37
|
/** Fires when the user clicks the header X button OR the footer Close button. */
|
|
35
38
|
onClose: () => void;
|
|
39
|
+
/**
|
|
40
|
+
* Optional informational note rendered right below the header — e.g. a reminder
|
|
41
|
+
* that administrators have full access regardless of the grants listed.
|
|
42
|
+
*/
|
|
43
|
+
note?: ReactNode;
|
|
36
44
|
/** Grantee rows shown inside the SHARED WITH section, in render order. */
|
|
37
45
|
grantees: IUiObjectShareDialogGrantee[];
|
|
46
|
+
/**
|
|
47
|
+
* Placeholder shown inside the SHARED WITH section when `grantees` is empty and the
|
|
48
|
+
* list is not loading — tells the user nobody has been granted access yet.
|
|
49
|
+
*/
|
|
50
|
+
emptyMessage?: ReactNode;
|
|
38
51
|
/**
|
|
39
52
|
* When true, skeleton rows stand in for the grantee list and the
|
|
40
53
|
* general-access radio — set it while the access list is loading, so the
|
|
@@ -86,5 +99,5 @@ export interface IUiObjectShareDialogCardProps {
|
|
|
86
99
|
*
|
|
87
100
|
* @internal
|
|
88
101
|
*/
|
|
89
|
-
export declare function UiObjectShareDialogCard({
|
|
102
|
+
export declare function UiObjectShareDialogCard({ title, onClose, note, grantees, emptyMessage, isLoading, onAddClick, isAddDisabled, generalAccess, onGeneralAccessChange, isGeneralAccessDisabled, workspaceAccessInherited, workspaceControls, workspaceLevel, error, dataTestId, }: IUiObjectShareDialogCardProps): import("react/jsx-runtime").JSX.Element;
|
|
90
103
|
//# sourceMappingURL=UiObjectShareDialogCard.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UiObjectShareDialogCard.d.ts","sourceRoot":"","sources":["../../../src/@ui/UiObjectShareDialog/UiObjectShareDialogCard.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAOvC,OAAO,EACH,KAAK,kBAAkB,EAE1B,MAAM,iDAAiD,CAAC;AACzD,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAS/E;;;;;;GAMG;AACH,MAAM,WAAW,2BAA2B;IACxC,6DAA6D;IAC7D,EAAE,EAAE,MAAM,CAAC;IACX,sBAAsB;IACtB,IAAI,EAAE,iBAAiB,CAAC;IACxB,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;OAGG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,6BAA6B;IAC1C
|
|
1
|
+
{"version":3,"file":"UiObjectShareDialogCard.d.ts","sourceRoot":"","sources":["../../../src/@ui/UiObjectShareDialog/UiObjectShareDialogCard.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAOvC,OAAO,EACH,KAAK,kBAAkB,EAE1B,MAAM,iDAAiD,CAAC;AACzD,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAS/E;;;;;;GAMG;AACH,MAAM,WAAW,2BAA2B;IACxC,6DAA6D;IAC7D,EAAE,EAAE,MAAM,CAAC;IACX,sBAAsB;IACtB,IAAI,EAAE,iBAAiB,CAAC;IACxB,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;OAGG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,6BAA6B;IAC1C;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IACd,iFAAiF;IACjF,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB;;;OAGG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IAEjB,0EAA0E;IAC1E,QAAQ,EAAE,2BAA2B,EAAE,CAAC;IACxC;;;OAGG;IACH,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,4EAA4E;IAC5E,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,oFAAoF;IACpF,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB,sCAAsC;IACtC,aAAa,EAAE,kBAAkB,CAAC;IAClC,mEAAmE;IACnE,qBAAqB,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAC3D,uFAAuF;IACvF,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC;;;;OAIG;IACH,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,SAAS,CAAC;IAC9B;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;IAE3C;;;;;OAKG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAElB,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,EACpC,KAAK,EACL,OAAO,EACP,IAAI,EACJ,QAAQ,EACR,YAAY,EACZ,SAAS,EACT,UAAU,EACV,aAAa,EACb,aAAa,EACb,qBAAqB,EACrB,uBAAuB,EACvB,wBAAwB,EACxB,iBAAiB,EACjB,cAAc,EACd,KAAK,EACL,UAAU,GACb,EAAE,6BAA6B,2CA8E/B"}
|
|
@@ -18,8 +18,7 @@ const { b, e } = bem("gd-ui-kit-object-share-dialog");
|
|
|
18
18
|
*
|
|
19
19
|
* @internal
|
|
20
20
|
*/
|
|
21
|
-
export function UiObjectShareDialogCard({
|
|
21
|
+
export function UiObjectShareDialogCard({ title, onClose, note, grantees, emptyMessage, isLoading, onAddClick, isAddDisabled, generalAccess, onGeneralAccessChange, isGeneralAccessDisabled, workspaceAccessInherited, workspaceControls, workspaceLevel, error, dataTestId, }) {
|
|
22
22
|
const intl = useIntl();
|
|
23
|
-
|
|
24
|
-
return (_jsxs("div", { className: b(), "data-testid": dataTestId, children: [_jsx(UiDialogHeader, { title: dialogTitle, onClose: onClose }), error ? (_jsx("div", { className: e("error"), role: "alert", children: error })) : (_jsxs(_Fragment, { children: [_jsx(UiSectionHeading, { label: intl.formatMessage(olpObjectShareDialogMessages.sharedWith), action: _jsx(UiButton, { label: intl.formatMessage(olpObjectShareDialogMessages.add), variant: "popout", size: "small", iconBefore: "plus", isDisabled: isAddDisabled, onClick: onAddClick }) }), _jsx("div", { className: e("grantees"), children: isLoading ? (_jsx(UiSkeleton, { itemsCount: 2, itemHeight: 40, itemsGap: 10 })) : (grantees.map((grantee) => (_jsx(UiGranteeRow, { kind: grantee.kind, name: grantee.name, email: grantee.email, isPending: grantee.isPending, controls: grantee.controls }, grantee.id)))) }), _jsx(UiSectionHeading, { label: intl.formatMessage(olpObjectShareDialogMessages.generalAccess) }), isLoading ? (_jsx(UiSkeleton, { itemsCount: 2, itemHeight: 40, itemsGap: 10 })) : (_jsx(UiGeneralAccessRadio, { value: generalAccess, onChange: onGeneralAccessChange, disabled: isGeneralAccessDisabled, workspaceAccessInherited: workspaceAccessInherited, workspaceControls: workspaceControls, workspaceLevel: workspaceLevel }))] })), _jsx(UiDialogFooter, { divider: true, children: _jsx(UiButton, { label: intl.formatMessage(commonDialogMessages.close), variant: "secondary", size: "medium", onClick: onClose }) })] }));
|
|
23
|
+
return (_jsxs("div", { className: b(), "data-testid": dataTestId, children: [_jsx(UiDialogHeader, { title: title, onClose: onClose }), note ? (_jsx("div", { className: e("note"), role: "note", children: note })) : null, error ? (_jsx("div", { className: e("error"), role: "alert", children: error })) : (_jsxs(_Fragment, { children: [_jsx(UiSectionHeading, { label: intl.formatMessage(olpObjectShareDialogMessages.sharedWith), action: _jsx(UiButton, { label: intl.formatMessage(olpObjectShareDialogMessages.add), variant: "popout", size: "small", iconBefore: "plus", isDisabled: isAddDisabled, onClick: onAddClick }) }), _jsx("div", { className: e("grantees"), children: isLoading ? (_jsx(UiSkeleton, { itemsCount: 2, itemHeight: 40, itemsGap: 10 })) : grantees.length === 0 && emptyMessage ? (_jsx("div", { className: e("empty"), children: emptyMessage })) : (grantees.map((grantee) => (_jsx(UiGranteeRow, { kind: grantee.kind, name: grantee.name, email: grantee.email, isPending: grantee.isPending, controls: grantee.controls }, grantee.id)))) }), _jsx(UiSectionHeading, { label: intl.formatMessage(olpObjectShareDialogMessages.generalAccess) }), isLoading ? (_jsx(UiSkeleton, { itemsCount: 2, itemHeight: 40, itemsGap: 10 })) : (_jsx(UiGeneralAccessRadio, { value: generalAccess, onChange: onGeneralAccessChange, disabled: isGeneralAccessDisabled, workspaceAccessInherited: workspaceAccessInherited, workspaceControls: workspaceControls, workspaceLevel: workspaceLevel }))] })), _jsx(UiDialogFooter, { divider: true, children: _jsx(UiButton, { label: intl.formatMessage(commonDialogMessages.close), variant: "secondary", size: "medium", onClick: onClose }) })] }));
|
|
25
24
|
}
|
|
@@ -31,7 +31,7 @@ export interface IUiPermissionMenuProps {
|
|
|
31
31
|
* the signed-in user may not pick because they exceed their own.
|
|
32
32
|
*/
|
|
33
33
|
disabledLevels?: ReadonlyArray<PermissionMenuLevel>;
|
|
34
|
-
/** Tooltip shown on disabled level rows
|
|
34
|
+
/** Tooltip shown on disabled level rows, explaining why the level can't be picked. */
|
|
35
35
|
disabledTooltip?: string;
|
|
36
36
|
/**
|
|
37
37
|
* Per-level override of `disabledTooltip`, for menus whose disabled levels have
|
|
@@ -57,6 +57,11 @@ export interface IUiPermissionMenuProps {
|
|
|
57
57
|
isRemoveDisabled?: boolean;
|
|
58
58
|
/** Tooltip shown on Remove access while it is disabled. */
|
|
59
59
|
removeDisabledTooltip?: string;
|
|
60
|
+
/**
|
|
61
|
+
* Label of the remove row. Defaults to "Remove access"; a picker staging a grantee
|
|
62
|
+
* that holds no access yet passes the shorter "Remove".
|
|
63
|
+
*/
|
|
64
|
+
removeAccessLabel?: string;
|
|
60
65
|
/** Test id forwarded to the menu body. */
|
|
61
66
|
dataTestId?: string;
|
|
62
67
|
}
|
|
@@ -64,10 +69,10 @@ export interface IUiPermissionMenuProps {
|
|
|
64
69
|
* Per-grantee permission popover. Renders a fixed set of rows — three
|
|
65
70
|
* permission levels (Can edit & share / Can view & share / Can view), an
|
|
66
71
|
* optional divider, an optional labels drill-in and an optional Remove access
|
|
67
|
-
* action row.
|
|
68
|
-
*
|
|
72
|
+
* action row. Enabled rows carry no tooltip; a disabled row (`disabledLevels`,
|
|
73
|
+
* `isRemoveDisabled`) shows its explanation as a tooltip over the whole row.
|
|
69
74
|
*
|
|
70
75
|
* @internal
|
|
71
76
|
*/
|
|
72
|
-
export declare function UiPermissionMenu({ anchor, selectedLevel, onPermissionChange, disabledLevels, disabledTooltip, disabledLevelTooltips, labels, selectedLabelIds, onLabelsChange, onRemoveAccess, isRemoveDisabled, removeDisabledTooltip, dataTestId, }: IUiPermissionMenuProps): import("react/jsx-runtime").JSX.Element;
|
|
77
|
+
export declare function UiPermissionMenu({ anchor, selectedLevel, onPermissionChange, disabledLevels, disabledTooltip, disabledLevelTooltips, labels, selectedLabelIds, onLabelsChange, onRemoveAccess, isRemoveDisabled, removeDisabledTooltip, removeAccessLabel, dataTestId, }: IUiPermissionMenuProps): import("react/jsx-runtime").JSX.Element;
|
|
73
78
|
//# sourceMappingURL=UiPermissionMenu.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UiPermissionMenu.d.ts","sourceRoot":"","sources":["../../../src/@ui/UiPermissionMenu/UiPermissionMenu.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAsB,KAAK,YAAY,
|
|
1
|
+
{"version":3,"file":"UiPermissionMenu.d.ts","sourceRoot":"","sources":["../../../src/@ui/UiPermissionMenu/UiPermissionMenu.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAsB,KAAK,YAAY,EAAwC,MAAM,OAAO,CAAC;AAEpG,OAAO,EAAE,KAAK,iBAAiB,EAAW,MAAM,YAAY,CAAC;AAM7D,OAAO,EAAE,KAAK,sBAAsB,EAAqB,MAAM,2CAA2C,CAAC;AAM3G;;;;;;GAMG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAQ5D;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,mBAAmB,GAAG,iBAAiB,CAEpF;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACnC,4CAA4C;IAC5C,MAAM,EAAE,YAAY,CAAC;IACrB,mEAAmE;IACnE,aAAa,CAAC,EAAE,mBAAmB,CAAC;IACpC,oDAAoD;IACpD,kBAAkB,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACzD;;;OAGG;IACH,cAAc,CAAC,EAAE,aAAa,CAAC,mBAAmB,CAAC,CAAC;IACpD,sFAAsF;IACtF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC,CAAC;IACrE;;;OAGG;IACH,MAAM,CAAC,EAAE,aAAa,CAAC,sBAAsB,CAAC,CAAC;IAC/C,mDAAmD;IACnD,gBAAgB,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACzC,uEAAuE;IACvE,cAAc,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACjD,+CAA+C;IAC/C,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,2DAA2D;IAC3D,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAqBD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,EAC7B,MAAM,EACN,aAAa,EACb,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,qBAAqB,EACrB,MAAM,EACN,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,qBAAqB,EACrB,iBAAiB,EACjB,UAAU,GACb,EAAE,sBAAsB,2CA2BxB"}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
// (C) 2026 GoodData Corporation
|
|
3
|
-
import { useCallback, useRef, useState } from "react";
|
|
3
|
+
import { useCallback, useId, useRef, useState } from "react";
|
|
4
4
|
import { useIntl } from "react-intl";
|
|
5
5
|
import { olpPermissionMessages } from "../../locales.js";
|
|
6
6
|
import { bem } from "../@utils/bem.js";
|
|
7
7
|
import { UiIcon } from "../UiIcon/UiIcon.js";
|
|
8
|
-
import { UiIconButton } from "../UiIconButton/UiIconButton.js";
|
|
9
8
|
import { UiLabelsChecklist } from "../UiLabelsChecklist/UiLabelsChecklist.js";
|
|
10
9
|
import { UiPopover } from "../UiPopover/UiPopover.js";
|
|
11
10
|
import { UiTooltip } from "../UiTooltip/UiTooltip.js";
|
|
@@ -28,16 +27,16 @@ export function permissionLevelMessage(level) {
|
|
|
28
27
|
* Per-grantee permission popover. Renders a fixed set of rows — three
|
|
29
28
|
* permission levels (Can edit & share / Can view & share / Can view), an
|
|
30
29
|
* optional divider, an optional labels drill-in and an optional Remove access
|
|
31
|
-
* action row.
|
|
32
|
-
*
|
|
30
|
+
* action row. Enabled rows carry no tooltip; a disabled row (`disabledLevels`,
|
|
31
|
+
* `isRemoveDisabled`) shows its explanation as a tooltip over the whole row.
|
|
33
32
|
*
|
|
34
33
|
* @internal
|
|
35
34
|
*/
|
|
36
|
-
export function UiPermissionMenu({ anchor, selectedLevel, onPermissionChange, disabledLevels, disabledTooltip, disabledLevelTooltips, labels, selectedLabelIds, onLabelsChange, onRemoveAccess, isRemoveDisabled, removeDisabledTooltip, dataTestId, }) {
|
|
35
|
+
export function UiPermissionMenu({ anchor, selectedLevel, onPermissionChange, disabledLevels, disabledTooltip, disabledLevelTooltips, labels, selectedLabelIds, onLabelsChange, onRemoveAccess, isRemoveDisabled, removeDisabledTooltip, removeAccessLabel, dataTestId, }) {
|
|
37
36
|
const hasLabels = (labels?.length ?? 0) > 0;
|
|
38
|
-
return (_jsx(UiPopover, { anchor: anchor, anchorAccessibilityConfig: { ariaHaspopup: "menu" }, width: hasLabels ? 200 : 180, content: ({ onClose }) => (_jsx(MenuBody, { selectedLevel: selectedLevel, onPermissionChange: onPermissionChange, disabledLevels: disabledLevels, disabledTooltip: disabledTooltip, disabledLevelTooltips: disabledLevelTooltips, labels: labels, selectedLabelIds: selectedLabelIds, onLabelsChange: onLabelsChange, onRemoveAccess: onRemoveAccess, isRemoveDisabled: isRemoveDisabled, removeDisabledTooltip: removeDisabledTooltip, onClose: onClose, dataTestId: dataTestId })) }));
|
|
37
|
+
return (_jsx(UiPopover, { anchor: anchor, anchorAccessibilityConfig: { ariaHaspopup: "menu" }, width: hasLabels ? 200 : 180, content: ({ onClose }) => (_jsx(MenuBody, { selectedLevel: selectedLevel, onPermissionChange: onPermissionChange, disabledLevels: disabledLevels, disabledTooltip: disabledTooltip, disabledLevelTooltips: disabledLevelTooltips, labels: labels, selectedLabelIds: selectedLabelIds, onLabelsChange: onLabelsChange, onRemoveAccess: onRemoveAccess, isRemoveDisabled: isRemoveDisabled, removeDisabledTooltip: removeDisabledTooltip, removeAccessLabel: removeAccessLabel, onClose: onClose, dataTestId: dataTestId })) }));
|
|
39
38
|
}
|
|
40
|
-
function MenuBody({ selectedLevel, onPermissionChange, disabledLevels, disabledTooltip, disabledLevelTooltips, labels, selectedLabelIds, onLabelsChange, onRemoveAccess, isRemoveDisabled, removeDisabledTooltip, onClose, dataTestId, }) {
|
|
39
|
+
function MenuBody({ selectedLevel, onPermissionChange, disabledLevels, disabledTooltip, disabledLevelTooltips, labels, selectedLabelIds, onLabelsChange, onRemoveAccess, isRemoveDisabled, removeDisabledTooltip, removeAccessLabel, onClose, dataTestId, }) {
|
|
41
40
|
const intl = useIntl();
|
|
42
41
|
// Drill-in state — swaps the row list for the labels checklist. Local to the
|
|
43
42
|
// popover content, so it resets every time the menu opens. `origin` is what
|
|
@@ -54,30 +53,28 @@ function MenuBody({ selectedLevel, onPermissionChange, disabledLevels, disabledT
|
|
|
54
53
|
onClose();
|
|
55
54
|
};
|
|
56
55
|
const hasLabels = (labels?.length ?? 0) > 0;
|
|
57
|
-
const levelItem = (level, label
|
|
56
|
+
const levelItem = (level, label) => {
|
|
58
57
|
const disabled = disabledLevels?.includes(level) ?? false;
|
|
59
58
|
return {
|
|
60
59
|
key: level,
|
|
61
60
|
label,
|
|
62
|
-
//
|
|
63
|
-
|
|
64
|
-
tooltip: disabled ? (disabledLevelTooltips?.[level] ?? disabledTooltip) || tooltip : tooltip,
|
|
61
|
+
// Only a disabled level explains itself — why it can't be picked.
|
|
62
|
+
tooltip: disabled ? (disabledLevelTooltips?.[level] ?? disabledTooltip) : undefined,
|
|
65
63
|
radioValue: level,
|
|
66
64
|
disabled,
|
|
67
65
|
onClick: disabled ? () => { } : choose(() => onPermissionChange(level)),
|
|
68
66
|
};
|
|
69
67
|
};
|
|
70
68
|
const levelItems = [
|
|
71
|
-
levelItem("EDIT", intl.formatMessage(olpPermissionMessages.canEditAndShare)
|
|
72
|
-
levelItem("SHARE", intl.formatMessage(olpPermissionMessages.canViewAndShare)
|
|
73
|
-
levelItem("VIEW", intl.formatMessage(olpPermissionMessages.canView)
|
|
69
|
+
levelItem("EDIT", intl.formatMessage(olpPermissionMessages.canEditAndShare)),
|
|
70
|
+
levelItem("SHARE", intl.formatMessage(olpPermissionMessages.canViewAndShare)),
|
|
71
|
+
levelItem("VIEW", intl.formatMessage(olpPermissionMessages.canView)),
|
|
74
72
|
];
|
|
75
73
|
const actionItems = [];
|
|
76
74
|
if (hasLabels) {
|
|
77
75
|
actionItems.push({
|
|
78
76
|
key: "labels",
|
|
79
77
|
label: intl.formatMessage(olpPermissionMessages.labels),
|
|
80
|
-
icon: "ldmLabel",
|
|
81
78
|
iconRight: "navigateRight",
|
|
82
79
|
// Drill in — the checklist owns Back/Cancel/Apply and closes the menu itself.
|
|
83
80
|
onClick: () => setView({ view: "labels", origin: "nav" }),
|
|
@@ -88,8 +85,7 @@ function MenuBody({ selectedLevel, onPermissionChange, disabledLevels, disabledT
|
|
|
88
85
|
// row can explain why instead of the action silently going missing.
|
|
89
86
|
actionItems.push({
|
|
90
87
|
key: "remove",
|
|
91
|
-
label: intl.formatMessage(olpPermissionMessages.removeAccess),
|
|
92
|
-
icon: "trash",
|
|
88
|
+
label: removeAccessLabel ?? intl.formatMessage(olpPermissionMessages.removeAccess),
|
|
93
89
|
tooltip: isRemoveDisabled ? removeDisabledTooltip : undefined,
|
|
94
90
|
disabled: isRemoveDisabled,
|
|
95
91
|
onClick: isRemoveDisabled ? () => { } : choose(onRemoveAccess),
|
|
@@ -132,12 +128,6 @@ function MenuBody({ selectedLevel, onPermissionChange, disabledLevels, disabledT
|
|
|
132
128
|
autoFocus: item.key === "labels" && origin === "nav" }, item.key)))] }) }));
|
|
133
129
|
}
|
|
134
130
|
function PermissionMenuItem({ item, selectedLevel, autoFocus }) {
|
|
135
|
-
const intl = useIntl();
|
|
136
|
-
// Tooltip anchor must live OUTSIDE the menu-item button so we don't nest an
|
|
137
|
-
// interactive element inside a button (invalid HTML, breaks focus). The row
|
|
138
|
-
// wrapper provides the flex layout; the button covers the label; the
|
|
139
|
-
// tooltip sits next to the button.
|
|
140
|
-
//
|
|
141
131
|
// When this row opens as the drill-in return target, focus it as it mounts via
|
|
142
132
|
// a callback ref — no effect, and it can't race the button's mount.
|
|
143
133
|
const focusOnAttach = useCallback((node) => {
|
|
@@ -147,9 +137,10 @@ function PermissionMenuItem({ item, selectedLevel, autoFocus }) {
|
|
|
147
137
|
}, [autoFocus]);
|
|
148
138
|
const isRadio = !!item.radioValue;
|
|
149
139
|
const isChecked = isRadio && item.radioValue === selectedLevel;
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
140
|
+
// The visual tooltip exists only while open, so the explanation is also kept as a
|
|
141
|
+
// persistent hidden description the button points at for assistive tech.
|
|
142
|
+
const descriptionId = useId();
|
|
143
|
+
const button = (_jsxs("button", { type: "button", ref: focusOnAttach, role: isRadio ? "menuitemradio" : "menuitem", "aria-checked": isRadio ? isChecked : undefined, "aria-disabled": item.disabled ? true : undefined, "aria-describedby": item.tooltip ? descriptionId : undefined, className: e("item", { disabled: Boolean(item.disabled) }), onClick: item.onClick, children: [_jsx("span", { className: e("item-label"), children: item.label }), item.iconRight ? _jsx(UiIcon, { type: item.iconRight, size: 14, color: "complementary-7" }) : null] }));
|
|
144
|
+
return (_jsx("div", { className: e("item-row"), children: item.tooltip ? (_jsxs(_Fragment, { children: [_jsx(UiTooltip, { triggerBy: ["hover", "focus"], content: _jsx("div", { className: e("item-tooltip"), children: item.tooltip }), anchorWrapperStyles: ROW_ANCHOR_STYLES, anchor: button }), _jsx("span", { className: "sr-only", id: descriptionId, children: item.tooltip })] })) : (button) }));
|
|
155
145
|
}
|
|
146
|
+
const ROW_ANCHOR_STYLES = { display: "flex", flex: "1 1 auto", minWidth: 0 };
|
|
@@ -42,7 +42,7 @@ export function useResponsiveTags(tags, mode, deps) {
|
|
|
42
42
|
hiddenTagsContainerRef,
|
|
43
43
|
addButtonRef,
|
|
44
44
|
mode,
|
|
45
|
-
//
|
|
45
|
+
// oxlint-disable-next-line react-hooks/exhaustive-deps
|
|
46
46
|
...(deps ?? []),
|
|
47
47
|
]);
|
|
48
48
|
useLayoutEffect(() => {
|