Files
standardnotes-app/packages/web/src/javascripts/Components/ItemSelectionDropdown/ItemSelectionDropdown.tsx
T
Antonella Sgarlatta 3aa26fa3ea chore: localization (#3031) [skip ci]
* chore: add extract scripts and fix dependencies

* chore: localization batch 2

* chore: localization batch 3

* chore: localization batch 4

* chore: localization batch 5

* chore: fix strings allocated to incorrect batches

* chore: localization batch 6

* chore: localization batch 7

* chore: add ttag packages

* chore: localization batch 8

* chore: missed strings from all batches

* chore: rename batches 7 and 8

* chore: fix issue in batch 3 string

* chore: rename batch 2

* chore: fix strings allocated to incorrect batches

* chore: fix linting issues

* chore: merge batches 4 and 5

* chore: split batch 3

* chore: reassign help panel strings

* chore: add missing strings

* chore: fix keyboard shortcuts regression and passcode bug

* chore: fix yarn lock file

* chore: fix ts errors

* chore: fix ts errors

* chore: fix lint issue

* chore: fix lint issues
2026-07-28 22:49:21 -03:00

92 lines
3.0 KiB
TypeScript

import { doesItemMatchSearchQuery } from '@/Utils/Items/Search/doesItemMatchSearchQuery'
import { c } from 'ttag'
import {
Combobox,
ComboboxItem,
ComboboxPopover,
ComboboxStoreProps,
useComboboxStore,
VisuallyHidden,
} from '@ariakit/react'
import { classNames, DecryptedItem, naturalSort } from '@standardnotes/snjs'
import { observer } from 'mobx-react-lite'
import { useDeferredValue, useEffect, useState } from 'react'
import { useApplication } from '../ApplicationProvider'
import LinkedItemMeta from '../LinkedItems/LinkedItemMeta'
type Props = {
contentTypes: string[]
placeholder: string
onSelection: (item: DecryptedItem) => void
className?: {
input?: string
popover?: string
}
comboboxProps?: ComboboxStoreProps
}
const ItemSelectionDropdown = ({ contentTypes, placeholder, onSelection, comboboxProps, className = {} }: Props) => {
const application = useApplication()
const combobox = useComboboxStore(comboboxProps)
const value = combobox.useState('value')
const open = combobox.useState('open')
useEffect(() => {
if (value.length < 1 && open) {
combobox.setOpen(false)
}
}, [combobox, open, value.length])
const searchQuery = useDeferredValue(value)
const [items, setItems] = useState<DecryptedItem[]>([])
useEffect(() => {
const searchableItems = naturalSort(application.items.getItems(contentTypes), 'title')
const filteredItems = searchableItems.filter((item) => {
return doesItemMatchSearchQuery(item, searchQuery, application)
})
setItems(filteredItems)
}, [searchQuery, application, contentTypes])
return (
<div>
<VisuallyHidden>{c('B2.NavSharedUI.AriaLabel').t`Select an item`}</VisuallyHidden>
<Combobox
store={combobox}
placeholder={placeholder}
className={classNames(
'h-7 w-70 bg-transparent text-sm text-text focus:border-b-2 focus:border-info focus:shadow-none focus:outline-none lg:text-xs',
className.input,
)}
/>
<ComboboxPopover
store={combobox}
className={classNames(
'z-dropdown-menu max-h-[var(--popover-available-height)] w-[var(--popover-anchor-width)] overflow-y-auto rounded bg-default py-2 shadow-main',
className.popover,
)}
>
{items.length > 0 ? (
items.map((item) => (
<ComboboxItem
key={item.uuid}
className="flex w-full cursor-pointer items-center justify-between gap-4 overflow-hidden px-3 py-2 hover:bg-contrast hover:text-foreground [&[data-active-item]]:bg-info-backdrop"
hideOnClick
onClick={() => {
combobox.setValue('')
onSelection(item)
}}
>
<LinkedItemMeta item={item} searchQuery={searchQuery} />
</ComboboxItem>
))
) : (
<div className="px-2">{c('B2.NavSharedUI.Info').t`No results found`}</div>
)}
</ComboboxPopover>
</div>
)
}
export default observer(ItemSelectionDropdown)