@gooddata/sdk-ui-ext 11.43.0-alpha.2 → 11.43.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.
Files changed (171) hide show
  1. package/NOTICE +4826 -13873
  2. package/esm/index.d.ts +2 -2
  3. package/esm/index.d.ts.map +1 -1
  4. package/esm/index.js +1 -1
  5. package/esm/internal/components/configurationControls/ConfigSection.d.ts +2 -1
  6. package/esm/internal/components/configurationControls/ConfigSection.d.ts.map +1 -1
  7. package/esm/internal/components/configurationControls/ConfigSection.js +7 -3
  8. package/esm/internal/components/configurationControls/colors/colorDropdown/ColorDropdown.d.ts +4 -0
  9. package/esm/internal/components/configurationControls/colors/colorDropdown/ColorDropdown.d.ts.map +1 -1
  10. package/esm/internal/components/configurationControls/colors/colorDropdown/ColorDropdown.js +13 -2
  11. package/esm/internal/components/configurationControls/colors/colorDropdown/ColorPalette.d.ts +5 -0
  12. package/esm/internal/components/configurationControls/colors/colorDropdown/ColorPalette.d.ts.map +1 -1
  13. package/esm/internal/components/configurationControls/colors/colorDropdown/ColorPalette.js +5 -3
  14. package/esm/internal/components/configurationControls/conditionalFormatting/ConditionalFormattingDialog.d.ts +13 -0
  15. package/esm/internal/components/configurationControls/conditionalFormatting/ConditionalFormattingDialog.d.ts.map +1 -0
  16. package/esm/internal/components/configurationControls/conditionalFormatting/ConditionalFormattingDialog.js +158 -0
  17. package/esm/internal/components/configurationControls/conditionalFormatting/ConditionalFormattingSection.d.ts +12 -0
  18. package/esm/internal/components/configurationControls/conditionalFormatting/ConditionalFormattingSection.d.ts.map +1 -0
  19. package/esm/internal/components/configurationControls/conditionalFormatting/ConditionalFormattingSection.js +54 -0
  20. package/esm/internal/components/configurationControls/conditionalFormatting/conditionalFormattingColors.d.ts +14 -0
  21. package/esm/internal/components/configurationControls/conditionalFormatting/conditionalFormattingColors.d.ts.map +1 -0
  22. package/esm/internal/components/configurationControls/conditionalFormatting/conditionalFormattingColors.js +32 -0
  23. package/esm/internal/components/configurationControls/conditionalFormatting/conditionalFormattingModel.d.ts +28 -0
  24. package/esm/internal/components/configurationControls/conditionalFormatting/conditionalFormattingModel.d.ts.map +1 -0
  25. package/esm/internal/components/configurationControls/conditionalFormatting/conditionalFormattingModel.js +149 -0
  26. package/esm/internal/components/configurationPanels/ConfigurationPanelContent.d.ts +1 -0
  27. package/esm/internal/components/configurationPanels/ConfigurationPanelContent.d.ts.map +1 -1
  28. package/esm/internal/components/configurationPanels/PivotTableConfigurationPanel.d.ts +1 -0
  29. package/esm/internal/components/configurationPanels/PivotTableConfigurationPanel.d.ts.map +1 -1
  30. package/esm/internal/components/configurationPanels/PivotTableConfigurationPanel.js +9 -1
  31. package/esm/internal/components/dialogs/userManagementDialogs/AddWorkspaceToSubjects.d.ts +0 -1
  32. package/esm/internal/components/dialogs/userManagementDialogs/AddWorkspaceToSubjects.d.ts.map +1 -1
  33. package/esm/internal/components/dialogs/userManagementDialogs/AddWorkspaceToSubjects.js +3 -3
  34. package/esm/internal/components/dialogs/userManagementDialogs/UserEditDialog.d.ts +0 -1
  35. package/esm/internal/components/dialogs/userManagementDialogs/UserEditDialog.d.ts.map +1 -1
  36. package/esm/internal/components/dialogs/userManagementDialogs/UserEditDialog.js +2 -2
  37. package/esm/internal/components/dialogs/userManagementDialogs/UserGroupEditDialog.d.ts +0 -1
  38. package/esm/internal/components/dialogs/userManagementDialogs/UserGroupEditDialog.d.ts.map +1 -1
  39. package/esm/internal/components/dialogs/userManagementDialogs/UserGroupEditDialog.js +3 -3
  40. package/esm/internal/components/dialogs/userManagementDialogs/Workspace/AddWorkspace.d.ts +1 -2
  41. package/esm/internal/components/dialogs/userManagementDialogs/Workspace/AddWorkspace.d.ts.map +1 -1
  42. package/esm/internal/components/dialogs/userManagementDialogs/Workspace/AddWorkspace.js +2 -2
  43. package/esm/internal/components/dialogs/userManagementDialogs/Workspace/WorkspaceItem/GranularPermissions.d.ts +1 -2
  44. package/esm/internal/components/dialogs/userManagementDialogs/Workspace/WorkspaceItem/GranularPermissions.d.ts.map +1 -1
  45. package/esm/internal/components/dialogs/userManagementDialogs/Workspace/WorkspaceItem/GranularPermissions.js +3 -3
  46. package/esm/internal/components/dialogs/userManagementDialogs/Workspace/WorkspaceItem/PermissionsDropdown.d.ts +0 -1
  47. package/esm/internal/components/dialogs/userManagementDialogs/Workspace/WorkspaceItem/PermissionsDropdown.d.ts.map +1 -1
  48. package/esm/internal/components/dialogs/userManagementDialogs/Workspace/WorkspaceItem/PermissionsDropdown.js +3 -5
  49. package/esm/internal/components/dialogs/userManagementDialogs/Workspace/WorkspaceItem/WorkspaceItem.d.ts +1 -2
  50. package/esm/internal/components/dialogs/userManagementDialogs/Workspace/WorkspaceItem/WorkspaceItem.d.ts.map +1 -1
  51. package/esm/internal/components/dialogs/userManagementDialogs/Workspace/WorkspaceItem/WorkspaceItem.js +2 -2
  52. package/esm/internal/components/dialogs/userManagementDialogs/Workspace/WorkspaceList.d.ts +0 -1
  53. package/esm/internal/components/dialogs/userManagementDialogs/Workspace/WorkspaceList.d.ts.map +1 -1
  54. package/esm/internal/components/pluggableVisualizations/pivotTableNext/PluggablePivotTableNext.d.ts +3 -0
  55. package/esm/internal/components/pluggableVisualizations/pivotTableNext/PluggablePivotTableNext.d.ts.map +1 -1
  56. package/esm/internal/components/pluggableVisualizations/pivotTableNext/PluggablePivotTableNext.js +33 -5
  57. package/esm/internal/constants/supportedProperties.d.ts.map +1 -1
  58. package/esm/internal/constants/supportedProperties.js +1 -0
  59. package/esm/internal/translations/de-DE.localization-bundle.d.ts +11 -0
  60. package/esm/internal/translations/de-DE.localization-bundle.d.ts.map +1 -1
  61. package/esm/internal/translations/de-DE.localization-bundle.js +12 -1
  62. package/esm/internal/translations/en-AU.localization-bundle.d.ts +11 -0
  63. package/esm/internal/translations/en-AU.localization-bundle.d.ts.map +1 -1
  64. package/esm/internal/translations/en-AU.localization-bundle.js +12 -1
  65. package/esm/internal/translations/en-GB.localization-bundle.d.ts +11 -0
  66. package/esm/internal/translations/en-GB.localization-bundle.d.ts.map +1 -1
  67. package/esm/internal/translations/en-GB.localization-bundle.js +12 -1
  68. package/esm/internal/translations/en-US.localization-bundle.d.ts +168 -0
  69. package/esm/internal/translations/en-US.localization-bundle.d.ts.map +1 -1
  70. package/esm/internal/translations/en-US.localization-bundle.js +168 -0
  71. package/esm/internal/translations/es-419.localization-bundle.d.ts +11 -0
  72. package/esm/internal/translations/es-419.localization-bundle.d.ts.map +1 -1
  73. package/esm/internal/translations/es-419.localization-bundle.js +12 -1
  74. package/esm/internal/translations/es-ES.localization-bundle.d.ts +11 -0
  75. package/esm/internal/translations/es-ES.localization-bundle.d.ts.map +1 -1
  76. package/esm/internal/translations/es-ES.localization-bundle.js +12 -1
  77. package/esm/internal/translations/fi-FI.localization-bundle.d.ts +11 -0
  78. package/esm/internal/translations/fi-FI.localization-bundle.d.ts.map +1 -1
  79. package/esm/internal/translations/fi-FI.localization-bundle.js +12 -1
  80. package/esm/internal/translations/fr-CA.localization-bundle.d.ts +11 -0
  81. package/esm/internal/translations/fr-CA.localization-bundle.d.ts.map +1 -1
  82. package/esm/internal/translations/fr-CA.localization-bundle.js +12 -1
  83. package/esm/internal/translations/fr-FR.localization-bundle.d.ts +11 -0
  84. package/esm/internal/translations/fr-FR.localization-bundle.d.ts.map +1 -1
  85. package/esm/internal/translations/fr-FR.localization-bundle.js +12 -1
  86. package/esm/internal/translations/id-ID.localization-bundle.d.ts +11 -0
  87. package/esm/internal/translations/id-ID.localization-bundle.d.ts.map +1 -1
  88. package/esm/internal/translations/id-ID.localization-bundle.js +12 -1
  89. package/esm/internal/translations/it-IT.localization-bundle.d.ts +11 -0
  90. package/esm/internal/translations/it-IT.localization-bundle.d.ts.map +1 -1
  91. package/esm/internal/translations/it-IT.localization-bundle.js +12 -1
  92. package/esm/internal/translations/ja-JP.localization-bundle.d.ts +11 -0
  93. package/esm/internal/translations/ja-JP.localization-bundle.d.ts.map +1 -1
  94. package/esm/internal/translations/ja-JP.localization-bundle.js +12 -1
  95. package/esm/internal/translations/ko-KR.localization-bundle.d.ts +11 -0
  96. package/esm/internal/translations/ko-KR.localization-bundle.d.ts.map +1 -1
  97. package/esm/internal/translations/ko-KR.localization-bundle.js +12 -1
  98. package/esm/internal/translations/nl-NL.localization-bundle.d.ts +11 -0
  99. package/esm/internal/translations/nl-NL.localization-bundle.d.ts.map +1 -1
  100. package/esm/internal/translations/nl-NL.localization-bundle.js +12 -1
  101. package/esm/internal/translations/pl-PL.localization-bundle.d.ts +11 -0
  102. package/esm/internal/translations/pl-PL.localization-bundle.d.ts.map +1 -1
  103. package/esm/internal/translations/pl-PL.localization-bundle.js +12 -1
  104. package/esm/internal/translations/pt-BR.localization-bundle.d.ts +11 -0
  105. package/esm/internal/translations/pt-BR.localization-bundle.d.ts.map +1 -1
  106. package/esm/internal/translations/pt-BR.localization-bundle.js +12 -1
  107. package/esm/internal/translations/pt-PT.localization-bundle.d.ts +11 -0
  108. package/esm/internal/translations/pt-PT.localization-bundle.d.ts.map +1 -1
  109. package/esm/internal/translations/pt-PT.localization-bundle.js +12 -1
  110. package/esm/internal/translations/ru-RU.localization-bundle.d.ts +11 -0
  111. package/esm/internal/translations/ru-RU.localization-bundle.d.ts.map +1 -1
  112. package/esm/internal/translations/ru-RU.localization-bundle.js +12 -1
  113. package/esm/internal/translations/sl-SI.localization-bundle.d.ts +11 -0
  114. package/esm/internal/translations/sl-SI.localization-bundle.d.ts.map +1 -1
  115. package/esm/internal/translations/sl-SI.localization-bundle.js +12 -1
  116. package/esm/internal/translations/th-TH.localization-bundle.d.ts +11 -0
  117. package/esm/internal/translations/th-TH.localization-bundle.d.ts.map +1 -1
  118. package/esm/internal/translations/th-TH.localization-bundle.js +12 -1
  119. package/esm/internal/translations/tr-TR.localization-bundle.d.ts +11 -0
  120. package/esm/internal/translations/tr-TR.localization-bundle.d.ts.map +1 -1
  121. package/esm/internal/translations/tr-TR.localization-bundle.js +12 -1
  122. package/esm/internal/translations/uk-UA.localization-bundle.d.ts +11 -0
  123. package/esm/internal/translations/uk-UA.localization-bundle.d.ts.map +1 -1
  124. package/esm/internal/translations/uk-UA.localization-bundle.js +12 -1
  125. package/esm/internal/translations/vi-VN.localization-bundle.d.ts +11 -0
  126. package/esm/internal/translations/vi-VN.localization-bundle.d.ts.map +1 -1
  127. package/esm/internal/translations/vi-VN.localization-bundle.js +12 -1
  128. package/esm/internal/translations/zh-HK.localization-bundle.d.ts +11 -0
  129. package/esm/internal/translations/zh-HK.localization-bundle.d.ts.map +1 -1
  130. package/esm/internal/translations/zh-HK.localization-bundle.js +12 -1
  131. package/esm/internal/translations/zh-Hans.localization-bundle.d.ts +11 -0
  132. package/esm/internal/translations/zh-Hans.localization-bundle.d.ts.map +1 -1
  133. package/esm/internal/translations/zh-Hans.localization-bundle.js +12 -1
  134. package/esm/internal/translations/zh-Hant.localization-bundle.d.ts +11 -0
  135. package/esm/internal/translations/zh-Hant.localization-bundle.d.ts.map +1 -1
  136. package/esm/internal/translations/zh-Hant.localization-bundle.js +12 -1
  137. package/esm/internal/utils/propertiesHelper.d.ts +2 -1
  138. package/esm/internal/utils/propertiesHelper.d.ts.map +1 -1
  139. package/esm/internal/utils/propertiesHelper.js +3 -0
  140. package/esm/locales.d.ts +79 -0
  141. package/esm/locales.d.ts.map +1 -1
  142. package/esm/locales.js +46 -0
  143. package/esm/sdk-ui-ext.d.ts +24 -10
  144. package/esm/share/ObjectShareDialog.js +2 -2
  145. package/esm/share/objectShareController.helpers.d.ts +0 -26
  146. package/esm/share/objectShareController.helpers.d.ts.map +1 -1
  147. package/esm/share/objectShareController.helpers.js +2 -38
  148. package/esm/share/objectShareController.types.d.ts +39 -0
  149. package/esm/share/objectShareController.types.d.ts.map +1 -1
  150. package/esm/share/useAccessList.d.ts +31 -18
  151. package/esm/share/useAccessList.d.ts.map +1 -1
  152. package/esm/share/useAccessList.js +85 -133
  153. package/esm/share/useLabelScope.d.ts +6 -8
  154. package/esm/share/useLabelScope.d.ts.map +1 -1
  155. package/esm/share/useLabelScope.js +34 -28
  156. package/esm/share/useObjectShareController.d.ts +19 -16
  157. package/esm/share/useObjectShareController.d.ts.map +1 -1
  158. package/esm/share/useObjectShareController.js +212 -119
  159. package/package.json +21 -21
  160. package/styles/css/main.css +238 -0
  161. package/styles/css/main.css.map +1 -1
  162. package/styles/internal/css/conditional_formatting.css +239 -0
  163. package/styles/internal/css/conditional_formatting.css.map +1 -0
  164. package/styles/internal/css/config_panel.css +5 -0
  165. package/styles/internal/css/config_panel.css.map +1 -1
  166. package/styles/internal/scss/conditional_formatting.scss +269 -0
  167. package/styles/internal/scss/config_panel.scss +11 -0
  168. package/styles/scss/main.scss +1 -0
  169. package/esm/share/useObjectShare.d.ts +0 -50
  170. package/esm/share/useObjectShare.d.ts.map +0 -1
  171. package/esm/share/useObjectShare.js +0 -17
