feat: implements icons searchbox

This commit is contained in:
Mark Mankarious
2023-09-03 12:22:42 +01:00
parent 9903755052
commit 887a91607c
12 changed files with 97 additions and 49 deletions

View File

@@ -1,20 +1,20 @@
import React, { useCallback } from 'react';
import { useSceneStore } from 'src/stores/sceneStore';
import { ControlsContainer } from 'src/components/ItemControls/components/ControlsContainer';
import { useUiStateStore } from 'src/stores/uiStateStore';
import { Icon } from 'src/types';
import { Section } from 'src/components/ItemControls/components/Section';
import { Searchbox } from 'src/components/ItemControls/IconSelectionControls/Searchbox';
import { useIconFiltering } from 'src/hooks/useIconFiltering';
import { Icons } from './Icons';
export const IconSelection = () => {
export const IconSelectionControls = () => {
const uiStateActions = useUiStateStore((state) => {
return state.actions;
});
const mode = useUiStateStore((state) => {
return state.mode;
});
const icons = useSceneStore((state) => {
return state.icons;
});
const { setFilter, filter, icons } = useIconFiltering();
const onMouseDown = useCallback(
(icon: Icon) => {
@@ -30,7 +30,13 @@ export const IconSelection = () => {
);
return (
<ControlsContainer>
<ControlsContainer
header={
<Section sx={{ position: 'sticky', top: 0, pt: 6, pb: 3 }}>
<Searchbox value={filter} onChange={setFilter} />
</Section>
}
>
<Icons icons={icons} onMouseDown={onMouseDown} />
</ControlsContainer>
);

View File

@@ -1,5 +1,5 @@
import React, { useMemo } from 'react';
import Grid from '@mui/material/Grid';
import { Grid } from '@mui/material';
import { Icon } from 'src/types';
import { IconCategory } from './IconCategory';

View File

@@ -0,0 +1,28 @@
import React from 'react';
import { TextField, InputAdornment } from '@mui/material';
import { Search as SearchIcon } from '@mui/icons-material';
interface Props {
value: string;
onChange: (value: string) => void;
}
export const Searchbox = ({ value, onChange }: Props) => {
return (
<TextField
sx={{ maxWidth: 200 }}
placeholder="Search icons"
value={value}
onChange={(e) => {
return onChange(e.target.value as string);
}}
InputProps={{
startAdornment: (
<InputAdornment position="start">
<SearchIcon />
</InputAdornment>
)
}}
/>
);
};

View File

@@ -1,7 +1,7 @@
import React, { useMemo } from 'react';
import { Box } from '@mui/material';
import { useUiStateStore } from 'src/stores/uiStateStore';
import { IconSelection } from 'src/components/ItemControls/IconSelection/IconSelection';
import { IconSelectionControls } from 'src/components/ItemControls/IconSelectionControls/IconSelectionControls';
import { NodeControls } from './NodeControls/NodeControls';
import { ConnectorControls } from './ConnectorControls/ConnectorControls';
import { TextBoxControls } from './TextBoxControls/TextBoxControls';
@@ -23,7 +23,7 @@ export const ItemControlsManager = () => {
case 'RECTANGLE':
return <RectangleControls key={itemControls.id} id={itemControls.id} />;
case 'ADD_ITEM':
return <IconSelection />;
return <IconSelectionControls />;
default:
return null;
}

View File

@@ -5,7 +5,7 @@ import { useSceneStore } from 'src/stores/sceneStore';
import { useNode } from 'src/hooks/useNode';
import { useUiStateStore } from 'src/stores/uiStateStore';
import { ControlsContainer } from '../components/ControlsContainer';
import { Icons } from '../IconSelection/Icons';
import { Icons } from '../IconSelectionControls/Icons';
import { Header } from '../components/Header';
import { NodeSettings } from './NodeSettings/NodeSettings';

View File

@@ -1,35 +0,0 @@
import React from 'react';
import Slide from '@mui/material/Slide';
import Card from '@mui/material/Card';
interface Props {
children: React.ReactElement;
isIn: boolean;
}
export const Transition = ({ children, isIn }: Props) => {
return (
<Slide
direction="right"
in={isIn}
mountOnEnter
unmountOnExit
style={{
transitionDelay: isIn ? '150ms' : '0ms'
}}
>
<Card
sx={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
borderRadius: 0
}}
>
{children}
</Card>
</Slide>
);
};

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { Box } from '@mui/material';
import { Box, Card, Divider } from '@mui/material';
interface Props {
header?: React.ReactNode;
@@ -19,7 +19,17 @@ export const ControlsContainer = ({ header, children }: Props) => {
}}
>
{header && (
<Box sx={{ width: '100%', boxShadow: 6, zIndex: 1 }}>{header}</Box>
<Card
sx={{
width: '100%',
zIndex: 1,
position: 'sticky',
top: 0
}}
>
{header}
<Divider />
</Card>
)}
<Box
sx={{

View File

@@ -0,0 +1,29 @@
import { useState, useMemo } from 'react';
import { useSceneStore } from 'src/stores/sceneStore';
import { Icon } from 'src/types';
export const useIconFiltering = () => {
const [filter, setFilter] = useState<string>('');
const icons = useSceneStore((state) => {
return state.icons;
});
const filteredIcons = useMemo(() => {
const regex = new RegExp(filter, 'gi');
return icons.filter((icon: Icon) => {
if (!filter) {
return true;
}
return regex.test(icon.name);
});
}, [icons, filter]);
return {
setFilter,
filter,
icons: filteredIcons
};
};

View File

@@ -4,8 +4,8 @@ import { getItemAtTile, generateId } from 'src/utils';
export const PlaceElement: ModeActions = {
mousemove: () => {},
mousedown: ({ uiState, scene }) => {
if (uiState.mode.type !== 'PLACE_ELEMENT') return;
mousedown: ({ uiState, scene, isRendererInteraction }) => {
if (uiState.mode.type !== 'PLACE_ELEMENT' || !isRendererInteraction) return;
if (!uiState.mode.icon) {
const itemAtTile = getItemAtTile({

View File

@@ -62,6 +62,11 @@ export const themeConfig: ThemeOptions = {
}
},
components: {
MuiCard: {
defaultProps: {
elevation: 0
}
},
MuiToolbar: {
styleOverrides: {
root: {
@@ -85,6 +90,11 @@ export const themeConfig: ThemeOptions = {
MuiTextField: {
defaultProps: {
variant: 'standard'
},
styleOverrides: {
root: {
'.MuiInputBase-input': {}
}
}
}
}