@gooddata/sdk-ui-ext 11.45.0-alpha.0 → 11.45.0-alpha.2

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 (80) hide show
  1. package/NOTICE +3 -3
  2. package/esm/insightPicker/InsightPickerCore.d.ts +1 -1
  3. package/esm/insightPicker/InsightPickerCore.d.ts.map +1 -1
  4. package/esm/insightPicker/InsightPickerCore.js +2 -2
  5. package/esm/insightPicker/InsightPickerRow.d.ts +1 -2
  6. package/esm/insightPicker/InsightPickerRow.d.ts.map +1 -1
  7. package/esm/insightPicker/InsightPickerRow.js +2 -2
  8. package/esm/insightPicker/types.d.ts +0 -1
  9. package/esm/insightPicker/types.d.ts.map +1 -1
  10. package/esm/internal/components/configurationPanels/ConfigurationPanelContent.d.ts.map +1 -1
  11. package/esm/internal/components/configurationPanels/ConfigurationPanelContent.js +4 -8
  12. package/esm/internal/components/dialogs/userManagementDialogs/DataSources/AddDataSourceSelect.d.ts.map +1 -1
  13. package/esm/internal/components/dialogs/userManagementDialogs/DataSources/AddDataSourceSelect.js +6 -1
  14. package/esm/internal/components/dialogs/userManagementDialogs/DataSources/DataSourceItem.d.ts.map +1 -1
  15. package/esm/internal/components/dialogs/userManagementDialogs/DataSources/DataSourceItem.js +10 -2
  16. package/esm/internal/components/dialogs/userManagementDialogs/DataSources/locales.d.ts +3 -0
  17. package/esm/internal/components/dialogs/userManagementDialogs/DataSources/locales.d.ts.map +1 -1
  18. package/esm/internal/components/dialogs/userManagementDialogs/DataSources/locales.js +2 -1
  19. package/esm/internal/components/dialogs/userManagementDialogs/Details/EditUserDetails.d.ts +1 -1
  20. package/esm/internal/components/dialogs/userManagementDialogs/Details/EditUserDetails.d.ts.map +1 -1
  21. package/esm/internal/components/dialogs/userManagementDialogs/Details/detailsHooks.d.ts +1 -1
  22. package/esm/internal/components/dialogs/userManagementDialogs/UserEditDialog.d.ts.map +1 -1
  23. package/esm/internal/components/dialogs/userManagementDialogs/UserEditDialog.js +11 -4
  24. package/esm/internal/components/dialogs/userManagementDialogs/UserGroupEditDialog.d.ts.map +1 -1
  25. package/esm/internal/components/dialogs/userManagementDialogs/UserGroupEditDialog.js +8 -3
  26. package/esm/internal/components/dialogs/userManagementDialogs/Workspace/AddSingleWorkspaceSelect.d.ts.map +1 -1
  27. package/esm/internal/components/dialogs/userManagementDialogs/Workspace/AddSingleWorkspaceSelect.js +7 -2
  28. package/esm/internal/components/dialogs/userManagementDialogs/Workspace/AddWorkspaceSelect.d.ts.map +1 -1
  29. package/esm/internal/components/dialogs/userManagementDialogs/Workspace/AddWorkspaceSelect.js +5 -1
  30. package/esm/internal/components/dialogs/userManagementDialogs/Workspace/WorkspaceItem/GranularPermissionsWorkspaceItem.d.ts.map +1 -1
  31. package/esm/internal/components/dialogs/userManagementDialogs/Workspace/WorkspaceItem/GranularPermissionsWorkspaceItem.js +9 -2
  32. package/esm/internal/components/dialogs/userManagementDialogs/Workspace/WorkspaceItem/InheritedIcon.d.ts +12 -0
  33. package/esm/internal/components/dialogs/userManagementDialogs/Workspace/WorkspaceItem/InheritedIcon.d.ts.map +1 -0
  34. package/esm/internal/components/dialogs/userManagementDialogs/Workspace/WorkspaceItem/InheritedIcon.js +12 -0
  35. package/esm/internal/components/dialogs/userManagementDialogs/Workspace/WorkspaceItem/locales.d.ts +6 -0
  36. package/esm/internal/components/dialogs/userManagementDialogs/Workspace/WorkspaceItem/locales.d.ts.map +1 -1
  37. package/esm/internal/components/dialogs/userManagementDialogs/Workspace/WorkspaceItem/locales.js +3 -1
  38. package/esm/internal/components/dialogs/userManagementDialogs/dialogHooks.d.ts +10 -2
  39. package/esm/internal/components/dialogs/userManagementDialogs/dialogHooks.d.ts.map +1 -1
  40. package/esm/internal/components/dialogs/userManagementDialogs/dialogHooks.js +15 -11
  41. package/esm/internal/components/dialogs/userManagementDialogs/hooks/usePermissions.d.ts +10 -3
  42. package/esm/internal/components/dialogs/userManagementDialogs/hooks/usePermissions.d.ts.map +1 -1
  43. package/esm/internal/components/dialogs/userManagementDialogs/hooks/usePermissions.js +59 -34
  44. package/esm/internal/components/dialogs/userManagementDialogs/locales.d.ts +3 -0
  45. package/esm/internal/components/dialogs/userManagementDialogs/locales.d.ts.map +1 -1
  46. package/esm/internal/components/dialogs/userManagementDialogs/locales.js +1 -0
  47. package/esm/internal/components/dialogs/userManagementDialogs/types.d.ts +20 -1
  48. package/esm/internal/components/dialogs/userManagementDialogs/types.d.ts.map +1 -1
  49. package/esm/internal/components/dialogs/userManagementDialogs/types.js +1 -1
  50. package/esm/internal/components/dialogs/userManagementDialogs/utils.d.ts +2 -0
  51. package/esm/internal/components/dialogs/userManagementDialogs/utils.d.ts.map +1 -1
  52. package/esm/internal/components/dialogs/userManagementDialogs/utils.js +40 -1
  53. package/esm/internal/components/pluggableVisualizations/baseChart/PluggableBaseChart.d.ts.map +1 -1
  54. package/esm/internal/components/pluggableVisualizations/baseChart/PluggableBaseChart.js +1 -1
  55. package/esm/internal/interfaces/Visualization.d.ts +1 -1
  56. package/esm/internal/interfaces/Visualization.d.ts.map +1 -1
  57. package/esm/internal/translations/en-US.localization-bundle.d.ts +24 -0
  58. package/esm/internal/translations/en-US.localization-bundle.d.ts.map +1 -1
  59. package/esm/internal/translations/en-US.localization-bundle.js +24 -0
  60. package/esm/internal/utils/bucketHelper.d.ts.map +1 -1
  61. package/esm/internal/utils/bucketHelper.js +10 -3
  62. package/esm/sdk-ui-ext.d.ts +55 -5
  63. package/esm/share/ObjectShareDialog.d.ts.map +1 -1
  64. package/esm/share/ObjectShareDialog.js +37 -5
  65. package/esm/share/messages.d.ts +18 -0
  66. package/esm/share/messages.d.ts.map +1 -1
  67. package/esm/share/messages.js +6 -0
  68. package/esm/share/objectShareController.types.d.ts +45 -5
  69. package/esm/share/objectShareController.types.d.ts.map +1 -1
  70. package/esm/share/useAccessList.d.ts +14 -2
  71. package/esm/share/useAccessList.d.ts.map +1 -1
  72. package/esm/share/useAccessList.js +29 -6
  73. package/esm/share/useObjectShareController.d.ts.map +1 -1
  74. package/esm/share/useObjectShareController.js +200 -2
  75. package/package.json +21 -21
  76. package/styles/css/main.css +15 -0
  77. package/styles/css/main.css.map +1 -1
  78. package/styles/internal/css/user_management_dialogs.css +15 -0
  79. package/styles/internal/css/user_management_dialogs.css.map +1 -1
  80. package/styles/internal/scss/user_management_dialogs.scss +22 -0