@@ -1,17 +1,23 @@
1
1
  // (C) 2026 GoodData Corporation
2
- import { useCallback, useEffect, useMemo, useRef, useState } from "react";
3
- import { objRefToString, } from "@gooddata/sdk-model";
2
+ import { useCallback, useEffect, useMemo, useState } from "react";
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";
6
6
  import { deriveGeneralAccess, deriveWorkspacePermissionLevel } from "./accessSummary.js";
7
7
  import { objectShareMessages } from "./messages.js";
8
- import { assigneeMatchesQuery, granteeId, granteesFromAccessList, mergeOverlay, reconcileOverlay, } from "./objectShareController.helpers.js";
8
+ import { assigneeMatchesQuery, granteeId, granteesFromAccessList } from "./objectShareController.helpers.js";
9
9
  /**
10
- * Owns the backend access list and its optimistic overlay. The list is fetched
11
- * via `useCancelablePromise` then owned locally: mutations patch the overlay and
12
- * a background refresh reconciles it, so the grantee list never blanks between a
13
- * change and the server response. A target switch is handled by stamping the
14
- * fetched list with its target and reading through `currentAccessList`.
10
+ * Owns the backend access list. It is fetched once (per target) then seeded into
11
+ * local state, which is authoritative while the dialog/summary is mounted:
12
+ * mutations write through to it directly and roll back the one changed entry on
13
+ * failure. There is no post-write refetch, so the grantee list never blanks and
14
+ * never fights the backend's read-after-write lag. A target switch re-seeds from
15
+ * the new fetch; the seed is gated on a per-target stamp so a late fetch for a
16
+ * previous target can't clobber the current one.
17
+ *
18
+ * Effective (inherited) permissions and display names come from that single
19
+ * fetch: inherited access doesn't change as a result of editing a direct grant,
20
+ * so the badge stays correct for the session without re-reading.
15
21
  *
16
22
  * @internal
17
23
  */
