@tecsinapse/cortex-react 1.15.0-beta.6 → 1.15.0-beta.8

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.
@@ -64,7 +64,7 @@ const Manager = ({
64
64
  showDelete: false
65
65
  },
66
66
  file.uid
67
- )) : /* @__PURE__ */ jsxRuntime.jsx(Upload.Folder, { items: files })
67
+ )) : /* @__PURE__ */ jsxRuntime.jsx(Upload.FolderList, { files })
68
68
  }
69
69
  )
70
70
  ] })
@@ -2,10 +2,32 @@
2
2
 
3
3
  var jsxRuntime = require('react/jsx-runtime');
4
4
  var cortexCore = require('@tecsinapse/cortex-core');
5
+ var React = require('react');
5
6
  var fa6 = require('react-icons/fa6');
6
7
  var md = require('react-icons/md');
7
8
  var ProgressBar = require('../ProgressBar/ProgressBar.js');
8
9
 
10
+ const recursiveCountFolderElements = (node) => {
11
+ let count = 0;
12
+ for (const key in node) {
13
+ count++;
14
+ count += recursiveCountFolderElements(node[key]);
15
+ }
16
+ return count;
17
+ };
18
+ const countFolderElements = (paths, root) => {
19
+ if (!paths.length) return 0;
20
+ const tree = {};
21
+ for (const path of paths) {
22
+ const parts = path.replace(root + "/", "").split("/").filter(Boolean);
23
+ let current = tree;
24
+ for (const part of parts) {
25
+ if (!current[part]) current[part] = {};
26
+ current = current[part];
27
+ }
28
+ }
29
+ return recursiveCountFolderElements(tree);
30
+ };
9
31
  const File = ({
10
32
  file,
11
33
  index,
@@ -63,33 +85,51 @@ const File = ({
63
85
  )
64
86
  ] }, index);
65
87
  };
66
- const Folder = ({ items }) => {
67
- const paths = /* @__PURE__ */ new Set();
68
- for (const file in items) {
69
- const path = items[file].file.relativePath.slice(1).split("/");
70
- path.map((item) => paths.add(item));
71
- }
72
- const intent = (items ?? []).some((item) => item.status === "success") ? "success" : (items ?? []).some((item) => item.status === "error") ? "error" : "info";
88
+ const Folder = ({ name, subItems }) => {
89
+ const size = countFolderElements(
90
+ subItems.map((it) => it.path),
91
+ name
92
+ );
93
+ const loading = React.useMemo(
94
+ () => subItems.some((it) => it.status === "uploading"),
95
+ [subItems]
96
+ );
97
+ const intent = React.useMemo(() => {
98
+ if (loading) return "info";
99
+ if ((subItems ?? []).some((item) => item.status === "error") && (subItems ?? []).some((item) => item.status === "success")) {
100
+ return "warning";
101
+ }
102
+ return "success";
103
+ }, [subItems]);
73
104
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col w-full", children: [
74
105
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-between border rounded-t-mili shadow p-mili", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-centi", children: [
75
106
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "border-2 text-kilo text-primary-medium w-tera h-tera flex items-center justify-center rounded-mili", children: /* @__PURE__ */ jsxRuntime.jsx(fa6.FaRegFolder, {}) }),
76
107
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-col", children: [
77
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-semibold truncate max-w-[200px]", children: Array.from(paths)[0] }),
108
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-semibold truncate max-w-[200px]", children: name }),
78
109
  /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-gray-500", children: [
79
- paths.size - 1,
80
- " itens"
110
+ size,
111
+ " ",
112
+ size > 1 ? "itens" : "item"
81
113
  ] })
82
114
  ] })
83
115
  ] }) }),
84
- /* @__PURE__ */ jsxRuntime.jsx(
85
- ProgressBar.ProgressBar,
86
- {
87
- intent,
88
- infinite: (items ?? []).some((item) => item.status === "uploading")
89
- }
90
- )
116
+ /* @__PURE__ */ jsxRuntime.jsx(ProgressBar.ProgressBar, { intent, infinite: loading })
91
117
  ] });
92
118
  };
