mirror of
https://github.com/stan-smith/FossFLOW.git
synced 2025-12-28 00:49:19 -05:00
feat: implements icons searchbox
This commit is contained in:
@@ -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>
|
||||
);
|
||||
@@ -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';
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
@@ -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={{
|
||||
|
||||
29
src/hooks/useIconFiltering.ts
Normal file
29
src/hooks/useIconFiltering.ts
Normal 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
|
||||
};
|
||||
};
|
||||
@@ -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({
|
||||
|
||||
@@ -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': {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user