@@ -19,37 +25,24 @@ export function useAccessList(target, onSaved) {
19
25
  const backend = useBackendStrict();
20
26
  const workspace = useWorkspaceStrict();
21
27
  const toast = useToastMessage();
22
- const [accessList, setAccessList] = useState(undefined);
23
- const [accessListTarget, setAccessListTarget] = useState(undefined);
24
- const [loadStatus, setLoadStatus] = useState(target ? "loading" : "idle");
28
+ // Authoritative local state, seeded from the fetch below.
29
+ const [grantees, setGrantees] = useState([]);
30
+ const [generalAccess, setGeneralAccess] = useState("RESTRICTED");
31
+ const [workspaceLevel, setWorkspaceLevel] = useState("VIEW");
32
+ // The target the local state was seeded for; undefined until the first seed.
33
+ // Reading state as belonging to the current target hinges on this matching
34
+ // `targetKey` — a target switch makes the old state stale until the re-seed.
35
+ const [seededTarget, setSeededTarget] = useState(undefined);
25
36
  const [loadError, setLoadError] = useState(undefined);
26
- // Optimistic overlay keyed by grantee id. Each entry holds the *intended* row
27
- // (add/level-change) or a removal, plus a pending flag while the write is in
28
- // flight. The backend has read-after-write lag, so we show the intended state
29
- // and clear an entry only once a refresh confirms it (or the write fails).
30
- const [overlay, setOverlay] = useState({});
31
- // Display names learned from the picker; keep a human name on a row after the
32
- // optimistic overlay reconciles away (the grant often returns only a raw id).
37
+ // Display names learned from the picker; used to give a fetched row a human
38
+ // name when its grant carried only a raw id.
33
39
  const [knownNames, setKnownNames] = useState({});
34
40
  // Original ObjRef per grantee id, learned from the picker (the access-list id
35
41
  // is a serialized `kind:identifier`, which loses Uri-vs-Id). Reused for writes.
36
42
  const [knownRefs, setKnownRefs] = useState({});
37
- // Optimistic general-access override — held from confirm until the fetched list
38
- // reflects it, so the radio + summary update instantly.
39
- const [optimisticGeneralAccess, setOptimisticGeneralAccess] = useState(undefined);
40
43
  const targetKey = target ? objRefToString(target.ref) : undefined;
41
- // The owned list as it applies to the *current* target. A target switch makes
42
- // the previous fetch's list stale until the new one lands; gating on the stamp
43
- // means everything derived ignores it immediately — no reset effect.
44
- const currentAccessList = accessListTarget === targetKey ? accessList : undefined;
45
- // Always-current target key, read inside async callbacks that captured an older
46
- // one. A background refresh started for the previous target can resolve after a
47
- // switch; without this it would stamp the list back to the stale target, leaving
48
- // the new target's `currentAccessList` undefined (and, with the load-gated
49
- // status, stuck "loading" since its own fetch already settled).
50
- const targetKeyRef = useRef(targetKey);
51
- targetKeyRef.current = targetKey;
52
- // Initial (and target-change) load. Feeds setAccessList once; thereafter we own it.
44
+ // Initial (and target-change) load. Seeds local state once per target; thereafter
45
+ // local state is authoritative and mutations write through it.
53
46
  const { result: fetchedList, status: fetchStatus, error: fetchError, } = useCancelablePromise({
54
47
  promise: target
55
48
  ? () => backend.workspace(workspace).objectPermissions().getAccessList(target)
@@ -58,118 +51,77 @@ export function useAccessList(target, onSaved) {
58
51
  // Key on the serialized ref, not the ObjRef object — an inline idRef(...) is a
59
52
  // new instance each render and would otherwise refetch forever.
60
53
  [backend, workspace, target?.kind, targetKey]);
54
+ // Local state belongs to the current target only once its list has been seeded
55
+ // AND no fetch is in flight for it. Requiring `fetchStatus === "success"` (not
56
+ // just a matching `seededTarget`) matters when the same object is reopened after
57
+ // navigating away: the deps change re-runs `useCancelablePromise`, which resets to
58
+ // `loading` while it refetches. Without this, the still-matching previous
59
+ // `seededTarget` would keep `hasList` true and surface the prior session's
60
+ // grantees as `success` (mutations enabled) until the new list lands.
61
+ const hasList = seededTarget === targetKey && targetKey !== undefined && fetchStatus === "success";
61
62
  useEffect(() => {
62
63
  if (fetchStatus === "success" && fetchedList) {
63
64
  // The cancelable promise is keyed on targetKey, so this list is for it.
64
- setAccessList(fetchedList);
65
- setAccessListTarget(targetKey);
66
- setLoadStatus("idle");
65
+ setGrantees(granteesFromAccessList(fetchedList));
66
+ setGeneralAccess(deriveGeneralAccess(fetchedList.grants));
67
+ setWorkspaceLevel(deriveWorkspacePermissionLevel(fetchedList.grants));
68
+ setSeededTarget(targetKey);
67
69
  setLoadError(undefined);
68
- setOverlay({}); // a target-change load is authoritative; drop stale overlay
69
- setOptimisticGeneralAccess(undefined);
70
70
  }
71
71
  else if (fetchStatus === "error") {
72
- setLoadStatus("error");
73
72
  setLoadError(fetchError instanceof Error ? fetchError : new Error(String(fetchError)));
74
73
  }
75
74
  else if (fetchStatus === "loading") {
76
- setLoadStatus("loading");
75
+ // A (re)fetch is in flight — including when the same object is reopened
76
+ // after navigating away. Drop the seed stamp so the previous session's
77
+ // list isn't surfaced as the current one until the fresh fetch is seeded.
78
+ setSeededTarget(undefined);
77
79
  }
78
80
  }, [fetchStatus, fetchedList, fetchError, targetKey]);
79
- // Background refresh pulls server truth without nulling the current list,
80
- // then reconciles the overlay (clears entries the server now confirms).
81
- const refresh = useCallback(async () => {
82
- if (!target) {
83
- return;
84
- }
85
- try {
86
- const fresh = await backend.workspace(workspace).objectPermissions().getAccessList(target);
87
- // The target may have changed while this refresh was in flight. Stamping
88
- // a stale target's list now would clobber the new target's stamp and
89
- // strand it loading, so drop the result if we've since switched away.
90
- if (targetKeyRef.current !== targetKey) {
91
- return;
92
- }
93
- setAccessList(fresh);
94
- setAccessListTarget(targetKey);
95
- setOverlay((prev) => reconcileOverlay(granteesFromAccessList(fresh), prev));
96
- // Drop the optimistic general-access override once the server confirms it.
97
- const freshGeneralAccess = deriveGeneralAccess(fresh.grants);
98
- setOptimisticGeneralAccess((prev) => (prev === freshGeneralAccess ? undefined : prev));
99
- }
100
- catch {
101
- // The refresh failed, but the mutation that triggered it already
102
- // succeeded. The overlay can't be reconciled against fresh data now, so
103
- // settle it optimistically: keep each entry's intended state (a `set`
104
- // value stays, a `remove` keeps hiding the row) but clear its `pending`
105
- // flag. Otherwise rows would spin on "saving"/"removing" forever even
106
- // though the change persisted and a success toast was shown.
107
- setOverlay((prev) => {
108
- let changed = false;
109
- const next = {};
110
- for (const [id, entry] of Object.entries(prev)) {
111
- if (entry.pending) {
112
- changed = true;
113
- next[id] = { ...entry, pending: false };
114
- }
115
- else {
116
- next[id] = entry;
117
- }
118
- }
119
- return changed ? next : prev;
120
- });
121
- }
122
- }, [backend, workspace, target, targetKey]);
123
- // Committed rows overlaid with optimistic intent; backfill a human name from
124
- // the picker cache where the grant only carried a raw id.
125
- const grantees = useMemo(() => {
126
- if (!currentAccessList) {
127
- return [];
128
- }
129
- const committed = granteesFromAccessList(currentAccessList).map((g) => {
81
+ // The current target's rows, with a human name backfilled from the picker
82
+ // cache where the grant returned only a raw id. Empty until the current
83
+ // target's list is seeded, so a stale previous target's rows never show
84
+ // through the switch window. Derivation, not state — re-applies as the cache grows.
85
+ const namedGrantees = useMemo(() => hasList
86
+ ? grantees.map((g) => {
130
87
  const known = knownNames[g.id];
131
88
  return known && g.name === objRefToString(g.granteeRef) ? { ...g, name: known } : g;
132
- });
133
- return mergeOverlay(committed, overlay);
134
- }, [currentAccessList, overlay, knownNames]);
135
- const granteeIdsKey = granteesFromAccessList(currentAccessList)
89
+ })
90
+ : [], [hasList, grantees, knownNames]);
91
+ // Stable sorted key of the currently-granted ids — drives the picker's
92
+ // "exclude already-granted" filter. Keyed on ids only (not names), so the
93
+ // picker's own name-cache writes can't change loadOptions' identity and
94
+ // re-trigger its fetch.
95
+ const excludedIdsKey = useMemo(() => grantees
96
+ .filter((g) => g.pending !== "removing")
136
97
  .map((g) => g.id)
137
98
  .sort()
138
- .join(",");
139
- const committedGeneralAccess = useMemo(() => (currentAccessList ? deriveGeneralAccess(currentAccessList.grants) : "RESTRICTED"), [currentAccessList]);
140
- const generalAccess = optimisticGeneralAccess ?? committedGeneralAccess;
99
+ .join(","), [grantees]);
141
100
  const summary = useMemo(() => {
142
- if (!currentAccessList) {
101
+ if (!hasList) {
143
102
  return undefined;
144
103
  }
145
104
  return {
146
105
  generalAccess,
147
- // While the optimistic override is active we just wrote the workspace
148
- // rule as VIEW, so report VIEW rather than the stale fetched grant
149
- // (which can still read SHARE through read-after-write lag).
150
- workspaceLevel: optimisticGeneralAccess
151
- ? "VIEW"
152
- : deriveWorkspacePermissionLevel(currentAccessList.grants),
153
- granteeCount: grantees.length,
106
+ workspaceLevel: generalAccess === "WORKSPACE" ? workspaceLevel : "VIEW",
107
+ granteeCount: namedGrantees.filter((g) => g.pending !== "removing").length,
154
108
  };
155
- }, [currentAccessList, generalAccess, optimisticGeneralAccess, grantees]);
156
- // "success" only once the *current* target's list has actually landed. After a
157
- // target switch the stamp clears `currentAccessList` immediately, but
158
- // `loadStatus` still reads "idle" from the previous target's completed load
159
- // until the effect re-runs so gating on loadStatus alone would briefly report
160
- // "success" with no list, letting the dialog enable mutations and the catalog
161
- // row hide both summary and skeleton. Treat "no list for this target yet" as
162
- // loading.
109
+ }, [hasList, generalAccess, workspaceLevel, namedGrantees]);
110
+ // "success" only once the *current* target's list has been seeded. After a
111
+ // target switch the previous seed is stale (seededTarget !== targetKey), so
112
+ // gating on hasList keeps the status at "loading" until the new list lands
113
+ // never "success" with no list, which would let the dialog enable mutations
114
+ // and the catalog row hide both summary and skeleton.
163
115
  const status = target
164
- ? loadStatus === "error"
116
+ ? fetchStatus === "error"
165
117
  ? "error"
166
- : loadStatus === "loading" || !currentAccessList
167
- ? "loading"
168
- : "success"
118
+ : hasList
119
+ ? "success"
120
+ : "loading"
169
121
  : "idle";
170
- // Commit a single grant change against the backend, then reconcile via refresh.
171
- // Optimistic state is applied by the caller; on failure the caller's rollback
172
- // runs and a toast is shown.
122
+ // Write a single grant change to the backend, then toast. The caller applies
123
+ // the optimistic local write-through and rolls it back on failure; there is no
124
+ // refetch local state stays authoritative.
173
125
  const commit = useCallback(async (mutate, successMessage) => {
174
126
  if (!target) {
175
127
  return false;
@@ -181,18 +133,17 @@ export function useAccessList(target, onSaved) {
181
133
  .manageObjectPermissions(target, mutate);
182
134
  toast.addSuccess(successMessage);
183
135
  onSaved?.();
184
- await refresh();
185
136
  return true;
186
137
  }
187
138
  catch {
188
139
  toast.addError(objectShareMessages.toastError);
189
140
  return false;
190
141
  }
191
- }, [backend, workspace, target, toast, onSaved, refresh]);
142
+ }, [backend, workspace, target, toast, onSaved]);
192
143
  // Picker loader — fetches available assignees on demand, filters by the typed
193
- // query, excludes anything already granted. Depends only on the grant sources
194
- // (accessList, overlay), so its identity changes only when the granted set
195
- // actually changes. It must NOT write state that feeds its own deps.
144
+ // query, excludes anything already granted. Depends only on the granted set
145
+ // (grantees), so its identity changes only when that set actually changes. It
146
+ // must NOT write state that feeds its own deps.
196
147
  const loadOptions = useCallback(async (search) => {
197
148
  if (!target) {
198
149
  return { groups: [], users: [] };
@@ -223,7 +174,7 @@ export function useAccessList(target, onSaved) {
223
174
  }
224
175
  return next;
225
176
  });
226
- const excluded = new Set(mergeOverlay(granteesFromAccessList(currentAccessList), overlay).map((g) => g.id));
177
+ const excluded = new Set(excludedIdsKey ? excludedIdsKey.split(",") : []);
227
178
  const selectable = withIds
228
179
  .filter(({ id }) => !excluded.has(id)) // hide anyone already granted
229
180
  .filter(({ assignee }) => assigneeMatchesQuery(assignee, query));
@@ -240,24 +191,25 @@ export function useAccessList(target, onSaved) {
240
191
  .filter(({ assignee }) => assignee.type !== "user")
241
192
  .map(({ assignee, id }) => ({ id, kind: "group", name: assignee.name })),
242
193
  };
243
- }, [backend, workspace, target, currentAccessList, overlay]);
194
+ }, [backend, workspace, target, excludedIdsKey]);
244
195
  // Reuse the picker's original ref (preserves UriRef vs IdentifierRef);
