xref: /expo/docs/ui/components/CommandMenu/utils.ts (revision 0a4db0c7)
189d2c67fSBartosz Kaszubowskiimport type { Dispatch, SetStateAction } from 'react';
289d2c67fSBartosz Kaszubowski
389d2c67fSBartosz Kaszubowskiimport type { AlgoliaItemHierarchy, AlgoliaItemType } from './types';
489d2c67fSBartosz Kaszubowski
589d2c67fSBartosz Kaszubowskiexport const getItemsAsync = async <T>(
689d2c67fSBartosz Kaszubowski  query: string,
789d2c67fSBartosz Kaszubowski  fetcher: (query: string, version?: string) => Promise<Response>,
889d2c67fSBartosz Kaszubowski  setter: Dispatch<SetStateAction<T[]>>,
989d2c67fSBartosz Kaszubowski  version?: string
1089d2c67fSBartosz Kaszubowski) => {
1189d2c67fSBartosz Kaszubowski  const { hits, libraries } = await fetcher(query, version).then(response => response.json());
1289d2c67fSBartosz Kaszubowski  setter(hits || libraries || []);
1389d2c67fSBartosz Kaszubowski};
1489d2c67fSBartosz Kaszubowski
1589d2c67fSBartosz Kaszubowskiconst getAlgoliaFetchParams = (
1689d2c67fSBartosz Kaszubowski  query: string,
1789d2c67fSBartosz Kaszubowski  appId: string,
1889d2c67fSBartosz Kaszubowski  apiKey: string,
1989d2c67fSBartosz Kaszubowski  indexName: string,
2089d2c67fSBartosz Kaszubowski  hits: number,
2189d2c67fSBartosz Kaszubowski  additionalParams: object = {}
2289d2c67fSBartosz Kaszubowski): [string, RequestInit] => [
2389d2c67fSBartosz Kaszubowski  `https://${appId}-dsn.algolia.net/1/indexes/${indexName}/query`,
2489d2c67fSBartosz Kaszubowski  {
2589d2c67fSBartosz Kaszubowski    method: 'POST',
2689d2c67fSBartosz Kaszubowski    headers: {
2789d2c67fSBartosz Kaszubowski      'X-Algolia-Application-Id': appId,
2889d2c67fSBartosz Kaszubowski      'X-Algolia-API-Key': apiKey,
2989d2c67fSBartosz Kaszubowski    },
3089d2c67fSBartosz Kaszubowski    body: JSON.stringify({
3189d2c67fSBartosz Kaszubowski      params: `query=${query}&hitsPerPage=${hits}`,
3289d2c67fSBartosz Kaszubowski      highlightPreTag: '<mark>',
3389d2c67fSBartosz Kaszubowski      highlightPostTag: '</mark>',
3489d2c67fSBartosz Kaszubowski      ...additionalParams,
3589d2c67fSBartosz Kaszubowski    }),
3689d2c67fSBartosz Kaszubowski  },
3789d2c67fSBartosz Kaszubowski];
3889d2c67fSBartosz Kaszubowski
3989d2c67fSBartosz Kaszubowskiexport const getExpoDocsResults = (query: string, version?: string) => {
4089d2c67fSBartosz Kaszubowski  return fetch(
41*0a4db0c7SBartosz Kaszubowski    ...getAlgoliaFetchParams(query, 'QEX7PB7D46', '6652d26570e8628af4601e1d78ad456b', 'expo', 20, {
4289d2c67fSBartosz Kaszubowski      facetFilters: [['version:none', `version:${version}`]],
4389d2c67fSBartosz Kaszubowski    })
4489d2c67fSBartosz Kaszubowski  );
4589d2c67fSBartosz Kaszubowski};
4689d2c67fSBartosz Kaszubowski
4789d2c67fSBartosz Kaszubowskiexport const getRNDocsResults = (query: string) => {
4889d2c67fSBartosz Kaszubowski  return fetch(
4989d2c67fSBartosz Kaszubowski    ...getAlgoliaFetchParams(
5089d2c67fSBartosz Kaszubowski      query,
5189d2c67fSBartosz Kaszubowski      '8TDSE0OHGQ',
5289d2c67fSBartosz Kaszubowski      'c9c791d9d5fd7f315d7f3859b32c1f3b',
5389d2c67fSBartosz Kaszubowski      'react-native-v2',
5489d2c67fSBartosz Kaszubowski      5,
5589d2c67fSBartosz Kaszubowski      { facetFilters: [['version:current']] }
5689d2c67fSBartosz Kaszubowski    )
5789d2c67fSBartosz Kaszubowski  );
5889d2c67fSBartosz Kaszubowski};
5989d2c67fSBartosz Kaszubowski
6089d2c67fSBartosz Kaszubowskiexport const getDirectoryResults = (query: string) => {
6189d2c67fSBartosz Kaszubowski  return fetch(`https://reactnative.directory/api/libraries?search=${encodeURI(query)}&limit=5`);
6289d2c67fSBartosz Kaszubowski};
6389d2c67fSBartosz Kaszubowski
6489d2c67fSBartosz Kaszubowskiexport const getHighlightHTML = (
6589d2c67fSBartosz Kaszubowski  item: AlgoliaItemType,
6689d2c67fSBartosz Kaszubowski  tag: keyof AlgoliaItemHierarchy<string>
6789d2c67fSBartosz Kaszubowski) => ({
6889d2c67fSBartosz Kaszubowski  dangerouslySetInnerHTML: {
6989d2c67fSBartosz Kaszubowski    __html: item._highlightResult.hierarchy[`${tag}`]?.value || '',
7089d2c67fSBartosz Kaszubowski  },
7189d2c67fSBartosz Kaszubowski});
7289d2c67fSBartosz Kaszubowski
73cc92baa1SBartosz Kaszubowskiconst trimContent = (content: string, length = 36) => {
7489d2c67fSBartosz Kaszubowski  if (!content || !content.length) return '';
7589d2c67fSBartosz Kaszubowski
76cc92baa1SBartosz Kaszubowski  const trimStart = Math.max(content.indexOf('<mark>') - length, 0);
77cc92baa1SBartosz Kaszubowski  const trimEnd = Math.min(content.indexOf('</mark>') + length + 6, content.length);
7889d2c67fSBartosz Kaszubowski
7989d2c67fSBartosz Kaszubowski  return `${trimStart !== 0 ? '…' : ''}${content.substring(trimStart, trimEnd).trim()}${
8089d2c67fSBartosz Kaszubowski    trimEnd !== content.length ? '…' : ''
8189d2c67fSBartosz Kaszubowski  }`;
8289d2c67fSBartosz Kaszubowski};
8389d2c67fSBartosz Kaszubowski
84cc92baa1SBartosz Kaszubowskiexport const getContentHighlightHTML = (item: AlgoliaItemType, skipDescription = false) =>
85cc92baa1SBartosz Kaszubowski  skipDescription
86cc92baa1SBartosz Kaszubowski    ? {}
87cc92baa1SBartosz Kaszubowski    : {
8889d2c67fSBartosz Kaszubowski        dangerouslySetInnerHTML: {
89cc92baa1SBartosz Kaszubowski          __html: item._highlightResult.content?.value
90cc92baa1SBartosz Kaszubowski            ? trimContent(item._highlightResult.content?.value)
91cc92baa1SBartosz Kaszubowski            : trimContent(item._highlightResult.hierarchy.lvl1?.value || '', 82),
9289d2c67fSBartosz Kaszubowski        },
93cc92baa1SBartosz Kaszubowski      };
9489d2c67fSBartosz Kaszubowski
9589d2c67fSBartosz Kaszubowski// note(simek): this code make sure that browser popup blocker
9689d2c67fSBartosz Kaszubowski// do not prevent opening links via key press (when it fires windows.open)
9789d2c67fSBartosz Kaszubowskiexport const openLink = (url: string, isExternal: boolean = false) => {
9889d2c67fSBartosz Kaszubowski  const link = document.createElement('a');
9989d2c67fSBartosz Kaszubowski  if (isExternal) {
10089d2c67fSBartosz Kaszubowski    link.target = '_blank';
10189d2c67fSBartosz Kaszubowski    link.rel = 'noopener noreferrer';
10289d2c67fSBartosz Kaszubowski  }
10389d2c67fSBartosz Kaszubowski  link.href = url;
10489d2c67fSBartosz Kaszubowski  link.click();
10589d2c67fSBartosz Kaszubowski};
10689d2c67fSBartosz Kaszubowski
10736dd3d19SAman Mittalconst ReferencePathChunks = ['/versions/', '/more/'] as const;
1082d1611c4SAman Mittal
1092d1611c4SAman Mittalexport const isReferencePath = (url: string) => {
1102d1611c4SAman Mittal  return ReferencePathChunks.some(pathChunk => url.includes(pathChunk));
1112d1611c4SAman Mittal};
1122d1611c4SAman Mittal
11389d2c67fSBartosz Kaszubowskiconst EASPathChunks = [
11489d2c67fSBartosz Kaszubowski  '/app-signing/',
11589d2c67fSBartosz Kaszubowski  '/build/',
11689d2c67fSBartosz Kaszubowski  '/build-reference/',
11789d2c67fSBartosz Kaszubowski  '/development/',
11889d2c67fSBartosz Kaszubowski  '/eas/',
11989d2c67fSBartosz Kaszubowski  '/eas/metadata/',
12089d2c67fSBartosz Kaszubowski  '/eas-update/',
12189d2c67fSBartosz Kaszubowski  '/submit/',
12289d2c67fSBartosz Kaszubowski] as const;
12389d2c67fSBartosz Kaszubowski
12489d2c67fSBartosz Kaszubowskiexport const isEASPath = (url: string) => {
1252d1611c4SAman Mittal  return EASPathChunks.some(pathChunk => url.includes(pathChunk));
1262d1611c4SAman Mittal};
1272d1611c4SAman Mittal
1282d1611c4SAman Mittalconst HomePathChunks = [
1292d1611c4SAman Mittal  '/get-started/',
1302d1611c4SAman Mittal  '/develop/',
1312d1611c4SAman Mittal  '/deploy/',
1322d1611c4SAman Mittal  '/faq/',
1332d1611c4SAman Mittal  '/core-concepts/',
1342d1611c4SAman Mittal  '/debugging/',
1352d1611c4SAman Mittal  '/config-plugins/',
1362d1611c4SAman Mittal] as const;
1372d1611c4SAman Mittal
1382d1611c4SAman Mittalexport const isHomePath = (url: string) => {
1392d1611c4SAman Mittal  return HomePathChunks.some(pathChunk => url.includes(pathChunk));
1402d1611c4SAman Mittal};
1412d1611c4SAman Mittal
1422d1611c4SAman Mittalconst LearnPathChunks = ['/tutorial', '/ui-programming/', '/additional-resources/'] as const;
1432d1611c4SAman Mittal
1442d1611c4SAman Mittalexport const isLearnPath = (url: string) => {
1452d1611c4SAman Mittal  return LearnPathChunks.some(pathChunk => url.includes(pathChunk));
14689d2c67fSBartosz Kaszubowski};
14789d2c67fSBartosz Kaszubowski
14889d2c67fSBartosz Kaszubowskiexport const isAppleDevice = () => {
14989d2c67fSBartosz Kaszubowski  return /(Mac|iPhone|iPod|iPad)/i.test(
15089d2c67fSBartosz Kaszubowski    navigator?.platform ?? navigator?.userAgentData?.platform ?? ''
15189d2c67fSBartosz Kaszubowski  );
15289d2c67fSBartosz Kaszubowski};
15389d2c67fSBartosz Kaszubowski
15489d2c67fSBartosz Kaszubowskiexport const addHighlight = (content: string, query: string) => {
15589d2c67fSBartosz Kaszubowski  const highlightStart = content.toLowerCase().indexOf(query.toLowerCase());
15689d2c67fSBartosz Kaszubowski
15789d2c67fSBartosz Kaszubowski  if (highlightStart === -1) return content;
15889d2c67fSBartosz Kaszubowski
15989d2c67fSBartosz Kaszubowski  const highlightEnd = highlightStart + query.length;
16089d2c67fSBartosz Kaszubowski  return (
16189d2c67fSBartosz Kaszubowski    content.substring(0, highlightStart) +
16289d2c67fSBartosz Kaszubowski    '<mark>' +
16389d2c67fSBartosz Kaszubowski    content.substring(highlightStart, highlightEnd) +
16489d2c67fSBartosz Kaszubowski    '</mark>' +
16589d2c67fSBartosz Kaszubowski    content.substring(highlightEnd)
16689d2c67fSBartosz Kaszubowski  );
16789d2c67fSBartosz Kaszubowski};
168