@@ -15,6 +15,7 @@ import { AutomationType } from '@gooddata/sdk-backend-spi';
15
15
  import { ChartInlineVisualizationType } from '@gooddata/sdk-ui-charts';
16
16
  import { ComponentType } from 'react';
17
17
  import { CopyCodeOriginType } from '@gooddata/sdk-ui-kit';
18
+ import { DataSourceAccessSource } from '@gooddata/sdk-model';
18
19
  import { Dispatch } from 'react';
19
20
  import { EmbedType } from '@gooddata/sdk-ui-kit';
20
21
  import { ExplicitDrill } from '@gooddata/sdk-ui';
@@ -47,6 +48,7 @@ import { IPivotTableConfig } from '@gooddata/sdk-ui-pivot';
47
48
  import { ISettings } from '@gooddata/sdk-model';
48
49
  import { ITab } from '@gooddata/sdk-ui-kit';
49
50
  import { ITheme } from '@gooddata/sdk-model';
51
+ import type { IUiGranteeAsyncOption } from '@gooddata/sdk-ui-kit';
50
52
  import type { IUiGranteeAsyncOptions } from '@gooddata/sdk-ui-kit';
51
53
  import type { IUiPickedGrantee } from '@gooddata/sdk-ui-kit';
52
54
  import { IUserWorkspaceSettings } from '@gooddata/sdk-backend-spi';
@@ -656,6 +658,15 @@ export declare interface IGrantedDataSource {
656
658
  id: string;
657
659
  title: string;
658
660
  permission: DataSourcePermission;
661
+ /**
662
+ * True when the data source is accessible only indirectly - inherited through a user group rather
663
+ * than assigned directly. Such entries are shown read-only.
664
+ */
665
+ isInherited?: boolean;
666
+ /**
667
+ * How the subject gains access to the data source (DIRECT, GROUP), when known.
668
+ */
669
+ accessSource?: DataSourceAccessSource;
659
670
  }
660
671
 
661
672
  /**
@@ -729,7 +740,6 @@ export declare interface IInsightPickerProps {
729
740
  author?: string;
730
741
  enabledVisualizationClassesUrls?: string[];
731
742
  selectedInsightId?: string;
732
- enableDescriptions?: boolean;
733
743
  metadataTimeZone?: string;
734
744
  enableSemanticSearch?: boolean;
735
745
  maxHeight?: number;
@@ -1454,11 +1464,13 @@ export declare interface IObjectShareControllerActions {
1454
1464
  closeAddGrantee: () => void;
1455
1465
  setPendingGrantees: (next: IUiPickedGrantee[]) => void;
1456
1466
  /**
1457
- * Loader for the add-grantee picker. Wraps `getAvailableAssignees` with
1467
+ * Loader for the grantee pickers. Wraps `getAvailableAssignees` with
1458
1468
  * client-side search + already-picked filtering, returning the picker's
1459
- * `{ groups, users }` shape.
1469
+ * `{ groups, users }` shape. By default excludes already-granted grantees
1470
+ * (add-grantee picker); pass `includeGranted` to keep them (transfer-ownership
1471
+ * picker, which may promote an existing viewer to owner).
1460
1472
  */