245
196
  // fall back to the serialized id only if it wasn't cached.
246
197
  const refForId = useCallback((id) => knownRefs[id] ?? { identifier: id.split(":", 2)[1] }, [knownRefs]);
247
198
  return {
248
199
  targetKey,
249
- currentAccessList,
250
- grantees,
251
- granteeIdsKey,
200
+ hasList,
201
+ grantees: namedGrantees,
252
202
  generalAccess,
203
+ workspaceLevel,
253
204
  summary,
254
205
  status,
255
206
  loadError,
256
207
  commit,
257
208
  loadOptions,
258
209
  refForId,
259
- setOverlay,
210
+ setGrantees,
211
+ setGeneralAccess,
212
+ setWorkspaceLevel,
260
213
  setKnownNames,
261
- setOptimisticGeneralAccess,
262
214
  };
263
215
  }
@@ -1,6 +1,4 @@
1
- import { type MutableRefObject } from "react";
2
1
  import { type IObjectPermissionsObject } from "@gooddata/sdk-backend-spi";
3
- import type { IObjectAccessList } from "@gooddata/sdk-model";
4
2
  import { type LabelScopePrincipal } from "./objectShareController.helpers.js";
5
3
  import type { IObjectShareLabel } from "./types.js";
6
4
  /**
@@ -30,11 +28,6 @@ export interface ILabelScope {
30
28
  /** Per-grantee label scope: grantee id → label ids in scope (primary always in). */
