@edifice.io/react 2.5.12-develop-pedago.20260227152929 → 2.5.13

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.
@@ -1,11 +1,8 @@
1
1
  import { Attachment } from './models/attachment';
2
- export type SingleAttachmentType = Attachment;
3
- export { useFileToAttachment } from './hooks/useFileToAttachment';
4
2
  export interface AddAttachmentsProps {
5
3
  attachments: Attachment[];
6
- onChange?: (attachments: Attachment[]) => void;
7
- onFilesSelected?: (files: File[]) => void;
8
- onRemoveAttachment?: (attachmentId: string) => void;
4
+ onFilesSelected: (files: File[]) => void;
5
+ onRemoveAttachment: (attachmentId: string) => void;
9
6
  editMode?: boolean;
10
7
  isMutating?: boolean;
11
8
  onCopyToWorkspace?: (attachments: Attachment[], folderId: string) => Promise<boolean>;
@@ -15,7 +12,7 @@ export interface AddAttachmentsProps {
15
12
  downloadAllUrl?: string;
16
13
  }
17
14
  export declare const AddAttachments: {
18
- ({ attachments, onChange, onFilesSelected, onRemoveAttachment, editMode, isMutating, onCopyToWorkspace, getDownloadUrl, downloadAllUrl, }: AddAttachmentsProps): import("react/jsx-runtime").JSX.Element | null;
15
+ ({ attachments, onFilesSelected, onRemoveAttachment, editMode, isMutating, onCopyToWorkspace, getDownloadUrl, downloadAllUrl, }: AddAttachmentsProps): import("react/jsx-runtime").JSX.Element | null;
19
16
  displayName: string;
20
17
  };
21
18
  export default AddAttachments;
@@ -1,6 +1,6 @@
1
1
  import { jsxs, Fragment, jsx } from "react/jsx-runtime";
2
2
  import clsx from "clsx";
3
- import { useRef, useState } from "react";
3
+ import { useRef, useState, useEffect } from "react";
4
4
  import { useTranslation } from "react-i18next";
5
5
  import SvgIconDelete from "../../modules/icons/components/IconDelete.js";
6
6
  import SvgIconDownload from "../../modules/icons/components/IconDownload.js";
@@ -8,13 +8,22 @@ import SvgIconFolderAdd from "../../modules/icons/components/IconFolderAdd.js";
8
8
  import SvgIconPlus from "../../modules/icons/components/IconPlus.js";
9
9
  import { AddAttachmentToWorkspaceModal } from "./components/AddAttachmentToWorkspaceModal.js";
10
10
  import { SingleAttachment } from "./components/SingleAttachment.js";
11
- import { useFileToAttachment } from "./hooks/useFileToAttachment.js";
12
11
  import Flex from "../Flex/Flex.js";
13
12
  import IconButton from "../Button/IconButton.js";
14
13
  import Button from "../Button/Button.js";
14
+ function fileToAttachment(file) {
15
+ return {
16
+ id: `${file.name}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
17
+ charset: "UTF-8",
18
+ contentTransferEncoding: "binary",
19
+ contentType: file.type || "application/octet-stream",
20
+ filename: file.name,
21
+ name: file.name,
22
+ size: file.size
23
+ };
24
+ }
15
25
  const AddAttachments = ({
16
26
  attachments,
17
- onChange,
18
27
  onFilesSelected,
19
28
  onRemoveAttachment,
20
29
  editMode = !1,
@@ -25,8 +34,10 @@ const AddAttachments = ({
25
34
  }) => {
26
35
  const {
27
36
  t
28
- } = useTranslation(), inputRef = useRef(null), fileToAttachment = useFileToAttachment(), [attachmentsToAddToWorkspace, setAttachmentsToAddToWorkspace] = useState(void 0);
29
- if (!editMode && !attachments.length) return null;
37
+ } = useTranslation(), inputRef = useRef(null), [optimisticAttachments, setOptimisticAttachments] = useState([]), [attachmentsToAddToWorkspace, setAttachmentsToAddToWorkspace] = useState(void 0), prevAttachmentsLengthRef = useRef(attachments.length), displayedAttachments = [...attachments, ...optimisticAttachments];
38
+ if (useEffect(() => {
39
+ attachments.length > prevAttachmentsLengthRef.current && setOptimisticAttachments([]), prevAttachmentsLengthRef.current = attachments.length;
40
+ }, [attachments.length]), !editMode && !displayedAttachments.length) return null;
30
41
  const resetInputValue = () => {
31
42
  inputRef.current && (inputRef.current.value = "");
32
43
  }, handleAttachClick = () => {
@@ -35,34 +46,36 @@ const AddAttachments = ({
35
46
  }, handleFileChange = (event) => {
36
47
  const files = Array.from(event.target.files ?? []);
37
48
  if (files.length > 0) {
38
- const newAttachments = files.map(fileToAttachment);
39
- onChange == null || onChange([...attachments, ...newAttachments]), onFilesSelected == null || onFilesSelected(files);
49
+ onFilesSelected(files);
50
+ const newOptimistic = files.map(fileToAttachment);
51
+ setOptimisticAttachments((prev) => [...prev, ...newOptimistic]);
40
52
  }
41
53
  resetInputValue();
42
54
  }, handleDetachAllClick = () => {
43
- onChange == null || onChange([]), attachments.forEach((a) => onRemoveAttachment == null ? void 0 : onRemoveAttachment(a.id)), resetInputValue();
55
+ setOptimisticAttachments([]), attachments.forEach((attachment) => {
56
+ onRemoveAttachment(attachment.id);
57
+ }), resetInputValue();
44
58
  }, handleDetachClick = (attachmentId) => {
45
- const next = attachments.filter((a) => a.id !== attachmentId);
46
- onChange == null || onChange(next), onRemoveAttachment == null || onRemoveAttachment(attachmentId), resetInputValue();
59
+ optimisticAttachments.some((attachment) => attachment.id === attachmentId) ? setOptimisticAttachments((prev) => prev.filter((attachment) => attachment.id !== attachmentId)) : onRemoveAttachment(attachmentId), resetInputValue();
47
60
  }, handleCopyToWorkspace = (attachments2) => {
48
61
  setAttachmentsToAddToWorkspace(attachments2);
49
62
  }, className = clsx("bg-gray-200 rounded px-12 py-8 message-attachments align-self-start gap-8 d-flex flex-column mw-100", {
50
63
  "border add-attachments-edit mx-16": editMode
51
64
  });
52
65
  return /* @__PURE__ */ jsxs("div", { className, "data-drag-handle": !0, children: [
53
- !!attachments.length && /* @__PURE__ */ jsxs(Fragment, { children: [
66
+ !!displayedAttachments.length && /* @__PURE__ */ jsxs(Fragment, { children: [
54
67
  /* @__PURE__ */ jsxs(Flex, { direction: "row", align: "center", justify: "between", className: "border-bottom", children: [
55
68
  /* @__PURE__ */ jsx("span", { className: "caption fw-bold my-8", children: t("attachments") }),
56
- attachments.length > 1 && /* @__PURE__ */ jsxs("div", { children: [
57
- onCopyToWorkspace && /* @__PURE__ */ jsx(IconButton, { title: t("conversation.copy.all.toworkspace"), color: "tertiary", type: "button", icon: /* @__PURE__ */ jsx(SvgIconFolderAdd, {}), onClick: () => handleCopyToWorkspace(attachments), variant: "ghost" }),
69
+ displayedAttachments.length > 1 && /* @__PURE__ */ jsxs("div", { children: [
70
+ onCopyToWorkspace && /* @__PURE__ */ jsx(IconButton, { title: t("conversation.copy.all.toworkspace"), color: "tertiary", type: "button", icon: /* @__PURE__ */ jsx(SvgIconFolderAdd, {}), onClick: () => handleCopyToWorkspace(displayedAttachments), variant: "ghost" }),
58
71
  downloadAllUrl && /* @__PURE__ */ jsx("a", { href: downloadAllUrl, download: !0, children: /* @__PURE__ */ jsx(IconButton, { title: t("download.all.attachment"), color: "tertiary", type: "button", icon: /* @__PURE__ */ jsx(SvgIconDownload, {}), variant: "ghost" }) }),
59
72
  editMode && /* @__PURE__ */ jsx(IconButton, { title: t("remove.all.attachment"), color: "danger", type: "button", icon: /* @__PURE__ */ jsx(SvgIconDelete, {}), variant: "ghost", onClick: handleDetachAllClick, disabled: isMutating })
60
73
  ] })
61
74
  ] }),
62
- /* @__PURE__ */ jsx("ul", { className: "d-flex gap-8 flex-column list-unstyled m-0", children: attachments.map((attachment) => /* @__PURE__ */ jsx("li", { className: "mw-100", children: /* @__PURE__ */ jsx(SingleAttachment, { attachment, editMode, onDelete: handleDetachClick, onCopyToWorkspace: onCopyToWorkspace ? (attachment2) => handleCopyToWorkspace([attachment2]) : void 0, getDownloadUrl, disabled: isMutating }) }, `${attachment.id}-${attachment.name}`)) })
75
+ /* @__PURE__ */ jsx("ul", { className: "d-flex gap-8 flex-column list-unstyled m-0", children: displayedAttachments.map((attachment) => /* @__PURE__ */ jsx("li", { className: "mw-100", children: /* @__PURE__ */ jsx(SingleAttachment, { attachment, editMode, onDelete: handleDetachClick, onCopyToWorkspace: onCopyToWorkspace ? (attachment2) => handleCopyToWorkspace([attachment2]) : void 0, getDownloadUrl, disabled: isMutating }) }, attachment.id)) })
63
76
  ] }),
64
77
  editMode && /* @__PURE__ */ jsxs(Fragment, { children: [
65
- /* @__PURE__ */ jsx(Button, { color: "secondary", variant: "ghost", isLoading: isMutating, onClick: handleAttachClick, disabled: isMutating, className: "align-self-start", leftIcon: /* @__PURE__ */ jsx(SvgIconPlus, {}), "data-testid": "common-add-attachments-button-add-attachment", children: t("add.attachment") }),
78
+ /* @__PURE__ */ jsx(Button, { color: "secondary", variant: "ghost", isLoading: isMutating, onClick: handleAttachClick, disabled: isMutating, className: "align-self-start", leftIcon: /* @__PURE__ */ jsx(SvgIconPlus, {}), children: t("add.attachment") }),
66
79
  /* @__PURE__ */ jsx("input", { ref: inputRef, multiple: !0, type: "file", name: "attachment-input", id: "attachment-input", onChange: handleFileChange, hidden: !0 })
67
80
  ] }),
68
81
  onCopyToWorkspace && !!attachmentsToAddToWorkspace && /* @__PURE__ */ jsx(AddAttachmentToWorkspaceModal, { isOpen: !0, onModalClose: () => setAttachmentsToAddToWorkspace(void 0), attachments: attachmentsToAddToWorkspace, onCopyToWorkspace })
@@ -70,6 +83,5 @@ const AddAttachments = ({
70
83
  };
71
84
  export {
72
85
  AddAttachments,
73
- AddAttachments as default,
74
- useFileToAttachment
86
+ AddAttachments as default
75
87
  };
@@ -6,5 +6,4 @@ export type Attachment = {
6
6
  filename: string;
7
7
  name: string;
8
8
  size: number;
9
- file: File;
10
9
  };
@@ -1,7 +1,8 @@
1
+ import { default as UAParser } from 'ua-parser-js';
1
2
  export default function useBrowserInfo(userAgent?: string): {
2
- os: import('ua-parser-js').IOS;
3
- device: import('ua-parser-js').IDevice;
4
- browser: import('ua-parser-js').IBrowser;
3
+ os: UAParser.IOS;
4
+ device: UAParser.IDevice;
5
+ browser: UAParser.IBrowser;
5
6
  isIphone: boolean;
6
7
  isIpod: boolean;
7
8
  isIpad: boolean;
@@ -1,4 +1,4 @@
1
- import { UAParser } from "ua-parser-js";
1
+ import UAParser from "ua-parser-js";
2
2
  function useBrowserInfo(userAgent) {
3
3
  var _a, _b, _c;
4
4
  const uaParser = new UAParser(userAgent), os = uaParser.getOS(), device = uaParser.getDevice(), browser = uaParser.getBrowser(), isIphone = ((_a = device.model) == null ? void 0 : _a.indexOf("iPhone")) != -1, isIpod = ((_b = device.model) == null ? void 0 : _b.indexOf("iPod")) != -1, isIpad = ((_c = device.model) == null ? void 0 : _c.indexOf("iPad")) != -1;
@@ -35,11 +35,11 @@ const useDropzone = (props) => {
35
35
  }, convertHEICImages = async (files2) => {
36
36
  if (files2 === null || files2.length === 0)
37
37
  return [];
38
- let heicToLib;
39
- return files2.some((file) => HEIC_MIME_TYPES.includes(file.type)) && (heicToLib = await import("heic-to")), Promise.all(files2.map(async (file) => {
40
- if (heicToLib.isHeic(file))
38
+ let heic2any;
39
+ return files2.some((file) => HEIC_MIME_TYPES.includes(file.type)) && (heic2any = (await import("heic2any")).default), Promise.all(files2.map(async (file) => {
40
+ if (HEIC_MIME_TYPES.includes(file.type) && heic2any)
41
41
  try {
42
- const converted = await heicToLib.heicTo({
42
+ const converted = await heic2any({
43
43
  blob: file,
44
44
  toType: "image/jpeg"
45
45
  });
package/dist/index.js CHANGED
@@ -141,7 +141,6 @@ import { mergeRefs, setRef } from "./utilities/refs/ref.js";
141
141
  import { useCheckable } from "./hooks/useCheckable/useCheckable.js";
142
142
  import { useEdificeClient } from "./providers/EdificeClientProvider/EdificeClientProvider.hook.js";
143
143
  import { useEdificeTheme } from "./providers/EdificeThemeProvider/EdificeThemeProvider.hook.js";
144
- import { useFileToAttachment } from "./components/AddAttachments/hooks/useFileToAttachment.js";
145
144
  import { useTreeSortable } from "./components/Tree/hooks/useTreeSortable.js";
146
145
  import { useTreeView } from "./components/TreeView/hooks/useTreeView.js";
147
146
  export {
@@ -292,7 +291,6 @@ export {
292
291
  useEdificeClient,
293
292
  default85 as useEdificeIcons,
294
293
  useEdificeTheme,
295
- useFileToAttachment,
296
294
  default86 as useHasWorkflow,
297
295
  default87 as useHover,
298
296
  default88 as useHttpErrorToast,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edifice.io/react",
3
- "version": "2.5.12-develop-pedago.20260227152929",
3
+ "version": "2.5.13",
4
4
  "description": "Edifice React Library",
5
5
  "keywords": [
6
6
  "react",
@@ -123,7 +123,7 @@
123
123
  "clsx": "^2.1.1",
124
124
  "dayjs": "1.11.19",
125
125
  "emoji-picker-react": "4.5.2",
126
- "heic-to": "1.4.2",
126
+ "heic2any": "0.0.4",
127
127
  "html-react-parser": "4.2.1",
128
128
  "ohash": "1.1.3",
129
129
  "pako": "2.1.0",
@@ -135,9 +135,9 @@
135
135
  "swiper": "^10.1.0",
136
136
  "ua-parser-js": "^1.0.36",
137
137
  "react-pdf": "10.2.0",
138
- "@edifice.io/tiptap-extensions": "2.5.12-develop-pedago.20260227152929",
139
- "@edifice.io/utilities": "2.5.12-develop-pedago.20260227152929",
140
- "@edifice.io/bootstrap": "2.5.12-develop-pedago.20260227152929"
138
+ "@edifice.io/bootstrap": "2.5.13",
139
+ "@edifice.io/tiptap-extensions": "2.5.13",
140
+ "@edifice.io/utilities": "2.5.13"
141
141
  },
142
142
  "devDependencies": {
143
143
  "@babel/plugin-transform-react-pure-annotations": "^7.23.3",
@@ -168,8 +168,8 @@
168
168
  "vite": "^5.4.11",
169
169
  "vite-plugin-dts": "^4.1.0",
170
170
  "vite-tsconfig-paths": "^5.0.1",
171
- "@edifice.io/client": "2.5.12-develop-pedago.20260227152929",
172
- "@edifice.io/config": "2.5.12-develop-pedago.20260227152929"
171
+ "@edifice.io/client": "2.5.13",
172
+ "@edifice.io/config": "2.5.13"
173
173
  },
174
174
  "peerDependencies": {
175
175
  "@react-spring/web": "^9.7.5",
@@ -1,3 +0,0 @@
1
- import { Attachment } from '../models/attachment';
2
- /** Convertit un File en Attachment (id unique généré). Exposé pour les apps qui utilisent AddAttachments. */
3
- export declare function useFileToAttachment(): (file: File) => Attachment;
@@ -1,16 +0,0 @@
1
- import { useCallback } from "react";
2
- function useFileToAttachment() {
3
- return useCallback((file) => ({
4
- id: `${file.name}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
5
- charset: "UTF-8",
6
- contentTransferEncoding: "binary",
7
- contentType: file.type || "application/octet-stream",
8
- filename: file.name,
9
- name: file.name,
10
- size: file.size,
11
- file
12
- }), []);
13
- }
14
- export {
15
- useFileToAttachment
16
- };