@arkyn/components 3.0.1-beta.22 → 3.0.1-beta.24
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.
- package/README.md +265 -0
- package/dist/bundle.js +1485 -859
- package/dist/bundle.umd.cjs +1 -1
- package/dist/components/audioUpload/hasFileContent/index.d.ts +13 -0
- package/dist/components/audioUpload/hasFileContent/index.d.ts.map +1 -0
- package/dist/components/audioUpload/hasFileContent/index.js +26 -0
- package/dist/components/audioUpload/index.d.ts +82 -0
- package/dist/components/audioUpload/index.d.ts.map +1 -0
- package/dist/components/audioUpload/index.js +120 -0
- package/dist/components/audioUpload/noFileContent/index.d.ts +12 -0
- package/dist/components/audioUpload/noFileContent/index.d.ts.map +1 -0
- package/dist/components/audioUpload/noFileContent/index.js +29 -0
- package/dist/components/clientOnly.d.ts +86 -0
- package/dist/components/clientOnly.d.ts.map +1 -0
- package/dist/components/clientOnly.js +86 -0
- package/dist/components/fileUpload/hasFileContent/index.d.ts +13 -0
- package/dist/components/fileUpload/hasFileContent/index.d.ts.map +1 -0
- package/dist/components/fileUpload/hasFileContent/index.js +34 -0
- package/dist/components/fileUpload/index.d.ts +94 -0
- package/dist/components/fileUpload/index.d.ts.map +1 -0
- package/dist/components/fileUpload/index.js +127 -0
- package/dist/components/fileUpload/noFileContent/index.d.ts +12 -0
- package/dist/components/fileUpload/noFileContent/index.d.ts.map +1 -0
- package/dist/components/fileUpload/noFileContent/index.js +29 -0
- package/dist/components/imageUpload/hasFileContent/index.d.ts +13 -0
- package/dist/components/imageUpload/hasFileContent/index.d.ts.map +1 -0
- package/dist/components/imageUpload/hasFileContent/index.js +24 -0
- package/dist/components/imageUpload/index.d.ts +114 -0
- package/dist/components/imageUpload/index.d.ts.map +1 -0
- package/dist/components/imageUpload/index.js +148 -0
- package/dist/components/imageUpload/noFileContent/index.d.ts +12 -0
- package/dist/components/imageUpload/noFileContent/index.d.ts.map +1 -0
- package/dist/components/imageUpload/noFileContent/index.js +29 -0
- package/dist/components/tab/tabContainer/index.d.ts +1 -1
- package/dist/components/tab/tabContainer/index.d.ts.map +1 -1
- package/dist/components/table/tableBody/index.d.ts +67 -0
- package/dist/components/table/tableBody/index.d.ts.map +1 -0
- package/dist/components/table/tableBody/index.js +69 -0
- package/dist/components/table/tableCaption/index.d.ts +62 -0
- package/dist/components/table/tableCaption/index.d.ts.map +1 -0
- package/dist/components/table/tableCaption/index.js +64 -0
- package/dist/components/table/tableContainer/index.d.ts +64 -0
- package/dist/components/table/tableContainer/index.d.ts.map +1 -0
- package/dist/components/table/tableContainer/index.js +66 -0
- package/dist/components/table/tableFooter/index.d.ts +45 -0
- package/dist/components/table/tableFooter/index.d.ts.map +1 -0
- package/dist/components/table/tableFooter/index.js +47 -0
- package/dist/components/table/tableHeader/index.d.ts +44 -0
- package/dist/components/table/tableHeader/index.d.ts.map +1 -0
- package/dist/components/table/tableHeader/index.js +46 -0
- package/dist/components/tooltip/index.d.ts.map +1 -1
- package/dist/components/tooltip/index.js +1 -1
- package/dist/hooks/useDrawer.d.ts +86 -0
- package/dist/hooks/useDrawer.d.ts.map +1 -0
- package/dist/hooks/useDrawer.js +20 -0
- package/dist/hooks/useHydrated.d.ts +76 -0
- package/dist/hooks/useHydrated.d.ts.map +1 -0
- package/dist/hooks/useHydrated.js +81 -0
- package/dist/hooks/useModal.d.ts +81 -0
- package/dist/hooks/useModal.d.ts.map +1 -0
- package/dist/hooks/useModal.js +20 -0
- package/dist/hooks/useToast.d.ts +70 -0
- package/dist/hooks/useToast.d.ts.map +1 -0
- package/dist/hooks/useToast.js +72 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -0
- package/dist/providers/drawerProvider.d.ts +106 -0
- package/dist/providers/drawerProvider.d.ts.map +1 -0
- package/dist/providers/drawerProvider.js +120 -0
- package/dist/providers/modalProvider.d.ts +103 -0
- package/dist/providers/modalProvider.d.ts.map +1 -0
- package/dist/providers/modalProvider.js +119 -0
- package/dist/providers/toastProvider.d.ts +48 -0
- package/dist/providers/toastProvider.d.ts.map +1 -0
- package/dist/providers/toastProvider.js +73 -0
- package/dist/style.css +1 -1
- package/package.json +21 -3
@@ -0,0 +1,120 @@
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
2
|
+
import { useState } from "react";
|
3
|
+
import { useForm } from "../../hooks/useForm";
|
4
|
+
import { FieldError } from "../fieldError";
|
5
|
+
import { FieldLabel } from "../fieldLabel";
|
6
|
+
import { FieldWrapper } from "../fieldWrapper";
|
7
|
+
import { HasFileContent } from "./hasFileContent";
|
8
|
+
import { NoFileContent } from "./noFileContent";
|
9
|
+
import "./styles.css";
|
10
|
+
/**
|
11
|
+
* AudioUpload component - handles audio file upload with drag & drop functionality and server upload
|
12
|
+
*
|
13
|
+
* @param props - AudioUpload component properties
|
14
|
+
* @param props.name - Required field name for form handling
|
15
|
+
* @param props.action - Required server endpoint URL for file upload
|
16
|
+
* @param props.fileName - Name of the file field in FormData. Default: "file"
|
17
|
+
* @param props.method - HTTP method for upload request. Default: "POST"
|
18
|
+
* @param props.acceptAudio - Audio file types to accept. Default: "audio/*"
|
19
|
+
* @param props.dropAudioText - Text displayed in drop zone. Default: "Ou arraste e solte um arquivo de áudio aqui"
|
20
|
+
* @param props.selectAudioButtonText - Text for file selection button. Default: "Selecionar arquivo de áudio"
|
21
|
+
* @param props.changeAudioButtonText - Text for change file button. Default: "Trocar arquivo de áudio"
|
22
|
+
* @param props.onChange - Callback function called after successful upload with the file URL
|
23
|
+
* @param props.fileResponseName - Name of the URL field in server response. Default: "url"
|
24
|
+
* @param props.label - Optional label text to display above the upload area
|
25
|
+
* @param props.showAsterisk - Whether to show asterisk on label for required fields. Default: false
|
26
|
+
* @param props.disabled - Whether the upload is disabled. Default: false
|
27
|
+
* @param props.defaultValue - Default audio URL value
|
28
|
+
*
|
29
|
+
* @returns AudioUpload JSX element with drag & drop zone or audio preview
|
30
|
+
*
|
31
|
+
* @example
|
32
|
+
* ```tsx
|
33
|
+
* // Basic audio upload
|
34
|
+
* <AudioUpload
|
35
|
+
* name="audio"
|
36
|
+
* action="/api/upload"
|
37
|
+
* />
|
38
|
+
*
|
39
|
+
* // Audio upload with label and custom texts
|
40
|
+
* <AudioUpload
|
41
|
+
* name="podcast"
|
42
|
+
* action="/api/upload/podcast"
|
43
|
+
* label="Upload Podcast"
|
44
|
+
* showAsterisk
|
45
|
+
* selectAudioButtonText="Choose Audio File"
|
46
|
+
* dropAudioText="Drop your audio file here"
|
47
|
+
* changeAudioButtonText="Change Audio"
|
48
|
+
* />
|
49
|
+
*
|
50
|
+
* // Audio upload with callback and custom settings
|
51
|
+
* <AudioUpload
|
52
|
+
* name="recording"
|
53
|
+
* action="/api/upload"
|
54
|
+
* label="Voice Recording"
|
55
|
+
* acceptAudio="audio/mp3,audio/wav"
|
56
|
+
* onChange={(url) => console.log('Uploaded:', url)}
|
57
|
+
* fileResponseName="audioUrl"
|
58
|
+
* fileName="recording"
|
59
|
+
* method="PUT"
|
60
|
+
* />
|
61
|
+
*
|
62
|
+
* // Disabled audio upload with default value
|
63
|
+
* <AudioUpload
|
64
|
+
* name="preview"
|
65
|
+
* action="/api/upload"
|
66
|
+
* disabled
|
67
|
+
* defaultValue="/path/to/audio.mp3"
|
68
|
+
* label="Audio Preview"
|
69
|
+
* />
|
70
|
+
* ```
|
71
|
+
*/
|
72
|
+
function AudioUpload(props) {
|
73
|
+
const { name, label, fileName = "file", method = "POST", onChange, fileResponseName = "url", selectAudioButtonText = "Selecionar arquivo de áudio", dropAudioText = "Ou arraste e solte um arquivo de áudio aqui", changeAudioButtonText = "Trocar arquivo de áudio", acceptAudio = "audio/*", action, defaultValue = "", showAsterisk = false, disabled = false, } = props;
|
74
|
+
const { fieldErrors } = useForm();
|
75
|
+
const fieldError = fieldErrors?.[name];
|
76
|
+
const [value, setValue] = useState(defaultValue);
|
77
|
+
const [error, setError] = useState("");
|
78
|
+
const [file, setFile] = useState(null);
|
79
|
+
const [filePath, setFilePath] = useState(defaultValue);
|
80
|
+
const [isLoading, setIsLoading] = useState(false);
|
81
|
+
async function handleUploadAudio(file) {
|
82
|
+
if (disabled)
|
83
|
+
return;
|
84
|
+
setIsLoading(true);
|
85
|
+
setFile(file);
|
86
|
+
setError("");
|
87
|
+
const formData = new FormData();
|
88
|
+
formData.append(fileName, file);
|
89
|
+
await fetch(action, { method: method, body: formData })
|
90
|
+
.then(async (response) => await response.json())
|
91
|
+
.then((response) => {
|
92
|
+
if (!!response?.error)
|
93
|
+
setError(response.error);
|
94
|
+
else
|
95
|
+
setValue(response?.[fileResponseName]);
|
96
|
+
onChange && onChange(response?.[fileResponseName]);
|
97
|
+
})
|
98
|
+
.catch((error) => {
|
99
|
+
console.error(error);
|
100
|
+
setError("Erro ao enviar audio");
|
101
|
+
})
|
102
|
+
.finally(() => setIsLoading(false));
|
103
|
+
}
|
104
|
+
function handleSelectFile(file) {
|
105
|
+
if (disabled)
|
106
|
+
return;
|
107
|
+
if (file.type.indexOf("audio") === -1) {
|
108
|
+
setError("O arquivo selecionado não é um arquivo de áudio");
|
109
|
+
return;
|
110
|
+
}
|
111
|
+
setFilePath(URL.createObjectURL(file));
|
112
|
+
handleUploadAudio(file);
|
113
|
+
}
|
114
|
+
const errorMessage = fieldError || error;
|
115
|
+
const hasErrorClassName = errorMessage ? "hasError" : "noHasError";
|
116
|
+
const hasImageClassName = filePath ? "hasAudio" : "noHasAudio";
|
117
|
+
const className = `arkynAudioUpload ${hasErrorClassName} ${hasImageClassName}`;
|
118
|
+
return (_jsxs(FieldWrapper, { children: [label && _jsx(FieldLabel, { showAsterisk: showAsterisk, children: label }), _jsxs("div", { className: className, children: [_jsx("input", { type: "hidden", name: name, value: value || "" }), !filePath && (_jsx(NoFileContent, { disabled: disabled, isLoading: isLoading, acceptAudio: acceptAudio, dropAudioText: dropAudioText, handleSelectFile: handleSelectFile, selectAudioButtonText: selectAudioButtonText })), filePath && (_jsx(HasFileContent, { filePath: filePath, acceptAudio: acceptAudio, changeAudioButtonText: changeAudioButtonText, disabled: disabled, handleSelectFile: handleSelectFile, isLoading: isLoading, reSendAudio: !!errorMessage && file ? () => handleUploadAudio(file) : undefined }))] }), errorMessage && _jsx(FieldError, { children: errorMessage })] }));
|
119
|
+
}
|
120
|
+
export { AudioUpload };
|
@@ -0,0 +1,12 @@
|
|
1
|
+
import "./styles.css";
|
2
|
+
type NoFileContentProps = {
|
3
|
+
disabled: boolean;
|
4
|
+
acceptAudio: string;
|
5
|
+
isLoading: boolean;
|
6
|
+
selectAudioButtonText: string;
|
7
|
+
dropAudioText: string;
|
8
|
+
handleSelectFile: (file: File) => void;
|
9
|
+
};
|
10
|
+
declare function NoFileContent(props: NoFileContentProps): import("react/jsx-runtime").JSX.Element;
|
11
|
+
export { NoFileContent };
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/audioUpload/noFileContent/index.tsx"],"names":[],"mappings":"AAGA,OAAO,cAAc,CAAC;AAEtB,KAAK,kBAAkB,GAAG;IACxB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;CACxC,CAAC;AAEF,iBAAS,aAAa,CAAC,KAAK,EAAE,kBAAkB,2CAkD/C;AAED,OAAO,EAAE,aAAa,EAAE,CAAC"}
|
@@ -0,0 +1,29 @@
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
2
|
+
import { Button } from "../../button";
|
3
|
+
import "./styles.css";
|
4
|
+
function NoFileContent(props) {
|
5
|
+
const { dropAudioText, isLoading, acceptAudio, handleSelectFile, selectAudioButtonText, disabled, } = props;
|
6
|
+
function handleDrop(event) {
|
7
|
+
if (disabled)
|
8
|
+
return;
|
9
|
+
event.preventDefault();
|
10
|
+
const file = event.dataTransfer.files[0];
|
11
|
+
if (file)
|
12
|
+
handleSelectFile(file);
|
13
|
+
}
|
14
|
+
function handleClick() {
|
15
|
+
if (disabled)
|
16
|
+
return;
|
17
|
+
const input = document.createElement("input");
|
18
|
+
input.type = "file";
|
19
|
+
input.accept = acceptAudio;
|
20
|
+
input.onchange = (event) => {
|
21
|
+
const file = event.target.files?.[0];
|
22
|
+
if (file)
|
23
|
+
handleSelectFile(file);
|
24
|
+
};
|
25
|
+
input.click();
|
26
|
+
}
|
27
|
+
return (_jsxs("div", { onDrop: handleDrop, className: "arkynAudioUploadNoFileContent", children: [_jsx(Button, { isLoading: isLoading, onClick: handleClick, variant: "ghost", size: "sm", type: "button", disabled: disabled, children: selectAudioButtonText }), _jsx("p", { children: dropAudioText })] }));
|
28
|
+
}
|
29
|
+
export { NoFileContent };
|
@@ -0,0 +1,86 @@
|
|
1
|
+
type ClientOnlyProps = {
|
2
|
+
children(): React.ReactNode;
|
3
|
+
fallback?: React.ReactNode;
|
4
|
+
};
|
5
|
+
/**
|
6
|
+
* ClientOnly component - renders children only after hydration on the client side
|
7
|
+
*
|
8
|
+
* This component prevents hydration mismatches by rendering different content during SSR
|
9
|
+
* and after client-side hydration. It's useful for components that rely on browser APIs
|
10
|
+
* or need to render differently on server and client.
|
11
|
+
*
|
12
|
+
* @param props - ClientOnly component properties
|
13
|
+
* @param props.children - Function that returns React nodes to render after hydration
|
14
|
+
* @param props.fallback - Optional React node to render during SSR or before hydration
|
15
|
+
*
|
16
|
+
* @returns React fragment containing either fallback content or children based on hydration state
|
17
|
+
*
|
18
|
+
* @example
|
19
|
+
* ```tsx
|
20
|
+
* // Basic usage with loading fallback
|
21
|
+
* <ClientOnly fallback={<div>Loading...</div>}>
|
22
|
+
* {() => <InteractiveWidget />}
|
23
|
+
* </ClientOnly>
|
24
|
+
*
|
25
|
+
* // Client-only component without fallback
|
26
|
+
* <ClientOnly>
|
27
|
+
* {() => (
|
28
|
+
* <div>
|
29
|
+
* <p>This content only appears on the client</p>
|
30
|
+
* <p>Current time: {new Date().toLocaleString()}</p>
|
31
|
+
* </div>
|
32
|
+
* )}
|
33
|
+
* </ClientOnly>
|
34
|
+
*
|
35
|
+
* // Using with browser APIs
|
36
|
+
* <ClientOnly fallback={<div>Preparing location services...</div>}>
|
37
|
+
* {() => <GeolocationComponent />}
|
38
|
+
* </ClientOnly>
|
39
|
+
*
|
40
|
+
* // Complex interactive component
|
41
|
+
* <ClientOnly fallback={<StaticPlaceholder />}>
|
42
|
+
* {() => (
|
43
|
+
* <div>
|
44
|
+
* <Chart data={chartData} />
|
45
|
+
* <InteractiveControls />
|
46
|
+
* <RealtimeUpdates />
|
47
|
+
* </div>
|
48
|
+
* )}
|
49
|
+
* </ClientOnly>
|
50
|
+
*
|
51
|
+
* // Conditional rendering based on client capabilities
|
52
|
+
* <ClientOnly fallback={<BasicTable data={data} />}>
|
53
|
+
* {() => (
|
54
|
+
* <AdvancedDataGrid
|
55
|
+
* data={data}
|
56
|
+
* features={['sorting', 'filtering', 'virtualization']}
|
57
|
+
* />
|
58
|
+
* )}
|
59
|
+
* </ClientOnly>
|
60
|
+
*
|
61
|
+
* // Using with dynamic imports
|
62
|
+
* <ClientOnly fallback={<div>Loading editor...</div>}>
|
63
|
+
* {() => <LazyCodeEditor />}
|
64
|
+
* </ClientOnly>
|
65
|
+
*
|
66
|
+
* // Preventing layout shift
|
67
|
+
* <ClientOnly fallback={<div className="skeleton-loader" />}>
|
68
|
+
* {() => <UserDashboard />}
|
69
|
+
* </ClientOnly>
|
70
|
+
*
|
71
|
+
* // Multiple client-only sections
|
72
|
+
* <div>
|
73
|
+
* <Header />
|
74
|
+
* <ClientOnly fallback={<div>Loading navigation...</div>}>
|
75
|
+
* {() => <InteractiveNavigation />}
|
76
|
+
* </ClientOnly>
|
77
|
+
* <MainContent />
|
78
|
+
* <ClientOnly>
|
79
|
+
* {() => <ChatWidget />}
|
80
|
+
* </ClientOnly>
|
81
|
+
* </div>
|
82
|
+
* ```
|
83
|
+
*/
|
84
|
+
declare function ClientOnly(props: ClientOnlyProps): import("react/jsx-runtime").JSX.Element;
|
85
|
+
export { ClientOnly };
|
86
|
+
//# sourceMappingURL=clientOnly.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"clientOnly.d.ts","sourceRoot":"","sources":["../../src/components/clientOnly.tsx"],"names":[],"mappings":"AAEA,KAAK,eAAe,GAAG;IACrB,QAAQ,IAAI,KAAK,CAAC,SAAS,CAAC;IAC5B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8EG;AAEH,iBAAS,UAAU,CAAC,KAAK,EAAE,eAAe,2CAGzC;AAED,OAAO,EAAE,UAAU,EAAE,CAAC"}
|
@@ -0,0 +1,86 @@
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
2
|
+
import { useHydrated } from "../hooks/useHydrated";
|
3
|
+
/**
|
4
|
+
* ClientOnly component - renders children only after hydration on the client side
|
5
|
+
*
|
6
|
+
* This component prevents hydration mismatches by rendering different content during SSR
|
7
|
+
* and after client-side hydration. It's useful for components that rely on browser APIs
|
8
|
+
* or need to render differently on server and client.
|
9
|
+
*
|
10
|
+
* @param props - ClientOnly component properties
|
11
|
+
* @param props.children - Function that returns React nodes to render after hydration
|
12
|
+
* @param props.fallback - Optional React node to render during SSR or before hydration
|
13
|
+
*
|
14
|
+
* @returns React fragment containing either fallback content or children based on hydration state
|
15
|
+
*
|
16
|
+
* @example
|
17
|
+
* ```tsx
|
18
|
+
* // Basic usage with loading fallback
|
19
|
+
* <ClientOnly fallback={<div>Loading...</div>}>
|
20
|
+
* {() => <InteractiveWidget />}
|
21
|
+
* </ClientOnly>
|
22
|
+
*
|
23
|
+
* // Client-only component without fallback
|
24
|
+
* <ClientOnly>
|
25
|
+
* {() => (
|
26
|
+
* <div>
|
27
|
+
* <p>This content only appears on the client</p>
|
28
|
+
* <p>Current time: {new Date().toLocaleString()}</p>
|
29
|
+
* </div>
|
30
|
+
* )}
|
31
|
+
* </ClientOnly>
|
32
|
+
*
|
33
|
+
* // Using with browser APIs
|
34
|
+
* <ClientOnly fallback={<div>Preparing location services...</div>}>
|
35
|
+
* {() => <GeolocationComponent />}
|
36
|
+
* </ClientOnly>
|
37
|
+
*
|
38
|
+
* // Complex interactive component
|
39
|
+
* <ClientOnly fallback={<StaticPlaceholder />}>
|
40
|
+
* {() => (
|
41
|
+
* <div>
|
42
|
+
* <Chart data={chartData} />
|
43
|
+
* <InteractiveControls />
|
44
|
+
* <RealtimeUpdates />
|
45
|
+
* </div>
|
46
|
+
* )}
|
47
|
+
* </ClientOnly>
|
48
|
+
*
|
49
|
+
* // Conditional rendering based on client capabilities
|
50
|
+
* <ClientOnly fallback={<BasicTable data={data} />}>
|
51
|
+
* {() => (
|
52
|
+
* <AdvancedDataGrid
|
53
|
+
* data={data}
|
54
|
+
* features={['sorting', 'filtering', 'virtualization']}
|
55
|
+
* />
|
56
|
+
* )}
|
57
|
+
* </ClientOnly>
|
58
|
+
*
|
59
|
+
* // Using with dynamic imports
|
60
|
+
* <ClientOnly fallback={<div>Loading editor...</div>}>
|
61
|
+
* {() => <LazyCodeEditor />}
|
62
|
+
* </ClientOnly>
|
63
|
+
*
|
64
|
+
* // Preventing layout shift
|
65
|
+
* <ClientOnly fallback={<div className="skeleton-loader" />}>
|
66
|
+
* {() => <UserDashboard />}
|
67
|
+
* </ClientOnly>
|
68
|
+
*
|
69
|
+
* // Multiple client-only sections
|
70
|
+
* <div>
|
71
|
+
* <Header />
|
72
|
+
* <ClientOnly fallback={<div>Loading navigation...</div>}>
|
73
|
+
* {() => <InteractiveNavigation />}
|
74
|
+
* </ClientOnly>
|
75
|
+
* <MainContent />
|
76
|
+
* <ClientOnly>
|
77
|
+
* {() => <ChatWidget />}
|
78
|
+
* </ClientOnly>
|
79
|
+
* </div>
|
80
|
+
* ```
|
81
|
+
*/
|
82
|
+
function ClientOnly(props) {
|
83
|
+
const { children, fallback = null } = props;
|
84
|
+
return useHydrated() ? _jsx(_Fragment, { children: children() }) : _jsx(_Fragment, { children: fallback });
|
85
|
+
}
|
86
|
+
export { ClientOnly };
|
@@ -0,0 +1,13 @@
|
|
1
|
+
import "./styles.css";
|
2
|
+
type HasFileContentProps = {
|
3
|
+
disabled: boolean;
|
4
|
+
acceptFile: string;
|
5
|
+
isLoading: boolean;
|
6
|
+
changeFileButtonText: string;
|
7
|
+
file: File;
|
8
|
+
reSendFile?: () => void;
|
9
|
+
handleSelectFile: (file: File) => void;
|
10
|
+
};
|
11
|
+
declare function HasFileContent(props: HasFileContentProps): import("react/jsx-runtime").JSX.Element;
|
12
|
+
export { HasFileContent };
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/fileUpload/hasFileContent/index.tsx"],"names":[],"mappings":"AAaA,OAAO,cAAc,CAAC;AAEtB,KAAK,mBAAmB,GAAG;IACzB,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,IAAI,EAAE,IAAI,CAAC;IACX,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,gBAAgB,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;CACxC,CAAC;AAEF,iBAAS,cAAc,CAAC,KAAK,EAAE,mBAAmB,2CAyEjD;AAED,OAAO,EAAE,cAAc,EAAE,CAAC"}
|
@@ -0,0 +1,34 @@
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
2
|
+
import { File, FileArchive, FileAudio, FileImage, RefreshCw, } from "lucide-react";
|
3
|
+
import { Button } from "../../button";
|
4
|
+
import { Divider } from "../../divider";
|
5
|
+
import { IconButton } from "../../iconButton";
|
6
|
+
import { Tooltip } from "../../tooltip";
|
7
|
+
import "./styles.css";
|
8
|
+
function HasFileContent(props) {
|
9
|
+
const { disabled, file, isLoading, acceptFile, changeFileButtonText, handleSelectFile, reSendFile, } = props;
|
10
|
+
function handleClick() {
|
11
|
+
if (disabled)
|
12
|
+
return;
|
13
|
+
const input = document.createElement("input");
|
14
|
+
input.type = "file";
|
15
|
+
input.accept = acceptFile;
|
16
|
+
input.onchange = (event) => {
|
17
|
+
const file = event.target.files?.[0];
|
18
|
+
if (file)
|
19
|
+
handleSelectFile(file);
|
20
|
+
};
|
21
|
+
input.click();
|
22
|
+
}
|
23
|
+
function FileIcon() {
|
24
|
+
if (file.type.startsWith("image/"))
|
25
|
+
return _jsx(FileImage, {});
|
26
|
+
if (file.type.startsWith("audio/"))
|
27
|
+
return _jsx(FileAudio, {});
|
28
|
+
if (file.type.startsWith("application/zip"))
|
29
|
+
return _jsx(FileArchive, {});
|
30
|
+
return _jsx(File, {});
|
31
|
+
}
|
32
|
+
return (_jsxs("div", { className: "arkynFileUploadHasFileContent", children: [_jsxs("section", { className: "arkynFileUploadFileContainer", children: [_jsx(FileIcon, {}), _jsx("p", { children: file.name })] }), _jsx(Divider, {}), _jsxs("div", { className: "arkynFileUploadButtonsContainer", children: [!!reSendFile && (_jsx(Tooltip, { orientation: "bottom", text: "Reenviar arquivo", children: _jsx(IconButton, { type: "button", "aria-label": "resend file", variant: "outline", scheme: "danger", size: "sm", isLoading: isLoading, onClick: reSendFile, icon: RefreshCw, disabled: disabled }) })), _jsx(Button, { isLoading: isLoading, onClick: handleClick, variant: "outline", size: "sm", type: "button", disabled: disabled, children: changeFileButtonText })] })] }));
|
33
|
+
}
|
34
|
+
export { HasFileContent };
|
@@ -0,0 +1,94 @@
|
|
1
|
+
import "./styles.css";
|
2
|
+
type FileUploadProps = {
|
3
|
+
name: string;
|
4
|
+
action: string;
|
5
|
+
disabled?: boolean;
|
6
|
+
label?: string;
|
7
|
+
showAsterisk?: boolean;
|
8
|
+
changeFileButtonText?: string;
|
9
|
+
selectFileButtonText?: string;
|
10
|
+
dropFileText?: string;
|
11
|
+
method?: string;
|
12
|
+
fileName?: string;
|
13
|
+
fileResponseName?: string;
|
14
|
+
acceptFile?: string;
|
15
|
+
onChange?: (url?: string) => void;
|
16
|
+
};
|
17
|
+
/**
|
18
|
+
* FileUpload component - used for uploading files with drag and drop functionality
|
19
|
+
*
|
20
|
+
* @param props - FileUpload component properties
|
21
|
+
* @param props.name - Required field name for form handling
|
22
|
+
* @param props.action - Required endpoint URL where the file will be uploaded
|
23
|
+
* @param props.disabled - Whether the file upload is disabled. Default: false
|
24
|
+
* @param props.label - Optional label text to display above the file upload area
|
25
|
+
* @param props.showAsterisk - Whether to show asterisk on label for required fields. Default: false
|
26
|
+
* @param props.changeFileButtonText - Text for the button to change/replace an uploaded file. Default: "Alterar arquivo"
|
27
|
+
* @param props.selectFileButtonText - Text for the button to select a file. Default: "Selecionar arquivo"
|
28
|
+
* @param props.dropFileText - Text displayed in the drop zone area. Default: "Ou arraste e solte o arquivo aqui"
|
29
|
+
* @param props.method - HTTP method for the upload request. Default: "POST"
|
30
|
+
* @param props.fileName - Form data field name for the file. Default: "file"
|
31
|
+
* @param props.fileResponseName - Property name in the response object containing the file URL. Default: "url"
|
32
|
+
* @param props.acceptFile - File types accepted by the input (e.g., "image/*", ".pdf"). Default: "*"
|
33
|
+
* @param props.onChange - Callback function called when file upload completes successfully, receives the file URL
|
34
|
+
*
|
35
|
+
* @returns FileUpload JSX element wrapped in FieldGroup with optional label and error handling
|
36
|
+
*
|
37
|
+
* @example
|
38
|
+
* ```tsx
|
39
|
+
* // Basic file upload
|
40
|
+
* <FileUpload
|
41
|
+
* name="document"
|
42
|
+
* action="/api/upload"
|
43
|
+
* />
|
44
|
+
*
|
45
|
+
* // File upload with label and custom text
|
46
|
+
* <FileUpload
|
47
|
+
* name="avatar"
|
48
|
+
* action="/api/upload/avatar"
|
49
|
+
* label="Profile Picture"
|
50
|
+
* showAsterisk
|
51
|
+
* selectFileButtonText="Choose Image"
|
52
|
+
* changeFileButtonText="Change Image"
|
53
|
+
* dropFileText="Drop your image here"
|
54
|
+
* />
|
55
|
+
*
|
56
|
+
* // File upload with restrictions and callback
|
57
|
+
* <FileUpload
|
58
|
+
* name="pdf"
|
59
|
+
* action="/api/upload/document"
|
60
|
+
* label="Upload PDF Document"
|
61
|
+
* acceptFile=".pdf"
|
62
|
+
* fileName="document"
|
63
|
+
* fileResponseName="documentUrl"
|
64
|
+
* onChange={(url) => console.log('File uploaded:', url)}
|
65
|
+
* />
|
66
|
+
*
|
67
|
+
* // Disabled file upload
|
68
|
+
* <FileUpload
|
69
|
+
* name="attachment"
|
70
|
+
* action="/api/upload"
|
71
|
+
* label="Attachment"
|
72
|
+
* disabled
|
73
|
+
* />
|
74
|
+
*
|
75
|
+
* // File upload with custom HTTP method and response handling
|
76
|
+
* <FileUpload
|
77
|
+
* name="file"
|
78
|
+
* action="/api/files"
|
79
|
+
* method="PUT"
|
80
|
+
* fileName="uploadedFile"
|
81
|
+
* fileResponseName="fileUrl"
|
82
|
+
* label="Custom Upload"
|
83
|
+
* onChange={(url) => {
|
84
|
+
* if (url) {
|
85
|
+
* setFileUrl(url);
|
86
|
+
* console.log('Upload successful:', url);
|
87
|
+
* }
|
88
|
+
* }}
|
89
|
+
* />
|
90
|
+
* ```
|
91
|
+
*/
|
92
|
+
declare function FileUpload(props: FileUploadProps): import("react/jsx-runtime").JSX.Element;
|
93
|
+
export { FileUpload };
|
94
|
+
//# sourceMappingURL=index.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/fileUpload/index.tsx"],"names":[],"mappings":"AASA,OAAO,cAAc,CAAC;AAEtB,KAAK,eAAe,GAAG;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IAEf,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0EG;AAEH,iBAAS,UAAU,CAAC,KAAK,EAAE,eAAe,2CAgGzC;AAED,OAAO,EAAE,UAAU,EAAE,CAAC"}
|
@@ -0,0 +1,127 @@
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
2
|
+
import { useState } from "react";
|
3
|
+
import { useForm } from "../../hooks/useForm";
|
4
|
+
import { FieldError } from "../fieldError";
|
5
|
+
import { FieldLabel } from "../fieldLabel";
|
6
|
+
import { FieldWrapper } from "../fieldWrapper";
|
7
|
+
import { HasFileContent } from "./hasFileContent";
|
8
|
+
import { NoFileContent } from "./noFileContent";
|
9
|
+
import "./styles.css";
|
10
|
+
/**
|
11
|
+
* FileUpload component - used for uploading files with drag and drop functionality
|
12
|
+
*
|
13
|
+
* @param props - FileUpload component properties
|
14
|
+
* @param props.name - Required field name for form handling
|
15
|
+
* @param props.action - Required endpoint URL where the file will be uploaded
|
16
|
+
* @param props.disabled - Whether the file upload is disabled. Default: false
|
17
|
+
* @param props.label - Optional label text to display above the file upload area
|
18
|
+
* @param props.showAsterisk - Whether to show asterisk on label for required fields. Default: false
|
19
|
+
* @param props.changeFileButtonText - Text for the button to change/replace an uploaded file. Default: "Alterar arquivo"
|
20
|
+
* @param props.selectFileButtonText - Text for the button to select a file. Default: "Selecionar arquivo"
|
21
|
+
* @param props.dropFileText - Text displayed in the drop zone area. Default: "Ou arraste e solte o arquivo aqui"
|
22
|
+
* @param props.method - HTTP method for the upload request. Default: "POST"
|
23
|
+
* @param props.fileName - Form data field name for the file. Default: "file"
|
24
|
+
* @param props.fileResponseName - Property name in the response object containing the file URL. Default: "url"
|
25
|
+
* @param props.acceptFile - File types accepted by the input (e.g., "image/*", ".pdf"). Default: "*"
|
26
|
+
* @param props.onChange - Callback function called when file upload completes successfully, receives the file URL
|
27
|
+
*
|
28
|
+
* @returns FileUpload JSX element wrapped in FieldGroup with optional label and error handling
|
29
|
+
*
|
30
|
+
* @example
|
31
|
+
* ```tsx
|
32
|
+
* // Basic file upload
|
33
|
+
* <FileUpload
|
34
|
+
* name="document"
|
35
|
+
* action="/api/upload"
|
36
|
+
* />
|
37
|
+
*
|
38
|
+
* // File upload with label and custom text
|
39
|
+
* <FileUpload
|
40
|
+
* name="avatar"
|
41
|
+
* action="/api/upload/avatar"
|
42
|
+
* label="Profile Picture"
|
43
|
+
* showAsterisk
|
44
|
+
* selectFileButtonText="Choose Image"
|
45
|
+
* changeFileButtonText="Change Image"
|
46
|
+
* dropFileText="Drop your image here"
|
47
|
+
* />
|
48
|
+
*
|
49
|
+
* // File upload with restrictions and callback
|
50
|
+
* <FileUpload
|
51
|
+
* name="pdf"
|
52
|
+
* action="/api/upload/document"
|
53
|
+
* label="Upload PDF Document"
|
54
|
+
* acceptFile=".pdf"
|
55
|
+
* fileName="document"
|
56
|
+
* fileResponseName="documentUrl"
|
57
|
+
* onChange={(url) => console.log('File uploaded:', url)}
|
58
|
+
* />
|
59
|
+
*
|
60
|
+
* // Disabled file upload
|
61
|
+
* <FileUpload
|
62
|
+
* name="attachment"
|
63
|
+
* action="/api/upload"
|
64
|
+
* label="Attachment"
|
65
|
+
* disabled
|
66
|
+
* />
|
67
|
+
*
|
68
|
+
* // File upload with custom HTTP method and response handling
|
69
|
+
* <FileUpload
|
70
|
+
* name="file"
|
71
|
+
* action="/api/files"
|
72
|
+
* method="PUT"
|
73
|
+
* fileName="uploadedFile"
|
74
|
+
* fileResponseName="fileUrl"
|
75
|
+
* label="Custom Upload"
|
76
|
+
* onChange={(url) => {
|
77
|
+
* if (url) {
|
78
|
+
* setFileUrl(url);
|
79
|
+
* console.log('Upload successful:', url);
|
80
|
+
* }
|
81
|
+
* }}
|
82
|
+
* />
|
83
|
+
* ```
|
84
|
+
*/
|
85
|
+
function FileUpload(props) {
|
86
|
+
const { name, label, showAsterisk = false, action, fileName = "file", method = "POST", acceptFile = "*", fileResponseName = "url", changeFileButtonText = "Alterar arquivo", selectFileButtonText = "Selecionar arquivo", dropFileText = "Ou arraste e solte o arquivo aqui", onChange, disabled = false, } = props;
|
87
|
+
const { fieldErrors } = useForm();
|
88
|
+
const fieldError = fieldErrors?.[name];
|
89
|
+
const [value, setValue] = useState("");
|
90
|
+
const [error, setError] = useState("");
|
91
|
+
const [file, setFile] = useState(null);
|
92
|
+
const [isLoading, setIsLoading] = useState(false);
|
93
|
+
async function handleUploadFile(file) {
|
94
|
+
if (disabled)
|
95
|
+
return;
|
96
|
+
setIsLoading(true);
|
97
|
+
setFile(file);
|
98
|
+
setError("");
|
99
|
+
const formData = new FormData();
|
100
|
+
formData.append(fileName, file);
|
101
|
+
await fetch(action, { method: method, body: formData })
|
102
|
+
.then(async (response) => await response.json())
|
103
|
+
.then((response) => {
|
104
|
+
if (!!response?.error)
|
105
|
+
setError(response.error);
|
106
|
+
else
|
107
|
+
setValue(response?.[fileResponseName]);
|
108
|
+
onChange && onChange(response?.[fileResponseName]);
|
109
|
+
})
|
110
|
+
.catch((error) => {
|
111
|
+
console.error(error);
|
112
|
+
setError("Erro ao enviar o arquivo");
|
113
|
+
})
|
114
|
+
.finally(() => setIsLoading(false));
|
115
|
+
}
|
116
|
+
function handleSelectFile(file) {
|
117
|
+
if (disabled)
|
118
|
+
return;
|
119
|
+
handleUploadFile(file);
|
120
|
+
}
|
121
|
+
const errorMessage = fieldError || error;
|
122
|
+
const hasErrorClassName = errorMessage ? "hasError" : "noHasError";
|
123
|
+
const hasFileClassName = file ? "hasFile" : "noHasFile";
|
124
|
+
const className = `arkynFileUpload ${hasErrorClassName} ${hasFileClassName}`;
|
125
|
+
return (_jsxs(FieldWrapper, { children: [label && _jsx(FieldLabel, { showAsterisk: showAsterisk, children: label }), _jsxs("div", { className: className, children: [_jsx("input", { type: "hidden", name: name, value: value || "" }), !file && (_jsx(NoFileContent, { disabled: disabled, isLoading: isLoading, acceptFile: acceptFile, dropFileText: dropFileText, handleSelectFile: handleSelectFile, selectFileButtonText: selectFileButtonText })), file && (_jsx(HasFileContent, { disabled: disabled, isLoading: isLoading, acceptFile: acceptFile, file: file, handleSelectFile: handleSelectFile, changeFileButtonText: changeFileButtonText, reSendFile: !!errorMessage && file ? () => handleUploadFile(file) : undefined }))] }), errorMessage && _jsx(FieldError, { children: errorMessage })] }));
|
126
|
+
}
|
127
|
+
export { FileUpload };
|
@@ -0,0 +1,12 @@
|
|
1
|
+
import "./styles.css";
|
2
|
+
type NoFileContentProps = {
|
3
|
+
disabled: boolean;
|
4
|
+
acceptFile: string;
|
5
|
+
isLoading: boolean;
|
6
|
+
selectFileButtonText: string;
|
7
|
+
dropFileText: string;
|
8
|
+
handleSelectFile: (file: File) => void;
|
9
|
+
};
|
10
|
+
declare function NoFileContent(props: NoFileContentProps): import("react/jsx-runtime").JSX.Element;
|
11
|
+
export { NoFileContent };
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/fileUpload/noFileContent/index.tsx"],"names":[],"mappings":"AAIA,OAAO,cAAc,CAAC;AAEtB,KAAK,kBAAkB,GAAG;IACxB,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;CACxC,CAAC;AAEF,iBAAS,aAAa,CAAC,KAAK,EAAE,kBAAkB,2CAkD/C;AAED,OAAO,EAAE,aAAa,EAAE,CAAC"}
|