31
29
  selectedLabelIdsByGrantee: Record<string, string[]>;
32
30
  setSelectedLabelIdsByGrantee: React.Dispatch<React.SetStateAction<Record<string, string[]>>>;
33
- /**
34
- * Grantee ids whose scope was just written optimistically; the resolution
35
- * effect keeps these instead of overwriting them through read-after-write lag.
36
- */
37
- optimisticScopeRef: MutableRefObject<Set<string>>;
38
31
  /**
39
32
  * The single per-label write path. Diffs `desired` vs `current` over the
40
33
  * permissionable labels and grants/revokes for one principal. Returns false
@@ -48,7 +41,12 @@ export interface ILabelScope {
48
41
  * which labels are permissionable, and exposes one reconcile primitive shared by
49
42
  * add / remove / general-access / the labels picker so their behavior can't drift.
50
43
  *
44
+ * The resolved scope is local-authoritative: the probe seeds a scope only for
45
+ * grantees it doesn't already know, so an optimistic scope written for a freshly
46
+ * added grantee is never overwritten by the backend's lagging read. Local scopes
47
+ * are dropped on a target switch so the next object re-resolves from scratch.
48
+ *
51
49
  * @internal
52
50
  */
53
- export declare function useLabelScope(target: IObjectPermissionsObject | undefined, targetKey: string | undefined, labels: IObjectShareLabel[], currentAccessList: IObjectAccessList | undefined, granteeIdsKey: string, labelsError: boolean, labelsLoading: boolean): ILabelScope;
51
+ export declare function useLabelScope(target: IObjectPermissionsObject | undefined, targetKey: string | undefined, labels: IObjectShareLabel[], hasList: boolean, committedGranteeIds: string[], labelsError: boolean, labelsLoading: boolean): ILabelScope;
54
52
  //# sourceMappingURL=useLabelScope.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useLabelScope.d.ts","sourceRoot":"","sources":["../../src/share/useLabelScope.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,gBAAgB,EAAqD,MAAM,OAAO,CAAC;AAEjG,OAAO,EAAE,KAAK,wBAAwB,EAA6B,MAAM,2BAA2B,CAAC;AACrG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAG7D,OAAO,EACH,KAAK,mBAAmB,EAI3B,MAAM,oCAAoC,CAAC;AAC5C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAWpD;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IACxB;;;;OAIG;IACH,eAAe,EAAE,iBAAiB,EAAE,CAAC;IACrC;;;;;;;;OAQG;IACH,cAAc,EAAE,OAAO,CAAC;IACxB,sFAAoF;IACpF,yBAAyB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACpD,4BAA4B,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7F;;;OAGG;IACH,kBAAkB,EAAE,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IAClD;;;;OAIG;IACH,mBAAmB,EAAE,CACjB,SAAS,EAAE,mBAAmB,EAC9B,eAAe,EAAE,WAAW,CAAC,MAAM,CAAC,EACpC,eAAe,EAAE,WAAW,CAAC,MAAM,CAAC,KACnC,OAAO,CAAC,OAAO,CAAC,CAAC;CACzB;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CACzB,MAAM,EAAE,wBAAwB,GAAG,SAAS,EAC5C,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,MAAM,EAAE,iBAAiB,EAAE,EAC3B,iBAAiB,EAAE,iBAAiB,GAAG,SAAS,EAChD,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,OAAO,EACpB,aAAa,EAAE,OAAO,GACvB,WAAW,CAoKb"}
