summaryrefslogtreecommitdiff
path: root/packages/web-util/src/forms/InputFile.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'packages/web-util/src/forms/InputFile.tsx')
-rw-r--r--packages/web-util/src/forms/InputFile.tsx67
1 files changed, 50 insertions, 17 deletions
diff --git a/packages/web-util/src/forms/InputFile.tsx b/packages/web-util/src/forms/InputFile.tsx
index 6337d0902..cd0a96d1c 100644
--- a/packages/web-util/src/forms/InputFile.tsx
+++ b/packages/web-util/src/forms/InputFile.tsx
@@ -1,5 +1,6 @@
import { Fragment, VNode, h } from "preact";
import { UIFormProps } from "./FormProvider.js";
+import { noHandlerPropsAndNoContextForField } from "./InputArray.js";
import { LabelWithTooltipMaybeRequired } from "./InputLine.js";
import { useField } from "./useField.js";
@@ -7,20 +8,36 @@ export function InputFile<T extends object, K extends keyof T>(
props: { maxBites: number; accept?: string } & UIFormProps<T, K>,
): VNode {
const {
- name,
label,
- placeholder,
tooltip,
required,
help: propsHelp,
maxBites,
accept,
} = props;
- const { value, onChange, state } = useField<T, K>(name);
- const help = propsHelp ?? state.help
+ //FIXME: remove deprecated
+ const fieldCtx = useField<T, K>(props.name);
+ const { value, onChange, state } =
+ props.handler ?? fieldCtx ?? noHandlerPropsAndNoContextForField(props.name);
+
+ const help = propsHelp ?? state.help;
if (state.hidden) {
return <div />;
}
+
+ const valueStr = !value ? "" : value.toString();
+ const firstColon = valueStr.indexOf(";");
+
+ const { fileName, dataUri } = valueStr.startsWith("file:")
+ ? {
+ fileName: valueStr.substring(5, firstColon),
+ dataUri: valueStr.substring(firstColon + 1),
+ }
+ : {
+ fileName: "",
+ dataUri: valueStr,
+ };
+
return (
<div class="col-span-full">
<LabelWithTooltipMaybeRequired
@@ -28,7 +45,7 @@ export function InputFile<T extends object, K extends keyof T>(
tooltip={tooltip}
required={required}
/>
- {!value || !(value as string).startsWith("data:image/") ? (
+ {!dataUri ? (
<div class="mt-2 flex justify-center rounded-lg border border-dashed border-gray-900/25 py-1">
<div class="text-center">
<svg
@@ -43,16 +60,15 @@ export function InputFile<T extends object, K extends keyof T>(
clip-rule="evenodd"
/>
</svg>
- {!state.disabled &&
+ {!state.disabled && (
<div class="my-2 flex text-sm leading-6 text-gray-600">
<label
- for="file-upload"
+ for={String(props.name)}
class="relative cursor-pointer rounded-md bg-white font-semibold text-indigo-600 focus-within:outline-none focus-within:ring-2 focus-within:ring-indigo-600 focus-within:ring-offset-2 hover:text-indigo-500"
>
<span>Upload a file</span>
<input
- id="file-upload"
- name="file-upload"
+ id={String(props.name)}
type="file"
class="sr-only"
accept={accept}
@@ -64,6 +80,7 @@ export function InputFile<T extends object, K extends keyof T>(
if (f[0].size > maxBites) {
return onChange(undefined!);
}
+ const fileName = f[0].name;
return f[0].arrayBuffer().then((b) => {
const b64 = window.btoa(
new Uint8Array(b).reduce(
@@ -71,24 +88,40 @@ export function InputFile<T extends object, K extends keyof T>(
"",
),
);
- return onChange(`data:${f[0].type};base64,${b64}` as any);
+ if (fileName) {
+ return onChange(
+ `file:${fileName};data:${f[0].type};base64,${b64}` as any,
+ );
+ } else {
+ return onChange(
+ `data:${f[0].type};base64,${b64}` as any,
+ );
+ }
});
}}
/>
</label>
{/* <p class="pl-1">or drag and drop</p> */}
</div>
- }
+ )}
</div>
</div>
) : (
<div class="mt-2 flex justify-center rounded-lg border border-dashed border-gray-900/25 relative">
- <img
- src={value as string}
- class=" h-24 w-full object-cover relative"
- />
+ {(dataUri as string).startsWith("data:image/") ? (
+ <img src={dataUri} class=" h-24 w-full object-cover relative" />
+ ) : (
+ <div />
+ )}
+ {fileName ? (
+ <div class="absolute rounded-lg border flex justify-center text-xl items-center text-white ">
+ {fileName}
+ </div>
+ ) : (
+ <Fragment />
+ )}
- {!state.disabled &&
+ {!state.disabled && (
<div
class="opacity-0 hover:opacity-70 duration-300 absolute rounded-lg border inset-0 z-10 flex justify-center text-xl items-center bg-black text-white cursor-pointer "
onClick={() => {
@@ -97,7 +130,7 @@ export function InputFile<T extends object, K extends keyof T>(
>
Clear
</div>
- }
+ )}
</div>
)}
{help && <p class="text-xs leading-5 text-gray-600 mt-2">{help}</p>}