1461
- loadOptions: (search: string) => Promise<IUiGranteeAsyncOptions>;
1473
+ loadOptions: (search: string, includeGranted?: boolean) => Promise<IUiGranteeAsyncOptions>;
1462
1474
  /** Commit all pending grantees to the backend. */
1463
1475
  confirmAddGrantees: () => Promise<void>;
1464
1476
  /** Change the permission level for a single grantee. Auto-saves. */
@@ -1482,13 +1494,31 @@ export declare interface IObjectShareControllerActions {
1482
1494
  * already-granted rule.
1483
1495
  */
1484
1496
  changeWorkspaceLevel: (level: "VIEW" | "SHARE") => Promise<void>;
1497
+ /** Open the transfer-ownership subview with an empty picker. */
1498
+ openTransferOwnership: () => void;
1499
+ /** Close the transfer-ownership subview and clear its buffers; returns to main. */
1500
+ closeTransferOwnership: () => void;
1501
+ /**
1502
+ * Pick (or replace) the candidate new owner. Recomputes whether that user
1503
+ * already owns the object (`transferTargetIsOwner`).
1504
+ */
1505
+ setTransferTarget: (owner: IUiGranteeAsyncOption) => void;
1506
+ /** Toggle "Also remove my access" in the transfer dialog. */
1507
+ setTransferAlsoRemoveSelf: (next: boolean) => void;
1508
+ /**
1509
+ * Commit the ownership transfer: grant the picked user EDIT and downgrade the
1510
+ * current user to VIEW (or remove them if "Also remove my access" is set), in
1511
+ * one write. When the picked user already owns the object this transfers
1512
+ * nothing and only applies the self-access choice. Auto-saves.
1513
+ */
1514
+ confirmTransferOwnership: () => Promise<void>;
1485
1515
  }
1486
1516
 
1487
1517
  /**
1488
1518
  * @internal
1489
1519
  */
1490
1520
  export declare interface IObjectShareControllerState {
1491
- subview: "main" | "addGrantee";
1521
+ subview: "main" | "addGrantee" | "transferOwnership";
1492
1522
  status: "idle" | "loading" | "success" | "error" | "saving";
1493
1523
  error?: Error;
1494
1524
  /**
@@ -1537,6 +1567,26 @@ export declare interface IObjectShareControllerState {
1537
1567
  pendingGeneralAccess?: GeneralAccessValue;
1538
1568
  /** Grantees staged in the add-grantee dialog before confirmation. */
1539
1569
  pendingGrantees: IUiPickedGrantee[];
1570
+ /**
1571
+ * The user picked as the new owner in the transfer-ownership subview, or
1572
+ * undefined before one is chosen. Only users can own an object, so this is
1573
+ * never a group.
1574
+ */
1575
+ transferTarget: IUiGranteeAsyncOption | undefined;
1576
+ /**
1577
+ * Whether "Also remove my access" is checked in the transfer dialog. When
1578
+ * true the current user's grant is removed after the transfer; otherwise it
1579
+ * is downgraded to VIEW.
1580
+ */
1581
+ transferAlsoRemoveSelf: boolean;
1582
+ /**
1583
+ * Whether `transferTarget` already owns the object (already holds EDIT). When
1584
+ * true there is nothing to transfer — consumers show the "already an owner"
1585
+ * variant offering to remove the current user's own access instead.
1586
+ */
1587
+ transferTargetIsOwner: boolean;
1588
+ /** Whether the transfer write (or self-removal) is in flight. */
1589
+ transferSaving: boolean;
1540
1590
  }
1541
1591
 
