sforkowany z mirror/soapbox
Move form hooks into their own files
rodzic
eb055339d8
commit
f3727440ff
|
@ -1,13 +1,13 @@
|
|||
import clsx from 'clsx';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
||||
|
||||
import Icon from 'soapbox/components/icon';
|
||||
import { Avatar, Button, Column, Form, FormActions, FormGroup, HStack, Input, Spinner, Text, Textarea } from 'soapbox/components/ui';
|
||||
import { useAppSelector, useInstance } from 'soapbox/hooks';
|
||||
import { useGroup, useUpdateGroup } from 'soapbox/hooks/api';
|
||||
import { useImageField, useTextField } from 'soapbox/hooks/forms';
|
||||
import { isDefaultAvatar, isDefaultHeader } from 'soapbox/utils/accounts';
|
||||
import resizeImage from 'soapbox/utils/resize-image';
|
||||
|
||||
import type { List as ImmutableList } from 'immutable';
|
||||
|
||||
|
@ -178,61 +178,4 @@ const EditGroup: React.FC<IEditGroup> = ({ params: { id: groupId } }) => {
|
|||
);
|
||||
};
|
||||
|
||||
function usePreview(file: File | null | undefined): string | undefined {
|
||||
return useMemo(() => {
|
||||
if (file) {
|
||||
return URL.createObjectURL(file);
|
||||
}
|
||||
}, [file]);
|
||||
}
|
||||
|
||||
function useTextField(initialValue: string | undefined) {
|
||||
const [value, setValue] = useState(initialValue);
|
||||
const hasInitialValue = typeof initialValue === 'string';
|
||||
|
||||
const onChange: React.ChangeEventHandler<HTMLInputElement | HTMLTextAreaElement> = (e) => {
|
||||
setValue(e.target.value);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (hasInitialValue) {
|
||||
setValue(initialValue);
|
||||
}
|
||||
}, [hasInitialValue]);
|
||||
|
||||
return {
|
||||
value,
|
||||
onChange,
|
||||
};
|
||||
}
|
||||
|
||||
interface UseImageFieldOpts {
|
||||
maxPixels?: number
|
||||
preview?: string
|
||||
}
|
||||
|
||||
function useImageField(opts: UseImageFieldOpts = {}) {
|
||||
const [file, setFile] = useState<File>();
|
||||
const src = usePreview(file) || opts.preview;
|
||||
|
||||
const onChange: React.ChangeEventHandler<HTMLInputElement> = ({ target: { files } }) => {
|
||||
const file = files?.item(0) || undefined;
|
||||
if (file) {
|
||||
if (typeof opts.maxPixels === 'number') {
|
||||
resizeImage(file, opts.maxPixels)
|
||||
.then((f) => setFile(f))
|
||||
.catch(console.error);
|
||||
} else {
|
||||
setFile(file);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
src,
|
||||
file,
|
||||
onChange,
|
||||
};
|
||||
}
|
||||
|
||||
export default EditGroup;
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
export { useImageField } from './useImageField';
|
||||
export { useTextField } from './useTextField';
|
||||
export { usePreview } from './usePreview';
|
|
@ -0,0 +1,40 @@
|
|||
import { useState } from 'react';
|
||||
|
||||
import resizeImage from 'soapbox/utils/resize-image';
|
||||
|
||||
import { usePreview } from './usePreview';
|
||||
|
||||
interface UseImageFieldOpts {
|
||||
/** Resize the image to the max dimensions, if defined. */
|
||||
maxPixels?: number
|
||||
/** Fallback URL before a file is uploaded. */
|
||||
preview?: string
|
||||
}
|
||||
|
||||
/** Handle image, and optionally resize it. */
|
||||
function useImageField(opts: UseImageFieldOpts = {}) {
|
||||
const [file, setFile] = useState<File>();
|
||||
const src = usePreview(file) || opts.preview;
|
||||
|
||||
const onChange: React.ChangeEventHandler<HTMLInputElement> = ({ target: { files } }) => {
|
||||
const file = files?.item(0) || undefined;
|
||||
if (file) {
|
||||
if (typeof opts.maxPixels === 'number') {
|
||||
resizeImage(file, opts.maxPixels)
|
||||
.then((f) => setFile(f))
|
||||
.catch(console.error);
|
||||
} else {
|
||||
setFile(file);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
src,
|
||||
file,
|
||||
onChange,
|
||||
};
|
||||
}
|
||||
|
||||
export { useImageField };
|
||||
export type { UseImageFieldOpts };
|
|
@ -0,0 +1,12 @@
|
|||
import { useMemo } from 'react';
|
||||
|
||||
/** Return a preview URL for a file. */
|
||||
function usePreview(file: File | null | undefined): string | undefined {
|
||||
return useMemo(() => {
|
||||
if (file) {
|
||||
return URL.createObjectURL(file);
|
||||
}
|
||||
}, [file]);
|
||||
}
|
||||
|
||||
export { usePreview };
|
|
@ -0,0 +1,23 @@
|
|||
import { useEffect, useState } from 'react';
|
||||
|
||||
function useTextField(initialValue: string | undefined) {
|
||||
const [value, setValue] = useState(initialValue);
|
||||
const hasInitialValue = typeof initialValue === 'string';
|
||||
|
||||
const onChange: React.ChangeEventHandler<HTMLInputElement | HTMLTextAreaElement> = (e) => {
|
||||
setValue(e.target.value);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (hasInitialValue) {
|
||||
setValue(initialValue);
|
||||
}
|
||||
}, [hasInitialValue]);
|
||||
|
||||
return {
|
||||
value,
|
||||
onChange,
|
||||
};
|
||||
}
|
||||
|
||||
export { useTextField };
|
Ładowanie…
Reference in New Issue