ar-design 0.2.68 → 0.2.69

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,6 +17,38 @@
17
17
  font-size: 0.15rem;
18
18
  }
19
19
 
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 > .information {
33
+ display: flex;
34
+ flex-direction: column;
35
+ justify-content: center;
36
+ align-items: center;
37
+ gap: 0.5rem;
38
+ }
39
+ .ar-upload-button > .button > .information > .properies {
40
+ display: flex;
41
+ flex-direction: row;
42
+ gap: 0.5rem;
43
+ font-size: 0.85rem;
44
+ }
45
+ .ar-upload-button > .button > .information > .properies > .max-size {
46
+ color: var(--gray-500);
47
+ }
48
+ .ar-upload-button > .button > .information > .properies > .allow-types {
49
+ color: var(--gray-500);
50
+ }
51
+
20
52
  .ar-upload-button > .ar-upload-files {
21
53
  width: 100%;
22
54
  transition: top 250ms ease-in-out;
@@ -69,4 +101,34 @@
69
101
  cursor: pointer;
70
102
  }
71
103
 
104
+ .ar-upload-button > .ar-upload-files > .file {
105
+ display: flex;
106
+ flex-direction: row;
107
+ justify-content: space-between;
108
+ align-items: center;
109
+ background-color: var(--gray-200);
110
+ margin-top: 0.5rem;
111
+ padding: 0.5rem;
112
+ border-radius: var(--border-radius-sm);
113
+ }
114
+ .ar-upload-button > .ar-upload-files > .file > .information {
115
+ display: flex;
116
+ flex-direction: row;
117
+ gap: 0.5rem;
118
+ }
119
+ .ar-upload-button > .ar-upload-files > .file > .information > span {
120
+ display: inline-block;
121
+ }
122
+ .ar-upload-button > .ar-upload-files > .file > .information > span:last-child {
123
+ background-color: var(--primary);
124
+ padding: 0 0.25rem;
125
+ border-radius: var(--border-radius-sm);
126
+ color: var(--white);
127
+ font-size: 0.75rem;
128
+ line-height: 2;
129
+ }
130
+ .ar-upload-button > .ar-upload-files > .file > .delete {
131
+ cursor: pointer;
132
+ }
133
+
72
134
  @import url("./animations.css");
@@ -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
  *
@@ -1,8 +1,7 @@
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";
4
+ import { ARIcon } from "../../icons";
6
5
  const Upload = ({ text, file, onChange, allowedTypes, maxSize, multiple }) => {
7
6
  // refs
8
7
  const _firstLoad = useRef(false);
@@ -39,6 +38,9 @@ const Upload = ({ text, file, onChange, allowedTypes, maxSize, multiple }) => {
39
38
  return newList;
40
39
  });
41
40
  }
41
+ else {
42
+ setSelectedFile(undefined);
43
+ }
42
44
  };
43
45
  const handleValidationFile = (file) => {
44
46
  const newErrors = [];
@@ -49,7 +51,7 @@ const Upload = ({ text, file, onChange, allowedTypes, maxSize, multiple }) => {
49
51
  }
50
52
  }
51
53
  if (maxSize) {
52
- const _maxSize = maxSize * 1024 * 1024; // 5MB
54
+ const _maxSize = maxSize * 1024 * 1024; // MB
53
55
  if (file.size > _maxSize) {
54
56
  newErrors.push({ [file.name]: "Dosya boyutu çok büyük." });
55
57
  _validationErrors.current.push(file.name);
@@ -57,36 +59,55 @@ const Upload = ({ text, file, onChange, allowedTypes, maxSize, multiple }) => {
57
59
  }
58
60
  setValidationErrors((prev) => [...prev, ...newErrors]);
59
61
  };
62
+ function handleFileToBase64(file) {
63
+ return new Promise((resolve, reject) => {
64
+ const reader = new FileReader();
65
+ reader.onload = () => {
66
+ if (reader.result && typeof reader.result === "string") {
67
+ resolve(reader.result);
68
+ }
69
+ else {
70
+ reject(new Error("Failed to read the file"));
71
+ }
72
+ };
73
+ reader.onerror = reject;
74
+ reader.readAsDataURL(file);
75
+ });
76
+ }
60
77
  // useEffects
61
78
  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);
