diff options
Diffstat (limited to 'packages/web-util/src/forms/InputFile.tsx')
-rw-r--r-- | packages/web-util/src/forms/InputFile.tsx | 67 |
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>} |