119
+ const FolderList = ({ files }) => {
120
+ const folders = React.useMemo(() => {
121
+ const segments = {};
122
+ files.forEach((file) => {
123
+ const path = file.file.relativePath.replace(/^\//, "");
124
+ const root = path.split("/")[0];
125
+ const current = Array.from(segments?.[root] ?? []);
126
+ segments[root] = [...current, { path, status: file.status }];
127
+ });
128
+ return segments;
129
+ }, [files]);
130
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: Object.entries(folders).map(([name, children], index) => /* @__PURE__ */ jsxRuntime.jsx(Folder, { name, subItems: children }, index)) });
131
+ };
93
132
 
94
133
  exports.File = File;
95
134
  exports.Folder = Folder;
135
+ exports.FolderList = FolderList;
@@ -1,6 +1,6 @@
1
1
  import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import { createPortal } from 'react-dom';
3
- import { File, Folder } from './Upload.js';
3
+ import { File, FolderList } from './Upload.js';
4
4
  import { Button } from '../Button.js';
5
5
  import { IoMdClose } from 'react-icons/io';
6
6
  import { useState } from 'react';
@@ -62,7 +62,7 @@ const Manager = ({
62
62
  showDelete: false
63
63
  },
64
64
  file.uid
65
- )) : /* @__PURE__ */ jsx(Folder, { items: files })
65
+ )) : /* @__PURE__ */ jsx(FolderList, { files })
66
66
  }
67
67
  )
68
68
  ] })
@@ -1,9 +1,31 @@
1
- import { jsxs, jsx } from 'react/jsx-runtime';
1
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
2
  import { button } from '@tecsinapse/cortex-core';
3
+ import { useMemo } from 'react';
3
4
  import { FaRegFileLines, FaRegFolder } from 'react-icons/fa6';
4
5
  import { MdClose } from 'react-icons/md';
5
6
  import { ProgressBar } from '../ProgressBar/ProgressBar.js';
6
7
 
8
+ const recursiveCountFolderElements = (node) => {
9
+ let count = 0;
10
+ for (const key in node) {
11
+ count++;
12
+ count += recursiveCountFolderElements(node[key]);
13
+ }
14
+ return count;
15
+ };
16
+ const countFolderElements = (paths, root) => {
17
+ if (!paths.length) return 0;
18
+ const tree = {};
19
+ for (const path of paths) {
20
+ const parts = path.replace(root + "/", "").split("/").filter(Boolean);
21
+ let current = tree;
22
+ for (const part of parts) {
23
+ if (!current[part]) current[part] = {};
24
+ current = current[part];
25
+ }
26
+ }
27
+ return recursiveCountFolderElements(tree);
28
+ };
7
29
  const File = ({
8
30
  file,
9
31
  index,
@@ -61,32 +83,49 @@ const File = ({
61
83
  )
62
84
  ] }, index);
63
85
  };
64
- const Folder = ({ items }) => {
65
- const paths = /* @__PURE__ */ new Set();
66
- for (const file in items) {
67
- const path = items[file].file.relativePath.slice(1).split("/");
68
- path.map((item) => paths.add(item));
69
- }
70
- const intent = (items ?? []).some((item) => item.status === "success") ? "success" : (items ?? []).some((item) => item.status === "error") ? "error" : "info";
86
+ const Folder = ({ name, subItems }) => {
87
+ const size = countFolderElements(
88
+ subItems.map((it) => it.path),
89
+ name
90
+ );
91
+ const loading = useMemo(
92
+ () => subItems.some((it) => it.status === "uploading"),
93
+ [subItems]
94
+ );
95
+ const intent = useMemo(() => {
96
+ if (loading) return "info";
97
+ if ((subItems ?? []).some((item) => item.status === "error") && (subItems ?? []).some((item) => item.status === "success")) {
98
+ return "warning";
99
+ }
100
+ return "success";
101
+ }, [subItems]);
71
102
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-col w-full", children: [
72
103
  /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between border rounded-t-mili shadow p-mili", children: /* @__PURE__ */ jsxs("div", { className: "flex gap-centi", children: [
73
104
  /* @__PURE__ */ jsx("span", { className: "border-2 text-kilo text-primary-medium w-tera h-tera flex items-center justify-center rounded-mili", children: /* @__PURE__ */ jsx(FaRegFolder, {}) }),
74
105
  /* @__PURE__ */ jsxs("div", { className: "flex-col", children: [
75
- /* @__PURE__ */ jsx("p", { className: "font-semibold truncate max-w-[200px]", children: Array.from(paths)[0] }),
106
+ /* @__PURE__ */ jsx("p", { className: "font-semibold truncate max-w-[200px]", children: name }),
76
107
  /* @__PURE__ */ jsxs("p", { className: "text-sm text-gray-500", children: [
77
- paths.size - 1,
78
- " itens"
108
+ size,
109
+ " ",
110
+ size > 1 ? "itens" : "item"
79
111
  ] })
80
112
  ] })
81
113
  ] }) }),
