@edifice.io/react 2.0.0 → 2.0.1-develop-hotfix.1736763055653

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.
@@ -32,7 +32,7 @@ const AppIcon = /* @__PURE__ */ forwardRef(({
32
32
  ...iconSizes,
33
33
  ...iconVariant,
34
34
  ...iconFits,
35
- [`bg-light-${appCode}`]: !isContain,
35
+ [`bg-light-${appCode}`]: appCode && !isContain,
36
36
  [`color-app-${appCode}`]: appCode
37
37
  }, className), IconComponent = iconsApps[`Icon${appCode.split("-").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("")}`] ?? SvgIconPlaceholder;
38
38
  if (isIconURL) {
@@ -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);
@@ -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
@@ -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;
@@ -24,6 +24,6 @@ export declare const useComments: ({ defaultComments, options, type, callbacks,
24
24
  handleDeleteComment: (id: string) => void;
25
25
  handleCreateComment: (content: string) => void;
26
26
  handleModifyComment: (commentId: string) => void;
27
- handleUpdateComment: (comment: string) => void;
27
+ handleUpdateComment: (comment: string) => Promise<void>;
28
28
  handleReset: () => void;
29
29
  };
@@ -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;
@@ -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';
@@ -12,11 +12,12 @@ const AttachmentRenderer = (props) => {
12
12
  const {
13
13
  t
14
14
  } = useTranslation(), {
15
- node
15
+ node,
16
+ editor
16
17
  } = props, {
17
18
  editable
18
- } = useEditorContext(), [attachmentArrayAttrs, setAttachmentArrayAttrs] = useState(node.attrs.links), handleDelete = (index) => {
19
- setAttachmentArrayAttrs((oldAttachments) => oldAttachments.filter((_, i) => i !== index));
19
+ } = useEditorContext(), [attachmentArrayAttrs, setAttachmentArrayAttrs] = useState(node.attrs.links), handleDelete = (index, documentId) => {
20
+ editor.commands.unsetAttachment(documentId), setAttachmentArrayAttrs((oldAttachments) => oldAttachments.filter((_, i) => i !== index));
20
21
  };
21
22
  return attachmentArrayAttrs.length !== 0 && /* @__PURE__ */ jsx(NodeViewWrapper, { children: /* @__PURE__ */ jsxs("div", { style: {
22
23
  backgroundColor: "#F2F2F2",
@@ -26,7 +27,7 @@ const AttachmentRenderer = (props) => {
26
27
  /* @__PURE__ */ jsx("p", { className: "m-12 mt-0", children: t("tiptap.attachments.bloc") }),
27
28
  /* @__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
29
  /* @__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) })
30
+ 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
31
  ] }) }) }, index)) })
31
32
  ] }) });
32
33
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edifice.io/react",
3
- "version": "2.0.0",
3
+ "version": "2.0.1-develop-hotfix.1736763055653",
4
4
  "description": "Edifice React Library",
5
5
  "keywords": [
6
6
  "react",
@@ -105,7 +105,7 @@
105
105
  "@tiptap/react": "2.3.0",
106
106
  "@tiptap/starter-kit": "2.3.0",
107
107
  "@uidotdev/usehooks": "^2.4.1",
108
- "clsx": "^2.1.1",
108
+ "clsx": "catalog:",
109
109
  "dayjs": "1.11.10",
110
110
  "emoji-picker-react": "4.5.2",
111
111
  "globals": "^15.11.0",
@@ -119,43 +119,43 @@
119
119
  "react-slugify": "^3.0.3",
120
120
  "swiper": "^10.1.0",
121
121
  "ua-parser-js": "^1.0.36",
122
- "@edifice.io/bootstrap": "2.0.0",
123
- "@edifice.io/tiptap-extensions": "2.0.0",
124
- "@edifice.io/utilities": "2.0.0"
122
+ "@edifice.io/bootstrap": "2.0.1-develop-hotfix.1736763055653",
123
+ "@edifice.io/utilities": "2.0.0",
124
+ "@edifice.io/tiptap-extensions": "2.0.1-develop-hotfix.1736763055653"
125
125
  },
126
126
  "devDependencies": {
127
127
  "@babel/plugin-transform-react-pure-annotations": "^7.23.3",
128
128
  "@eslint/js": "^9.12.0",
129
129
  "@react-spring/web": "^9.7.5",
130
130
  "@svgr/cli": "^8.1.0",
131
- "@tanstack/react-query": "5.62.7",
132
- "@types/node": "^22.9.1",
131
+ "@tanstack/react-query": "catalog:",
132
+ "@types/node": "catalog:",
133
133
  "@types/pako": "^2.0.3",
134
- "@types/react": "^18.2.33",
135
- "@types/react-dom": "^18.2.14",
134
+ "@types/react": "catalog:",
135
+ "@types/react-dom": "catalog:",
136
136
  "@types/ua-parser-js": "^0.7.37",
137
- "@vitejs/plugin-react": "^4.3.2",
137
+ "@vitejs/plugin-react": "catalog:",
138
138
  "eslint": "^9.12.0",
139
139
  "eslint-plugin-react-hooks": "5.1.0-rc.0",
140
140
  "eslint-plugin-react-refresh": "^0.4.12",
141
- "react": "^18.3.1",
142
- "react-dom": "^18.3.1",
143
- "react-hook-form": "^7.53.0",
144
- "react-i18next": "^14.1.0",
141
+ "react": "catalog:",
142
+ "react-dom": "catalog:",
143
+ "react-hook-form": "catalog:",
144
+ "react-i18next": "catalog:",
145
145
  "rollup-plugin-pure": "^0.2.1",
146
- "rollup-plugin-visualizer": "5.12.0",
146
+ "rollup-plugin-visualizer": "catalog:",
147
147
  "typescript-eslint": "^8.8.1",
148
- "vite": "^5.4.11",
149
- "vite-plugin-dts": "^4.1.0",
150
- "@edifice.io/client": "2.0.0"
148
+ "vite": "catalog:",
149
+ "vite-plugin-dts": "catalog:",
150
+ "@edifice.io/client": "2.0.1-develop-hotfix.1736763055653"
151
151
  },
152
152
  "peerDependencies": {
153
- "@react-spring/web": "^9.7.5",
154
- "@tanstack/react-query": "5.62.7",
155
- "react": "^18.3.1",
156
- "react-dom": "^18.3.1",
157
- "react-hook-form": "^7.53.0",
158
- "react-i18next": "^14.1.0"
153
+ "@react-spring/web": "catalog:",
154
+ "@tanstack/react-query": "catalog:",
155
+ "react": "catalog:",
156
+ "react-dom": "catalog:",
157
+ "react-hook-form": "catalog:",
158
+ "react-i18next": "catalog:"
159
159
  },
160
160
  "optionalDependencies": {
161
161
  "@tiptap-pro/extension-mathematics": "2.2.1"