react-window#FixedSizeList TypeScript Examples
The following examples show how to use
react-window#FixedSizeList.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.tsx From calories-in with MIT License | 6 votes |
function VirtualizedList({
getFood,
isFoodSelected,
onFoodSelect,
onFoodPreview,
foodsCount,
forwardRef,
itemUsageType,
}: Props) {
const { elementHeight, elementRef } = useElementHeight()
return (
<Box position="relative" ref={elementRef} flex={1}>
<FixedSizeList
style={{ position: 'absolute', top: 0 }}
innerElementType={Inner}
height={elementHeight}
itemCount={foodsCount}
itemData={{
getFood,
onFoodSelect,
onFoodPreview,
isFoodSelected,
usageType: itemUsageType,
}}
itemSize={72}
width="100%"
ref={forwardRef}
>
{FoodItemRenderer}
</FixedSizeList>
</Box>
)
}
Example #2
Source File: ListViewport.tsx From flood with GNU General Public License v3.0 | 6 votes |
ListViewport = forwardRef<FixedSizeList, ListViewportProps>((props: ListViewportProps, ref) => {
const {className, itemCount, itemKey, itemRenderer, itemSize, outerRef} = props;
const {height: windowHeight} = useWindowSize();
return (
<FixedSizeList
className={`${className} ${ConfigStore.isPreferDark ? 'os-theme-light' : 'os-theme-dark'}`}
height={Math.max(itemSize * 30, windowHeight)}
itemCount={itemCount}
itemKey={itemKey}
itemSize={itemSize}
width="100%"
outerElementType={ConfigStore.isSmallScreen ? undefined : Overflow} // Don't use custom scrollbar on smaller screens
ref={ref}
overscanCount={30}
outerRef={outerRef}
>
{itemRenderer}
</FixedSizeList>
);
})
Example #3
Source File: NativeSelect.tsx From GTAV-NativeDB with MIT License | 5 votes |
ListboxComponent = React.forwardRef<HTMLDivElement>(function ListboxComponent(
props,
ref,
) {
const { children, ...other } = props
const itemData = React.Children.toArray(children)
const theme = useTheme()
const smUp = useMediaQuery(theme.breakpoints.up('sm'), {
noSsr: true
})
const itemCount = itemData.length
const itemSize = smUp ? 36 : 48
const getHeight = () => {
if (itemCount > 8) {
return 8 * itemSize
}
return itemData.map(() => smUp ? 36 : 48).reduce((a, b) => a + b, 0)
}
const gridRef = useResetCache(itemCount);
return (
<div ref={ref}>
<OuterElementContext.Provider value={other}>
<FixedSizeList
itemData={itemData}
height={getHeight() + 2 * LISTBOX_PADDING}
width="100%"
ref={gridRef}
outerElementType={OuterElementType}
innerElementType="ul"
itemSize={smUp ? 36 : 48}
overscanCount={5}
itemCount={itemCount}
>
{renderRow}
</FixedSizeList>
</OuterElementContext.Provider>
</div>
);
})
Example #4
Source File: CurrencyList.tsx From pancakeswap-testnet with GNU General Public License v3.0 | 5 votes |
export default function CurrencyList({
height,
currencies,
selectedCurrency,
onCurrencySelect,
otherCurrency,
fixedListRef,
showETH,
}: {
height: number
currencies: Currency[]
selectedCurrency?: Currency | null
onCurrencySelect: (currency: Currency) => void
otherCurrency?: Currency | null
fixedListRef?: MutableRefObject<FixedSizeList | undefined>
showETH: boolean
}) {
const itemData = useMemo(() => (showETH ? [Currency.ETHER, ...currencies] : [...currencies]), [currencies, showETH])
const Row = useCallback(
({ data, index, style }) => {
const currency: Currency = data[index]
const isSelected = Boolean(selectedCurrency && currencyEquals(selectedCurrency, currency))
const otherSelected = Boolean(otherCurrency && currencyEquals(otherCurrency, currency))
const handleSelect = () => onCurrencySelect(currency)
return (
<CurrencyRow
style={style}
currency={currency}
isSelected={isSelected}
onSelect={handleSelect}
otherSelected={otherSelected}
/>
)
},
[onCurrencySelect, otherCurrency, selectedCurrency]
)
const itemKey = useCallback((index: number, data: any) => currencyKey(data[index]), [])
return (
<FixedSizeList
height={height}
ref={fixedListRef as any}
width="100%"
itemData={itemData}
itemCount={itemData.length}
itemSize={56}
itemKey={itemKey}
>
{Row}
</FixedSizeList>
)
}
Example #5
Source File: CurrencyList.tsx From luaswap-interface with GNU General Public License v3.0 | 5 votes |
export default function CurrencyList({
height,
currencies,
selectedCurrency,
onCurrencySelect,
otherCurrency,
fixedListRef,
showETH
}: {
height: number
currencies: Currency[]
selectedCurrency?: Currency | null
onCurrencySelect: (currency: Currency) => void
otherCurrency?: Currency | null
fixedListRef?: MutableRefObject<FixedSizeList | undefined>
showETH: boolean
}) {
const { chainId } = useActiveWeb3React()
const IsTomo = IsTomoChain(chainId)
const NATIVE_TOKEN = IsTomo ? Currency.TOMO : Currency.ETHER
const itemData = useMemo(() => (showETH ? [NATIVE_TOKEN, ...currencies] : currencies), [currencies, showETH])
const Row = useCallback(
({ data, index, style }) => {
const currency: Currency = data[index]
const isSelected = Boolean(selectedCurrency && currencyEquals(selectedCurrency, currency))
const otherSelected = Boolean(otherCurrency && currencyEquals(otherCurrency, currency))
const handleSelect = () => onCurrencySelect(currency)
return (
<CurrencyRow
style={style}
currency={currency}
isSelected={isSelected}
onSelect={handleSelect}
otherSelected={otherSelected}
/>
)
},
[onCurrencySelect, otherCurrency, selectedCurrency]
)
const itemKey = useCallback((index: number, data: any) => currencyKey(data[index]), [])
return (
<FixedSizeList
height={height}
ref={fixedListRef as any}
width="100%"
itemData={itemData}
itemCount={itemData.length}
itemSize={56}
itemKey={itemKey}
>
{Row}
</FixedSizeList>
)
}
Example #6
Source File: Typeahead.tsx From grafana-chinese with Apache License 2.0 | 5 votes |
listRef = createRef<FixedSizeList>();
Example #7
Source File: Tree.tsx From react-beautiful-tree with Apache License 2.0 | 5 votes |
render() {
const {
isNestingEnabled,
isVirtualizationEnabled,
virtualItemHeight,
} = this.props
const { flattenedTree } = this.state
const renderedItems = this.renderItems()
return (
<DragDropContext
onDragStart={this.onDragStart}
onDragEnd={this.onDragEnd}
onDragUpdate={this.onDragUpdate}
>
<Droppable
droppableId="tree"
isCombineEnabled={isNestingEnabled}
ignoreContainerClipping
mode={isVirtualizationEnabled ? 'virtual' : 'standard'}
renderClone={
isVirtualizationEnabled
? (provided, snapshot, rubric) =>
this.renderVirtualItem({
provided,
snapshot,
flatItem: flattenedTree[rubric.source.index],
})
: undefined
}
>
{(provided: DroppableProvided) => {
const finalProvided: DroppableProvided = this.patchDroppableProvided(
provided
)
return isVirtualizationEnabled ? (
<AutoSizer defaultHeight={1} defaultWidth={1}>
{({ height, width }: { height: number; width: number }) => (
<FixedSizeList
height={height}
itemCount={flattenedTree.length}
itemSize={virtualItemHeight}
width={width}
outerRef={provided.innerRef}
itemData={flattenedTree}
>
{this.renderVirtualRow}
</FixedSizeList>
)}
</AutoSizer>
) : (
<div
ref={finalProvided.innerRef}
style={{ pointerEvents: 'auto' }}
onTouchMove={this.onPointerMove}
onMouseMove={this.onPointerMove}
{...finalProvided.droppableProps}
>
{renderedItems}
{provided.placeholder}
</div>
)
}}
</Droppable>
</DragDropContext>
)
}
Example #8
Source File: CurrencyList.tsx From panther-frontend-dex with GNU General Public License v3.0 | 5 votes |
export default function CurrencyList({
height,
currencies,
selectedCurrency,
onCurrencySelect,
otherCurrency,
fixedListRef,
showETH,
}: {
height: number
currencies: Currency[]
selectedCurrency?: Currency | null
onCurrencySelect: (currency: Currency) => void
otherCurrency?: Currency | null
fixedListRef?: MutableRefObject<FixedSizeList | undefined>
showETH: boolean
}) {
const itemData = useMemo(() => (showETH ? [Currency.ETHER, ...currencies] : [...currencies]), [currencies, showETH])
const Row = useCallback(
({ data, index, style }) => {
const currency: Currency = data[index]
const isSelected = Boolean(selectedCurrency && currencyEquals(selectedCurrency, currency))
const otherSelected = Boolean(otherCurrency && currencyEquals(otherCurrency, currency))
const handleSelect = () => onCurrencySelect(currency)
return (
<CurrencyRow
style={style}
currency={currency}
isSelected={isSelected}
onSelect={handleSelect}
otherSelected={otherSelected}
/>
)
},
[onCurrencySelect, otherCurrency, selectedCurrency]
)
const itemKey = useCallback((index: number, data: any) => currencyKey(data[index]), [])
return (
<FixedSizeList
height={height}
ref={fixedListRef as any}
width="100%"
itemData={itemData}
itemCount={itemData.length}
itemSize={56}
itemKey={itemKey}
>
{Row}
</FixedSizeList>
)
}
Example #9
Source File: CurrencyList.tsx From pancake-swap-testnet with MIT License | 5 votes |
export default function CurrencyList({
height,
currencies,
selectedCurrency,
onCurrencySelect,
otherCurrency,
fixedListRef,
showETH,
}: {
height: number
currencies: Currency[]
selectedCurrency?: Currency | null
onCurrencySelect: (currency: Currency) => void
otherCurrency?: Currency | null
fixedListRef?: MutableRefObject<FixedSizeList | undefined>
showETH: boolean
}) {
const itemData = useMemo(() => (showETH ? [Currency.ETHER, ...currencies] : [...currencies]), [currencies, showETH])
const Row = useCallback(
({ data, index, style }) => {
const currency: Currency = data[index]
const isSelected = Boolean(selectedCurrency && currencyEquals(selectedCurrency, currency))
const otherSelected = Boolean(otherCurrency && currencyEquals(otherCurrency, currency))
const handleSelect = () => onCurrencySelect(currency)
return (
<CurrencyRow
style={style}
currency={currency}
isSelected={isSelected}
onSelect={handleSelect}
otherSelected={otherSelected}
/>
)
},
[onCurrencySelect, otherCurrency, selectedCurrency]
)
const itemKey = useCallback((index: number, data: any) => currencyKey(data[index]), [])
return (
<FixedSizeList
height={height}
ref={fixedListRef as any}
width="100%"
itemData={itemData}
itemCount={itemData.length}
itemSize={56}
itemKey={itemKey}
>
{Row}
</FixedSizeList>
)
}
Example #10
Source File: CurrencyList.tsx From pancake-swap-exchange-testnet with GNU General Public License v3.0 | 5 votes |
export default function CurrencyList({
height,
currencies,
selectedCurrency,
onCurrencySelect,
otherCurrency,
fixedListRef,
showETH,
}: {
height: number
currencies: Currency[]
selectedCurrency?: Currency | null
onCurrencySelect: (currency: Currency) => void
otherCurrency?: Currency | null
fixedListRef?: MutableRefObject<FixedSizeList | undefined>
showETH: boolean
}) {
const itemData = useMemo(() => (showETH ? [Currency.ETHER, ...currencies] : [...currencies]), [currencies, showETH])
const Row = useCallback(
({ data, index, style }) => {
const currency: Currency = data[index]
const isSelected = Boolean(selectedCurrency && currencyEquals(selectedCurrency, currency))
const otherSelected = Boolean(otherCurrency && currencyEquals(otherCurrency, currency))
const handleSelect = () => onCurrencySelect(currency)
return (
<CurrencyRow
style={style}
currency={currency}
isSelected={isSelected}
onSelect={handleSelect}
otherSelected={otherSelected}
/>
)
},
[onCurrencySelect, otherCurrency, selectedCurrency]
)
const itemKey = useCallback((index: number, data: any) => currencyKey(data[index]), [])
return (
<FixedSizeList
height={height}
ref={fixedListRef as any}
width="100%"
itemData={itemData}
itemCount={itemData.length}
itemSize={56}
itemKey={itemKey}
>
{Row}
</FixedSizeList>
)
}
Example #11
Source File: CurrencyList.tsx From mozartfinance-swap-interface with GNU General Public License v3.0 | 5 votes |
export default function CurrencyList({
height,
currencies,
selectedCurrency,
onCurrencySelect,
otherCurrency,
fixedListRef,
showETH,
}: {
height: number
currencies: Currency[]
selectedCurrency?: Currency | null
onCurrencySelect: (currency: Currency) => void
otherCurrency?: Currency | null
fixedListRef?: MutableRefObject<FixedSizeList | undefined>
showETH: boolean
}) {
const itemData = useMemo(() => (showETH ? [Currency.ETHER, ...currencies] : [...currencies]), [currencies, showETH])
const Row = useCallback(
({ data, index, style }) => {
const currency: Currency = data[index]
const isSelected = Boolean(selectedCurrency && currencyEquals(selectedCurrency, currency))
const otherSelected = Boolean(otherCurrency && currencyEquals(otherCurrency, currency))
const handleSelect = () => onCurrencySelect(currency)
return (
<CurrencyRow
style={style}
currency={currency}
isSelected={isSelected}
onSelect={handleSelect}
otherSelected={otherSelected}
/>
)
},
[onCurrencySelect, otherCurrency, selectedCurrency]
)
const itemKey = useCallback((index: number, data: any) => currencyKey(data[index]), [])
return (
<FixedSizeList
height={height}
ref={fixedListRef as any}
width="100%"
itemData={itemData}
itemCount={itemData.length}
itemSize={56}
itemKey={itemKey}
>
{Row}
</FixedSizeList>
)
}
Example #12
Source File: CurrencySearch.tsx From goose-frontend-amm with GNU General Public License v3.0 | 5 votes |
export function CurrencySearch({
selectedCurrency,
onCurrencySelect,
otherSelectedCurrency,
showCommonBases,
onDismiss,
isOpen,
onChangeList,
}: CurrencySearchProps) {
const { t } = useTranslation()
const { chainId } = useActiveWeb3React()
const theme = useContext(ThemeContext)
const fixedList = useRef<FixedSizeList>()
const [searchQuery, setSearchQuery] = useState<string>('')
const [invertSearchOrder, setInvertSearchOrder] = useState<boolean>(false)
const allTokens = useAllTokens()
// if they input an address, use it
const isAddressSearch = isAddress(searchQuery)
const searchToken = useToken(searchQuery)
const showETH: boolean = useMemo(() => {
const s = searchQuery.toLowerCase().trim()
return s === '' || s === 'e' || s === 'et' || s === 'eth'
}, [searchQuery])
const tokenComparator = useTokenComparator(invertSearchOrder)
const audioPlay = useSelector<AppState, AppState['user']['audioPlay']>((state) => state.user.audioPlay)
const filteredTokens: Token[] = useMemo(() => {
if (isAddressSearch) return searchToken ? [searchToken] : []
return filterTokens(Object.values(allTokens), searchQuery)
}, [isAddressSearch, searchToken, allTokens, searchQuery])
const filteredSortedTokens: Token[] = useMemo(() => {
if (searchToken) return [searchToken]
const sorted = filteredTokens.sort(tokenComparator)
const symbolMatch = searchQuery
.toLowerCase()
.split(/\s+/)
.filter((s) => s.length > 0)
if (symbolMatch.length > 1) return sorted
return [
...(searchToken ? [searchToken] : []),
// sort any exact symbol matches first
...sorted.filter((token) => token.symbol?.toLowerCase() === symbolMatch[0]),
...sorted.filter((token) => token.symbol?.toLowerCase() !== symbolMatch[0]),
]
}, [filteredTokens, searchQuery, searchToken, tokenComparator])
const handleCurrencySelect = useCallback(
(currency: Currency) => {
onCurrencySelect(currency)
onDismiss()
if (audioPlay) {
const audio = document.getElementById('bgMusic') as HTMLAudioElement
if (audio) {
audio.play()
}
}
},
[onDismiss, onCurrencySelect, audioPlay]
)
// clear the input on open
useEffect(() => {
if (isOpen) setSearchQuery('')
}, [isOpen])
// manage focus on modal show
const inputRef = useRef<HTMLInputElement>()
const handleInput = useCallback((event) => {
const input = event.target.value
const checksummedInput = isAddress(input)
setSearchQuery(checksummedInput || input)
fixedList.current?.scrollTo(0)
}, [])
const handleEnter = useCallback(
(e: KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter') {
const s = searchQuery.toLowerCase().trim()
if (s === 'eth') {
handleCurrencySelect(ETHER)
} else if (filteredSortedTokens.length > 0) {
if (
filteredSortedTokens[0].symbol?.toLowerCase() === searchQuery.trim().toLowerCase() ||
filteredSortedTokens.length === 1
) {
handleCurrencySelect(filteredSortedTokens[0])
}
}
}
},
[filteredSortedTokens, handleCurrencySelect, searchQuery]
)
const selectedListInfo = useSelectedListInfo()
return (
<Column style={{ width: '100%', flex: '1 1' }}>
<PaddedColumn gap="14px">
<RowBetween>
<Text>
<TranslatedText translationId={82}>Select a token</TranslatedText>
<QuestionHelper
text={TranslateString(
130,
'Find a token by searching for its name or symbol or by pasting its address below.'
)}
/>
</Text>
<CloseIcon onClick={onDismiss} />
</RowBetween>
<SearchInput
type="text"
id="token-search-input"
placeholder={t('tokenSearchPlaceholder')}
value={searchQuery}
ref={inputRef as RefObject<HTMLInputElement>}
onChange={handleInput}
onKeyDown={handleEnter}
/>
{showCommonBases && (
<CommonBases chainId={chainId} onSelect={handleCurrencySelect} selectedCurrency={selectedCurrency} />
)}
<RowBetween>
<Text fontSize="14px">
<TranslatedText translationId={126}>Token name</TranslatedText>
</Text>
<SortButton ascending={invertSearchOrder} toggleSortOrder={() => setInvertSearchOrder((iso) => !iso)} />
</RowBetween>
</PaddedColumn>
<Separator />
<div style={{ flex: '1' }}>
<AutoSizer disableWidth>
{({ height }) => (
<CurrencyList
height={height}
showETH={showETH}
currencies={filteredSortedTokens}
onCurrencySelect={handleCurrencySelect}
otherCurrency={otherSelectedCurrency}
selectedCurrency={selectedCurrency}
fixedListRef={fixedList}
/>
)}
</AutoSizer>
</div>
{null && (
<>
<Separator />
<Card>
<RowBetween>
{selectedListInfo.current ? (
<Row>
{selectedListInfo.current.logoURI ? (
<ListLogo
style={{ marginRight: 12 }}
logoURI={selectedListInfo.current.logoURI}
alt={`${selectedListInfo.current.name} list logo`}
/>
) : null}
<Main id="currency-search-selected-list-name">{selectedListInfo.current.name}</Main>
</Row>
) : null}
<LinkStyledButton
style={{ fontWeight: 500, color: theme.colors.textSubtle, fontSize: 16 }}
onClick={onChangeList}
id="currency-search-change-list-button"
>
{selectedListInfo.current ? 'Change' : 'Select a list'}
</LinkStyledButton>
</RowBetween>
</Card>
</>
)}
</Column>
)
}
Example #13
Source File: CustomSelectorInput.tsx From legend-studio with Apache License 2.0 | 5 votes |
CustomMenuList: React.FC<{
options: Record<PropertyKey, unknown>[];
children: React.Component<ListChildComponentProps>[];
getValue: () => [Record<PropertyKey, unknown>];
selectProps: CustomSelectorInputProps;
}> = (props) => {
// Get row height in pixel since `react-window` does not support `rem`
// See https://stackoverflow.com/questions/45001097/convert-rem-to-px-without-reflow
const ROW_HEIGHT =
parseInt(getComputedStyle(document.documentElement).fontSize, 10) * 3.5;
const MAX_OPTIONS_LENGTH = 6;
const { options, children, getValue, selectProps } = props;
const [value] = getValue();
const initialOffset = options.indexOf(value) * ROW_HEIGHT;
const scrollToIndex = children.length
? children.findIndex((child) => child.props.isFocused)
: 0;
// We use `scrollToItem` function to make it possible for react-select to focus on item within `react-window`
// If we don't have this, if we search and use up/down arrow and once we get past the initial view-able values
// the list doesn't auto scroll
// See https://github.com/JedWatson/react-select/issues/2850
const listRef = useRef<FixedSizeList>(null);
useEffect(() => {
listRef.current?.scrollToItem(scrollToIndex);
}, [scrollToIndex]);
// Checking for the children list in case there is no match and the list height shrinks down to 0
// which causes `react-window` to throw an error
if (children.length) {
return (
<FixedSizeList
className={selectProps.darkMode ? 'selector-menu--dark' : ''}
ref={listRef}
width={'100%'}
height={Math.min(children.length, MAX_OPTIONS_LENGTH) * ROW_HEIGHT}
itemCount={children.length}
itemSize={ROW_HEIGHT}
initialScrollOffset={initialOffset}
>
{({ index, style }): React.ReactElement<ListChildComponentProps> => (
<div style={style}>{children[index] as React.ReactNode}</div>
)}
</FixedSizeList>
);
}
// TODO: Maybe a no option thing here
return (
<div
className={`selector-menu--no-match ${
selectProps.darkMode ? 'selector-menu--dark' : ''
}`}
>
No match found
</div>
);
}
Example #14
Source File: CurrencyList.tsx From dyp with Do What The F*ck You Want To Public License | 5 votes |
export default function CurrencyList({
height,
currencies,
selectedCurrency,
onCurrencySelect,
otherCurrency,
fixedListRef,
showETH
}: {
height: number
currencies: Currency[]
selectedCurrency?: Currency | null
onCurrencySelect: (currency: Currency) => void
otherCurrency?: Currency | null
fixedListRef?: MutableRefObject<FixedSizeList | undefined>
showETH: boolean
}) {
const itemData = useMemo(() => (showETH ? [Currency.ETHER, ...currencies] : currencies), [currencies, showETH])
const Row = useCallback(
({ data, index, style }) => {
const currency: Currency = data[index]
const isSelected = Boolean(selectedCurrency && currencyEquals(selectedCurrency, currency))
const otherSelected = Boolean(otherCurrency && currencyEquals(otherCurrency, currency))
const handleSelect = () => onCurrencySelect(currency)
return (
<CurrencyRow
style={style}
currency={currency}
isSelected={isSelected}
onSelect={handleSelect}
otherSelected={otherSelected}
/>
)
},
[onCurrencySelect, otherCurrency, selectedCurrency]
)
const itemKey = useCallback((index: number, data: any) => currencyKey(data[index]), [])
return (
<FixedSizeList
height={height}
ref={fixedListRef as any}
width="100%"
itemData={itemData}
itemCount={itemData.length}
itemSize={56}
itemKey={itemKey}
>
{Row}
</FixedSizeList>
)
}
Example #15
Source File: NativeSelect.tsx From GTAV-NativeDB with MIT License | 5 votes |
function useResetCache(data: any) {
const ref = React.useRef<FixedSizeList>(null)
return ref
}
Example #16
Source File: index.tsx From hubble-ui with Apache License 2.0 | 5 votes |
FlowsTable = memo<Props>(function FlowsTable(props: Props) {
const scroll = useScroll(props.onFlowsDiffCount);
const itemData = useMemo((): RowRendererData => {
return {
flows: props.flows,
visibleColumns: props.visibleColumns,
selectedFlow: props.selectedFlow,
onSelectFlow: props.onSelectFlow,
ticker: props.ticker,
};
}, [
props.flows,
props.visibleColumns,
props.selectedFlow,
props.onSelectFlow,
props.ticker,
]);
return (
<div className={css.wrapper}>
<Header visibleColumns={itemData.visibleColumns} />
<AutoSizer>
{({ width, height }) => (
<FixedSizeList
{...scroll}
className={css.table}
width={width}
height={height - sizes.flowsTableHeadHeight}
itemSize={sizes.flowsTableRowHeight}
itemCount={props.flows.length}
itemKey={itemKey}
itemData={itemData}
overscanCount={Math.ceil(height / sizes.flowsTableRowHeight / 2)}
>
{RowRenderer}
</FixedSizeList>
)}
</AutoSizer>
</div>
);
})
Example #17
Source File: CurrencyList.tsx From cheeseswap-interface with GNU General Public License v3.0 | 5 votes |
export default function CurrencyList({
height,
currencies,
selectedCurrency,
onCurrencySelect,
otherCurrency,
fixedListRef,
showETH
}: {
height: number
currencies: Currency[]
selectedCurrency?: Currency | null
onCurrencySelect: (currency: Currency) => void
otherCurrency?: Currency | null
fixedListRef?: MutableRefObject<FixedSizeList | undefined>
showETH: boolean
}) {
const itemData = useMemo(() => (showETH ? [Currency.ETHER, ...currencies] : [...currencies]), [currencies, showETH])
const Row = useCallback(
({ data, index, style }) => {
const currency: Currency = data[index]
const isSelected = Boolean(selectedCurrency && currencyEquals(selectedCurrency, currency))
const otherSelected = Boolean(otherCurrency && currencyEquals(otherCurrency, currency))
const handleSelect = () => onCurrencySelect(currency)
return (
<CurrencyRow
style={style}
currency={currency}
isSelected={isSelected}
onSelect={handleSelect}
otherSelected={otherSelected}
/>
)
},
[onCurrencySelect, otherCurrency, selectedCurrency]
)
const itemKey = useCallback((index: number, data: any) => currencyKey(data[index]), [])
// console.log(itemData)
return (
<FixedSizeList
height={height}
ref={fixedListRef as any}
width="100%"
itemData={itemData}
itemCount={itemData.length}
itemSize={56}
itemKey={itemKey}
>
{Row}
</FixedSizeList>
)
}
Example #18
Source File: TransactionFeed.tsx From celo-web-wallet with MIT License | 5 votes |
export function TransactionFeed(props: { feedState?: FeedState }) {
const feedState = props.feedState || 'normal'
const openTransactionHash = useAppSelector((s) => s.feed.openTransaction)
const transactions = useAppSelector((s) => s.feed.transactions)
const isWalletEmpty = useAreBalancesEmpty()
const tokens = useTokens()
const dispatch = useAppDispatch()
const navigate = useNavigate()
const onFeedItemClick = (hash: string) => {
dispatch(openTransaction(hash))
navigate('/tx')
}
const { setNodeRef, width, height } = useDimensionsResizeObserver(widthEstimate, heightEstimate)
heightEstimate = height
widthEstimate = width
// 480 const here must correspond with where font sizes drop in index.html
const itemSize =
feedState === 'mobile' && width < 480 ? FEED_ITEM_HEIGHT_COMPACT : FEED_ITEM_HEIGHT_NORMAL
const itemData = useMemo(() => {
const sortedTransaction = Object.values(transactions).sort((a, b) => b.timestamp - a.timestamp)
return sortedTransaction.map(
(tx): FeedItemData => ({
tx,
tokens,
itemSize,
isOpen: openTransactionHash === tx.hash,
onClick: onFeedItemClick,
collapsed: feedState === 'collapsed',
})
)
}, [transactions, tokens, openTransactionHash, feedState, itemSize])
const isFeedEmpty = !itemData.length
const onScroll = useCallback((onScrollProps: { scrollOffset: number }) => {
scrollOffset = onScrollProps.scrollOffset
}, [])
return (
<div css={style.container} ref={setNodeRef}>
{isFeedEmpty ? (
<Box direction="column" align="center" justify="center" styles={style.tipContainer}>
<div>
<img width="110em" height="110em" src={Nurture} alt="Plant seed" css={style.logo} />
</div>
<div css={style.tipText}>You have no wallet activity yet.</div>
<div css={style.tipText}>
{isWalletEmpty
? 'Start by adding funds to your account.'
: 'Try a payment or an exchange.'}
</div>
</Box>
) : (
<FixedSizeList
height={height}
width="100%"
itemSize={itemSize}
itemCount={itemData.length}
itemData={itemData}
initialScrollOffset={scrollOffset}
onScroll={onScroll}
>
{FeedItem as any}
</FixedSizeList>
)}
</div>
)
}
Example #19
Source File: RealLogViewer.tsx From backstage with Apache License 2.0 | 4 votes |
export function RealLogViewer(props: RealLogViewerProps) {
const classes = useStyles({ classes: props.classes });
const listRef = useRef<FixedSizeList | null>(null);
// The processor keeps state that optimizes appending to the text
const processor = useMemo(() => new AnsiProcessor(), []);
const lines = processor.process(props.text);
const search = useLogViewerSearch(lines);
const selection = useLogViewerSelection(lines);
const location = useLocation();
useEffect(() => {
if (search.resultLine !== undefined && listRef.current) {
listRef.current.scrollToItem(search.resultLine - 1, 'center');
}
}, [search.resultLine]);
useEffect(() => {
if (location.hash) {
// #line-6 -> 6
const line = parseInt(location.hash.replace(/\D/g, ''), 10);
selection.setSelection(line, false);
}
}, []); // eslint-disable-line react-hooks/exhaustive-deps
const handleSelectLine = (
line: number,
event: { shiftKey: boolean; preventDefault: () => void },
) => {
selection.setSelection(line, event.shiftKey);
};
return (
<AutoSizer>
{({ height, width }) => (
<div style={{ width, height }} className={classes.root}>
<div className={classes.header}>
<LogViewerControls {...search} />
</div>
<FixedSizeList
ref={listRef}
className={classes.log}
height={height - HEADER_SIZE}
width={width}
itemData={search.lines}
itemSize={20}
itemCount={search.lines.length}
>
{({ index, style, data }) => {
const line = data[index];
const { lineNumber } = line;
return (
<div
style={{ ...style }}
className={classnames(classes.line, {
[classes.lineSelected]: selection.isSelected(lineNumber),
})}
>
{selection.shouldShowButton(lineNumber) && (
<IconButton
data-testid="copy-button"
size="small"
className={classes.lineCopyButton}
onClick={() => selection.copySelection()}
>
<CopyIcon fontSize="inherit" />
</IconButton>
)}
<a
role="row"
target="_self"
href={`#line-${lineNumber}`}
className={classes.lineNumber}
onClick={event => handleSelectLine(lineNumber, event)}
onKeyPress={event => handleSelectLine(lineNumber, event)}
>
{lineNumber}
</a>
<LogLine
line={line}
classes={classes}
searchText={search.searchText}
highlightResultIndex={
search.resultLine === lineNumber
? search.resultLineIndex
: undefined
}
/>
</div>
);
}}
</FixedSizeList>
</div>
)}
</AutoSizer>
);
}
Example #20
Source File: CurrencySearch.tsx From pancake-swap-testnet with MIT License | 4 votes |
export function CurrencySearch({
selectedCurrency,
onCurrencySelect,
otherSelectedCurrency,
showCommonBases,
onDismiss,
isOpen,
onChangeList,
}: CurrencySearchProps) {
const { t } = useTranslation()
const { chainId } = useActiveWeb3React()
const theme = useContext(ThemeContext)
const fixedList = useRef<FixedSizeList>()
const [searchQuery, setSearchQuery] = useState<string>('')
const [invertSearchOrder, setInvertSearchOrder] = useState<boolean>(false)
const allTokens = useAllTokens()
// if they input an address, use it
const isAddressSearch = isAddress(searchQuery)
const searchToken = useToken(searchQuery)
const showETH: boolean = useMemo(() => {
const s = searchQuery.toLowerCase().trim()
return s === '' || s === 'b' || s === 'bn' || s === 'bnb'
}, [searchQuery])
const tokenComparator = useTokenComparator(invertSearchOrder)
const audioPlay = useSelector<AppState, AppState['user']['audioPlay']>((state) => state.user.audioPlay)
const filteredTokens: Token[] = useMemo(() => {
if (isAddressSearch) return searchToken ? [searchToken] : []
return filterTokens(Object.values(allTokens), searchQuery)
}, [isAddressSearch, searchToken, allTokens, searchQuery])
const filteredSortedTokens: Token[] = useMemo(() => {
if (searchToken) return [searchToken]
const sorted = filteredTokens.sort(tokenComparator)
const symbolMatch = searchQuery
.toLowerCase()
.split(/\s+/)
.filter((s) => s.length > 0)
if (symbolMatch.length > 1) return sorted
return [
...(searchToken ? [searchToken] : []),
// sort any exact symbol matches first
...sorted.filter((token) => token.symbol?.toLowerCase() === symbolMatch[0]),
...sorted.filter((token) => token.symbol?.toLowerCase() !== symbolMatch[0]),
]
}, [filteredTokens, searchQuery, searchToken, tokenComparator])
const handleCurrencySelect = useCallback(
(currency: Currency) => {
onCurrencySelect(currency)
onDismiss()
if (audioPlay) {
const audio = document.getElementById('bgMusic') as HTMLAudioElement
if (audio) {
audio.play()
}
}
},
[onDismiss, onCurrencySelect, audioPlay]
)
// clear the input on open
useEffect(() => {
if (isOpen) setSearchQuery('')
}, [isOpen])
// manage focus on modal show
const inputRef = useRef<HTMLInputElement>()
const handleInput = useCallback((event) => {
const input = event.target.value
const checksummedInput = isAddress(input)
setSearchQuery(checksummedInput || input)
fixedList.current?.scrollTo(0)
}, [])
const handleEnter = useCallback(
(e: KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter') {
const s = searchQuery.toLowerCase().trim()
if (s === 'bnb') {
handleCurrencySelect(ETHER)
} else if (filteredSortedTokens.length > 0) {
if (
filteredSortedTokens[0].symbol?.toLowerCase() === searchQuery.trim().toLowerCase() ||
filteredSortedTokens.length === 1
) {
handleCurrencySelect(filteredSortedTokens[0])
}
}
}
},
[filteredSortedTokens, handleCurrencySelect, searchQuery]
)
const selectedListInfo = useSelectedListInfo()
const TranslateString = useI18n()
return (
<Column style={{ width: '100%', flex: '1 1' }}>
<PaddedColumn gap="14px">
<RowBetween>
<Text>
{TranslateString(82, 'Select a token')}
<QuestionHelper
text={TranslateString(
128,
'Find a token by searching for its name or symbol or by pasting its address below.'
)}
/>
</Text>
<CloseIcon onClick={onDismiss} />
</RowBetween>
<SearchInput
type="text"
id="token-search-input"
placeholder={t('tokenSearchPlaceholder')}
value={searchQuery}
ref={inputRef as RefObject<HTMLInputElement>}
onChange={handleInput}
onKeyDown={handleEnter}
/>
{showCommonBases && (
<CommonBases chainId={chainId} onSelect={handleCurrencySelect} selectedCurrency={selectedCurrency} />
)}
<RowBetween>
<Text fontSize="14px">{TranslateString(126, 'Token name')}</Text>
<SortButton ascending={invertSearchOrder} toggleSortOrder={() => setInvertSearchOrder((iso) => !iso)} />
</RowBetween>
</PaddedColumn>
<Separator />
<div style={{ flex: '1' }}>
<AutoSizer disableWidth>
{({ height }) => (
<CurrencyList
height={height}
showETH={showETH}
currencies={filteredSortedTokens}
onCurrencySelect={handleCurrencySelect}
otherCurrency={otherSelectedCurrency}
selectedCurrency={selectedCurrency}
fixedListRef={fixedList}
/>
)}
</AutoSizer>
</div>
{null && (
<>
<Separator />
<Card>
<RowBetween>
{selectedListInfo.current ? (
<Row>
{selectedListInfo.current.logoURI ? (
<ListLogo
style={{ marginRight: 12 }}
logoURI={selectedListInfo.current.logoURI}
alt={`${selectedListInfo.current.name} list logo`}
/>
) : null}
<Text id="currency-search-selected-list-name">{selectedListInfo.current.name}</Text>
</Row>
) : null}
<LinkStyledButton
style={{ fontWeight: 500, color: theme.colors.textSubtle, fontSize: 16 }}
onClick={onChangeList}
id="currency-search-change-list-button"
>
{selectedListInfo.current ? TranslateString(180, 'Change') : TranslateString(1152, 'Select a list')}
</LinkStyledButton>
</RowBetween>
</Card>
</>
)}
</Column>
)
}
Example #21
Source File: CurrencySearch.tsx From cheeseswap-interface with GNU General Public License v3.0 | 4 votes |
export function CurrencySearch({
selectedCurrency,
onCurrencySelect,
otherSelectedCurrency,
showCommonBases,
onDismiss,
isOpen,
onChangeList
}: CurrencySearchProps) {
const { t } = useTranslation()
const { chainId } = useActiveWeb3React()
const theme = useContext(ThemeContext)
const fixedList = useRef<FixedSizeList>()
const [searchQuery, setSearchQuery] = useState<string>('')
const [invertSearchOrder, setInvertSearchOrder] = useState<boolean>(false)
const allTokens = useAllTokens()
// if they input an address, use it
const isAddressSearch = isAddress(searchQuery)
const searchToken = useToken(searchQuery)
useEffect(() => {
if (isAddressSearch) {
ReactGA.event({
category: 'Currency Select',
action: 'Search by address',
label: isAddressSearch
})
}
}, [isAddressSearch])
const showETH: boolean = useMemo(() => {
const s = searchQuery.toLowerCase().trim()
return s === '' || s === 'e' || s === 'et' || s === 'eth'
}, [searchQuery])
const tokenComparator = useTokenComparator(invertSearchOrder)
const audioPlay = useSelector<AppState, AppState['user']['audioPlay']>(state => state.user.audioPlay)
const filteredTokens: Token[] = useMemo(() => {
if (isAddressSearch) return searchToken ? [searchToken] : []
return filterTokens(Object.values(allTokens), searchQuery)
}, [isAddressSearch, searchToken, allTokens, searchQuery])
const filteredSortedTokens: Token[] = useMemo(() => {
if (searchToken) return [searchToken]
const sorted = filteredTokens.sort(tokenComparator)
const symbolMatch = searchQuery
.toLowerCase()
.split(/\s+/)
.filter(s => s.length > 0)
if (symbolMatch.length > 1) return sorted
return [
...(searchToken ? [searchToken] : []),
// sort any exact symbol matches first
...sorted.filter(token => token.symbol?.toLowerCase() === symbolMatch[0]),
...sorted.filter(token => token.symbol?.toLowerCase() !== symbolMatch[0])
]
}, [filteredTokens, searchQuery, searchToken, tokenComparator])
const handleCurrencySelect = useCallback(
(currency: Currency) => {
onCurrencySelect(currency)
onDismiss()
if (audioPlay) {
// @ts-ignore
const audio = document.getElementById('bgMusic')
// @ts-ignore
audio && audio.play()
}
},
[onDismiss, onCurrencySelect, audioPlay]
)
// clear the input on open
useEffect(() => {
if (isOpen) setSearchQuery('')
}, [isOpen])
// manage focus on modal show
const inputRef = useRef<HTMLInputElement>()
const handleInput = useCallback(event => {
const input = event.target.value
const checksummedInput = isAddress(input)
setSearchQuery(checksummedInput || input)
fixedList.current?.scrollTo(0)
}, [])
const handleEnter = useCallback(
(e: KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter') {
const s = searchQuery.toLowerCase().trim()
if (s === 'eth') {
handleCurrencySelect(ETHER)
} else if (filteredSortedTokens.length > 0) {
if (
filteredSortedTokens[0].symbol?.toLowerCase() === searchQuery.trim().toLowerCase() ||
filteredSortedTokens.length === 1
) {
handleCurrencySelect(filteredSortedTokens[0])
}
}
}
},
[filteredSortedTokens, handleCurrencySelect, searchQuery]
)
const selectedListInfo = useSelectedListInfo()
return (
<Column style={{ width: '100%', flex: '1 1' }}>
<PaddedColumn gap="14px">
<RowBetween>
<Text fontWeight={700} fontSize={14}>
<TranslatedText translationId={82}>Select a token</TranslatedText>
<QuestionHelper
text={TranslateString(
130,
'Find a token by searching for its name or symbol or by pasting its address below.'
)}
/>
</Text>
<CloseIcon onClick={onDismiss} />
</RowBetween>
<SearchInput
type="text"
id="token-search-input"
placeholder={t('Search token or paste address')}
value={searchQuery}
ref={inputRef as RefObject<HTMLInputElement>}
onChange={handleInput}
onKeyDown={handleEnter}
/>
{showCommonBases && (
<CommonBases chainId={chainId} onSelect={handleCurrencySelect} selectedCurrency={selectedCurrency} />
)}
<RowBetween>
<Text fontSize={14} fontWeight={700}>
<TranslatedText translationId={126}>Token name</TranslatedText>
</Text>
<SortButton ascending={invertSearchOrder} toggleSortOrder={() => setInvertSearchOrder(iso => !iso)} />
</RowBetween>
</PaddedColumn>
<Separator />
<div style={{ flex: '1' }}>
<AutoSizer disableWidth>
{({ height }) => (
<CurrencyList
height={height}
showETH={showETH}
currencies={filteredSortedTokens}
onCurrencySelect={handleCurrencySelect}
otherCurrency={otherSelectedCurrency}
selectedCurrency={selectedCurrency}
fixedListRef={fixedList}
/>
)}
</AutoSizer>
</div>
{null && (
<>
<Separator />
<Card>
<RowBetween>
{selectedListInfo.current ? (
<Row>
{selectedListInfo.current.logoURI ? (
<ListLogo
style={{ marginRight: 12 }}
logoURI={selectedListInfo.current.logoURI}
alt={`${selectedListInfo.current.name} list logo`}
/>
) : null}
<TYPE.main id="currency-search-selected-list-name">{selectedListInfo.current.name}</TYPE.main>
</Row>
) : null}
<LinkStyledButton
style={{ fontWeight: 700, color: theme.colors.text2, fontSize: 14 }}
onClick={onChangeList}
id="currency-search-change-list-button"
>
{selectedListInfo.current ? 'Change' : 'Select a list'}
</LinkStyledButton>
</RowBetween>
</Card>
</>
)}
</Column>
)
}
Example #22
Source File: CurrencySearch.tsx From panther-frontend-dex with GNU General Public License v3.0 | 4 votes |
export function CurrencySearch({
selectedCurrency,
onCurrencySelect,
otherSelectedCurrency,
showCommonBases,
onDismiss,
isOpen,
onChangeList,
}: CurrencySearchProps) {
const { t } = useTranslation()
const { chainId } = useActiveWeb3React()
const theme = useContext(ThemeContext)
const fixedList = useRef<FixedSizeList>()
const [searchQuery, setSearchQuery] = useState<string>('')
const [invertSearchOrder, setInvertSearchOrder] = useState<boolean>(false)
const allTokens = useAllTokens()
// if they input an address, use it
const isAddressSearch = isAddress(searchQuery)
const searchToken = useToken(searchQuery)
const showETH: boolean = useMemo(() => {
const s = searchQuery.toLowerCase().trim()
return s === '' || s === 'e' || s === 'et' || s === 'eth'
}, [searchQuery])
const tokenComparator = useTokenComparator(invertSearchOrder)
const audioPlay = useSelector<AppState, AppState['user']['audioPlay']>((state) => state.user.audioPlay)
const filteredTokens: Token[] = useMemo(() => {
if (isAddressSearch) return searchToken ? [searchToken] : []
return filterTokens(Object.values(allTokens), searchQuery)
}, [isAddressSearch, searchToken, allTokens, searchQuery])
const filteredSortedTokens: Token[] = useMemo(() => {
if (searchToken) return [searchToken]
const sorted = filteredTokens.sort(tokenComparator)
const symbolMatch = searchQuery
.toLowerCase()
.split(/\s+/)
.filter((s) => s.length > 0)
if (symbolMatch.length > 1) return sorted
return [
...(searchToken ? [searchToken] : []),
// sort any exact symbol matches first
...sorted.filter((token) => token.symbol?.toLowerCase() === symbolMatch[0]),
...sorted.filter((token) => token.symbol?.toLowerCase() !== symbolMatch[0]),
]
}, [filteredTokens, searchQuery, searchToken, tokenComparator])
const handleCurrencySelect = useCallback(
(currency: Currency) => {
onCurrencySelect(currency)
onDismiss()
if (audioPlay) {
const audio = document.getElementById('bgMusic') as HTMLAudioElement
if (audio) {
audio.play()
}
}
},
[onDismiss, onCurrencySelect, audioPlay]
)
// clear the input on open
useEffect(() => {
if (isOpen) setSearchQuery('')
}, [isOpen])
// manage focus on modal show
const inputRef = useRef<HTMLInputElement>()
const handleInput = useCallback((event) => {
const input = event.target.value
const checksummedInput = isAddress(input)
setSearchQuery(checksummedInput || input)
fixedList.current?.scrollTo(0)
}, [])
const handleEnter = useCallback(
(e: KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter') {
const s = searchQuery.toLowerCase().trim()
if (s === 'eth') {
handleCurrencySelect(ETHER)
} else if (filteredSortedTokens.length > 0) {
if (
filteredSortedTokens[0].symbol?.toLowerCase() === searchQuery.trim().toLowerCase() ||
filteredSortedTokens.length === 1
) {
handleCurrencySelect(filteredSortedTokens[0])
}
}
}
},
[filteredSortedTokens, handleCurrencySelect, searchQuery]
)
const selectedListInfo = useSelectedListInfo()
return (
<Column style={{ width: '100%', flex: '1 1' }}>
<PaddedColumn gap="14px">
<RowBetween>
<Text>
<TranslatedText translationId={82}>Select a token</TranslatedText>
<QuestionHelper
text={TranslateString(
130,
'Find a token by searching for its name or symbol or by pasting its address below.'
)}
/>
</Text>
<CloseIcon onClick={onDismiss} />
</RowBetween>
<SearchInput
type="text"
id="token-search-input"
placeholder={t('tokenSearchPlaceholder')}
value={searchQuery}
ref={inputRef as RefObject<HTMLInputElement>}
onChange={handleInput}
onKeyDown={handleEnter}
/>
{showCommonBases && (
<CommonBases chainId={chainId} onSelect={handleCurrencySelect} selectedCurrency={selectedCurrency} />
)}
<RowBetween>
<Text fontSize="14px">
<TranslatedText translationId={126}>Token name</TranslatedText>
</Text>
<SortButton ascending={invertSearchOrder} toggleSortOrder={() => setInvertSearchOrder((iso) => !iso)} />
</RowBetween>
</PaddedColumn>
<Separator />
<div style={{ flex: '1' }}>
<AutoSizer disableWidth>
{({ height }) => (
<CurrencyList
height={height}
showETH={showETH}
currencies={filteredSortedTokens}
onCurrencySelect={handleCurrencySelect}
otherCurrency={otherSelectedCurrency}
selectedCurrency={selectedCurrency}
fixedListRef={fixedList}
/>
)}
</AutoSizer>
</div>
{null && (
<>
<Separator />
<Card>
<RowBetween>
{selectedListInfo.current ? (
<Row>
{selectedListInfo.current.logoURI ? (
<ListLogo
style={{ marginRight: 12 }}
logoURI={selectedListInfo.current.logoURI}
alt={`${selectedListInfo.current.name} list logo`}
/>
) : null}
<Main id="currency-search-selected-list-name">{selectedListInfo.current.name}</Main>
</Row>
) : null}
<LinkStyledButton
style={{ fontWeight: 500, color: theme.colors.textSubtle, fontSize: 16 }}
onClick={onChangeList}
id="currency-search-change-list-button"
>
{selectedListInfo.current ? 'Change' : 'Select a list'}
</LinkStyledButton>
</RowBetween>
</Card>
</>
)}
</Column>
)
}
Example #23
Source File: CurrencyList.tsx From forward.swaps with GNU General Public License v3.0 | 4 votes |
export default function CurrencyList({
height,
currencies,
selectedCurrency,
onCurrencySelect,
otherCurrency,
fixedListRef,
showETH,
showImportView,
setImportToken
}: {
height: number
currencies: Currency[]
selectedCurrency?: Currency | null
onCurrencySelect: (currency: Currency) => void
otherCurrency?: Currency | null
fixedListRef?: MutableRefObject<FixedSizeList | undefined>
showETH: boolean
showImportView: () => void
setImportToken: (token: Token) => void
}) {
const itemData = useMemo(() => (showETH ? [Currency.ETHER, ...currencies] : currencies), [currencies, showETH])
const { chainId } = useActiveWeb3React()
const inactiveTokens: {
[address: string]: Token
} = useAllInactiveTokens()
const Row = useCallback(
({ data, index, style }) => {
const currency: Currency = data[index]
const isSelected = Boolean(selectedCurrency && currencyEquals(selectedCurrency, currency))
const otherSelected = Boolean(otherCurrency && currencyEquals(otherCurrency, currency))
const handleSelect = () => onCurrencySelect(currency)
const token = wrappedCurrency(currency, chainId)
const showImport = inactiveTokens && token && Object.keys(inactiveTokens).includes(token.address)
if (showImport && token) {
return (
<ImportRow
style={style}
token={token}
showImportView={showImportView}
setImportToken={setImportToken}
dim={true}
/>
)
} else {
return (
<CurrencyRow
style={style}
currency={currency}
isSelected={isSelected}
onSelect={handleSelect}
otherSelected={otherSelected}
/>
)
}
},
[chainId, inactiveTokens, onCurrencySelect, otherCurrency, selectedCurrency, setImportToken, showImportView]
)
const itemKey = useCallback((index: number, data: any) => currencyKey(data[index]), [])
return (
<FixedSizeList
height={height}
ref={fixedListRef as any}
width="100%"
itemData={itemData}
itemCount={itemData.length}
itemSize={56}
itemKey={itemKey}
>
{Row}
</FixedSizeList>
)
}
Example #24
Source File: navigator.tsx From utopia with MIT License | 4 votes |
NavigatorComponent = React.memo(() => {
const { dispatch, minimised, visibleNavigatorTargets } = useEditorState((store) => {
return {
dispatch: store.dispatch,
minimised: store.editor.navigator.minimised,
visibleNavigatorTargets: store.derived.visibleNavigatorTargets,
}
}, 'NavigatorComponent')
const onFocus = React.useCallback(
(e: React.FocusEvent<HTMLElement>) => {
dispatch([setFocus('navigator')])
},
[dispatch],
)
const onMouseLeave = React.useCallback(
(e: React.MouseEvent<HTMLElement>) => {
dispatch([clearHighlightedViews()], 'everyone')
},
[dispatch],
)
const onContextMenu = React.useCallback(
(event: React.MouseEvent<HTMLElement>) => {
dispatch([showContextMenu('context-menu-navigator', event.nativeEvent)], 'everyone')
},
[dispatch],
)
const toggleTwirler = React.useCallback(() => {
dispatch([EditorActions.togglePanel('navigator')])
}, [dispatch])
const ItemList = (size: Size) => {
if (size.height == null) {
return null
} else {
return (
<FixedSizeList
width={'100%'}
height={size.height}
itemSize={UtopiaTheme.layout.rowHeight.smaller}
itemCount={visibleNavigatorTargets.length}
layout={'vertical'}
style={{ overflowX: 'hidden' }}
>
{Item}
</FixedSizeList>
)
}
}
return (
<Section
data-name='Navigator'
onFocus={onFocus}
onMouseLeave={onMouseLeave}
onContextMenu={onContextMenu}
id={NavigatorContainerId}
tabIndex={-1}
style={{
zIndex: 1,
flexGrow: 1,
height: '100%',
display: 'flex',
flexDirection: 'column',
alignItems: 'stretch',
justifyContent: 'stretch',
overscrollBehavior: 'contain',
}}
>
<SectionTitleRow minimised={minimised} toggleMinimised={toggleTwirler}>
<FlexRow flexGrow={1}>
<Title>Structure</Title>
</FlexRow>
</SectionTitleRow>
<SectionBodyArea
minimised={minimised}
flexGrow={1}
style={{
flexGrow: 1,
overscrollBehavior: 'contain',
display: 'flex',
alignItems: 'stretch',
justifyContent: 'stretch',
}}
>
<ElementContextMenu contextMenuInstance={'context-menu-navigator'} />
<FlexColumn
style={{
flexGrow: 1,
flexShrink: 1,
flexBasis: '100%',
overflowX: 'hidden',
}}
>
<AutoSizer
disableWidth={true}
style={{
overscrollBehavior: 'contain',
overflowX: 'hidden',
height: '100%',
}}
>
{ItemList}
</AutoSizer>
</FlexColumn>
</SectionBodyArea>
</Section>
)
})
Example #25
Source File: CurrencySearch.tsx From interface-v2 with GNU General Public License v3.0 | 4 votes |
CurrencySearch: React.FC<CurrencySearchProps> = ({
selectedCurrency,
onCurrencySelect,
otherSelectedCurrency,
showCommonBases,
onDismiss,
isOpen,
}) => {
const classes = useStyles();
const { t } = useTranslation();
const { account, chainId } = useActiveWeb3React();
const dispatch = useDispatch<AppDispatch>();
const fixedList = useRef<FixedSizeList>();
const handleInput = useCallback((input: string) => {
const checksummedInput = isAddress(input);
setSearchQuery(checksummedInput || input);
fixedList.current?.scrollTo(0);
}, []);
const [searchQuery, setSearchQuery] = useState<string>('');
const [searchQueryInput, setSearchQueryInput] = useDebouncedChangeHandler(
searchQuery,
handleInput,
);
const allTokens = useAllTokens();
// if they input an address, use it
const isAddressSearch = isAddress(searchQuery);
const searchToken = useToken(searchQuery);
useEffect(() => {
if (isAddressSearch) {
ReactGA.event({
category: 'Currency Select',
action: 'Search by address',
label: isAddressSearch,
});
}
}, [isAddressSearch]);
const showETH: boolean = useMemo(() => {
const s = searchQuery.toLowerCase().trim();
return s === '' || s === 'e' || s === 'et' || s === 'eth';
}, [searchQuery]);
const tokenComparator = useTokenComparator(false);
const filteredTokens: Token[] = useMemo(() => {
if (isAddressSearch) return searchToken ? [searchToken] : [];
return filterTokens(Object.values(allTokens), searchQuery);
}, [isAddressSearch, searchToken, allTokens, searchQuery]);
const filteredSortedTokens: Token[] = useMemo(() => {
if (searchToken) return [searchToken];
const sorted = filteredTokens.sort(tokenComparator);
const symbolMatch = searchQuery
.toLowerCase()
.split(/\s+/)
.filter((s) => s.length > 0);
if (symbolMatch.length > 1) return sorted;
return [
...(searchToken ? [searchToken] : []),
// sort any exact symbol matches first
...sorted.filter(
(token) => token.symbol?.toLowerCase() === symbolMatch[0],
),
...sorted.filter(
(token) => token.symbol?.toLowerCase() !== symbolMatch[0],
),
];
}, [filteredTokens, searchQuery, searchToken, tokenComparator]);
const handleCurrencySelect = useCallback(
(currency: Currency) => {
onCurrencySelect(currency);
onDismiss();
},
[onDismiss, onCurrencySelect],
);
// clear the input on open
useEffect(() => {
if (isOpen) setSearchQuery('');
}, [isOpen]);
const handleEnter = useCallback(
(e: KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter') {
const s = searchQuery.toLowerCase().trim();
if (s === 'eth') {
handleCurrencySelect(ETHER);
} else if (filteredSortedTokens.length > 0) {
if (
filteredSortedTokens[0].symbol?.toLowerCase() ===
searchQuery.trim().toLowerCase() ||
filteredSortedTokens.length === 1
) {
handleCurrencySelect(filteredSortedTokens[0]);
}
}
}
},
[filteredSortedTokens, handleCurrencySelect, searchQuery],
);
// manage focus on modal show
const inputRef = useRef<HTMLInputElement>();
let selectedListInfo = useSelectedListInfo();
if (selectedListInfo.current === null) {
dispatch(selectList(GlobalConst.utils.DEFAULT_TOKEN_LIST_URL));
}
selectedListInfo = useSelectedListInfo();
return (
<Box className={classes.wrapper}>
<Box className={classes.header}>
<Typography variant='subtitle2'>Select a token</Typography>
<CloseIcon onClick={onDismiss} />
</Box>
<Box className={classes.searchInputWrapper}>
<SearchIcon />
<input
type='text'
placeholder={t('tokenSearchPlaceholder')}
value={searchQueryInput}
ref={inputRef as RefObject<HTMLInputElement>}
onChange={(e) => setSearchQueryInput(e.target.value)}
onKeyDown={handleEnter}
/>
</Box>
{showCommonBases && (
<CommonBases
chainId={chainId}
onSelect={handleCurrencySelect}
selectedCurrency={selectedCurrency}
/>
)}
<Divider />
<Box flex={1}>
<AutoSizer disableWidth>
{({ height }) => (
<CurrencyList
showETH={showETH}
height={height}
currencies={filteredSortedTokens}
onCurrencySelect={handleCurrencySelect}
otherCurrency={otherSelectedCurrency}
selectedCurrency={selectedCurrency}
fixedListRef={fixedList}
/>
)}
</AutoSizer>
</Box>
<Box className={classes.footer} />
</Box>
);
}
Example #26
Source File: CurrencySearch.tsx From luaswap-interface with GNU General Public License v3.0 | 4 votes |
export function CurrencySearch({
selectedCurrency,
onCurrencySelect,
otherSelectedCurrency,
showCommonBases,
onDismiss,
isOpen,
onChangeList
}: CurrencySearchProps) {
const { t } = useTranslation()
const { chainId } = useActiveWeb3React()
const IsTomo = IsTomoChain(chainId)
const theme = useContext(ThemeContext)
const fixedList = useRef<FixedSizeList>()
const [searchQuery, setSearchQuery] = useState<string>('')
const [invertSearchOrder, setInvertSearchOrder] = useState<boolean>(false)
const allTokens = useAllTokens()
// if they input an address, use it
const isAddressSearch = isAddress(searchQuery)
const searchToken = useToken(searchQuery)
useEffect(() => {
if (isAddressSearch) {
ReactGA.event({
category: 'Currency Select',
action: 'Search by address',
label: isAddressSearch
})
}
}, [isAddressSearch])
const showETH: boolean = useMemo(() => {
const s = searchQuery.toLowerCase().trim()
if (IsTomo) {
return s === '' || s === 't' || s === 'to' || s === 'tom' || s === 'tomo'
} else {
return s === '' || s === 'e' || s === 'et' || s === 'eth'
}
}, [searchQuery])
const tokenComparator = useTokenComparator(invertSearchOrder)
const filteredTokens: Token[] = useMemo(() => {
if (isAddressSearch) return searchToken ? [searchToken] : []
return filterTokens(Object.values(allTokens), searchQuery)
}, [isAddressSearch, searchToken, allTokens, searchQuery])
const filteredSortedTokens: Token[] = useMemo(() => {
if (searchToken) return [searchToken]
const sorted = filteredTokens.sort(tokenComparator)
const symbolMatch = searchQuery
.toLowerCase()
.split(/\s+/)
.filter(s => s.length > 0)
if (symbolMatch.length > 1) return sorted
return [
...(searchToken ? [searchToken] : []),
// sort any exact symbol matches first
...sorted.filter(token => token.symbol?.toLowerCase() === symbolMatch[0]),
...sorted.filter(token => token.symbol?.toLowerCase() !== symbolMatch[0])
]
}, [filteredTokens, searchQuery, searchToken, tokenComparator])
const handleCurrencySelect = useCallback(
(currency: Currency) => {
onCurrencySelect(currency)
onDismiss()
},
[onDismiss, onCurrencySelect]
)
// clear the input on open
useEffect(() => {
if (isOpen) setSearchQuery('')
}, [isOpen])
// manage focus on modal show
const inputRef = useRef<HTMLInputElement>()
const handleInput = useCallback(event => {
const input = event.target.value
const checksummedInput = isAddress(input)
setSearchQuery(checksummedInput || input)
fixedList.current?.scrollTo(0)
}, [])
const handleEnter = useCallback(
(e: KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter') {
const s = searchQuery.toLowerCase().trim()
if (s === 'eth') {
handleCurrencySelect(ETHER)
} else if (s === 'tomo' && IsTomo) {
handleCurrencySelect(TOMO)
} else if (filteredSortedTokens.length > 0) {
if (
filteredSortedTokens[0].symbol?.toLowerCase() === searchQuery.trim().toLowerCase() ||
filteredSortedTokens.length === 1
) {
handleCurrencySelect(filteredSortedTokens[0])
}
}
}
},
[filteredSortedTokens, handleCurrencySelect, searchQuery]
)
const selectedListInfo = useSelectedListInfo()
return (
<Column style={{ width: '100%', flex: '1 1' }}>
<PaddedColumn gap="14px">
<RowBetween>
<Text fontWeight={500} fontSize={16}>
Select a token
<QuestionHelper text="Find a token by searching for its name or symbol or by pasting its address below." />
</Text>
<CloseIcon onClick={onDismiss} />
</RowBetween>
<SearchInput
type="text"
id="token-search-input"
placeholder={t('tokenSearchPlaceholder')}
value={searchQuery}
ref={inputRef as RefObject<HTMLInputElement>}
onChange={handleInput}
onKeyDown={handleEnter}
/>
{showCommonBases && (
<CommonBases chainId={chainId} onSelect={handleCurrencySelect} selectedCurrency={selectedCurrency} />
)}
<RowBetween>
<Text fontSize={14} fontWeight={500}>
Token Name
</Text>
<SortButton ascending={invertSearchOrder} toggleSortOrder={() => setInvertSearchOrder(iso => !iso)} />
</RowBetween>
</PaddedColumn>
<Separator />
<div style={{ flex: '1' }}>
<AutoSizer disableWidth>
{({ height }) => (
<CurrencyList
height={height}
showETH={showETH}
currencies={filteredSortedTokens}
onCurrencySelect={handleCurrencySelect}
otherCurrency={otherSelectedCurrency}
selectedCurrency={selectedCurrency}
fixedListRef={fixedList}
/>
)}
</AutoSizer>
</div>
<Separator />
<Card>
<RowBetween>
{selectedListInfo.current ? (
<Row>
{selectedListInfo.current.logoURI ? (
<ListLogo
style={{ marginRight: 12 }}
logoURI={selectedListInfo.current.logoURI}
alt={`${selectedListInfo.current.name} list logo`}
/>
) : null}
<TYPE.main id="currency-search-selected-list-name">{selectedListInfo.current.name}</TYPE.main>
</Row>
) : null}
<LinkStyledButton
style={{ fontWeight: 500, color: theme.text2, fontSize: 16, backgroundColor: theme.bg3 }}
onClick={onChangeList}
id="currency-search-change-list-button"
>
{/* {selectedListInfo.current ? 'Change' : 'Select a list'} */}
</LinkStyledButton>
</RowBetween>
</Card>
</Column>
)
}
Example #27
Source File: CurrencyList.tsx From cuiswap with GNU General Public License v3.0 | 4 votes |
export default function CurrencyList({
currencies,
allBalances,
selectedCurrency,
onCurrencySelect,
otherCurrency,
showSendWithSwap
}: {
currencies: Currency[]
selectedCurrency: Currency
allBalances: { [tokenAddress: string]: CurrencyAmount }
onCurrencySelect: (currency: Currency) => void
otherCurrency: Currency
showSendWithSwap?: boolean
}) {
const { account, chainId } = useActiveWeb3React()
const theme = useContext(ThemeContext)
const allTokens = useAllTokens()
const defaultTokens = useDefaultTokenList()
const addToken = useAddUserToken()
const removeToken = useRemoveUserAddedToken()
const ETHBalance = useETHBalances([account])[account]
const CurrencyRow = useMemo(() => {
return memo(function CurrencyRow({ index, style }: { index: number; style: CSSProperties }) {
const currency = index === 0 ? Currency.ETHER : currencies[index - 1]
const key = currencyKey(currency)
const isDefault = isDefaultToken(defaultTokens, currency)
const customAdded = Boolean(!isDefault && currency instanceof Token && allTokens[currency.address])
const balance = currency === ETHER ? ETHBalance : allBalances[key]
const zeroBalance = balance && JSBI.equal(JSBI.BigInt(0), balance.raw)
const isSelected = Boolean(selectedCurrency && currencyEquals(currency, selectedCurrency))
const otherSelected = Boolean(otherCurrency && currencyEquals(otherCurrency, currency))
return (
<MenuItem
style={style}
className={`token-item-${key}`}
onClick={() => (isSelected ? null : onCurrencySelect(currency))}
disabled={isSelected}
selected={otherSelected}
>
<RowFixed>
<CurrencyLogo currency={currency} size={'24px'} style={{ marginRight: '14px' }} />
<Column>
<Text fontWeight={500}>{currency.symbol}</Text>
<FadedSpan>
{customAdded ? (
<TYPE.main fontWeight={500}>
Added by user
<LinkStyledButton
onClick={event => {
event.stopPropagation()
if (currency instanceof Token) removeToken(chainId, currency.address)
}}
>
(Remove)
</LinkStyledButton>
</TYPE.main>
) : null}
{!isDefault && !customAdded ? (
<TYPE.main fontWeight={500}>
Found by address
<LinkStyledButton
onClick={event => {
event.stopPropagation()
if (currency instanceof Token) addToken(currency)
}}
>
(Add)
</LinkStyledButton>
</TYPE.main>
) : null}
</FadedSpan>
</Column>
</RowFixed>
<AutoColumn>
{balance ? (
<Text>
{zeroBalance && showSendWithSwap ? (
<ButtonSecondary padding={'4px 8px'}>
<Text textAlign="center" fontWeight={500} fontSize={14} color={theme.primary1}>
Send With Swap
</Text>
</ButtonSecondary>
) : balance ? (
balance.toSignificant(6)
) : (
'-'
)}
</Text>
) : account ? (
<Loader />
) : (
'-'
)}
</AutoColumn>
</MenuItem>
)
})
}, [
ETHBalance,
account,
addToken,
allBalances,
allTokens,
chainId,
currencies,
defaultTokens,
onCurrencySelect,
otherCurrency,
removeToken,
selectedCurrency,
showSendWithSwap,
theme.primary1
])
return (
<FixedSizeList
width="100%"
height={500}
itemCount={currencies.length + 1}
itemSize={56}
style={{ flex: '1' }}
itemKey={index => currencyKey(currencies[index])}
>
{CurrencyRow}
</FixedSizeList>
)
}
Example #28
Source File: index.tsx From calories-in with MIT License | 4 votes |
function FoodsList({
selection,
searchInputRef,
onFoodPreview,
forwardedRef,
allowsFiltering = true,
itemUsageType = 'selectOrPreview',
...rest
}: Props) {
const { allFoods, userFoods } = useFoods()
const listRef = useRef<FixedSizeList>(null)
const filter = useFoodsFilter()
const foodsFilterActions = useFoodsFilterActions()
const filteredFoods = useFilterFoods(allFoods, userFoods, filter)
useEffect(() => {
if (filter.categoryId) {
listRef.current?.scrollToItem(0, 'start')
}
}, [filter.categoryId])
useImperativeHandle(forwardedRef, () => ({
scrollToFood: (food: Food) => {
foodsFilterActions.resetCategoryIdAndQuery()
if (listRef.current) {
const foods = filter.onlyFoodsAddedByUser ? userFoods : allFoods
const index = foods.map(({ id }) => id).indexOf(food.id)
listRef.current.scrollToItem(index, 'center')
}
},
}))
function onFoodSelect(food: Food) {
if (selection) {
selection.toggleItem(food)
const input = searchInputRef?.current
if (input && !isMobile) {
input.focus()
input.setSelectionRange(0, input.value.length)
}
}
}
return (
<Flex flexDirection="column" {...rest}>
<HStack spacing={3}>
{allowsFiltering && (
<Box>
<FoodsFilterPopoverOrModal />
</Box>
)}
<InputGroup size="md" flex={4}>
<InputLeftElement
pointerEvents="none"
children={
<SearchStyled pointerEvents="none" size={20} color="gray.400" />
}
/>
<Input
ref={searchInputRef}
value={filter.query}
onChange={(event: ChangeEvent<HTMLInputElement>) =>
foodsFilterActions.updateFilter({ query: event.target.value })
}
placeholder="Search"
/>
</InputGroup>
</HStack>
<Divider mt={3} width="100%" />
{filteredFoods.length > 0 ? (
<VirtualizedList
ref={listRef}
foodsCount={filteredFoods.length}
isFoodSelected={food =>
selection ? selection.isIdSelected(food.id) : false
}
getFood={index => filteredFoods[index]}
onFoodSelect={onFoodSelect}
onFoodPreview={onFoodPreview || (() => {})}
itemUsageType={itemUsageType}
/>
) : (
<Flex flex={1} alignItems="center" justifyContent="center">
<Text textColor="gray.500">No foods found</Text>
</Flex>
)}
</Flex>
)
}
Example #29
Source File: CurrencyList.tsx From vvs-ui with GNU General Public License v3.0 | 4 votes |
export default function CurrencyList({
height,
currencies,
selectedCurrency,
onCurrencySelect,
otherCurrency,
fixedListRef,
showETH,
showImportView,
setImportToken,
breakIndex,
}: {
height: number
currencies: Currency[]
selectedCurrency?: Currency | null
onCurrencySelect: (currency: Currency) => void
otherCurrency?: Currency | null
fixedListRef?: MutableRefObject<FixedSizeList | undefined>
showETH: boolean
showImportView: () => void
setImportToken: (token: Token) => void
breakIndex: number | undefined
}) {
const itemData: (Currency | undefined)[] = useMemo(() => {
let formatted: (Currency | undefined)[] = showETH ? [Currency.ETHER, ...currencies] : currencies
if (breakIndex !== undefined) {
formatted = [...formatted.slice(0, breakIndex), undefined, ...formatted.slice(breakIndex, formatted.length)]
}
return formatted
}, [breakIndex, currencies, showETH])
const { chainId } = useActiveWeb3React()
const { t } = useTranslation()
const inactiveTokens: {
[address: string]: Token
} = useAllInactiveTokens()
const Row = useCallback(
({ data, index, style }) => {
const currency: Currency = data[index]
const isSelected = Boolean(selectedCurrency && currencyEquals(selectedCurrency, currency))
const otherSelected = Boolean(otherCurrency && currencyEquals(otherCurrency, currency))
const handleSelect = () => onCurrencySelect(currency)
const token = wrappedCurrency(currency, chainId)
const showImport = inactiveTokens && token && Object.keys(inactiveTokens).includes(token.address)
if (index === breakIndex || !data) {
return (
<FixedContentRow style={style}>
<LightGreyCard padding="8px 12px" borderRadius="8px">
<RowBetween>
<Text small>{t('Expanded results from inactive Token Lists')}</Text>
<QuestionHelper
text={t(
"Tokens from inactive lists. Import specific tokens below or click 'Manage' to activate more lists.",
)}
ml="4px"
/>
</RowBetween>
</LightGreyCard>
</FixedContentRow>
)
}
if (showImport && token) {
return (
<ImportRow style={style} token={token} showImportView={showImportView} setImportToken={setImportToken} dim />
)
}
return (
<CurrencyRow
style={style}
currency={currency}
isSelected={isSelected}
onSelect={handleSelect}
otherSelected={otherSelected}
/>
)
},
[
chainId,
inactiveTokens,
onCurrencySelect,
otherCurrency,
selectedCurrency,
setImportToken,
showImportView,
breakIndex,
t,
],
)
const itemKey = useCallback((index: number, data: any) => currencyKey(data[index]), [])
return (
<FixedSizeList
height={height}
ref={fixedListRef as any}
width="100%"
itemData={itemData}
itemCount={itemData.length}
itemSize={56}
itemKey={itemKey}
>
{Row}
</FixedSizeList>
)
}