79
+ (async () => {
80
+ const dataTransfer = new DataTransfer();
81
+ const fileFormData = new FormData();
82
+ setValidationErrors([]);
83
+ _validationErrors.current = [];
84
+ if (_input.current) {
85
+ if (multiple) {
86
+ // Seçilmiş olan dosyalar validasyona gönderiliyor.
87
+ selectedFiles.forEach((f) => handleValidationFile(f));
88
+ const inValidFiles = Array.from(new Set(_validationErrors.current));
84
89
  // Input içerisine dosyalar aktarılıyor.
85
- dataTransfer.items.add(selectedFile);
90
+ selectedFiles.forEach((f) => dataTransfer.items.add(f));
86
91
  _input.current.files = dataTransfer.files;
92
+ // Geçerli olan dosyalar alındı...
93
+ const validFiles = [...selectedFiles.filter((x) => !inValidFiles.includes(x.name))];
94
+ validFiles.forEach((f) => fileFormData.append("file", f));
95
+ // Geçerli olan dosyalar base64'e dönüştürülüyor...
96
+ const base64Array = await Promise.all(validFiles.map((validFile) => handleFileToBase64(validFile)));
97
+ onChange(fileFormData, validFiles, base64Array, _validationErrors.current.length === 0);
98
+ }
99
+ else {
100
+ if (selectedFile) {
101
+ handleValidationFile(selectedFile);
102
+ fileFormData.append("file", selectedFile);
103
+ onChange(fileFormData, selectedFile, await handleFileToBase64(selectedFile));
104
+ // Input içerisine dosyalar aktarılıyor.
105
+ dataTransfer.items.add(selectedFile);
106
+ _input.current.files = dataTransfer.files;
107
+ }
87
108
  }
88
109
  }
89
- }
110
+ })();
90
111
  }, [selectedFiles, selectedFile]);
91
112
  useEffect(() => {
92
113
  if (_firstLoad.current)
@@ -97,25 +118,40 @@ const Upload = ({ text, file, onChange, allowedTypes, maxSize, multiple }) => {
97
118
  return (React.createElement("div", { ref: _arUplaod, className: "ar-upload" },
98
119
  React.createElement("input", { ref: _input, type: "file", onChange: (event) => handleFileChange(event.target.files), multiple: multiple }),
99
120
  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: () => {
121
+ React.createElement("div", { className: "button", onClick: () => {
101
122
  if (_input.current)
102
123
  _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
- }))))));
124
+ } },
125
+ React.createElement("div", { className: "information" },
126
+ React.createElement(ARIcon, { variant: "linear", icon: "Upload", stroke: "var(--gray-600)", fill: "transparent" }),
127
+ React.createElement("div", { className: "properies" },
128
+ allowedTypes && (React.createElement("div", { className: "allow-types" }, allowedTypes?.map((allowedType) => allowedType.split("/")[1].toLocaleUpperCase()).join(", "))),
129
+ maxSize && React.createElement("div", { className: "max-size" },
130
+ "up to ",
131
+ maxSize,
132
+ "MB"))),
133
+ text && React.createElement("span", null, text)),
134
+ React.createElement("div", { className: "ar-upload-files" }, multiple ? (React.createElement("ul", null, selectedFiles.map((selectedFile, index) => {
135
+ let _className = [];
136
+ const errorMessages = validationErrors
137
+ .filter((error) => Object.keys(error).includes(selectedFile.name))
138
+ .map((error) => error[selectedFile.name]);
139
+ if (errorMessages.length > 0)
140
+ _className.push("error");
141
+ const content = (React.createElement("div", { className: "content" },
142
+ React.createElement("span", { className: _className.map((c) => c).join(" ") }, selectedFile.name),
143
+ React.createElement("span", { onClick: (event) => {
144
+ event.stopPropagation();
145
+ handleFileRemove(selectedFile);
146
+ } }, "x")));
147
+ 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))));
148
+ }))) : (selectedFile && (React.createElement("div", { className: "file" },
149
+ React.createElement("div", { className: "information" },
150
+ React.createElement("span", null, selectedFile.name),
151
+ React.createElement("span", null,
152
+ (selectedFile.size / 1024).toFixed(3),
153
+ "KB")),
154
+ React.createElement("div", { className: "delete", onClick: () => handleFileRemove(selectedFile) },
155
+ React.createElement(ARIcon, { icon: "CloseCircle", fill: "transparent", size: 20 })))))))));
120
156
  };
121
157
  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.69",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",