diff --git a/gui/src/components/Help.js b/gui/src/components/Help.js
index b888dea9e81ea6782ec0603fff7c5489255859fa..b529a87695ade6bea1415eb133b055df8910f98f 100644
--- a/gui/src/components/Help.js
+++ b/gui/src/components/Help.js
@@ -15,13 +15,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import React, { useCallback, useState } from 'react'
+import React, { forwardRef, useCallback, useState } from 'react'
 import { Button, IconButton, Dialog, DialogTitle, DialogContent, DialogActions } from '@material-ui/core'
 import Markdown from './Markdown'
 import PropTypes from 'prop-types'
 import HelpIcon from '@material-ui/icons/Help'
 
-export const HelpButton = ({title, content, maxWidth, IconProps, children, ...IconButtonProps}) => {
+export const HelpButton = forwardRef(({heading, content, text, maxWidth, IconProps, children, ...IconButtonProps}, ref) => {
   const [open, setOpen] = useState(false)
   const handleToggleOpen = useCallback(() => {
     setOpen(old => !old)
@@ -29,30 +29,31 @@ export const HelpButton = ({title, content, maxWidth, IconProps, children, ...Ic
   }, [IconButtonProps])
 
   return <>
-    <IconButton {...IconButtonProps} onClick={handleToggleOpen}>
+    <IconButton {...IconButtonProps} onClick={handleToggleOpen} ref={ref}>
       {children || <HelpIcon {...IconProps}/>}
     </IconButton>
-    <HelpDialog title={title} content={content} open={open} onClose={handleToggleOpen} maxWidth={maxWidth} />
+    <HelpDialog heading={heading} content={content} text={text} open={open} onClose={handleToggleOpen} maxWidth={maxWidth} />
   </>
-}
+})
 
 HelpButton.propTypes = {
-  title: PropTypes.string,
+  heading: PropTypes.string,
   content: PropTypes.string,
+  text: PropTypes.string,
   maxWidth: PropTypes.string,
   IconProps: PropTypes.object,
   children: PropTypes.node
 }
 
-const HelpDialog = ({title, content, maxWidth, open, onClose}) => {
+const HelpDialog = ({heading, content, text, maxWidth, open, onClose}) => {
   return <Dialog
     maxWidth={maxWidth}
     onClose={onClose}
     open={open}
   >
-    <DialogTitle>{title || 'Help'}</DialogTitle>
+    <DialogTitle>{heading || 'Help'}</DialogTitle>
     <DialogContent>
-      <Markdown>{content}</Markdown>
+      <Markdown text={text}>{content}</Markdown>
     </DialogContent>
     <DialogActions>
       <Button onClick={onClose} color="primary">
@@ -63,8 +64,9 @@ const HelpDialog = ({title, content, maxWidth, open, onClose}) => {
 }
 
 HelpDialog.propTypes = {
-  title: PropTypes.string,
+  heading: PropTypes.string,
   content: PropTypes.string,
+  text: PropTypes.string,
   maxWidth: PropTypes.string,
   open: PropTypes.bool,
   onClose: PropTypes.func
diff --git a/gui/src/components/Markdown.js b/gui/src/components/Markdown.js
index 4abcd650c46af978ca4bc2858aa907d17d6994e7..e9bc5f2de8e4c6092a6c68849755662f78f72f63 100644
--- a/gui/src/components/Markdown.js
+++ b/gui/src/components/Markdown.js
@@ -1,3 +1,4 @@
+/* eslint-disable no-unused-vars */
 /*
  * Copyright The NOMAD Authors.
  *
@@ -17,7 +18,6 @@
  */
 import React from 'react'
 import PropTypes from 'prop-types'
-// import remark from 'remark'
 import { withStyles, Link } from '@material-ui/core'
 import { Link as RouterLink } from 'react-router-dom'
 import extend from '@babel/runtime/helpers/extends'
@@ -101,20 +101,12 @@ const styles = theme => {
         marginBottom: theme.spacing(1)
       },
       '& ul': {
-        paddingLeft: 0,
+        paddingLeft: theme.spacing(4),
         '& li': {
-          listStyleType: 'none',
-          fontSize: 'inherit',
-          paddingLeft: theme.spacing(4),
-          '&:before': {
-            content: '\'■\'',
-            fontSize: 'x-large',
-            marginLeft: -theme.spacing(1) * 4,
-            paddingRight: theme.spacing(4) - 14
-          }
+          listStyleType: 'square',
+          fontSize: 'inherit'
         }
       },
-
       '& h1, & h2, & h3, & h4': {
         '& code': {
           fontSize: 'inherit',
diff --git a/gui/src/components/UserdataPage.js b/gui/src/components/UserdataPage.js
index 0b0d3b012acf19fd16cf09e44d70dfeab93f2334..2481cfd5419b516c35e6cfa570f386ddc772e4da 100644
--- a/gui/src/components/UserdataPage.js
+++ b/gui/src/components/UserdataPage.js
@@ -17,6 +17,7 @@
  */
 import React from 'react'
 import { ui } from '../config'
+import { cloneDeep } from 'lodash'
 import { withLoginRequired } from './api'
 import { SearchContext } from './search/SearchContext'
 import SearchPage from './search/SearchPage'
@@ -71,14 +72,17 @@ DOI, they will be redirected to a NOMAD view that shows the dataset and allows i
 Once you assigned a DOI to a dataset, no entries can be removed or added to the dataset.
 `
 
-const context = ui?.apps?.options?.entries
+// Use the same context as in the global entries search, but with free-text
+// query enabled
+const context = cloneDeep(ui?.apps?.options?.entries)
+context.search_syntaxes.exclude = undefined
+
 const initialFiltersLocked = {
   'visibility': 'user'
 }
 const UserdataPage = React.memo(() => {
   return <SearchContext
     resource={context?.resource}
-    initialSchemas={context?.schemas}
     initialPagination={context?.pagination}
     initialColumns={context?.columns}
     initialRows={context?.rows}
@@ -86,6 +90,7 @@ const UserdataPage = React.memo(() => {
     initialFilters={context?.filters}
     initialFiltersLocked={initialFiltersLocked}
     initialDashboard={context?.dashboard}
+    initialSearchSyntaxes={context?.search_syntaxes}
   >
     <SearchPage/>
   </SearchContext>
diff --git a/gui/src/components/dataset/DatasetPage.js b/gui/src/components/dataset/DatasetPage.js
index 0de1eb4b581407d3c7822ce172bfd20161669daa..d9f93019aea688e948e34ed4a5aa9d88890c4603 100644
--- a/gui/src/components/dataset/DatasetPage.js
+++ b/gui/src/components/dataset/DatasetPage.js
@@ -17,6 +17,7 @@
  */
 import React, { useContext, useState, useEffect, useMemo } from 'react'
 import PropTypes from 'prop-types'
+import { cloneDeep } from 'lodash'
 import { Typography, makeStyles } from '@material-ui/core'
 import { ui } from '../../config'
 import { errorContext } from '../errors'
@@ -30,7 +31,11 @@ This page allows you to **inspect** and **download** NOMAD datasets. It also all
 to explore a dataset with similar controls that the search page offers.
 `
 
-const context = ui?.apps?.options?.entries
+// Use the same context as in the global entries search, but with free-text
+// query enabled
+const context = cloneDeep(ui?.apps?.options?.entries)
+context.search_syntaxes.exclude = undefined
+
 const useStyles = makeStyles(theme => ({
   header: {
     display: 'flex',
@@ -62,7 +67,6 @@ const DatasetPage = React.memo(({match}) => {
   return dataset
     ? <SearchContext
       resource={context?.resource}
-      initialSchemas={context?.schemas}
       initialPagination={context?.pagination}
       initialColumns={context?.columns}
       initialRows={context?.rows}
@@ -70,6 +74,8 @@ const DatasetPage = React.memo(({match}) => {
       initialFilters={context?.filters}
       initialFiltersLocked={datasetFilter}
       initialDashboard={context?.dashboard}
+      initialSearchSyntaxes={context?.search_syntaxes}
+      id='dataset-search'
     >
       <SearchPage header={
         <div className={styles.header}>
diff --git a/gui/src/components/entry/properties/SampleHistoryCard.js b/gui/src/components/entry/properties/SampleHistoryCard.js
index 420980de31e63bd3eb8aec99b6556ba1627416a5..5b2e7db2e19728198d50c79e8ef1b3b9eeeb8366 100644
--- a/gui/src/components/entry/properties/SampleHistoryCard.js
+++ b/gui/src/components/entry/properties/SampleHistoryCard.js
@@ -77,12 +77,12 @@ const SampleHistoryUsingCard = memo(({ index }) => {
   return (
     <SearchContext
       resource={context?.resource}
-      initialSchemas={context?.schemas}
       initialPagination={context?.pagination}
       initialColumns={context?.columns}
       initialRows={context?.rows}
       initialFilterMenus={context?.filter_menus}
       initialFiltersLocked={filtersLocked}
+      initialSearchSyntaxes={context?.search_syntaxes}
     >
       <HistoryCard />
     </SearchContext>
diff --git a/gui/src/components/nav/Breadcrumbs.js b/gui/src/components/nav/Breadcrumbs.js
index 038438e23bb09a3de59fd319dc1229ca96904bd6..d360155376cf6ba43043eeca048b14931bf53c98 100644
--- a/gui/src/components/nav/Breadcrumbs.js
+++ b/gui/src/components/nav/Breadcrumbs.js
@@ -86,9 +86,7 @@ const Breadcrumbs = React.memo(function Breadcrumbs() {
             {title}
             {route.help && (
               <Tooltip title={route?.help?.title || ""}>
-                <span>
-                  <HelpButton className={styles.help} size="small" IconProps={{fontSize: 'small'}} {...route.help} />
-                </span>
+                <HelpButton className={styles.help} size="small" IconProps={{fontSize: 'small'}} heading={route?.help?.title} content={route?.help?.content} />
               </Tooltip>
             )}
           </Box>
diff --git a/gui/src/components/nav/Routes.js b/gui/src/components/nav/Routes.js
index aa6d1c4d9be53e37001f1dbbb3fe5cc11da9d04a..abc69391b05cc4697850ed73b268f3851462e9e3 100644
--- a/gui/src/components/nav/Routes.js
+++ b/gui/src/components/nav/Routes.js
@@ -197,7 +197,6 @@ const searchRoutes = Object.values(ui?.apps?.options || {})
       render: (props) => (
         <SearchContext
           resource={context.resource}
-          initialSchemas={context?.schemas}
           initialPagination={context.pagination}
           initialColumns={context.columns}
           initialRows={context.rows}
@@ -205,6 +204,8 @@ const searchRoutes = Object.values(ui?.apps?.options || {})
           initialFilters={context?.filters}
           initialFiltersLocked={context.filters_locked}
           initialDashboard={context?.dashboard}
+          initialSearchSyntaxes={context?.search_syntaxes}
+          id={context?.path}
         >
           <SearchPage/>
         </SearchContext>
diff --git a/gui/src/components/search/FilterRegistry.js b/gui/src/components/search/FilterRegistry.js
index 4c6340be5dd4074c076c25181834aba18442d848..89b0b7d1427869f48452643583b0090cd16044a5 100644
--- a/gui/src/components/search/FilterRegistry.js
+++ b/gui/src/components/search/FilterRegistry.js
@@ -378,6 +378,7 @@ registerFilter('entry_name.prefix', idMetadata, {...noAggQuantity, label: 'Entry
 registerFilter('results.material.material_id', idMetadata, termQuantity)
 registerFilter('optimade_filter', idOptimade, {multiple: true, queryMode: 'all'})
 registerFilter('processed', idMetadata, {label: 'Processed', queryMode: 'all'})
+registerFilter('text_search_contents', idMetadata, {multiple: true, queryMode: 'all'})
 registerFilter('custom_quantities', idCustomQuantities, {
   serializerExact: value => {
     const jsonStr = JSON.stringify(value)
@@ -720,8 +721,7 @@ export function getStaticSuggestions(quantities, filterData) {
       const minLength = maxLength <= 2 ? 1 : 2
       suggestions[quantity] = getSuggestions(
         options,
-        minLength,
-        quantity
+        minLength
       )
     }
   }
@@ -730,8 +730,7 @@ export function getStaticSuggestions(quantities, filterData) {
   if (quantities.has(quantityNameSearch)) {
     suggestions[quantityNameSearch] = getSuggestions(
       filters.filter(value => value !== quantityNameSearch && !filterData[value].section),
-      2,
-      quantityNameSearch
+      2
     )
   }
   return suggestions
@@ -909,7 +908,6 @@ export const withFilters = (WrappedComponent) => {
 
   WithFilters.displayName = `withFilter(${WrappedComponent.displayName || WrappedComponent.name})`
   WithFilters.propTypes = {
-    initialSchemas: PropTypes.object, // Determines which schemas are available
     initialFilters: PropTypes.object // Determines which filters are available
   }
 
diff --git a/gui/src/components/search/FilterSummary.spec.js b/gui/src/components/search/FilterSummary.spec.js
index 4c251f56b69a9531f86a511633da9758fef716e6..e64559f3efc313f4ce2285321c8869ace49989e8 100644
--- a/gui/src/components/search/FilterSummary.spec.js
+++ b/gui/src/components/search/FilterSummary.spec.js
@@ -32,7 +32,6 @@ test.each([
   render(
     <SearchContext
         resource={context.resource}
-        initialSchemas={context?.schemas}
         initialPagination={context.pagination}
         initialColumns={context.columns}
         initialRows={context.rows}
@@ -40,6 +39,7 @@ test.each([
         initialFiltersLocked={context.filters_locked}
         initialDashboard={context?.dashboard}
         initialFilterValues={{[quantity]: input}}
+        initialSearchSyntaxes={context?.search_syntaxes}
     >
       <FilterSummary quantities={new Set([quantity])}/>
     </SearchContext>
diff --git a/gui/src/components/search/SearchBar.js b/gui/src/components/search/SearchBar.js
index 3b6b8d46fa7f0a15641c708ecd6668fb217f0ed0..221a36a7757bfb83297b9574752fd55c2f50cf47 100644
--- a/gui/src/components/search/SearchBar.js
+++ b/gui/src/components/search/SearchBar.js
@@ -15,36 +15,121 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import React, { useCallback, useState, useMemo } from 'react'
+import React, { useCallback, useState, useMemo, createContext, useContext, useRef } from 'react'
 import PropTypes from 'prop-types'
 import clsx from 'clsx'
 import assert from 'assert'
 import { isNil, has } from 'lodash'
 import { makeStyles } from '@material-ui/core/styles'
 import SearchIcon from '@material-ui/icons/Search'
-import { Paper, Tooltip } from '@material-ui/core'
-import IconButton from '@material-ui/core/IconButton'
-import { DType } from '../../utils'
+import HistoryIcon from '@material-ui/icons/History'
+import CloseIcon from '@material-ui/icons/Close'
+import { HelpButton } from '../../components/Help'
+import { Paper, Tooltip, Chip, List, ListSubheader, Typography, IconButton } from '@material-ui/core'
+import { parseQuantityName, getSchemaAbbreviation } from '../../utils'
 import { useSuggestions } from '../../hooks'
 import { useSearchContext } from './SearchContext'
 import { quantityNameSearch } from './FilterRegistry'
-import { MetainfoOption, ListboxMetainfo, renderGroup } from './input/InputMetainfo'
+import { VariableSizeList } from 'react-window'
 import { InputText } from './input/InputText'
+import { SearchSuggestion, SuggestionType } from './SearchSuggestion'
+import { SearchSyntaxes } from './SearchSyntaxes'
+import { renderRow, useResetCache, LISTBOX_PADDING } from './input/InputMetainfo'
 
-const opMap = {
-  '<=': 'lte',
-  '>=': 'gte',
-  '>': 'gt',
-  '<': 'lt'
-}
-const opMapReverse = {
-  '<=': 'gte',
-  '>=': 'lte',
-  '>': 'lt',
-  '<': 'gt'
+/**
+ * Displays a suggestion in the search bar.
+ */
+export const useSuggestionStyles = makeStyles(theme => ({
+  root: {
+    width: '100%',
+    height: '100%',
+    display: 'flex',
+    alignItems: 'center',
+    '& > *': {
+        marginRight: theme.spacing(1)
+    },
+    '& > *:last-child': {
+        marginRight: 0
+    },
+    // The delete icon is hidden until the item is hovered. It is not removed
+    // from the document with "display: none" in order for the hover to not
+    // change the layout which may cause other elements to shift around.
+    '& .delete': {
+      visibility: "hidden"
+    },
+    '&:hover .delete': {
+      visibility: "visible"
+    }
+  },
+  primary: {
+    flexGrow: 1,
+    whiteSpace: 'nowrap',
+    overflowX: 'scroll',
+    '&::-webkit-scrollbar': {
+      display: 'none'
+    },
+    '-ms-overflow-style': 'none',
+    scrollbarWidth: 'none'
+  }
+}))
+const Suggestion = ({suggestion, onDelete, tooltip}) => {
+  const typeTooltip = (suggestion.type === SuggestionType.Name
+    ? 'Suggested name for an available filter in this app'
+    : SearchSyntaxes[suggestion.type]?.readme) || ''
+  const label = (suggestion.type === SuggestionType.Name
+    ? 'name'
+    : SearchSyntaxes[suggestion.type]?.labelShort) || ''
+  const styles = useSuggestionStyles()
+  let schema, primary
+  if (suggestion.type === SuggestionType.Name) {
+    const {path, schema: schemaTmp} = parseQuantityName(suggestion.input)
+    primary = path
+    schema = schemaTmp
+  } else {
+    primary = suggestion.input
+  }
+
+  return <div className={styles.root}>
+    <Typography className={styles.primary}>
+      <Tooltip title={tooltip || ''} placement='bottom' enterDelay={500} enterNextDelay={500}>
+        <span>{primary}</span>
+      </Tooltip>
+    </Typography>
+    {suggestion.history
+      ? <Tooltip title="Remove from search history">
+        <IconButton className="delete" size="small" onClick={(event) => {
+          event.preventDefault()
+          event.stopPropagation()
+          onDelete?.()
+        }}>
+          <CloseIcon fontSize="small" color="action" />
+        </IconButton>
+      </Tooltip>
+      : null
+    }
+    {suggestion.history
+      ? <Tooltip title="From search history">
+        <HistoryIcon fontSize="small" color="action"/>
+      </Tooltip>
+      : null
+    }
+    {schema
+      ? <Tooltip title={`Definition from ${schema}`}>
+      <Typography variant='caption'>{getSchemaAbbreviation(schema)}</Typography>
+    </Tooltip>
+      : null
+    }
+    <Tooltip title={typeTooltip}>
+      <Chip size='small' label={label}/>
+    </Tooltip>
+  </div>
 }
 
-const numericTypes = new Set([DType.Timestamp, DType.Int, DType.Float])
+Suggestion.propTypes = {
+  suggestion: PropTypes.object,
+  onDelete: PropTypes.func,
+  tooltip: PropTypes.string
+}
 
 export const useStyles = makeStyles(theme => ({
   root: {
@@ -52,9 +137,6 @@ export const useStyles = makeStyles(theme => ({
     alignItems: 'center',
     position: 'relative'
   },
-  notchedOutline: {
-    borderColor: 'rgba(0, 0, 0, 0.0)'
-  },
   iconButton: {
     padding: 10
   }
@@ -73,15 +155,29 @@ const SearchBar = React.memo(({
     filterData,
     filterFullnames,
     useUpdateFilter,
-    useFiltersLocked,
-    useParseQuery
+    useParseQuery,
+    useSearchSuggestions,
+    usePushSearchSuggestion,
+    useRemoveSearchSuggestion,
+    useSetPagination,
+    searchSyntaxes
   } = useSearchContext()
+  const includedFormats = Object
+    .keys(SearchSyntaxes)
+    .filter((key) => !searchSyntaxes?.exclude?.includes(key))
+  const formatReadmeList = includedFormats
+    .map((key) => {
+      const examples = SearchSyntaxes[key]?.examples?.map((example) => `   ${example}`).join('\n')
+      return ` - **${SearchSyntaxes[key]?.label}**: ${SearchSyntaxes[key]?.readme} For example:\n\n   \`\`\`\n${examples}\n   \`\`\`\n`
+    })
+    .join('\n')
   const [inputValue, setInputValue] = useState('')
   const [suggestionInput, setSuggestionInput] = useState('')
   const [error, setError] = useState(false)
-  const filtersLocked = useFiltersLocked()
+  const setPagination = useSetPagination()
   const updateFilter = useUpdateFilter()
   const parseQuery = useParseQuery()
+  const inputRef = useRef()
 
   const [quantitiesAll, quantitiesAllSet, quantitiesSuggestable] = useMemo(() => {
     let quantitySetSuggestable, quantityList
@@ -128,32 +224,53 @@ const SearchBar = React.memo(({
   const suggestionQuantities = useMemo(() => {
     return quantitiesAll.filter((q) => suggestionNames.has(q.name))
   }, [quantitiesAll, suggestionNames])
-  const [suggestions, loading] = useSuggestions(suggestionQuantities, quantitiesAllSet, suggestionInput, filterData)
-  const {options, keys} = useMemo(() => {
-    const keys = []
-    const options = {}
-    for (const suggestion of suggestions) {
-      let filter, key, primary
+
+  const [suggestionsMatch, setSuggestionsMatch] = useState([])
+  const pushSuggestion = usePushSearchSuggestion()
+  const removeSuggestion = useRemoveSearchSuggestion()
+  const suggestionsHistory = useSearchSuggestions(inputValue)
+  const [suggestionsMetainfo, loading] = useSuggestions(suggestionQuantities, quantitiesAllSet, suggestionInput, filterData)
+
+  // Contains the final set of suggestions
+  const [suggestions, keys] = useMemo(() => {
+    const suggestions = {}
+
+    for (const suggestion of suggestionsMatch) {
+      suggestions[suggestion.key] = suggestion
+    }
+
+    for (const suggestion of suggestionsHistory) {
+      suggestions[suggestion.key] = suggestion
+    }
+
+    for (const suggestion of suggestionsMetainfo) {
+      let input, type
       if (suggestion.category === quantityNameSearch) {
-        filter = filterData[suggestion.value]
-        key = suggestion.value
-        primary = filter?.quantity || suggestion.value
+        type = SuggestionType.Name
+        input = suggestion.value
       } else {
-        key = `${suggestion.category}=${suggestion.value}`
-        primary = key
+        type = SuggestionType.Equality
+        input = `${suggestion.category} = ${suggestion.value}`
       }
-      keys.push(key)
-      options[key] = {
-        key: key,
-        group: suggestion.category,
-        dtype: filter?.dtype,
-        schema: filter?.schema,
-        primary: primary,
-        description: filter?.description
+      const suggestionObject = new SearchSuggestion({input, type})
+      const key = suggestionObject.key
+      if (!has(suggestions, key)) {
+        suggestions[key] = suggestionObject
       }
     }
-    return {options, keys}
-  }, [suggestions, filterData])
+    return [suggestions, Object.keys(suggestions)]
+  }, [suggestionsMatch, suggestionsHistory, suggestionsMetainfo])
+
+  const clearSuggestions = useCallback(() => {
+    setSuggestionInput('')
+    setSuggestionsMatch([])
+  }, [])
+
+  const clearInput = useCallback(() => {
+    setError(error => error ? undefined : null)
+    setInputValue('')
+    setSuggestionInput('')
+  }, [])
 
   // Used to check the validity of the given quantity name
   const checkMetainfo = useCallback((name) => {
@@ -167,184 +284,143 @@ const SearchBar = React.memo(({
     return [fullName, undefined]
   }, [quantitiesAllSet, filterData, filterFullnames])
 
-  // Triggered when a value is submitted by pressing enter or clicking the
-  // search icon.
-  const handleSubmit = useCallback((value) => {
-    if (!value?.trim()?.length) {
-      return
+  // Get suggestions based on the current input and the supported query syntaxes
+  const getSuggestionsMatch = useCallback((input) => {
+    input = input?.trim()
+    if (!input?.length) {
+      return []
     }
-    const reString = '[^\\s=<>](?:[^=<>]*[^\\s=<>])?'
-    const op = '(?:<|>)=?'
-    let valid = false
-    let quantityFullname
-    let queryValue
-    let comparison = true
-
-    // Presence query
-    const presence = value.match(new RegExp(`^\\s*(${reString})\\s*=\\s*\\*\\s*$`))
-    if (presence) {
-      quantityFullname = `quantities`
-      queryValue = parseQuery(quantityFullname, presence[1])
-      valid = true
-    }
-
-    // Equality query
-    if (!valid) {
-      const equals = value.match(new RegExp(`^\\s*(${reString})\\s*=\\s*(${reString})\\s*$`))
-      if (equals) {
-        const quantityName = equals[1]
-        const [fullName, error] = checkMetainfo(quantityName)
-        quantityFullname = fullName
-        if (error) {
-          setError(error)
-          return
+    const suggestions = []
+    for (const key of includedFormats) {
+        // regex.test() is significantly faster than string.match()
+        const match = SearchSyntaxes[key].regex.test(input)
+        if (match) {
+          suggestions.push(new SearchSuggestion({input, type: key}))
         }
-        try {
-          queryValue = parseQuery(quantityFullname, equals[2])
-        } catch (error) {
-          setError(`Invalid value for this metainfo. Please check your syntax.`)
-          return
-        }
-        comparison = false
-        valid = true
-      }
     }
+    return suggestions
+  }, [includedFormats])
 
-    // Simple LTE/GTE query
-    if (!valid) {
-      const ltegte = value.match(new RegExp(`^\\s*(${reString})\\s*(${op})\\s*(${reString})\\s*$`))
-      if (ltegte) {
-        const a = ltegte[1]
-        const op = ltegte[2]
-        const b = ltegte[3]
-        const [aFullname, aError] = checkMetainfo(a)
-        const [bFullname, bError] = checkMetainfo(b)
-        if (aError && bError) {
-          if (!aFullname && !bFullname) {
-            setError(`Unknown quantity name`)
-          } else {
-            setError(aError || bError)
-          }
-          return
-        }
-        quantityFullname = aError ? bFullname : aFullname
-        const value = aError ? a : b
-        const dtype = filterData[quantityFullname].dtype
-        if (!numericTypes.has(dtype)) {
-          setError(`Cannot perform range query for a non-numeric quantity`)
-          return
-        }
-        let quantityValue
-        try {
-          quantityValue = parseQuery(quantityFullname, value, undefined, false)
-        } catch (error) {
-          console.log(error)
-          setError(`Invalid value for this metainfo. Please check your syntax.`)
-          return
-        }
-        queryValue = {}
-        queryValue[opMap[op]] = quantityValue
-        valid = true
+  // Triggered when the user selects a highlighted item with mouse or with
+  // keyboard.
+  const handleAccept = useCallback((key) => {
+    let suggestion = suggestions[key]
+    if (!suggestion) {
+      const bestSuggestion = suggestions[keys[0]]
+      if (bestSuggestion?.input?.trim() === key?.trim()) {
+        suggestion = bestSuggestion
+      } else {
+        setError('Unsupported query')
+        return
       }
     }
+    if (suggestion.type === SuggestionType.Name) {
+      setInputValue(suggestion.input)
+      return
+    }
 
-    // Sandwiched LTE/GTE query
-    if (!valid) {
-      const ltegteSandwich = value.match(new RegExp(`^\\s*(${reString})\\s*(${op})\\s*(${reString})\\s*(${op})\\s*(${reString})\\s*$`))
-      if (ltegteSandwich) {
-        const a = ltegteSandwich[1]
-        const op1 = ltegteSandwich[2]
-        const b = ltegteSandwich[3]
-        const op2 = ltegteSandwich[4]
-        const c = ltegteSandwich[5]
-        const [fullName, error] = checkMetainfo(b)
-        if (error) {
-          setError(error)
-          return
-        }
-        quantityFullname = fullName
-        const dtype = filterData[quantityFullname].dtype
-        if (!numericTypes.has(dtype)) {
-          setError(`Cannot perform range query for a non-numeric quantity.`)
-          return
-        }
-        queryValue = {}
-        try {
-          queryValue[opMapReverse[op1]] = parseQuery(quantityFullname, a, undefined, false)
-          queryValue[opMap[op2]] = parseQuery(quantityFullname, c, undefined, false)
-        } catch (error) {
-          setError(`Invalid value for this metainfo. Please check your syntax.`)
-          return
-        }
-        valid = true
+    // Parse the suggestion using the matched format
+    const format = SearchSyntaxes[suggestion.type]
+    const {target: targetTmp, value: valueTmp, inputNormalized} = format.parse(suggestion.input)
+
+    // Check that targeted metainfo is ok, and attempt to parse the query
+    const [target, errorMeta] = checkMetainfo(targetTmp)
+    let value, errorQuery
+    if (!errorMeta) {
+      try {
+        value = parseQuery(target, valueTmp)
+      } catch (err) {
+        errorQuery = `Invalid value for the metainfo ${target}. Please check your syntax.`
       }
     }
 
-    // Check if filter is locked
-    if (!isNil(filtersLocked[quantityFullname]) && filterData[quantityFullname].global) {
-      setError(`Cannot change the filter as it is locked in the current search context.`)
+    // Catch any errors and raise them
+    const error = errorMeta || errorQuery
+    if (error) {
+      setError(error)
       return
     }
 
-    // Submit to search context on successful validation.
-    if (valid) {
-      updateFilter([quantityFullname, old => {
-        const multiple = filterData[quantityFullname].multiple
-        return (comparison || isNil(old) || !multiple)
-          ? queryValue
-          : new Set([...old, ...queryValue])
-      }])
-      setInputValue('')
-    } else {
-      setError(`Invalid query`)
+    // The pagination is explicitly set to be done by descending relevance
+    // score if a free-text query is performed
+    if (suggestion.type === SuggestionType.Freetext) {
+      setPagination(old => {
+        return {...old, order_by: '_score', order: 'desc'}
+      })
     }
-  }, [checkMetainfo, updateFilter, filterData, parseQuery, filtersLocked])
 
-  const handleSelect = useCallback((key) => {
-    setInputValue(key)
-  }, [])
+    // Update the search filter
+    updateFilter([target, old => {
+      const multiple = filterData[target].multiple
+      return (format?.label === SuggestionType.RangeHalfBounded || suggestion.type === SuggestionType.RangeBounded || isNil(old) || !multiple)
+        ? value
+        : new Set([...old, ...value])
+    }])
+
+    // We need to create a copy here, since Recoil won't allow mutating object
+    // stored in a state.
+    const normalizedSuggestion = new SearchSuggestion(suggestion)
+    normalizedSuggestion.input = inputNormalized
+
+    pushSuggestion(normalizedSuggestion)
+    clearSuggestions()
+    clearInput()
+  }, [checkMetainfo, clearInput, clearSuggestions, filterData, keys, parseQuery, pushSuggestion, suggestions, updateFilter, setPagination])
+
+  // When a suggestion is highlighted with keyboard (not mouse), the text field
+  // is changed to that suggestion value. Note that this should not trigger the
+  // suggestions etc. and this is why we don't set inputValue.
+  const handleHighlight = useCallback((key, reason) => {
+    if (reason === 'keyboard') {
+      const suggestion = suggestions[key]?.input
+      if (suggestion) {
+        inputRef.current.value = suggestion
+      }
+    }
+  }, [suggestions])
 
-  // Handle typing events. After a debounce time has expired, a list of
-  // suggestion will be retrieved if they are available for this metainfo and
-  // the input is deemed meaningful.
-  const handleInputChange = useCallback((value) => {
+  // Handle typing events
+  const handleInputChange = useCallback((input) => {
     setError(error => error ? undefined : null)
-    setInputValue(value)
-    value = value?.trim()
-    if (!value) {
-      setSuggestionInput('')
+    setInputValue(input)
+    input = input?.trim()
+    if (!input) {
+      clearSuggestions()
       return
     }
 
-    // If some input is given, and the quantity supports suggestions, we use
-    // input suggester to suggest values. If the input is prefixed with a proper
-    // quantity name and an equals-sign, we extract the quantity name and the
-    // typed input
-    const split = value.split('=', 2)
+    // Get suggestions for making specific queries
+    setSuggestionsMatch(getSuggestionsMatch(input))
+
+    // Start getting suggestions from ES
+    const split = input.split('=', 2)
     let quantitySet = quantitiesSuggestable
     if (split.length === 2) {
       const quantityName = split[0].trim()
       const quantityFullname = filterFullnames[quantityName]
       if (quantitiesSuggestable.has(quantityName)) {
         quantitySet = new Set([quantityName])
-        value = split[1].trim()
+        input = split[1].trim()
       } else if (quantitiesSuggestable.has(quantityFullname)) {
         quantitySet = new Set([quantityFullname])
-        value = split[1].trim()
+        input = split[1].trim()
       }
     }
     setSuggestionNames(quantitySet)
-    setSuggestionInput(value)
-  }, [quantitiesSuggestable, filterFullnames])
+    setSuggestionInput(input)
+  }, [quantitiesSuggestable, filterFullnames, getSuggestionsMatch, clearSuggestions])
 
   return <Paper className={clsx(className, styles.root)}>
     <InputText
       value={inputValue || null}
       onChange={handleInputChange}
-      onSelect={handleSelect}
-      onAccept={handleSubmit}
+      onSelect={handleAccept}
+      onAccept={handleAccept}
+      onHighlight={handleHighlight}
       suggestions={keys}
-      ListboxComponent={ListboxMetainfo}
+      disableAcceptOnBlur
+      autoHighlight={inputValue?.trim() === suggestions[keys[0]]?.input?.trim()}
+      ListboxComponent={ListboxSuggestion}
       TextFieldProps={{
         variant: 'outlined',
         placeholder: 'Type your query or keyword here',
@@ -354,21 +430,32 @@ const SearchBar = React.memo(({
         size: "medium"
       }}
       InputProps={{
-        classes: {
-          notchedOutline: styles.notchedOutline
-        },
-        startAdornment: <Tooltip title="Add filter">
-          <IconButton onClick={() => handleSubmit(inputValue)} className={styles.iconButton} aria-label="search">
-            <SearchIcon />
-          </IconButton>
-        </Tooltip>
+        startAdornment: <SearchIcon className={styles.iconButton} color="action" />,
+        endAdornment: <Tooltip title="Search bar syntax help">
+          <HelpButton
+            IconProps={{fontSize: 'small'}}
+            maxWidth="md"
+            size="small"
+            heading="Search bar help"
+            text={`
+The search bar provides a fast way to start formulating queries.
+Once you start typing a keyword or a query, suggestions for queries
+and metainfo names are given based on your search history and the
+available data. This search bar supports the following syntaxes:
+
+${formatReadmeList}`}
+          />
+        </Tooltip>,
+        inputRef: inputRef
       }}
-      groupBy={(key) => options?.[key]?.group}
-      renderGroup={renderGroup}
       getOptionLabel={option => option}
       filterOptions={(options) => options}
       loading={loading}
-      renderOption={(id) => <MetainfoOption id={id} options={options} />}
+      renderOption={(id) => <Suggestion
+        suggestion={suggestions[id]}
+        onDelete={() => removeSuggestion(suggestions[id].key)}
+        tooltip={suggestions[id].type === SuggestionType.Name ? filterData[suggestions[id].input]?.description : undefined}
+      />}
     />
   </Paper>
 })
@@ -383,4 +470,61 @@ SearchBar.propTypes = {
   className: PropTypes.string
 }
 
+/**
+ * Custom virtualized list component for displaying searchbar suggestions.
+ */
+const OuterElementContext = createContext({})
+export const ListboxSuggestion = React.forwardRef((props, ref) => {
+  const { children, ...other } = props
+  const itemSize = 48
+  const headerSize = 40
+  const itemData = React.Children.toArray(children)
+  const itemCount = itemData.length
+
+  // Calculate size of child element.
+  const getChildSize = (child) => {
+    return React.isValidElement(child) && child.type === ListSubheader
+      ? headerSize
+      : itemSize
+  }
+
+  // Calculates the height of the suggestion box
+  const getHeight = () => {
+    return itemCount > 8
+      ? 8 * itemSize
+      : itemData.map(getChildSize).reduce((a, b) => a + b, 0)
+  }
+
+  const gridRef = useResetCache(itemCount)
+
+  return <div ref={ref}>
+    <OuterElementContext.Provider value={other}>
+      <List disablePadding>
+        <VariableSizeList
+          itemData={itemData}
+          height={getHeight() + 2 * LISTBOX_PADDING}
+          width="100%"
+          ref={gridRef}
+          outerElementType={OuterElementType}
+          innerElementType="ul"
+          itemSize={(index) => getChildSize(itemData[index])}
+          overscanCount={5}
+          itemCount={itemCount}
+        >
+          {renderRow}
+        </VariableSizeList>
+      </List>
+    </OuterElementContext.Provider>
+  </div>
+})
+
+ListboxSuggestion.propTypes = {
+  children: PropTypes.node
+}
+
+const OuterElementType = React.forwardRef((props, ref) => {
+  const outerProps = useContext(OuterElementContext)
+  return <div ref={ref} {...props} {...outerProps} />
+})
+
 export default SearchBar
diff --git a/gui/src/components/search/SearchBar.spec.js b/gui/src/components/search/SearchBar.spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..4cb4ba6ca076f095c9ae096cf7f287b12ca90d73
--- /dev/null
+++ b/gui/src/components/search/SearchBar.spec.js
@@ -0,0 +1,163 @@
+/*
+ * Copyright The NOMAD Authors.
+ *
+ * This file is part of NOMAD. See https://nomad-lab.eu for further info.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import React from 'react'
+import { ui } from '../../config'
+import { render, screen, within } from '../conftest.spec'
+import userEvent from '@testing-library/user-event'
+import { SearchContext } from './SearchContext'
+import SearchBar from './SearchBar'
+import { SearchSuggestion, SuggestionType } from './SearchSuggestion'
+
+describe('searchbar queries', function() {
+  test.each([
+    ['equality', 'results.material.n_elements = 1', 'equality'],
+    ['existence', 'results.material.n_elements = *', 'existence'],
+    ['range, -gt', 'results.material.n_elements > 0', 'range'],
+    ['range, -gte', 'results.material.n_elements >= 0', 'range'],
+    ['range, -lt', 'results.material.n_elements < 0', 'range'],
+    ['range, -lte', 'results.material.n_elements <= 0', 'range'],
+    ['range, gt-', '0 > results.material.n_elements', 'range'],
+    ['range, gte-', '0 >= results.material.n_elements', 'range'],
+    ['range, lt-', '0 < results.material.n_elements', 'range'],
+    ['range, lte', '0 <= results.material.n_elements', 'range'],
+    ['range, lt-lt', '0 < results.material.n_elements < 1', 'range'],
+    ['range, lte-lt', '0 <= results.material.n_elements < 1', 'range'],
+    ['range, lt-lte', '0 < results.material.n_elements <= 1', 'range'],
+    ['range, lte-lte', '0 <= results.material.n_elements <= 1', 'range'],
+    ['range, gt-gt', '0 > results.material.n_elements > 1', 'range'],
+    ['range, gte-gt', '0 >= results.material.n_elements > 1', 'range'],
+    ['range, gt-gte', '0 > results.material.n_elements >= 1', 'range'],
+    ['range, gte-gte', '0 >= results.material.n_elements >= 1', 'range']
+  ])('%s', async (name, input, type) => {
+    const context = ui.apps.options.entries
+    render(
+      <SearchContext
+          resource={context.resource}
+          initialPagination={context.pagination}
+          initialColumns={context.columns}
+          initialRows={context.rows}
+          initialFilterMenus={context.filter_menus}
+          initialFiltersLocked={context.filters_locked}
+          initialDashboard={context?.dashboard}
+          initialSearchSyntaxes={context?.search_syntaxes}
+      >
+        <SearchBar />
+      </SearchContext>
+    )
+    const textInput = screen.getByRole('textbox')
+    await userEvent.type(textInput, input)
+    expect(screen.getByRole('textbox')).toHaveValue(input)
+    expect(screen.getByText(type))
+    await userEvent.keyboard('{enter}')
+    expect(screen.getByRole('textbox')).toHaveValue('')
+  })
+})
+
+const suggestionsInitial = [
+  new SearchSuggestion({input: 'old', type: SuggestionType.Freetext, history: true}),
+  new SearchSuggestion({input: 'older', type: SuggestionType.Freetext, history: true}),
+  new SearchSuggestion({input: 'oldest', type: SuggestionType.Freetext, history: true})
+]
+describe('suggestions: history', function() {
+  beforeAll(() => {
+    window.localStorage.setItem(
+      'nomad-searchcontext-entries',
+      JSON.stringify(suggestionsInitial)
+    )
+  })
+  afterAll(() => {
+    window.localStorage.removeItem('nomad-searchcontext-entries')
+  })
+  test('initial suggestions are shown in correct order upon focus', async () => {
+    const context = ui.apps.options.entries
+    render(
+      <SearchContext
+          resource={context.resource}
+          initialPagination={context.pagination}
+          initialColumns={context.columns}
+          initialRows={context.rows}
+          initialFilterMenus={context.filter_menus}
+          initialFiltersLocked={context.filters_locked}
+          initialDashboard={context?.dashboard}
+          initialSearchSyntaxes={context?.search_syntaxes}
+          id={context?.path}
+      >
+        <SearchBar />
+      </SearchContext>
+    )
+    const textInput = screen.getByRole('textbox')
+    await userEvent.click(textInput)
+    const options = screen.getAllByRole('option')
+    expect(options.length).toBe(3)
+    expect(options[0]).toHaveTextContent('old')
+    expect(options[1]).toHaveTextContent('older')
+    expect(options[2]).toHaveTextContent('oldest')
+  })
+  test('options are filtered according to input', async () => {
+    const context = ui.apps.options.entries
+    render(
+      <SearchContext
+          resource={context.resource}
+          initialPagination={context.pagination}
+          initialColumns={context.columns}
+          initialRows={context.rows}
+          initialFilterMenus={context.filter_menus}
+          initialFiltersLocked={context.filters_locked}
+          initialDashboard={context?.dashboard}
+          initialSearchSyntaxes={context?.search_syntaxes}
+          id={context?.path}
+      >
+        <SearchBar />
+      </SearchContext>
+    )
+    const textInput = screen.getByRole('textbox')
+    await userEvent.type(textInput, 'olde')
+    const options = screen.getAllByRole('option')
+    expect(options.length).toBe(2)
+    expect(options[0]).toHaveTextContent('older')
+    expect(options[1]).toHaveTextContent('oldest')
+  })
+  test('clicking delete icon removes option from list', async () => {
+    const context = ui.apps.options.entries
+    render(
+      <SearchContext
+          resource={context.resource}
+          initialPagination={context.pagination}
+          initialColumns={context.columns}
+          initialRows={context.rows}
+          initialFilterMenus={context.filter_menus}
+          initialFiltersLocked={context.filters_locked}
+          initialDashboard={context?.dashboard}
+          initialSearchSyntaxes={context?.search_syntaxes}
+          id={context?.path}
+      >
+        <SearchBar />
+      </SearchContext>
+    )
+    const textInput = screen.getByRole('textbox')
+    await userEvent.click(textInput)
+    const options = screen.getAllByRole('option')
+    await userEvent.hover(options[0])
+    const removeButton = within(options[0]).getByTooltip('Remove from search history')
+    await userEvent.click(removeButton)
+    const optionsNew = screen.getAllByRole('option')
+    expect(optionsNew.length).toBe(2)
+    expect(optionsNew[0]).toHaveTextContent('older')
+    expect(optionsNew[1]).toHaveTextContent('oldest')
+  })
+})
diff --git a/gui/src/components/search/SearchContext.js b/gui/src/components/search/SearchContext.js
index cd80a45d67ee7affa832b01aa5eff97031eaec29..f33a6c49ecad544967a47e80f793f367fefba115 100644
--- a/gui/src/components/search/SearchContext.js
+++ b/gui/src/components/search/SearchContext.js
@@ -1,3 +1,4 @@
+/* eslint-disable no-unused-vars */
 /*
  * Copyright The NOMAD Authors.
  *
@@ -57,7 +58,8 @@ import {
   setToArray,
   parseQuantityName,
   rsplit,
-  parseOperator
+  parseOperator,
+  getSuggestions
 } from '../../utils'
 import { Quantity } from '../units/Quantity'
 import { Unit } from '../units/Unit'
@@ -66,6 +68,7 @@ import { combinePagination, addColumnDefaults } from '../datatable/Datatable'
 import UploadStatusIcon from '../uploads/UploadStatusIcon'
 import { getWidgetsObject } from './widgets/Widget'
 import { inputSectionContext } from './input/InputSection'
+import { SearchSuggestion } from './SearchSuggestion'
 import { withFilters } from './FilterRegistry'
 import { useUnitContext } from '../units/UnitContext'
 
@@ -197,6 +200,9 @@ export const SearchContextRaw = React.memo(({
   initialFilterData,
   initialFilterGroups,
   initialFilterValues,
+  initialSearchSyntaxes,
+  id,
+  suggestionHistorySize,
   children
 }) => {
   const {api, user} = useApi()
@@ -211,9 +217,9 @@ export const SearchContextRaw = React.memo(({
   const updatedFilters = useRef(new Set())
   const firstLoad = useRef(true)
   const disableUpdate = useRef(false)
-  const contextID = useMemo(() => uuidv4(), [])
   const indexFilters = useRef(0)
   const indexLocked = useRef(0)
+  const contextID = useMemo(() => uuidv4(), [])
 
   // Initialize the set of filters that are available in this context
   const {initialFilterPaths, initialFilterAbbreviations} = useMemo(() => {
@@ -403,7 +409,10 @@ export const SearchContextRaw = React.memo(({
       useRemoveWidget,
       useResetWidgets,
       useQuery,
+      useSearchSuggestionsValue,
+      useSetSearchSuggestions,
       usePagination,
+      useSetPagination,
       usePaginationState,
       useAgg,
       useAggs,
@@ -429,38 +438,73 @@ export const SearchContextRaw = React.memo(({
       key: `isMenuOpen_${contextID}`,
       default: false
     })
+
     const isCollapsedState = atom({
       key: `isCollapsed_${contextID}`,
       default: false
     })
+
     const isStatisticsEnabledState = atom({
       key: `statisticsEnabled_${contextID}`,
       default: true
     })
+
     const apiDataState = atom({
       key: `apiData_${contextID}`,
       default: null
     })
+
     const apiQueryState = atom({
       key: `apiQuery_${contextID}`,
       default: null
     })
+
     const resultsState = atom({
       key: `results_${contextID}`,
       default: {
         pagination: {}
       }
     })
+
     const resultsUsedState = atom({
       key: `resultsUsed_${contextID}`,
       default: false
     })
+
+    let suggestions = []
+    const suggestionID = id && `nomad-searchcontext-${id}`
+    if (suggestionID) {
+      try {
+        suggestions = JSON
+          .parse(window.localStorage.getItem(suggestionID))
+          .map(item => new SearchSuggestion(item))
+          .slice(0, suggestionHistorySize)
+      } catch (e) {
+      }
+    }
+    const searchSuggestionsState = atom({
+      key: `searchSuggestions_${contextID}`,
+      default: suggestions,
+      effects: [
+        ({onSet}) => {
+          if (suggestionID) {
+            onSet((newValue, _, isReset) => {
+              isReset
+                ? window.localStorage.removeItem(suggestionID)
+                : window.localStorage.setItem(suggestionID, JSON.stringify(newValue))
+            })
+          }
+        }
+      ]
+    })
+
     const requiredState = atom({
       key: `required_${contextID}`,
       default: {
         exclude: resource === 'entries' ? ['quantities', 'sections', 'files'] : undefined
       }
     })
+
     // Stores the available filters. Initialized with static filters, can be
     // modified later.
     const filtersDataState = atom({
@@ -477,6 +521,7 @@ export const SearchContextRaw = React.memo(({
       key: `queryFamily_${contextID}`,
       default: (name) => initialQuery[name]
     })
+
     const dynamicQueryModesFamily = atomFamily({
       key: `dynamicQueryModesFamily_${contextID}`,
       default: (name) => undefined
@@ -511,7 +556,10 @@ export const SearchContextRaw = React.memo(({
 
     const paginationState = atom({
       key: `pagination_${contextID}`,
-      default: initialPagination
+      default: {
+        ...initialPagination,
+        order_by: '_score'
+      }
     })
 
     const guiLocked = parseQueries(initialFiltersLocked, initialFilterData, initialFilterAbbreviations.filterFullnames)
@@ -1056,6 +1104,22 @@ export const SearchContextRaw = React.memo(({
       }, [])
     }
 
+    /**
+     * Used to retrieve the currently set search suggestions.
+     *
+     * @returns Array containing the value and a function for setting it.
+     */
+    function useSearchSuggestionsValue() {
+      return useRecoilValue(searchSuggestionsState)
+    }
+
+    /**
+     * Used to set the currently set search suggestions.
+     */
+    function useSetSearchSuggestions() {
+      return useSetRecoilState(searchSuggestionsState)
+    }
+
     return {
       useFilterLocked,
       useFiltersLocked,
@@ -1080,6 +1144,8 @@ export const SearchContextRaw = React.memo(({
       useSetFilters,
       useUpdateFilter,
       useQuery,
+      useSearchSuggestionsValue,
+      useSetSearchSuggestions,
       useFilterNames: () => useRecoilValue(filterNamesState),
       useFiltersData: () => useRecoilValue(filtersDataState),
       useFilterMaps: () => useRecoilValue(filterMapsState),
@@ -1087,6 +1153,7 @@ export const SearchContextRaw = React.memo(({
       useAggs: () => useRecoilValue(aggsState),
       useSetAggsResponse: () => useSetRecoilState(aggsResponseState),
       usePagination: () => useRecoilValue(paginationState),
+      useSetPagination: () => useSetRecoilState(paginationState),
       usePaginationState: () => useRecoilState(paginationState),
       useIsMenuOpen: () => useRecoilValue(isMenuOpenState),
       useSetIsMenuOpen: () => useSetRecoilState(isMenuOpenState),
@@ -1113,7 +1180,9 @@ export const SearchContextRaw = React.memo(({
     initialFiltersLocked,
     initialPagination,
     dashboard,
-    initialAggs
+    initialAggs,
+    id,
+    suggestionHistorySize
   ])
 
   const setResults = useSetResults()
@@ -1503,6 +1572,54 @@ export const SearchContextRaw = React.memo(({
       return results
     }
 
+    /**
+     * Hook that can be used to fetch search suggestions stored in the local
+     * device.
+     * */
+    const useSearchSuggestions = (input, size = 5) => {
+      const suggestions = useSearchSuggestionsValue()
+      const suggestionFilter = useMemo(() => {
+        const sugg = getSuggestions(suggestions, 0, suggestion => suggestion.input)
+        return sugg.filter
+      }, [suggestions])
+
+      return input.trim() === ''
+        ? suggestions.slice(0, size)
+        : suggestionFilter(input).slice(0, size)
+    }
+
+    /**
+     * Hook for pushing new suggestion values to the search context. New values
+     * are pushed to the top of the list, and if the suggestion already exists,
+     * it is simply pulled to the top.
+     * */
+    const usePushSearchSuggestion = () => {
+      const setSuggestions = useSetSearchSuggestions()
+      return useCallback((suggestion) => {
+        setSuggestions(old => {
+          let newSuggestions = old.filter(x => x.key !== suggestion.key)
+          const newSuggestion = new SearchSuggestion(suggestion)
+          newSuggestion.history = true
+          newSuggestions = [newSuggestion, ...old].slice(0, suggestionHistorySize)
+          return newSuggestions
+        })
+      }, [setSuggestions])
+    }
+
+    /**
+     * Hook for deleting specific suggestion values from the search context
+     * using the suggestion key.
+     * */
+    const useRemoveSearchSuggestion = () => {
+      const setSuggestions = useSetSearchSuggestions()
+      return useCallback((key) => {
+        setSuggestions(old => {
+          const newSuggestions = [...old].filter(x => x.key !== key)
+          return newSuggestions
+        })
+      }, [setSuggestions])
+    }
+
     /**
      * Hook that returns a function for parsing a single filter key, value pair
      * into a form that is supported by the GUI. The parsing depends on the
@@ -1515,7 +1632,6 @@ export const SearchContextRaw = React.memo(({
         []
       )
     }
-
     /**
      * Hook that returns a function for parsing an object containing filter
      * values into a form that is supported by the GUI. The parsing depends on
@@ -1539,6 +1655,7 @@ export const SearchContextRaw = React.memo(({
       filterGroups: initialFilterGroups,
       filterFullnames,
       filterAbbreviations,
+      searchSyntaxes: initialSearchSyntaxes,
       useIsMenuOpen,
       useSetIsMenuOpen,
       useIsCollapsed,
@@ -1548,8 +1665,12 @@ export const SearchContextRaw = React.memo(({
       useApiData,
       useApiQuery,
       useQuery,
+      useSetPagination,
       useParseQuery,
       useParseQueries,
+      useSearchSuggestions,
+      usePushSearchSuggestion,
+      useRemoveSearchSuggestion,
       useFilterValue,
       useSetFilter,
       useFilterState,
@@ -1585,6 +1706,7 @@ export const SearchContextRaw = React.memo(({
     initialFilterGroups,
     filterFullnames,
     filterAbbreviations,
+    initialSearchSyntaxes,
     useIsMenuOpen,
     useSetIsMenuOpen,
     useIsCollapsed,
@@ -1609,6 +1731,7 @@ export const SearchContextRaw = React.memo(({
     useResetWidgets,
     useQueryString,
     usePagination,
+    useSetPagination,
     useResults,
     useResultsUsed,
     useRequired,
@@ -1626,7 +1749,10 @@ export const SearchContextRaw = React.memo(({
     setPagination,
     setResults,
     setApiData,
-    units
+    units,
+    suggestionHistorySize,
+    useSearchSuggestionsValue,
+    useSetSearchSuggestions
   ])
 
   return <searchContext.Provider value={values}>
@@ -1645,7 +1771,14 @@ SearchContextRaw.propTypes = {
   initialFilterData: PropTypes.object, // Determines which filters are available
   initialFilterGroups: PropTypes.object, // Maps filter groups to a set of filter names
   initialFilterValues: PropTypes.object, // Here one can provide default filter values
-  children: PropTypes.node
+  initialSearchSyntaxes: PropTypes.object, // Determines which syntaxes are supported
+  children: PropTypes.node,
+  id: PropTypes.string,
+  suggestionHistorySize: PropTypes.number
+}
+
+SearchContextRaw.defaultProps = {
+  suggestionHistorySize: 20
 }
 
 export const SearchContext = compose(withQueryString, withFilters)(SearchContextRaw)
diff --git a/gui/src/components/search/SearchContext.spec.js b/gui/src/components/search/SearchContext.spec.js
index 2f2fc8e5faefcb866e0413a96874c20c564e7535..a98aaac87dcefd1f380c0e25aaa75ac041814a0f 100644
--- a/gui/src/components/search/SearchContext.spec.js
+++ b/gui/src/components/search/SearchContext.spec.js
@@ -15,11 +15,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import { renderHook } from '@testing-library/react-hooks'
+import { renderHook, act } from '@testing-library/react-hooks'
 import { WrapperSearch } from './conftest.spec'
 import { useSearchContext } from './SearchContext'
 import { Quantity } from '../units/Quantity'
 import { isEqualWith } from 'lodash'
+import { SearchSuggestion, SuggestionType } from './SearchSuggestion'
 
 describe('parseQuery', function() {
   test.each([
@@ -45,3 +46,39 @@ describe('parseQuery', function() {
     }
   )
 })
+
+const suggestionsInitial = [
+  new SearchSuggestion({input: 'old', type: SuggestionType.Freetext})
+]
+describe('suggestions', function() {
+  beforeAll(() => {
+    window.localStorage.setItem(
+      'nomad-searchcontext-entries',
+      JSON.stringify(suggestionsInitial)
+    )
+  })
+  afterAll(() => {
+    window.localStorage.removeItem('nomad-searchcontext-entries')
+  })
+  test('load initial suggestions from localStorage', async () => {
+    const { result: resultUseSearchContext } = renderHook(() => useSearchContext(), { wrapper: WrapperSearch })
+    const { result: resultUseSearchSuggestions } = renderHook(() => resultUseSearchContext.current.useSearchSuggestions(''), { wrapper: WrapperSearch })
+    const suggestions = resultUseSearchSuggestions.current
+    expect(suggestions).toHaveLength(suggestionsInitial.length)
+    suggestions.forEach((value, index) => {
+      expect(value.key === suggestionsInitial[index].key)
+    })
+  })
+  test('save new suggestion to localStorage', async () => {
+    const { result: resultUseSearchContext } = renderHook(() => useSearchContext(), { wrapper: WrapperSearch })
+    const { result: resultusePushSearchSuggestion } = renderHook(() => resultUseSearchContext.current.usePushSearchSuggestion(), { wrapper: WrapperSearch })
+    const pushSearchSuggestion = resultusePushSearchSuggestion.current
+    const newSuggestion = new SearchSuggestion({input: 'new', type: SuggestionType.Freetext})
+    act(() => {
+      pushSearchSuggestion(newSuggestion)
+    })
+    const suggestions = JSON.parse(window.localStorage.getItem('nomad-searchcontext-entries')).map(x => new SearchSuggestion(x))
+    expect(suggestions).toHaveLength(suggestionsInitial.length + 1)
+    expect(suggestions[0].key).toBe(newSuggestion.key)
+  })
+})
diff --git a/gui/src/components/search/SearchPage.spec.js b/gui/src/components/search/SearchPage.spec.js
index 16e04fbed4a8d4c833fc50892bd5a60030a1f911..a426eb3fa89b31765b35979a084cac5907dc508c 100644
--- a/gui/src/components/search/SearchPage.spec.js
+++ b/gui/src/components/search/SearchPage.spec.js
@@ -31,19 +31,19 @@ describe('', () => {
   afterAll(() => closeAPI())
 
   test.each(
-    // [ui.apps.options['mofs']]
     Object.entries(ui.apps.options)
   )('renders search page correctly, context: %s', async (key, context) => {
     render(
       <SearchContext
           resource={context.resource}
-          initialSchemas={context.schemas}
           initialPagination={context.pagination}
           initialColumns={context.columns}
           initialRows={context.rows}
           initialFilterMenus={context.filter_menus}
           initialFiltersLocked={context.filters_locked}
           initialDashboard={context?.dashboard}
+          initialSearchSyntaxes={context?.search_syntaxes}
+          id={context?.path}
       >
         <SearchPage />
       </SearchContext>
diff --git a/gui/src/components/search/SearchSuggestion.js b/gui/src/components/search/SearchSuggestion.js
new file mode 100644
index 0000000000000000000000000000000000000000..bf4bda932f31519d3d75781d6516268b43d2e65e
--- /dev/null
+++ b/gui/src/components/search/SearchSuggestion.js
@@ -0,0 +1,46 @@
+/*
+ * Copyright The NOMAD Authors.
+ *
+ * This file is part of NOMAD. See https://nomad-lab.eu for further info.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Represents a suggestable option in the search bar. In TypeScript this would
+ * be an interface.
+ */
+export class SearchSuggestion {
+  input
+  type
+  history
+
+  constructor(param) {
+    this.input = param.input
+    this.type = param.type
+    this.history = param.history
+    this.key = `${this.input}-${this.type}`
+  }
+}
+
+/**
+ * Enum for types of suggestions. In TypeScript this would be an Enum.
+ */
+export const SuggestionType = {
+  Freetext: 'free-text',
+  Equality: 'equality',
+  RangeHalfBounded: 'range_half_bounded',
+  RangeBounded: 'range_bounded',
+  Existence: 'existence',
+  Name: 'name'
+}
diff --git a/gui/src/components/search/SearchSyntaxes.js b/gui/src/components/search/SearchSyntaxes.js
new file mode 100644
index 0000000000000000000000000000000000000000..ffaf0c0b8337ccaaaf3dc529ce1fbeadfc796183
--- /dev/null
+++ b/gui/src/components/search/SearchSyntaxes.js
@@ -0,0 +1,142 @@
+/*
+ * Copyright The NOMAD Authors.
+ *
+ * This file is part of NOMAD. See https://nomad-lab.eu for further info.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Contains definitions for the different search bar syntaxes. This mapping is
+// used for performing the parsing, creating an info dialog and for
+// including/excluding certain syntaxes with the app config.
+
+const opMap = {
+  '<=': 'lte',
+  '>=': 'gte',
+  '>': 'gt',
+  '<': 'lt'
+}
+const opMapReverse = {
+  '<=': 'gte',
+  '>=': 'lte',
+  '>': 'lt',
+  '<': 'gt'
+}
+
+const reString = '[^\\s=<>](?:[^=<>]*[^\\s=<>])?'
+const reOp = '(?:<|>)=?'
+const reEquality = new RegExp(`^(${reString})\\s*=\\s*(${reString})$`)
+const reLte = RegExp(`^(${reString})\\s*(${reOp})\\s*(${reString})$`)
+const reLteGte = new RegExp(`^(${reString})\\s*(${reOp})\\s*(${reString})\\s*(${reOp})\\s*(${reString})$`)
+const reExists = new RegExp(`^(${reString})\\s*=\\s*\\*$`)
+
+export const SearchSyntaxes = {
+  existence: {
+    regex: reExists,
+    parse: (input) => {
+      const exists = input.match(reExists)
+      return {
+        inputNormalized: `${exists[1]} = *`,
+        target: 'quantities',
+        value: exists[1]
+      }
+    },
+    readme: 'Used to query for the existence of a specific metainfo field in the data.',
+    examples: ['authors.name = *'],
+    label: 'Value existence',
+    labelShort: 'existence'
+  },
+  equality: {
+    regex: reEquality,
+    parse: (input) => {
+      const equals = input.match(reEquality)
+      const target = equals[1]
+      return {
+        inputNormalized: `${equals[1]} = ${equals[2]}`,
+        target,
+        value: equals[2]
+      }
+    },
+    readme: 'Used to query for a specific value with exact match.',
+    examples: ['author.name = John Doe'],
+    label: 'Value equality',
+    labelShort: 'equality'
+  },
+  range_bounded: {
+    regex: reLteGte,
+    parse: (input) => {
+      const ltegteSandwich = input.match(reLteGte)
+      const a = ltegteSandwich[1]
+      const op1 = ltegteSandwich[2]
+      const b = ltegteSandwich[3]
+      const op2 = ltegteSandwich[4]
+      const c = ltegteSandwich[5]
+      const target = b
+      const value = {
+        [opMapReverse[op1]]: a,
+        [opMap[op2]]: c
+      }
+      return {
+        inputNormalized: `${ltegteSandwich[1]} ${ltegteSandwich[2]} ${ltegteSandwich[3]} ${ltegteSandwich[4]} ${ltegteSandwich[5]}`,
+        target,
+        value
+      }
+    },
+    readme: 'Queries values that are between two numerical limits, inclusive or exclusive. You can also specify a unit if the target has a certain dimensionality.',
+    examples: [
+      '0 <= results.material.n_elements <= 2',
+      '0 eV < results.properties.geometry_optimization.final_energy_difference < 1e-3 eV'
+    ],
+    label: 'Range query (bounded)',
+    labelShort: 'range'
+  },
+  range_half_bounded: {
+    regex: reLte,
+    parse: (input) => {
+      const ltegte = input.match(reLte)
+      const a = ltegte[1]
+      const op = ltegte[2]
+      const b = ltegte[3]
+      const aNumber = /\d/.test(a)
+      const target = aNumber ? b : a
+      const query = aNumber ? a : b
+      const value = {[opMap[op]]: query}
+return {
+        inputNormalized: `${ltegte[1]} ${ltegte[2]} ${ltegte[3]}`,
+        target,
+        value
+      }
+    },
+    readme: 'Queries values that are above/below a numerical limit, inclusive or exclusive. You can also specify a unit if the target has a certain dimensionality.',
+    examples: [
+      'results.material.n_elements > 2',
+      'results.properties.geometry_optimization.final_energy_difference <= 1e-3 eV'
+    ],
+    label: 'Range query (half-bounded)',
+    labelShort: 'range'
+  },
+  free_text: {
+    regex: /[^]*/,
+    parse: (input) => {
+      return {
+        inputNormalized: input,
+        target: 'text_search_contents',
+        value: input
+      }
+    },
+    readme: 'Free-form text query across keywords associated with an entry. Requires that a set of text search contents has been filled in the entry.',
+    examples: ['type anything there'],
+    label: 'Free-text query',
+    labelShort: 'free-text'
+  }
+}
diff --git a/gui/src/components/search/conftest.spec.js b/gui/src/components/search/conftest.spec.js
index 7792d374268c78d581da81adc14d2b1cc975d793..36f3ac68c750170b1bb6ccccde10552b4b1ca66c 100644
--- a/gui/src/components/search/conftest.spec.js
+++ b/gui/src/components/search/conftest.spec.js
@@ -39,7 +39,7 @@ import { menuMap } from './menus/FilterMainMenu'
  */
 export const WrapperSearch = ({children}) => {
   return <WrapperDefault>
-    <SearchContext resource="entries">
+    <SearchContext resource="entries" id='entries'>
       {children}
     </SearchContext>
   </WrapperDefault>
diff --git a/gui/src/components/search/input/InputMetainfo.js b/gui/src/components/search/input/InputMetainfo.js
index bd8f86cd83e7e358c0a230e0d851d03c601702dd..15faa08a9c1be44f0b896f154153dba56debc4eb 100644
--- a/gui/src/components/search/input/InputMetainfo.js
+++ b/gui/src/components/search/input/InputMetainfo.js
@@ -163,7 +163,7 @@ export const InputMetainfo = React.memo(({
 
   // Used to filter the shown options based on input
   const filterOptions = useCallback((opt, { inputValue }) => {
-    let filtered = filter(inputValue).map(option => option.value)
+    let filtered = filter(inputValue)
     if (group) filtered = filtered.sort((a, b) => options[a].group > options[b].group ? 1 : -1)
     return filtered
   }, [options, filter, group])
@@ -343,10 +343,10 @@ ListboxMetainfo.propTypes = {
   children: PropTypes.node
 }
 
-const LISTBOX_PADDING = 8
+export const LISTBOX_PADDING = 8
 const OuterElementContext = createContext({})
 
-const OuterElementType = React.forwardRef((props, ref) => {
+export const OuterElementType = React.forwardRef((props, ref) => {
   const outerProps = useContext(OuterElementContext)
   return <div ref={ref} {...props} {...outerProps} />
 })
@@ -358,7 +358,7 @@ export const renderGroup = (params) => [
   params.children
 ]
 
-function useResetCache(data) {
+export function useResetCache(data) {
   const ref = useRef(null)
   useEffect(() => {
     if (ref.current != null) {
@@ -368,7 +368,7 @@ function useResetCache(data) {
   return ref
 }
 
-function renderRow({ data, index, style }) {
+export function renderRow({ data, index, style }) {
   return React.cloneElement(data[index], {
     style: {
       ...style,
diff --git a/gui/src/components/search/input/InputText.js b/gui/src/components/search/input/InputText.js
index 6c99cd0e2ac78cfd281a710606fe24db839ceb20..23a370c42202fed7b224c974c220687dd9c2c947 100644
--- a/gui/src/components/search/input/InputText.js
+++ b/gui/src/components/search/input/InputText.js
@@ -80,12 +80,16 @@ const useInputTextStyles = makeStyles(theme => ({
     padding: '3px'
   },
   listbox: {
-      boxSizing: 'border-box',
-      '& ul': {
-        padding: 0,
-        margin: 0
-      }
+    boxSizing: 'border-box',
+    '& ul': {
+      padding: 0,
+      margin: 0
     }
+  },
+  option: {
+    paddingTop: 0,
+    paddingBottom: 0
+  }
 }))
 export const InputText = React.memo(({
   value,
@@ -96,6 +100,7 @@ export const InputText = React.memo(({
   onChange,
   onAccept,
   onSelect,
+  onHighlight,
   onBlur,
   onFocus,
   onError,
@@ -105,6 +110,7 @@ export const InputText = React.memo(({
   renderGroup,
   suggestAllOnFocus,
   showOpenSuggestions,
+  autoHighlight,
   ListboxComponent,
   filterOptions,
   className,
@@ -133,8 +139,9 @@ export const InputText = React.memo(({
 
   // Handle item highlighting: items can he highlighted with mouse or keyboard.
   const handleHighlight = useCallback((event, value, reason) => {
+    onHighlight?.(value, reason)
     highlightRef.current = value
-  }, [highlightRef])
+  }, [highlightRef, onHighlight])
 
   // Handle blur
   const handleBlur = useCallback(() => {
@@ -196,7 +203,11 @@ export const InputText = React.memo(({
       onBlur={handleBlur}
       fullWidth
       disableClearable
-      classes={{listbox: styles.listbox}}
+      autoHighlight={autoHighlight}
+      classes={{
+        listbox: styles.listbox,
+        option: styles.option
+      }}
       ListboxComponent={ListboxComponent}
       PaperComponent={PaperComponent}
       options={suggestions}
@@ -227,6 +238,7 @@ export const InputText = React.memo(({
           InputLabelProps={{shrink}}
           InputProps={{
             ...params.InputProps,
+            ...InputProps,
             endAdornment: (<div className={styles.adornmentList}>
               {loading ? <CircularProgress color="inherit" size={20} className={styles.adornment} /> : null}
               {(value?.length && !disableClearable)
@@ -256,8 +268,8 @@ export const InputText = React.memo(({
                 </IconButton>
                 : null
               }
-            </div>),
-            ...InputProps
+              {InputProps?.endAdornment || null}
+            </div>)
           }}
           {...TextFieldProps}
         />
@@ -277,6 +289,7 @@ InputText.propTypes = {
   onAccept: PropTypes.func, // Triggered when value should be accepted
   onBlur: PropTypes.func, // Triggered when text goes out of focus
   onFocus: PropTypes.func, // Triggered when text is focused
+  onHighlight: PropTypes.func, // Triggered when selection is highlighted
   onError: PropTypes.func, // Triggered when any errors should be cleared
   getOptionLabel: PropTypes.func,
   groupBy: PropTypes.func,
@@ -288,6 +301,7 @@ InputText.propTypes = {
   InputProps: PropTypes.object,
   filterOptions: PropTypes.func,
   disableClearable: PropTypes.bool,
+  autoHighlight: PropTypes.bool,
   disableAcceptOnBlur: PropTypes.bool,
   suggestAllOnFocus: PropTypes.bool, // Whether to provide all suggestion values when input is focused
   showOpenSuggestions: PropTypes.bool, // Whether to show button for opening suggestions
@@ -297,7 +311,8 @@ InputText.propTypes = {
 
 InputText.defaultProps = {
   getOptionLabel: (option) => option.value,
-  showOpenSuggestions: false
+  showOpenSuggestions: false,
+  autoHighlight: false
 }
 
 /*
diff --git a/gui/src/components/search/widgets/WidgetScatterPlot.js b/gui/src/components/search/widgets/WidgetScatterPlot.js
index 0b8d175e10a70be927db7de5d1b69d8e33453943..a7ed2946814ee4cc54e7b5a0d7bda707ea4aea50 100644
--- a/gui/src/components/search/widgets/WidgetScatterPlot.js
+++ b/gui/src/components/search/widgets/WidgetScatterPlot.js
@@ -112,8 +112,7 @@ export const WidgetScatterPlot = React.memo((
   const setWidget = useSetWidget(id)
   const pagination = useMemo(() => ({
     page_size: size,
-    order: 'asc',
-    order_by: 'entry_id'
+    order: 'asc'
   }), [size])
   const required = useMemo(() => {
     const include = ['entry_id']
diff --git a/gui/src/components/units/UnitInput.js b/gui/src/components/units/UnitInput.js
index d8cc5a41da7e9216df39d33731959fd8006ee53c..9f84b838fd9a9ca9faa3e1f4ade678a4d3fe22fa 100644
--- a/gui/src/components/units/UnitInput.js
+++ b/gui/src/components/units/UnitInput.js
@@ -98,7 +98,7 @@ export const UnitInput = React.memo(({value, error, onChange, onAccept, onSelect
 
   // Used to filter the shown options based on input
   const filterOptions = useCallback((opt, { inputValue }) => {
-    let filtered = filter(inputValue).map(option => option.value)
+    let filtered = filter(inputValue)
     if (!disableGroup) filtered = filtered.sort((a, b) => options[a].group > options[b].group ? 1 : -1)
     return filtered
   }, [disableGroup, filter, options])
diff --git a/gui/src/components/units/UnitMenu.js b/gui/src/components/units/UnitMenu.js
index ac46985c7f86f1996b1cca9c0e1572146518aef1..81d90f110c6cd687d28dc8178f9f96c927b95378 100644
--- a/gui/src/components/units/UnitMenu.js
+++ b/gui/src/components/units/UnitMenu.js
@@ -36,6 +36,10 @@ const useStyles = makeStyles(theme => ({
   list: {
     paddingRight: '0 !important',
     width: '100% !important'
+  },
+  option: {
+    paddingTop: '6px',
+    paddingBottom: '6px'
   }
 }))
 const UnitMenu = React.memo(({
@@ -160,7 +164,9 @@ const UnitMenu = React.memo(({
           onChange={handleChange}
           onSelect={handleSelect}
           onBlur={handleBlur}
-          renderOption={(option) => dimensionMap[option].label}
+          renderOption={(option) => <Typography className={styles.option}>
+            {dimensionMap[option].label}
+          </Typography>}
           getOptionLabel={(option) => option}
           TextFieldProps={{label: 'Dimension'}}
         />
diff --git a/gui/src/components/uploads/SectionSelectDialog.js b/gui/src/components/uploads/SectionSelectDialog.js
index 225e7029c685ea84464e59a43ec99be446c5ecf2..e9f82baa722242df9e7e1a93d406f7de850dbe07 100644
--- a/gui/src/components/uploads/SectionSelectDialog.js
+++ b/gui/src/components/uploads/SectionSelectDialog.js
@@ -38,8 +38,11 @@ import {Check} from '@material-ui/icons'
 import { cloneDeep } from 'lodash'
 import {getItemLabelKey} from '../archive/ArchiveBrowser'
 
+// Use the same context as in the global entries search, but with free-text
+// query enabled
 const searchDialogContext = React.createContext()
 const context = cloneDeep(ui?.apps?.options?.entries)
+context.search_syntaxes.exclude = undefined
 
 const allFilters = new Set(defaultFilterGroups && (Object.keys(context?.filter_menus?.options))
   .map(filter => {
@@ -280,6 +283,7 @@ function SearchBox({open, onCancel, onSelectedChanged, selected}) {
     let quantities = new Set([
       'entry_name',
       'mainfile',
+      'text_search_contents',
       'results.material.elements',
       'results.material.chemical_formula_hill',
       'results.material.chemical_formula_anonymous',
@@ -407,12 +411,13 @@ function SectionSelectDialog(props) {
 
   return <SearchContext
     resource={context?.resource}
-    initialSchemas={context?.schemas}
     initialPagination={context?.pagination}
     initialColumns={columns}
     initialRows={rows}
     initialFilterMenus={context?.filter_menus}
     initialFiltersLocked={filtersLocked}
+    initialSearchSyntaxes={context?.search_syntaxes}
+    id='sectionselect'
   >
     <SearchBox open={open} onCancel={onCancel} onSelectedChanged={onSelectedChanged} selected={selected}/>
   </SearchContext>
diff --git a/gui/src/components/uploads/UploadsPage.js b/gui/src/components/uploads/UploadsPage.js
index 7c834eab508203fb0d6d06efb51100f5307a4a9a..5339043c6b2302763f3e779f37c665ff38d7b5b9 100644
--- a/gui/src/components/uploads/UploadsPage.js
+++ b/gui/src/components/uploads/UploadsPage.js
@@ -169,42 +169,40 @@ function UploadCommands({uploadCommands}) {
         </Tooltip>
       </CopyToClipboard>
       <Tooltip title="Alternative shell commands">
-        <span>
-          <HelpButton maxWidth="md" title="Alternative shell commands" content={`
-            As an experienced shell and *curl* user, you can modify the commands to
-            your liking.
-
-            The given command can be modified. To see progress on large files, use
-            \`\`\`
-              ${uploadCommands.upload_progress_command}
-            \`\`\`
-            To \`tar\` and upload multiple folders in one command, use
-            \`\`\`
-            ${uploadCommands.upload_tar_command}
-            \`\`\`
-
-            ### Form data vs. streaming
-            NOMAD accepts stream data (\`-T <local_file>\`) (like in the
-            examples above) or multi-part form data (\`-X PUT -f file=@<local_file>\`):
-            \`\`\`
-            ${uploadCommands.upload_command_form}
-            \`\`\`
-            We generally recommend to use streaming, because form data can produce very
-            large HTTP request on large files. Form data has the advantage of carrying
-            more information (e.g. the file name) to our servers (see below).
-
-            #### Upload names
-            With multi-part form data (\`-X PUT -f file=@<local_file>\`), your upload will
-            be named after the file by default. With stream data (\`-T <local_file>\`)
-            there will be no default name. To set a custom name, you can use the URL
-            parameter \`name\`:
-            \`\`\`
-            ${uploadCommands.upload_command_with_name}
-            \`\`\`
-            Make sure to user proper [URL encoding](https://www.w3schools.com/tags/ref_urlencode.asp)
-            and shell encoding, if your name contains spaces or other special characters.
-          `}/>
-        </span>
+        <HelpButton maxWidth="md" heading="Alternative shell commands" content={`
+          As an experienced shell and *curl* user, you can modify the commands to
+          your liking.
+
+          The given command can be modified. To see progress on large files, use
+          \`\`\`
+            ${uploadCommands.upload_progress_command}
+          \`\`\`
+          To \`tar\` and upload multiple folders in one command, use
+          \`\`\`
+          ${uploadCommands.upload_tar_command}
+          \`\`\`
+
+          ### Form data vs. streaming
+          NOMAD accepts stream data (\`-T <local_file>\`) (like in the
+          examples above) or multi-part form data (\`-X PUT -f file=@<local_file>\`):
+          \`\`\`
+          ${uploadCommands.upload_command_form}
+          \`\`\`
+          We generally recommend to use streaming, because form data can produce very
+          large HTTP request on large files. Form data has the advantage of carrying
+          more information (e.g. the file name) to our servers (see below).
+
+          #### Upload names
+          With multi-part form data (\`-X PUT -f file=@<local_file>\`), your upload will
+          be named after the file by default. With stream data (\`-T <local_file>\`)
+          there will be no default name. To set a custom name, you can use the URL
+          parameter \`name\`:
+          \`\`\`
+          ${uploadCommands.upload_command_with_name}
+          \`\`\`
+          Make sure to user proper [URL encoding](https://www.w3schools.com/tags/ref_urlencode.asp)
+          and shell encoding, if your name contains spaces or other special characters.
+        `}/>
       </Tooltip>
     </div>
   </div>
diff --git a/gui/src/hooks.js b/gui/src/hooks.js
index 3f393357a54abe5fc2aecaa6ed689f653efb7064..844c8f2357aa0d8271941661e135c4cf9e5b3bb7 100644
--- a/gui/src/hooks.js
+++ b/gui/src/hooks.js
@@ -127,7 +127,7 @@ export function useSuggestions(quantitiesSuggest, quantitiesAll, input, filterDa
     const suggestionsTemp = {}
     for (const quantity of quantitiesFixed) {
       const fixed = staticSuggestions[quantity.name]
-      suggestionsTemp[quantity.name] = fixed.filter(input)
+      suggestionsTemp[quantity.name] = fixed.filter(input).map((value) => ({value, category: quantity.name}))
     }
 
     // Start loading the dynamic suggestions
@@ -143,7 +143,6 @@ export function useSuggestions(quantitiesSuggest, quantitiesAll, input, filterDa
                 suggestionsTemp[quantity.name] = esSuggestions.map(suggestion => ({
                   category: quantity.name,
                   value: suggestion.value
-                  // text: `${quantity.name}=${suggestion.value}`
                 }))
               }
             }
diff --git a/gui/src/utils.js b/gui/src/utils.js
index cf3f085bbdd9ea66022aa1bd3c36c57de776deca..ff56409ec2e9c04278327a7308c17d0800e966c9 100644
--- a/gui/src/utils.js
+++ b/gui/src/utils.js
@@ -1384,24 +1384,26 @@ export const alphabet = [
  *
  * @param {array} values Array of available values
  * @param {number} minLength Minimum input length before suggestions are considered.
- * @param {str} category Category for the suggestions
  * @param {func} text Function that maps the value into the suggested text input
  *
  * @return {object} Object containing a list of options and a function for
  *   filtering them based on the input.
  */
-export function getSuggestions(
-  values, minLength = 2, category) {
+export function getSuggestions(values, minLength = 2, get = (x) => x) {
+  const normalizer = (input) => {
+    return input
+      .replace(/[_.]/g, ' ') // Ignore dots and underscores
+      .replace(/[ ]/g, '') // Ignore whitespacing
+      .toLowerCase() // Ignore case
+  }
+
   const options = values
-    .map(value => {
-      const optionCleaned = value.trim().replace(/_/g, ' ').toLowerCase()
-      const matches = [...optionCleaned.matchAll(/[ .]/g)]
-      let tokens = [optionCleaned]
-      tokens = tokens.concat(matches.map(match => optionCleaned.slice(match.index + 1)))
+    .map(item => {
+      const value = get(item)
       return {
         value: value,
-        category: category,
-        tokens: tokens
+        normalized: normalizer(value),
+        original: item
       }
     })
   const filter = (input) => {
@@ -1410,13 +1412,13 @@ export function getSuggestions(
       return []
     }
     // Gather all matches
-    const inputCleaned = input.trim().replace(/_/g, ' ').toLowerCase()
-    let suggestions = options.filter(option => option.tokens.some(token => token.startsWith(inputCleaned)))
+    const inputNormalized = normalizer(input)
+    let suggestions = options.filter(option => option.normalized.includes(inputNormalized))
 
     // Sort matches based on value length (the more the input covers from the
     // value, the better the match)
     suggestions = suggestions.sort((a, b) => a.value.length - b.value.length)
-    return suggestions
+    return suggestions.map(suggestion => suggestion.original)
   }
 
   return {options, filter}
diff --git a/gui/tests/artifacts.js b/gui/tests/artifacts.js
index 397ef3c209af761569dbec9919aeb8e7dbcd5d84..a379a92ab57934cc55a8bd3d7b73517b2890dfae 100644
--- a/gui/tests/artifacts.js
+++ b/gui/tests/artifacts.js
@@ -143,6 +143,19 @@ window.nomadArtifacts = {
       "aggregatable": false,
       "dynamic": false
     },
+    "text_search_contents": {
+      "name": "text_search_contents",
+      "description": "Contains text contents that should be considered when\ndoing free text queries for entries.",
+      "type": {
+        "type_kind": "python",
+        "type_data": "str"
+      },
+      "shape": [
+        "*"
+      ],
+      "aggregatable": false,
+      "dynamic": false
+    },
     "files": {
       "name": "files",
       "description": "The paths to the files within the upload that belong to this entry.\nAll files within the same directory as the entry's mainfile are considered the\nauxiliary files that belong to the entry.",
@@ -27885,6 +27898,25 @@ window.nomadArtifacts = {
                 "m_def": "nomad.metainfo.metainfo.Quantity",
                 "m_parent_index": 13,
                 "m_parent_sub_section": "quantities",
+                "m_annotations": {
+                  "elasticsearch": [
+                    "text_search_contents"
+                  ]
+                },
+                "name": "text_search_contents",
+                "description": "Contains text contents that should be considered when\ndoing free text queries for entries.",
+                "type": {
+                  "type_kind": "python",
+                  "type_data": "str"
+                },
+                "shape": [
+                  "*"
+                ]
+              },
+              {
+                "m_def": "nomad.metainfo.metainfo.Quantity",
+                "m_parent_index": 14,
+                "m_parent_sub_section": "quantities",
                 "m_annotations": {
                   "elasticsearch": [
                     "files",
@@ -27903,7 +27935,7 @@ window.nomadArtifacts = {
               },
               {
                 "m_def": "nomad.metainfo.metainfo.Quantity",
-                "m_parent_index": 14,
+                "m_parent_index": 15,
                 "m_parent_sub_section": "quantities",
                 "m_annotations": {
                   "elasticsearch": [
@@ -27922,7 +27954,7 @@ window.nomadArtifacts = {
               },
               {
                 "m_def": "nomad.metainfo.metainfo.Quantity",
-                "m_parent_index": 15,
+                "m_parent_index": 16,
                 "m_parent_sub_section": "quantities",
                 "m_annotations": {
                   "elasticsearch": [
@@ -27938,7 +27970,7 @@ window.nomadArtifacts = {
               },
               {
                 "m_def": "nomad.metainfo.metainfo.Quantity",
-                "m_parent_index": 16,
+                "m_parent_index": 17,
                 "m_parent_sub_section": "quantities",
                 "m_annotations": {
                   "elasticsearch": [
@@ -27958,7 +27990,7 @@ window.nomadArtifacts = {
               },
               {
                 "m_def": "nomad.metainfo.metainfo.Quantity",
-                "m_parent_index": 17,
+                "m_parent_index": 18,
                 "m_parent_sub_section": "quantities",
                 "m_annotations": {
                   "elasticsearch": [
@@ -27978,7 +28010,7 @@ window.nomadArtifacts = {
               },
               {
                 "m_def": "nomad.metainfo.metainfo.Quantity",
-                "m_parent_index": 18,
+                "m_parent_index": 19,
                 "m_parent_sub_section": "quantities",
                 "m_annotations": {
                   "auth_level": [
@@ -28001,7 +28033,7 @@ window.nomadArtifacts = {
               },
               {
                 "m_def": "nomad.metainfo.metainfo.Quantity",
-                "m_parent_index": 19,
+                "m_parent_index": 20,
                 "m_parent_sub_section": "quantities",
                 "m_annotations": {
                   "elasticsearch": [
@@ -28022,7 +28054,7 @@ window.nomadArtifacts = {
               },
               {
                 "m_def": "nomad.metainfo.metainfo.Quantity",
-                "m_parent_index": 20,
+                "m_parent_index": 21,
                 "m_parent_sub_section": "quantities",
                 "name": "embargo_length",
                 "description": "The length of the requested embargo period, in months",
@@ -28037,7 +28069,7 @@ window.nomadArtifacts = {
               },
               {
                 "m_def": "nomad.metainfo.metainfo.Quantity",
-                "m_parent_index": 21,
+                "m_parent_index": 22,
                 "m_parent_sub_section": "quantities",
                 "m_annotations": {
                   "auth_level": [
@@ -28058,7 +28090,7 @@ window.nomadArtifacts = {
               },
               {
                 "m_def": "nomad.metainfo.metainfo.Quantity",
-                "m_parent_index": 22,
+                "m_parent_index": 23,
                 "m_parent_sub_section": "quantities",
                 "m_annotations": {
                   "elasticsearch": [
@@ -28079,7 +28111,7 @@ window.nomadArtifacts = {
               },
               {
                 "m_def": "nomad.metainfo.metainfo.Quantity",
-                "m_parent_index": 23,
+                "m_parent_index": 24,
                 "m_parent_sub_section": "quantities",
                 "m_annotations": {
                   "elasticsearch": [
@@ -28098,7 +28130,7 @@ window.nomadArtifacts = {
               },
               {
                 "m_def": "nomad.metainfo.metainfo.Quantity",
-                "m_parent_index": 24,
+                "m_parent_index": 25,
                 "m_parent_sub_section": "quantities",
                 "m_annotations": {
                   "elasticsearch": [
@@ -28117,7 +28149,7 @@ window.nomadArtifacts = {
               },
               {
                 "m_def": "nomad.metainfo.metainfo.Quantity",
-                "m_parent_index": 25,
+                "m_parent_index": 26,
                 "m_parent_sub_section": "quantities",
                 "m_annotations": {
                   "elasticsearch": [
@@ -28136,7 +28168,7 @@ window.nomadArtifacts = {
               },
               {
                 "m_def": "nomad.metainfo.metainfo.Quantity",
-                "m_parent_index": 26,
+                "m_parent_index": 27,
                 "m_parent_sub_section": "quantities",
                 "m_annotations": {
                   "elasticsearch": [
@@ -28155,7 +28187,7 @@ window.nomadArtifacts = {
               },
               {
                 "m_def": "nomad.metainfo.metainfo.Quantity",
-                "m_parent_index": 27,
+                "m_parent_index": 28,
                 "m_parent_sub_section": "quantities",
                 "m_annotations": {
                   "elasticsearch": [
@@ -28175,7 +28207,7 @@ window.nomadArtifacts = {
               },
               {
                 "m_def": "nomad.metainfo.metainfo.Quantity",
-                "m_parent_index": 28,
+                "m_parent_index": 29,
                 "m_parent_sub_section": "quantities",
                 "m_annotations": {
                   "elasticsearch": [
@@ -28198,7 +28230,7 @@ window.nomadArtifacts = {
               },
               {
                 "m_def": "nomad.metainfo.metainfo.Quantity",
-                "m_parent_index": 29,
+                "m_parent_index": 30,
                 "m_parent_sub_section": "quantities",
                 "m_annotations": {
                   "elasticsearch": [
@@ -28225,7 +28257,7 @@ window.nomadArtifacts = {
               },
               {
                 "m_def": "nomad.metainfo.metainfo.Quantity",
-                "m_parent_index": 30,
+                "m_parent_index": 31,
                 "m_parent_sub_section": "quantities",
                 "m_annotations": {
                   "elasticsearch": [
@@ -28242,7 +28274,7 @@ window.nomadArtifacts = {
               },
               {
                 "m_def": "nomad.metainfo.metainfo.Quantity",
-                "m_parent_index": 31,
+                "m_parent_index": 32,
                 "m_parent_sub_section": "quantities",
                 "m_annotations": {
                   "auth_level": [
@@ -28265,7 +28297,7 @@ window.nomadArtifacts = {
               },
               {
                 "m_def": "nomad.metainfo.metainfo.Quantity",
-                "m_parent_index": 32,
+                "m_parent_index": 33,
                 "m_parent_sub_section": "quantities",
                 "name": "coauthors",
                 "description": "A user provided list of co-authors for the whole upload. These can view and edit the\nupload when in staging, and view it also if it is embargoed.",
@@ -28284,7 +28316,7 @@ window.nomadArtifacts = {
               },
               {
                 "m_def": "nomad.metainfo.metainfo.Quantity",
-                "m_parent_index": 33,
+                "m_parent_index": 34,
                 "m_parent_sub_section": "quantities",
                 "name": "entry_coauthors",
                 "description": "A user provided list of co-authors specific for this entry. This is a legacy field,\nfor new uploads, coauthors should be specified on the upload level only.",
@@ -28302,7 +28334,7 @@ window.nomadArtifacts = {
               },
               {
                 "m_def": "nomad.metainfo.metainfo.Quantity",
-                "m_parent_index": 34,
+                "m_parent_index": 35,
                 "m_parent_sub_section": "quantities",
                 "name": "reviewers",
                 "description": "A user provided list of reviewers. Reviewers can see the whole upload, also if\nit is unpublished or embargoed",
@@ -28321,7 +28353,7 @@ window.nomadArtifacts = {
               },
               {
                 "m_def": "nomad.metainfo.metainfo.Quantity",
-                "m_parent_index": 35,
+                "m_parent_index": 36,
                 "m_parent_sub_section": "quantities",
                 "m_annotations": {
                   "elasticsearch": [
@@ -28341,7 +28373,7 @@ window.nomadArtifacts = {
               },
               {
                 "m_def": "nomad.metainfo.metainfo.Quantity",
-                "m_parent_index": 36,
+                "m_parent_index": 37,
                 "m_parent_sub_section": "quantities",
                 "m_annotations": {
                   "elasticsearch": [
@@ -28361,7 +28393,7 @@ window.nomadArtifacts = {
               },
               {
                 "m_def": "nomad.metainfo.metainfo.Quantity",
-                "m_parent_index": 37,
+                "m_parent_index": 38,
                 "m_parent_sub_section": "quantities",
                 "m_annotations": {
                   "elasticsearch": [
@@ -28381,7 +28413,7 @@ window.nomadArtifacts = {
               },
               {
                 "m_def": "nomad.metainfo.metainfo.Quantity",
-                "m_parent_index": 38,
+                "m_parent_index": 39,
                 "m_parent_sub_section": "quantities",
                 "m_annotations": {
                   "elasticsearch": [
@@ -28405,7 +28437,7 @@ window.nomadArtifacts = {
               },
               {
                 "m_def": "nomad.metainfo.metainfo.Quantity",
-                "m_parent_index": 39,
+                "m_parent_index": 40,
                 "m_parent_sub_section": "quantities",
                 "m_annotations": {
                   "elasticsearch": [
@@ -28424,7 +28456,7 @@ window.nomadArtifacts = {
               },
               {
                 "m_def": "nomad.metainfo.metainfo.Quantity",
-                "m_parent_index": 40,
+                "m_parent_index": 41,
                 "m_parent_sub_section": "quantities",
                 "m_annotations": {
                   "elasticsearch": [
@@ -28441,7 +28473,7 @@ window.nomadArtifacts = {
               },
               {
                 "m_def": "nomad.metainfo.metainfo.Quantity",
-                "m_parent_index": 41,
+                "m_parent_index": 42,
                 "m_parent_sub_section": "quantities",
                 "m_annotations": {
                   "elasticsearch": [
@@ -28461,7 +28493,7 @@ window.nomadArtifacts = {
               },
               {
                 "m_def": "nomad.metainfo.metainfo.Quantity",
-                "m_parent_index": 42,
+                "m_parent_index": 43,
                 "m_parent_sub_section": "quantities",
                 "m_annotations": {
                   "elasticsearch": [
diff --git a/gui/tests/env.js b/gui/tests/env.js
index b8819f67867beb497dd99b339daddd33e4184008..bf5a2a57cc5e61b7e835f996b5e89c079fbef21c 100644
--- a/gui/tests/env.js
+++ b/gui/tests/env.js
@@ -714,6 +714,11 @@ window.nomadEnv = {
               "entry_name",
               "combine"
             ]
+          },
+          "search_syntaxes": {
+            "exclude": [
+              "free_text"
+            ]
           }
         },
         "calculations": {
@@ -1191,6 +1196,11 @@ window.nomadEnv = {
           },
           "filters_locked": {
             "quantities": "results.method.simulation.program_name"
+          },
+          "search_syntaxes": {
+            "exclude": [
+              "free_text"
+            ]
           }
         },
         "materials": {
@@ -1372,6 +1382,11 @@ window.nomadEnv = {
               "mainfile",
               "entry_name"
             ]
+          },
+          "search_syntaxes": {
+            "exclude": [
+              "free_text"
+            ]
           }
         },
         "eln": {
@@ -1657,6 +1672,11 @@ window.nomadEnv = {
           },
           "filters_locked": {
             "results.method.method_name": "EELS"
+          },
+          "search_syntaxes": {
+            "exclude": [
+              "free_text"
+            ]
           }
         },
         "solarcells": {
@@ -2311,6 +2331,11 @@ window.nomadEnv = {
           },
           "filters_locked": {
             "sections": "nomad.datamodel.results.SolarCell"
+          },
+          "search_syntaxes": {
+            "exclude": [
+              "free_text"
+            ]
           }
         },
         "heterogeneouscatalyst": {
@@ -3250,6 +3275,11 @@ window.nomadEnv = {
           },
           "filters_locked": {
             "quantities": "results.properties.catalytic"
+          },
+          "search_syntaxes": {
+            "exclude": [
+              "free_text"
+            ]
           }
         },
         "mofs": {
@@ -3659,6 +3689,11 @@ window.nomadEnv = {
           },
           "filters_locked": {
             "results.material.topology.label": "MOF"
+          },
+          "search_syntaxes": {
+            "exclude": [
+              "free_text"
+            ]
           }
         }
       }
diff --git a/gui/yarn.lock b/gui/yarn.lock
index 856f5ebd87c3d956d1f1e0cfc84b4474fbd0337a..57b91c21cedeb6435e5b111a04588174d1e261c0 100644
--- a/gui/yarn.lock
+++ b/gui/yarn.lock
@@ -36,6 +36,14 @@
   dependencies:
     "@babel/highlight" "^7.18.6"
 
+"@babel/code-frame@^7.22.13", "@babel/code-frame@^7.23.5":
+  version "7.23.5"
+  resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244"
+  integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==
+  dependencies:
+    "@babel/highlight" "^7.23.4"
+    chalk "^2.4.2"
+
 "@babel/compat-data@^7.17.7", "@babel/compat-data@^7.18.8":
   version "7.18.13"
   resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.18.13.tgz#6aff7b350a1e8c3e40b029e46cbe78e24a913483"
@@ -102,6 +110,16 @@
     "@jridgewell/gen-mapping" "^0.3.2"
     jsesc "^2.5.1"
 
+"@babel/generator@^7.23.5":
+  version "7.23.5"
+  resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.5.tgz#17d0a1ea6b62f351d281350a5f80b87a810c4755"
+  integrity sha512-BPssCHrBD+0YrxviOa3QzpqwhNIXKEtOa2jQrm4FlmkC2apYgRnQcmPWiGZDlGxiNtltnUFolMe8497Esry+jA==
+  dependencies:
+    "@babel/types" "^7.23.5"
+    "@jridgewell/gen-mapping" "^0.3.2"
+    "@jridgewell/trace-mapping" "^0.3.17"
+    jsesc "^2.5.1"
+
 "@babel/helper-annotate-as-pure@^7.18.6":
   version "7.18.6"
   resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb"
@@ -165,6 +183,11 @@
   resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be"
   integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==
 
+"@babel/helper-environment-visitor@^7.22.20":
+  version "7.22.20"
+  resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167"
+  integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==
+
 "@babel/helper-explode-assignable-expression@^7.18.6":
   version "7.18.6"
   resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz#41f8228ef0a6f1a036b8dfdfec7ce94f9a6bc096"
@@ -180,6 +203,14 @@
     "@babel/template" "^7.18.6"
     "@babel/types" "^7.18.9"
 
+"@babel/helper-function-name@^7.23.0":
+  version "7.23.0"
+  resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759"
+  integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==
+  dependencies:
+    "@babel/template" "^7.22.15"
+    "@babel/types" "^7.23.0"
+
 "@babel/helper-hoist-variables@^7.18.6":
   version "7.18.6"
   resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678"
@@ -187,6 +218,13 @@
   dependencies:
     "@babel/types" "^7.18.6"
 
+"@babel/helper-hoist-variables@^7.22.5":
+  version "7.22.5"
+  resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb"
+  integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==
+  dependencies:
+    "@babel/types" "^7.22.5"
+
 "@babel/helper-member-expression-to-functions@^7.18.9":
   version "7.18.9"
   resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz#1531661e8375af843ad37ac692c132841e2fd815"
@@ -269,16 +307,33 @@
   dependencies:
     "@babel/types" "^7.18.6"
 
+"@babel/helper-split-export-declaration@^7.22.6":
+  version "7.22.6"
+  resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c"
+  integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==
+  dependencies:
+    "@babel/types" "^7.22.5"
+
 "@babel/helper-string-parser@^7.18.10":
   version "7.18.10"
   resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz#181f22d28ebe1b3857fa575f5c290b1aaf659b56"
   integrity sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==
 
+"@babel/helper-string-parser@^7.23.4":
+  version "7.23.4"
+  resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83"
+  integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==
+
 "@babel/helper-validator-identifier@^7.18.6":
   version "7.18.6"
   resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz#9c97e30d31b2b8c72a1d08984f2ca9b574d7a076"
   integrity sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==
 
+"@babel/helper-validator-identifier@^7.22.20":
+  version "7.22.20"
+  resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0"
+  integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==
+
 "@babel/helper-validator-option@^7.18.6":
   version "7.18.6"
   resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8"
@@ -312,11 +367,25 @@
     chalk "^2.0.0"
     js-tokens "^4.0.0"
 
+"@babel/highlight@^7.23.4":
+  version "7.23.4"
+  resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b"
+  integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==
+  dependencies:
+    "@babel/helper-validator-identifier" "^7.22.20"
+    chalk "^2.4.2"
+    js-tokens "^4.0.0"
+
 "@babel/parser@^7.1.0", "@babel/parser@^7.12.3", "@babel/parser@^7.14.7", "@babel/parser@^7.18.10", "@babel/parser@^7.18.13":
   version "7.18.13"
   resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.13.tgz#5b2dd21cae4a2c5145f1fbd8ca103f9313d3b7e4"
   integrity sha512-dgXcIfMuQ0kgzLB2b9tRZs7TTFFaGM2AbtA4fJgUUYukzGH4jwsS7hzQHEGs67jdehpm22vkgKwvbU+aEflgwg==
 
+"@babel/parser@^7.22.15", "@babel/parser@^7.23.5", "@babel/parser@^7.7.0":
+  version "7.23.5"
+  resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.5.tgz#37dee97c4752af148e1d38c34b856b2507660563"
+  integrity sha512-hOOqoiNXrmGdFbhgCzu6GiURxUgM27Xwd/aPuu8RfHEZPBzL1Z54okAHAQjXfcQNwvrlkAmAp4SlRTZ45vlthQ==
+
 "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6":
   version "7.18.6"
   resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz#da5b8f9a580acdfbe53494dba45ea389fb09a4d2"
@@ -1090,6 +1159,13 @@
   dependencies:
     regenerator-runtime "^0.13.11"
 
+"@babel/runtime@^7.21.0":
+  version "7.23.5"
+  resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.5.tgz#11edb98f8aeec529b82b211028177679144242db"
+  integrity sha512-NdUTHcPe4C99WxPub+K9l9tK5/lV4UXIoaHSYgzco9BCyjKAAwzdBI+wWtYqHt7LJdbo74ZjRPJgzVweq1sz0w==
+  dependencies:
+    regenerator-runtime "^0.14.0"
+
 "@babel/template@^7.10.4", "@babel/template@^7.18.10", "@babel/template@^7.18.6", "@babel/template@^7.3.3":
   version "7.18.10"
   resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71"
@@ -1099,6 +1175,15 @@
     "@babel/parser" "^7.18.10"
     "@babel/types" "^7.18.10"
 
+"@babel/template@^7.22.15":
+  version "7.22.15"
+  resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38"
+  integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==
+  dependencies:
+    "@babel/code-frame" "^7.22.13"
+    "@babel/parser" "^7.22.15"
+    "@babel/types" "^7.22.15"
+
 "@babel/traverse@^7.1.0", "@babel/traverse@^7.1.6", "@babel/traverse@^7.12.1", "@babel/traverse@^7.18.11", "@babel/traverse@^7.18.13", "@babel/traverse@^7.18.9", "@babel/traverse@^7.4.5", "@babel/traverse@^7.6.2":
   version "7.18.13"
   resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.18.13.tgz#5ab59ef51a997b3f10c4587d648b9696b6cb1a68"
@@ -1115,6 +1200,22 @@
     debug "^4.1.0"
     globals "^11.1.0"
 
+"@babel/traverse@^7.7.0":
+  version "7.23.5"
+  resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.5.tgz#f546bf9aba9ef2b042c0e00d245990c15508e7ec"
+  integrity sha512-czx7Xy5a6sapWWRx61m1Ke1Ra4vczu1mCTtJam5zRTBOonfdJ+S/B6HYmGYu3fJtr8GGET3si6IhgWVBhJ/m8w==
+  dependencies:
+    "@babel/code-frame" "^7.23.5"
+    "@babel/generator" "^7.23.5"
+    "@babel/helper-environment-visitor" "^7.22.20"
+    "@babel/helper-function-name" "^7.23.0"
+    "@babel/helper-hoist-variables" "^7.22.5"
+    "@babel/helper-split-export-declaration" "^7.22.6"
+    "@babel/parser" "^7.23.5"
+    "@babel/types" "^7.23.5"
+    debug "^4.1.0"
+    globals "^11.1.0"
+
 "@babel/types@^7.0.0", "@babel/types@^7.12.1", "@babel/types@^7.12.6", "@babel/types@^7.18.10", "@babel/types@^7.18.13", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.2.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4":
   version "7.18.13"
   resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.18.13.tgz#30aeb9e514f4100f7c1cb6e5ba472b30e48f519a"
@@ -1124,6 +1225,15 @@
     "@babel/helper-validator-identifier" "^7.18.6"
     to-fast-properties "^2.0.0"
 
+"@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.5", "@babel/types@^7.7.0":
+  version "7.23.5"
+  resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.5.tgz#48d730a00c95109fa4393352705954d74fb5b602"
+  integrity sha512-ON5kSOJwVO6xXVRTvOI0eOnWe7VdUcIpsovGo9U/Br4Ie4UVFQTboO2cYnDhAGU6Fp+UxSiT+pMft0SMHfuq6w==
+  dependencies:
+    "@babel/helper-string-parser" "^7.23.4"
+    "@babel/helper-validator-identifier" "^7.22.20"
+    to-fast-properties "^2.0.0"
+
 "@bcoe/v8-coverage@^0.2.3":
   version "0.2.3"
   resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
@@ -1544,6 +1654,11 @@
   resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78"
   integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==
 
+"@jridgewell/resolve-uri@^3.1.0":
+  version "3.1.1"
+  resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721"
+  integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==
+
 "@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1":
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72"
@@ -1557,11 +1672,24 @@
     "@jridgewell/gen-mapping" "^0.3.0"
     "@jridgewell/trace-mapping" "^0.3.9"
 
+"@jridgewell/source-map@^0.3.3":
+  version "0.3.5"
+  resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.5.tgz#a3bb4d5c6825aab0d281268f47f6ad5853431e91"
+  integrity sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==
+  dependencies:
+    "@jridgewell/gen-mapping" "^0.3.0"
+    "@jridgewell/trace-mapping" "^0.3.9"
+
 "@jridgewell/sourcemap-codec@^1.4.10":
   version "1.4.14"
   resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24"
   integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==
 
+"@jridgewell/sourcemap-codec@^1.4.14":
+  version "1.4.15"
+  resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
+  integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
+
 "@jridgewell/trace-mapping@0.3.9":
   version "0.3.9"
   resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9"
@@ -1570,7 +1698,7 @@
     "@jridgewell/resolve-uri" "^3.0.3"
     "@jridgewell/sourcemap-codec" "^1.4.10"
 
-"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.14", "@jridgewell/trace-mapping@^0.3.9":
+"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.9":
   version "0.3.15"
   resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz#aba35c48a38d3fd84b37e66c9c0423f9744f9774"
   integrity sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==
@@ -1578,6 +1706,14 @@
     "@jridgewell/resolve-uri" "^3.0.3"
     "@jridgewell/sourcemap-codec" "^1.4.10"
 
+"@jridgewell/trace-mapping@^0.3.17":
+  version "0.3.20"
+  resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz#72e45707cf240fa6b081d0366f8265b0cd10197f"
+  integrity sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==
+  dependencies:
+    "@jridgewell/resolve-uri" "^3.1.0"
+    "@jridgewell/sourcemap-codec" "^1.4.14"
+
 "@material-ui/codemod@^4.5.0":
   version "4.5.1"
   resolved "https://registry.yarnpkg.com/@material-ui/codemod/-/codemod-4.5.1.tgz#5be24c352897a4018e817f4d65416041234430c3"
@@ -2096,11 +2232,6 @@
   dependencies:
     "@babel/types" "^7.3.0"
 
-"@types/component-emitter@^1.2.10":
-  version "1.2.11"
-  resolved "https://registry.yarnpkg.com/@types/component-emitter/-/component-emitter-1.2.11.tgz#50d47d42b347253817a39709fef03ce66a108506"
-  integrity sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==
-
 "@types/cookie@^0.3.1":
   version "0.3.3"
   resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.3.3.tgz#85bc74ba782fb7aa3a514d11767832b0e3bc6803"
@@ -2112,9 +2243,11 @@
   integrity sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==
 
 "@types/cors@^2.8.12":
-  version "2.8.12"
-  resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.12.tgz#6b2c510a7ad7039e98e7b8d3d6598f4359e5c080"
-  integrity sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==
+  version "2.8.17"
+  resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.17.tgz#5d718a5e494a8166f569d986794e49c48b216b2b"
+  integrity sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==
+  dependencies:
+    "@types/node" "*"
 
 "@types/d3-color@*":
   version "3.1.0"
@@ -2165,17 +2298,17 @@
     "@types/ms" "*"
 
 "@types/eslint-scope@^3.7.3":
-  version "3.7.4"
-  resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16"
-  integrity sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==
+  version "3.7.7"
+  resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5"
+  integrity sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==
   dependencies:
     "@types/eslint" "*"
     "@types/estree" "*"
 
 "@types/eslint@*":
-  version "8.4.6"
-  resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.6.tgz#7976f054c1bccfcf514bff0564c0c41df5c08207"
-  integrity sha512-/fqTbjxyFUaYNO7VcW5g+4npmqVACz1bB7RTHYuLj+PRjw9hrCwrUXVQFpChUS0JsyEFvMZ7U/PfmvWgxJhI9g==
+  version "8.44.8"
+  resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.44.8.tgz#f4fe1dab9b3d3dd98082d4b9f80e59ab40f1261c"
+  integrity sha512-4K8GavROwhrYl2QXDXm0Rv9epkA8GBFu0EI+XrrnnuCl7u8CWBRusX7fXJfanhZTDWSAL24gDI/UqXyUM0Injw==
   dependencies:
     "@types/estree" "*"
     "@types/json-schema" "*"
@@ -2198,10 +2331,10 @@
   resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f"
   integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==
 
-"@types/estree@^0.0.51":
-  version "0.0.51"
-  resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40"
-  integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==
+"@types/estree@^1.0.0":
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4"
+  integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==
 
 "@types/glob@^7.1.1":
   version "7.2.0"
@@ -2219,11 +2352,11 @@
     "@types/node" "*"
 
 "@types/hast@^2.0.0":
-  version "2.3.4"
-  resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.4.tgz#8aa5ef92c117d20d974a82bdfb6a648b08c0bafc"
-  integrity sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==
+  version "2.3.8"
+  resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.8.tgz#4ac5caf38b262b7bd5ca3202dda71f0271635660"
+  integrity sha512-aMIqAlFd2wTIDZuvLbhUT+TGvMxrNC8ECUIVtH6xxy0sQLs3iu6NO8Kp/VT5je7i5ufnebXzdV1dNDMnvaH6IQ==
   dependencies:
-    "@types/unist" "*"
+    "@types/unist" "^2"
 
 "@types/hoist-non-react-statics@^3.0.1":
   version "3.3.1"
@@ -2309,11 +2442,6 @@
   dependencies:
     "@types/unist" "*"
 
-"@types/mdurl@^1.0.0":
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/@types/mdurl/-/mdurl-1.0.2.tgz#e2ce9d83a613bacf284c7be7d491945e39e1f8e9"
-  integrity sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==
-
 "@types/minimatch@*":
   version "5.1.0"
   resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.0.tgz#c3018161691376002f8a22ebb87f341e0dba3219"
@@ -2324,11 +2452,18 @@
   resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197"
   integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==
 
-"@types/node@*", "@types/node@>=10.0.0":
+"@types/node@*":
   version "18.7.13"
   resolved "https://registry.yarnpkg.com/@types/node/-/node-18.7.13.tgz#23e6c5168333480d454243378b69e861ab5c011a"
   integrity sha512-46yIhxSe5xEaJZXWdIBP7GU4HDTG8/eo0qd9atdiL+lFpA03y8KS+lkTN834TWJj5767GbWv4n/P6efyTFt1Dw==
 
+"@types/node@>=10.0.0":
+  version "20.10.3"
+  resolved "https://registry.yarnpkg.com/@types/node/-/node-20.10.3.tgz#4900adcc7fc189d5af5bb41da8f543cea6962030"
+  integrity sha512-XJavIpZqiXID5Yxnxv3RUDKTN5b81ddNC3ecsA0SoFXz/QU8OGBwZGMomiq0zw+uuqbL/krztv/DINAQ/EV4gg==
+  dependencies:
+    undici-types "~5.26.4"
+
 "@types/normalize-package-data@^2.4.0":
   version "2.4.1"
   resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301"
@@ -2349,11 +2484,16 @@
   resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.0.tgz#ea03e9f0376a4446f44797ca19d9c46c36e352dc"
   integrity sha512-RI1L7N4JnW5gQw2spvL7Sllfuf1SaHdrZpCHiBlCXjIlufi1SMNnbu2teze3/QE67Fg2tBlH7W+mi4hVNk4p0A==
 
-"@types/prop-types@*", "@types/prop-types@^15.0.0":
+"@types/prop-types@*":
   version "15.7.5"
   resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf"
   integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==
 
+"@types/prop-types@^15.0.0":
+  version "15.7.11"
+  resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.11.tgz#2596fb352ee96a1379c657734d4b913a613ad563"
+  integrity sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==
+
 "@types/q@^1.5.1":
   version "1.5.5"
   resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.5.tgz#75a2a8e7d8ab4b230414505d92335d1dcb53a6df"
@@ -2470,6 +2610,11 @@
   resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d"
   integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==
 
+"@types/unist@^2":
+  version "2.0.10"
+  resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.10.tgz#04ffa7f406ab628f7f7e97ca23e290cd8ab15efc"
+  integrity sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==
+
 "@types/webpack-sources@*":
   version "3.2.0"
   resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-3.2.0.tgz#16d759ba096c289034b26553d2df1bf45248d38b"
@@ -2793,13 +2938,13 @@
     prop-types "^15.5.10"
     react-use-measure "^2.0.4"
 
-"@webassemblyjs/ast@1.11.1":
-  version "1.11.1"
-  resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7"
-  integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==
+"@webassemblyjs/ast@1.11.6", "@webassemblyjs/ast@^1.11.5":
+  version "1.11.6"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.6.tgz#db046555d3c413f8966ca50a95176a0e2c642e24"
+  integrity sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==
   dependencies:
-    "@webassemblyjs/helper-numbers" "1.11.1"
-    "@webassemblyjs/helper-wasm-bytecode" "1.11.1"
+    "@webassemblyjs/helper-numbers" "1.11.6"
+    "@webassemblyjs/helper-wasm-bytecode" "1.11.6"
 
 "@webassemblyjs/ast@1.9.0":
   version "1.9.0"
@@ -2810,30 +2955,30 @@
     "@webassemblyjs/helper-wasm-bytecode" "1.9.0"
     "@webassemblyjs/wast-parser" "1.9.0"
 
-"@webassemblyjs/floating-point-hex-parser@1.11.1":
-  version "1.11.1"
-  resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f"
-  integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==
+"@webassemblyjs/floating-point-hex-parser@1.11.6":
+  version "1.11.6"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431"
+  integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==
 
 "@webassemblyjs/floating-point-hex-parser@1.9.0":
   version "1.9.0"
   resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz#3c3d3b271bddfc84deb00f71344438311d52ffb4"
   integrity sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==
 
-"@webassemblyjs/helper-api-error@1.11.1":
-  version "1.11.1"
-  resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16"
-  integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==
+"@webassemblyjs/helper-api-error@1.11.6":
+  version "1.11.6"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768"
+  integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==
 
 "@webassemblyjs/helper-api-error@1.9.0":
   version "1.9.0"
   resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz#203f676e333b96c9da2eeab3ccef33c45928b6a2"
   integrity sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==
 
-"@webassemblyjs/helper-buffer@1.11.1":
-  version "1.11.1"
-  resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5"
-  integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==
+"@webassemblyjs/helper-buffer@1.11.6":
+  version "1.11.6"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz#b66d73c43e296fd5e88006f18524feb0f2c7c093"
+  integrity sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==
 
 "@webassemblyjs/helper-buffer@1.9.0":
   version "1.9.0"
@@ -2859,34 +3004,34 @@
   dependencies:
     "@webassemblyjs/ast" "1.9.0"
 
-"@webassemblyjs/helper-numbers@1.11.1":
-  version "1.11.1"
-  resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae"
-  integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==
+"@webassemblyjs/helper-numbers@1.11.6":
+  version "1.11.6"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5"
+  integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==
   dependencies:
-    "@webassemblyjs/floating-point-hex-parser" "1.11.1"
-    "@webassemblyjs/helper-api-error" "1.11.1"
+    "@webassemblyjs/floating-point-hex-parser" "1.11.6"
+    "@webassemblyjs/helper-api-error" "1.11.6"
     "@xtuc/long" "4.2.2"
 
-"@webassemblyjs/helper-wasm-bytecode@1.11.1":
-  version "1.11.1"
-  resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1"
-  integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==
+"@webassemblyjs/helper-wasm-bytecode@1.11.6":
+  version "1.11.6"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9"
+  integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==
 
 "@webassemblyjs/helper-wasm-bytecode@1.9.0":
   version "1.9.0"
   resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz#4fed8beac9b8c14f8c58b70d124d549dd1fe5790"
   integrity sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==
 
-"@webassemblyjs/helper-wasm-section@1.11.1":
-  version "1.11.1"
-  resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a"
-  integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==
+"@webassemblyjs/helper-wasm-section@1.11.6":
+  version "1.11.6"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz#ff97f3863c55ee7f580fd5c41a381e9def4aa577"
+  integrity sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==
   dependencies:
-    "@webassemblyjs/ast" "1.11.1"
-    "@webassemblyjs/helper-buffer" "1.11.1"
-    "@webassemblyjs/helper-wasm-bytecode" "1.11.1"
-    "@webassemblyjs/wasm-gen" "1.11.1"
+    "@webassemblyjs/ast" "1.11.6"
+    "@webassemblyjs/helper-buffer" "1.11.6"
+    "@webassemblyjs/helper-wasm-bytecode" "1.11.6"
+    "@webassemblyjs/wasm-gen" "1.11.6"
 
 "@webassemblyjs/helper-wasm-section@1.9.0":
   version "1.9.0"
@@ -2898,10 +3043,10 @@
     "@webassemblyjs/helper-wasm-bytecode" "1.9.0"
     "@webassemblyjs/wasm-gen" "1.9.0"
 
-"@webassemblyjs/ieee754@1.11.1":
-  version "1.11.1"
-  resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614"
-  integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==
+"@webassemblyjs/ieee754@1.11.6":
+  version "1.11.6"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a"
+  integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==
   dependencies:
     "@xtuc/ieee754" "^1.2.0"
 
@@ -2912,10 +3057,10 @@
   dependencies:
     "@xtuc/ieee754" "^1.2.0"
 
-"@webassemblyjs/leb128@1.11.1":
-  version "1.11.1"
-  resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5"
-  integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==
+"@webassemblyjs/leb128@1.11.6":
+  version "1.11.6"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7"
+  integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==
   dependencies:
     "@xtuc/long" "4.2.2"
 
@@ -2926,30 +3071,16 @@
   dependencies:
     "@xtuc/long" "4.2.2"
 
-"@webassemblyjs/utf8@1.11.1":
-  version "1.11.1"
-  resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff"
-  integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==
+"@webassemblyjs/utf8@1.11.6":
+  version "1.11.6"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a"
+  integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==
 
 "@webassemblyjs/utf8@1.9.0":
   version "1.9.0"
   resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.9.0.tgz#04d33b636f78e6a6813227e82402f7637b6229ab"
   integrity sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==
 
-"@webassemblyjs/wasm-edit@1.11.1":
-  version "1.11.1"
-  resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6"
-  integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==
-  dependencies:
-    "@webassemblyjs/ast" "1.11.1"
-    "@webassemblyjs/helper-buffer" "1.11.1"
-    "@webassemblyjs/helper-wasm-bytecode" "1.11.1"
-    "@webassemblyjs/helper-wasm-section" "1.11.1"
-    "@webassemblyjs/wasm-gen" "1.11.1"
-    "@webassemblyjs/wasm-opt" "1.11.1"
-    "@webassemblyjs/wasm-parser" "1.11.1"
-    "@webassemblyjs/wast-printer" "1.11.1"
-
 "@webassemblyjs/wasm-edit@1.9.0":
   version "1.9.0"
   resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz#3fe6d79d3f0f922183aa86002c42dd256cfee9cf"
@@ -2964,16 +3095,30 @@
     "@webassemblyjs/wasm-parser" "1.9.0"
     "@webassemblyjs/wast-printer" "1.9.0"
 
-"@webassemblyjs/wasm-gen@1.11.1":
-  version "1.11.1"
-  resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76"
-  integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==
-  dependencies:
-    "@webassemblyjs/ast" "1.11.1"
-    "@webassemblyjs/helper-wasm-bytecode" "1.11.1"
-    "@webassemblyjs/ieee754" "1.11.1"
-    "@webassemblyjs/leb128" "1.11.1"
-    "@webassemblyjs/utf8" "1.11.1"
+"@webassemblyjs/wasm-edit@^1.11.5":
+  version "1.11.6"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz#c72fa8220524c9b416249f3d94c2958dfe70ceab"
+  integrity sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==
+  dependencies:
+    "@webassemblyjs/ast" "1.11.6"
+    "@webassemblyjs/helper-buffer" "1.11.6"
+    "@webassemblyjs/helper-wasm-bytecode" "1.11.6"
+    "@webassemblyjs/helper-wasm-section" "1.11.6"
+    "@webassemblyjs/wasm-gen" "1.11.6"
+    "@webassemblyjs/wasm-opt" "1.11.6"
+    "@webassemblyjs/wasm-parser" "1.11.6"
+    "@webassemblyjs/wast-printer" "1.11.6"
+
+"@webassemblyjs/wasm-gen@1.11.6":
+  version "1.11.6"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz#fb5283e0e8b4551cc4e9c3c0d7184a65faf7c268"
+  integrity sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==
+  dependencies:
+    "@webassemblyjs/ast" "1.11.6"
+    "@webassemblyjs/helper-wasm-bytecode" "1.11.6"
+    "@webassemblyjs/ieee754" "1.11.6"
+    "@webassemblyjs/leb128" "1.11.6"
+    "@webassemblyjs/utf8" "1.11.6"
 
 "@webassemblyjs/wasm-gen@1.9.0":
   version "1.9.0"
@@ -2986,15 +3131,15 @@
     "@webassemblyjs/leb128" "1.9.0"
     "@webassemblyjs/utf8" "1.9.0"
 
-"@webassemblyjs/wasm-opt@1.11.1":
-  version "1.11.1"
-  resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2"
-  integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==
+"@webassemblyjs/wasm-opt@1.11.6":
+  version "1.11.6"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz#d9a22d651248422ca498b09aa3232a81041487c2"
+  integrity sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==
   dependencies:
-    "@webassemblyjs/ast" "1.11.1"
-    "@webassemblyjs/helper-buffer" "1.11.1"
-    "@webassemblyjs/wasm-gen" "1.11.1"
-    "@webassemblyjs/wasm-parser" "1.11.1"
+    "@webassemblyjs/ast" "1.11.6"
+    "@webassemblyjs/helper-buffer" "1.11.6"
+    "@webassemblyjs/wasm-gen" "1.11.6"
+    "@webassemblyjs/wasm-parser" "1.11.6"
 
 "@webassemblyjs/wasm-opt@1.9.0":
   version "1.9.0"
@@ -3006,17 +3151,17 @@
     "@webassemblyjs/wasm-gen" "1.9.0"
     "@webassemblyjs/wasm-parser" "1.9.0"
 
-"@webassemblyjs/wasm-parser@1.11.1":
-  version "1.11.1"
-  resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199"
-  integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==
+"@webassemblyjs/wasm-parser@1.11.6", "@webassemblyjs/wasm-parser@^1.11.5":
+  version "1.11.6"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz#bb85378c527df824004812bbdb784eea539174a1"
+  integrity sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==
   dependencies:
-    "@webassemblyjs/ast" "1.11.1"
-    "@webassemblyjs/helper-api-error" "1.11.1"
-    "@webassemblyjs/helper-wasm-bytecode" "1.11.1"
-    "@webassemblyjs/ieee754" "1.11.1"
-    "@webassemblyjs/leb128" "1.11.1"
-    "@webassemblyjs/utf8" "1.11.1"
+    "@webassemblyjs/ast" "1.11.6"
+    "@webassemblyjs/helper-api-error" "1.11.6"
+    "@webassemblyjs/helper-wasm-bytecode" "1.11.6"
+    "@webassemblyjs/ieee754" "1.11.6"
+    "@webassemblyjs/leb128" "1.11.6"
+    "@webassemblyjs/utf8" "1.11.6"
 
 "@webassemblyjs/wasm-parser@1.9.0":
   version "1.9.0"
@@ -3042,12 +3187,12 @@
     "@webassemblyjs/helper-fsm" "1.9.0"
     "@xtuc/long" "4.2.2"
 
-"@webassemblyjs/wast-printer@1.11.1":
-  version "1.11.1"
-  resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0"
-  integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==
+"@webassemblyjs/wast-printer@1.11.6":
+  version "1.11.6"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz#a7bf8dd7e362aeb1668ff43f35cb849f188eff20"
+  integrity sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==
   dependencies:
-    "@webassemblyjs/ast" "1.11.1"
+    "@webassemblyjs/ast" "1.11.6"
     "@xtuc/long" "4.2.2"
 
 "@webassemblyjs/wast-printer@1.9.0":
@@ -3107,10 +3252,10 @@ acorn-globals@^6.0.0:
     acorn "^7.1.1"
     acorn-walk "^7.1.1"
 
-acorn-import-assertions@^1.7.6:
-  version "1.8.0"
-  resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9"
-  integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==
+acorn-import-assertions@^1.9.0:
+  version "1.9.0"
+  resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac"
+  integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==
 
 acorn-jsx@^5.3.1:
   version "5.3.2"
@@ -3137,7 +3282,7 @@ acorn@^7.1.0, acorn@^7.1.1, acorn@^7.4.0:
   resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
   integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
 
-acorn@^8.2.4, acorn@^8.5.0, acorn@^8.7.1:
+acorn@^8.2.4, acorn@^8.5.0:
   version "8.8.0"
   resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8"
   integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==
@@ -3147,6 +3292,11 @@ acorn@^8.4.1:
   resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.1.tgz#0a3f9cbecc4ec3bea6f0a80b66ae8dd2da250b73"
   integrity sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==
 
+acorn@^8.7.1, acorn@^8.8.2:
+  version "8.11.2"
+  resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.2.tgz#ca0d78b51895be5390a5903c5b3bdcdaf78ae40b"
+  integrity sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==
+
 address@1.1.2:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6"
@@ -3283,11 +3433,6 @@ ansi-regex@^5.0.0, ansi-regex@^5.0.1:
   resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
   integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
 
-ansi-styles@^2.2.1:
-  version "2.2.1"
-  resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
-  integrity sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==
-
 ansi-styles@^3.2.0, ansi-styles@^3.2.1:
   version "3.2.1"
   resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
@@ -3320,7 +3465,7 @@ anymatch@^2.0.0:
     micromatch "^3.1.4"
     normalize-path "^2.1.1"
 
-anymatch@^3.0.0, anymatch@^3.0.3, anymatch@~3.1.1, anymatch@~3.1.2:
+anymatch@^3.0.0, anymatch@^3.0.3, anymatch@~3.1.2:
   version "3.1.2"
   resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716"
   integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==
@@ -3328,6 +3473,14 @@ anymatch@^3.0.0, anymatch@^3.0.3, anymatch@~3.1.1, anymatch@~3.1.2:
     normalize-path "^3.0.0"
     picomatch "^2.0.4"
 
+anymatch@~3.1.1:
+  version "3.1.3"
+  resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e"
+  integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==
+  dependencies:
+    normalize-path "^3.0.0"
+    picomatch "^2.0.4"
+
 append-buffer@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/append-buffer/-/append-buffer-1.0.2.tgz#d8220cf466081525efea50614f3de6514dfa58f1"
@@ -3687,6 +3840,18 @@ axobject-query@^2.2.0:
   resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be"
   integrity sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==
 
+babel-eslint@^10.1.0:
+  version "10.1.0"
+  resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232"
+  integrity sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==
+  dependencies:
+    "@babel/code-frame" "^7.0.0"
+    "@babel/parser" "^7.7.0"
+    "@babel/traverse" "^7.7.0"
+    "@babel/types" "^7.7.0"
+    eslint-visitor-keys "^1.0.0"
+    resolve "^1.12.0"
+
 babel-extract-comments@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/babel-extract-comments/-/babel-extract-comments-1.0.0.tgz#0a2aedf81417ed391b85e18b4614e693a0351a21"
@@ -4095,23 +4260,22 @@ browser-stdout@1.3.1:
   resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60"
   integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==
 
-browser-sync-client@^2.27.10:
-  version "2.27.10"
-  resolved "https://registry.yarnpkg.com/browser-sync-client/-/browser-sync-client-2.27.10.tgz#f06233ea66bd873b96664f001cbc49035022634d"
-  integrity sha512-KCFKA1YDj6cNul0VsA28apohtBsdk5Wv8T82ClOZPZMZWxPj4Ny5AUbrj9UlAb/k6pdxE5HABrWDhP9+cjt4HQ==
+browser-sync-client@^2.29.3:
+  version "2.29.3"
+  resolved "https://registry.yarnpkg.com/browser-sync-client/-/browser-sync-client-2.29.3.tgz#9300b97f42abc2c4f95ca29b5a9781b5c492f14a"
+  integrity sha512-4tK5JKCl7v/3aLbmCBMzpufiYLsB1+UI+7tUXCCp5qF0AllHy/jAqYu6k7hUF3hYtlClKpxExWaR+rH+ny07wQ==
   dependencies:
     etag "1.8.1"
     fresh "0.5.2"
     mitt "^1.1.3"
-    rxjs "^5.5.6"
-    typescript "^4.6.2"
 
-browser-sync-ui@^2.27.10:
-  version "2.27.10"
-  resolved "https://registry.yarnpkg.com/browser-sync-ui/-/browser-sync-ui-2.27.10.tgz#59dd6e436e17b743c99094ff5129306ab7ab5b79"
-  integrity sha512-elbJILq4Uo6OQv6gsvS3Y9vRAJlWu+h8j0JDkF0X/ua+3S6SVbbiWnZc8sNOFlG7yvVGIwBED3eaYQ0iBo1Dtw==
+browser-sync-ui@^2.29.3:
+  version "2.29.3"
+  resolved "https://registry.yarnpkg.com/browser-sync-ui/-/browser-sync-ui-2.29.3.tgz#35e2ce3b470dce6b7219307cac7278bf324a0f16"
+  integrity sha512-kBYOIQjU/D/3kYtUIJtj82e797Egk1FB2broqItkr3i4eF1qiHbFCG6srksu9gWhfmuM/TNG76jMfzAdxEPakg==
   dependencies:
     async-each-series "0.1.1"
+    chalk "4.1.2"
     connect-history-api-fallback "^1"
     immutable "^3"
     server-destroy "1.0.1"
@@ -4119,20 +4283,20 @@ browser-sync-ui@^2.27.10:
     stream-throttle "^0.1.3"
 
 browser-sync@^2.27.9:
-  version "2.27.10"
-  resolved "https://registry.yarnpkg.com/browser-sync/-/browser-sync-2.27.10.tgz#3568d4f66afb0f68fee4a10902ecbbe8b2f680dd"
-  integrity sha512-xKm+6KJmJu6RuMWWbFkKwOCSqQOxYe3nOrFkKI5Tr/ZzjPxyU3pFShKK3tWnazBo/3lYQzN7fzjixG8fwJh1Xw==
+  version "2.29.3"
+  resolved "https://registry.yarnpkg.com/browser-sync/-/browser-sync-2.29.3.tgz#c2a3ff00c659eb87a13cae9d7a427e1b4b580ee1"
+  integrity sha512-NiM38O6XU84+MN+gzspVmXV2fTOoe+jBqIBx3IBdhZrdeURr6ZgznJr/p+hQ+KzkKEiGH/GcC4SQFSL0jV49bg==
   dependencies:
-    browser-sync-client "^2.27.10"
-    browser-sync-ui "^2.27.10"
+    browser-sync-client "^2.29.3"
+    browser-sync-ui "^2.29.3"
     bs-recipes "1.3.4"
-    bs-snippet-injector "^2.0.1"
+    chalk "4.1.2"
     chokidar "^3.5.1"
     connect "3.6.6"
     connect-history-api-fallback "^1"
     dev-ip "^1.0.1"
     easy-extender "^2.3.4"
-    eazy-logger "3.1.0"
+    eazy-logger "^4.0.1"
     etag "^1.8.1"
     fresh "^0.5.2"
     fs-extra "3.0.1"
@@ -4142,7 +4306,6 @@ browser-sync@^2.27.9:
     micromatch "^4.0.2"
     opn "5.3.0"
     portscanner "2.2.0"
-    qs "6.2.3"
     raw-body "^2.3.2"
     resp-modifier "6.0.2"
     rx "4.1.0"
@@ -4151,7 +4314,7 @@ browser-sync@^2.27.9:
     serve-static "1.13.2"
     server-destroy "1.0.1"
     socket.io "^4.4.1"
-    ua-parser-js "1.0.2"
+    ua-parser-js "^1.0.33"
     yargs "^17.3.1"
 
 browserify-aes@^1.0.0, browserify-aes@^1.0.4:
@@ -4225,7 +4388,7 @@ browserslist@4.14.2:
     escalade "^3.0.2"
     node-releases "^1.1.61"
 
-browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4.20.2, browserslist@^4.21.3, browserslist@^4.6.2, browserslist@^4.6.4:
+browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.20.2, browserslist@^4.21.3, browserslist@^4.6.2, browserslist@^4.6.4:
   version "4.21.3"
   resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.3.tgz#5df277694eb3c48bc5c4b05af3e8b7e09c5a6d1a"
   integrity sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==
@@ -4235,16 +4398,21 @@ browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4
     node-releases "^2.0.6"
     update-browserslist-db "^1.0.5"
 
+browserslist@^4.14.5:
+  version "4.22.2"
+  resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.2.tgz#704c4943072bd81ea18997f3bd2180e89c77874b"
+  integrity sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==
+  dependencies:
+    caniuse-lite "^1.0.30001565"
+    electron-to-chromium "^1.4.601"
+    node-releases "^2.0.14"
+    update-browserslist-db "^1.0.13"
+
 bs-recipes@1.3.4:
   version "1.3.4"
   resolved "https://registry.yarnpkg.com/bs-recipes/-/bs-recipes-1.3.4.tgz#0d2d4d48a718c8c044769fdc4f89592dc8b69585"
   integrity sha512-BXvDkqhDNxXEjeGM8LFkSbR+jzmP/CYpCiVKYn+soB1dDldeU15EBNDkwVXndKuX35wnNUaPd0qSoQEAkmQtMw==
 
-bs-snippet-injector@^2.0.1:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/bs-snippet-injector/-/bs-snippet-injector-2.0.1.tgz#61b5393f11f52559ed120693100343b6edb04dd5"
-  integrity sha512-4u8IgB+L9L+S5hknOj3ddNSb42436gsnGm1AuM15B7CdbkpQTyVWgIM5/JUBiKiRwGOR86uo0Lu/OsX+SAlJmw==
-
 bser@2.1.1:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05"
@@ -4253,9 +4421,9 @@ bser@2.1.1:
     node-int64 "^0.4.0"
 
 buffer-equal@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.0.tgz#59616b498304d556abd466966b22eeda3eca5fbe"
-  integrity sha512-tcBWO2Dl4e7Asr9hTGcpVrCe+F7DubpmqWCTbj4FHLmjqO2hIaC383acQubWtRJhdceqs5uBHs6Es+Sk//RKiQ==
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.1.tgz#2f7651be5b1b3f057fcd6e7ee16cf34767077d90"
+  integrity sha512-QoV3ptgEaQpvVwbXdSO39iqPQTCxSF7A5U99AxbHYqUdCizL/lH2Z0A2y6nbZucxMEOtNyZfG2s6gsVugGpKkg==
 
 buffer-from@^1.0.0:
   version "1.1.2"
@@ -4402,6 +4570,15 @@ call-bind@^1.0.0, call-bind@^1.0.2:
     function-bind "^1.1.1"
     get-intrinsic "^1.0.2"
 
+call-bind@^1.0.5:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.5.tgz#6fa2b7845ce0ea49bf4d8b9ef64727a2c2e2e513"
+  integrity sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==
+  dependencies:
+    function-bind "^1.1.2"
+    get-intrinsic "^1.2.1"
+    set-function-length "^1.1.1"
+
 caller-callsite@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134"
@@ -4464,6 +4641,11 @@ caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109, can
   resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001481.tgz"
   integrity sha512-KCqHwRnaa1InZBtqXzP98LPg0ajCVujMKjqKDhZEthIpAsJl/YEIa3YvXjGXPVqzZVguccuu7ga9KOE1J9rKPQ==
 
+caniuse-lite@^1.0.30001565:
+  version "1.0.30001566"
+  resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001566.tgz#61a8e17caf3752e3e426d4239c549ebbb37fef0d"
+  integrity sha512-ggIhCsTxmITBAMmK8yZjEhCO5/47jKXPu6Dha/wuCS4JePVL+3uiDEBuhu2aIoT+bqTOR8L76Ip1ARL9xYsEJA==
+
 capture-exit@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4"
@@ -4490,17 +4672,17 @@ chai-almost@^1.0.1:
     type-detect "^4.0.3"
 
 chai@^4.3.4:
-  version "4.3.6"
-  resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.6.tgz#ffe4ba2d9fa9d6680cc0b370adae709ec9011e9c"
-  integrity sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==
+  version "4.3.10"
+  resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.10.tgz#d784cec635e3b7e2ffb66446a63b4e33bd390384"
+  integrity sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==
   dependencies:
     assertion-error "^1.1.0"
-    check-error "^1.0.2"
-    deep-eql "^3.0.1"
-    get-func-name "^2.0.0"
-    loupe "^2.3.1"
+    check-error "^1.0.3"
+    deep-eql "^4.1.3"
+    get-func-name "^2.0.2"
+    loupe "^2.3.6"
     pathval "^1.1.1"
-    type-detect "^4.0.5"
+    type-detect "^4.0.8"
 
 chalk@2.4.1:
   version "2.4.1"
@@ -4528,16 +4710,13 @@ chalk@4.1.1:
     ansi-styles "^4.1.0"
     supports-color "^7.1.0"
 
-chalk@^1.1.3:
-  version "1.1.3"
-  resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
-  integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==
+chalk@4.1.2, chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1:
+  version "4.1.2"
+  resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
+  integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
   dependencies:
-    ansi-styles "^2.2.1"
-    escape-string-regexp "^1.0.2"
-    has-ansi "^2.0.0"
-    strip-ansi "^3.0.0"
-    supports-color "^2.0.0"
+    ansi-styles "^4.1.0"
+    supports-color "^7.1.0"
 
 chalk@^3.0.0:
   version "3.0.0"
@@ -4547,14 +4726,6 @@ chalk@^3.0.0:
     ansi-styles "^4.1.0"
     supports-color "^7.1.0"
 
-chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1:
-  version "4.1.2"
-  resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
-  integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
-  dependencies:
-    ansi-styles "^4.1.0"
-    supports-color "^7.1.0"
-
 change-emitter@^0.1.2:
   version "0.1.6"
   resolved "https://registry.yarnpkg.com/change-emitter/-/change-emitter-0.1.6.tgz#e8b2fe3d7f1ab7d69a32199aff91ea6931409515"
@@ -4580,10 +4751,12 @@ charm@~0.1.0:
   resolved "https://registry.yarnpkg.com/charm/-/charm-0.1.2.tgz#06c21eed1a1b06aeb67553cdc53e23274bac2296"
   integrity sha512-syedaZ9cPe7r3hoQA9twWYKu5AIyCswN5+szkmPBe9ccdLrj4bYaCnLVPTLd2kgVRc7+zoX4tyPgRnFKCj5YjQ==
 
-check-error@^1.0.2:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82"
-  integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==
+check-error@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.3.tgz#a6502e4312a7ee969f646e83bb3ddd56281bd694"
+  integrity sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==
+  dependencies:
+    get-func-name "^2.0.2"
 
 check-types@^11.1.1:
   version "11.1.2"
@@ -4789,6 +4962,15 @@ cliui@^7.0.2:
     strip-ansi "^6.0.0"
     wrap-ansi "^7.0.0"
 
+cliui@^8.0.1:
+  version "8.0.1"
+  resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa"
+  integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==
+  dependencies:
+    string-width "^4.2.0"
+    strip-ansi "^6.0.1"
+    wrap-ansi "^7.0.0"
+
 clone-buffer@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58"
@@ -4951,7 +5133,7 @@ complex.js@^2.0.11:
   resolved "https://registry.yarnpkg.com/complex.js/-/complex.js-2.1.1.tgz#0675dac8e464ec431fb2ab7d30f41d889fb25c31"
   integrity sha512-8njCHOTtFFLtegk6zQo0kkVX1rngygb/KQI6z1qZxlFI3scluC+LVTCFbrkWjBv4vvLlbQ9t88IPMC6k95VTTg==
 
-component-emitter@^1.2.1, component-emitter@~1.3.0:
+component-emitter@^1.2.1:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"
   integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==
@@ -5085,13 +5267,18 @@ convert-source-map@^0.3.3:
   resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-0.3.5.tgz#f1d802950af7dd2631a1febe0596550c86ab3190"
   integrity sha512-+4nRk0k3oEpwUB7/CalD7xE2z4VmtEnnq0GO2IPTkrooTrAhEsWvuLF5iWP1dXrwluki/azwXV1ve7gtYuPldg==
 
-convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0:
+convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0:
   version "1.8.0"
   resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369"
   integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==
   dependencies:
     safe-buffer "~5.1.1"
 
+convert-source-map@^1.5.0:
+  version "1.9.0"
+  resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f"
+  integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==
+
 cookie-signature@1.0.6:
   version "1.0.6"
   resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
@@ -5909,7 +6096,14 @@ data-urls@^2.0.0:
     whatwg-mimetype "^2.3.0"
     whatwg-url "^8.0.0"
 
-date-fns@^2.0.1, date-fns@^2.22.1:
+date-fns@^2.0.1:
+  version "2.30.0"
+  resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.30.0.tgz#f367e644839ff57894ec6ac480de40cae4b0f4d0"
+  integrity sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==
+  dependencies:
+    "@babel/runtime" "^7.21.0"
+
+date-fns@^2.22.1:
   version "2.29.2"
   resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.29.2.tgz#0d4b3d0f3dff0f920820a070920f0d9662c51931"
   integrity sha512-0VNbwmWJDS/G3ySwFSJA3ayhbURMTJLtwM2DTxf9CWondCnh6DTNlO9JgRSq6ibf4eD0lfMJNBxUdEAHHix+bA==
@@ -5988,10 +6182,10 @@ deep-eql@^2.0.2:
   dependencies:
     type-detect "^3.0.0"
 
-deep-eql@^3.0.1:
-  version "3.0.1"
-  resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df"
-  integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==
+deep-eql@^4.1.3:
+  version "4.1.3"
+  resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d"
+  integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==
   dependencies:
     type-detect "^4.0.0"
 
@@ -6049,6 +6243,15 @@ defaults@^1.0.3:
   dependencies:
     clone "^1.0.2"
 
+define-data-property@^1.0.1, define-data-property@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.1.tgz#c35f7cd0ab09883480d12ac5cb213715587800b3"
+  integrity sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==
+  dependencies:
+    get-intrinsic "^1.2.1"
+    gopd "^1.0.1"
+    has-property-descriptors "^1.0.0"
+
 define-properties@^1.1.2, define-properties@^1.1.3, define-properties@^1.1.4:
   version "1.1.4"
   resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1"
@@ -6057,6 +6260,15 @@ define-properties@^1.1.2, define-properties@^1.1.3, define-properties@^1.1.4:
     has-property-descriptors "^1.0.0"
     object-keys "^1.1.1"
 
+define-properties@^1.2.1:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c"
+  integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==
+  dependencies:
+    define-data-property "^1.0.1"
+    has-property-descriptors "^1.0.0"
+    object-keys "^1.1.1"
+
 define-property@^0.2.5:
   version "0.2.5"
   resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116"
@@ -6207,11 +6419,6 @@ dir-glob@^3.0.1:
   dependencies:
     path-type "^4.0.0"
 
-dlv@^1.1.3:
-  version "1.1.3"
-  resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79"
-  integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==
-
 dns-equal@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d"
@@ -6419,12 +6626,12 @@ easy-extender@^2.3.4:
   dependencies:
     lodash "^4.17.10"
 
-eazy-logger@3.1.0:
-  version "3.1.0"
-  resolved "https://registry.yarnpkg.com/eazy-logger/-/eazy-logger-3.1.0.tgz#b169eb56df714608fa114f164c8a2956bec9f0f3"
-  integrity sha512-/snsn2JqBtUSSstEl4R0RKjkisGHAhvYj89i7r3ytNUKW12y178KDZwXLXIgwDqLW6E/VRMT9qfld7wvFae8bQ==
+eazy-logger@^4.0.1:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/eazy-logger/-/eazy-logger-4.0.1.tgz#2e9fe487fb14ed6ac20d5f01d90dff377d403041"
+  integrity sha512-2GSFtnnC6U4IEKhEI7+PvdxrmjJ04mdsj3wHZTFiw0tUtG4HCWzTr13ZYTk8XOGnA1xQMaDljoBOYlk3D/MMSw==
   dependencies:
-    tfunk "^4.0.0"
+    chalk "4.1.2"
 
 ee-first@1.1.1:
   version "1.1.1"
@@ -6441,6 +6648,11 @@ electron-to-chromium@^1.3.564, electron-to-chromium@^1.4.202:
   resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.228.tgz#3baff13cf54198c2045f9bdd8b64db93aafd7f33"
   integrity sha512-XfDHCvou7CsDMlFwb0WZ1tWmW48e7Sn7VBRyPfZsZZila9esRsJl1trO+OqDNV97GggFSt0ISbWslKXfQkG//g==
 
+electron-to-chromium@^1.4.601:
+  version "1.4.603"
+  resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.603.tgz#446907c21d333b55d0beaba1cb5b48430775a8a7"
+  integrity sha512-Dvo5OGjnl7AZTU632dFJtWj0uJK835eeOVQIuRcmBmsFsTNn3cL05FqOyHAfGQDIoHfLhyJ1Tya3PJ0ceMz54g==
+
 elliptic@^6.5.3:
   version "6.5.4"
   resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb"
@@ -6510,26 +6722,26 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0:
   dependencies:
     once "^1.4.0"
 
-engine.io-client@~6.2.1:
-  version "6.2.2"
-  resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-6.2.2.tgz#c6c5243167f5943dcd9c4abee1bfc634aa2cbdd0"
-  integrity sha512-8ZQmx0LQGRTYkHuogVZuGSpDqYZtCM/nv8zQ68VZ+JkOpazJ7ICdsSpaO6iXwvaU30oFg5QJOJWj8zWqhbKjkQ==
+engine.io-client@~6.5.2:
+  version "6.5.3"
+  resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-6.5.3.tgz#4cf6fa24845029b238f83c628916d9149c399bc5"
+  integrity sha512-9Z0qLB0NIisTRt1DZ/8U2k12RJn8yls/nXMZLn+/N8hANT3TcYjKFKcwbw5zFQiN4NTde3TSY9zb79e1ij6j9Q==
   dependencies:
     "@socket.io/component-emitter" "~3.1.0"
     debug "~4.3.1"
-    engine.io-parser "~5.0.3"
-    ws "~8.2.3"
+    engine.io-parser "~5.2.1"
+    ws "~8.11.0"
     xmlhttprequest-ssl "~2.0.0"
 
-engine.io-parser@~5.0.3:
-  version "5.0.4"
-  resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.0.4.tgz#0b13f704fa9271b3ec4f33112410d8f3f41d0fc0"
-  integrity sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg==
+engine.io-parser@~5.2.1:
+  version "5.2.1"
+  resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.2.1.tgz#9f213c77512ff1a6cc0c7a86108a7ffceb16fcfb"
+  integrity sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==
 
-engine.io@~6.2.0:
-  version "6.2.0"
-  resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-6.2.0.tgz#003bec48f6815926f2b1b17873e576acd54f41d0"
-  integrity sha512-4KzwW3F3bk+KlzSOY57fj/Jx6LyRQ1nbcyIadehl+AnXjKT7gDO0ORdRi/84ixvMKTym6ZKuxvbzN62HDDU1Lg==
+engine.io@~6.5.2:
+  version "6.5.4"
+  resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-6.5.4.tgz#6822debf324e781add2254e912f8568508850cdc"
+  integrity sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg==
   dependencies:
     "@types/cookie" "^0.4.1"
     "@types/cors" "^2.8.12"
@@ -6539,8 +6751,8 @@ engine.io@~6.2.0:
     cookie "~0.4.1"
     cors "~2.8.5"
     debug "~4.3.1"
-    engine.io-parser "~5.0.3"
-    ws "~8.2.3"
+    engine.io-parser "~5.2.1"
+    ws "~8.11.0"
 
 enhanced-resolve@^4.3.0:
   version "4.5.0"
@@ -6551,10 +6763,10 @@ enhanced-resolve@^4.3.0:
     memory-fs "^0.5.0"
     tapable "^1.0.0"
 
-enhanced-resolve@^5.10.0:
-  version "5.10.0"
-  resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz#0dc579c3bb2a1032e357ac45b8f3a6f3ad4fb1e6"
-  integrity sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==
+enhanced-resolve@^5.15.0:
+  version "5.15.0"
+  resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz#1af946c7d93603eb88e9896cee4904dc012e9c35"
+  integrity sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==
   dependencies:
     graceful-fs "^4.2.4"
     tapable "^2.2.0"
@@ -6631,10 +6843,10 @@ es-array-method-boxes-properly@^1.0.0:
   resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e"
   integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==
 
-es-module-lexer@^0.9.0:
-  version "0.9.3"
-  resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19"
-  integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==
+es-module-lexer@^1.2.1:
+  version "1.4.1"
+  resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.4.1.tgz#41ea21b43908fe6a287ffcbe4300f790555331f5"
+  integrity sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==
 
 es-shim-unscopables@^1.0.0:
   version "1.0.0"
@@ -6703,7 +6915,7 @@ escape-latex@^1.2.0:
   resolved "https://registry.yarnpkg.com/escape-latex/-/escape-latex-1.2.0.tgz#07c03818cf7dac250cce517f4fda1b001ef2bca1"
   integrity sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw==
 
-escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
+escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5:
   version "1.0.5"
   resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
   integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==
@@ -6918,7 +7130,7 @@ eslint-utils@^3.0.0:
   dependencies:
     eslint-visitor-keys "^2.0.0"
 
-eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0:
+eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e"
   integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==
@@ -7595,11 +7807,16 @@ focus-group@^0.3.1:
   resolved "https://registry.yarnpkg.com/focus-group/-/focus-group-0.3.1.tgz#e0f32ed86b0dabdd6ffcebdf898ecb32e47fedce"
   integrity sha512-IA01dzk2cStQso/qnt2rWhXCFBZlBfjZmohB9mXUx9feEaJcORAK0FQGvwaApsNNGwzEnqrp/2qTR4lq8PXfnQ==
 
-follow-redirects@^1.0.0, follow-redirects@^1.14.0:
+follow-redirects@^1.0.0:
   version "1.15.1"
   resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5"
   integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==
 
+follow-redirects@^1.14.0:
+  version "1.15.3"
+  resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.3.tgz#fe2f3ef2690afce7e82ed0b44db08165b207123a"
+  integrity sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==
+
 follow-redirects@^1.15.0:
   version "1.15.2"
   resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13"
@@ -7789,6 +8006,11 @@ function-bind@^1.1.1:
   resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
   integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
 
+function-bind@^1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
+  integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
+
 function.prototype.name@^1.1.5:
   version "1.1.5"
   resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621"
@@ -7824,10 +8046,10 @@ get-caller-file@^2.0.1, get-caller-file@^2.0.5:
   resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
   integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
 
-get-func-name@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41"
-  integrity sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==
+get-func-name@^2.0.1, get-func-name@^2.0.2:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41"
+  integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==
 
 get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1:
   version "1.1.2"
@@ -7838,6 +8060,16 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1:
     has "^1.0.3"
     has-symbols "^1.0.3"
 
+get-intrinsic@^1.1.3, get-intrinsic@^1.2.1:
+  version "1.2.2"
+  resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.2.tgz#281b7622971123e1ef4b3c90fd7539306da93f3b"
+  integrity sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==
+  dependencies:
+    function-bind "^1.1.2"
+    has-proto "^1.0.1"
+    has-symbols "^1.0.3"
+    hasown "^2.0.0"
+
 get-node-dimensions@^1.2.1:
   version "1.2.1"
   resolved "https://registry.yarnpkg.com/get-node-dimensions/-/get-node-dimensions-1.2.1.tgz#fb7b4bb57060fb4247dd51c9d690dfbec56b0823"
@@ -8043,7 +8275,19 @@ glogg@^1.0.0:
   dependencies:
     sparkles "^1.0.0"
 
-graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.9:
+gopd@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c"
+  integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==
+  dependencies:
+    get-intrinsic "^1.1.3"
+
+graceful-fs@^4.0.0:
+  version "4.2.11"
+  resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
+  integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
+
+graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.9:
   version "4.2.10"
   resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c"
   integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==
@@ -8139,13 +8383,6 @@ harmony-reflect@^1.4.6:
   resolved "https://registry.yarnpkg.com/harmony-reflect/-/harmony-reflect-1.6.2.tgz#31ecbd32e648a34d030d86adb67d4d47547fe710"
   integrity sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==
 
-has-ansi@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
-  integrity sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==
-  dependencies:
-    ansi-regex "^2.0.0"
-
 has-bigints@^1.0.1, has-bigints@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa"
@@ -8168,6 +8405,11 @@ has-property-descriptors@^1.0.0:
   dependencies:
     get-intrinsic "^1.1.1"
 
+has-proto@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0"
+  integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==
+
 has-symbols@^1.0.0, has-symbols@^1.0.1, has-symbols@^1.0.2, has-symbols@^1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8"
@@ -8235,10 +8477,17 @@ hash.js@^1.0.0, hash.js@^1.0.3:
     inherits "^2.0.3"
     minimalistic-assert "^1.0.1"
 
-hast-util-whitespace@^2.0.0:
+hasown@^2.0.0:
   version "2.0.0"
-  resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-2.0.0.tgz#4fc1086467cc1ef5ba20673cb6b03cec3a970f1c"
-  integrity sha512-Pkw+xBHuV6xFeJprJe2BBEoDV+AvQySaz3pPDRUs5PNZEMQjpXJJueqrpcHIXxnWTcAGi/UOCgVShlkY6kLoqg==
+  resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c"
+  integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==
+  dependencies:
+    function-bind "^1.1.2"
+
+hast-util-whitespace@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-2.0.1.tgz#0ec64e257e6fc216c7d14c8a1b74d27d650b4557"
+  integrity sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==
 
 he@1.2.0, he@^1.2.0:
   version "1.2.0"
@@ -8854,6 +9103,13 @@ is-core-module@^2.0.0, is-core-module@^2.10.0, is-core-module@^2.8.1, is-core-mo
   dependencies:
     has "^1.0.3"
 
+is-core-module@^2.13.0:
+  version "2.13.1"
+  resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384"
+  integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==
+  dependencies:
+    hasown "^2.0.0"
+
 is-data-descriptor@^0.1.4:
   version "0.1.4"
   resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56"
@@ -10389,12 +10645,12 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3
   dependencies:
     js-tokens "^3.0.0 || ^4.0.0"
 
-loupe@^2.3.1:
-  version "2.3.4"
-  resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.4.tgz#7e0b9bffc76f148f9be769cb1321d3dcf3cb25f3"
-  integrity sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==
+loupe@^2.3.6:
+  version "2.3.7"
+  resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.7.tgz#6e69b7d4db7d3ab436328013d37d1c8c3540c697"
+  integrity sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==
   dependencies:
-    get-func-name "^2.0.0"
+    get-func-name "^2.0.1"
 
 lower-case@^2.0.2:
   version "2.0.2"
@@ -10544,9 +10800,9 @@ md5.js@^1.3.4:
     safe-buffer "^5.1.2"
 
 mdast-util-definitions@^5.0.0:
-  version "5.1.1"
-  resolved "https://registry.yarnpkg.com/mdast-util-definitions/-/mdast-util-definitions-5.1.1.tgz#2c1d684b28e53f84938bb06317944bee8efa79db"
-  integrity sha512-rQ+Gv7mHttxHOBx2dkF4HWTg+EE+UR78ptQWDylzPKaQuVGdG4HIoY3SrS/pCp80nZ04greFvXbVFHT+uf0JVQ==
+  version "5.1.2"
+  resolved "https://registry.yarnpkg.com/mdast-util-definitions/-/mdast-util-definitions-5.1.2.tgz#9910abb60ac5d7115d6819b57ae0bcef07a3f7a7"
+  integrity sha512-8SVPMuHqlPME/z3gqVwWY4zVXn8lqKv/pAhC57FuJ40ImXyBpmO5ukh98zB2v7Blql2FiHjHv9LVztSIqjY+MA==
   dependencies:
     "@types/mdast" "^3.0.0"
     "@types/unist" "^2.0.0"
@@ -10648,18 +10904,15 @@ mdast-util-math@^2.0.0:
     mdast-util-to-markdown "^1.3.0"
 
 mdast-util-to-hast@^12.1.0:
-  version "12.2.0"
-  resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-12.2.0.tgz#4dbff7ab2b20b8d12fc8fe98bf804d97e7358cbf"
-  integrity sha512-YDwT5KhGzLgPpSnQhAlK1+WpCW4gsPmNNAxUNMkMTDhxQyPp2eX86WOelnKnLKEvSpfxqJbPbInHFkefXZBhEA==
+  version "12.3.0"
+  resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-12.3.0.tgz#045d2825fb04374e59970f5b3f279b5700f6fb49"
+  integrity sha512-pits93r8PhnIoU4Vy9bjW39M2jJ6/tdHyja9rrot9uujkN7UTU9SDnE6WNJz/IGyQk3XHX6yNNtrBH6cQzm8Hw==
   dependencies:
     "@types/hast" "^2.0.0"
     "@types/mdast" "^3.0.0"
-    "@types/mdurl" "^1.0.0"
     mdast-util-definitions "^5.0.0"
-    mdurl "^1.0.0"
-    micromark-util-sanitize-uri "^1.0.0"
+    micromark-util-sanitize-uri "^1.1.0"
     trim-lines "^3.0.0"
-    unist-builder "^3.0.0"
     unist-util-generated "^2.0.0"
     unist-util-position "^4.0.0"
     unist-util-visit "^4.0.0"
@@ -10692,11 +10945,6 @@ mdn-data@2.0.4:
   resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b"
   integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==
 
-mdurl@^1.0.0:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
-  integrity sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==
-
 media-typer@0.3.0:
   version "0.3.0"
   resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
@@ -11008,6 +11256,15 @@ micromark-util-sanitize-uri@^1.0.0:
     micromark-util-encode "^1.0.0"
     micromark-util-symbol "^1.0.0"
 
+micromark-util-sanitize-uri@^1.1.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.2.0.tgz#613f738e4400c6eedbc53590c67b197e30d7f90d"
+  integrity sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==
+  dependencies:
+    micromark-util-character "^1.0.0"
+    micromark-util-encode "^1.0.0"
+    micromark-util-symbol "^1.0.0"
+
 micromark-util-subtokenize@^1.0.0:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/micromark-util-subtokenize/-/micromark-util-subtokenize-1.0.2.tgz#ff6f1af6ac836f8bfdbf9b02f40431760ad89105"
@@ -11177,11 +11434,16 @@ minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2:
   dependencies:
     brace-expansion "^1.1.7"
 
-minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6:
+minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.6:
   version "1.2.6"
   resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
   integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==
 
+minimist@^1.2.5:
+  version "1.2.8"
+  resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
+  integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
+
 minipass-collect@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617"
@@ -11571,6 +11833,11 @@ node-releases@^1.1.61:
   resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.77.tgz#50b0cfede855dd374e7585bf228ff34e57c1c32e"
   integrity sha512-rB1DUFUNAN4Gn9keO2K1efO35IDK7yKHCdCaIMvFO7yUYmmZYeDjnGKle26G4rwj+LKRQpjyUUvMkPglwGCYNQ==
 
+node-releases@^2.0.14:
+  version "2.0.14"
+  resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b"
+  integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==
+
 node-releases@^2.0.6:
   version "2.0.6"
   resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503"
@@ -11727,7 +11994,17 @@ object.assign@4.1.0:
     has-symbols "^1.0.0"
     object-keys "^1.0.11"
 
-object.assign@^4.0.4, object.assign@^4.1.0, object.assign@^4.1.2, object.assign@^4.1.3:
+object.assign@^4.0.4:
+  version "4.1.5"
+  resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0"
+  integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==
+  dependencies:
+    call-bind "^1.0.5"
+    define-properties "^1.2.1"
+    has-symbols "^1.0.3"
+    object-keys "^1.1.1"
+
+object.assign@^4.1.0, object.assign@^4.1.2, object.assign@^4.1.3:
   version "4.1.4"
   resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f"
   integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==
@@ -13281,11 +13558,6 @@ qs@6.10.3:
   dependencies:
     side-channel "^1.0.4"
 
-qs@6.2.3:
-  version "6.2.3"
-  resolved "https://registry.yarnpkg.com/qs/-/qs-6.2.3.tgz#1cfcb25c10a9b2b483053ff39f5dfc9233908cfe"
-  integrity sha512-AY4g8t3LMboim0t6XWFdz6J5OuJ1ZNYu54SXihS/OMpgyCqYmcAJnWqkNSOjSjWmq3xxy+GF9uWQI2lI/7tKIA==
-
 qs@^6.10.2, qs@^6.10.5:
   version "6.11.0"
   resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a"
@@ -13367,7 +13639,7 @@ range-parser@^1.2.1, range-parser@~1.2.0, range-parser@~1.2.1:
   resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
   integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
 
-raw-body@2.5.1, raw-body@^2.3.2:
+raw-body@2.5.1:
   version "2.5.1"
   resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857"
   integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==
@@ -13377,6 +13649,16 @@ raw-body@2.5.1, raw-body@^2.3.2:
     iconv-lite "0.4.24"
     unpipe "1.0.0"
 
+raw-body@^2.3.2:
+  version "2.5.2"
+  resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a"
+  integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==
+  dependencies:
+    bytes "3.1.2"
+    http-errors "2.0.0"
+    iconv-lite "0.4.24"
+    unpipe "1.0.0"
+
 raw-loader@^4.0.2:
   version "4.0.2"
   resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-4.0.2.tgz#1aac6b7d1ad1501e66efdac1522c73e59a584eb6"
@@ -13673,9 +13955,9 @@ react-lifecycles-compat@^3.0.2, react-lifecycles-compat@^3.0.4:
   integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
 
 react-markdown@^8.0.3:
-  version "8.0.3"
-  resolved "https://registry.yarnpkg.com/react-markdown/-/react-markdown-8.0.3.tgz#e8aba0d2f5a1b2124d476ee1fff9448a2f57e4b3"
-  integrity sha512-We36SfqaKoVNpN1QqsZwWSv/OZt5J15LNgTLWynwAN5b265hrQrsjMtlRNwUvS+YyR3yDM8HpTNc4pK9H/Gc0A==
+  version "8.0.7"
+  resolved "https://registry.yarnpkg.com/react-markdown/-/react-markdown-8.0.7.tgz#c8dbd1b9ba5f1c5e7e5f2a44de465a3caafdf89b"
+  integrity sha512-bvWbzG4MtOU62XqBx3Xx+zB2raaFFsq4mYiAzfjXJMEz2sixgeAfraA3tvzULF02ZdOMUOKTBFFaZJDDrq+BJQ==
   dependencies:
     "@types/hast" "^2.0.0"
     "@types/prop-types" "^15.0.0"
@@ -13688,7 +13970,7 @@ react-markdown@^8.0.3:
     remark-parse "^10.0.0"
     remark-rehype "^10.0.0"
     space-separated-tokens "^2.0.0"
-    style-to-object "^0.3.0"
+    style-to-object "^0.4.0"
     unified "^10.0.0"
     unist-util-visit "^4.0.0"
     vfile "^5.0.0"
@@ -13826,6 +14108,7 @@ react-scripts@4.0.3:
     "@svgr/webpack" "5.5.0"
     "@typescript-eslint/eslint-plugin" "^4.5.0"
     "@typescript-eslint/parser" "^4.5.0"
+    babel-eslint "^10.1.0"
     babel-jest "^26.6.0"
     babel-loader "8.1.0"
     babel-plugin-named-asset-import "^0.3.7"
@@ -14041,7 +14324,7 @@ read-pkg@^5.2.0:
     parse-json "^5.0.0"
     type-fest "^0.6.0"
 
-"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6:
+"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6:
   version "2.3.7"
   resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
   integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
@@ -14054,7 +14337,29 @@ read-pkg@^5.2.0:
     string_decoder "~1.1.1"
     util-deprecate "~1.0.1"
 
-"readable-stream@2 || 3", readable-stream@^3.0.6, readable-stream@^3.4.0, readable-stream@^3.6.0:
+"readable-stream@2 || 3":
+  version "3.6.2"
+  resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967"
+  integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==
+  dependencies:
+    inherits "^2.0.3"
+    string_decoder "^1.1.1"
+    util-deprecate "^1.0.1"
+
+readable-stream@^2.0.5, readable-stream@^2.3.5:
+  version "2.3.8"
+  resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b"
+  integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==
+  dependencies:
+    core-util-is "~1.0.0"
+    inherits "~2.0.3"
+    isarray "~1.0.0"
+    process-nextick-args "~2.0.0"
+    safe-buffer "~5.1.1"
+    string_decoder "~1.1.1"
+    util-deprecate "~1.0.1"
+
+readable-stream@^3.0.6, readable-stream@^3.4.0, readable-stream@^3.6.0:
   version "3.6.0"
   resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
   integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
@@ -14175,6 +14480,11 @@ regenerator-runtime@^0.13.3, regenerator-runtime@^0.13.7:
   resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52"
   integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==
 
+regenerator-runtime@^0.14.0:
+  version "0.14.0"
+  resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz#5e19d68eb12d486f797e15a3c6a918f7cec5eb45"
+  integrity sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==
+
 regenerator-transform@^0.15.0:
   version "0.15.0"
   resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.0.tgz#cbd9ead5d77fae1a48d957cf889ad0586adb6537"
@@ -14481,7 +14791,16 @@ resolve@1.18.1:
     is-core-module "^2.0.0"
     path-parse "^1.0.6"
 
-resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.18.1, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.0, resolve@^1.22.1, resolve@^1.3.2, resolve@^1.4.0:
+resolve@^1.1.6, resolve@^1.1.7, resolve@^1.12.0, resolve@^1.4.0:
+  version "1.22.8"
+  resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d"
+  integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==
+  dependencies:
+    is-core-module "^2.13.0"
+    path-parse "^1.0.7"
+    supports-preserve-symlinks-flag "^1.0.0"
+
+resolve@^1.10.0, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.18.1, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.0, resolve@^1.22.1, resolve@^1.3.2:
   version "1.22.1"
   resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177"
   integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==
@@ -14701,13 +15020,6 @@ rx@4.1.0:
   resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782"
   integrity sha512-CiaiuN6gapkdl+cZUr67W6I8jquN4lkak3vtIsIWCl4XIPP8ffsoyN6/+PuGXnQy8Cu8W2y9Xxh31Rq4M6wUug==
 
-rxjs@^5.5.6:
-  version "5.5.12"
-  resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.12.tgz#6fa61b8a77c3d793dbaf270bee2f43f652d741cc"
-  integrity sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw==
-  dependencies:
-    symbol-observable "1.0.1"
-
 rxjs@^6.5.2:
   version "6.6.7"
   resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9"
@@ -14820,7 +15132,7 @@ schema-utils@^2.6.5, schema-utils@^2.7.0, schema-utils@^2.7.1:
     ajv "^6.12.4"
     ajv-keywords "^3.5.2"
 
-schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1:
+schema-utils@^3.0.0, schema-utils@^3.1.1:
   version "3.1.1"
   resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281"
   integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==
@@ -14829,6 +15141,15 @@ schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1:
     ajv "^6.12.5"
     ajv-keywords "^3.5.2"
 
+schema-utils@^3.2.0:
+  version "3.3.0"
+  resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe"
+  integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==
+  dependencies:
+    "@types/json-schema" "^7.0.8"
+    ajv "^6.12.5"
+    ajv-keywords "^3.5.2"
+
 script-loader@^0.7.2:
   version "0.7.2"
   resolved "https://registry.yarnpkg.com/script-loader/-/script-loader-0.7.2.tgz#2016db6f86f25f5cf56da38915d83378bb166ba7"
@@ -14865,7 +15186,7 @@ semver-greatest-satisfied-range@^1.1.0:
   dependencies:
     sver-compat "^1.5.0"
 
-"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.6.0, semver@^5.7.0:
+"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.6.0:
   version "5.7.1"
   resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
   integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
@@ -14880,6 +15201,11 @@ semver@7.3.2:
   resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938"
   integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==
 
+semver@^5.7.0:
+  version "5.7.2"
+  resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8"
+  integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
+
 semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0:
   version "6.3.0"
   resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
@@ -14949,10 +15275,10 @@ serialize-javascript@^5.0.1:
   dependencies:
     randombytes "^2.1.0"
 
-serialize-javascript@^6.0.0:
-  version "6.0.0"
-  resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8"
-  integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==
+serialize-javascript@^6.0.1:
+  version "6.0.1"
+  resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.1.tgz#b206efb27c3da0b0ab6b52f48d170b7996458e5c"
+  integrity sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==
   dependencies:
     randombytes "^2.1.0"
 
@@ -15040,6 +15366,16 @@ set-cookie-parser@^2.4.6:
   resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.5.1.tgz#ddd3e9a566b0e8e0862aca974a6ac0e01349430b"
   integrity sha512-1jeBGaKNGdEq4FgIrORu/N570dwoPYio8lSoYLWmX7sQ//0JY08Xh9o5pBcgmHQ/MbsYp/aZnOe1s1lIsbLprQ==
 
+set-function-length@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.1.1.tgz#4bc39fafb0307224a33e106a7d35ca1218d659ed"
+  integrity sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==
+  dependencies:
+    define-data-property "^1.1.1"
+    get-intrinsic "^1.2.1"
+    gopd "^1.0.1"
+    has-property-descriptors "^1.0.0"
+
 set-value@^2.0.0, set-value@^2.0.1:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b"
@@ -15195,49 +15531,43 @@ snapdragon@^0.8.1:
     source-map-resolve "^0.5.0"
     use "^3.1.0"
 
-socket.io-adapter@~2.4.0:
-  version "2.4.0"
-  resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.4.0.tgz#b50a4a9ecdd00c34d4c8c808224daa1a786152a6"
-  integrity sha512-W4N+o69rkMEGVuk2D/cvca3uYsvGlMwsySWV447y99gUPghxq42BxqLNMndb+a1mm/5/7NeXVQS7RLa2XyXvYg==
+socket.io-adapter@~2.5.2:
+  version "2.5.2"
+  resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz#5de9477c9182fdc171cd8c8364b9a8894ec75d12"
+  integrity sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==
+  dependencies:
+    ws "~8.11.0"
 
 socket.io-client@^4.4.1:
-  version "4.5.1"
-  resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-4.5.1.tgz#cab8da71976a300d3090414e28c2203a47884d84"
-  integrity sha512-e6nLVgiRYatS+AHXnOnGi4ocOpubvOUCGhyWw8v+/FxW8saHkinG6Dfhi9TU0Kt/8mwJIAASxvw6eujQmjdZVA==
+  version "4.7.2"
+  resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-4.7.2.tgz#f2f13f68058bd4e40f94f2a1541f275157ff2c08"
+  integrity sha512-vtA0uD4ibrYD793SOIAwlo8cj6haOeMHrGvwPxJsxH7CeIksqJ+3Zc06RvWTIFgiSqx4A3sOnTXpfAEE2Zyz6w==
   dependencies:
     "@socket.io/component-emitter" "~3.1.0"
     debug "~4.3.2"
-    engine.io-client "~6.2.1"
-    socket.io-parser "~4.2.0"
+    engine.io-client "~6.5.2"
+    socket.io-parser "~4.2.4"
 
-socket.io-parser@~4.0.4:
-  version "4.0.5"
-  resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.0.5.tgz#cb404382c32324cc962f27f3a44058cf6e0552df"
-  integrity sha512-sNjbT9dX63nqUFIOv95tTVm6elyIU4RvB1m8dOeZt+IgWwcWklFDOdmGcfo3zSiRsnR/3pJkjY5lfoGqEe4Eig==
-  dependencies:
-    "@types/component-emitter" "^1.2.10"
-    component-emitter "~1.3.0"
-    debug "~4.3.1"
-
-socket.io-parser@~4.2.0:
-  version "4.2.1"
-  resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.1.tgz#01c96efa11ded938dcb21cbe590c26af5eff65e5"
-  integrity sha512-V4GrkLy+HeF1F/en3SpUaM+7XxYXpuMUWLGde1kSSh5nQMN4hLrbPIkD+otwh6q9R6NOQBN4AMaOZ2zVjui82g==
+socket.io-parser@~4.2.4:
+  version "4.2.4"
+  resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.4.tgz#c806966cf7270601e47469ddeec30fbdfda44c83"
+  integrity sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==
   dependencies:
     "@socket.io/component-emitter" "~3.1.0"
     debug "~4.3.1"
 
 socket.io@^4.4.1:
-  version "4.5.1"
-  resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.5.1.tgz#aa7e73f8a6ce20ee3c54b2446d321bbb6b1a9029"
-  integrity sha512-0y9pnIso5a9i+lJmsCdtmTTgJFFSvNQKDnPQRz28mGNnxbmqYg2QPtJTLFxhymFZhAIn50eHAKzJeiNaKr+yUQ==
+  version "4.7.2"
+  resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.7.2.tgz#22557d76c3f3ca48f82e73d68b7add36a22df002"
+  integrity sha512-bvKVS29/I5fl2FGLNHuXlQaUH/BlzX1IN6S+NKLNZpBsPZIDH+90eQmCs2Railn4YUiww4SzUedJ6+uzwFnKLw==
   dependencies:
     accepts "~1.3.4"
     base64id "~2.0.0"
+    cors "~2.8.5"
     debug "~4.3.2"
-    engine.io "~6.2.0"
-    socket.io-adapter "~2.4.0"
-    socket.io-parser "~4.0.4"
+    engine.io "~6.5.2"
+    socket.io-adapter "~2.5.2"
+    socket.io-parser "~4.2.4"
 
 sockjs-client@^1.5.0:
   version "1.6.1"
@@ -15720,10 +16050,10 @@ style-loader@1.3.0:
     loader-utils "^2.0.0"
     schema-utils "^2.7.0"
 
-style-to-object@^0.3.0:
-  version "0.3.0"
-  resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-0.3.0.tgz#b1b790d205991cc783801967214979ee19a76e46"
-  integrity sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA==
+style-to-object@^0.4.0:
+  version "0.4.4"
+  resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-0.4.4.tgz#266e3dfd56391a7eefb7770423612d043c3f33ec"
+  integrity sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg==
   dependencies:
     inline-style-parser "0.1.1"
 
@@ -15743,11 +16073,6 @@ supports-color@6.0.0:
   dependencies:
     has-flag "^3.0.0"
 
-supports-color@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
-  integrity sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==
-
 supports-color@^5.3.0:
   version "5.5.0"
   resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
@@ -15840,11 +16165,6 @@ swagger-client@^3.8.22:
     traverse "~0.6.6"
     url "~0.11.0"
 
-symbol-observable@1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4"
-  integrity sha512-Kb3PrPYz4HanVF1LVGuAdW6LoVgIwjUYJGzFe7NDrBLCN4lsV/5J0MFurV+ygS4bRVwrCEt2c7MQ1R2a72oJDw==
-
 symbol-observable@^1.0.4:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
@@ -15945,16 +16265,16 @@ terser-webpack-plugin@^1.4.3:
     webpack-sources "^1.4.0"
     worker-farm "^1.7.0"
 
-terser-webpack-plugin@^5.1.3:
-  version "5.3.5"
-  resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.5.tgz#f7d82286031f915a4f8fb81af4bd35d2e3c011bc"
-  integrity sha512-AOEDLDxD2zylUGf/wxHxklEkOe2/r+seuyOWujejFrIxHf11brA1/dWQNIgXa1c6/Wkxgu7zvv0JhOWfc2ELEA==
+terser-webpack-plugin@^5.3.7:
+  version "5.3.9"
+  resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz#832536999c51b46d468067f9e37662a3b96adfe1"
+  integrity sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==
   dependencies:
-    "@jridgewell/trace-mapping" "^0.3.14"
+    "@jridgewell/trace-mapping" "^0.3.17"
     jest-worker "^27.4.5"
     schema-utils "^3.1.1"
-    serialize-javascript "^6.0.0"
-    terser "^5.14.1"
+    serialize-javascript "^6.0.1"
+    terser "^5.16.8"
 
 terser@^4.1.2, terser@^4.6.2, terser@^4.6.3:
   version "4.8.1"
@@ -15965,7 +16285,17 @@ terser@^4.1.2, terser@^4.6.2, terser@^4.6.3:
     source-map "~0.6.1"
     source-map-support "~0.5.12"
 
-terser@^5.14.1, terser@^5.3.4:
+terser@^5.16.8:
+  version "5.25.0"
+  resolved "https://registry.yarnpkg.com/terser/-/terser-5.25.0.tgz#6579b4cca45b08bf0fdaa1a04605fd5860dfb2ac"
+  integrity sha512-we0I9SIsfvNUMP77zC9HG+MylwYYsGFSBG8qm+13oud2Yh+O104y614FRbyjpxys16jZwot72Fpi827YvGzuqg==
+  dependencies:
+    "@jridgewell/source-map" "^0.3.3"
+    acorn "^8.8.2"
+    commander "^2.20.0"
+    source-map-support "~0.5.20"
+
+terser@^5.3.4:
   version "5.15.0"
   resolved "https://registry.yarnpkg.com/terser/-/terser-5.15.0.tgz#e16967894eeba6e1091509ec83f0c60e179f2425"
   integrity sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA==
@@ -15989,14 +16319,6 @@ text-table@0.2.0, text-table@^0.2.0:
   resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
   integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==
 
-tfunk@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/tfunk/-/tfunk-4.0.0.tgz#de9399feaf2060901d590b7faad80fcd5443077e"
-  integrity sha512-eJQ0dGfDIzWNiFNYFVjJ+Ezl/GmwHaFTBTjrtqNPW0S7cuVDBrZrmzUz6VkMeCR4DZFqhd4YtLwsw3i2wYHswQ==
-  dependencies:
-    chalk "^1.1.3"
-    dlv "^1.1.3"
-
 three.meshline@1.4.0:
   version "1.4.0"
   resolved "https://registry.yarnpkg.com/three.meshline/-/three.meshline-1.4.0.tgz#2a483cbd99cd5f74cf6ee5c253a9a4b4a8169178"
@@ -16303,7 +16625,7 @@ type-check@~0.3.2:
   dependencies:
     prelude-ls "~1.1.2"
 
-type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.3, type-detect@^4.0.5:
+type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.3, type-detect@^4.0.8:
   version "4.0.8"
   resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
   integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
@@ -16383,21 +16705,16 @@ typescript@^3.9.10:
   resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.10.tgz#70f3910ac7a51ed6bef79da7800690b19bf778b8"
   integrity sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==
 
-typescript@^4.6.2:
-  version "4.7.4"
-  resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.4.tgz#1a88596d1cf47d59507a1bcdfb5b9dfe4d488235"
-  integrity sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==
-
-ua-parser-js@1.0.2:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-1.0.2.tgz#e2976c34dbfb30b15d2c300b2a53eac87c57a775"
-  integrity sha512-00y/AXhx0/SsnI51fTc0rLRmafiGOM4/O+ny10Ps7f+j/b8p/ZY11ytMgznXkOVo4GQ+KwQG5UQLkLGirsACRg==
-
 ua-parser-js@^0.7.30:
   version "0.7.31"
   resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.31.tgz#649a656b191dffab4f21d5e053e27ca17cbff5c6"
   integrity sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==
 
+ua-parser-js@^1.0.33:
+  version "1.0.37"
+  resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-1.0.37.tgz#b5dc7b163a5c1f0c510b08446aed4da92c46373f"
+  integrity sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ==
+
 unbox-primitive@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e"
@@ -16434,6 +16751,11 @@ undertaker@^1.2.1:
     object.reduce "^1.0.0"
     undertaker-registry "^1.0.0"
 
+undici-types@~5.26.4:
+  version "5.26.5"
+  resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
+  integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
+
 unicode-canonical-property-names-ecmascript@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc"
@@ -16524,17 +16846,10 @@ unique-string@^1.0.0:
   dependencies:
     crypto-random-string "^1.0.0"
 
-unist-builder@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/unist-builder/-/unist-builder-3.0.0.tgz#728baca4767c0e784e1e64bb44b5a5a753021a04"
-  integrity sha512-GFxmfEAa0vi9i5sd0R2kcrI9ks0r82NasRq5QHh2ysGngrc6GiqD5CDf1FjPenY4vApmFASBIIlk/jj5J5YbmQ==
-  dependencies:
-    "@types/unist" "^2.0.0"
-
 unist-util-generated@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-2.0.0.tgz#86fafb77eb6ce9bfa6b663c3f5ad4f8e56a60113"
-  integrity sha512-TiWE6DVtVe7Ye2QxOVW9kqybs6cZexNwTwSMVgkfjEReqy/xwGpAXb99OxktoWwmL+Z+Epb0Dn8/GNDYP1wnUw==
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-2.0.1.tgz#e37c50af35d3ed185ac6ceacb6ca0afb28a85cae"
+  integrity sha512-qF72kLmPxAw0oN2fwpWIqbXAVyEqUzDHMsbtPvOudIlUzXYFIeQIuxXQCRCFh22B7cixvU0MG7m3MW8FTq/S+A==
 
 unist-util-is@^5.0.0:
   version "5.1.1"
@@ -16542,9 +16857,9 @@ unist-util-is@^5.0.0:
   integrity sha512-F5CZ68eYzuSvJjGhCLPL3cYx45IxkqXSetCcRgUXtbcm50X2L9oOWQlfUfDdAf+6Pd27YDblBfdtmsThXmwpbQ==
 
 unist-util-position@^4.0.0:
-  version "4.0.3"
-  resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-4.0.3.tgz#5290547b014f6222dff95c48d5c3c13a88fadd07"
-  integrity sha512-p/5EMGIa1qwbXjA+QgcBXaPWjSnZfQ2Sc3yBEEfgPwsEmJd8Qh+DSk3LGnmOM4S1bY2C0AjmMnB8RuEYxpPwXQ==
+  version "4.0.4"
+  resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-4.0.4.tgz#93f6d8c7d6b373d9b825844645877c127455f037"
+  integrity sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg==
   dependencies:
     "@types/unist" "^2.0.0"
 
@@ -16623,6 +16938,14 @@ upath@^1.1.1, upath@^1.1.2, upath@^1.2.0:
   resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894"
   integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==
 
+update-browserslist-db@^1.0.13:
+  version "1.0.13"
+  resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4"
+  integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==
+  dependencies:
+    escalade "^3.1.1"
+    picocolors "^1.0.0"
+
 update-browserslist-db@^1.0.5:
   version "1.0.5"
   resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz#be06a5eedd62f107b7c19eb5bcefb194411abf38"
@@ -17138,21 +17461,21 @@ webpack@4.44.2:
     webpack-sources "^1.4.1"
 
 webpack@^5.72.0:
-  version "5.74.0"
-  resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.74.0.tgz#02a5dac19a17e0bb47093f2be67c695102a55980"
-  integrity sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA==
+  version "5.89.0"
+  resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.89.0.tgz#56b8bf9a34356e93a6625770006490bf3a7f32dc"
+  integrity sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==
   dependencies:
     "@types/eslint-scope" "^3.7.3"
-    "@types/estree" "^0.0.51"
-    "@webassemblyjs/ast" "1.11.1"
-    "@webassemblyjs/wasm-edit" "1.11.1"
-    "@webassemblyjs/wasm-parser" "1.11.1"
+    "@types/estree" "^1.0.0"
+    "@webassemblyjs/ast" "^1.11.5"
+    "@webassemblyjs/wasm-edit" "^1.11.5"
+    "@webassemblyjs/wasm-parser" "^1.11.5"
     acorn "^8.7.1"
-    acorn-import-assertions "^1.7.6"
+    acorn-import-assertions "^1.9.0"
     browserslist "^4.14.5"
     chrome-trace-event "^1.0.2"
-    enhanced-resolve "^5.10.0"
-    es-module-lexer "^0.9.0"
+    enhanced-resolve "^5.15.0"
+    es-module-lexer "^1.2.1"
     eslint-scope "5.1.1"
     events "^3.2.0"
     glob-to-regexp "^0.4.1"
@@ -17161,9 +17484,9 @@ webpack@^5.72.0:
     loader-runner "^4.2.0"
     mime-types "^2.1.27"
     neo-async "^2.6.2"
-    schema-utils "^3.1.0"
+    schema-utils "^3.2.0"
     tapable "^2.1.1"
-    terser-webpack-plugin "^5.1.3"
+    terser-webpack-plugin "^5.3.7"
     watchpack "^2.4.0"
     webpack-sources "^3.2.3"
 
@@ -17578,10 +17901,10 @@ ws@^7.4.6:
   resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591"
   integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==
 
-ws@~8.2.3:
-  version "8.2.3"
-  resolved "https://registry.yarnpkg.com/ws/-/ws-8.2.3.tgz#63a56456db1b04367d0b721a0b80cae6d8becbba"
-  integrity sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==
+ws@~8.11.0:
+  version "8.11.0"
+  resolved "https://registry.yarnpkg.com/ws/-/ws-8.11.0.tgz#6a0d36b8edfd9f96d8b25683db2f8d7de6e8e143"
+  integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==
 
 xml-name-validator@^3.0.0:
   version "3.0.0"
@@ -17659,7 +17982,7 @@ yargs-parser@^20.2.2, yargs-parser@^20.2.9:
   resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
   integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==
 
-yargs-parser@^21.0.0:
+yargs-parser@^21.0.0, yargs-parser@^21.1.1:
   version "21.1.1"
   resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35"
   integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==
@@ -17740,7 +18063,7 @@ yargs@^16.2.0:
     y18n "^5.0.5"
     yargs-parser "^20.2.2"
 
-yargs@^17.3.0, yargs@^17.3.1:
+yargs@^17.3.0:
   version "17.5.1"
   resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.5.1.tgz#e109900cab6fcb7fd44b1d8249166feb0b36e58e"
   integrity sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==
@@ -17753,6 +18076,19 @@ yargs@^17.3.0, yargs@^17.3.1:
     y18n "^5.0.5"
     yargs-parser "^21.0.0"
 
+yargs@^17.3.1:
+  version "17.7.2"
+  resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269"
+  integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==
+  dependencies:
+    cliui "^8.0.1"
+    escalade "^3.1.1"
+    get-caller-file "^2.0.5"
+    require-directory "^2.1.1"
+    string-width "^4.2.3"
+    y18n "^5.0.5"
+    yargs-parser "^21.1.1"
+
 yargs@^7.1.0:
   version "7.1.2"
   resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.2.tgz#63a0a5d42143879fdbb30370741374e0641d55db"
diff --git a/nomad/app/v1/models/models.py b/nomad/app/v1/models/models.py
index 9a2bca29b8d27b9382ff69189936367445b1159b..8ea1774e85f2ed427c361e0d823bdf9b897bd266 100644
--- a/nomad/app/v1/models/models.py
+++ b/nomad/app/v1/models/models.py
@@ -897,8 +897,13 @@ class MetadataBasedPagination(Pagination):
         None,
         description=strip(
             """
-            The results are ordered by the values of this field. If omitted, default
-            ordering is applied.
+            The results are ordered by the values of this field. You can order
+            by any indexed scalar value, or one following two special fields:
+
+             - `_score`: Sorts by relevance score.
+             - `_doc`: Use when sorting does not matter, gives the best performance.
+
+            If omitted, default ordering is applied.
         """
         ),
     )
diff --git a/nomad/config/models.py b/nomad/config/models.py
index 107e1e4875c9cb41d326325e54246611fd1ebc24..d18fd71e2798c776d848601c7eaff2b9b7b7ea4d 100644
--- a/nomad/config/models.py
+++ b/nomad/config/models.py
@@ -1262,6 +1262,28 @@ class Filters(OptionsGlob):
     )
 
 
+class SearchSyntaxes(StrictSettings):
+    """Controls the availability of different search syntaxes. These syntaxes
+    determine how raw user input in e.g. the search bar is parsed into queries
+    supported by the API.
+
+    Currently you can only exclude items. By default, the following options are
+    included:
+
+     - `existence`: Used to query for the existence of a specific metainfo field in the data.
+     - `equality`: Used to query for a specific value with exact match.
+     - `range_bounded`: Queries values that are between two numerical limits, inclusive or exclusive.
+     - `range_half_bounded`: Queries values that are above/below a numerical limit, inclusive or exclusive.
+     - `free_text`: For inexact, queries. Requires that a set of keywords has been filled in the entry.
+    """
+
+    exclude: Optional[List[str]] = Field(
+        description="""
+        List of excluded options.
+    """
+    )
+
+
 class Layout(StrictSettings):
     """Defines widget size and grid positioning for different breakpoints."""
 
@@ -1432,6 +1454,9 @@ class App(StrictSettings):
         user by default.
         """
     )
+    search_syntaxes: Optional[SearchSyntaxes] = Field(
+        description='Controls which types of search syntax are available.'
+    )
 
 
 class Apps(Options):
@@ -1768,6 +1793,7 @@ class UI(StrictSettings):
                                 },
                             }
                         },
+                        'search_syntaxes': {'exclude': ['free_text']},
                     },
                     'calculations': {
                         'label': 'Calculations',
@@ -2132,11 +2158,12 @@ class UI(StrictSettings):
                                         },
                                     },
                                 },
-                            ]
+                            ],
                         },
                         'filters_locked': {
                             'quantities': 'results.method.simulation.program_name',
                         },
+                        'search_syntaxes': {'exclude': ['free_text']},
                     },
                     'materials': {
                         'label': 'Materials',
@@ -2260,6 +2287,7 @@ class UI(StrictSettings):
                             }
                         },
                         'filters': {'exclude': ['mainfile', 'entry_name']},
+                        'search_syntaxes': {'exclude': ['free_text']},
                     },
                     'eln': {
                         'label': 'ELN',
@@ -2414,6 +2442,7 @@ class UI(StrictSettings):
                             }
                         },
                         'filters_locked': {'results.method.method_name': 'EELS'},
+                        'search_syntaxes': {'exclude': ['free_text']},
                     },
                     'solarcells': {
                         'label': 'Solar Cells',
@@ -2994,6 +3023,7 @@ class UI(StrictSettings):
                         'filters_locked': {
                             'sections': 'nomad.datamodel.results.SolarCell'
                         },
+                        'search_syntaxes': {'exclude': ['free_text']},
                     },
                     'heterogeneouscatalyst': {
                         'label': 'Heterogeneous Catalysis',
@@ -3866,6 +3896,7 @@ class UI(StrictSettings):
                         'filters_locked': {
                             'quantities': 'results.properties.catalytic'
                         },
+                        'search_syntaxes': {'exclude': ['free_text']},
                     },
                     'mofs': {
                         'label': 'Metal-Organic Frameworks',
@@ -4228,6 +4259,7 @@ class UI(StrictSettings):
                             }
                         },
                         'filters_locked': {'results.material.topology.label': 'MOF'},
+                        'search_syntaxes': {'exclude': ['free_text']},
                     },
                 },
             }
diff --git a/nomad/datamodel/datamodel.py b/nomad/datamodel/datamodel.py
index 7cd690bf5f00a2851612399484d768218bfd6e9c..d113c12d7a6732a2a3374bf1a357b76154ddbd14 100644
--- a/nomad/datamodel/datamodel.py
+++ b/nomad/datamodel/datamodel.py
@@ -26,8 +26,9 @@ import rfc3161ng
 from elasticsearch_dsl import analyzer, tokenizer
 
 from nomad import utils
-from nomad.metainfo.mongoengine_extension import Mongo, MongoDocument
 from nomad.datamodel.metainfo.common import FastAccess
+from nomad.metainfo.mongoengine_extension import Mongo, MongoDocument
+from nomad.metainfo.util import MTypes
 from nomad.metainfo.pydantic_extension import PydanticModel
 from nomad.metainfo.elasticsearch_extension import (
     Elasticsearch,
@@ -561,6 +562,14 @@ class EntryMetadata(MSection):
         a_elasticsearch=PathSearch(),
     )
 
+    text_search_contents = Quantity(
+        type=str,
+        shape=['*'],
+        description="""Contains text contents that should be considered when
+        doing free text queries for entries.""",
+        a_elasticsearch=[Elasticsearch(mapping='text', es_query='match_bool_prefix')],
+    )
+
     files = Quantity(
         type=str,
         shape=['0..*'],
@@ -865,6 +874,7 @@ class EntryMetadata(MSection):
         section_paths = {}
         entry_references = []
         search_quantities = []
+        keywords_set = set()
 
         def get_section_path(section):
             section_path = section_paths.get(section)
@@ -1000,6 +1010,19 @@ class EntryMetadata(MSection):
             if section_path.startswith(('data', 'nexus')) and isinstance(
                 property_def, Quantity
             ):
+                # From each string dtype, we get a truncated sample to put into
+                # the keywords field, unless we are already storing too many unique values.
+                print(property_def.type)
+                if (
+                    property_def.type in MTypes.str
+                    or isinstance(property_def.type, MEnum)
+                ) and len(keywords_set) < 10000:
+                    keyword = section.m_get(property_def)
+                    if keyword:
+                        if not property_def.shape:
+                            keyword = [keyword]
+                        for val in keyword:
+                            keywords_set.add(str(val)[0:500].strip())
                 searchable_quantity = create_searchable_quantity(
                     property_def,
                     quantity_path,
@@ -1036,6 +1059,7 @@ class EntryMetadata(MSection):
         self.sections = [section.qualified_name() for section in sections]
         self.sections.sort()
         self.n_quantities = n_quantities
+        self.text_search_contents = list(keywords_set)
 
         def generate_compatible(_s, used_directly: bool):
             return CompatibleSectionDef(
diff --git a/nomad/search.py b/nomad/search.py
index 9e03d2a2101f5fe3f49f069d52d77bbf500e200f..c7187e33e8b28670d57686d0aae4c8a0e07c2e01 100644
--- a/nomad/search.py
+++ b/nomad/search.py
@@ -106,6 +106,7 @@ from nomad.metainfo.elasticsearch_extension import (
     entry_type,
     material_entry_type,
     entry_index,
+    Elasticsearch,
     Index,
     DocumentType,
     SearchQuantity,
@@ -1044,16 +1045,25 @@ def validate_pagination(
 ):
     order_quantity = None
     if pagination.order_by is not None:
-        order_quantity = validate_quantity(
-            pagination.order_by,
-            doc_type=doc_type,
-            loc=(loc if loc else []) + ['pagination', 'order_by'],
-        )
-        if not order_quantity.definition.is_scalar:
-            raise QueryValidationError(
-                'the order_by quantity must be a scalar',
+        # When sorting by _score, or by _doc is requested, we create a dummy
+        # order_quantity
+        if pagination.order_by == '_score' or pagination.order_by == '_doc':
+            dummy_annotation = Elasticsearch(
+                definition=Quantity(type=float), doc_type=doc_type
+            )
+            order_quantity = SearchQuantity(dummy_annotation)
+            order_quantity.search_field = pagination.order_by
+        else:
+            order_quantity = validate_quantity(
+                pagination.order_by,
+                doc_type=doc_type,
                 loc=(loc if loc else []) + ['pagination', 'order_by'],
             )
+            if not order_quantity.definition.is_scalar:
+                raise QueryValidationError(
+                    'the order_by quantity must be a scalar',
+                    loc=(loc if loc else []) + ['pagination', 'order_by'],
+                )
 
     page_after_value = pagination.page_after_value
     if (
diff --git a/tests/datamodel/test_metadata.py b/tests/datamodel/test_metadata.py
index b150a4342586608b3577cff95a7882336b8fbec1..4f1f60d981f9a4e783ee14511b804351c2706eb0 100644
--- a/tests/datamodel/test_metadata.py
+++ b/tests/datamodel/test_metadata.py
@@ -256,3 +256,42 @@ def test_search_quantities_plugin(
         == f'data.{source_quantity}{schema_separator}{python_schema_name}'
     )
     assert searchable_quantity.definition == definition
+
+
+def test_text_search_contents():
+    """Test that text search contents are correctly extracted from the data-section."""
+
+    class MySubSection(MSection):
+        str_scalar = Quantity(type=str)
+        str_array = Quantity(type=str, shape=['*'])
+        enum_scalar = Quantity(type=MEnum('enum1', 'enum2'))
+        enum_array = Quantity(type=MEnum('enum1', 'enum2'), shape=['*'])
+
+    class MySchema(EntryData, MySubSection):
+        children = SubSection(section=MySubSection, repeats=True)
+
+    archive = EntryArchive(metadata=EntryMetadata(entry_name='test'))
+    archive.data = MySchema(str_scalar='scalar1', str_array=['array1', ' array2'])
+    archive.data.children.append(
+        MySubSection(str_scalar=' scalar2', str_array=['  array1  ', 'array3'])
+    )
+    archive.data.children.append(
+        MySubSection(enum_scalar='enum1', enum_array=['enum1', 'enum2'])
+    )
+    archive.data.children.append(MySubSection(str_scalar='scalar3 '))
+    archive.data.children.append(MySubSection(str_scalar='scalar1'))
+    archive.data.children.append(MySubSection(str_scalar='  scalar1  '))
+
+    archive.metadata.apply_archive_metadata(archive)
+    assert len(archive.metadata.text_search_contents) == 8
+    for value in [
+        'scalar1',
+        'scalar2',
+        'scalar3',
+        'array1',
+        'array2',
+        'array3',
+        'enum1',
+        'enum2',
+    ]:
+        assert value in archive.metadata.text_search_contents
diff --git a/tests/test_search.py b/tests/test_search.py
index 6eda9f87a42e44247643f8564401b6ffff1d411a..327c0bdd2b80b625059367099df710e0f7bf07bd 100644
--- a/tests/test_search.py
+++ b/tests/test_search.py
@@ -170,6 +170,23 @@ def example_data(elastic_function, test_user):
     data.save(with_files=False, with_mongo=False)
 
 
+@pytest.fixture()
+def example_text_search_data(mongo_module, elastic_function, test_user):
+    data = ExampleData(main_author=test_user)
+    data.create_upload(upload_id='test_upload_text_search', published=True)
+    data.create_entry(
+        upload_id='test_upload_text_search',
+        entry_id=f'test_entry_text_search',
+        mainfile='test_content/test_embargo_entry/mainfile.json',
+        text_search_contents=['this is a test keyword'],
+    )
+    data.save(with_files=False, with_mongo=False)
+
+    yield
+
+    data.delete()
+
+
 @pytest.fixture()
 def example_eln_data(elastic_function, test_user):
     class DataSection(EntryData):
@@ -592,3 +609,25 @@ def test_pagination_dynamic(
         path = order_by.split(schema_separator)[0]
         for i, data in enumerate(results.data):
             assert deep_get(data, *split(path)) == expected[i]
+
+
+@pytest.mark.parametrize(
+    'query, expected',
+    [
+        pytest.param(
+            '{"text_search_contents": "this is a test keyword"}', 1, id='exact match'
+        ),
+        pytest.param('{"text_search_contents": "keyword"}', 1, id='single word match'),
+        pytest.param('{"text_search_contents": "KEYWORD"}', 1, id='case insensitive'),
+        pytest.param(
+            '{"text_search_contents": "keyw"}', 1, id='also match for partial word'
+        ),
+        pytest.param('{"text_search_contents": "nope"}', 0, id='no match'),
+    ],
+)
+def test_text_search(example_text_search_data, query, expected):
+    """Tests that free-text queries correctly use the correct ES query type to
+    return reasonable matches.
+    """
+    results = search(owner='all', query=WithQuery(query=json.loads(query)).query)
+    assert len(results.data) == expected