UNPKG

@wordpress/components

Version:
140 lines (134 loc) 4.18 kB
/** * External dependencies */ import { ActivityIndicator, FlatList, View } from 'react-native'; /** * WordPress dependencies */ import { debounce } from '@wordpress/compose'; import { useState, useEffect, useRef } from '@wordpress/element'; import { useSelect } from '@wordpress/data'; /** * Internal dependencies */ import styles from './styles.scss'; import BottomSheet from '../bottom-sheet'; import { BottomSheetConsumer } from '../bottom-sheet/bottom-sheet-context'; import { jsx as _jsx } from "react/jsx-runtime"; const PER_PAGE = 20; const REQUEST_DEBOUNCE_DELAY = 400; const MINIMUM_QUERY_SIZE = 2; const meetsThreshold = query => MINIMUM_QUERY_SIZE <= query.length; export default function LinkPickerResults({ query, onLinkPicked, directEntry }) { const [links, setLinks] = useState([directEntry]); const [hasAllSuggestions, setHasAllSuggestions] = useState(false); const nextPage = useRef(1); const pendingRequest = useRef(); const clearRequest = () => { pendingRequest.current = null; }; // A stable debounced function to fetch suggestions and append. const { fetchMoreSuggestions } = useSelect(select => { const { getSettings } = select('core/block-editor'); const fetchLinkSuggestions = async ({ search }) => { if (meetsThreshold(search)) { return await getSettings().__experimentalFetchLinkSuggestions(search, { page: nextPage.current, type: 'post', perPage: PER_PAGE }); } }; const fetchMore = async ({ query: search, links: currentSuggestions }) => { // Return early if we've already detected the end of data or we are // already awaiting a response. if (hasAllSuggestions || pendingRequest.current) { return; } const request = fetchLinkSuggestions({ search }); pendingRequest.current = request; const suggestions = await request; // Only update links for the most recent request. if (suggestions && request === pendingRequest.current) { // Since we don't have the response header, we check if the results // are truncated to determine we've reached the end. if (suggestions.length < PER_PAGE) { setHasAllSuggestions(true); } setLinks([...currentSuggestions, ...suggestions]); nextPage.current++; } clearRequest(); }; return { fetchMoreSuggestions: debounce(fetchMore, REQUEST_DEBOUNCE_DELAY) }; // Not adding dependencies for now, to avoid introducing a regression // (see https://github.com/WordPress/gutenberg/pull/23922#discussion_r1170634879). }, []); // Prevent setting state when unmounted. useEffect(() => clearRequest, []); // Any time the query changes, we reset pagination. useEffect(() => { clearRequest(); nextPage.current = 1; setHasAllSuggestions(false); setLinks([directEntry]); fetchMoreSuggestions({ query, links: [directEntry] }); // See https://github.com/WordPress/gutenberg/pull/41166 }, [query]); const onEndReached = () => fetchMoreSuggestions({ query, links }); const spinner = !hasAllSuggestions && meetsThreshold(query) && /*#__PURE__*/_jsx(View, { style: styles.spinner, testID: "link-picker-loading", children: /*#__PURE__*/_jsx(ActivityIndicator, { animating: true }) }); return /*#__PURE__*/_jsx(BottomSheetConsumer, { children: ({ listProps }) => /*#__PURE__*/_jsx(FlatList, { data: links, keyboardShouldPersistTaps: "always", renderItem: ({ item }) => /*#__PURE__*/_jsx(BottomSheet.LinkSuggestionItemCell, { suggestion: item, onLinkPicked: onLinkPicked }), keyExtractor: ({ url, type }) => `${url}-${type}`, onEndReached: onEndReached, onEndReachedThreshold: 0.1, initialNumToRender: PER_PAGE, ListFooterComponent: spinner, ...listProps, contentContainerStyle: [...listProps.contentContainerStyle, styles.list] }) }); } //# sourceMappingURL=link-picker-results.native.js.map