Browse Source

ref(story): Cleanup SearchPanel (#36283)

Evan Purkhiser 2 years ago
parent
commit
1484ab8528
1 changed files with 74 additions and 92 deletions
  1. 74 92
      docs-ui/stories/assets/icons/searchPanel.tsx

+ 74 - 92
docs-ui/stories/assets/icons/searchPanel.tsx

@@ -1,7 +1,6 @@
 import {useCallback, useEffect, useState} from 'react';
 import styled from '@emotion/styled';
 import Fuse from 'fuse.js';
-import debounce from 'lodash/debounce';
 
 import TextField from 'sentry/components/deprecatedforms/textField';
 import space from 'sentry/styles/space';
@@ -21,82 +20,75 @@ export type SelectedIcon = {
   icon: string;
 };
 
-const SearchPanel = () => {
-  /**
-   * The same icon can appear in multiple groups,
-   * so we also need to store which group the
-   * selected icon is in
-   */
-  const [selectedIcon, setSelectedIcon] = useState<SelectedIcon>({group: '', icon: ''});
-
-  /**
-   * All the icons, split into iterable groups
-   */
-  const addIconNames = (iconData: IconData[]): ExtendedIconData[] =>
-    iconData.map(icon => {
-      const nameString = icon.id.split('-')[0];
-      const name = nameString.charAt(0).toUpperCase() + nameString.slice(1);
-      return {...icon, name};
-    });
-
-  const enumerateIconProps = (
-    iconData: ExtendedIconData[],
-    prop: string
-  ): ExtendedIconData[] =>
-    iconData.reduce((acc: ExtendedIconData[], cur: ExtendedIconData) => {
-      const propData = iconProps[prop];
-
-      switch (propData.type) {
-        case 'select':
-          const availableOptions: string[][] =
-            cur.limitOptions?.[prop] ?? propData.options;
-
-          return [
-            ...acc,
-            ...availableOptions.map(option => ({
-              ...cur,
-              id: `${cur.id}-${prop}-${option[0]}`,
-              defaultProps: {
-                ...cur.defaultProps,
-                [prop]: option[0],
-              },
-            })),
-          ];
-        case 'boolean':
-          return [
-            ...acc,
-            {...cur, defaultProps: {...cur.defaultProps, [prop]: false}},
-            {
-              ...cur,
-              id: `${cur.id}-${prop}`,
-              defaultProps: {...cur.defaultProps, [prop]: true},
+const enumerateIconProps = (iconData: ExtendedIconData[], prop: string) =>
+  iconData.reduce<ExtendedIconData[]>((acc, cur) => {
+    const propData = iconProps[prop];
+
+    switch (propData.type) {
+      case 'select':
+        const availableOptions: string[][] = cur.limitOptions?.[prop] ?? propData.options;
+
+        return [
+          ...acc,
+          ...availableOptions.map(option => ({
+            ...cur,
+            id: `${cur.id}-${prop}-${option[0]}`,
+            defaultProps: {
+              ...cur.defaultProps,
+              [prop]: option[0],
             },
-          ];
-        default:
-          return acc;
+          })),
+        ];
+      case 'boolean':
+        return [
+          ...acc,
+          {...cur, defaultProps: {...cur.defaultProps, [prop]: false}},
+          {
+            ...cur,
+            id: `${cur.id}-${prop}`,
+            defaultProps: {...cur.defaultProps, [prop]: true},
+          },
+        ];
+      default:
+        return acc;
+    }
+  }, []);
+
+const enumerateIconVariants = (iconData: ExtendedIconData[]): ExtendedIconData[] =>
+  iconData.reduce<ExtendedIconData[]>((acc, cur) => {
+    let iconVariants: ExtendedIconData[] = [{...cur, defaultProps: {}}];
+
+    cur.additionalProps?.forEach(prop => {
+      if (iconProps[prop].enumerate) {
+        iconVariants = enumerateIconProps(iconVariants, prop);
       }
-    }, []);
+    });
 
-  const enumerateIconVariants = (iconData: ExtendedIconData[]): ExtendedIconData[] =>
-    iconData.reduce((acc: ExtendedIconData[], cur: ExtendedIconData) => {
-      let iconVariants: ExtendedIconData[] = [{...cur, defaultProps: {}}];
+    return [...acc, ...iconVariants];
+  }, []);
 
-      cur.additionalProps?.forEach(prop => {
-        if (iconProps[prop].enumerate) {
-          iconVariants = enumerateIconProps(iconVariants, prop);
-        }
-      });
+// All the icons, split into iterable groups
+const addIconNames = (iconData: IconData[]): ExtendedIconData[] =>
+  iconData.map(icon => {
+    const nameString = icon.id.split('-')[0];
+    const name = nameString.charAt(0).toUpperCase() + nameString.slice(1);
+    return {...icon, name};
+  });
 
-      return [...acc, ...iconVariants];
-    }, []);
+const groupedIcons: Results = iconGroups.map(group => {
+  const filteredIcons = icons.filter(i => i.groups.includes(group.id));
+  const namedIcons = addIconNames(filteredIcons);
+  const enumeratedIcons = enumerateIconVariants(namedIcons);
 
-  const groupedIcons: Results = iconGroups.map(group => {
-    const filteredIcons = icons.filter(i => i.groups.includes(group.id));
-    const namedIcons = addIconNames(filteredIcons);
-    const enumeratedIcons = enumerateIconVariants(namedIcons);
+  return {...group, icons: enumeratedIcons};
+});
 
-    return {...group, icons: enumeratedIcons};
-  });
+const fuse = new Fuse(icons, {keys: ['id', 'groups', 'keywords'], threshold: 0.3});
+
+function SearchPanel() {
+  // The same icon can appear in multiple groups, so we also need to store
+  // which group the selected icon is in
+  const [selectedIcon, setSelectedIcon] = useState<SelectedIcon>({group: '', icon: ''});
 
   /**
    * Use Fuse.js to implement icon search
@@ -104,29 +96,19 @@ const SearchPanel = () => {
   const [query, setQuery] = useState('');
   const [results, setResults] = useState<Results>(groupedIcons);
 
-  const fuse = new Fuse(icons, {
-    keys: ['id', 'groups', 'keywords'],
-    threshold: 0.3,
-  });
+  const debouncedSearch = useCallback((newQuery: string) => {
+    if (!newQuery) {
+      setResults(groupedIcons);
+    } else {
+      const searchResults = fuse.search(newQuery).map(result => result.item);
+      const namedIcons = addIconNames(searchResults);
+      const enumeratedIcons = enumerateIconVariants(namedIcons);
 
-  const debouncedSearch = useCallback(
-    debounce(newQuery => {
-      if (!newQuery) {
-        setResults(groupedIcons);
-      } else {
-        const searchResults = fuse.search(newQuery).map(result => result.item);
-        const namedIcons = addIconNames(searchResults);
-        const enumeratedIcons = enumerateIconVariants(namedIcons);
+      setResults([{id: 'search', icons: enumeratedIcons}]);
+    }
+  }, []);
 
-        setResults([{id: 'search', icons: enumeratedIcons}]);
-      }
-    }, 250),
-    []
-  );
-
-  useEffect(() => {
-    debouncedSearch(query);
-  }, [query]);
+  useEffect(() => void debouncedSearch(query), [query, debouncedSearch]);
 
   return (
     <Wrap>
@@ -158,7 +140,7 @@ const SearchPanel = () => {
       ))}
     </Wrap>
   );
-};
+}
 
 export default SearchPanel;