1542
1592
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"ObjectShareDialog.d.ts","sourceRoot":"","sources":["../../src/share/ObjectShareDialog.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAS1E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC/E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAQpD;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACpC,gDAAgD;IAChD,MAAM,EAAE,wBAAwB,GAAG,SAAS,CAAC;IAC7C,wEAAwE;IACxE,WAAW,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,MAAM,EAAE,OAAO,CAAC;IAChB,sFAAsF;IACtF,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,4FAA0F;IAC1F,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB;;;;OAIG;IACH,MAAM,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAC7B;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;OAIG;IACH,UAAU,CAAC,EAAE,sBAAsB,CAAC;CACvC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAAC,EAC9B,MAAM,EACN,WAAW,EACX,MAAM,EACN,OAAO,EACP,OAAO,EACP,MAAM,EACN,aAAa,EACb,WAAW,EACX,UAAU,EACb,EAAE,uBAAuB,2CAmKzB"}
1
+ {"version":3,"file":"ObjectShareDialog.d.ts","sourceRoot":"","sources":["../../src/share/ObjectShareDialog.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAW1E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC/E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAQpD;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACpC,gDAAgD;IAChD,MAAM,EAAE,wBAAwB,GAAG,SAAS,CAAC;IAC7C,wEAAwE;IACxE,WAAW,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,MAAM,EAAE,OAAO,CAAC;IAChB,sFAAsF;IACtF,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,4FAA0F;IAC1F,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB;;;;OAIG;IACH,MAAM,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAC7B;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;OAIG;IACH,UAAU,CAAC,EAAE,sBAAsB,CAAC;CACvC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAAC,EAC9B,MAAM,EACN,WAAW,EACX,MAAM,EACN,OAAO,EACP,OAAO,EACP,MAAM,EACN,aAAa,EACb,WAAW,EACX,UAAU,EACb,EAAE,uBAAuB,2CAkPzB"}
@@ -2,7 +2,7 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
2
2
  // (C) 2026 GoodData Corporation
3
3
  import { useCallback } from "react";
4
4
  import { useIntl } from "react-intl";
5
- import { UiAddGranteeDialog, UiConfirmDialog, UiGranteeRowControls, UiObjectShareDialog, } from "@gooddata/sdk-ui-kit";
5
+ import { UiAddGranteeDialog, UiConfirmDialog, UiGranteeRowControls, UiObjectShareDialog, UiRadioRow, UiTransferOwnershipDialog, } from "@gooddata/sdk-ui-kit";
6
6
  import { objectShareMessages } from "./messages.js";
7
7
  import { useObjectShareController } from "./useObjectShareController.js";
8
8
  // The workspace row has no labels menu (see workspaceControls below), so its
@@ -43,8 +43,27 @@ export function ObjectShareDialog({ target, objectTitle, isOpen, onClose, onSave
43
43
  actions.reset();
44
44
  onClose();
45
45
  }, [actions, onClose]);
46
+ // Owner is always an individual user, so the transfer picker drops any groups
47
+ // the shared loader returns. `includeGranted` keeps already-granted users in
48
+ // the list — promoting an existing viewer to owner is a primary case.
49
+ //
50
+ // Depend on the stable `loadOptions` alone, not the whole `actions` object:
51
+ // `actions` changes identity as transfer state ticks (and as the picker's own
52
+ // name-cache writes re-derive grantees), and the autocomplete refetches page 0
53
+ // whenever its loader's identity changes — depending on `actions` here would
54
+ // self-feed into an infinite assignee-fetch loop.
55
+ const { loadOptions } = actions;
56
+ const loadOwnerOptions = useCallback(async (search) => {
57
+ const { users } = await loadOptions(search, true);
58
+ return { groups: [], users };
59
+ }, [loadOptions]);
46
60
  const isAddGranteeOpen = isOpen && state.subview === "addGrantee";
47
- const isShareOpen = isOpen && state.subview !== "addGrantee";
61
+ // The transfer subview splits into two co-mounted dialogs: the transfer card
62
+ // while picking a non-owner, and the "already an owner" confirm once the picked
63
+ // user already owns the object.
64
+ const isTransferOpen = isOpen && state.subview === "transferOwnership" && !state.transferTargetIsOwner;
65
+ const isAlreadyOwnerOpen = isOpen && state.subview === "transferOwnership" && state.transferTargetIsOwner;
66
+ const isShareOpen = isOpen && state.subview === "main";
48
67
  const isConfirmOpen = isOpen && !!state.pendingGeneralAccess;
49
68
  // Don't allow mutations until the access list has loaded: before then the
50
69
  // controller reports empty grantees + RESTRICTED, which is a placeholder, not
@@ -55,8 +74,13 @@ export function ObjectShareDialog({ target, objectTitle, isOpen, onClose, onSave
55
74
  // wrong labels). `labelsResolved` is false while labels are still loading and
56
75
  // when their fetch failed, so a pending/failed label set blocks every
57
76
  // access-changing control here — Add, row controls and general access alike.
77
+ // Also locked while a transfer-ownership write is committing: the transfer
78
+ // dialog can be dismissed (Back/Cancel/close) mid-save, so without this the
79
+ // user could return here and mutate other grantees concurrently with the
80
+ // in-flight ownership write — racing the same object's permissions with no
81
+ // refetch to reconcile. `transferSaving` clears when the transfer settles.
58
82
  const isLoaded = state.status === "success";
59
- const isMutable = isLoaded && state.labelsResolved;
83
+ const isMutable = isLoaded && state.labelsResolved && !state.transferSaving;
60
84
  const isAddDisabled = !isMutable;
61
85
  // Map the controller's labels to the picker's item shape; the primary label
62
86
  // is rendered locked (always selected, can't be unchecked).
@@ -78,13 +102,13 @@ export function ObjectShareDialog({ target, objectTitle, isOpen, onClose, onSave
78
102
  // probe in flight) — removing or re-scoping before then
79
103
  // would diff against the "assume all"/empty placeholder
80
104
  // and silently orphan real per-label grants.
81
- isDisabled: g.pending !== undefined || !state.labelsResolved, onLabelsChange: (selectedIds) => {
105
+ isDisabled: g.pending !== undefined || !state.labelsResolved || state.transferSaving, onLabelsChange: (selectedIds) => {
82
106
  void actions.changeGranteeLabels(g.id, selectedIds);
83
107
  }, onPermissionChange: (level) => {
84
108
  void actions.changePermissionLevel(g.id, level);
85
109
  }, onRemoveAccess: () => {
86
110
  void actions.removeGrantee(g.id);
87
- } })),
111
+ }, onTransferOwnership: actions.openTransferOwnership })),
88
112
  })), onAddClick: actions.openAddGrantee, isAddDisabled: isAddDisabled, generalAccess: state.generalAccess, onGeneralAccessChange: actions.requestGeneralAccessChange,
89
113
  // Permission dropdown on the "All workspace members" row — only while
90
114
  // workspace access is on (the rule must exist to be re-graded). No
