@edifice.io/react 2.4.2-develop-b2school-actualites.20251119110458 → 2.4.2-develop-b2school-actualites.20251124095016

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/dist/index.js CHANGED
@@ -90,19 +90,20 @@ import { default as default88 } from "./modules/modals/OnboardingModal/Onboardin
90
90
  import { default as default89 } from "./modules/modals/PublishModal/PublishModal.js";
91
91
  import { default as default90 } from "./modules/modals/ResourceModal/apps/BlogPublic.js";
92
92
  import { default as default91 } from "./modules/modals/ResourceModal/hooks/useUpdateMutation.js";
93
- import { default as default92 } from "./modules/modals/ShareModal/ShareModal.js";
94
- import { default as default93 } from "./modules/modals/ShareModal/apps/ShareBlog.js";
95
- import { default as default94 } from "./modules/modals/ShareModal/hooks/useShareMutation.js";
96
- import { default as default95 } from "./modules/multimedia/AudioRecorder/AudioRecorder.js";
97
- import { default as default96 } from "./modules/multimedia/Embed/Embed.js";
98
- import { default as default97 } from "./modules/multimedia/ImageEditor/components/ImageEditor.js";
99
- import { default as default98 } from "./modules/multimedia/ImagePicker/ImagePicker.js";
100
- import { default as default99 } from "./modules/multimedia/FileCard/FileCard.js";
101
- import { default as default100 } from "./modules/multimedia/MediaLibrary/MediaLibrary.js";
102
- import { default as default101 } from "./modules/multimedia/VideoEmbed/VideoEmbed.js";
103
- import { default as default102 } from "./modules/multimedia/VideoRecorder/VideoRecorder.js";
104
- import { default as default103 } from "./modules/multimedia/Workspace/Workspace.js";
105
- import { default as default104 } from "./modules/multimedia/WorkspaceFolders/WorkspaceFolders.js";
93
+ import { default as default92 } from "./modules/modals/ShareModal/apps/ShareBlog.js";
94
+ import { default as default93 } from "./modules/modals/ShareModal/hooks/useShareMutation.js";
95
+ import { default as default94 } from "./modules/modals/ShareModal/ShareModal.js";
96
+ import { default as default95 } from "./modules/modals/ShareModal/ShareResources.js";
97
+ import { default as default96 } from "./modules/multimedia/AudioRecorder/AudioRecorder.js";
98
+ import { default as default97 } from "./modules/multimedia/Embed/Embed.js";
99
+ import { default as default98 } from "./modules/multimedia/ImageEditor/components/ImageEditor.js";
100
+ import { default as default99 } from "./modules/multimedia/ImagePicker/ImagePicker.js";
101
+ import { default as default100 } from "./modules/multimedia/FileCard/FileCard.js";
102
+ import { default as default101 } from "./modules/multimedia/MediaLibrary/MediaLibrary.js";
103
+ import { default as default102 } from "./modules/multimedia/VideoEmbed/VideoEmbed.js";
104
+ import { default as default103 } from "./modules/multimedia/VideoRecorder/VideoRecorder.js";
105
+ import { default as default104 } from "./modules/multimedia/Workspace/Workspace.js";
106
+ import { default as default105 } from "./modules/multimedia/WorkspaceFolders/WorkspaceFolders.js";
106
107
  import { AccessiblePalette, DefaultPalette } from "./components/ColorPicker/ColorPalette.js";
107
108
  import { Divider } from "./components/Divider/Divider.js";
108
109
  import { DropzoneContext, useDropzoneContext } from "./components/Dropzone/DropzoneContext.js";
