import * as React from 'react'; import { useEffect } from 'react'; import classnames from 'classnames'; import * as Icons from './Icons'; import { Icons as IconsNamespace } from './Icons'; import InputSearch from '../inputs/InputSearch/InputSearch'; import { useContext, useState } from 'react'; import styles from './IconsStoriesAll.scss'; import { IconSvgStoryMeta } from './helpers/withIconSvg'; import { IconsStoriesAllFooter } from './IconsStoriesAllFooter'; type AdditionalPropChanges = {[propName: string]: any}; type IconType = React.FC & {meta: IconSvgStoryMeta}; interface IconsImportType { [key: string]: IconType; } interface IconStoriesAllContextType { additionalPropChanges: AdditionalPropChanges; changedAdditionalProps: AdditionalPropChanges; selectedIconData?: { exportIconName: string, exportNamespaceIconName: string | undefined, Icon: IconType, meta: IconSvgStoryMeta, }; setAdditionalPropChanges: (value: AdditionalPropChanges) => void, setDoShowAdditionalProps: (value: IconStoriesAllContextType['doShowAdditionalProps']) => void, doShowAdditionalProps: boolean; } export const IconStoriesAllContext = React.createContext({ additionalPropChanges: {}, changedAdditionalProps: {}, selectedIconData: undefined, setAdditionalPropChanges: () => {}, setDoShowAdditionalProps: () => {}, doShowAdditionalProps: true, }); const localStorageIconPropKey = 'IconsStoryAll-selected-iconPropKey'; const localStorageSearchText = 'IconsStoryAll-selected-searchText'; export const IconsStoriesAll = () => { const contextValue = useContext(IconStoriesAllContext); const [searchInputValue, setSearchInputValue] = useState(''); const [selectedIconData, setSelectedIconData] = useState(contextValue.selectedIconData); const [doShowAdditionalProps, setDoShowAdditionalProps] = useState(contextValue.doShowAdditionalProps); const [additionalPropChanges, setAdditionalPropChanges] = useState(contextValue.additionalPropChanges); const changedAdditionalProps: AdditionalPropChanges = {}; const iconsPropKeys: PropertyKey[] = Reflect.ownKeys(Icons); // use reflection to get all available icons const iconsNamespacePropKeys: PropertyKey[] = Reflect.ownKeys(IconsNamespace); function getIconComponentRef(iconPropKey?: string): IconType | undefined { if (!iconPropKey) { return; } return (Icons as unknown as IconsImportType)[iconPropKey]; } function getExportNamespaceIconName(iconPropKey?: string): string | undefined { if (!iconPropKey) { return; } const Icon = getIconComponentRef(iconPropKey); return iconsNamespacePropKeys.find((key) => (IconsNamespace as any)[key] === Icon) as string; } function onIconChangeByIconPropKey(iconPropKey?: string){ const Icon = getIconComponentRef(iconPropKey); if (!iconPropKey || !Icon) { return; } localStorage.setItem(localStorageIconPropKey, iconPropKey); // need to manually dispatch for this picked up by the split view since it's in the same tab window.dispatchEvent(new Event('storage')); } function onChangeInput(event: React.ChangeEvent) { const value = event?.target?.value; setSearchInputValue(value ? value : ''); localStorage.setItem(localStorageSearchText, value); // need to manually dispatch for this picked up by the split view since it's in the same tab window.dispatchEvent(new Event('storage')); } function onStorage() { // SELECTED ICON const lsIconPropKey = window.localStorage.getItem(localStorageIconPropKey); if (typeof lsIconPropKey !== undefined && lsIconPropKey !== null && selectedIconData?.exportIconName !== lsIconPropKey) { const Icon = getIconComponentRef(lsIconPropKey); if (!Icon) { return; } // clear out all additional prop value changes made setAdditionalPropChanges({}); // select clicked icon setSelectedIconData({ exportIconName: lsIconPropKey, exportNamespaceIconName: getExportNamespaceIconName(lsIconPropKey), Icon, meta: Icon.meta, }); } // SEARCH TEXT const lsSearchText = window.localStorage.getItem(localStorageSearchText); if (!!lsSearchText) { setSearchInputValue(lsSearchText); } else { setSearchInputValue(''); } } Object.entries(additionalPropChanges).map(([propName, propValue]) => { changedAdditionalProps[propName] = propValue; }); useEffect(() => { // check for initial persisted values onStorage(); window.addEventListener('storage', onStorage); return () => { window.removeEventListener('storage', onStorage); } }, []); return (
{iconsPropKeys.map((iconPropKey) => { // ignore if property key is not a string or is in exclusion list if (typeof iconPropKey !== 'string' || [ 'Icons', '__esModule', 'Symbol(Symbol.toStringTag)' ].includes(iconPropKey as string) ) { return; } const Icon = getIconComponentRef(iconPropKey); const exportNamespaceIconName = getExportNamespaceIconName(iconPropKey); const meta: IconSvgStoryMeta | undefined = Icon?.meta; const IconRef: React.FC = Icon as React.FC; // filter out non-matching icons if there is search criteria if (searchInputValue && !iconPropKey.toLowerCase().includes(searchInputValue.toLowerCase()) && !exportNamespaceIconName?.toLowerCase().includes(searchInputValue.toLowerCase()) && !meta?.tags?.join('`').toLowerCase().includes(searchInputValue.toLowerCase()) ) { return; } return ( ); })}
); };