@@ -112,6 +136,14 @@ export function ObjectShareDialog({ target, objectTitle, isOpen, onClose, onSave
112
136
  // read as "no one has access".
113
137
  error: state.status === "error" ? intl.formatMessage(objectShareMessages.loadError) : undefined }), _jsx(UiAddGranteeDialog, { isOpen: isAddGranteeOpen, objectTitle: objectTitle, loadOptions: actions.loadOptions, selectedGrantees: state.pendingGrantees, onSelectedGranteesChange: actions.setPendingGrantees, onBack: actions.closeAddGrantee, onClose: handleClose, onCancel: actions.closeAddGrantee, onShare: () => {
114
138
  void actions.confirmAddGrantees();
139
+ } }), _jsx(UiTransferOwnershipDialog, { isOpen: isTransferOpen, objectTitle: objectTitle, loadOptions: loadOwnerOptions, selectedOwner: state.transferTarget, onSelectedOwnerChange: actions.setTransferTarget, alsoRemoveMyAccess: state.transferAlsoRemoveSelf, onAlsoRemoveMyAccessChange: actions.setTransferAlsoRemoveSelf, onBack: actions.closeTransferOwnership, onClose: handleClose, onCancel: actions.closeTransferOwnership, onTransfer: () => {
140
+ void actions.confirmTransferOwnership();
141
+ }, isSaving: state.transferSaving }), _jsx(UiConfirmDialog, { isOpen: isAlreadyOwnerOpen, title: intl.formatMessage(objectShareMessages.transferAlreadyOwnerTitle, {
142
+ name: state.transferTarget?.name ?? "",
143
+ }), description: _jsxs(_Fragment, { children: [
144
+ _jsx("p", { children: intl.formatMessage(objectShareMessages.transferAlreadyOwnerDescription) }), _jsx(UiRadioRow, { name: "transfer-already-owner", checked: !state.transferAlsoRemoveSelf, onChange: () => actions.setTransferAlsoRemoveSelf(false), title: intl.formatMessage(objectShareMessages.transferAlreadyOwnerKeepAccess) }), _jsx(UiRadioRow, { name: "transfer-already-owner", checked: state.transferAlsoRemoveSelf, onChange: () => actions.setTransferAlsoRemoveSelf(true), title: intl.formatMessage(objectShareMessages.transferAlreadyOwnerRemoveAccess) })
145
+ ] }), confirmLabel: intl.formatMessage(objectShareMessages.transferConfirmButton), confirmVariant: "primary", onCancel: actions.closeTransferOwnership, onClose: actions.closeTransferOwnership, onConfirm: () => {
146
+ void actions.confirmTransferOwnership();
115
147
  } }), _jsx(UiConfirmDialog, { isOpen: isConfirmOpen, title: intl.formatMessage(state.pendingGeneralAccess === "RESTRICTED"
116
148
  ? objectShareMessages.confirmRestrictTitle
117
149
  : objectShareMessages.confirmGrantWorkspaceTitle), description: intl.formatMessage(state.pendingGeneralAccess === "RESTRICTED"
@@ -22,6 +22,21 @@ export declare const objectShareMessages: {
22
22
  confirmButton: {
23
23
  id: string;
24
24
  };
25
+ transferAlreadyOwnerTitle: {
26
+ id: string;
27
+ };
28
+ transferAlreadyOwnerDescription: {
29
+ id: string;
30
+ };
31
+ transferAlreadyOwnerKeepAccess: {
32
+ id: string;
33
+ };
34
+ transferAlreadyOwnerRemoveAccess: {
35
+ id: string;
36
+ };
37
+ transferConfirmButton: {
38
+ id: string;
39
+ };
25
40
  toastGranteeAdded: {
26
41
  id: string;
27
42
  };
@@ -31,6 +46,9 @@ export declare const objectShareMessages: {
31
46
  toastGeneralAccessUpdated: {
32
47
  id: string;
33
48
  };
49
+ toastOwnershipTransferred: {
50
+ id: string;
51
+ };
34
52
  toastError: {
35
53
  id: string;
36
54
  };
@@ -1 +1 @@
1
- {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/share/messages.ts"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAY9B,CAAC"}
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/share/messages.ts"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkB9B,CAAC"}
@@ -14,9 +14,15 @@ export const objectShareMessages = defineMessages({
14
14
  confirmGrantWorkspaceTitle: { id: "objectShare.confirm.grantWorkspace.title" },
15
15
  confirmGrantWorkspaceDescription: { id: "objectShare.confirm.grantWorkspace.description" },
16
16
  confirmButton: { id: "objectShare.confirm.button" },
17
+ transferAlreadyOwnerTitle: { id: "objectShare.transfer.alreadyOwner.title" },
18
+ transferAlreadyOwnerDescription: { id: "objectShare.transfer.alreadyOwner.description" },
19
+ transferAlreadyOwnerKeepAccess: { id: "objectShare.transfer.alreadyOwner.keepAccess" },
20
+ transferAlreadyOwnerRemoveAccess: { id: "objectShare.transfer.alreadyOwner.removeAccess" },
21
+ transferConfirmButton: { id: "objectShare.transfer.confirmButton" },
17
22
  toastGranteeAdded: { id: "objectShare.toast.granteeAdded" },
18
23
  toastAccessUpdated: { id: "objectShare.toast.accessUpdated" },
19
24
  toastGeneralAccessUpdated: { id: "objectShare.toast.generalAccessUpdated" },
25
+ toastOwnershipTransferred: { id: "objectShare.toast.ownershipTransferred" },
20
26
  toastError: { id: "objectShare.toast.error" },
21
27
  toastLabelScopePartial: { id: "objectShare.toast.labelScopePartial" },
22
28
  loadError: { id: "objectShare.loadError" },
@@ -1,5 +1,5 @@
1
1
  import type { AccessGranularPermission, ObjRef } from "@gooddata/sdk-model";
2
- import type { GeneralAccessValue, IUiGranteeAsyncOptions, IUiPickedGrantee } from "@gooddata/sdk-ui-kit";
2
+ import type { GeneralAccessValue, IUiGranteeAsyncOption, IUiGranteeAsyncOptions, IUiPickedGrantee } from "@gooddata/sdk-ui-kit";
3
3
  import type { IObjectAccessSummary, IObjectShareLabel } from "./types.js";
4
4
  /**
5
5
  * Permission level surfaced in the share dialog — the model's granular access
@@ -48,7 +48,7 @@ export interface IObjectShareGrantee {
48
48
  * @internal
49
49
  */
50
50
  export interface IObjectShareControllerState {
51
- subview: "main" | "addGrantee";
51
+ subview: "main" | "addGrantee" | "transferOwnership";
52
52
  status: "idle" | "loading" | "success" | "error" | "saving";
53
53
  error?: Error;
54
54
  /**
@@ -97,6 +97,26 @@ export interface IObjectShareControllerState {
97
97
  pendingGeneralAccess?: GeneralAccessValue;
98
98
  /** Grantees staged in the add-grantee dialog before confirmation. */
99
99
  pendingGrantees: IUiPickedGrantee[];
100
+ /**
101
+ * The user picked as the new owner in the transfer-ownership subview, or
102
+ * undefined before one is chosen. Only users can own an object, so this is
103
+ * never a group.
104
+ */
105
+ transferTarget: IUiGranteeAsyncOption | undefined;
106
+ /**
107
+ * Whether "Also remove my access" is checked in the transfer dialog. When
108
+ * true the current user's grant is removed after the transfer; otherwise it
109
+ * is downgraded to VIEW.
110
+ */
111
+ transferAlsoRemoveSelf: boolean;
112
+ /**
113
+ * Whether `transferTarget` already owns the object (already holds EDIT). When
114
+ * true there is nothing to transfer — consumers show the "already an owner"
115
+ * variant offering to remove the current user's own access instead.
116
+ */
117
+ transferTargetIsOwner: boolean;
118
+ /** Whether the transfer write (or self-removal) is in flight. */
119
+ transferSaving: boolean;
100
120
  }
101
121
  /**
102
122
  * @internal
@@ -108,11 +128,13 @@ export interface IObjectShareControllerActions {
108
128
  closeAddGrantee: () => void;
109
129
  setPendingGrantees: (next: IUiPickedGrantee[]) => void;
110
130
  /**
111
- * Loader for the add-grantee picker. Wraps `getAvailableAssignees` with
131
+ * Loader for the grantee pickers. Wraps `getAvailableAssignees` with
112
132
  * client-side search + already-picked filtering, returning the picker's
113
- * `{ groups, users }` shape.
133
+ * `{ groups, users }` shape. By default excludes already-granted grantees
134
+ * (add-grantee picker); pass `includeGranted` to keep them (transfer-ownership
135
+ * picker, which may promote an existing viewer to owner).
114
136
  */
115
- loadOptions: (search: string) => Promise<IUiGranteeAsyncOptions>;
137
+ loadOptions: (search: string, includeGranted?: boolean) => Promise<IUiGranteeAsyncOptions>;
116
138
  /** Commit all pending grantees to the backend. */
117
139
  confirmAddGrantees: () => Promise<void>;
118
140
  /** Change the permission level for a single grantee. Auto-saves. */
@@ -136,6 +158,24 @@ export interface IObjectShareControllerActions {
136
158
  * already-granted rule.
137
159
  */
138
160
  changeWorkspaceLevel: (level: "VIEW" | "SHARE") => Promise<void>;
161
+ /** Open the transfer-ownership subview with an empty picker. */
162
+ openTransferOwnership: () => void;
163
+ /** Close the transfer-ownership subview and clear its buffers; returns to main. */
164
+ closeTransferOwnership: () => void;
165
+ /**
166
+ * Pick (or replace) the candidate new owner. Recomputes whether that user
167
+ * already owns the object (`transferTargetIsOwner`).
168
+ */
169
+ setTransferTarget: (owner: IUiGranteeAsyncOption) => void;
170
+ /** Toggle "Also remove my access" in the transfer dialog. */
171
+ setTransferAlsoRemoveSelf: (next: boolean) => void;
172
+ /**
173
+ * Commit the ownership transfer: grant the picked user EDIT and downgrade the
174
+ * current user to VIEW (or remove them if "Also remove my access" is set), in
175
+ * one write. When the picked user already owns the object this transfers
176
+ * nothing and only applies the self-access choice. Auto-saves.
177
+ */
178
+ confirmTransferOwnership: () => Promise<void>;
139
179
  }
140
180
  /**
141
181
  * @internal
@@ -1 +1 @@
1
- {"version":3,"file":"objectShareController.types.d.ts","sourceRoot":"","sources":["../../src/share/objectShareController.types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"objectShareController.types.d.ts","sourceRoot":"","sources":["../../src/share/objectShareController.types.ts"],"names":[],"mappings":"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"}
@@ -36,8 +36,20 @@ export interface IAccessList {
36
36
  commit: (mutate: IGranularAccessGrantee[], successMessage: {
37
37
  id: string;
38
38
  }) => Promise<boolean>;
39
- /** Picker loader — available assignees minus already-granted, filtered by query. */
40
- loadOptions: (search: string) => Promise<IUiGranteeAsyncOptions>;
39
+ /**
40
+ * Picker loader available assignees filtered by query. By default excludes
41
+ * already-granted grantees (add-grantee picker); pass `includeGranted` to keep
42
+ * them (transfer-ownership picker, which may promote an existing viewer).
43
+ */
44
+ loadOptions: (search: string, includeGranted?: boolean) => Promise<IUiGranteeAsyncOptions>;
45
+ /**
46
+ * The current user's ref, resolved on demand (and cached). Used by the
47
+ * transfer-ownership flow to write the current user's own grant change. The
48
+ * add-grantee *picker* excludes the current user, but `getAccessList` does
49
+ * not, so a self grant can still appear as a row. Rejects if the profile
50
+ * can't be read.
51
+ */
52
+ getCurrentUserRef: () => Promise<ObjRef>;
41
53
  /** Resolve a grantee id back to the picker's original ObjRef (preserves Uri vs Id ref). */
42
54
  refForId: (id: string) => ObjRef;
43
55
  /** Write through a local grantee-row change (insert / level / remove); rolled back by the caller. */
@@ -1 +1 @@
1
- {"version":3,"file":"useAccessList.d.ts","sourceRoot":"","sources":["../../src/share/useAccessList.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAC1E,OAAO,EAEH,KAAK,sBAAsB,EAC3B,KAAK,MAAM,EAEd,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,KAAK,kBAAkB,EAAE,KAAK,sBAAsB,EAAmB,MAAM,sBAAsB,CAAC;AAW7G,OAAO,KAAK,EAAE,2BAA2B,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACzG,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEvD;;;;GAIG;AACH,MAAM,WAAW,WAAW;IACxB,iFAAiF;IACjF,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,wFAAwF;IACxF,OAAO,EAAE,OAAO,CAAC;IACjB,iGAA+F;IAC/F,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC,uFAAqF;IACrF,aAAa,EAAE,kBAAkB,CAAC;IAClC,6FAA2F;IAC3F,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC;IACjC,iEAAiE;IACjE,OAAO,EAAE,oBAAoB,GAAG,SAAS,CAAC;IAC1C,+DAA+D;IAC/D,MAAM,EAAE,2BAA2B,CAAC,QAAQ,CAAC,CAAC;IAC9C,iDAAiD;IACjD,SAAS,EAAE,KAAK,GAAG,SAAS,CAAC;IAC7B;;;;;OAKG;IACH,iBAAiB,EAAE,OAAO,CAAC;IAE3B,mFAAmF;IACnF,MAAM,EAAE,CAAC,MAAM,EAAE,sBAAsB,EAAE,EAAE,cAAc,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/F,sFAAoF;IACpF,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACjE,2FAA2F;IAC3F,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC;IAEjC,qGAAqG;IACrG,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,mBAAmB,EAAE,CAAC,CAAC,CAAC;IACzE,8EAA8E;IAC9E,gBAAgB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,kBAAkB,CAAC,CAAC,CAAC;IAC3E;;;;OAIG;IACH,iBAAiB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAC1E,aAAa,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;CAC/E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CACzB,MAAM,EAAE,wBAAwB,GAAG,SAAS,EAC5C,OAAO,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,GAClC,WAAW,CA4Qb"}
1
+ {"version":3,"file":"useAccessList.d.ts","sourceRoot":"","sources":["../../src/share/useAccessList.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAC1E,OAAO,EAEH,KAAK,sBAAsB,EAC3B,KAAK,MAAM,EAEd,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,KAAK,kBAAkB,EAAE,KAAK,sBAAsB,EAAmB,MAAM,sBAAsB,CAAC;AAW7G,OAAO,KAAK,EAAE,2BAA2B,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACzG,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEvD;;;;GAIG;AACH,MAAM,WAAW,WAAW;IACxB,iFAAiF;IACjF,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,wFAAwF;IACxF,OAAO,EAAE,OAAO,CAAC;IACjB,iGAA+F;IAC/F,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC,uFAAqF;IACrF,aAAa,EAAE,kBAAkB,CAAC;IAClC,6FAA2F;IAC3F,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC;IACjC,iEAAiE;IACjE,OAAO,EAAE,oBAAoB,GAAG,SAAS,CAAC;IAC1C,+DAA+D;IAC/D,MAAM,EAAE,2BAA2B,CAAC,QAAQ,CAAC,CAAC;IAC9C,iDAAiD;IACjD,SAAS,EAAE,KAAK,GAAG,SAAS,CAAC;IAC7B;;;;;OAKG;IACH,iBAAiB,EAAE,OAAO,CAAC;IAE3B,mFAAmF;IACnF,MAAM,EAAE,CAAC,MAAM,EAAE,sBAAsB,EAAE,EAAE,cAAc,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/F;;;;OAIG;IACH,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,sBAAsB,CAAC,CAAC;IAC3F;;;;;;OAMG;IACH,iBAAiB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,2FAA2F;IAC3F,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC;IAEjC,qGAAqG;IACrG,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,mBAAmB,EAAE,CAAC,CAAC,CAAC;IACzE,8EAA8E;IAC9E,gBAAgB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,kBAAkB,CAAC,CAAC,CAAC;IAC3E;;;;OAIG;IACH,iBAAiB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAC1E,aAAa,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;CAC/E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CACzB,MAAM,EAAE,wBAAwB,GAAG,SAAS,EAC5C,OAAO,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,GAClC,WAAW,CAoSb"}
@@ -1,5 +1,5 @@
1
1
  // (C) 2026 GoodData Corporation
2
- import { useCallback, useEffect, useMemo, useState } from "react";
2
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
3
3
  import { objRefToString, } from "@gooddata/sdk-model";
4
4
  import { useBackendStrict, useCancelablePromise, useWorkspaceStrict } from "@gooddata/sdk-ui";
5
5
  import { useToastMessage } from "@gooddata/sdk-ui-kit";
@@ -41,6 +41,9 @@ export function useAccessList(target, onSaved) {
41
41
  // Original ObjRef per grantee id, learned from the picker (the access-list id
42
42
  // is a serialized `kind:identifier`, which loses Uri-vs-Id). Reused for writes.
43
43
  const [knownRefs, setKnownRefs] = useState({});
44
+ // Memoized current-user-ref fetch — the profile doesn't change while mounted,
45
+ // so resolve it at most once and share the promise across callers.
46
+ const currentUserRefCache = useRef(undefined);
44
47
  const targetKey = target ? objRefToString(target.ref) : undefined;
45
48
  // Learn each assignee's real name + ref into the caches, keyed by the same
46
49
  // grantee id the rows use. Written from both the picker (loadOptions) and the
@@ -190,10 +193,14 @@ export function useAccessList(target, onSaved) {
190
193
  }
191
194
  }, [backend, workspace, target, toast, onSaved]);
192
195
  // Picker loader — fetches available assignees on demand, filters by the typed
193
- // query, excludes anything already granted. Depends only on the granted set
194
- // (grantees), so its identity changes only when that set actually changes. It
195
- // must NOT write state that feeds its own deps.
196
- const loadOptions = useCallback(async (search) => {
196
+ // query, and by default excludes anything already granted. Depends only on the
197
+ // granted set (grantees), so its identity changes only when that set actually
198
+ // changes. It must NOT write state that feeds its own deps.
199
+ //
200
+ // `includeGranted` keeps already-granted grantees in the result. The
201
+ // transfer-ownership picker needs this: promoting an existing viewer to owner
202
+ // is a primary case, and the add-grantee exclusion would otherwise hide them.
203
+ const loadOptions = useCallback(async (search, includeGranted = false) => {
197
204
  if (!target) {
198
205
  return { groups: [], users: [] };
199
206
  }
@@ -210,7 +217,7 @@ export function useAccessList(target, onSaved) {
210
217
  // even when the access-list grant later returns only a raw id. Safe here:
211
218
  // the caches aren't dependencies of loadOptions, so this won't re-trigger it.
212
219
  cacheAssignees(assignees);
213
- const excluded = new Set(excludedIdsKey ? excludedIdsKey.split(",") : []);
220
+ const excluded = new Set(includeGranted || !excludedIdsKey ? [] : excludedIdsKey.split(","));
214
221
  const selectable = withIds
215
222
  .filter(({ id }) => !excluded.has(id)) // hide anyone already granted
216
223
  .filter(({ assignee }) => assigneeMatchesQuery(assignee, query));
@@ -231,6 +238,21 @@ export function useAccessList(target, onSaved) {
231
238
  // Reuse the picker's original ref (preserves UriRef vs IdentifierRef);
232
239
  // fall back to the serialized id only if it wasn't cached.
233
240
  const refForId = useCallback((id) => knownRefs[id] ?? { identifier: id.split(":", 2)[1] }, [knownRefs]);
241
+ const getCurrentUserRef = useCallback(async () => {
242
+ if (!currentUserRefCache.current) {
243
+ currentUserRefCache.current = backend
244
+ .currentUser()
245
+ .getUser()
246
+ .then((user) => user.ref)
247
+ .catch((error) => {
248
+ // Don't cache a rejected promise, or a transient profile-read
249
+ // failure would make every later transfer fail immediately.
250
+ currentUserRefCache.current = undefined;
251
+ throw error;
252
+ });
253
+ }
254
+ return currentUserRefCache.current;
255
+ }, [backend]);
234
256
  return {
235
257
  targetKey,
236
258
  hasList,
@@ -244,6 +266,7 @@ export function useAccessList(target, onSaved) {
244
266
  commit,
245
267
  loadOptions,
246
268
  refForId,
269
+ getCurrentUserRef,
247
270
  setGrantees,
248
271
  setGeneralAccess,
249
272
  setWorkspaceLevel,
@@ -1 +1 @@
1
- {"version":3,"file":"useObjectShareController.d.ts","sourceRoot":"","sources":["../../src/share/useObjectShareController.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAa1E,OAAO,EACH,KAAK,sBAAsB,EAI3B,KAAK,sBAAsB,EAE9B,MAAM,kCAAkC,CAAC;AAI1C;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,wBAAwB,CACpC,MAAM,EAAE,wBAAwB,GAAG,SAAS,EAC5C,OAAO,CAAC,EAAE,sBAAsB,GACjC,sBAAsB,CA8jBxB"}
1
+ {"version":3,"file":"useObjectShareController.d.ts","sourceRoot":"","sources":["../../src/share/useObjectShareController.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAkB1E,OAAO,EACH,KAAK,sBAAsB,EAI3B,KAAK,sBAAsB,EAE9B,MAAM,kCAAkC,CAAC;AAI1C;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,wBAAwB,CACpC,MAAM,EAAE,wBAAwB,GAAG,SAAS,EAC5C,OAAO,CAAC,EAAE,sBAAsB,GACjC,sBAAsB,CAwyBxB"}