@ws-serenity/react-attachments v1.0.6
@ws-serenity/react-attachments
TODO
В общем. Поместить запросы в либу. И сделать сетап для них подобный тому,
как работают api-requests. Его один раз делаешь и все. Нужно будет передать просто api туда,
а возвращаем мы уже AttachmentApi
с getAll(ids)
.
А в компоненте мы все же не будем по умолчанию использовать их.
Пусть пропсом передается initial
с промисом:
<AttachmentContainer
customDragComponent={<CustomActiveDrag />}
className={'sample-attachment-container'}
showAttachedFiles={true}
uploadComponent={CustomUploadComponent}
handleSubmit={filesRef}
initialAttachments={attachmentApi.getAll(ids)}
// интерфейсом мы ограничим наличие "getAll", здесь он нам больше не нужен будет
attachmentApi={attachmentsApi}
downloadComponent={DownloadButton}
deleteComponent={DeleteButton}
/>;
// inside useAttachmentDataHandler
useEffect(()=>{
initialAttachments.then(resp=>setApiAttachments(resp.items))
},[])
About
Концепция - максимально настраиваемый без лишних стилей. Не подходит по дизайну? Используй вспомогательные хуки и настрой самостоятельно!
Компонент не создает самостоятельно аттачменты. Но удаляет существующие (над этим стоит еще подумать). Поэтому можно сказать, что им полностью управляет внешняя форма.
Иными словами, всегда хранится два состояния:
- Что пришло с API
- Что добавил пользователь, но еще не отправил
Если это необходимо, можно будет создать настройку этого поведения.
Отправка формы аттачментов
Необходимо выполнять "вручную". Это сделано, чтобы лишний раз не нагружать сеть при удалении/добавлении элементов. Запросы отправляются параллельно.
Пример:
export function SomeFormWithAttachments(){
const filesRef = useExtractApiData();
async function handleSubmit(e: any) {
e.preventDefault();
if (!filesRef.current) return;
// make component send create requests
const files = await filesRef.current.extract();
// now u can submit form with attachmentIds
}
return (
<form
action={'#'}
className={'test-container'}
onSubmit={handleSubmit}
>
<AttachmentContainer
customDragComponent={<CustomActiveDrag/>}
className={'sample-attachment-container'}
showAttachedFiles={true}
handleSubmit={filesRef}
uploadComponent={CustomUploadComponent}
attachmentApi={attachmentsApi}
downloadComponent={DownloadButton}
deleteComponent={DeleteButton}
/>
<button className={'test-container__submit'}>
Submit
</button>
</form>
);
}
// You can override default Component on active drag (if it's enabled)
const CustomActiveDrag = () => (
<div className={'custom-active-drop'}>
<p>Drop your files here</p>
<UploadIcon/>
</div>
);
// You must define buttons to delete and remove attachment if u want to use built-in AttachmentItem-component
// You can define your own behaviour using "AttachmentCustomItem" type
const DownloadButton = (props: ActionProps) => (
<button
type={'button'}
onClick={props.onClick}
className={clsx(props.className, 'sample-attachment-container__attachment-button')}
>
<DownloadIcon/>
</button>
);
const DeleteButton = (props: ActionProps) => (
<button
type={'button'}
onClick={props.onClick}
className={clsx(props.className, 'sample-attachment-container__attachment-button')}
>
<DeleteIcon/>
</button>
);
// U can also define custom component to upload files.
// It's displayed when component is empty or user can upload more files
// You can manage It's behaviour using css-styling. Component has to state-classes (read further)
const CustomUploadComponent = (props:UploadComponentProps) => (
<div onClick={props.handleUploadClick} className={props.className}>
<p>Drop your files here</p>
</div>
)
State-styles
- Когда компонент не содержит вложений, он имеет стиль:
ws-attachment-container--empty
- При активном drag-and-drop добавляется
ws-attachments-container--drag-active
В большинстве случаев, следует добавлять классы, передаваемые в пропсы к кастомным компонентам. Они могут содержать важные стили для состояния.
Limitations
Пока что все кастомные JSX-элементы (JSXElementConstructor<Props>
) не могут иметь каких-либо
дополнительных пропсов, что сильно ограничивает их функционал. Вскоре планируется добавить