mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
perf(ui): split out gallery settings popover components
This was taking over 15ms (!) to render each time a setting changed, wtf
This commit is contained in:
parent
2b744480d6
commit
1468f4d37e
@ -1,172 +0,0 @@
|
|||||||
import type { ComboboxOption, FormLabelProps } from '@invoke-ai/ui-library';
|
|
||||||
import {
|
|
||||||
Checkbox,
|
|
||||||
Combobox,
|
|
||||||
CompositeSlider,
|
|
||||||
Divider,
|
|
||||||
Flex,
|
|
||||||
FormControl,
|
|
||||||
FormControlGroup,
|
|
||||||
FormLabel,
|
|
||||||
IconButton,
|
|
||||||
Popover,
|
|
||||||
PopoverBody,
|
|
||||||
PopoverContent,
|
|
||||||
PopoverTrigger,
|
|
||||||
Switch,
|
|
||||||
} from '@invoke-ai/ui-library';
|
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
|
||||||
import type { SingleValue } from 'chakra-react-select';
|
|
||||||
import {
|
|
||||||
alwaysShowImageSizeBadgeChanged,
|
|
||||||
autoAssignBoardOnClickChanged,
|
|
||||||
orderDirChanged,
|
|
||||||
setGalleryImageMinimumWidth,
|
|
||||||
shouldAutoSwitchChanged,
|
|
||||||
shouldShowArchivedBoardsChanged,
|
|
||||||
starredFirstChanged,
|
|
||||||
} from 'features/gallery/store/gallerySlice';
|
|
||||||
import type { ChangeEvent } from 'react';
|
|
||||||
import { memo, useCallback, useMemo } from 'react';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import { RiSettings4Fill } from 'react-icons/ri';
|
|
||||||
import { assert } from 'tsafe';
|
|
||||||
|
|
||||||
import BoardAutoAddSelect from './Boards/BoardAutoAddSelect';
|
|
||||||
|
|
||||||
const formLabelProps: FormLabelProps = {
|
|
||||||
flexGrow: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
const GallerySettingsPopover = () => {
|
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const galleryImageMinimumWidth = useAppSelector((s) => s.gallery.galleryImageMinimumWidth);
|
|
||||||
const shouldAutoSwitch = useAppSelector((s) => s.gallery.shouldAutoSwitch);
|
|
||||||
const autoAssignBoardOnClick = useAppSelector((s) => s.gallery.autoAssignBoardOnClick);
|
|
||||||
const alwaysShowImageSizeBadge = useAppSelector((s) => s.gallery.alwaysShowImageSizeBadge);
|
|
||||||
const shouldShowArchivedBoards = useAppSelector((s) => s.gallery.shouldShowArchivedBoards);
|
|
||||||
const orderDir = useAppSelector((s) => s.gallery.orderDir);
|
|
||||||
const starredFirst = useAppSelector((s) => s.gallery.starredFirst);
|
|
||||||
|
|
||||||
const handleChangeGalleryImageMinimumWidth = useCallback(
|
|
||||||
(v: number) => {
|
|
||||||
dispatch(setGalleryImageMinimumWidth(v));
|
|
||||||
},
|
|
||||||
[dispatch]
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleChangeAutoSwitch = useCallback(
|
|
||||||
(e: ChangeEvent<HTMLInputElement>) => {
|
|
||||||
dispatch(shouldAutoSwitchChanged(e.target.checked));
|
|
||||||
},
|
|
||||||
[dispatch]
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleChangeAutoAssignBoardOnClick = useCallback(
|
|
||||||
(e: ChangeEvent<HTMLInputElement>) => dispatch(autoAssignBoardOnClickChanged(e.target.checked)),
|
|
||||||
[dispatch]
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleChangeAlwaysShowImageSizeBadgeChanged = useCallback(
|
|
||||||
(e: ChangeEvent<HTMLInputElement>) => dispatch(alwaysShowImageSizeBadgeChanged(e.target.checked)),
|
|
||||||
[dispatch]
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleChangeShouldShowArchivedBoardsChanged = useCallback(
|
|
||||||
(e: ChangeEvent<HTMLInputElement>) => {
|
|
||||||
dispatch(shouldShowArchivedBoardsChanged(e.target.checked));
|
|
||||||
},
|
|
||||||
[dispatch]
|
|
||||||
);
|
|
||||||
|
|
||||||
const onChangeStarredFirst = useCallback(
|
|
||||||
(e: ChangeEvent<HTMLInputElement>) => {
|
|
||||||
dispatch(starredFirstChanged(e.target.checked));
|
|
||||||
},
|
|
||||||
[dispatch]
|
|
||||||
);
|
|
||||||
|
|
||||||
const orderDirOptions = useMemo<ComboboxOption[]>(
|
|
||||||
() => [
|
|
||||||
{ value: 'DESC', label: t('gallery.newestFirst') },
|
|
||||||
{ value: 'ASC', label: t('gallery.oldestFirst') },
|
|
||||||
],
|
|
||||||
[t]
|
|
||||||
);
|
|
||||||
|
|
||||||
const onChangeOrderDir = useCallback(
|
|
||||||
(v: SingleValue<ComboboxOption>) => {
|
|
||||||
assert(v?.value === 'ASC' || v?.value === 'DESC');
|
|
||||||
dispatch(orderDirChanged(v.value));
|
|
||||||
},
|
|
||||||
[dispatch]
|
|
||||||
);
|
|
||||||
|
|
||||||
const orderDirValue = useMemo(() => {
|
|
||||||
return orderDirOptions.find((opt) => opt.value === orderDir);
|
|
||||||
}, [orderDir, orderDirOptions]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Popover isLazy>
|
|
||||||
<PopoverTrigger>
|
|
||||||
<IconButton aria-label={t('gallery.gallerySettings')} size="sm" icon={<RiSettings4Fill />} />
|
|
||||||
</PopoverTrigger>
|
|
||||||
<PopoverContent>
|
|
||||||
<PopoverBody>
|
|
||||||
<Flex direction="column" gap={2}>
|
|
||||||
<FormControl>
|
|
||||||
<FormLabel>{t('gallery.galleryImageSize')}</FormLabel>
|
|
||||||
<CompositeSlider
|
|
||||||
value={galleryImageMinimumWidth}
|
|
||||||
onChange={handleChangeGalleryImageMinimumWidth}
|
|
||||||
min={45}
|
|
||||||
max={256}
|
|
||||||
defaultValue={90}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormControlGroup formLabelProps={formLabelProps}>
|
|
||||||
<FormControl>
|
|
||||||
<FormLabel>{t('gallery.autoSwitchNewImages')}</FormLabel>
|
|
||||||
<Checkbox isChecked={shouldAutoSwitch} onChange={handleChangeAutoSwitch} />
|
|
||||||
</FormControl>
|
|
||||||
<FormControl>
|
|
||||||
<FormLabel>{t('gallery.autoAssignBoardOnClick')}</FormLabel>
|
|
||||||
<Checkbox isChecked={autoAssignBoardOnClick} onChange={handleChangeAutoAssignBoardOnClick} />
|
|
||||||
</FormControl>
|
|
||||||
<FormControl>
|
|
||||||
<FormLabel>{t('gallery.alwaysShowImageSizeBadge')}</FormLabel>
|
|
||||||
<Checkbox isChecked={alwaysShowImageSizeBadge} onChange={handleChangeAlwaysShowImageSizeBadgeChanged} />
|
|
||||||
</FormControl>
|
|
||||||
<FormControl>
|
|
||||||
<FormLabel>{t('gallery.showArchivedBoards')}</FormLabel>
|
|
||||||
<Checkbox isChecked={shouldShowArchivedBoards} onChange={handleChangeShouldShowArchivedBoardsChanged} />
|
|
||||||
</FormControl>
|
|
||||||
</FormControlGroup>
|
|
||||||
<BoardAutoAddSelect />
|
|
||||||
<Divider />
|
|
||||||
<FormControl w="full">
|
|
||||||
<FormLabel flexGrow={1} m={0}>
|
|
||||||
{t('gallery.showStarredImagesFirst')}
|
|
||||||
</FormLabel>
|
|
||||||
<Switch size="sm" isChecked={starredFirst} onChange={onChangeStarredFirst} />
|
|
||||||
</FormControl>
|
|
||||||
<FormControl>
|
|
||||||
<FormLabel flexGrow={1} m={0}>
|
|
||||||
{t('gallery.sortDirection')}
|
|
||||||
</FormLabel>
|
|
||||||
<Combobox
|
|
||||||
isSearchable={false}
|
|
||||||
value={orderDirValue}
|
|
||||||
options={orderDirOptions}
|
|
||||||
onChange={onChangeOrderDir}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
</Flex>
|
|
||||||
</PopoverBody>
|
|
||||||
</PopoverContent>
|
|
||||||
</Popover>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default memo(GallerySettingsPopover);
|
|
@ -0,0 +1,26 @@
|
|||||||
|
import { Checkbox, FormControl, FormLabel } from '@invoke-ai/ui-library';
|
||||||
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { alwaysShowImageSizeBadgeChanged } from 'features/gallery/store/gallerySlice';
|
||||||
|
import type { ChangeEvent } from 'react';
|
||||||
|
import { memo, useCallback } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
const GallerySettingsPopover = () => {
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const alwaysShowImageSizeBadge = useAppSelector((s) => s.gallery.alwaysShowImageSizeBadge);
|
||||||
|
|
||||||
|
const onChange = useCallback(
|
||||||
|
(e: ChangeEvent<HTMLInputElement>) => dispatch(alwaysShowImageSizeBadgeChanged(e.target.checked)),
|
||||||
|
[dispatch]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormControl>
|
||||||
|
<FormLabel flexGrow={1}>{t('gallery.alwaysShowImageSizeBadge')}</FormLabel>
|
||||||
|
<Checkbox isChecked={alwaysShowImageSizeBadge} onChange={onChange} />
|
||||||
|
</FormControl>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(GallerySettingsPopover);
|
@ -0,0 +1,26 @@
|
|||||||
|
import { Checkbox, FormControl, FormLabel } from '@invoke-ai/ui-library';
|
||||||
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { autoAssignBoardOnClickChanged } from 'features/gallery/store/gallerySlice';
|
||||||
|
import type { ChangeEvent } from 'react';
|
||||||
|
import { memo, useCallback } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
const GallerySettingsPopover = () => {
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const autoAssignBoardOnClick = useAppSelector((s) => s.gallery.autoAssignBoardOnClick);
|
||||||
|
|
||||||
|
const onChange = useCallback(
|
||||||
|
(e: ChangeEvent<HTMLInputElement>) => dispatch(autoAssignBoardOnClickChanged(e.target.checked)),
|
||||||
|
[dispatch]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormControl>
|
||||||
|
<FormLabel flexGrow={1}>{t('gallery.autoAssignBoardOnClick')}</FormLabel>
|
||||||
|
<Checkbox isChecked={autoAssignBoardOnClick} onChange={onChange} />
|
||||||
|
</FormControl>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(GallerySettingsPopover);
|
@ -0,0 +1,28 @@
|
|||||||
|
import { Checkbox, FormControl, FormLabel } from '@invoke-ai/ui-library';
|
||||||
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { shouldAutoSwitchChanged } from 'features/gallery/store/gallerySlice';
|
||||||
|
import type { ChangeEvent } from 'react';
|
||||||
|
import { memo, useCallback } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
const GallerySettingsPopover = () => {
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const shouldAutoSwitch = useAppSelector((s) => s.gallery.shouldAutoSwitch);
|
||||||
|
|
||||||
|
const onChange = useCallback(
|
||||||
|
(e: ChangeEvent<HTMLInputElement>) => {
|
||||||
|
dispatch(shouldAutoSwitchChanged(e.target.checked));
|
||||||
|
},
|
||||||
|
[dispatch]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormControl>
|
||||||
|
<FormLabel flexGrow={1}>{t('gallery.autoSwitchNewImages')}</FormLabel>
|
||||||
|
<Checkbox isChecked={shouldAutoSwitch} onChange={onChange} />
|
||||||
|
</FormControl>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(GallerySettingsPopover);
|
@ -0,0 +1,41 @@
|
|||||||
|
import { Divider, Flex, IconButton, Popover, PopoverBody, PopoverContent, PopoverTrigger } from '@invoke-ai/ui-library';
|
||||||
|
import BoardAutoAddSelect from 'features/gallery/components/Boards/BoardAutoAddSelect';
|
||||||
|
import AlwaysShowImageSizeCheckbox from 'features/gallery/components/GallerySettingsPopover/AlwaysShowImageSizeCheckbox';
|
||||||
|
import AutoAssignBoardCheckbox from 'features/gallery/components/GallerySettingsPopover/AutoAssignBoardCheckbox';
|
||||||
|
import AutoSwitchCheckbox from 'features/gallery/components/GallerySettingsPopover/AutoSwitchCheckbox';
|
||||||
|
import ImageMinimumWidthSlider from 'features/gallery/components/GallerySettingsPopover/ImageMinimumWidthSlider';
|
||||||
|
import ShowArchivedBoardsCheckbox from 'features/gallery/components/GallerySettingsPopover/ShowArchivedBoardsCheckbox';
|
||||||
|
import ShowStarredFirstCheckbox from 'features/gallery/components/GallerySettingsPopover/ShowStarredFirstCheckbox';
|
||||||
|
import SortDirectionCombobox from 'features/gallery/components/GallerySettingsPopover/SortDirectionCombobox';
|
||||||
|
import { memo } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { RiSettings4Fill } from 'react-icons/ri';
|
||||||
|
|
||||||
|
const GallerySettingsPopover = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Popover isLazy>
|
||||||
|
<PopoverTrigger>
|
||||||
|
<IconButton aria-label={t('gallery.gallerySettings')} size="sm" icon={<RiSettings4Fill />} />
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent>
|
||||||
|
<PopoverBody>
|
||||||
|
<Flex direction="column" gap={2}>
|
||||||
|
<ImageMinimumWidthSlider />
|
||||||
|
<AutoSwitchCheckbox />
|
||||||
|
<AutoAssignBoardCheckbox />
|
||||||
|
<AlwaysShowImageSizeCheckbox />
|
||||||
|
<ShowArchivedBoardsCheckbox />
|
||||||
|
<BoardAutoAddSelect />
|
||||||
|
<Divider />
|
||||||
|
<ShowStarredFirstCheckbox />
|
||||||
|
<SortDirectionCombobox />
|
||||||
|
</Flex>
|
||||||
|
</PopoverBody>
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(GallerySettingsPopover);
|
@ -0,0 +1,26 @@
|
|||||||
|
import { CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library';
|
||||||
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { setGalleryImageMinimumWidth } from 'features/gallery/store/gallerySlice';
|
||||||
|
import { memo, useCallback } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
const GallerySettingsPopover = () => {
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const galleryImageMinimumWidth = useAppSelector((s) => s.gallery.galleryImageMinimumWidth);
|
||||||
|
|
||||||
|
const onChange = useCallback(
|
||||||
|
(v: number) => {
|
||||||
|
dispatch(setGalleryImageMinimumWidth(v));
|
||||||
|
},
|
||||||
|
[dispatch]
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<FormControl>
|
||||||
|
<FormLabel>{t('gallery.galleryImageSize')}</FormLabel>
|
||||||
|
<CompositeSlider value={galleryImageMinimumWidth} onChange={onChange} min={45} max={256} defaultValue={90} />
|
||||||
|
</FormControl>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(GallerySettingsPopover);
|
@ -0,0 +1,28 @@
|
|||||||
|
import { Checkbox, FormControl, FormLabel } from '@invoke-ai/ui-library';
|
||||||
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { shouldShowArchivedBoardsChanged } from 'features/gallery/store/gallerySlice';
|
||||||
|
import type { ChangeEvent } from 'react';
|
||||||
|
import { memo, useCallback } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
const GallerySettingsPopover = () => {
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const shouldShowArchivedBoards = useAppSelector((s) => s.gallery.shouldShowArchivedBoards);
|
||||||
|
|
||||||
|
const onChange = useCallback(
|
||||||
|
(e: ChangeEvent<HTMLInputElement>) => {
|
||||||
|
dispatch(shouldShowArchivedBoardsChanged(e.target.checked));
|
||||||
|
},
|
||||||
|
[dispatch]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormControl>
|
||||||
|
<FormLabel flexGrow={1}>{t('gallery.showArchivedBoards')}</FormLabel>
|
||||||
|
<Checkbox isChecked={shouldShowArchivedBoards} onChange={onChange} />
|
||||||
|
</FormControl>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(GallerySettingsPopover);
|
@ -0,0 +1,30 @@
|
|||||||
|
import { FormControl, FormLabel, Switch } from '@invoke-ai/ui-library';
|
||||||
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { starredFirstChanged } from 'features/gallery/store/gallerySlice';
|
||||||
|
import type { ChangeEvent } from 'react';
|
||||||
|
import { memo, useCallback } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
const GallerySettingsPopover = () => {
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const starredFirst = useAppSelector((s) => s.gallery.starredFirst);
|
||||||
|
|
||||||
|
const onChange = useCallback(
|
||||||
|
(e: ChangeEvent<HTMLInputElement>) => {
|
||||||
|
dispatch(starredFirstChanged(e.target.checked));
|
||||||
|
},
|
||||||
|
[dispatch]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormControl w="full">
|
||||||
|
<FormLabel flexGrow={1} m={0}>
|
||||||
|
{t('gallery.showStarredImagesFirst')}
|
||||||
|
</FormLabel>
|
||||||
|
<Switch size="sm" isChecked={starredFirst} onChange={onChange} />
|
||||||
|
</FormControl>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(GallerySettingsPopover);
|
@ -0,0 +1,45 @@
|
|||||||
|
import type { ComboboxOption } from '@invoke-ai/ui-library';
|
||||||
|
import { Combobox, FormControl, FormLabel } from '@invoke-ai/ui-library';
|
||||||
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import type { SingleValue } from 'chakra-react-select';
|
||||||
|
import { orderDirChanged } from 'features/gallery/store/gallerySlice';
|
||||||
|
import { memo, useCallback, useMemo } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { assert } from 'tsafe';
|
||||||
|
|
||||||
|
const GallerySettingsPopover = () => {
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const orderDir = useAppSelector((s) => s.gallery.orderDir);
|
||||||
|
|
||||||
|
const options = useMemo<ComboboxOption[]>(
|
||||||
|
() => [
|
||||||
|
{ value: 'DESC', label: t('gallery.newestFirst') },
|
||||||
|
{ value: 'ASC', label: t('gallery.oldestFirst') },
|
||||||
|
],
|
||||||
|
[t]
|
||||||
|
);
|
||||||
|
|
||||||
|
const onChange = useCallback(
|
||||||
|
(v: SingleValue<ComboboxOption>) => {
|
||||||
|
assert(v?.value === 'ASC' || v?.value === 'DESC');
|
||||||
|
dispatch(orderDirChanged(v.value));
|
||||||
|
},
|
||||||
|
[dispatch]
|
||||||
|
);
|
||||||
|
|
||||||
|
const value = useMemo(() => {
|
||||||
|
return options.find((opt) => opt.value === orderDir);
|
||||||
|
}, [orderDir, options]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormControl>
|
||||||
|
<FormLabel flexGrow={1} m={0}>
|
||||||
|
{t('gallery.sortDirection')}
|
||||||
|
</FormLabel>
|
||||||
|
<Combobox isSearchable={false} value={value} options={options} onChange={onChange} />
|
||||||
|
</FormControl>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(GallerySettingsPopover);
|
@ -10,7 +10,7 @@ import { RiServerLine } from 'react-icons/ri';
|
|||||||
|
|
||||||
import BoardsList from './Boards/BoardsList/BoardsList';
|
import BoardsList from './Boards/BoardsList/BoardsList';
|
||||||
import GalleryBoardName from './GalleryBoardName';
|
import GalleryBoardName from './GalleryBoardName';
|
||||||
import GallerySettingsPopover from './GallerySettingsPopover';
|
import GallerySettingsPopover from './GallerySettingsPopover/GallerySettingsPopover';
|
||||||
import GalleryImageGrid from './ImageGrid/GalleryImageGrid';
|
import GalleryImageGrid from './ImageGrid/GalleryImageGrid';
|
||||||
import { GalleryPagination } from './ImageGrid/GalleryPagination';
|
import { GalleryPagination } from './ImageGrid/GalleryPagination';
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user