@edifice.io/react 2.0.3 → 2.0.5-develop-pedago.20250123145105

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 (45) hide show
  1. package/README.md +3 -3
  2. package/dist/components/Attachment/Attachment.js +1 -1
  3. package/dist/components/Button/Button.js +1 -1
  4. package/dist/components/Layout/components/Header.js +4 -3
  5. package/dist/components/Modal/Modal.js +1 -1
  6. package/dist/components/Tree/components/SortableTree.js +3 -2
  7. package/dist/components/Tree/types/index.d.ts +1 -0
  8. package/dist/components/Tree/utilities/tree.d.ts +2 -1
  9. package/dist/hooks/useConf/useConf.d.ts +2 -2
  10. package/dist/hooks/useDropzone/useDropzone.js +1 -1
  11. package/dist/hooks/useHasWorkflow/useHasWorkflow.js +3 -11
  12. package/dist/hooks/useSession/useSession.d.ts +2 -1
  13. package/dist/hooks/useTrapFocus/useTrapFocus.d.ts +1 -1
  14. package/dist/hooks/useTrapFocus/useTrapFocus.js +3 -2
  15. package/dist/hooks/useWorkspaceSearch/useWorkspaceSearch.js +3 -11
  16. package/dist/index.js +2 -0
  17. package/dist/modules/audience/ReactionChoice.d.ts +13 -0
  18. package/dist/modules/audience/ReactionModal.d.ts +24 -6
  19. package/dist/modules/audience/ReactionModal.js +12 -9
  20. package/dist/modules/audience/ReactionSummary.d.ts +9 -0
  21. package/dist/modules/audience/ViewsCounter.d.ts +10 -0
  22. package/dist/modules/audience/ViewsModal.d.ts +13 -1
  23. package/dist/modules/audience/ViewsModal.js +22 -19
  24. package/dist/modules/comments/components/Comment.js +10 -7
  25. package/dist/modules/comments/components/DeleteModal.d.ts +7 -0
  26. package/dist/modules/comments/components/DeleteModal.js +19 -0
  27. package/dist/modules/comments/context/Context.d.ts +2 -0
  28. package/dist/modules/comments/hooks/useComments.d.ts +5 -2
  29. package/dist/modules/comments/hooks/useComments.js +1 -1
  30. package/dist/modules/comments/hooks/useCommentsContext.d.ts +1 -0
  31. package/dist/modules/comments/hooks/useProfileQueries.d.ts +4 -1
  32. package/dist/modules/comments/provider/CommentProvider.js +2 -1
  33. package/dist/modules/comments/types.d.ts +5 -1
  34. package/dist/modules/editor/components/Renderer/AttachmentRenderer.js +12 -7
  35. package/dist/modules/editor/components/Renderer/AudioRenderer.js +4 -1
  36. package/dist/modules/editor/hooks/useCommentEditor.d.ts +1 -1
  37. package/dist/modules/editor/hooks/useTipTapEditor.d.ts +1 -1
  38. package/dist/modules/editor/hooks/useTipTapEditor.js +1 -1
  39. package/dist/providers/MockedProvider/MockedProvider.d.ts +4 -0
  40. package/dist/providers/MockedProvider/MockedProvider.js +20 -0
  41. package/dist/providers/index.d.ts +1 -0
  42. package/package.json +38 -35
  43. package/dist/providers/MockedDataProvider/MockedDataProvider.d.ts +0 -28
  44. package/dist/providers/MockedDataProvider/MockedDataProvider.js +0 -9
  45. package/dist/providers/MockedDataProvider/index.d.ts +0 -1
package/README.md CHANGED
@@ -52,8 +52,8 @@ src
52
52
  - Export everything if Component has types & interfaces
53
53
 
54
54
  ```jsx
55
- export { default as Component } from "./Component";
56
- export * from "./Component";
55
+ export { default as Component } from './Component';
56
+ export * from './Component';
57
57
  ```
58
58
 
59
59
  ### Component Guideline
