ar-design 0.2.68 → 0.2.70

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.
@@ -17,55 +17,89 @@
17
17
  font-size: 0.15rem;
18
18
  }
19
19
 
20
- .ar-upload-button > .ar-upload-files {
20
+ .ar-upload-button > .button {
21
+ display: flex;
22
+ flex-direction: column;
23
+ justify-content: center;
24
+ align-items: center;
25
+ gap: 1rem;
26
+ padding: 1rem 0;
27
+ border: dashed 1px var(--gray-300);
28
+ border-radius: var(--border-radius-sm);
29
+ cursor: pointer;
30
+ user-select: none;
31
+ }
32
+ .ar-upload-button > .button:has(> img) {
33
+ padding: 0;
34
+ border: none;
35
+ overflow: hidden;
36
+ }
37
+ .ar-upload-button > .button > img {
21
38
  width: 100%;
22
- transition: top 250ms ease-in-out;
39
+ height: 200px;
40
+ object-fit: fill;
41
+ object-position: top;
23
42
  }
24
- .ar-upload-button > .ar-upload-files > ul {
43
+ .ar-upload-button > .button > .information {
25
44
  display: flex;
26
45
  flex-direction: column;
27
- list-style-type: none;
28
- }
29
- .ar-upload-button > .ar-upload-files > ul > li {
30
- position: relative;
31
- border-bottom: solid 1px var(--gray-200);
46
+ justify-content: center;
47
+ align-items: center;
48
+ gap: 0.5rem;
32
49
  }
33
- .ar-upload-button > .ar-upload-files > ul > li:hover > .errors {
50
+ .ar-upload-button > .button > .information > .properies {
34
51
  display: flex;
52
+ flex-direction: row;
53
+ gap: 0.5rem;
54
+ font-size: 0.85rem;
55
+ }
56
+ .ar-upload-button > .button > .information > .properies > .max-size {
57
+ color: var(--gray-500);
58
+ }
59
+ .ar-upload-button > .button > .information > .properies > .allow-types {
60
+ color: var(--gray-500);
35
61
  }
36
- .ar-upload-button > .ar-upload-files > ul > li.error {
37
- border-left: solid 2px var(--danger);
62
+
63
+ .ar-upload-button > .ar-upload-files {
64
+ width: 100%;
65
+ transition: top 250ms ease-in-out;
38
66
  }
39
- .ar-upload-button > .ar-upload-files > ul > li .content {
67
+ .ar-upload-button > .ar-upload-files > ul {
68
+ list-style: none;
69
+ }
70
+
71
+ .ar-upload-button > .ar-upload-files > ul > li > .file,
72
+ .ar-upload-button > .ar-upload-files > .file {
40
73
  display: flex;
41
74
  flex-direction: row;
42
75
  justify-content: space-between;
43
76
  align-items: center;
44
- width: 100%;
45
- height: 2rem;
46
- padding: 0 0.5rem;
77
+ background-color: var(--gray-200);
78
+ margin-top: 0.5rem;
79
+ padding: 0.5rem;
80
+ border-radius: var(--border-radius-sm);
47
81
  }
48
- .ar-upload-button > .ar-upload-files > ul > li .content > span:first-child {
49
- width: 90%;
50
- font-size: 0.75rem;
51
- text-overflow: ellipsis;
52
- overflow: hidden;
53
- white-space: nowrap;
54
- }
55
- .ar-upload-button > .ar-upload-files > ul > li .content > span:first-child.error {
56
- color: var(--danger);
57
- /* -webkit-text-stroke: 0.5px var(--danger); */
58
- }
59
- .ar-upload-button > .ar-upload-files > ul > li .content > span:last-child {
60
- background-color: rgba(var(--danger-rgb), 0.1);
61
- width: 1rem;
62
- height: 1rem;
63
- border-radius: var(--border-radius-pill);
64
- color: rgba(var(--danger-rgb), 0.5);
82
+ .ar-upload-button > .ar-upload-files > ul > li > .file > .information,
83
+ .ar-upload-button > .ar-upload-files > .file > .information {
84
+ display: flex;
85
+ flex-direction: row;
86
+ gap: 0.5rem;
87
+ }
88
+ .ar-upload-button > .ar-upload-files > ul > li > .file > .information > span,
89
+ .ar-upload-button > .ar-upload-files > .file > .information > span {
90
+ display: inline-block;
91
+ }
92
+ .ar-upload-button > .ar-upload-files > ul > li > .file > .information > span:last-child,
93
+ .ar-upload-button > .ar-upload-files > .file > .information > span:last-child {
94
+ background-color: var(--primary);
95
+ padding: 0 0.25rem;
96
+ border-radius: var(--border-radius-sm);
97
+ color: var(--white);
65
98
  font-size: 0.75rem;
66
- text-align: center;
67
- /* -webkit-text-stroke: 1px rgba(var(--danger-rgb), 0.5); */
68
- line-height: 0.85rem;
99
+ line-height: 2;
100
+ }
101
+ .ar-upload-button > .ar-upload-files > ul > li > .file > .delete,
102
+ .ar-upload-button > .ar-upload-files > .file > .delete {
69
103
  cursor: pointer;
70
104
  }
71
105
 
@@ -32,7 +32,7 @@ interface IMultiple {
32
32
  * />
33
33
  * ```
34
34
  */
35
- onChange: (formData: FormData, files: File[], isInvalidFileExist: boolean) => void;
35
+ onChange: (formData: FormData, files: File[], base64: string[], isInvalidFileExist: boolean) => void;
36
36
  /**
37
37
  * Çoklu dosya seçiminin aktif olduğunu belirtir.
38
38
  *
@@ -66,7 +66,7 @@ interface ISingle {
66
66
  * <Upload onChange={(formData, file) => console.log(file)} />
67
67
  * ```
68
68
  */
69
- onChange: (formData: FormData | undefined, files: File | null) => void;
69
+ onChange: (formData: FormData | undefined, files: File | null, base64: string) => void;
70
70
  /**
71
71
  * Çoklu dosya seçiminin devre dışı olduğunu belirtir.
72
72
  *
@@ -98,6 +98,7 @@ type Props = {
98
98
  * ```
99
99
  */
100
100
  allowedTypes?: AllowedTypes[];
101
+ uploadType?: "image" | "application-file";
101
102
  /**
102
103
  * Kabul edilen maksimum dosya boyutu (byte cinsinden).
103
104
  *
@@ -1,9 +1,8 @@
1
1
  import React, { useEffect, useRef, useState } from "react";
2
2
  import "../../../assets/css/components/form/upload/styles.css";
3
- import { ARIcon } from "../../icons";
4
- import Button from "../button";
5
3
  import Tooltip from "../../feedback/tooltip";
6
- const Upload = ({ text, file, onChange, allowedTypes, maxSize, multiple }) => {
4
+ import { ARIcon } from "../../icons";
5
+ const Upload = ({ text, file, onChange, allowedTypes, uploadType = "application-file", maxSize, multiple, }) => {
7
6
  // refs
8
7
  const _firstLoad = useRef(false);
9
8
  const _input = useRef(null);
@@ -11,8 +10,9 @@ const Upload = ({ text, file, onChange, allowedTypes, maxSize, multiple }) => {
11
10
  // refs -> File Data
12
11
  const _validationErrors = useRef([]);
13
12
  // states
14
- const [selectedFiles, setSelectedFiles] = useState([]);
15
13
  const [selectedFile, setSelectedFile] = useState(undefined);
14
+ const [selectedFileBase64, setSelectedFileBase64] = useState(undefined);
15
+ const [selectedFiles, setSelectedFiles] = useState([]);
16
16
  const [validationErrors, setValidationErrors] = useState([]);
17
17
  // methods
18
18
  const handleFileChange = (files) => {
@@ -39,6 +39,10 @@ const Upload = ({ text, file, onChange, allowedTypes, maxSize, multiple }) => {
39
39
  return newList;
40
40
  });
41
41
  }
42
+ else {
43
+ setSelectedFile(undefined);
44
+ setSelectedFileBase64(undefined);
45
+ }
42
46
  };
43
47
  const handleValidationFile = (file) => {
44
48
  const newErrors = [];
@@ -49,7 +53,7 @@ const Upload = ({ text, file, onChange, allowedTypes, maxSize, multiple }) => {
49
53
  }
50
54
  }
51
55
  if (maxSize) {
52
- const _maxSize = maxSize * 1024 * 1024; // 5MB
56
+ const _maxSize = maxSize * 1024 * 1024; // MB
53
57
  if (file.size > _maxSize) {
54
58
  newErrors.push({ [file.name]: "Dosya boyutu çok büyük." });
55
59
  _validationErrors.current.push(file.name);
@@ -57,36 +61,56 @@ const Upload = ({ text, file, onChange, allowedTypes, maxSize, multiple }) => {
57
61
  }
58
62
  setValidationErrors((prev) => [...prev, ...newErrors]);
59
63
  };
64
+ function handleFileToBase64(file) {
65
+ return new Promise((resolve, reject) => {
66
+ const reader = new FileReader();
67
+ reader.onload = () => {
68
+ if (reader.result && typeof reader.result === "string") {
69
+ resolve(reader.result);
70
+ }
71
+ else {
72
+ reject(new Error("Failed to read the file"));
73
+ }
74
+ };
75
+ reader.onerror = reject;
76
+ reader.readAsDataURL(file);
77
+ });
78
+ }
60
79
  // useEffects
61
80
  useEffect(() => {
62
- const dataTransfer = new DataTransfer();
63
- const fileFormData = new FormData();
64
- setValidationErrors([]);
65
- _validationErrors.current = [];
66
- if (_input.current) {
67
- if (multiple) {
68
- // Seçilmiş olan dosyalar validasyona gönderiliyor.
69
- selectedFiles.forEach((f) => handleValidationFile(f));
70
- const inValidFiles = Array.from(new Set(_validationErrors.current));
71
- // Input içerisine dosyalar aktarılıyor.
72
- selectedFiles.forEach((f) => dataTransfer.items.add(f));
73
- _input.current.files = dataTransfer.files;
74
- // Geçerli olan dosyalar alındı...
75
- const validFiles = [...selectedFiles.filter((x) => !inValidFiles.includes(x.name))];
76
- validFiles.forEach((f) => fileFormData.append("file", f));
77
- onChange(fileFormData, validFiles, _validationErrors.current.length === 0);
78
- }
79
- else {
80
- if (selectedFile) {
81
- handleValidationFile(selectedFile);
82
- fileFormData.append("file", selectedFile);
83
- onChange(fileFormData, selectedFile);
81
+ (async () => {
82
+ const dataTransfer = new DataTransfer();
83
+ const fileFormData = new FormData();
84
+ setValidationErrors([]);
85
+ _validationErrors.current = [];
86
+ if (_input.current) {
87
+ if (multiple) {
88
+ // Seçilmiş olan dosyalar validasyona gönderiliyor.
89
+ selectedFiles.forEach((f) => handleValidationFile(f));
90
+ const inValidFiles = Array.from(new Set(_validationErrors.current));
84
91
  // Input içerisine dosyalar aktarılıyor.
85
- dataTransfer.items.add(selectedFile);
92
+ selectedFiles.forEach((f) => dataTransfer.items.add(f));
86
93
  _input.current.files = dataTransfer.files;
94
+ // Geçerli olan dosyalar alındı...
95
+ const validFiles = [...selectedFiles.filter((x) => !inValidFiles.includes(x.name))];
96
+ validFiles.forEach((f) => fileFormData.append("file", f));
97
+ // Geçerli olan dosyalar base64'e dönüştürülüyor...
98
+ const base64Array = await Promise.all(validFiles.map((validFile) => handleFileToBase64(validFile)));
99
+ onChange(fileFormData, validFiles, base64Array, _validationErrors.current.length === 0);
100
+ }
101
+ else {
102
+ if (selectedFile) {
103
+ handleValidationFile(selectedFile);
104
+ fileFormData.append("file", selectedFile);
105
+ onChange(fileFormData, selectedFile, await handleFileToBase64(selectedFile));
106
+ setSelectedFileBase64(await handleFileToBase64(selectedFile));
107
+ // Input içerisine dosyalar aktarılıyor.
108
+ dataTransfer.items.add(selectedFile);
109
+ _input.current.files = dataTransfer.files;
110
+ }
87
111
  }
88
112
  }
89
- }
113
+ })();
90
114
  }, [selectedFiles, selectedFile]);
91
115
  useEffect(() => {
92
116
  if (_firstLoad.current)
@@ -97,25 +121,44 @@ const Upload = ({ text, file, onChange, allowedTypes, maxSize, multiple }) => {
97
121
  return (React.createElement("div", { ref: _arUplaod, className: "ar-upload" },
98
122
  React.createElement("input", { ref: _input, type: "file", onChange: (event) => handleFileChange(event.target.files), multiple: multiple }),
99
123
  React.createElement("div", { className: "ar-upload-button" },
100
- React.createElement(Button, { variant: "outlined", status: "light", icon: { element: React.createElement(ARIcon, { variant: "bulk", icon: "Upload", fill: "var(--gray-300)" }) }, onClick: () => {
124
+ React.createElement("div", { className: "button", onClick: () => {
101
125
  if (_input.current)
102
126
  _input.current.click();
103
- } }, text && React.createElement("span", null, text)),
104
- React.createElement("div", { className: "ar-upload-files" },
105
- React.createElement("ul", null, selectedFiles.map((selectedFile, index) => {
106
- let _className = [];
107
- const errorMessages = validationErrors
108
- .filter((error) => Object.keys(error).includes(selectedFile.name))
109
- .map((error) => error[selectedFile.name]);
110
- if (errorMessages.length > 0)
111
- _className.push("error");
112
- const content = (React.createElement("div", { className: "content" },
113
- React.createElement("span", { className: _className.map((c) => c).join(" ") }, selectedFile.name),
114
- React.createElement("span", { onClick: (event) => {
115
- event.stopPropagation();
116
- handleFileRemove(selectedFile);
117
- } }, "x")));
118
- return (React.createElement("li", { key: index, className: _className.map((c) => c).join(" ") }, errorMessages.length === 0 ? (content) : (React.createElement(Tooltip, { text: errorMessages.map((message) => message ?? "") }, content))));
119
- }))))));
127
+ } },
128
+ uploadType === "image" && selectedFileBase64 && React.createElement("img", { src: selectedFileBase64 }),
129
+ (uploadType === "application-file" || !selectedFileBase64) && (React.createElement(React.Fragment, null,
130
+ React.createElement("div", { className: "information" },
131
+ React.createElement(ARIcon, { variant: "linear", icon: "Upload", stroke: "var(--gray-600)", fill: "transparent" }),
132
+ React.createElement("div", { className: "properies" },
133
+ allowedTypes && (React.createElement("div", { className: "allow-types" }, allowedTypes?.map((allowedType) => allowedType.split("/")[1].toLocaleUpperCase()).join(", "))),
134
+ maxSize && React.createElement("div", { className: "max-size" },
135
+ "up to ",
136
+ maxSize,
137
+ "MB"))),
138
+ text && React.createElement("span", null, text)))),
139
+ React.createElement("div", { className: "ar-upload-files" }, multiple ? (React.createElement("ul", null, selectedFiles.map((selectedFile, index) => {
140
+ let _className = [];
141
+ const errorMessages = validationErrors
142
+ .filter((error) => Object.keys(error).includes(selectedFile.name))
143
+ .map((error) => error[selectedFile.name]);
144
+ if (errorMessages.length > 0)
145
+ _className.push("error");
146
+ const content = (React.createElement("div", { className: "file" },
147
+ React.createElement("div", { className: "information" },
148
+ React.createElement("span", null, selectedFile.name),
149
+ React.createElement("span", null,
150
+ (selectedFile.size / 1024).toFixed(3),
151
+ "KB")),
152
+ React.createElement("div", { className: "delete", onClick: () => handleFileRemove(selectedFile) },
153
+ React.createElement(ARIcon, { icon: "CloseCircle", fill: "transparent", size: 20 }))));
154
+ return (React.createElement("li", { key: index, className: _className.map((c) => c).join(" ") }, errorMessages.length === 0 ? (content) : (React.createElement(Tooltip, { text: errorMessages.map((message) => message ?? "") }, content))));
155
+ }))) : (selectedFile && (React.createElement("div", { className: "file" },
156
+ React.createElement("div", { className: "information" },
157
+ React.createElement("span", null, selectedFile.name),
158
+ React.createElement("span", null,
159
+ (selectedFile.size / 1024).toFixed(3),
160
+ "KB")),
161
+ React.createElement("div", { className: "delete", onClick: () => handleFileRemove(selectedFile) },
162
+ React.createElement(ARIcon, { icon: "CloseCircle", fill: "transparent", size: 20 })))))))));
120
163
  };
121
164
  export default Upload;
@@ -48,6 +48,11 @@ class Icon {
48
48
  return (React.createElement(React.Fragment, null,
49
49
  React.createElement("path", { d: "M6 4v6a6 6 0 0 0 12 0V4", stroke: this._stroke, strokeWidth: this._strokeWidth, strokeLinecap: "round", strokeLinejoin: "round" }),
50
50
  React.createElement("line", { x1: "4", y1: "20", x2: "20", y2: "20", stroke: this._stroke, strokeWidth: this._strokeWidth, strokeLinecap: "round", strokeLinejoin: "round" })));
51
+ case "Upload":
52
+ return (React.createElement(React.Fragment, null,
53
+ React.createElement("path", { d: "M9 17v-6l-2 2M9 11l2 2", stroke: this._stroke, strokeWidth: this._strokeWidth, strokeLinecap: "round", strokeLinejoin: "round" }),
54
+ React.createElement("path", { d: "M22 10v5c0 5-2 7-7 7H9c-5 0-7-2-7-7V9c0-5 2-7 7-7h5", stroke: this._stroke, strokeWidth: this._strokeWidth, strokeLinecap: "round", strokeLinejoin: "round" }),
55
+ React.createElement("path", { d: "M22 10h-4c-3 0-4-1-4-4V2l8 8Z", stroke: this._stroke, strokeWidth: this._strokeWidth, strokeLinecap: "round", strokeLinejoin: "round" })));
51
56
  case "Strikethrough":
52
57
  return (React.createElement(React.Fragment, null,
53
58
  React.createElement("line", { x1: "4", y1: "12", x2: "20", y2: "12", stroke: this._stroke, strokeWidth: this._strokeWidth, strokeLinecap: "round", strokeLinejoin: "round" }),
@@ -1,7 +1,7 @@
1
1
  import React from "react";
2
2
  import Svg from "./Svg";
3
3
  import Icon from "./Compiler";
4
- export const ARIcon = ({ viewBox, size, variant = "linear", icon, fill = "var(--dark)", stroke = "var(--dark)", strokeWidth = 2, style, }) => {
4
+ export const ARIcon = ({ viewBox, size, variant = "linear", icon, fill = "var(--dark)", stroke = "var(--dark)", strokeWidth = 1, style, }) => {
5
5
  const { Compiler } = new Icon(fill, stroke, strokeWidth);
6
6
  return (React.createElement(Svg, { viewBox: viewBox, fill: fill, width: size, height: size, style: style }, Compiler(variant, icon)));
7
7
  };
@@ -20,7 +20,10 @@ declare class Api {
20
20
  data?: any;
21
21
  headers?: HeadersInit;
22
22
  init?: Omit<RequestInit | undefined, "body">;
23
- }): Promise<Response>;
23
+ }): Promise<{
24
+ p_response: Promise<Response>;
25
+ response: Response;
26
+ }>;
24
27
  PostWithFormData(values: {
25
28
  input?: RequestInfo;
26
29
  data?: FormData;
@@ -29,13 +29,15 @@ class Api {
29
29
  if (values.input && values.input.toString().includes("?")) {
30
30
  values.input = values.input.toString().replace(/\/(?=\?)/, "");
31
31
  }
32
- const response = await this.CustomFetch(`${this._url}${values.input}`, {
32
+ const p_response = this.CustomFetch(`${this._url}${values.input}`, {
33
33
  method: "POST",
34
34
  headers: { ...this.HeaderProperties(), ...values.headers },
35
35
  body: JSON.stringify(values.data),
36
36
  ...values.init,
37
37
  });
38
- return response;
38
+ const clone = (await p_response).clone();
39
+ const response = await clone;
40
+ return { p_response, response };
39
41
  }
40
42
  async PostWithFormData(values) {
41
43
  if (values.input && values.input.toString().includes("?")) {
@@ -26,13 +26,13 @@ class Service {
26
26
  let endPoint = `${this._endPoint}`;
27
27
  if (values?.input)
28
28
  endPoint += `/${values.input}`;
29
- const response = await this._api.Post({
29
+ const { p_response, response } = await this._api.Post({
30
30
  input: endPoint,
31
31
  data: values?.data,
32
32
  headers: values?.headers,
33
33
  init: values?.init,
34
34
  });
35
- return await this.Response(null, response);
35
+ return await this.Response(p_response, response);
36
36
  }
37
37
  catch (error) {
38
38
  throw new Error(error instanceof Error ? error.message : "Beklenmeyen bir hata oluştu.");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ar-design",
3
- "version": "0.2.68",
3
+ "version": "0.2.70",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",