82
- /* @__PURE__ */ jsx(
83
- ProgressBar,
84
- {
85
- intent,
86
- infinite: (items ?? []).some((item) => item.status === "uploading")
87
- }
88
- )
114
+ /* @__PURE__ */ jsx(ProgressBar, { intent, infinite: loading })
89
115
  ] });
90
116
  };
117
+ const FolderList = ({ files }) => {
118
+ const folders = useMemo(() => {
119
+ const segments = {};
120
+ files.forEach((file) => {
121
+ const path = file.file.relativePath.replace(/^\//, "");
122
+ const root = path.split("/")[0];
123
+ const current = Array.from(segments?.[root] ?? []);
124
+ segments[root] = [...current, { path, status: file.status }];
125
+ });
126
+ return segments;
127
+ }, [files]);
128
+ return /* @__PURE__ */ jsx(Fragment, { children: Object.entries(folders).map(([name, children], index) => /* @__PURE__ */ jsx(Folder, { name, subItems: children }, index)) });
129
+ };
91
130
 
92
- export { File, Folder };
131
+ export { File, Folder, FolderList };
@@ -1,3 +1,4 @@
1
- import { FileProps, FolderProps } from './types';
1
+ import { FileProps, FolderListProps, FolderProps } from './types';
2
2
  export declare const File: <T>({ file, index, onDelete, showDelete, }: FileProps<T>) => import("react/jsx-runtime").JSX.Element;
3
- export declare const Folder: <T>({ items }: FolderProps<T>) => import("react/jsx-runtime").JSX.Element;
3
+ export declare const Folder: ({ name, subItems }: FolderProps) => import("react/jsx-runtime").JSX.Element;
4
+ export declare const FolderList: <T>({ files }: FolderListProps<T>) => import("react/jsx-runtime").JSX.Element;
@@ -1,4 +1,10 @@
1
1
  import { DropzoneInputProps, DropzoneRootProps, type FileError, type FileRejection, type FileWithPath } from 'react-dropzone';
2
+ declare global {
3
+ interface File {
4
+ relativePath: string;
5
+ path?: string;
6
+ }
7
+ }
2
8
  export interface FileItem {
3
9
  file: File;
4
10
  loading: 'loading' | 'success' | 'error';
@@ -9,8 +15,15 @@ export interface FileProps<T> {
9
15
  onDelete: (index: number) => void;
10
16
  showDelete?: boolean;
11
17
  }
12
- export interface FolderProps<T> {
13
- items: FileUpload<T>[];
18
+ export interface FolderProps {
19
+ name: string;
20
+ subItems: {
21
+ status: string;
22
+ path: string;
23
+ }[];
24
+ }
25
+ export interface FolderListProps<T> {
26
+ files: FileUpload<T>[];
14
27
  }
15
28
  export interface FilesProps<T> {
16
29
  files: FileUpload<T>[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tecsinapse/cortex-react",
3
- "version": "1.15.0-beta.6",
3
+ "version": "1.15.0-beta.8",
4
4
  "description": "React components based in @tecsinapse/cortex-core",
5
5
  "license": "MIT",
6
6
  "main": "dist/esm/index.js",
@@ -20,7 +20,7 @@
20
20
  "dependencies": {
21
21
  "@floating-ui/react": "^0.26.18",
22
22
  "@internationalized/date": "3.7.0",
23
- "@tecsinapse/cortex-core": "1.2.0-beta.4",
23
+ "@tecsinapse/cortex-core": "1.2.0-beta.6",
24
24
  "clsx": "2.1.1",
25
25
  "currency.js": "2.0.4",
26
26
  "embla-carousel-autoplay": "^8.0.0",
@@ -48,5 +48,5 @@
48
48
  "react-icons": ">=5.2.0",
49
49
  "tailwind": ">=3.3.0"
50
50
  },
51
- "gitHead": "4b3f865fef0e94a662c300ccd5173c9aecdd4fd7"
51
+ "gitHead": "e193bd148328ee510548708de7803cb1832abd6d"
52
52
  }