1
+ {"version":3,"file":"useLabelScope.d.ts","sourceRoot":"","sources":["../../src/share/useLabelScope.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,wBAAwB,EAA6B,MAAM,2BAA2B,CAAC;AAGrG,OAAO,EACH,KAAK,mBAAmB,EAG3B,MAAM,oCAAoC,CAAC;AAC5C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAWpD;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IACxB;;;;OAIG;IACH,eAAe,EAAE,iBAAiB,EAAE,CAAC;IACrC;;;;;;;;OAQG;IACH,cAAc,EAAE,OAAO,CAAC;IACxB,sFAAoF;IACpF,yBAAyB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACpD,4BAA4B,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7F;;;;OAIG;IACH,mBAAmB,EAAE,CACjB,SAAS,EAAE,mBAAmB,EAC9B,eAAe,EAAE,WAAW,CAAC,MAAM,CAAC,EACpC,eAAe,EAAE,WAAW,CAAC,MAAM,CAAC,KACnC,OAAO,CAAC,OAAO,CAAC,CAAC;CACzB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CACzB,MAAM,EAAE,wBAAwB,GAAG,SAAS,EAC5C,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,MAAM,EAAE,iBAAiB,EAAE,EAC3B,OAAO,EAAE,OAAO,EAChB,mBAAmB,EAAE,MAAM,EAAE,EAC7B,WAAW,EAAE,OAAO,EACpB,aAAa,EAAE,OAAO,GACvB,WAAW,CAsKb"}
@@ -1,8 +1,8 @@
1
1
  // (C) 2026 GoodData Corporation
2
- import { useCallback, useEffect, useMemo, useRef, useState } from "react";
2
+ import { useCallback, useEffect, useMemo, useState } from "react";
3
3
  import { isUnexpectedResponseError } from "@gooddata/sdk-backend-spi";
4
4
  import { useBackendStrict, useWorkspaceStrict } from "@gooddata/sdk-ui";
5
- import { buildLabelMutations, granteesFromAccessList, isGranteeGrantedIn, } from "./objectShareController.helpers.js";
5
+ import { buildLabelMutations, isGranteeGrantedIn, } from "./objectShareController.helpers.js";
6
6
  /**
7
7
  * Whether a label's access-list error means the label is genuinely not
8
8
  * independently permissionable (a definitive 404 / 501), as opposed to a
@@ -17,13 +17,17 @@ function isNotPermissionable(error) {
17
17
  * which labels are permissionable, and exposes one reconcile primitive shared by
18
18
  * add / remove / general-access / the labels picker so their behavior can't drift.
19
19
  *
20
+ * The resolved scope is local-authoritative: the probe seeds a scope only for
21
+ * grantees it doesn't already know, so an optimistic scope written for a freshly
22
+ * added grantee is never overwritten by the backend's lagging read. Local scopes
23
+ * are dropped on a target switch so the next object re-resolves from scratch.
24
+ *
20
25
  * @internal
21
26
  */
22
- export function useLabelScope(target, targetKey, labels, currentAccessList, granteeIdsKey, labelsError, labelsLoading) {
27
+ export function useLabelScope(target, targetKey, labels, hasList, committedGranteeIds, labelsError, labelsLoading) {
23
28
  const backend = useBackendStrict();
24
29
  const workspace = useWorkspaceStrict();
25
30
  const [selectedLabelIdsByGrantee, setSelectedLabelIdsByGrantee] = useState({});
26
- const optimisticScopeRef = useRef(new Set());
27
31
  // Label ids whose permissions endpoint responded — not every display form is
28
32
  // independently permissionable (some 404). `undefined` means "not resolved
29
33
  // yet" (assume all).
@@ -39,19 +43,30 @@ export function useLabelScope(target, targetKey, labels, currentAccessList, gran
39
43
  useEffect(() => {
40
44
  setPermissionableLabelIds(undefined);
41
45
  }, [targetKey, labelsKey]);
46
+ // A target switch — or a label-set change under the same target (labels finish
47
+ // loading, a label added/removed) — drops every resolved scope so the seeding
48
+ // effect below re-resolves from the current label set's per-label lists rather
49
+ // than preserving scopes computed against the old labels. Without the labelsKey
50
+ // reset, an existing grantee would keep a scope missing a newly-added label even
51
+ // when the backend grants them access to it. (An add under the SAME labels only
52
+ // changes granteeIdsKey, not labelsKey, so an optimistic scope still survives.)
53
+ useEffect(() => {
54
+ setSelectedLabelIdsByGrantee({});
55
+ }, [targetKey, labelsKey]);
56
+ // Stable string key of the committed grantee ids — the array is rebuilt each
57
+ // render, so the effect keys on this instead to re-resolve only on a real change.
58
+ const granteeIdsKey = committedGranteeIds.slice().sort().join(",");
42
59
  // Resolve each grantee's label scope: fetch every label's access list once and
43
60
  // record, per grantee, which labels they appear in (primary label always counts).
44
61
  // Keyed on the committed grantee ids + labels so it re-resolves after add/remove.
45
- // `hasAccessList` is a dep too: a list that loads with no named grantees keeps
62
+ // `hasList` is a dep too: a list that loads with no named grantees keeps
46
63
  // `granteeIdsKey` empty, so without it the effect would never run and the
47
64
  // permissionable set (404 filtering) would never resolve.
48
- const hasAccessList = currentAccessList !== undefined;
49
65
  useEffect(() => {
50
- if (!target || labels.length === 0 || !currentAccessList) {
66
+ if (!target || labels.length === 0 || !hasList) {
51
67
  return;
52
68
  }
53
69
  let cancelled = false;
54
- const committedGranteeIds = granteesFromAccessList(currentAccessList).map((g) => g.id);
55
70
  Promise.all(labels.map((label) => backend
56
71
  .workspace(workspace)
57
72
  .objectPermissions()
@@ -89,13 +104,14 @@ export function useLabelScope(target, targetKey, labels, currentAccessList, gran
89
104
  }
90
105
  }
91
106
  setSelectedLabelIdsByGrantee((prev) => {
92
- // Keep a just-written optimistic scope through read-after-write lag;
93
- // take the freshly-resolved scope for everyone else.
94
- const next = { ...resolved };
95
- for (const id of optimisticScopeRef.current) {
96
- if (prev[id]) {
97
- next[id] = prev[id];
98
- }
107
+ // Seed a scope only for grantees we don't already have one for. A
108
+ // scope written optimistically (a fresh add, a labels edit) is
109
+ // local-authoritative and must survive the re-resolution that the
110
+ // grantee-set change triggers the backend's lagging read would
111
+ // otherwise reset it. Grantees gone from the list are dropped.
112
+ const next = {};
113
+ for (const id of committedGranteeIds) {
114
+ next[id] = prev[id] ?? resolved[id];
99
115
  }
100
116
  return next;
101
117
  });
@@ -105,23 +121,14 @@ export function useLabelScope(target, targetKey, labels, currentAccessList, gran
105
121
  cancelled = true;
106
122
  };
107
123
  // eslint-disable-next-line react-hooks/exhaustive-deps
108
- }, [backend, workspace, targetKey, labelsKey, granteeIdsKey, hasAccessList]);
109
- // A label-set change OR a target switch re-resolves scopes; drop the optimistic-
110
- // scope guard so the freshly-resolved scopes aren't held stale. Keying on
111
- // labelsKey alone leaked across objects that happen to share a labelsKey (e.g.
112
- // during navigation, before the new object's labels load): the prior object's
113
- // optimistic entries would then merge over the new object's resolved scopes and
114
- // show/save the wrong label grants. targetKey makes the guard per-object.
115
- useEffect(() => {
116
- optimisticScopeRef.current = new Set();
117
- }, [labelsKey, targetKey]);
124
+ }, [backend, workspace, targetKey, labelsKey, granteeIdsKey, hasList]);
118
125
  // Only labels whose permissions endpoint responded are scope-controllable; until
119
126
  // resolution completes (permissionableLabelIds undefined) assume all are usable.
120
127
  // While the current target's list isn't loaded yet, ignore a permissionable set
121
128
  // left over from a previous object so we never mis-filter the new labels.
122
- const effectiveLabels = useMemo(() => currentAccessList && permissionableLabelIds
129
+ const effectiveLabels = useMemo(() => hasList && permissionableLabelIds
123
130
  ? labels.filter((l) => permissionableLabelIds.has(l.id))
124
- : labels, [labels, permissionableLabelIds, currentAccessList]);
131
+ : labels, [labels, permissionableLabelIds, hasList]);
125
132
  // Resolution is done when the probe has produced a permissionable set, or when
126
133
  // there are genuinely no labels to probe (a label-free object). Until then
127
134
  // callers must treat the scope as unknown (not "all selected").
@@ -154,7 +161,6 @@ export function useLabelScope(target, targetKey, labels, currentAccessList, gran
154
161
  labelsResolved,
155
162
  selectedLabelIdsByGrantee,
156
163
  setSelectedLabelIdsByGrantee,
157
- optimisticScopeRef,
158
164
  reconcileLabelScope,
159
165
  };
160
166
  }
@@ -1,24 +1,27 @@
1
1
  import type { IObjectPermissionsObject } from "@gooddata/sdk-backend-spi";
2
- import { type IObjectShareController } from "./objectShareController.types.js";
3
- import type { IObjectShareLabel } from "./types.js";
2
+ import { type IObjectShareController, type IUseObjectShareOptions } from "./objectShareController.types.js";
4
3
  /**
5
- * Manages the share dialog state and backend I/O for a single shareable
6
- * object.
4
+ * Manages the share dialog state and backend I/O for a single shareable object.
7
5
  *
8
- * The access list is fetched (and re-fetched after every save) via
9
- * `useCancelablePromise`; everything that reflects the backend the grantee
10
- * rows, general-access value, summary is derived from it on render, never
11
- * copied into local state. Local state is only the dialog's own transient UI:
12
- * the active subview, the add-grantee buffer, the pending general-access
13
- * confirm, and an in-flight save flag. Top-level open/close is the consumer's
14
- * concern (see {@link ObjectShareDialog}).
6
+ * The access list is fetched once and seeded into local state, which is the
7
+ * source of truth while the dialog/summary is mounted. Each access change is
8
+ * written through to local state immediately and sent to the backend; on failure
9
+ * the one changed entry is rolled back. There is no post-write refetch, so the
10
+ * grantee list never blanks and never fights the backend's read-after-write lag.
11
+ * Top-level open/close is the consumer's concern (see {@link ObjectShareDialog}).
15
12
  *
16
- * Mutations follow a **commit-on-interaction** model: each access change is
17
- * sent immediately; the general-access toggle goes through a confirm step
18
- * because it is high-impact. There is no batched Save. The list is fetched
19
- * eagerly so `state.summary` also drives an inline access row while closed.
13
+ * Mutations follow a **commit-on-interaction** model: each access change is sent
14
+ * immediately; the general-access toggle goes through a confirm step because it
15
+ * is high-impact. There is no batched Save. The list is fetched eagerly so
16
+ * `state.summary` also drives an inline access row while closed.
17
+ *
18
+ * Most consumers do not call this directly — render {@link ObjectShareDialog} with
19
+ * plain props and it owns its controller. Call this (exported as `useObjectShare`)
20
+ * only to share a single access-list fetch between the dialog and an inline summary
21
+ * row: call it once, read `state.summary` for the row, and pass the controller into
22
+ * the dialog.
20
23
  *
21
24
  * @internal
22
25
  */
23
- export declare function useObjectShareController(target: IObjectPermissionsObject | undefined, onSaved?: () => void, labels?: IObjectShareLabel[], labelsError?: boolean, labelsLoading?: boolean): IObjectShareController;
26
+ export declare function useObjectShareController(target: IObjectPermissionsObject | undefined, options?: IUseObjectShareOptions): IObjectShareController;
24
27
  //# sourceMappingURL=useObjectShareController.d.ts.map
@@ -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;AAW1E,OAAO,EACH,KAAK,sBAAsB,EAK9B,MAAM,kCAAkC,CAAC;AAC1C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAIpD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,wBAAwB,CACpC,MAAM,EAAE,wBAAwB,GAAG,SAAS,EAC5C,OAAO,CAAC,EAAE,MAAM,IAAI,EACpB,MAAM,GAAE,iBAAiB,EAAc,EACvC,WAAW,UAAQ,EACnB,aAAa,UAAQ,GACtB,sBAAsB,CAyZxB"}
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,CAggBxB"}