@@ -141,7 +142,7 @@ export {
141
142
  default4 as AppHeader,
142
143
  default5 as AppIcon,
143
144
  default6 as Attachment,
144
- default95 as AudioRecorder,
145
+ default96 as AudioRecorder,
145
146
  default7 as Avatar,
146
147
  default8 as AvatarGroup,
147
148
  default9 as Badge,
@@ -166,10 +167,10 @@ export {
166
167
  EdificeClientProvider,
167
168
  EdificeThemeContext,
168
169
  EdificeThemeProvider,
169
- default96 as Embed,
170
+ default97 as Embed,
170
171
  default21 as EmptyScreen,
171
172
  ExternalLinker,
172
- default99 as FileCard,
173
+ default100 as FileCard,
173
174
  default22 as Flex,
174
175
  default24 as FormControl,
175
176
  default23 as FormText,
@@ -177,8 +178,8 @@ export {
177
178
  default25 as Heading,
178
179
  default12 as IconButton,
179
180
  default26 as Image,
180
- default97 as ImageEditor,
181
- default98 as ImagePicker,
181
+ default98 as ImageEditor,
182
+ default99 as ImagePicker,
182
183
  default27 as Input,
183
184
  InternalLinker,
184
185
  default28 as Label,
@@ -187,7 +188,7 @@ export {
187
188
  default29 as Loading,
188
189
  default30 as LoadingScreen,
189
190
  default31 as Logo,
190
- default100 as MediaLibrary,
191
+ default101 as MediaLibrary,
191
192
  Menu,
192
193
  MockedProvider,
193
194
  default32 as Modal,
@@ -205,8 +206,9 @@ export {
205
206
  default13 as SearchButton,
206
207
  default37 as Select,
207
208
  SeparatedInfo,
208
- default93 as ShareBlog,
209
- default92 as ShareModal,
209
+ default92 as ShareBlog,
210
+ default94 as ShareModal,
211
+ default95 as ShareResources,
210
212
  default46 as SortableTree,
211
213
  default40 as StackedGroup,
212
214
  default41 as Stepper,
@@ -221,13 +223,13 @@ export {
221
223
  TreeNode,
222
224
  TreeNodeFolderWrapper,
223
225
  default48 as TreeView,
224
- default101 as VideoEmbed,
225
- default102 as VideoRecorder,
226
+ default102 as VideoEmbed,
227
+ default103 as VideoRecorder,
226
228
  default49 as VisuallyHidden,
227
229
  WORKSPACE_SHARED_FOLDER_ID,
228
230
  WORKSPACE_USER_FOLDER_ID,
229
- default103 as Workspace,
230
- default104 as WorkspaceFolders,
231
+ default104 as Workspace,
232
+ default105 as WorkspaceFolders,
231
233
  addNode,
232
234
  arrayUnique,
233
235
  buildTree,
@@ -284,7 +286,7 @@ export {
284
286
  default70 as useLibraryUrl,
285
287
  default71 as useMediaLibrary,
286
288
  default72 as useScrollToTop,
287
- default94 as useShareMutation,
289
+ default93 as useShareMutation,
288
290
  default73 as useTitle,
289
291
  default74 as useToast,
290
292
  default75 as useToggle,
package/dist/modals.js CHANGED
@@ -3,9 +3,10 @@ import { default as default3 } from "./modules/modals/OnboardingModal/Onboarding
3
3
  import { default as default4 } from "./modules/modals/PublishModal/PublishModal.js";
4
4
  import { default as default5 } from "./modules/modals/ResourceModal/apps/BlogPublic.js";
5
5
  import { default as default6 } from "./modules/modals/ResourceModal/hooks/useUpdateMutation.js";
6
- import { default as default7 } from "./modules/modals/ShareModal/ShareModal.js";
7
- import { default as default8 } from "./modules/modals/ShareModal/apps/ShareBlog.js";
8
- import { default as default9 } from "./modules/modals/ShareModal/hooks/useShareMutation.js";
6
+ import { default as default7 } from "./modules/modals/ShareModal/apps/ShareBlog.js";
7
+ import { default as default8 } from "./modules/modals/ShareModal/hooks/useShareMutation.js";
8
+ import { default as default9 } from "./modules/modals/ShareModal/ShareModal.js";
9
+ import { default as default10 } from "./modules/modals/ShareModal/ShareResources.js";
9
10
  import { ResourceModal } from "./modules/modals/ResourceModal/ResourceModal.js";
10
11
  export {
11
12
  default5 as BlogPublic,
@@ -13,8 +14,9 @@ export {
13
14
  default3 as OnboardingModal,
14
15
  default4 as PublishModal,
15
16
  ResourceModal,
16
- default8 as ShareBlog,
17
- default7 as ShareModal,
18
- default9 as useShareMutation,
17
+ default7 as ShareBlog,
18
+ default9 as ShareModal,
19
+ default10 as ShareResources,
20
+ default8 as useShareMutation,
19
21
  default6 as useUpdateMutation
20
22
  };
@@ -1,15 +1,5 @@
1
1
  import { ReactNode } from 'react';
2
- import { ID, PutShareResponse, RightStringified, ShareRight } from '@edifice.io/client';
3
- import { UseMutationResult } from '../../../node_modules/@tanstack/react-query';
4
- export type ShareOptions = {
5
- resourceId: ID;
6
- resourceRights: RightStringified[];
7
- resourceCreatorId: string;
8
- };
9
- export type ShareResourceMutation = UseMutationResult<PutShareResponse, unknown, {
10
- resourceId: string;
11
- rights: ShareRight[];
12
- }, unknown>;
2
+ import { ShareOptions, ShareResourceMutation } from './ShareResources';
13
3
  interface ShareResourceModalProps {
14
4
  /** Handle open/close state */
15
5
  isOpen: boolean;
@@ -1,25 +1,11 @@
1
1
  import { jsxs, jsx } from "react/jsx-runtime";
2
- import { useState } from "react";
2
+ import { useRef } from "react";
3
3
  import { createPortal } from "react-dom";
4
4
  import { useTranslation } from "react-i18next";
5
- import SvgIconBookmark from "../../icons/components/IconBookmark.js";
6
- import SvgIconInfoCircle from "../../icons/components/IconInfoCircle.js";
7
- import SvgIconRafterDown from "../../icons/components/IconRafterDown.js";
8
- import { ShareBookmark } from "./ShareBookmark.js";
9
- import { ShareBookmarkLine } from "./ShareBookmarkLine.js";
10
- import { useSearch } from "./hooks/useSearch.js";
11
- import useShare from "./hooks/useShare.js";
12
- import { useShareBookmark } from "./hooks/useShareBookmark.js";
5
+ import ShareResources from "./ShareResources.js";
13
6
  import Modal from "../../../components/Modal/Modal.js";
14
7
  import Alert from "../../../components/Alert/Alert.js";
15
- import Heading from "../../../components/Heading/Heading.js";
16
- import LoadingScreen from "../../../components/LoadingScreen/LoadingScreen.js";
17
- import VisuallyHidden from "../../../components/VisuallyHidden/VisuallyHidden.js";
18
- import Avatar from "../../../components/Avatar/Avatar.js";
19
- import Checkbox from "../../../components/Checkbox/Checkbox.js";
20
8
  import Button from "../../../components/Button/Button.js";
21
- import Tooltip from "../../../components/Tooltip/Tooltip.js";
22
- import Combobox from "../../../components/Combobox/Combobox.js";
23
9
  function ShareResourceModal({
24
10
  isOpen,
25
11
  shareOptions,
@@ -28,104 +14,25 @@ function ShareResourceModal({
28
14
  onSuccess,
29
15
  onCancel
30
16
  }) {
31
- const {
32
- resourceId,
33
- resourceCreatorId,
34
- resourceRights
35
- } = shareOptions, [isLoading, setIsLoading] = useState(!0), {
36
- state: {
37
- isSharing,
38
- shareRights,
39
- shareRightActions
40
- },
41
- dispatch: shareDispatch,
42
- myAvatar,
43
- currentIsAuthor,
44
- handleShare,
45
- toggleRight,
46
- handleDeleteRow
47
- } = useShare({
48
- resourceId,
49
- resourceCreatorId,
50
- resourceRights,
51
- shareResource,
52
- setIsLoading,
53
- onSuccess
54
- }), {
55
- state: {
56
- searchResults,
57
- searchInputValue
58
- },
59
- showSearchAdmlHint,
60
- showSearchLoading,
61
- showSearchNoResults,
62
- getSearchMinLength,
63
- handleSearchInputChange,
64
- handleSearchResultsChange
65
- } = useSearch({
66
- resourceId,
67
- resourceCreatorId,
68
- shareRights,
69
- shareDispatch
70
- }), {
71
- refBookmark,
72
- showBookmark,
73
- handleBookmarkChange,
74
- toggleBookmark,
75
- bookmark,
76
- handleOnSave,
77
- showBookmarkInput,
78
- toggleBookmarkInput
79
- } = useShareBookmark({
80
- shareRights,
81
- shareDispatch
82
- }), {
17
+ var _a, _b;
18
+ const refShareResources = useRef(null), handleShare = () => {
19
+ var _a2;
20
+ (_a2 = refShareResources.current) == null || _a2.handleShare();
21
+ }, {
83
22
  t
84
- } = useTranslation(), searchPlaceholder = showSearchAdmlHint() ? t("explorer.search.adml.hint") : t("explorer.modal.share.search.placeholder");
23
+ } = useTranslation();
85
24
  return /* @__PURE__ */ createPortal(/* @__PURE__ */ jsxs(Modal, { id: "share_modal", size: "lg", isOpen, onModalClose: onCancel, children: [
86
25
  /* @__PURE__ */ jsx(Modal.Header, { onModalClose: onCancel, children: t("share.title") }),
87
26
  /* @__PURE__ */ jsxs(Modal.Body, { children: [
88
27
  /* @__PURE__ */ jsx(Alert, { type: "info", className: "mb-16", children: t("explorer.modal.share.alert.community") }),
89
- /* @__PURE__ */ jsx(Heading, { headingStyle: "h4", level: "h3", className: "mb-16", children: t("explorer.modal.share.usersWithAccess") }),
90
- /* @__PURE__ */ jsx("div", { className: "table-responsive", children: isLoading ? /* @__PURE__ */ jsx(LoadingScreen, {}) : /* @__PURE__ */ jsxs("table", { className: "table border align-middle mb-0", children: [
91
- /* @__PURE__ */ jsx("thead", { className: "bg-secondary", children: /* @__PURE__ */ jsxs("tr", { children: [
92
- /* @__PURE__ */ jsx("th", { scope: "col", className: "w-32", children: /* @__PURE__ */ jsx(VisuallyHidden, { children: t("explorer.modal.share.avatar.shared.alt") }) }),
93
- /* @__PURE__ */ jsx("th", { scope: "col", children: /* @__PURE__ */ jsx(VisuallyHidden, { children: t("explorer.modal.share.search.placeholder") }) }),
94
- shareRightActions.map((shareRightAction) => /* @__PURE__ */ jsx("th", { scope: "col", className: "text-center text-white", children: t(shareRightAction.displayName) }, shareRightAction.displayName)),
95
- /* @__PURE__ */ jsx("th", { scope: "col", children: /* @__PURE__ */ jsx(VisuallyHidden, { children: t("close") }) })
96
- ] }) }),
97
- /* @__PURE__ */ jsxs("tbody", { children: [
98
- currentIsAuthor() && /* @__PURE__ */ jsxs("tr", { children: [
99
- /* @__PURE__ */ jsx("th", { scope: "row", children: /* @__PURE__ */ jsx(Avatar, { alt: t("explorer.modal.share.avatar.me.alt"), size: "xs", src: myAvatar, variant: "circle" }) }),
100
- /* @__PURE__ */ jsx("td", { children: t("share.me") }),
101
- shareRightActions.map((shareRightAction) => /* @__PURE__ */ jsx("td", { style: {
102
- width: "80px"
103
- }, className: "text-center text-white", children: /* @__PURE__ */ jsx(Checkbox, { checked: !0, disabled: !0 }) }, shareRightAction.displayName)),
104
- /* @__PURE__ */ jsx("td", {})
105
- ] }),
106
- /* @__PURE__ */ jsx(ShareBookmarkLine, { showBookmark, shareRightActions, shareRights, onDeleteRow: handleDeleteRow, toggleRight, toggleBookmark })
107
- ] })
108
- ] }) }),
109
- /* @__PURE__ */ jsxs("div", { className: "mt-16", children: [
110
- /* @__PURE__ */ jsx(Button, { color: "tertiary", leftIcon: /* @__PURE__ */ jsx(SvgIconBookmark, {}), rightIcon: /* @__PURE__ */ jsx(SvgIconRafterDown, { title: t("show"), className: "w-16 min-w-0", style: {
111
- transition: "rotate 0.2s ease-out",
112
- rotate: showBookmarkInput ? "-180deg" : "0deg"
113
- } }), type: "button", variant: "ghost", className: "fw-normal", onClick: () => toggleBookmarkInput(!showBookmarkInput), children: t("share.save.sharebookmark") }),
114
- showBookmarkInput && /* @__PURE__ */ jsx(ShareBookmark, { refBookmark, bookmark, onBookmarkChange: handleBookmarkChange, onSave: handleOnSave })
115
- ] }),
116
- /* @__PURE__ */ jsx("hr", {}),
117
- /* @__PURE__ */ jsxs(Heading, { headingStyle: "h4", level: "h3", className: "mb-16 d-flex align-items-center", children: [
118
- /* @__PURE__ */ jsx("div", { className: "me-8", children: t("explorer.modal.share.search") }),
119
- /* @__PURE__ */ jsx(Tooltip, { message: "Vos favoris de partage s’affichent en priorité dans votre liste lorsque vous recherchez un groupe ou une personne, vous pouvez les retrouver dans l’annuaire.", placement: "top", children: /* @__PURE__ */ jsx(SvgIconInfoCircle, { className: "c-pointer", height: "18" }) })
120
- ] }),
121
- /* @__PURE__ */ jsx("div", { className: "row", children: /* @__PURE__ */ jsx("div", { className: "col-10", children: /* @__PURE__ */ jsx(Combobox, { value: searchInputValue, placeholder: searchPlaceholder, isLoading: showSearchLoading(), noResult: showSearchNoResults(), options: searchResults, searchMinLength: getSearchMinLength(), onSearchInputChange: handleSearchInputChange, onSearchResultsChange: handleSearchResultsChange }) }) }),
28
+ /* @__PURE__ */ jsx(ShareResources, { shareOptions, shareResource, ref: refShareResources, onSuccess, classNameSearchInput: "flex-fill" }),
122
29
  children
123
30
  ] }),
124
31
  /* @__PURE__ */ jsxs(Modal.Footer, { children: [
125
32
  /* @__PURE__ */ jsx(Button, { type: "button", color: "tertiary", variant: "ghost", onClick: onCancel, children: t("explorer.cancel") }),
126
- /* @__PURE__ */ jsx(Button, { type: "button", color: "primary", variant: "filled", isLoading: isSharing, onClick: handleShare, disabled: isSharing, children: t("share") })
33
+ /* @__PURE__ */ jsx(Button, { type: "button", color: "primary", variant: "filled", isLoading: !!((_a = refShareResources.current) != null && _a.isSharing()), onClick: handleShare, disabled: !!((_b = refShareResources.current) != null && _b.isSharing()), children: t("share") })
127
34
  ] })
128
- ] }), document.getElementById("portal"));
35
+ ] }), document.getElementById("portal") || document.body);
129
36
  }
130
37
  export {
131
38
  ShareResourceModal as default
@@ -0,0 +1,165 @@
1
+ import { ID, PutShareResponse, RightStringified, ShareRight, ShareRightActionDisplayName, ShareUrls } from '@edifice.io/client';
2
+ import { UseMutationResult } from '../../../node_modules/@tanstack/react-query';
3
+ /**
4
+ * Configuration options for sharing a resource
5
+ *
6
+ * @typedef {Object} ShareOptions
7
+ * @property {ID} resourceId - Unique identifier of the resource to share
8
+ * @property {RightStringified[]} resourceRights - Current rights assigned to the resource
9
+ * @property {string} resourceCreatorId - User ID of the resource creator
10
+ * @property {ShareRightActionDisplayName[]} [filteredActions] - Optional list of allowed actions to display
11
+ * @property {ShareUrls} [urls] - Optional custom URLs for API endpoints related to sharing operations
12
+ *
13
+ * @example Example related to sharing thread resources:
14
+ * ```ts
15
+ * const shareOptions: ShareOptions = {
16
+ * resourceId: '12345',
17
+ * resourceRights: [],
18
+ * resourceCreatorId: 'user-67890',
19
+ * filteredActions: ['read', 'contrib'],
20
+ * urls: {
21
+ * getResourceRights: '/api/V1/thread/shares', (get endpoint)
22
+ * saveResourceRights: '/api/V1/thread/shares', (put endpoint)
23
+ * getShareMapping: '/api/V1/rights/sharing'
24
+ * }
25
+ * };
26
+ * ```
27
+ *
28
+ * @example Example related to sharing info resources:
29
+ * ```ts
30
+ * const shareOptions: ShareOptions = {
31
+ * resourceId: '12345',
32
+ * resourceRights: [],
33
+ * resourceCreatorId: 'user-67890',
34
+ * filteredActions: ['read', 'contrib'],
35
+ * urls: {
36
+ * getResourceRights: '/api/V1/info/shares', (get endpoint)
37
+ * saveResourceRights: '/api/V1/info/shares', (put endpoint)
38
+ * getShareMapping: '/api/V1/rights/sharing'
39
+ * }
40
+ * };
41
+ * ```
42
+ */
43
+ export type ShareOptions = {
44
+ resourceId: ID;
45
+ resourceRights: RightStringified[];
46
+ resourceCreatorId: string;
47
+ filteredActions?: ShareRightActionDisplayName[];
48
+ urls?: ShareUrls;
49
+ };
50
+ /**
51
+ * React Query mutation result for share operations
52
+ *
53
+ * @typedef {UseMutationResult<PutShareResponse, unknown, {resourceId: string; rights: ShareRight[]}, unknown>} ShareResourceMutation
54
+ */
55
+ export type ShareResourceMutation = UseMutationResult<PutShareResponse, unknown, {
56
+ resourceId: string;
57
+ rights: ShareRight[];
58
+ }, unknown>;
59
+ /**
60
+ * Props for the ShareResources component
61
+ *
62
+ * @interface ShareResourceProps
63
+ * @property {ShareOptions} shareOptions - Configuration for the resource being shared
64
+ * @property {ShareResourceMutation} [shareResource] - Optional React Query mutation for optimistic UI updates
65
+ * @property {() => void} [onSuccess] - Callback fired after successful share operation
66
+ * @property {(shareRights: ShareRight[], isDirty: boolean) => void} [onChange] - Callback fired when share rights change
67
+ * @property {string} [classNameSearchInput] - Optional CSS class for the search input wrapper (default: 'col-6')
68
+ */
69
+ interface ShareResourceProps {
70
+ /**
71
+ * Expect resourceId,
72
+ * new rights array (replace shared array),
73
+ * creatorId
74
+ * of a resource */
75
+ shareOptions: ShareOptions;
76
+ /**
77
+ * Use the `shareResource` props when you need to do Optimistic UI
78
+ * otherwise ShareModal handles everything
79
+ * Must use React Query */
80
+ shareResource?: ShareResourceMutation;
81
+ /**
82
+ * onSuccess callback when a resource is successfully shared
83
+ */
84
+ onSuccess?: () => void;
85
+ /**
86
+ * Callback when share rights change
87
+ */
88
+ onChange?: (shareRights: ShareRight[], isDirty: boolean) => void;
89
+ /**
90
+ * Optional className for the search input
91
+ */
92
+ classNameSearchInput?: string;
93
+ }
94
+ /**
95
+ * Ref interface exposed by ShareResources component
96
+ *
97
+ * @interface ShareResourcesRef
98
+ * @property {() => void} handleShare - Method to trigger the share operation
99
+ * @property {() => boolean} isSharing - Method to check if sharing is in progress
100
+ *
101
+ * @example
102
+ * ```tsx
103
+ * const ref = useRef<ShareResourcesRef>(null);
104
+ *
105
+ * // Trigger share programmatically
106
+ * ref.current?.handleShare();
107
+ *
108
+ * // Check sharing status
109
+ * const sharing = ref.current?.isSharing();
110
+ * ```
111
+ */
112
+ export interface ShareResourcesRef {
113
+ handleShare: () => void;
114
+ isSharing: () => boolean;
115
+ }
116
+ /**
117
+ * ShareResources Component
118
+ *
119
+ * A component for managing resource sharing permissions with users and groups.
120
+ * Provides search functionality, bookmark management, and granular rights control.
121
+ *
122
+ * @example
123
+ * ```tsx
124
+ * import { useRef } from 'react';
125
+ * import ShareResources, { ShareResourcesRef, ShareOptions } from './ShareResources';
126
+ *
127
+ * function MyComponent() {
128
+ * const shareRef = useRef<ShareResourcesRef>(null);
129
+ *
130
+ * const shareOptions: ShareOptions = {
131
+ * resourceId: '123',
132
+ * resourceRights: [],
133
+ * resourceCreatorId: 'user-456',
134
+ * filteredActions: ['read', 'contrib'],
135
+ * urls: {
136
+ * getResourceRights: '/api/share/rights',
137
+ * putResourceRights: '/api/share/update'
138
+ * }
139
+ * };
140
+ *
141
+ * const handleSave = () => {
142
+ * if (shareRef.current) {
143
+ * shareRef.current.handleShare();
144
+ * }
145
+ * };
146
+ *
147
+ * return (
148
+ * <>
149
+ * <ShareResources
150
+ * ref={shareRef}
151
+ * shareOptions={shareOptions}
152
+ * onSuccess={() => console.log('Shared successfully')}
153
+ * onChange={(rights, isDirty) => console.log('Rights changed:', isDirty)}
154
+ * />
155
+ * <button onClick={handleSave}>Save Changes</button>
156
+ * </>
157
+ * );
158
+ * }
159
+ * ```
160
+ *
161
+ * @component
162
+ * @forwardRef
163
+ */
164
+ declare const ShareResources: import('react').ForwardRefExoticComponent<ShareResourceProps & import('react').RefAttributes<ShareResourcesRef>>;
165
+ export default ShareResources;
@@ -0,0 +1,132 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { forwardRef, useState, useImperativeHandle, useEffect } from "react";
3
+ import { useTranslation } from "react-i18next";
4
+ import SvgIconBookmark from "../../icons/components/IconBookmark.js";
5
+ import SvgIconInfoCircle from "../../icons/components/IconInfoCircle.js";
6
+ import SvgIconRafterDown from "../../icons/components/IconRafterDown.js";
7
+ import { ShareBookmark } from "./ShareBookmark.js";
8
+ import { ShareBookmarkLine } from "./ShareBookmarkLine.js";
9
+ import { useSearch } from "./hooks/useSearch.js";
10
+ import useShare from "./hooks/useShare.js";
11
+ import { useShareBookmark } from "./hooks/useShareBookmark.js";
12
+ import Heading from "../../../components/Heading/Heading.js";
13
+ import Tooltip from "../../../components/Tooltip/Tooltip.js";
14
+ import Combobox from "../../../components/Combobox/Combobox.js";
15
+ import LoadingScreen from "../../../components/LoadingScreen/LoadingScreen.js";
16
+ import VisuallyHidden from "../../../components/VisuallyHidden/VisuallyHidden.js";
17
+ import Avatar from "../../../components/Avatar/Avatar.js";
18
+ import Checkbox from "../../../components/Checkbox/Checkbox.js";
19
+ import Button from "../../../components/Button/Button.js";
20
+ const ShareResources = /* @__PURE__ */ forwardRef(({
21
+ shareOptions,
22
+ shareResource,
23
+ onSuccess = () => {
24
+ },
25
+ onChange = () => {
26
+ },
27
+ classNameSearchInput = "col-6"
28
+ }, ref) => {
29
+ const {
30
+ resourceId,
31
+ resourceCreatorId,
32
+ resourceRights,
33
+ filteredActions,
34
+ urls
35
+ } = shareOptions, [isLoading, setIsLoading] = useState(!0), {
36
+ state: {
37
+ isSharing,
38
+ shareRights,
39
+ shareRightActions
40
+ },
41
+ dispatch: shareDispatch,
42
+ myAvatar,
43
+ currentIsAuthor,
44
+ toggleRight,
45
+ handleShare,
46
+ handleDeleteRow,
47
+ isDirty
48
+ } = useShare({
49
+ resourceId,
50
+ resourceCreatorId,
51
+ resourceRights,
52
+ shareResource,
53
+ setIsLoading,
54
+ onSuccess,
55
+ filteredActions,
56
+ urls
57
+ }), {
58
+ state: {
59
+ searchResults,
60
+ searchInputValue
61
+ },
62
+ showSearchAdmlHint,
63
+ showSearchLoading,
64
+ showSearchNoResults,
65
+ getSearchMinLength,
66
+ handleSearchInputChange,
67
+ handleSearchResultsChange
68
+ } = useSearch({
69
+ resourceId,
70
+ resourceCreatorId,
71
+ shareRights,
72
+ shareDispatch,
73
+ urlResourceRights: urls == null ? void 0 : urls.getResourceRights
74
+ }), {
75
+ refBookmark,
76
+ showBookmark,
77
+ handleBookmarkChange,
78
+ toggleBookmark,
79
+ bookmark,
80
+ handleOnSave,
81
+ showBookmarkInput,
82
+ toggleBookmarkInput
83
+ } = useShareBookmark({
84
+ shareRights,
85
+ shareDispatch
86
+ });
87
+ useImperativeHandle(ref, () => ({
88
+ handleShare,
89
+ isSharing: () => isSharing
90
+ }), [handleShare, isSharing]), useEffect(() => {
91
+ onChange(shareRights.rights, isDirty);
92
+ }, [isDirty, shareRights.rights, onChange]);
93
+ const {
94
+ t
95
+ } = useTranslation(), searchPlaceholder = showSearchAdmlHint() ? t("explorer.search.adml.hint") : t("explorer.modal.share.search.placeholder");
96
+ return /* @__PURE__ */ jsxs("div", { children: [
97
+ /* @__PURE__ */ jsxs(Heading, { headingStyle: "h4", level: "h3", className: "mb-16 d-flex align-items-center", children: [
98
+ /* @__PURE__ */ jsx("div", { className: "me-8", children: t("explorer.modal.share.search") }),
99
+ /* @__PURE__ */ jsx(Tooltip, { message: "Vos favoris de partage s’affichent en priorité dans votre liste lorsque vous recherchez un groupe ou une personne, vous pouvez les retrouver dans l’annuaire.", placement: "top", children: /* @__PURE__ */ jsx(SvgIconInfoCircle, { className: "c-pointer", height: "18" }) })
100
+ ] }),
101
+ /* @__PURE__ */ jsx("div", { className: "row mb-16", children: /* @__PURE__ */ jsx("div", { className: classNameSearchInput, children: /* @__PURE__ */ jsx(Combobox, { value: searchInputValue, placeholder: searchPlaceholder, isLoading: showSearchLoading(), noResult: showSearchNoResults(), options: searchResults, searchMinLength: getSearchMinLength(), onSearchInputChange: handleSearchInputChange, onSearchResultsChange: handleSearchResultsChange }) }) }),
102
+ /* @__PURE__ */ jsx("div", { className: "table-responsive", children: isLoading ? /* @__PURE__ */ jsx(LoadingScreen, {}) : /* @__PURE__ */ jsxs("table", { className: "table border align-middle mb-0", children: [
103
+ /* @__PURE__ */ jsx("thead", { className: "bg-blue-200", children: /* @__PURE__ */ jsxs("tr", { children: [
104
+ /* @__PURE__ */ jsx("th", { scope: "col", className: "w-32", children: /* @__PURE__ */ jsx(VisuallyHidden, { children: t("explorer.modal.share.avatar.shared.alt") }) }),
105
+ /* @__PURE__ */ jsx("th", { scope: "col", children: /* @__PURE__ */ jsx(VisuallyHidden, { children: t("explorer.modal.share.search.placeholder") }) }),
106
+ shareRightActions.map((shareRightAction) => /* @__PURE__ */ jsx("th", { scope: "col", className: "text-center text-gray-800", children: t(shareRightAction.displayName) }, shareRightAction.displayName)),
107
+ /* @__PURE__ */ jsx("th", { scope: "col", children: /* @__PURE__ */ jsx(VisuallyHidden, { children: t("close") }) })
108
+ ] }) }),
109
+ /* @__PURE__ */ jsxs("tbody", { children: [
110
+ currentIsAuthor() && /* @__PURE__ */ jsxs("tr", { children: [
111
+ /* @__PURE__ */ jsx("th", { scope: "row", children: /* @__PURE__ */ jsx(Avatar, { alt: t("explorer.modal.share.avatar.me.alt"), size: "xs", src: myAvatar, variant: "circle" }) }),
112
+ /* @__PURE__ */ jsx("td", { children: t("share.me") }),
113
+ shareRightActions.map((shareRightAction) => /* @__PURE__ */ jsx("td", { style: {
114
+ width: "80px"
115
+ }, className: "text-center text-white", children: /* @__PURE__ */ jsx(Checkbox, { checked: !0, disabled: !0 }) }, shareRightAction.displayName)),
116
+ /* @__PURE__ */ jsx("td", {})
117
+ ] }),
118
+ /* @__PURE__ */ jsx(ShareBookmarkLine, { showBookmark, shareRightActions, shareRights, onDeleteRow: handleDeleteRow, toggleRight, toggleBookmark })
119
+ ] })
120
+ ] }) }),
121
+ /* @__PURE__ */ jsxs("div", { className: "mt-16", children: [
122
+ /* @__PURE__ */ jsx(Button, { color: "tertiary", leftIcon: /* @__PURE__ */ jsx(SvgIconBookmark, {}), rightIcon: /* @__PURE__ */ jsx(SvgIconRafterDown, { title: t("show"), className: "w-16 min-w-0", style: {
123
+ transition: "rotate 0.2s ease-out",
124
+ rotate: showBookmarkInput ? "-180deg" : "0deg"
125
+ } }), type: "button", variant: "ghost", className: "fw-normal", onClick: () => toggleBookmarkInput(!showBookmarkInput), children: t("share.save.sharebookmark") }),
126
+ showBookmarkInput && /* @__PURE__ */ jsx(ShareBookmark, { refBookmark, bookmark, onBookmarkChange: handleBookmarkChange, onSave: handleOnSave })
127
+ ] })
128
+ ] });
129
+ });
130
+ export {
131
+ ShareResources as default
132
+ };
@@ -3,11 +3,12 @@ import { ShareRightWithVisibles, ShareSubject } from '@edifice.io/client';
3
3
  import { OptionListItemType } from '../../../../components';
4
4
  import { ShareOptions } from '../ShareModal';
5
5
  import { ShareAction } from './useShare';
6
- export declare const useSearch: ({ resourceId, resourceCreatorId, shareRights, shareDispatch, }: {
6
+ export declare const useSearch: ({ resourceId, resourceCreatorId, shareRights, shareDispatch, urlResourceRights, }: {
7
7
  resourceId: ShareOptions["resourceCreatorId"];
8
8
  resourceCreatorId: ShareOptions["resourceCreatorId"];
9
9
  shareRights: ShareRightWithVisibles;
10
10
  shareDispatch: Dispatch<ShareAction>;
11
+ urlResourceRights?: string;
11
12
  }) => {
12
13
  state: {
13
14
  searchInputValue: string;
@@ -58,7 +58,8 @@ const defaultActions = [{
58
58
  resourceId,
59
59
  resourceCreatorId,
60
60
  shareRights,
61
- shareDispatch
61
+ shareDispatch,
62
+ urlResourceRights
62
63
  }) => {
63
64
  const [state, dispatch] = useReducer(reducer, initialState), debouncedSearchInputValue = useDebounce(state.searchInputValue, 500), {
64
65
  isAdml
@@ -82,7 +83,7 @@ const defaultActions = [{
82
83
  type: "isSearching",
83
84
  payload: !0
84
85
  }), !isAdml && debouncedSearchInputValue2.length >= 1 || isAdml && debouncedSearchInputValue2.length >= 3) {
85
- const resSearchShareSubjects = await odeServices.share().searchShareSubjects(appCode, resourceId, debouncedSearchInputValue2);
86
+ const resSearchShareSubjects = await odeServices.share().searchShareSubjects(appCode, resourceId, debouncedSearchInputValue2, urlResourceRights);
86
87
  dispatch({
87
88
  type: "addApiResult",
88
89
  payload: resSearchShareSubjects
@@ -1,5 +1,5 @@
1
- import { ShareRight, ShareRightAction, ShareRightActionDisplayName, ShareRightWithVisibles } from '@edifice.io/client';
2
- import { ShareOptions, ShareResourceMutation } from '../ShareModal';
1
+ import { ShareRight, ShareRightAction, ShareRightActionDisplayName, ShareRightWithVisibles, ShareUrls } from '@edifice.io/client';
2
+ import { ShareOptions, ShareResourceMutation } from '../ShareResources';
3
3
  interface UseShareResourceModalProps {
4
4
  /**
5
5
  * Resource ID (assetId)
@@ -15,10 +15,15 @@ interface UseShareResourceModalProps {
15
15
  resourceCreatorId: ShareOptions['resourceCreatorId'];
16
16
  shareResource?: ShareResourceMutation;
17
17
  onSuccess: () => void;
18
- setIsLoading: (value: boolean) => void;
18
+ setIsLoading?: (value: boolean) => void;
19
+ resourceShareRights?: ShareRightWithVisibles;
20
+ resourceShareRightActions?: ShareRightAction[];
21
+ filteredActions?: ShareRightActionDisplayName[];
22
+ urls?: ShareUrls;
19
23
  }
20
24
  type State = {
21
25
  isSharing: boolean;
26
+ isDirty?: boolean;
22
27
  shareRights: ShareRightWithVisibles;
23
28
  shareRightActions: ShareRightAction[];
24
29
  };
@@ -38,9 +43,10 @@ export type ShareAction = {
38
43
  type: 'isSharing';
39
44
  payload: boolean;
40
45
  };
41
- export default function useShare({ resourceId, resourceRights, resourceCreatorId, shareResource, setIsLoading, onSuccess, }: UseShareResourceModalProps): {
46
+ export default function useShare({ resourceId, resourceRights, resourceCreatorId, shareResource, setIsLoading, onSuccess, filteredActions, urls, }: UseShareResourceModalProps): {
42
47
  state: {
43
48
  isSharing: boolean;
49
+ isDirty?: boolean;
44
50
  shareRights: ShareRightWithVisibles;
45
51
  shareRightActions: ShareRightAction[];
46
52
  };
@@ -50,5 +56,6 @@ export default function useShare({ resourceId, resourceRights, resourceCreatorId
50
56
  handleDeleteRow: (shareRight: ShareRight) => void;
51
57
  handleShare: () => Promise<void>;
52
58
  toggleRight: (shareRight: ShareRight, actionName: ShareRightActionDisplayName) => void;
59
+ isDirty: boolean;
53
60
  };
54
61
  export {};
@@ -6,6 +6,7 @@ import useUser from "../../../../hooks/useUser/useUser.js";
6
6
  import useToast from "../../../../hooks/useToast/useToast.js";
7
7
  const initialState = {
8
8
  isSharing: !1,
9
+ isDirty: !1,
9
10
  shareRights: {
10
11
  rights: [],
11
12
  visibleBookmarks: [],
@@ -24,17 +25,20 @@ function reducer(state, action) {
24
25
  case "deleteRow":
25
26
  return {
26
27
  ...state,
27
- shareRights: action.payload
28
+ shareRights: action.payload,
29
+ isDirty: !0
28
30
  };
29
31
  case "updateShareRights":
30
32
  return {
31
33
  ...state,
32
- shareRights: action.payload
34
+ shareRights: action.payload,
35
+ isDirty: !0
33
36
  };
34
37
  case "toggleRight":
35
38
  return {
36
39
  ...state,
37
- shareRights: action.payload
40
+ shareRights: action.payload,
41
+ isDirty: !0
38
42
  };
39
43
  case "isSharing":
40
44
  return {
@@ -51,7 +55,9 @@ function useShare({
51
55
  resourceCreatorId,
52
56
  shareResource,
53
57
  setIsLoading,
54
- onSuccess
58
+ onSuccess,
59
+ filteredActions,
60
+ urls
55
61
  }) {
56
62
  const {
57
63
  appCode
@@ -64,18 +70,18 @@ function useShare({
64
70
  useEffect(() => {
65
71
  resourceId && (async () => {
66
72
  try {
67
- const [shareRightActions, shareRights] = await Promise.all([odeServices.share().getActionsForApp(appCode), odeServices.share().getRightsForResource(appCode, resourceId)]);
73
+ const [shareRightActions, shareRights] = await Promise.all([odeServices.share().getActionsForApp(appCode, urls == null ? void 0 : urls.getShareMapping), odeServices.share().getRightsForResource(appCode, resourceId, urls)]), filteredShareRightActions = filteredActions ? shareRightActions.filter((action) => filteredActions.includes(action.id)) : shareRightActions;
68
74
  dispatch({
69
75
  type: "init",
70
76
  payload: {
71
- shareRightActions,
77
+ shareRightActions: filteredShareRightActions,
72
78
  shareRights
73
79
  }
74
80
  });
75
81
  } catch (error) {
76
82
  console.error(error);
77
83
  }
78
- setIsLoading(!1);
84
+ setIsLoading == null || setIsLoading(!1);
79
85
  })();
80
86
  }, [resourceId]);
81
87
  const toggleRight = (shareRight, actionName) => {
@@ -171,10 +177,10 @@ function useShare({
171
177
  });
172
178
  notifySuccess(result);
173
179
  } else {
174
- const result = await odeServices.share().saveRights(appCode, resourceId, shares);
180
+ const result = await odeServices.share().saveRights(appCode, resourceId, shares, urls);
175
181
  notifySuccess(result);
176
182
  }
177
- onSuccess();
183
+ urls != null && urls.getResourceRights && odeServices.cache().clearCache(urls.getResourceRights), onSuccess();
178
184
  } catch (error) {
179
185
  typeof error == "string" && toast.error(t("explorer.shared.status.error")), typeof error == "object" && toast.error(t((error == null ? void 0 : error.error) || "explorer.shared.status.error")), console.error("Failed to save share", error);
180
186
  } finally {
@@ -184,7 +190,8 @@ function useShare({
184
190
  });
185
191
  }
186
192
  },
187
- toggleRight
193
+ toggleRight,
194
+ isDirty: !!state.isDirty
188
195
  };
189
196
  }
190
197
  export {
@@ -1,3 +1,5 @@
1
- export { default as ShareModal } from './ShareModal';
2
1
  export { default as ShareBlog } from './apps/ShareBlog';
3
2
  export { default as useShareMutation } from './hooks/useShareMutation';
3
+ export { default as ShareModal } from './ShareModal';
4
+ export * from './ShareResources';
5
+ export { default as ShareResources } from './ShareResources';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edifice.io/react",
3
- "version": "2.4.2-develop-b2school-actualites.20251119110458",
3
+ "version": "2.4.2-develop-b2school-actualites.20251124095016",
4
4
  "description": "Edifice React Library",
5
5
  "keywords": [
6
6
  "react",
@@ -131,9 +131,9 @@
131
131
  "react-slugify": "^3.0.3",
132
132
  "swiper": "^10.1.0",
133
133
  "ua-parser-js": "^1.0.36",
134
- "@edifice.io/bootstrap": "2.4.2-develop-b2school-actualites.20251119110458",
135
- "@edifice.io/utilities": "2.4.2-develop-b2school-actualites.20251119110458",
136
- "@edifice.io/tiptap-extensions": "2.4.2-develop-b2school-actualites.20251119110458"
134
+ "@edifice.io/utilities": "2.4.2-develop-b2school-actualites.20251124095016",
135
+ "@edifice.io/tiptap-extensions": "2.4.2-develop-b2school-actualites.20251124095016",
136
+ "@edifice.io/bootstrap": "2.4.2-develop-b2school-actualites.20251124095016"
137
137
  },
138
138
  "devDependencies": {
139
139
  "@babel/plugin-transform-react-pure-annotations": "^7.23.3",
@@ -164,8 +164,8 @@
164
164
  "vite": "^5.4.11",
165
165
  "vite-plugin-dts": "^4.1.0",
166
166
  "vite-tsconfig-paths": "^5.0.1",
167
- "@edifice.io/client": "2.4.2-develop-b2school-actualites.20251119110458",
168
- "@edifice.io/config": "2.4.2-develop-b2school-actualites.20251119110458"
167
+ "@edifice.io/client": "2.4.2-develop-b2school-actualites.20251124095016",
168
+ "@edifice.io/config": "2.4.2-develop-b2school-actualites.20251124095016"
169
169
  },
170
170
  "peerDependencies": {
171
171
  "@react-spring/web": "^9.7.5",