@@ -102,7 +102,7 @@ export interface ButtonProps {
102
102
  - Import your component inside `index.ts` file.
103
103
 
104
104
  ```jsx
105
- export * from "./Button";
105
+ export * from './Button';
106
106
  ```
107
107
 
108
108
  ## Dev
@@ -6,7 +6,7 @@ const Attachment = /* @__PURE__ */ forwardRef(({
6
6
  name = "Attachment Name",
7
7
  options,
8
8
  ...restProps
9
- }, ref) => /* @__PURE__ */ jsxs("div", { ref, className: "attachment px-12 py-8", ...restProps, children: [
9
+ }, ref) => /* @__PURE__ */ jsxs("div", { ref, className: "attachment px-12 py-8", ...restProps, tabIndex: 0, children: [
10
10
  /* @__PURE__ */ jsxs(Tooltip, { message: name, className: "filename text-truncate d-flex align-items-center gap-8", children: [
11
11
  /* @__PURE__ */ jsx(SvgIconPaperclip, { height: 22, width: 22 }),
12
12
  /* @__PURE__ */ jsx("div", { className: "filename text-truncate", children: name })
@@ -24,7 +24,7 @@ const Button = /* @__PURE__ */ forwardRef(({
24
24
  "btn-lg": size === "lg",
25
25
  "btn-sm": size === "sm"
26
26
  }, className);
27
- return /* @__PURE__ */ jsx("button", { ref, className: classes, type, ...restProps, children: isLoading ? /* @__PURE__ */ jsx(Loading, { isLoading: !0, loadingIcon, loadingPosition, children }) : /* @__PURE__ */ jsxs("span", { children: [
27
+ return /* @__PURE__ */ jsx("button", { ref, className: classes, type, ...restProps, "data-testid": "button", children: isLoading ? /* @__PURE__ */ jsx(Loading, { isLoading: !0, loadingIcon, loadingPosition, children }) : /* @__PURE__ */ jsxs("span", { children: [
28
28
  leftIcon,
29
29
  children,
30
30
  rightIcon
@@ -4,13 +4,14 @@ import { useTranslation } from "react-i18next";
4
4
  import { useEdificeClient } from "../../../providers/EdificeClientProvider/EdificeClientProvider.hook.js";
5
5
  import { useEdificeTheme } from "../../../providers/EdificeThemeProvider/EdificeThemeProvider.hook.js";
6
6
  import SvgIconRafterDown from "../../../modules/icons/components/IconRafterDown.js";
7
- import SvgIconAssistance from "../../../modules/icons/components/apps/IconAssistance.js";
8
7
  import SvgIconCommunity from "../../../modules/icons/components/nav/IconCommunity.js";
9
8
  import SvgIconDisconnect from "../../../modules/icons/components/nav/IconDisconnect.js";
10
9
  import SvgIconHome from "../../../modules/icons/components/nav/IconHome.js";
11
10
  import SvgIconMyApps from "../../../modules/icons/components/nav/IconMyApps.js";
11
+ import SvgIconNeoAssistance from "../../../modules/icons/components/nav/IconNeoAssistance.js";
12
12
  import SvgIconNeoMessaging from "../../../modules/icons/components/nav/IconNeoMessaging.js";
13
13
  import SvgIconNewRelease from "../../../modules/icons/components/nav/IconNewRelease.js";
14
+ import SvgIconOneAssistance from "../../../modules/icons/components/nav/IconOneAssistance.js";
14
15
  import SvgIconOneMessaging from "../../../modules/icons/components/nav/IconOneMessaging.js";
15
16
  import SvgIconOneProfile from "../../../modules/icons/components/nav/IconOneProfile.js";
16
17
  import SvgIconUserbook from "../../../modules/icons/components/nav/IconUserbook.js";
@@ -98,7 +99,7 @@ const Header = ({
98
99
  /* @__PURE__ */ jsxs("button", { className: "nav-link", onClick: () => {
99
100
  setIsHelpOpen(!0);
100
101
  }, children: [
101
- /* @__PURE__ */ jsx(SvgIconAssistance, { className: "icon help" }),
102
+ /* @__PURE__ */ jsx(SvgIconOneAssistance, { className: "icon help" }),
102
103
  /* @__PURE__ */ jsx(VisuallyHidden, { children: t("navbar.help") })
103
104
  ] }),
104
105
  /* @__PURE__ */ jsx(Help, { isHelpOpen, setIsHelpOpen, parsedContent, parsedHeadline, error })
@@ -157,7 +158,7 @@ const Header = ({
157
158
  /* @__PURE__ */ jsxs("button", { className: "nav-link btn btn-naked", onClick: () => {
158
159
  setIsHelpOpen(!0);
159
160
  }, children: [
160
- /* @__PURE__ */ jsx(SvgIconAssistance, { color: "#fff" }),
161
+ /* @__PURE__ */ jsx(SvgIconNeoAssistance, { color: "#fff" }),
161
162
  /* @__PURE__ */ jsx(VisuallyHidden, { children: t("support") })
162
163
  ] }),
163
164
  /* @__PURE__ */ jsx(Help, { isHelpOpen, setIsHelpOpen, parsedContent, parsedHeadline, error })
@@ -20,7 +20,7 @@ const Root = /* @__PURE__ */ forwardRef((props, ref) => {
20
20
  scrollable = !1,
21
21
  focusId,
22
22
  children
23
- } = props, ariaLabelId = `aria_label_${id}`, ariaDescriptionId = `aria_desc_${id}`, modalRef = useClickOutside(onModalClose), trapRef = useTrapFocus();
23
+ } = props, ariaLabelId = `aria_label_${id}`, ariaDescriptionId = `aria_desc_${id}`, modalRef = useClickOutside(onModalClose), trapRef = useTrapFocus(isOpen);
24
24
  useKeyPress(onModalClose, ["Escape"]), useEffect(() => {
25
25
  if (isOpen && (document.body.style.overflow = "hidden", focusId)) {
26
26
  const elem = document.getElementById(focusId);
@@ -11,6 +11,7 @@ import SvgIconRafterRight from "../../../modules/icons/components/IconRafterRigh
11
11
  import { useTree } from "../hooks/useTree.js";
12
12
  import { useTreeSortable } from "../hooks/useTreeSortable.js";
13
13
  import { flattenNodes } from "../utilities/tree-sortable.js";
14
+ import { mergeRefs } from "../../../utilities/refs/ref.js";
14
15
  const SortableTree = ({
15
16
  nodes,
16
17
  selectedNodeId: externalSelectedNodeId,
@@ -73,7 +74,7 @@ const SortableTree = ({
73
74
  renderNode,
74
75
  onTreeItemClick,
75
76
  onToggleNode
76
- }) => {
77
+ }, ref) => {
77
78
  const {
78
79
  t
79
80
  } = useTranslation(), selected = selectedNodeId === node.id, expanded = expandedNodes.has(node.id), animateLayoutChanges = ({
@@ -108,7 +109,7 @@ const SortableTree = ({
108
109
  }, handleItemToggleKeyDown = (event) => {
109
110
  (event.code === "Enter" || event.code === "Space") && (event.preventDefault(), event.stopPropagation(), onToggleNode == null || onToggleNode(node.id));
110
111
  }, spaceGestion = () => isDragging ? isChild ? depth === 1 ? `${indentationWidth * depth}px` : "0px" : `${indentationWidth * depth}px` : isChild ? "20px" : null;
111
- return /* @__PURE__ */ jsx("li", { ref: setNodeRef, id: `treeitem-${node.id}`, role: "treeitem", "aria-selected": selected, "aria-expanded": expanded, style: {
112
+ return /* @__PURE__ */ jsx("li", { ref: mergeRefs(setNodeRef, ref), id: `treeitem-${node.id}`, role: "treeitem", "aria-selected": selected, "aria-expanded": expanded, style: {
112
113
  ...style,
113
114
  marginLeft: spaceGestion()
114
115
  }, ...listeners, children: /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs("div", { className: treeItemClasses.action, children: [
@@ -41,6 +41,7 @@ export interface TreeProps extends SharedTreeProps {
41
41
  onTreeItemUnfold?: (nodeId: string) => void;
42
42
  /**
43
43
  * Callback function to secondary action
44
+ * @deprecated Use `renderNode ` instead
44
45
  */
45
46
  onTreeItemAction?: (nodeId: string) => void;
46
47
  }
@@ -1,6 +1,7 @@
1
1
  import { IFolder } from '@edifice.io/client';
2
2
  import { TreeItem } from '../types';
3
3
  export declare function findNodeById(data: TreeItem | TreeItem[], id: string): TreeItem | undefined;
4
+ export declare function getChildrenIds(data: TreeItem[], folderId: string): string[];
4
5
  export declare function addNode(node: TreeItem, { parentId, newFolder }: {
5
6
  parentId: string;
6
7
  newFolder: IFolder;
@@ -10,7 +11,7 @@ export declare function deleteNode(node: TreeItem, { folders }: {
10
11
  folders: string[];
11
12
  }): TreeItem;
12
13
  export declare const findParentNode: (parentNode: TreeItem, childId: string) => TreeItem | undefined;
13
- export declare function getAncestors(data: TreeItem, folderId: string): string[];
14
+ export declare function getAncestors(data: TreeItem[], folderId: string): string[];
14
15
  export declare function hasChildren(folderId: string, data: TreeItem): boolean;
15
16
  export declare function modifyNode(data: TreeItem, callback: (node: TreeItem, parent?: TreeItem) => TreeItem | undefined): TreeItem;
16
17
  export declare function moveNode(node: TreeItem, { destinationId, folders }: {
@@ -1,4 +1,4 @@
1
- import { App } from '@edifice.io/client';
1
+ import { App, IGetConf } from '@edifice.io/client';
2
2
  export default function useConf({ appCode }: {
3
3
  appCode: App;
4
- }): QueryObserverResult<TData, TError>;
4
+ }): import('../../../node_modules/@tanstack/react-query').UseQueryResult<IGetConf, Error>;
@@ -30,7 +30,7 @@ const useDropzone = (props) => {
30
30
  type: file.type
31
31
  })
32
32
  ));
33
- props != null && props.forceFilters ? (filesToAdd = applyInputFiltersOn(filesToAdd), filesToAdd && filesToAdd.length && setFiles((prevFiles) => [...prevFiles, ...filesToAdd])) : setFiles((prevFiles) => [...prevFiles, ...files2]);
33
+ filesToAdd.reverse(), props != null && props.forceFilters ? (filesToAdd = applyInputFiltersOn(filesToAdd), filesToAdd && filesToAdd.length && setFiles((prevFiles) => [...prevFiles, ...filesToAdd])) : setFiles((prevFiles) => [...prevFiles, ...files2]);
34
34
  }, cleanFiles = () => {
35
35
  setFiles([]);
36
36
  }, handleOnChange = (event) => {
@@ -1,21 +1,13 @@
1
1
  import { useState, useEffect } from "react";
2
2
  import { odeServices } from "@edifice.io/client";
3
- import { useMockedData } from "../../providers/MockedDataProvider/MockedDataProvider.js";
4
3
  function useHasWorkflow(workflow) {
5
- const mock = useMockedData(), [state, setState] = useState();
4
+ const [state, setState] = useState();
6
5
  return useEffect(() => {
7
6
  (async () => {
8
7
  let response;
9
- if (mock != null && mock.hasWorkflow)
10
- if (typeof workflow == "string")
11
- response = await mock.hasWorkflow(workflow);
12
- else
13
- throw "not.implemented.yet)";
14
- else
15
- typeof workflow == "string" ? response = await odeServices.rights().sessionHasWorkflowRight(workflow) : response = await odeServices.rights().sessionHasWorkflowRights(workflow);
16
- setState(response);
8
+ typeof workflow == "string" ? response = await odeServices.rights().sessionHasWorkflowRight(workflow) : response = await odeServices.rights().sessionHasWorkflowRights(workflow), setState(response);
17
9
  })();
18
- }, [workflow, mock]), state;
10
+ }, [workflow]), state;
19
11
  }
20
12
  export {
21
13
  useHasWorkflow as default
@@ -1 +1,2 @@
1
- export default function useSession(): QueryObserverResult<TData, TError>;
1
+ import { IGetSession } from '@edifice.io/client';
2
+ export default function useSession(): import('../../../node_modules/@tanstack/react-query').UseQueryResult<IGetSession, Error>;
@@ -1 +1 @@
1
- export default function useTrapFocus(): import('react').MutableRefObject<HTMLElement | null>;
1
+ export default function useTrapFocus(isActive?: boolean): import('react').MutableRefObject<HTMLElement | null>;
@@ -1,7 +1,8 @@
1
1
  import { useRef, useEffect } from "react";
2
- function useTrapFocus() {
2
+ function useTrapFocus(isActive) {
3
3
  const ref = useRef(null), focusableElements = 'button:not([disabled]), [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
4
4
  return useEffect(() => {
5
+ if (!isActive) return;
5
6
  const node = ref.current, firstFocusableElement = node.querySelectorAll(focusableElements)[0], focusableContent = node.querySelectorAll(focusableElements), lastFocusableElement = ref && (focusableContent == null ? void 0 : focusableContent[focusableContent.length - 1]), handleKeydown = (event) => {
6
7
  event.key === "Tab" && (event.shiftKey ? document.activeElement === firstFocusableElement && (lastFocusableElement.focus(), event.preventDefault()) : document.activeElement === lastFocusableElement && (firstFocusableElement.focus(), event.preventDefault()));
7
8
  };
@@ -9,7 +10,7 @@ function useTrapFocus() {
9
10
  return node.addEventListener("keydown", handleKeydown), () => {
10
11
  node.removeEventListener("keydown", handleKeydown);
11
12
  };
12
- }, []), ref;
13
+ }, [isActive]), ref;
13
14
  }
14
15
  export {
15
16
  useTrapFocus as default
@@ -2,9 +2,8 @@ import { useReducer, useCallback } from "react";
2
2
  import { odeServices, DocumentHelper } from "@edifice.io/client";
3
3
  import { findNodeById } from "../../components/TreeView/utilities/treeview.js";
4
4
  import useHasWorkflow from "../useHasWorkflow/useHasWorkflow.js";
5
- import { useMockedData } from "../../providers/MockedDataProvider/MockedDataProvider.js";
6
5
  function useWorkspaceSearch(rootId, rootName, filter, format) {
7
- const mock = useMockedData(), canListDocs = useHasWorkflow("org.entcore.workspace.controllers.WorkspaceController|listDocuments"), canListFolders = useHasWorkflow("org.entcore.workspace.controllers.WorkspaceController|listFolders");
6
+ const canListDocs = useHasWorkflow("org.entcore.workspace.controllers.WorkspaceController|listDocuments"), canListFolders = useHasWorkflow("org.entcore.workspace.controllers.WorkspaceController|listFolders");
8
7
  function treeReducer(state, action) {
9
8
  switch (action.type) {
10
9
  case "update": {
@@ -25,15 +24,8 @@ function useWorkspaceSearch(rootId, rootName, filter, format) {
25
24
  name: rootName,
26
25
  section: !0
27
26
  }), loadContent = useCallback(async (folderId) => {
28
- var _a;
29
27
  if (canListDocs && canListFolders) {
30
- const realWorkspaceId = folderId === rootId ? "" : folderId, payload = mock != null && mock.listWorkspaceDocuments ? await ((_a = mock == null ? void 0 : mock.listWorkspaceDocuments) == null ? void 0 : _a.call(mock).then((results) => results.map((result) => {
31
- const ret = {
32
- ...result,
33
- _id: "" + Math.round(Math.random() * 9999)
34
- };
35
- return ret.name = result.eType == "folder" ? "folder id=" + ret._id : "file id=" + ret._id, ret;
36
- }))) : await odeServices.workspace().listDocuments(filter, realWorkspaceId), subfolders = [], files = [];
28
+ const realWorkspaceId = folderId === rootId ? "" : folderId, payload = await odeServices.workspace().listDocuments(filter, realWorkspaceId), subfolders = [], files = [];
37
29
  payload.filter((f) => {
38
30
  if (!format || f.eType === "folder") return !0;
39
31
  const role = DocumentHelper.getRole(f);
@@ -47,7 +39,7 @@ function useWorkspaceSearch(rootId, rootName, filter, format) {
47
39
  type: "update"
48
40
  });
49
41
  }
50
- }, [canListDocs, canListFolders, rootId, mock, filter, format]);
42
+ }, [canListDocs, canListFolders, rootId, filter, format]);
51
43
  return {
52
44
  root,
53
45
  loadContent
package/dist/index.js CHANGED
@@ -100,6 +100,7 @@ import { useEdificeClient } from "./providers/EdificeClientProvider/EdificeClien
100
100
  import { EdificeThemeProvider } from "./providers/EdificeThemeProvider/EdificeThemeProvider.js";
101
101
  import { EdificeThemeContext } from "./providers/EdificeThemeProvider/EdificeThemeProvider.context.js";
102
102
  import { useEdificeTheme } from "./providers/EdificeThemeProvider/EdificeThemeProvider.hook.js";
103
+ import { MockedProvider } from "./providers/MockedProvider/MockedProvider.js";
103
104
  import { checkUserRight } from "./utilities/check-user-rights/check-user-rights.js";
104
105
  import { emptyScreenMapping } from "./utilities/emptyscreen-mapping/emptyscreen-mapping.js";
105
106
  import { mergeRefs, setRef } from "./utilities/refs/ref.js";
@@ -145,6 +146,7 @@ export {
145
146
  default64 as LoadingScreen,
146
147
  default19 as Logo,
147
148
  Menu,
149
+ MockedProvider,
148
150
  default65 as Modal,
149
151
  default74 as OnboardingModal,
150
152
  Popover,
@@ -1,7 +1,20 @@
1
1
  import { ReactionSummaryData, ReactionType } from '@edifice.io/client';
2
+ /**
3
+ * Props for the ReactionChoice component.
4
+ */
2
5
  export interface ReactionChoiceProps {
6
+ /**
7
+ * An array of available reactions that can be chosen.
8
+ */
3
9
  availableReactions: ReactionType[];
10
+ /**
11
+ * Optional summary data of the reactions.
12
+ */
4
13
  summary?: ReactionSummaryData;
14
+ /**
15
+ * Optional callback function that is called when a reaction is chosen.
16
+ * @param chosenReaction - The reaction that was chosen.
17
+ */
5
18
  onChange?: (chosenReaction?: ReactionType) => void;
6
19
  }
7
20
  declare const ReactionChoice: {
@@ -1,19 +1,37 @@
1
1
  import { ReactionDetailsData } from '@edifice.io/client';
2
2
  import { ReactionModalCard } from './ReactionModal.Card';
3
+ /**
4
+ * Props for the ReactionModal component.
5
+ */
3
6
  export interface ReactionModalProps {
4
- /** Id of resource. */
7
+ /**
8
+ * The unique identifier for the resource.
9
+ */
5
10
  resourceId: string;
6
- /** Number of results per page, defaults to 30. */
11
+ /**
12
+ * The number of items to display per page. Optional.
13
+ */
7
14
  pageSize?: number;
8
- /** Display modal ? */
15
+ /**
16
+ * Indicates whether the modal is open.
17
+ */
9
18
  isOpen: boolean;
10
- /** Close button handler. */
19
+ /**
20
+ * Callback function to handle the modal close event.
21
+ */
11
22
  onModalClose(): void;
12
- /** Function for loading reactions to the resource. */
23
+ /**
24
+ * Function to load reaction details for a given resource.
25
+ *
26
+ * @param resourceId - The unique identifier for the resource.
27
+ * @param page - The current page number.
28
+ * @param size - The number of items to display per page.
29
+ * @returns A promise that resolves to the reaction details data or undefined.
30
+ */
13
31
  reactionDetailsLoader: (resourceId: string, page: number, size: number) => Promise<ReactionDetailsData | undefined>;
14
32
  }
15
33
  declare const ReactionModal: {
16
- ({ resourceId, pageSize, reactionDetailsLoader: loadReactionDetails, onModalClose, ...restProps }: ReactionModalProps): import('react').ReactPortal;
34
+ ({ resourceId, pageSize, reactionDetailsLoader: loadReactionDetails, onModalClose, ...restProps }: ReactionModalProps): import("react/jsx-runtime").JSX.Element;
17
35
  displayName: string;
18
36
  Card: typeof ReactionModalCard;
19
37
  };
@@ -1,4 +1,4 @@
1
- import { jsx, jsxs } from "react/jsx-runtime";
1
+ import { jsx, Fragment, jsxs } from "react/jsx-runtime";
2
2
  import { ReactionTypes } from "@edifice.io/client";
3
3
  import { StringUtils } from "@edifice.io/utilities";
4
4
  import { useState, useId, useCallback, useMemo, useEffect } from "react";
@@ -57,14 +57,17 @@ const ALL_TAB_ID = "all", ReactionModal = ({
57
57
  const handleTabChange = (tab) => {
58
58
  setCurrentTabId(tab.id);
59
59
  }, hasMore = reactions.length < counters.allReactionsCounter;
60
- return /* @__PURE__ */ createPortal(/* @__PURE__ */ jsxs(Modal, { id, ...restProps, onModalClose, size: "md", scrollable: !0, children: [
61
- /* @__PURE__ */ jsx(Modal.Header, { onModalClose, children: t("audience.reaction.modal.header") }),
62
- /* @__PURE__ */ jsx(Modal.Body, { children: /* @__PURE__ */ jsx(Tabs, { items: tabs, defaultId: ALL_TAB_ID, onChange: handleTabChange }) }),
63
- /* @__PURE__ */ jsxs(Modal.Footer, { children: [
64
- hasMore && /* @__PURE__ */ jsx(Button, { color: "tertiary", onClick: loadNextPage, children: t("audience.reaction.modal.more") }),
65
- /* @__PURE__ */ jsx(Button, { color: "primary", onClick: onModalClose, type: "button", variant: "filled", children: t("close") })
66
- ] })
67
- ] }), document.getElementById("portal"));
60
+ return (
61
+ // Using a fragment to ensure Storybook correctly interprets JSDoc comments: https://github.com/storybookjs/storybook/issues/27169
62
+ /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ createPortal(/* @__PURE__ */ jsxs(Modal, { id, ...restProps, onModalClose, size: "md", scrollable: !0, children: [
63
+ /* @__PURE__ */ jsx(Modal.Header, { onModalClose, children: t("audience.reaction.modal.header") }),
64
+ /* @__PURE__ */ jsx(Modal.Body, { children: /* @__PURE__ */ jsx(Tabs, { items: tabs, defaultId: ALL_TAB_ID, onChange: handleTabChange }) }),
65
+ /* @__PURE__ */ jsxs(Modal.Footer, { children: [
66
+ hasMore && /* @__PURE__ */ jsx(Button, { color: "tertiary", onClick: loadNextPage, children: t("audience.reaction.modal.more") }),
67
+ /* @__PURE__ */ jsx(Button, { color: "primary", onClick: onModalClose, type: "button", variant: "filled", children: t("close") })
68
+ ] })
69
+ ] }), document.getElementById("portal")) })
70
+ );
68
71
  };
69
72
  ReactionModal.Card = ReactionModalCard;
70
73
  export {
@@ -1,6 +1,15 @@
1
1
  import { ReactionSummaryData } from '@edifice.io/client';
2
+ /**
3
+ * Props for the ReactionSummary component.
4
+ */
2
5
  export interface ReactionSummaryProps {
6
+ /**
7
+ * An optional summary of reaction data.
8
+ */
3
9
  summary?: ReactionSummaryData;
10
+ /**
11
+ * An optional click handler function.
12
+ */
4
13
  onClick?: () => void;
5
14
  }
6
15
  declare const ReactionSummary: {
@@ -1,6 +1,16 @@
1
1
  export interface ViewsCounterProps {
2
+ /**
3
+ * The number of views to display.
4
+ *
5
+ */
2
6
  viewsCounter: number;
7
+ /**
8
+ * Optional click handler for the counter button.
9
+ */
3
10
  onClick?: (event?: React.MouseEvent<HTMLButtonElement>) => void;
11
+ /**
12
+ * Optional CSS class name to apply to the counter component.
13
+ */
4
14
  className?: string;
5
15
  }
6
16
  declare const ViewsCounter: {
@@ -1,11 +1,23 @@
1
1
  import { ViewsDetails } from '@edifice.io/client';
2
+ /**
3
+ * Props for the ViewsModal component.
4
+ */
2
5
  export interface ViewsModalProps {
6
+ /**
7
+ * Details of the views to be displayed in the modal.
8
+ */
3
9
  viewsDetails: ViewsDetails;
10
+ /**
11
+ * Boolean flag indicating whether the modal is open.
12
+ */
4
13
  isOpen: boolean;
14
+ /**
15
+ * Callback function to be called when the modal is closed.
16
+ */
5
17
  onModalClose: () => void;
6
18
  }
7
19
  declare const ViewsModal: {
8
- ({ viewsDetails, isOpen, onModalClose, }: ViewsModalProps): import('react').ReactPortal;
20
+ ({ viewsDetails, isOpen, onModalClose, }: ViewsModalProps): import("react/jsx-runtime").JSX.Element;
9
21
  displayName: string;
10
22
  };
11
23
  export default ViewsModal;
@@ -1,4 +1,4 @@
1
- import { jsxs, jsx, Fragment } from "react/jsx-runtime";
1
+ import { jsx, Fragment, jsxs } from "react/jsx-runtime";
2
2
  import { StringUtils } from "@edifice.io/utilities";
3
3
  import { createPortal } from "react-dom";
4
4
  import { useTranslation } from "react-i18next";
@@ -16,25 +16,28 @@ const ViewsModal = ({
16
16
  const {
17
17
  t
18
18
  } = useTranslation(), hasUniqueViews = viewsDetails.uniqueViewsCounter !== void 0;
19
- return /* @__PURE__ */ createPortal(/* @__PURE__ */ jsxs(Modal, { id: "ViewsModal", isOpen, onModalClose, children: [
20
- /* @__PURE__ */ jsx(Modal.Header, { onModalClose, children: t("audience.views.title") }),
21
- /* @__PURE__ */ jsxs(Modal.Body, { children: [
22
- /* @__PURE__ */ jsxs("div", { className: "views-detail-line p-8 mb-12", children: [
23
- /* @__PURE__ */ jsx("div", { className: "views-detail-icon rounded p-8", children: /* @__PURE__ */ jsx(SvgIconSee, {}) }),
24
- /* @__PURE__ */ jsx("div", { className: "h3", children: StringUtils.toCounter(viewsDetails.viewsCounter) }),
25
- /* @__PURE__ */ jsx("div", { children: t("audience.views.detail.viewsCounter") })
19
+ return (
20
+ // Using a fragment to ensure Storybook correctly interprets JSDoc comments: https://github.com/storybookjs/storybook/issues/27169
21
+ /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ createPortal(/* @__PURE__ */ jsxs(Modal, { id: "ViewsModal", isOpen, onModalClose, children: [
22
+ /* @__PURE__ */ jsx(Modal.Header, { onModalClose, children: t("audience.views.title") }),
23
+ /* @__PURE__ */ jsxs(Modal.Body, { children: [
24
+ /* @__PURE__ */ jsxs("div", { className: "views-detail-line p-8 mb-12", children: [
25
+ /* @__PURE__ */ jsx("div", { className: "views-detail-icon rounded p-8", children: /* @__PURE__ */ jsx(SvgIconSee, {}) }),
26
+ /* @__PURE__ */ jsx("div", { className: "h3", children: StringUtils.toCounter(viewsDetails.viewsCounter) }),
27
+ /* @__PURE__ */ jsx("div", { children: t("audience.views.detail.viewsCounter") })
28
+ ] }),
29
+ /* @__PURE__ */ jsxs("div", { className: "views-detail-line p-8 mb-12", children: [
30
+ /* @__PURE__ */ jsx("div", { className: "views-detail-icon rounded p-8", children: /* @__PURE__ */ jsx(SvgIconUsers, {}) }),
31
+ hasUniqueViews ? /* @__PURE__ */ jsxs(Fragment, { children: [
32
+ /* @__PURE__ */ jsx("div", { className: "h3", children: StringUtils.toCounter(viewsDetails.uniqueViewsCounter) }),
33
+ /* @__PURE__ */ jsx("div", { children: t("audience.views.detail.uniqueViewsCounter") })
34
+ ] }) : /* @__PURE__ */ jsx("div", { children: t("audience.views.detail.noUniqueViews") })
35
+ ] }),
36
+ hasUniqueViews ? (_a = viewsDetails.uniqueViewsPerProfile) == null ? void 0 : _a.map((viewsByProfile) => /* @__PURE__ */ jsx(ViewsByProfileCard, { viewsByProfile }, viewsByProfile.profile)) : null
26
37
  ] }),
27
- /* @__PURE__ */ jsxs("div", { className: "views-detail-line p-8 mb-12", children: [
28
- /* @__PURE__ */ jsx("div", { className: "views-detail-icon rounded p-8", children: /* @__PURE__ */ jsx(SvgIconUsers, {}) }),
29
- hasUniqueViews ? /* @__PURE__ */ jsxs(Fragment, { children: [
30
- /* @__PURE__ */ jsx("div", { className: "h3", children: StringUtils.toCounter(viewsDetails.uniqueViewsCounter) }),
31
- /* @__PURE__ */ jsx("div", { children: t("audience.views.detail.uniqueViewsCounter") })
32
- ] }) : /* @__PURE__ */ jsx("div", { children: t("audience.views.detail.noUniqueViews") })
33
- ] }),
34
- hasUniqueViews ? (_a = viewsDetails.uniqueViewsPerProfile) == null ? void 0 : _a.map((viewsByProfile) => /* @__PURE__ */ jsx(ViewsByProfileCard, { viewsByProfile }, viewsByProfile.profile)) : null
35
- ] }),
36
- /* @__PURE__ */ jsx(Modal.Footer, { children: /* @__PURE__ */ jsx(Button, { color: "primary", onClick: onModalClose, type: "button", variant: "filled", children: t("audience.views.cancel") }) })
37
- ] }), document.getElementById("portal"));
38
+ /* @__PURE__ */ jsx(Modal.Footer, { children: /* @__PURE__ */ jsx(Button, { color: "primary", onClick: onModalClose, type: "button", variant: "filled", children: t("audience.views.cancel") }) })
39
+ ] }), document.getElementById("portal")) })
40
+ );
38
41
  };
39
42
  export {
40
43
  ViewsModal as default
@@ -1,5 +1,5 @@
1
1
  import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
- import { useState } from "react";
2
+ import { useState, Suspense, lazy } from "react";
3
3
  import { useTranslation } from "react-i18next";
4
4
  import SvgIconSave from "../../icons/components/IconSave.js";
5
5
  import { useAutosizeTextarea } from "../hooks/useAutosizeTextarea.js";
@@ -10,7 +10,8 @@ import { CommentDate } from "./CommentDate.js";
10
10
  import { CommentTitle } from "./CommentTitle.js";
11
11
  import { TextCounter } from "./TextCounter.js";
12
12
  import Button from "../../../components/Button/Button.js";
13
- const Comment = ({
13
+ import LoadingScreen from "../../../components/LoadingScreen/LoadingScreen.js";
14
+ const DeleteModal = /* @__PURE__ */ lazy(() => import("./DeleteModal.js")), Comment = ({
14
15
  comment,
15
16
  userId,
16
17
  profile
@@ -22,12 +23,13 @@ const Comment = ({
22
23
  createdAt,
23
24
  updatedAt,
24
25
  comment: content
25
- } = comment, [ref, onFocus, resizeTextarea] = useAutosizeTextarea(!0), {
26
+ } = comment, [ref, onFocus, resizeTextarea] = useAutosizeTextarea(!0), [isDeleteModalOpen, setIsDeleteModalOpen] = useState(!1), {
26
27
  t
27
28
  } = useTranslation(), {
28
29
  editCommentId,
29
30
  options,
30
31
  type,
32
+ userRights,
31
33
  handleDeleteComment: onDeleteComment,
32
34
  handleModifyComment,
33
35
  handleReset,
@@ -57,14 +59,15 @@ const Comment = ({
57
59
  ] })
58
60
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
59
61
  /* @__PURE__ */ jsx("div", { className: "mt-8 mb-4", children: content }),
60
- userId === authorId && type === "edit" && /* @__PURE__ */ jsxs("div", { className: "ms-n8", children: [
61
- /* @__PURE__ */ jsx(Button, { variant: "ghost", color: "tertiary", size: "sm", onClick: () => {
62
+ type === "edit" && /* @__PURE__ */ jsxs("div", { className: "ms-n8", children: [
63
+ userId === authorId && /* @__PURE__ */ jsx(Button, { variant: "ghost", color: "tertiary", size: "sm", onClick: () => {
62
64
  handleModifyComment(comment.id), setValue(content);
63
65
  }, children: t("comment.edit") }),
64
- /* @__PURE__ */ jsx(Button, { variant: "ghost", color: "tertiary", size: "sm", onClick: () => onDeleteComment(id), children: t("comment.remove") })
66
+ (userId === authorId || (userRights == null ? void 0 : userRights.manager)) && /* @__PURE__ */ jsx(Button, { variant: "ghost", color: "tertiary", size: "sm", onClick: () => setIsDeleteModalOpen(!0), children: t("comment.remove") })
65
67
  ] })
66
68
  ] })
67
- ] })
69
+ ] }),
70
+ /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(LoadingScreen, { position: !1 }), children: isDeleteModalOpen && /* @__PURE__ */ jsx(DeleteModal, { isOpen: isDeleteModalOpen, onCancel: () => setIsDeleteModalOpen(!1), onSuccess: () => onDeleteComment(id) }) })
68
71
  ] }, id);
69
72
  };
70
73
  export {
@@ -0,0 +1,7 @@
1
+ interface DeleteModalProps {
2
+ isOpen: boolean;
3
+ onCancel: () => void;
4
+ onSuccess: () => void;
5
+ }
6
+ export declare const DeleteModal: ({ isOpen, onCancel, onSuccess, }: DeleteModalProps) => import("react/jsx-runtime").JSX.Element;
7
+ export default DeleteModal;
@@ -0,0 +1,19 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import Modal from "../../../components/Modal/Modal.js";
3
+ import Button from "../../../components/Button/Button.js";
4
+ const DeleteModal = ({
5
+ isOpen,
6
+ onCancel,
7
+ onSuccess
8
+ }) => /* @__PURE__ */ jsxs(Modal, { isOpen, onModalClose: onCancel, id: "delete-comment-modal", children: [
9
+ /* @__PURE__ */ jsx(Modal.Header, { onModalClose: onCancel, children: "Suppression de commentaire" }),
10
+ /* @__PURE__ */ jsx(Modal.Body, { children: /* @__PURE__ */ jsx("p", { children: "Voulez-vous vraiment supprimer ce commentaire ?" }) }),
11
+ /* @__PURE__ */ jsxs(Modal.Footer, { children: [
12
+ /* @__PURE__ */ jsx(Button, { color: "tertiary", onClick: onCancel, type: "button", variant: "ghost", children: "Annuler" }),
13
+ /* @__PURE__ */ jsx(Button, { color: "danger", onClick: onSuccess, type: "button", variant: "filled", children: "Supprimer le commentaire" })
14
+ ] })
15
+ ] });
16
+ export {
17
+ DeleteModal,
18
+ DeleteModal as default
19
+ };
@@ -1,3 +1,4 @@
1
+ import { RightRole } from '@edifice.io/client';
1
2
  import { CommentOptions, CommentProps, CommentType, UserProfileResult } from '../types';
2
3
  export declare const CommentContext: import('react').Context<{
3
4
  comments: CommentProps[] | undefined;
@@ -6,6 +7,7 @@ export declare const CommentContext: import('react').Context<{
6
7
  profiles: (UserProfileResult | undefined)[];
7
8
  options: Partial<CommentOptions>;
8
9
  type: CommentType;
10
+ userRights?: Record<RightRole, boolean>;
9
11
  setEditCommentId: (value: string | null) => void;
10
12
  handleModifyComment: (commentId: string) => void;
11
13
  handleChangeContent: (event: React.ChangeEvent<HTMLTextAreaElement>) => void;
@@ -6,7 +6,10 @@ export declare const useComments: ({ defaultComments, options, type, callbacks,
6
6
  callbacks: CommentCallbacks | null;
7
7
  }) => {
8
8
  profilesQueries: {
9
- data: any[];
9
+ data: ({
10
+ userId: string;
11
+ profile: "Student" | "Teacher" | "Relative" | "Personnel" | "Guest";
12
+ } | undefined)[];
10
13
  isLoading: boolean;
11
14
  };
12
15
  content: string;
@@ -24,6 +27,6 @@ export declare const useComments: ({ defaultComments, options, type, callbacks,
24
27
  handleDeleteComment: (id: string) => void;
25
28
  handleCreateComment: (content: string) => void;
26
29
  handleModifyComment: (commentId: string) => void;
27
- handleUpdateComment: (comment: string) => void;
30
+ handleUpdateComment: (comment: string) => Promise<void>;
28
31
  handleReset: () => void;
29
32
  };
@@ -50,7 +50,7 @@ const useComments = ({
50
50
  handleModifyComment: (commentId) => {
51
51
  setEditCommentId(commentId);
52
52
  },
53
- handleUpdateComment: (comment) => {
53
+ handleUpdateComment: async (comment) => {
54
54
  editCommentId && (type === "edit" && (callbacks == null || callbacks.put({
55
55
  comment,
56
56
  commentId: editCommentId
@@ -5,6 +5,7 @@ export declare const useCommentsContext: () => {
5
5
  profiles: (import('../types').UserProfileResult | undefined)[];
6
6
  options: Partial<import('../types').CommentOptions>;
7
7
  type: import('../types').CommentType;
8
+ userRights?: Record<import('@edifice.io/client').RightRole, boolean>;
8
9
  setEditCommentId: (value: string | null) => void;
9
10
  handleModifyComment: (commentId: string) => void;
10
11
  handleChangeContent: (event: React.ChangeEvent<HTMLTextAreaElement>) => void;
@@ -1,4 +1,7 @@
1
1
  export declare const useProfileQueries: (usersIds: string[]) => {
2
- data: any[];
2
+ data: ({
3
+ userId: string;
4
+ profile: "Student" | "Teacher" | "Relative" | "Personnel" | "Guest";
5
+ } | undefined)[];
3
6
  isLoading: boolean;
4
7
  };
@@ -46,7 +46,7 @@ const CommentProvider = ({
46
46
  defaultComments,
47
47
  callbacks: type == "edit" ? props.callbacks : null,
48
48
  options
49
- }), values = useMemo(
49
+ }), userRights = type === "edit" ? props.rights : void 0, values = useMemo(
50
50
  () => ({
51
51
  comments,
52
52
  content,
@@ -54,6 +54,7 @@ const CommentProvider = ({
54
54
  editCommentId,
55
55
  options,
56
56
  type,
57
+ userRights,
57
58
  setEditCommentId,
58
59
  handleCreateComment,
59
60
  handleModifyComment,
@@ -1,4 +1,4 @@
1
- import { UserProfile } from '@edifice.io/client';
1
+ import { RightRole, UserProfile } from '@edifice.io/client';
2
2
  export interface CommentProps {
3
3
  /**
4
4
  * Comment Id
@@ -61,6 +61,10 @@ interface EditRootProps extends BaseProps {
61
61
  * Callbacks to perform CRUD on comment
62
62
  */
63
63
  callbacks: CommentCallbacks;
64
+ /**
65
+ * Rights to perform CRUD on comment
66
+ */
67
+ rights?: Record<RightRole, boolean>;
64
68
  }
65
69
  interface ReadRootProps extends BaseProps {
66
70
  type: 'read';
@@ -1,5 +1,5 @@
1
1
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
- import { useState } from "react";
2
+ import { useState, useEffect } from "react";
3
3
  import { NodeViewWrapper } from "@tiptap/react";
4
4
  import { useTranslation } from "react-i18next";
5
5
  import SvgIconDelete from "../../../icons/components/IconDelete.js";
@@ -10,15 +10,20 @@ import { useEditorContext } from "../../hooks/useEditorContext.js";
10
10
  import { Grid } from "../../../../components/Grid/Grid.js";
11
11
  const AttachmentRenderer = (props) => {
12
12
  const {
13
+ node,
14
+ editor
15
+ } = props, [attachmentArrayAttrs, setAttachmentArrayAttrs] = useState(node.attrs.links), {
13
16
  t
14
17
  } = useTranslation(), {
15
- node
16
- } = props, {
17
18
  editable
18
- } = useEditorContext(), [attachmentArrayAttrs, setAttachmentArrayAttrs] = useState(node.attrs.links), handleDelete = (index) => {
19
- setAttachmentArrayAttrs((oldAttachments) => oldAttachments.filter((_, i) => i !== index));
19
+ } = useEditorContext();
20
+ useEffect(() => {
21
+ attachmentArrayAttrs !== node.attrs.links && setAttachmentArrayAttrs(node.attrs.links);
22
+ }, [node.attrs.links, attachmentArrayAttrs]);
23
+ const handleDelete = (index, documentId) => {
24
+ editor.commands.unsetAttachment(documentId), setAttachmentArrayAttrs((oldAttachments) => oldAttachments.filter((_, i) => i !== index));
20
25
  };
21
- return attachmentArrayAttrs.length !== 0 && /* @__PURE__ */ jsx(NodeViewWrapper, { children: /* @__PURE__ */ jsxs("div", { style: {
26
+ return (attachmentArrayAttrs == null ? void 0 : attachmentArrayAttrs.length) !== 0 && /* @__PURE__ */ jsx(NodeViewWrapper, { children: /* @__PURE__ */ jsxs("div", { style: {
22
27
  backgroundColor: "#F2F2F2",
23
28
  borderRadius: ".8rem",
24
29
  padding: "1.2rem"
@@ -26,7 +31,7 @@ const AttachmentRenderer = (props) => {
26
31
  /* @__PURE__ */ jsx("p", { className: "m-12 mt-0", children: t("tiptap.attachments.bloc") }),
27
32
  /* @__PURE__ */ jsx(Grid, { children: attachmentArrayAttrs == null ? void 0 : attachmentArrayAttrs.map((attachment, index) => /* @__PURE__ */ jsx(Grid.Col, { sm: "6", children: /* @__PURE__ */ jsx(Attachment, { name: attachment.name, options: /* @__PURE__ */ jsxs(Fragment, { children: [
28
33
  /* @__PURE__ */ jsx("a", { href: attachment.href, download: !0, children: /* @__PURE__ */ jsx(IconButton, { "aria-label": t("tiptap.attachments.download"), color: "tertiary", type: "button", icon: /* @__PURE__ */ jsx(SvgIconDownload, {}), variant: "ghost" }) }),
29
- editable && /* @__PURE__ */ jsx(IconButton, { "aria-label": t("tiptap.attachments.delete"), color: "danger", type: "button", icon: /* @__PURE__ */ jsx(SvgIconDelete, {}), variant: "ghost", onClick: () => handleDelete(index) })
34
+ editable && /* @__PURE__ */ jsx(IconButton, { "aria-label": t("tiptap.attachments.delete"), color: "danger", type: "button", icon: /* @__PURE__ */ jsx(SvgIconDelete, {}), variant: "ghost", onClick: () => handleDelete(index, attachment.documentId) })
30
35
  ] }) }) }, index)) })
31
36
  ] }) });
32
37
  };
@@ -4,7 +4,10 @@ const AudioRenderer = (props) => {
4
4
  const {
5
5
  node
6
6
  } = props;
7
- return /* @__PURE__ */ jsx(NodeViewWrapper, { children: /* @__PURE__ */ jsx("div", { className: "audio-wrapper", children: /* @__PURE__ */ jsx("audio", { src: node.attrs.src, controls: !0, "data-document-id": node.attrs.src, children: /* @__PURE__ */ jsx("track", { kind: "captions" }) }) }) });
7
+ return /* @__PURE__ */ jsx(NodeViewWrapper, { style: {
8
+ display: "inline-block",
9
+ width: "fit-content"
10
+ }, children: /* @__PURE__ */ jsx("div", { className: "audio-wrapper", "data-drag-handle": !0, children: /* @__PURE__ */ jsx("audio", { src: node.attrs.src, controls: !0, "data-document-id": node.attrs.src, children: /* @__PURE__ */ jsx("track", { kind: "captions" }) }) }) });
8
11
  };
9
12
  export {
10
13
  AudioRenderer as default
@@ -6,7 +6,7 @@ import { Content, HTMLContent } from '@tiptap/react';
6
6
  * @param content default rich content
7
7
  */
8
8
  export declare const useCommentEditor: (editable: boolean, content: Content, maxLength?: number) => {
9
- editor: import('@tiptap/react').Editor | null;
9
+ editor: import('@tiptap/core').Editor | null;
10
10
  commentLength: number;
11
11
  getComment: () => HTMLContent;
12
12
  resetComment: () => void;
@@ -11,6 +11,6 @@ import { WorkspaceVisibility } from '@edifice.io/client';
11
11
  export declare const useTipTapEditor: (editable: boolean, content: Content, focus?: FocusPosition, placeholder?: string, onContentChange?: ({ editor }: {
12
12
  editor: any;
13
13
  }) => void, visibility?: WorkspaceVisibility) => {
14
- editor: import('@tiptap/react').Editor | null;
14
+ editor: import('@tiptap/core').Editor | null;
15
15
  editable: boolean;
16
16
  };
@@ -58,7 +58,7 @@ const useTipTapEditor = (editable, content, focus, placeholder, onContentChange,
58
58
  }), Underline, TextStyle, Color, Subscript, Superscript, Table.configure({
59
59
  resizable: !0
60
60
  }), TableRow, TableHeader, TableCell, TextAlign.configure({
61
- types: ["heading", "paragraph", "custom-image", "video"]
61
+ types: ["heading", "paragraph", "video"]
62
62
  }), CustomHeading.configure({
63
63
  levels: [1, 2]
64
64
  }), Typography, FontSize, SpeechRecognition, SpeechSynthesis.configure({
@@ -0,0 +1,4 @@
1
+ import { ReactNode } from 'react';
2
+ export declare const MockedProvider: ({ children }: {
3
+ children: ReactNode;
4
+ }) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,20 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
3
+ import { EdificeClientProvider } from "../EdificeClientProvider/EdificeClientProvider.js";
4
+ import { EdificeThemeContext } from "../EdificeThemeProvider/EdificeThemeProvider.context.js";
5
+ const queryClient = new QueryClient(), Providers = ({
6
+ children
7
+ }) => /* @__PURE__ */ jsx(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx(EdificeClientProvider, { params: {
8
+ app: "wiki"
9
+ }, children }) }), MockedProvider = ({
10
+ children
11
+ }) => {
12
+ const themeContextValue = {
13
+ theme: "default",
14
+ setTheme: vi.fn()
15
+ };
16
+ return /* @__PURE__ */ jsx(Providers, { children: /* @__PURE__ */ jsx(EdificeThemeContext.Provider, { value: themeContextValue, children }) });
17
+ };
18
+ export {
19
+ MockedProvider
20
+ };
@@ -4,3 +4,4 @@ export * from './EdificeClientProvider/EdificeClientProvider.hook';
4
4
  export * from './EdificeThemeProvider/EdificeThemeProvider';
5
5
  export * from './EdificeThemeProvider/EdificeThemeProvider.context';
6
6
  export * from './EdificeThemeProvider/EdificeThemeProvider.hook';
7
+ export * from './MockedProvider/MockedProvider';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edifice.io/react",
3
- "version": "2.0.3",
3
+ "version": "2.0.5-develop-pedago.20250123145105",
4
4
  "description": "Edifice React Library",
5
5
  "keywords": [
6
6
  "react",
@@ -80,35 +80,34 @@
80
80
  "@pixi/mixin-get-child-by-name": "7.4.2",
81
81
  "@pixi/react": "7.1.2",
82
82
  "@popperjs/core": "2.11.8",
83
- "@tiptap/core": "2.3.0",
84
- "@tiptap/extension-character-count": "2.3.0",
85
- "@tiptap/extension-color": "2.3.0",
86
- "@tiptap/extension-focus": "2.3.0",
87
- "@tiptap/extension-font-family": "2.3.0",
88
- "@tiptap/extension-heading": "2.3.0",
89
- "@tiptap/extension-highlight": "2.3.0",
90
- "@tiptap/extension-image": "2.3.0",
91
- "@tiptap/extension-link": "2.3.0",
92
- "@tiptap/extension-list-item": "2.3.0",
93
- "@tiptap/extension-placeholder": "2.3.0",
94
- "@tiptap/extension-subscript": "2.3.0",
95
- "@tiptap/extension-superscript": "2.3.0",
96
- "@tiptap/extension-table": "2.3.0",
97
- "@tiptap/extension-table-cell": "2.3.0",
98
- "@tiptap/extension-table-header": "2.3.0",
99
- "@tiptap/extension-table-row": "2.3.0",
100
- "@tiptap/extension-text-align": "2.3.0",
101
- "@tiptap/extension-text-style": "2.3.0",
102
- "@tiptap/extension-typography": "2.3.0",
103
- "@tiptap/extension-underline": "2.3.0",
104
- "@tiptap/pm": "2.3.0",
105
- "@tiptap/react": "2.3.0",
106
- "@tiptap/starter-kit": "2.3.0",
83
+ "@tiptap/core": "2.11.0",
84
+ "@tiptap/extension-character-count": "2.11.0",
85
+ "@tiptap/extension-color": "2.11.0",
86
+ "@tiptap/extension-focus": "2.11.0",
87
+ "@tiptap/extension-font-family": "2.11.0",
88
+ "@tiptap/extension-heading": "2.11.0",
89
+ "@tiptap/extension-highlight": "2.11.0",
90
+ "@tiptap/extension-image": "2.11.0",
91
+ "@tiptap/extension-link": "2.11.0",
92
+ "@tiptap/extension-list-item": "2.11.0",
93
+ "@tiptap/extension-placeholder": "2.11.0",
94
+ "@tiptap/extension-subscript": "2.11.0",
95
+ "@tiptap/extension-superscript": "2.11.0",
96
+ "@tiptap/extension-table": "2.11.0",
97
+ "@tiptap/extension-table-cell": "2.11.0",
98
+ "@tiptap/extension-table-header": "2.11.0",
99
+ "@tiptap/extension-table-row": "2.11.0",
100
+ "@tiptap/extension-text-align": "2.11.0",
101
+ "@tiptap/extension-text-style": "2.11.0",
102
+ "@tiptap/extension-typography": "2.11.0",
103
+ "@tiptap/extension-underline": "2.11.0",
104
+ "@tiptap/pm": "2.11.0",
105
+ "@tiptap/react": "2.11.0",
106
+ "@tiptap/starter-kit": "2.11.0",
107
107
  "@uidotdev/usehooks": "^2.4.1",
108
108
  "clsx": "^2.1.1",
109
109
  "dayjs": "1.11.10",
110
110
  "emoji-picker-react": "4.5.2",
111
- "globals": "^15.11.0",
112
111
  "html-react-parser": "4.2.1",
113
112
  "ohash": "1.1.3",
114
113
  "pako": "2.1.0",
@@ -119,15 +118,16 @@
119
118
  "react-slugify": "^3.0.3",
120
119
  "swiper": "^10.1.0",
121
120
  "ua-parser-js": "^1.0.36",
122
- "@edifice.io/tiptap-extensions": "2.0.3",
123
- "@edifice.io/bootstrap": "2.0.3",
124
- "@edifice.io/utilities": "2.0.3"
121
+ "@edifice.io/bootstrap": "2.0.5-develop-pedago.20250123145105",
122
+ "@edifice.io/tiptap-extensions": "2.0.5-develop-pedago.20250123145105",
123
+ "@edifice.io/utilities": "2.0.5-develop-pedago.20250123145105"
125
124
  },
126
125
  "devDependencies": {
127
126
  "@babel/plugin-transform-react-pure-annotations": "^7.23.3",
128
127
  "@eslint/js": "^9.12.0",
129
128
  "@react-spring/web": "^9.7.5",
130
129
  "@svgr/cli": "^8.1.0",
130
+ "@tanstack/query-core": "5.62.7",
131
131
  "@tanstack/react-query": "5.62.7",
132
132
  "@types/node": "^22.9.1",
133
133
  "@types/pako": "^2.0.3",
@@ -147,7 +147,9 @@
147
147
  "typescript-eslint": "^8.8.1",
148
148
  "vite": "^5.4.11",
149
149
  "vite-plugin-dts": "^4.1.0",
150
- "@edifice.io/client": "2.0.3"
150
+ "vite-tsconfig-paths": "^5.0.1",
151
+ "@edifice.io/client": "2.0.5-develop-pedago.20250123145105",
152
+ "@edifice.io/config": "2.0.5-develop-pedago.20250123145105"
151
153
  },
152
154
  "peerDependencies": {
153
155
  "@react-spring/web": "^9.7.5",
@@ -167,11 +169,12 @@
167
169
  "scripts": {
168
170
  "build": "pnpm build:icons && vite build",
169
171
  "build:icons": "svgr src/modules/icons/assets --config-file ./svgr.config.cjs",
170
- "fix": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
172
+ "fix": "eslint --fix --report-unused-disable-directives --max-warnings 0",
171
173
  "format": "pnpm run format:write && pnpm run format:check",
172
- "format:check": "npx prettier --check .",
173
- "format:write": "npx prettier --write .",
174
- "lint": "eslint .",
175
- "test": "vitest"
174
+ "format:check": "npx prettier --check \"src/**/*.{ts,tsx}\"",
175
+ "format:write": "npx prettier --write \"src/**/*.{ts,tsx}\"",
176
+ "lint": "eslint",
177
+ "test": "vitest",
178
+ "test:watch": "vitest --watch"
176
179
  }
177
180
  }
@@ -1,28 +0,0 @@
1
- import { ReactNode } from 'react';
2
- import { App, GetContextParameters, IResource, ResourceType, WorkspaceElement } from '@edifice.io/client';
3
- export interface MockedDataProps {
4
- children: ReactNode;
5
- mocks: {
6
- /** Current app code */
7
- app?: App;
8
- /** User's granted workflow rights */
9
- workflows?: string[];
10
- /** List of pseudo-documents from workspace. */
11
- workspaceDocuments?: WorkspaceElement[];
12
- /** List of available apps. */
13
- availableApps?: App[];
14
- /** List of pseudo-IResource by type. */
15
- appResources?: {
16
- [resourceType: ResourceType]: IResource[];
17
- };
18
- };
19
- }
20
- export interface MockedContextProps {
21
- app?: App;
22
- availableApps?: Promise<App[]>;
23
- hasWorkflow?: (workflow: string) => Promise<boolean>;
24
- listWorkspaceDocuments?: () => Promise<WorkspaceElement[]>;
25
- loadResources?: (filters: GetContextParameters) => Promise<IResource[]>;
26
- }
27
- export declare function MockedDataProvider({ children, mocks }: MockedDataProps): import("react/jsx-runtime").JSX.Element;
28
- export declare function useMockedData(): MockedContextProps | null;
@@ -1,9 +0,0 @@
1
- import "react/jsx-runtime";
2
- import { useContext, createContext } from "react";
3
- const MockedDataContext = /* @__PURE__ */ createContext(null);
4
- function useMockedData() {
5
- return useContext(MockedDataContext);
6
- }
7
- export {
8
- useMockedData
9
- };
@@ -1 +0,0 @@
1
- export * from './MockedDataProvider';