@dxos/plugin-search 0.8.4-main.e8ec1fe → 0.8.4-main.effb148878
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +102 -5
- package/README.md +0 -1
- package/dist/lib/neutral/SearchArticle-CQMZ46ZS.mjs +51 -0
- package/dist/lib/neutral/SearchArticle-CQMZ46ZS.mjs.map +7 -0
- package/dist/lib/neutral/SearchDialog-IFMA5UP5.mjs +76 -0
- package/dist/lib/neutral/SearchDialog-IFMA5UP5.mjs.map +7 -0
- package/dist/lib/neutral/SearchPlugin.mjs +10 -0
- package/dist/lib/neutral/SearchPlugin.mjs.map +7 -0
- package/dist/lib/neutral/app-graph-builder-B3W3UWHV.mjs +71 -0
- package/dist/lib/neutral/app-graph-builder-B3W3UWHV.mjs.map +7 -0
- package/dist/lib/neutral/capabilities/index.mjs +13 -0
- package/dist/lib/neutral/capabilities/index.mjs.map +7 -0
- package/dist/lib/neutral/chunk-7ASS5WTT.mjs +8 -0
- package/dist/lib/neutral/chunk-7ASS5WTT.mjs.map +7 -0
- package/dist/lib/neutral/chunk-7VNJDD75.mjs +22 -0
- package/dist/lib/neutral/chunk-7VNJDD75.mjs.map +7 -0
- package/dist/lib/neutral/chunk-FIZRI3JV.mjs +27 -0
- package/dist/lib/neutral/chunk-FIZRI3JV.mjs.map +7 -0
- package/dist/lib/neutral/chunk-J5LGTIGS.mjs +10 -0
- package/dist/lib/neutral/chunk-J5LGTIGS.mjs.map +7 -0
- package/dist/lib/neutral/chunk-NAKPT2JM.mjs +8 -0
- package/dist/lib/neutral/chunk-NAKPT2JM.mjs.map +7 -0
- package/dist/lib/{browser/chunk-ZEP4O5SU.mjs → neutral/chunk-NBE5GQ5J.mjs} +66 -75
- package/dist/lib/neutral/chunk-NBE5GQ5J.mjs.map +7 -0
- package/dist/lib/neutral/chunk-QWFRJRPV.mjs +38 -0
- package/dist/lib/neutral/chunk-QWFRJRPV.mjs.map +7 -0
- package/dist/lib/neutral/components/index.mjs +97 -0
- package/dist/lib/neutral/components/index.mjs.map +7 -0
- package/dist/lib/neutral/containers/index.mjs +11 -0
- package/dist/lib/neutral/containers/index.mjs.map +7 -0
- package/dist/lib/neutral/hooks/index.mjs +30 -0
- package/dist/lib/neutral/hooks/index.mjs.map +7 -0
- package/dist/lib/neutral/index.mjs +40 -0
- package/dist/lib/neutral/index.mjs.map +7 -0
- package/dist/lib/neutral/meta.json +1 -0
- package/dist/lib/neutral/meta.mjs +10 -0
- package/dist/lib/neutral/meta.mjs.map +7 -0
- package/dist/lib/neutral/open-search-ABE2Y6ZG.mjs +23 -0
- package/dist/lib/neutral/open-search-ABE2Y6ZG.mjs.map +7 -0
- package/dist/lib/neutral/operation-handler-DY624P2R.mjs +13 -0
- package/dist/lib/neutral/operation-handler-DY624P2R.mjs.map +7 -0
- package/dist/lib/neutral/operations/index.mjs +8 -0
- package/dist/lib/neutral/operations/index.mjs.map +7 -0
- package/dist/lib/neutral/plugin.mjs +16 -0
- package/dist/lib/neutral/plugin.mjs.map +7 -0
- package/dist/lib/neutral/react-surface-ER7Q4W6Y.mjs +61 -0
- package/dist/lib/neutral/react-surface-ER7Q4W6Y.mjs.map +7 -0
- package/dist/lib/neutral/testing.mjs +8 -0
- package/dist/lib/neutral/testing.mjs.map +7 -0
- package/dist/lib/neutral/translations.mjs +25 -0
- package/dist/lib/neutral/translations.mjs.map +7 -0
- package/dist/lib/neutral/types/index.mjs +8 -0
- package/dist/lib/neutral/types/index.mjs.map +7 -0
- package/dist/types/src/SearchPlugin.d.ts +3 -1
- package/dist/types/src/SearchPlugin.d.ts.map +1 -1
- package/dist/types/src/capabilities/app-graph-builder.d.ts +4 -2
- package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
- package/dist/types/src/capabilities/index.d.ts +5 -3
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/operation-handler.d.ts +6 -0
- package/dist/types/src/capabilities/operation-handler.d.ts.map +1 -0
- package/dist/types/src/capabilities/react-surface.d.ts +3 -2
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
- package/dist/types/src/components/SearchResultStack/SearchResultStack.d.ts +9 -0
- package/dist/types/src/components/SearchResultStack/SearchResultStack.d.ts.map +1 -0
- package/dist/types/src/components/SearchResultStack/index.d.ts +2 -0
- package/dist/types/src/components/SearchResultStack/index.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +1 -3
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/constants.d.ts +2 -0
- package/dist/types/src/constants.d.ts.map +1 -0
- package/dist/types/src/containers/SearchArticle/SearchArticle.d.ts +4 -0
- package/dist/types/src/containers/SearchArticle/SearchArticle.d.ts.map +1 -0
- package/dist/types/src/{components/Searchbar/Searchbar.stories.d.ts → containers/SearchArticle/SearchArticle.stories.d.ts} +3 -2
- package/dist/types/src/containers/SearchArticle/SearchArticle.stories.d.ts.map +1 -0
- package/dist/types/src/containers/SearchArticle/index.d.ts +2 -0
- package/dist/types/src/containers/SearchArticle/index.d.ts.map +1 -0
- package/dist/types/src/containers/SearchDialog/SearchDialog.d.ts +7 -0
- package/dist/types/src/containers/SearchDialog/SearchDialog.d.ts.map +1 -0
- package/dist/types/src/{components/SearchResults/SearchResults.stories.d.ts → containers/SearchDialog/SearchDialog.stories.d.ts} +4 -4
- package/dist/types/src/containers/SearchDialog/SearchDialog.stories.d.ts.map +1 -0
- package/dist/types/src/containers/SearchDialog/index.d.ts +2 -0
- package/dist/types/src/containers/SearchDialog/index.d.ts.map +1 -0
- package/dist/types/src/containers/index.d.ts +4 -0
- package/dist/types/src/containers/index.d.ts.map +1 -0
- package/dist/types/src/hooks/sync.d.ts +4 -3
- package/dist/types/src/hooks/sync.d.ts.map +1 -1
- package/dist/types/src/hooks/useGlobalSearch.d.ts +8 -4
- package/dist/types/src/hooks/useGlobalSearch.d.ts.map +1 -1
- package/dist/types/src/hooks/useSearchResults.d.ts +3 -2
- package/dist/types/src/hooks/useSearchResults.d.ts.map +1 -1
- package/dist/types/src/hooks/useWebSearch.d.ts +7 -4
- package/dist/types/src/hooks/useWebSearch.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +0 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/meta.d.ts +2 -2
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/operations/index.d.ts +3 -0
- package/dist/types/src/operations/index.d.ts.map +1 -0
- package/dist/types/src/operations/open-search.d.ts +5 -0
- package/dist/types/src/operations/open-search.d.ts.map +1 -0
- package/dist/types/src/plugin.d.ts +4 -0
- package/dist/types/src/plugin.d.ts.map +1 -0
- package/dist/types/src/search/exa.d.ts +5 -4
- package/dist/types/src/search/exa.d.ts.map +1 -1
- package/dist/types/src/testing.d.ts +2 -0
- package/dist/types/src/testing.d.ts.map +1 -0
- package/dist/types/src/translations.d.ts +15 -10
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/SearchOperation.d.ts +3 -0
- package/dist/types/src/types/SearchOperation.d.ts.map +1 -0
- package/dist/types/src/types/index.d.ts +1 -1
- package/dist/types/src/types/index.d.ts.map +1 -1
- package/dist/types/src/types/search.d.ts +1 -20
- package/dist/types/src/types/search.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +119 -48
- package/src/SearchPlugin.tsx +14 -47
- package/src/capabilities/app-graph-builder.ts +55 -69
- package/src/capabilities/index.ts +8 -4
- package/src/capabilities/operation-handler.ts +16 -0
- package/src/capabilities/react-surface.tsx +65 -49
- package/src/components/SearchResultStack/SearchResultStack.tsx +118 -0
- package/src/components/SearchResultStack/index.ts +5 -0
- package/src/components/index.ts +1 -3
- package/src/constants.ts +7 -0
- package/src/containers/SearchArticle/SearchArticle.stories.tsx +79 -0
- package/src/containers/SearchArticle/SearchArticle.tsx +60 -0
- package/src/containers/SearchArticle/index.ts +5 -0
- package/src/containers/SearchDialog/SearchDialog.stories.tsx +108 -0
- package/src/containers/SearchDialog/SearchDialog.tsx +93 -0
- package/src/containers/SearchDialog/index.ts +5 -0
- package/src/containers/index.ts +8 -0
- package/src/hooks/sync.test.ts +9 -7
- package/src/hooks/sync.ts +31 -33
- package/src/hooks/useGlobalSearch.tsx +32 -13
- package/src/hooks/useSearchResults.ts +6 -3
- package/src/hooks/useWebSearch.ts +25 -14
- package/src/index.ts +2 -2
- package/src/meta.ts +22 -6
- package/src/operations/index.ts +7 -0
- package/src/operations/open-search.ts +24 -0
- package/src/plugin.ts +11 -0
- package/src/search/exa.test.ts +7 -7
- package/src/search/exa.ts +9 -8
- package/src/testing.ts +7 -0
- package/src/translations.ts +10 -9
- package/src/types/SearchOperation.ts +19 -0
- package/src/types/command-score.d.ts +16 -0
- package/src/types/index.ts +2 -1
- package/src/types/search.ts +1 -25
- package/dist/lib/browser/app-graph-builder-HQR6P4C7.mjs +0 -78
- package/dist/lib/browser/app-graph-builder-HQR6P4C7.mjs.map +0 -7
- package/dist/lib/browser/chunk-GN2FSWTM.mjs +0 -22
- package/dist/lib/browser/chunk-GN2FSWTM.mjs.map +0 -7
- package/dist/lib/browser/chunk-TCVYYI44.mjs +0 -21
- package/dist/lib/browser/chunk-TCVYYI44.mjs.map +0 -7
- package/dist/lib/browser/chunk-ZEP4O5SU.mjs.map +0 -7
- package/dist/lib/browser/index.mjs +0 -112
- package/dist/lib/browser/index.mjs.map +0 -7
- package/dist/lib/browser/intent-resolver-UYQA6UUQ.mjs +0 -22
- package/dist/lib/browser/intent-resolver-UYQA6UUQ.mjs.map +0 -7
- package/dist/lib/browser/meta.json +0 -1
- package/dist/lib/browser/react-surface-H5CKQVII.mjs +0 -307
- package/dist/lib/browser/react-surface-H5CKQVII.mjs.map +0 -7
- package/dist/types/src/capabilities/intent-resolver.d.ts +0 -4
- package/dist/types/src/capabilities/intent-resolver.d.ts.map +0 -1
- package/dist/types/src/components/Search.stories.d.ts +0 -16
- package/dist/types/src/components/Search.stories.d.ts.map +0 -1
- package/dist/types/src/components/SearchDialog.d.ts +0 -7
- package/dist/types/src/components/SearchDialog.d.ts.map +0 -1
- package/dist/types/src/components/SearchMain.d.ts +0 -6
- package/dist/types/src/components/SearchMain.d.ts.map +0 -1
- package/dist/types/src/components/SearchResults/SearchResults.d.ts +0 -20
- package/dist/types/src/components/SearchResults/SearchResults.d.ts.map +0 -1
- package/dist/types/src/components/SearchResults/SearchResults.stories.d.ts.map +0 -1
- package/dist/types/src/components/SearchResults/index.d.ts +0 -2
- package/dist/types/src/components/SearchResults/index.d.ts.map +0 -1
- package/dist/types/src/components/Searchbar/Searchbar.d.ts +0 -10
- package/dist/types/src/components/Searchbar/Searchbar.d.ts.map +0 -1
- package/dist/types/src/components/Searchbar/Searchbar.stories.d.ts.map +0 -1
- package/dist/types/src/components/Searchbar/index.d.ts +0 -2
- package/dist/types/src/components/Searchbar/index.d.ts.map +0 -1
- package/dist/types/src/types/action.d.ts +0 -13
- package/dist/types/src/types/action.d.ts.map +0 -1
- package/src/capabilities/intent-resolver.ts +0 -18
- package/src/components/Search.stories.tsx +0 -64
- package/src/components/SearchDialog.tsx +0 -136
- package/src/components/SearchMain.tsx +0 -62
- package/src/components/SearchResults/SearchResults.stories.tsx +0 -59
- package/src/components/SearchResults/SearchResults.tsx +0 -83
- package/src/components/SearchResults/index.ts +0 -5
- package/src/components/Searchbar/Searchbar.stories.tsx +0 -28
- package/src/components/Searchbar/Searchbar.tsx +0 -48
- package/src/components/Searchbar/index.ts +0 -5
- package/src/types/action.tsx +0 -16
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/capabilities/react-surface.tsx", "../../../src/components/Searchbar/Searchbar.tsx", "../../../src/components/SearchMain.tsx", "../../../src/components/SearchResults/SearchResults.tsx", "../../../src/components/SearchDialog.tsx"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport React from 'react';\n\nimport { Capabilities, contributes, createSurface } from '@dxos/app-framework';\nimport { useActiveSpace } from '@dxos/plugin-space';\nimport { type Space, isSpace } from '@dxos/react-client/echo';\n\nimport { SEARCH_DIALOG, SearchDialog, type SearchDialogProps, SearchMain } from '../components';\nimport { SearchContextProvider } from '../hooks';\n\nexport default () =>\n contributes(Capabilities.ReactSurface, [\n createSurface({\n id: SEARCH_DIALOG,\n role: 'dialog',\n filter: (data): data is { props: SearchDialogProps } => data.component === SEARCH_DIALOG,\n component: ({ data }) => (\n <SearchContextProvider>\n <SearchDialog {...data.props} />\n </SearchContextProvider>\n ),\n }),\n createSurface({\n id: `${SEARCH_DIALOG}/search-input`,\n role: 'search-input',\n component: () => {\n const space = useActiveSpace();\n\n return (\n <SearchContextProvider>\n <SearchMain space={space} />\n </SearchContextProvider>\n );\n },\n }),\n createSurface({\n id: `${SEARCH_DIALOG}/search`,\n role: 'deck-companion--search',\n filter: (data): data is { subject: Space } => isSpace(data.subject),\n component: ({ data }) => {\n const space = data.subject;\n if (!space) {\n return null;\n }\n\n return (\n <SearchContextProvider>\n <SearchMain space={space} />\n </SearchContextProvider>\n );\n },\n }),\n ]);\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport React, { type KeyboardEvent, useCallback, useRef } from 'react';\n\nimport { Input, type TextInputProps, type ThemedClassName, Toolbar, useControlledState } from '@dxos/react-ui';\n\nexport type SearchbarProps = ThemedClassName<\n Pick<TextInputProps, 'variant' | 'placeholder'> & {\n delay?: number;\n value?: string;\n onChange?: (text?: string) => void;\n onSubmit?: (text?: string) => void;\n }\n>;\n\nexport const Searchbar = ({ classNames, variant, placeholder, value, onChange, onSubmit }: SearchbarProps) => {\n const [text, setText] = useControlledState(value, onChange);\n const inputRef = useRef<HTMLInputElement>(null);\n\n const handleKeyDown = useCallback(\n (event: KeyboardEvent<HTMLInputElement>) => {\n switch (event.key) {\n case 'Enter':\n onSubmit?.(text);\n break;\n }\n },\n [text, onSubmit],\n );\n\n return (\n <Toolbar.Root classNames={classNames}>\n <Input.Root>\n <Input.TextInput\n ref={inputRef}\n placeholder={placeholder}\n autoFocus\n variant={variant}\n value={text ?? ''}\n onChange={({ target }) => setText(target.value)}\n onKeyDown={handleKeyDown}\n />\n </Input.Root>\n </Toolbar.Root>\n );\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport React, { useState } from 'react';\n\nimport { useClient } from '@dxos/react-client';\nimport { Filter, type Space, useQuery } from '@dxos/react-client/echo';\nimport { useTranslation } from '@dxos/react-ui';\nimport { Stack, StackItem } from '@dxos/react-ui-stack';\nimport { activeSurface, mx } from '@dxos/react-ui-theme';\n\nimport { useGlobalSearch, useGlobalSearchResults, useWebSearch } from '../hooks';\nimport { meta } from '../meta';\n\nimport { Searchbar } from './Searchbar';\nimport { SearchResults } from './SearchResults';\n\nexport const SearchMain = ({ space }: { space?: Space }) => {\n const { t } = useTranslation(meta.id);\n const client = useClient();\n const { setMatch } = useGlobalSearch();\n const [query, setQuery] = useState<string>();\n // TODO(burdon): Option to search across spaces.\n const allSpaces = false;\n const objects = useQuery(allSpaces ? client.spaces : space, Filter.everything());\n const results = useGlobalSearchResults(objects);\n\n const { runSearch, results: webResults } = useWebSearch({ query });\n\n // TODO(burdon): Activate and/or filter current main (set context).\n const [selected, setSelected] = useState<string>();\n const handleSelect = (id: string) => {\n setSelected((selected) => (selected === id ? undefined : id));\n };\n\n const allResults = [...results, ...webResults];\n\n return (\n <Stack orientation='vertical' size='contain' itemsCount={1} rail={false} classNames={['bs-full', activeSurface]}>\n <StackItem.Root item={{ id: 'search' }} role='article'>\n <StackItem.Content toolbar>\n <Searchbar\n classNames='pli-2'\n placeholder={t('search placeholder')}\n delay={300}\n onChange={(text) => {\n setQuery(text);\n setMatch?.(text);\n }}\n onSubmit={runSearch}\n />\n {allResults.length > 0 && (\n <div className={mx('flex flex-col bs-full overflow-hidden')}>\n <SearchResults items={allResults} selected={selected} onSelect={handleSelect} />\n </div>\n )}\n </StackItem.Content>\n </StackItem.Root>\n </Stack>\n );\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport React, { type FC, forwardRef } from 'react';\n\nimport { Surface } from '@dxos/app-framework/react';\nimport { Obj } from '@dxos/echo';\nimport { Card } from '@dxos/react-ui-stack';\nimport { ghostHover } from '@dxos/react-ui-theme';\n\nimport { type SearchResult } from '../../types';\n\nexport type SearchResultsProps = {\n items: SearchResult[];\n match?: RegExp;\n selected?: string;\n onSelect?: (id: string) => void;\n};\n\n// TODO(burdon): Key cursor up/down.\n// TODO(burdon): Use stack (should be virtualized).\nexport const SearchResults = ({ items }: SearchResultsProps) => {\n return (\n <div className='overflow-y-auto'>\n <div className='flex flex-col'>\n {items\n // TODO(burdon): Hack to reduce noise from system objects.\n .filter((item) => Obj.getLabel(item.object))\n .map((item) => (\n <div key={item.id} role='none' className='pli-2 first:pbs-2 pbe-2'>\n <Surface role='card' data={{ subject: item.object }} limit={1} />\n </div>\n ))}\n </div>\n </div>\n );\n};\n\nexport type SearchItemProps = SearchResult & { selected: boolean } & Pick<SearchResultsProps, 'onSelect'>;\n\nexport const SearchItem = forwardRef<HTMLDivElement, SearchItemProps>((item, forwardRef) => {\n const { id, objectType, label, snippet, match, selected, onSelect } = item;\n\n return (\n <Card.StaticRoot\n ref={forwardRef}\n classNames={['mx-2 mt-2 cursor-pointer', selected && '!bg-activeSurface', ghostHover]}\n onClick={() => onSelect?.(id)}\n >\n {objectType && <div className='text-xs text-neutral-400 ml-4'>{objectType}</div>}\n <Card.Heading>{label ?? 'Untitled'}</Card.Heading>\n {snippet && <Snippet text={snippet} match={match} />}\n </Card.StaticRoot>\n );\n});\n\nexport const Snippet: FC<{ text: string; match?: RegExp }> = ({ text, match }) => {\n let content = <>{text}</>;\n if (match) {\n const result = text.match(match);\n if (result?.index !== undefined) {\n // Break near to match.\n const maxOffset = 16;\n let before = text.slice(0, result.index);\n if (before.length > maxOffset) {\n const idx = before.indexOf(' ', result.index - maxOffset);\n before = '… ' + before.slice(idx);\n }\n\n const after = text.slice(result.index + result[0].length);\n content = (\n <>\n {before}\n <span className='text-blue-500'>{result[0]}</span>\n {after}\n </>\n );\n }\n }\n\n return <span className='text-xs mb-1 line-clamp-3 text-neutral-300'>{content}</span>;\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport * as Option from 'effect/Option';\nimport React, { forwardRef, useCallback, useState } from 'react';\n\nimport { LayoutAction, createIntent } from '@dxos/app-framework';\nimport { useAppGraph, useIntentDispatcher, useLayout } from '@dxos/app-framework/react';\nimport { Obj } from '@dxos/echo';\nimport { type Node } from '@dxos/plugin-graph';\nimport { useClient } from '@dxos/react-client';\nimport { Filter, useQuery } from '@dxos/react-client/echo';\nimport { Button, Dialog, Icon, toLocalizedString, useTranslation } from '@dxos/react-ui';\nimport { SearchList, type SearchListItemProps } from '@dxos/react-ui-searchlist';\nimport { descriptionText, mx } from '@dxos/react-ui-theme';\n\nimport { useSearchResults } from '../hooks';\nimport { meta } from '../meta';\n\nexport const SEARCH_DIALOG = `${meta.id}/SearchDialog`;\n\ntype SearchListResultProps = {\n node: Node;\n} & Pick<SearchListItemProps, 'onSelect'>;\n\nconst SearchListResult = forwardRef<HTMLDivElement, SearchListResultProps>(({ node, onSelect }, forwardedRef) => {\n const { t } = useTranslation(meta.id);\n const label = toLocalizedString(node?.properties.label ?? 'never', t);\n return (\n <SearchList.Item\n value={label}\n key={node!.id}\n classNames='flex gap-2 items-center pli-2'\n onSelect={() => onSelect?.(node!.id)}\n ref={forwardedRef}\n >\n <Icon size={5} icon={node?.properties.icon} />\n <span className='is-0 grow truncate'>{label}</span>\n </SearchList.Item>\n );\n});\n\nexport type SearchDialogProps = {\n pivotId: string;\n};\n\nexport const SearchDialog = ({ pivotId }: SearchDialogProps) => {\n const { t } = useTranslation(meta.id);\n const { graph } = useAppGraph();\n const layout = useLayout();\n const closed = (Array.isArray(layout.inactive) ? layout.inactive : [layout.inactive])\n .map((id) => graph?.getNode(id))\n .filter(Boolean);\n const [queryString, setQueryString] = useState('');\n const client = useClient();\n const dangerouslyLoadAllObjects = useQuery(client.spaces, Filter.everything());\n const [pending, results] = useSearchResults(queryString, dangerouslyLoadAllObjects);\n const resultObjects = Array.from(results.keys());\n const { dispatchPromise: dispatch } = useIntentDispatcher();\n\n const handleSelect = useCallback(\n async (nodeId: string) => {\n await dispatch(\n createIntent(LayoutAction.UpdateDialog, {\n part: 'dialog',\n options: { state: false },\n }),\n );\n\n // If node is already present in the active parts, scroll to it and close the dialog.\n const index = layout.active.findIndex((id) => id === nodeId);\n if (index !== -1) {\n await dispatch(\n createIntent(LayoutAction.ScrollIntoView, {\n part: 'current',\n subject: nodeId,\n }),\n );\n } else {\n await dispatch(\n createIntent(LayoutAction.Open, {\n part: 'main',\n subject: [nodeId],\n options: {\n pivotId,\n positioning: 'end',\n },\n }),\n );\n }\n },\n [pivotId, dispatch, layout],\n );\n\n return (\n <Dialog.Content classNames={['md:max-is-[24rem] overflow-hidden mbs-12']}>\n <Dialog.Title>{t('search dialog title')}</Dialog.Title>\n <SearchList.Root label={t('search placeholder')} classNames='flex flex-col grow overflow-hidden my-2'>\n <SearchList.Input\n value={queryString}\n onValueChange={(nextValue) => {\n setQueryString(nextValue);\n }}\n placeholder={t('search placeholder')}\n classNames='pli-1 my-2'\n />\n <SearchList.Content classNames='max-bs-[24rem] overflow-auto'>\n {queryString.length > 0 ? (\n resultObjects.length > 0 ? (\n resultObjects\n .map((object) => graph.getNode(Obj.getDXN(object).toString()))\n .filter(Option.isSome)\n .map((node) => <SearchListResult key={node.value.id} node={node.value} onSelect={handleSelect} />)\n ) : (\n <p className='pli-1'>{t(pending ? 'pending results message' : 'empty results message')}</p>\n )\n ) : (\n <>\n {closed.length > 0 && <h2 className={mx('mlb-1', descriptionText)}>{t('recently closed heading')}</h2>}\n {closed.filter(Option.isSome).map((node) => (\n <SearchListResult key={node.value.id} node={node.value} onSelect={handleSelect} />\n ))}\n </>\n )}\n </SearchList.Content>\n </SearchList.Root>\n\n <Dialog.Close asChild>\n <Button variant='primary' classNames='mbs-2'>\n {t('close label', { ns: 'os' })}\n </Button>\n </Dialog.Close>\n </Dialog.Content>\n );\n};\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["React", "Capabilities", "contributes", "createSurface", "useActiveSpace", "isSpace", "React", "useCallback", "useRef", "Input", "Toolbar", "useControlledState", "Searchbar", "classNames", "variant", "placeholder", "value", "onChange", "onSubmit", "text", "setText", "useControlledState", "inputRef", "useRef", "handleKeyDown", "useCallback", "event", "key", "Toolbar", "Root", "Input", "TextInput", "ref", "autoFocus", "target", "onKeyDown", "React", "useState", "useClient", "Filter", "useQuery", "useTranslation", "Stack", "StackItem", "activeSurface", "mx", "React", "forwardRef", "Surface", "Obj", "Card", "ghostHover", "SearchResults", "items", "React", "div", "className", "filter", "item", "Obj", "getLabel", "object", "map", "key", "id", "role", "Surface", "data", "subject", "limit", "SearchMain", "space", "t", "useTranslation", "meta", "id", "client", "useClient", "setMatch", "useGlobalSearch", "query", "setQuery", "useState", "allSpaces", "objects", "useQuery", "spaces", "Filter", "everything", "results", "useGlobalSearchResults", "runSearch", "webResults", "useWebSearch", "selected", "setSelected", "handleSelect", "undefined", "allResults", "React", "Stack", "orientation", "size", "itemsCount", "rail", "classNames", "activeSurface", "StackItem", "Root", "item", "role", "Content", "toolbar", "Searchbar", "placeholder", "delay", "onChange", "text", "onSubmit", "length", "div", "className", "mx", "SearchResults", "items", "onSelect", "Option", "React", "forwardRef", "useCallback", "useState", "LayoutAction", "createIntent", "useAppGraph", "useIntentDispatcher", "useLayout", "Obj", "useClient", "Filter", "useQuery", "Button", "Dialog", "Icon", "toLocalizedString", "useTranslation", "SearchList", "descriptionText", "mx", "SEARCH_DIALOG", "meta", "id", "SearchListResult", "forwardRef", "node", "onSelect", "forwardedRef", "t", "useTranslation", "label", "toLocalizedString", "properties", "React", "SearchList", "Item", "value", "key", "classNames", "ref", "Icon", "size", "icon", "span", "className", "SearchDialog", "pivotId", "graph", "useAppGraph", "layout", "useLayout", "closed", "Array", "isArray", "inactive", "map", "getNode", "filter", "Boolean", "queryString", "setQueryString", "useState", "client", "useClient", "dangerouslyLoadAllObjects", "useQuery", "spaces", "Filter", "everything", "pending", "results", "useSearchResults", "resultObjects", "from", "keys", "dispatchPromise", "dispatch", "useIntentDispatcher", "handleSelect", "useCallback", "nodeId", "createIntent", "LayoutAction", "UpdateDialog", "part", "options", "state", "index", "active", "findIndex", "ScrollIntoView", "subject", "Open", "positioning", "Dialog", "Content", "Title", "Root", "Input", "onValueChange", "nextValue", "placeholder", "length", "object", "Obj", "getDXN", "toString", "isSome", "p", "h2", "mx", "descriptionText", "Close", "asChild", "Button", "variant", "ns", "contributes", "Capabilities", "ReactSurface", "createSurface", "id", "SEARCH_DIALOG", "role", "filter", "data", "component", "React", "SearchContextProvider", "SearchDialog", "props", "space", "useActiveSpace", "SearchMain", "isSpace", "subject"]
|
|
7
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"intent-resolver.d.ts","sourceRoot":"","sources":["../../../../src/capabilities/intent-resolver.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAA2D,MAAM,qBAAqB,CAAC;;AAI5G,wBASI"}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { type Decorator, type StoryObj } from '@storybook/react-vite';
|
|
2
|
-
import React from 'react';
|
|
3
|
-
import { type SearchbarProps } from './Searchbar';
|
|
4
|
-
type StoryProps = SearchbarProps & {
|
|
5
|
-
objects?: any[];
|
|
6
|
-
};
|
|
7
|
-
export declare const Default: Story;
|
|
8
|
-
declare const meta: {
|
|
9
|
-
title: string;
|
|
10
|
-
component: ({ classNames, variant, placeholder, value, onChange, onSubmit }: SearchbarProps) => React.JSX.Element;
|
|
11
|
-
render: ({ objects, ...props }: StoryProps) => React.JSX.Element;
|
|
12
|
-
decorators: Decorator[];
|
|
13
|
-
};
|
|
14
|
-
export default meta;
|
|
15
|
-
type Story = StoryObj<typeof meta>;
|
|
16
|
-
//# sourceMappingURL=Search.stories.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Search.stories.d.ts","sourceRoot":"","sources":["../../../../src/components/Search.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,SAAS,EAAa,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjF,OAAO,KAAmB,MAAM,OAAO,CAAC;AAOxC,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAK7D,KAAK,UAAU,GAAG,cAAc,GAAG;IACjC,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC;CACjB,CAAC;AAyBF,eAAO,MAAM,OAAO,EAAE,KAQrB,CAAC;AAEF,QAAA,MAAM,IAAI;;;oCAjCmC,UAAU;;CAsCrB,CAAC;AAEnC,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC"}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
export declare const SEARCH_DIALOG: string;
|
|
3
|
-
export type SearchDialogProps = {
|
|
4
|
-
pivotId: string;
|
|
5
|
-
};
|
|
6
|
-
export declare const SearchDialog: ({ pivotId }: SearchDialogProps) => React.JSX.Element;
|
|
7
|
-
//# sourceMappingURL=SearchDialog.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SearchDialog.d.ts","sourceRoot":"","sources":["../../../../src/components/SearchDialog.tsx"],"names":[],"mappings":"AAKA,OAAO,KAA4C,MAAM,OAAO,CAAC;AAejE,eAAO,MAAM,aAAa,QAA4B,CAAC;AAuBvD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,aAAa,iBAAiB,sBAwF1D,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SearchMain.d.ts","sourceRoot":"","sources":["../../../../src/components/SearchMain.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAGxC,OAAO,EAAU,KAAK,KAAK,EAAY,MAAM,yBAAyB,CAAC;AAWvE,eAAO,MAAM,UAAU,GAAI,WAAW;IAAE,KAAK,CAAC,EAAE,KAAK,CAAA;CAAE,sBA2CtD,CAAC"}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import React, { type FC } from 'react';
|
|
2
|
-
import { type SearchResult } from '../../types';
|
|
3
|
-
export type SearchResultsProps = {
|
|
4
|
-
items: SearchResult[];
|
|
5
|
-
match?: RegExp;
|
|
6
|
-
selected?: string;
|
|
7
|
-
onSelect?: (id: string) => void;
|
|
8
|
-
};
|
|
9
|
-
export declare const SearchResults: ({ items }: SearchResultsProps) => React.JSX.Element;
|
|
10
|
-
export type SearchItemProps = SearchResult & {
|
|
11
|
-
selected: boolean;
|
|
12
|
-
} & Pick<SearchResultsProps, 'onSelect'>;
|
|
13
|
-
export declare const SearchItem: React.ForwardRefExoticComponent<SearchResult & {
|
|
14
|
-
selected: boolean;
|
|
15
|
-
} & Pick<SearchResultsProps, "onSelect"> & React.RefAttributes<HTMLDivElement>>;
|
|
16
|
-
export declare const Snippet: FC<{
|
|
17
|
-
text: string;
|
|
18
|
-
match?: RegExp;
|
|
19
|
-
}>;
|
|
20
|
-
//# sourceMappingURL=SearchResults.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SearchResults.d.ts","sourceRoot":"","sources":["../../../../../src/components/SearchResults/SearchResults.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,EAAE,KAAK,EAAE,EAAc,MAAM,OAAO,CAAC;AAOnD,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC,CAAC;AAIF,eAAO,MAAM,aAAa,GAAI,WAAW,kBAAkB,sBAe1D,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,YAAY,GAAG;IAAE,QAAQ,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAAC,kBAAkB,EAAE,UAAU,CAAC,CAAC;AAE1G,eAAO,MAAM,UAAU;cAFkC,OAAO;+EAgB9D,CAAC;AAEH,eAAO,MAAM,OAAO,EAAE,EAAE,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAyBxD,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SearchResults.stories.d.ts","sourceRoot":"","sources":["../../../../../src/components/SearchResults/SearchResults.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAa,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,KAAmB,MAAM,OAAO,CAAC;AAQxC,OAAO,EAAiB,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AA0BzE,QAAA,MAAM,IAAI;;;oBAtBmB,kBAAkB;;;;;CA8BT,CAAC;AAEvC,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,OAAO,EAAE,KAKrB,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/SearchResults/index.ts"],"names":[],"mappings":"AAIA,cAAc,iBAAiB,CAAC"}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { type TextInputProps, type ThemedClassName } from '@dxos/react-ui';
|
|
3
|
-
export type SearchbarProps = ThemedClassName<Pick<TextInputProps, 'variant' | 'placeholder'> & {
|
|
4
|
-
delay?: number;
|
|
5
|
-
value?: string;
|
|
6
|
-
onChange?: (text?: string) => void;
|
|
7
|
-
onSubmit?: (text?: string) => void;
|
|
8
|
-
}>;
|
|
9
|
-
export declare const Searchbar: ({ classNames, variant, placeholder, value, onChange, onSubmit }: SearchbarProps) => React.JSX.Element;
|
|
10
|
-
//# sourceMappingURL=Searchbar.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Searchbar.d.ts","sourceRoot":"","sources":["../../../../../src/components/Searchbar/Searchbar.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAkD,MAAM,OAAO,CAAC;AAEvE,OAAO,EAAS,KAAK,cAAc,EAAE,KAAK,eAAe,EAA+B,MAAM,gBAAgB,CAAC;AAE/G,MAAM,MAAM,cAAc,GAAG,eAAe,CAC1C,IAAI,CAAC,cAAc,EAAE,SAAS,GAAG,aAAa,CAAC,GAAG;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC,CACF,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,iEAAiE,cAAc,sBA8BxG,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Searchbar.stories.d.ts","sourceRoot":"","sources":["../../../../../src/components/Searchbar/Searchbar.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAa,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAMjE,QAAA,MAAM,IAAI;;;;;;;CAOwB,CAAC;AAEnC,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,OAAO,EAAE,KAIrB,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/Searchbar/index.ts"],"names":[],"mappings":"AAIA,cAAc,aAAa,CAAC"}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import * as Schema from 'effect/Schema';
|
|
2
|
-
export declare namespace SearchAction {
|
|
3
|
-
const OpenSearch_base: Schema.TaggedClass<OpenSearch, `${string}/open-search`, {
|
|
4
|
-
readonly _tag: Schema.tag<`${string}/open-search`>;
|
|
5
|
-
} & {
|
|
6
|
-
input: typeof Schema.Void;
|
|
7
|
-
output: typeof Schema.Void;
|
|
8
|
-
}>;
|
|
9
|
-
export class OpenSearch extends OpenSearch_base {
|
|
10
|
-
}
|
|
11
|
-
export {};
|
|
12
|
-
}
|
|
13
|
-
//# sourceMappingURL=action.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"action.d.ts","sourceRoot":"","sources":["../../../../src/types/action.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAIxC,yBAAiB,YAAY,CAAC;;;;;;;IAG5B,MAAM,OAAO,UAAW,SAAQ,eAG9B;KAAG;;CACN"}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2025 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { Capabilities, LayoutAction, contributes, createIntent, createResolver } from '@dxos/app-framework';
|
|
6
|
-
|
|
7
|
-
import { SearchAction } from '../types';
|
|
8
|
-
|
|
9
|
-
export default () =>
|
|
10
|
-
contributes(
|
|
11
|
-
Capabilities.IntentResolver,
|
|
12
|
-
createResolver({
|
|
13
|
-
intent: SearchAction.OpenSearch,
|
|
14
|
-
resolve: () => ({
|
|
15
|
-
intents: [createIntent(LayoutAction.UpdateComplementary, { part: 'complementary', subject: 'search' })],
|
|
16
|
-
}),
|
|
17
|
-
}),
|
|
18
|
-
);
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2023 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { type Decorator, type Meta, type StoryObj } from '@storybook/react-vite';
|
|
6
|
-
import React, { useState } from 'react';
|
|
7
|
-
|
|
8
|
-
import { faker } from '@dxos/random';
|
|
9
|
-
import { withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
10
|
-
|
|
11
|
-
import { SearchContextProvider, useGlobalSearch, useGlobalSearchResults } from '../hooks';
|
|
12
|
-
|
|
13
|
-
import { Searchbar, type SearchbarProps } from './Searchbar';
|
|
14
|
-
import { SearchResults } from './SearchResults';
|
|
15
|
-
|
|
16
|
-
faker.seed(1);
|
|
17
|
-
|
|
18
|
-
type StoryProps = SearchbarProps & {
|
|
19
|
-
objects?: any[];
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
const DefaultStory = ({ objects, ...props }: StoryProps) => {
|
|
23
|
-
const [selected, setSelected] = useState<string>();
|
|
24
|
-
const { setMatch } = useGlobalSearch();
|
|
25
|
-
const filteredItems = useGlobalSearchResults(objects);
|
|
26
|
-
|
|
27
|
-
return (
|
|
28
|
-
<div className='flex grow justify-center overflow-hidden'>
|
|
29
|
-
<div className='flex flex-col is-[300px] m-4 overflow-hidden'>
|
|
30
|
-
<Searchbar variant='subdued' placeholder='Enter regular expression...' onChange={setMatch} {...props} />
|
|
31
|
-
<SearchResults items={filteredItems} selected={selected} onSelect={setSelected} />
|
|
32
|
-
</div>
|
|
33
|
-
</div>
|
|
34
|
-
);
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
const withSearchContext = (): Decorator => {
|
|
38
|
-
return (Story) => (
|
|
39
|
-
<SearchContextProvider>
|
|
40
|
-
<Story />
|
|
41
|
-
</SearchContextProvider>
|
|
42
|
-
);
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
export const Default: Story = {
|
|
46
|
-
args: {
|
|
47
|
-
objects: Array.from({ length: 8 }).map(() => ({
|
|
48
|
-
id: faker.string.uuid(),
|
|
49
|
-
label: faker.lorem.sentence(4).replace(/\./g, ''),
|
|
50
|
-
content: faker.lorem.sentences(3),
|
|
51
|
-
})),
|
|
52
|
-
},
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
const meta = {
|
|
56
|
-
title: 'plugins/plugin-search/Search',
|
|
57
|
-
component: Searchbar,
|
|
58
|
-
render: DefaultStory,
|
|
59
|
-
decorators: [withTheme, withLayout({ container: 'column' }), withSearchContext()],
|
|
60
|
-
} satisfies Meta<typeof Searchbar>;
|
|
61
|
-
|
|
62
|
-
export default meta;
|
|
63
|
-
|
|
64
|
-
type Story = StoryObj<typeof meta>;
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2024 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import * as Option from 'effect/Option';
|
|
6
|
-
import React, { forwardRef, useCallback, useState } from 'react';
|
|
7
|
-
|
|
8
|
-
import { LayoutAction, createIntent } from '@dxos/app-framework';
|
|
9
|
-
import { useAppGraph, useIntentDispatcher, useLayout } from '@dxos/app-framework/react';
|
|
10
|
-
import { Obj } from '@dxos/echo';
|
|
11
|
-
import { type Node } from '@dxos/plugin-graph';
|
|
12
|
-
import { useClient } from '@dxos/react-client';
|
|
13
|
-
import { Filter, useQuery } from '@dxos/react-client/echo';
|
|
14
|
-
import { Button, Dialog, Icon, toLocalizedString, useTranslation } from '@dxos/react-ui';
|
|
15
|
-
import { SearchList, type SearchListItemProps } from '@dxos/react-ui-searchlist';
|
|
16
|
-
import { descriptionText, mx } from '@dxos/react-ui-theme';
|
|
17
|
-
|
|
18
|
-
import { useSearchResults } from '../hooks';
|
|
19
|
-
import { meta } from '../meta';
|
|
20
|
-
|
|
21
|
-
export const SEARCH_DIALOG = `${meta.id}/SearchDialog`;
|
|
22
|
-
|
|
23
|
-
type SearchListResultProps = {
|
|
24
|
-
node: Node;
|
|
25
|
-
} & Pick<SearchListItemProps, 'onSelect'>;
|
|
26
|
-
|
|
27
|
-
const SearchListResult = forwardRef<HTMLDivElement, SearchListResultProps>(({ node, onSelect }, forwardedRef) => {
|
|
28
|
-
const { t } = useTranslation(meta.id);
|
|
29
|
-
const label = toLocalizedString(node?.properties.label ?? 'never', t);
|
|
30
|
-
return (
|
|
31
|
-
<SearchList.Item
|
|
32
|
-
value={label}
|
|
33
|
-
key={node!.id}
|
|
34
|
-
classNames='flex gap-2 items-center pli-2'
|
|
35
|
-
onSelect={() => onSelect?.(node!.id)}
|
|
36
|
-
ref={forwardedRef}
|
|
37
|
-
>
|
|
38
|
-
<Icon size={5} icon={node?.properties.icon} />
|
|
39
|
-
<span className='is-0 grow truncate'>{label}</span>
|
|
40
|
-
</SearchList.Item>
|
|
41
|
-
);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
export type SearchDialogProps = {
|
|
45
|
-
pivotId: string;
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
export const SearchDialog = ({ pivotId }: SearchDialogProps) => {
|
|
49
|
-
const { t } = useTranslation(meta.id);
|
|
50
|
-
const { graph } = useAppGraph();
|
|
51
|
-
const layout = useLayout();
|
|
52
|
-
const closed = (Array.isArray(layout.inactive) ? layout.inactive : [layout.inactive])
|
|
53
|
-
.map((id) => graph?.getNode(id))
|
|
54
|
-
.filter(Boolean);
|
|
55
|
-
const [queryString, setQueryString] = useState('');
|
|
56
|
-
const client = useClient();
|
|
57
|
-
const dangerouslyLoadAllObjects = useQuery(client.spaces, Filter.everything());
|
|
58
|
-
const [pending, results] = useSearchResults(queryString, dangerouslyLoadAllObjects);
|
|
59
|
-
const resultObjects = Array.from(results.keys());
|
|
60
|
-
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
61
|
-
|
|
62
|
-
const handleSelect = useCallback(
|
|
63
|
-
async (nodeId: string) => {
|
|
64
|
-
await dispatch(
|
|
65
|
-
createIntent(LayoutAction.UpdateDialog, {
|
|
66
|
-
part: 'dialog',
|
|
67
|
-
options: { state: false },
|
|
68
|
-
}),
|
|
69
|
-
);
|
|
70
|
-
|
|
71
|
-
// If node is already present in the active parts, scroll to it and close the dialog.
|
|
72
|
-
const index = layout.active.findIndex((id) => id === nodeId);
|
|
73
|
-
if (index !== -1) {
|
|
74
|
-
await dispatch(
|
|
75
|
-
createIntent(LayoutAction.ScrollIntoView, {
|
|
76
|
-
part: 'current',
|
|
77
|
-
subject: nodeId,
|
|
78
|
-
}),
|
|
79
|
-
);
|
|
80
|
-
} else {
|
|
81
|
-
await dispatch(
|
|
82
|
-
createIntent(LayoutAction.Open, {
|
|
83
|
-
part: 'main',
|
|
84
|
-
subject: [nodeId],
|
|
85
|
-
options: {
|
|
86
|
-
pivotId,
|
|
87
|
-
positioning: 'end',
|
|
88
|
-
},
|
|
89
|
-
}),
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
|
-
},
|
|
93
|
-
[pivotId, dispatch, layout],
|
|
94
|
-
);
|
|
95
|
-
|
|
96
|
-
return (
|
|
97
|
-
<Dialog.Content classNames={['md:max-is-[24rem] overflow-hidden mbs-12']}>
|
|
98
|
-
<Dialog.Title>{t('search dialog title')}</Dialog.Title>
|
|
99
|
-
<SearchList.Root label={t('search placeholder')} classNames='flex flex-col grow overflow-hidden my-2'>
|
|
100
|
-
<SearchList.Input
|
|
101
|
-
value={queryString}
|
|
102
|
-
onValueChange={(nextValue) => {
|
|
103
|
-
setQueryString(nextValue);
|
|
104
|
-
}}
|
|
105
|
-
placeholder={t('search placeholder')}
|
|
106
|
-
classNames='pli-1 my-2'
|
|
107
|
-
/>
|
|
108
|
-
<SearchList.Content classNames='max-bs-[24rem] overflow-auto'>
|
|
109
|
-
{queryString.length > 0 ? (
|
|
110
|
-
resultObjects.length > 0 ? (
|
|
111
|
-
resultObjects
|
|
112
|
-
.map((object) => graph.getNode(Obj.getDXN(object).toString()))
|
|
113
|
-
.filter(Option.isSome)
|
|
114
|
-
.map((node) => <SearchListResult key={node.value.id} node={node.value} onSelect={handleSelect} />)
|
|
115
|
-
) : (
|
|
116
|
-
<p className='pli-1'>{t(pending ? 'pending results message' : 'empty results message')}</p>
|
|
117
|
-
)
|
|
118
|
-
) : (
|
|
119
|
-
<>
|
|
120
|
-
{closed.length > 0 && <h2 className={mx('mlb-1', descriptionText)}>{t('recently closed heading')}</h2>}
|
|
121
|
-
{closed.filter(Option.isSome).map((node) => (
|
|
122
|
-
<SearchListResult key={node.value.id} node={node.value} onSelect={handleSelect} />
|
|
123
|
-
))}
|
|
124
|
-
</>
|
|
125
|
-
)}
|
|
126
|
-
</SearchList.Content>
|
|
127
|
-
</SearchList.Root>
|
|
128
|
-
|
|
129
|
-
<Dialog.Close asChild>
|
|
130
|
-
<Button variant='primary' classNames='mbs-2'>
|
|
131
|
-
{t('close label', { ns: 'os' })}
|
|
132
|
-
</Button>
|
|
133
|
-
</Dialog.Close>
|
|
134
|
-
</Dialog.Content>
|
|
135
|
-
);
|
|
136
|
-
};
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2023 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import React, { useState } from 'react';
|
|
6
|
-
|
|
7
|
-
import { useClient } from '@dxos/react-client';
|
|
8
|
-
import { Filter, type Space, useQuery } from '@dxos/react-client/echo';
|
|
9
|
-
import { useTranslation } from '@dxos/react-ui';
|
|
10
|
-
import { Stack, StackItem } from '@dxos/react-ui-stack';
|
|
11
|
-
import { activeSurface, mx } from '@dxos/react-ui-theme';
|
|
12
|
-
|
|
13
|
-
import { useGlobalSearch, useGlobalSearchResults, useWebSearch } from '../hooks';
|
|
14
|
-
import { meta } from '../meta';
|
|
15
|
-
|
|
16
|
-
import { Searchbar } from './Searchbar';
|
|
17
|
-
import { SearchResults } from './SearchResults';
|
|
18
|
-
|
|
19
|
-
export const SearchMain = ({ space }: { space?: Space }) => {
|
|
20
|
-
const { t } = useTranslation(meta.id);
|
|
21
|
-
const client = useClient();
|
|
22
|
-
const { setMatch } = useGlobalSearch();
|
|
23
|
-
const [query, setQuery] = useState<string>();
|
|
24
|
-
// TODO(burdon): Option to search across spaces.
|
|
25
|
-
const allSpaces = false;
|
|
26
|
-
const objects = useQuery(allSpaces ? client.spaces : space, Filter.everything());
|
|
27
|
-
const results = useGlobalSearchResults(objects);
|
|
28
|
-
|
|
29
|
-
const { runSearch, results: webResults } = useWebSearch({ query });
|
|
30
|
-
|
|
31
|
-
// TODO(burdon): Activate and/or filter current main (set context).
|
|
32
|
-
const [selected, setSelected] = useState<string>();
|
|
33
|
-
const handleSelect = (id: string) => {
|
|
34
|
-
setSelected((selected) => (selected === id ? undefined : id));
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
const allResults = [...results, ...webResults];
|
|
38
|
-
|
|
39
|
-
return (
|
|
40
|
-
<Stack orientation='vertical' size='contain' itemsCount={1} rail={false} classNames={['bs-full', activeSurface]}>
|
|
41
|
-
<StackItem.Root item={{ id: 'search' }} role='article'>
|
|
42
|
-
<StackItem.Content toolbar>
|
|
43
|
-
<Searchbar
|
|
44
|
-
classNames='pli-2'
|
|
45
|
-
placeholder={t('search placeholder')}
|
|
46
|
-
delay={300}
|
|
47
|
-
onChange={(text) => {
|
|
48
|
-
setQuery(text);
|
|
49
|
-
setMatch?.(text);
|
|
50
|
-
}}
|
|
51
|
-
onSubmit={runSearch}
|
|
52
|
-
/>
|
|
53
|
-
{allResults.length > 0 && (
|
|
54
|
-
<div className={mx('flex flex-col bs-full overflow-hidden')}>
|
|
55
|
-
<SearchResults items={allResults} selected={selected} onSelect={handleSelect} />
|
|
56
|
-
</div>
|
|
57
|
-
)}
|
|
58
|
-
</StackItem.Content>
|
|
59
|
-
</StackItem.Root>
|
|
60
|
-
</Stack>
|
|
61
|
-
);
|
|
62
|
-
};
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2023 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
6
|
-
import React, { useState } from 'react';
|
|
7
|
-
|
|
8
|
-
import { withPluginManager } from '@dxos/app-framework/testing';
|
|
9
|
-
import { faker } from '@dxos/random';
|
|
10
|
-
import { withTheme } from '@dxos/react-ui/testing';
|
|
11
|
-
|
|
12
|
-
import { filterObjectsSync } from '../../hooks';
|
|
13
|
-
|
|
14
|
-
import { SearchResults, type SearchResultsProps } from './SearchResults';
|
|
15
|
-
|
|
16
|
-
faker.seed(1);
|
|
17
|
-
|
|
18
|
-
const DefaultStory = (props: SearchResultsProps) => {
|
|
19
|
-
const [selected, setSelected] = useState<string>();
|
|
20
|
-
|
|
21
|
-
return (
|
|
22
|
-
<div className='flex grow justify-center overflow-hidden'>
|
|
23
|
-
<div className='flex is-[300px] m-4 overflow-hidden'>
|
|
24
|
-
<SearchResults {...props} selected={selected} onSelect={setSelected} />
|
|
25
|
-
</div>
|
|
26
|
-
</div>
|
|
27
|
-
);
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
const word = 'hello';
|
|
31
|
-
|
|
32
|
-
const objects = Array.from({ length: 100 }).map((_, i) => ({
|
|
33
|
-
id: faker.string.uuid(),
|
|
34
|
-
name: faker.lorem.sentence(4),
|
|
35
|
-
content: faker.lorem.sentence() + ` ${word} ` + faker.lorem.sentence(),
|
|
36
|
-
}));
|
|
37
|
-
|
|
38
|
-
const match = new RegExp(word, 'i');
|
|
39
|
-
|
|
40
|
-
const meta = {
|
|
41
|
-
title: 'plugins/plugin-search/SearchResults',
|
|
42
|
-
component: SearchResults,
|
|
43
|
-
render: DefaultStory,
|
|
44
|
-
decorators: [withTheme, withPluginManager({ plugins: [] })],
|
|
45
|
-
parameters: {
|
|
46
|
-
layout: 'fullscreen',
|
|
47
|
-
},
|
|
48
|
-
} satisfies Meta<typeof SearchResults>;
|
|
49
|
-
|
|
50
|
-
export default meta;
|
|
51
|
-
|
|
52
|
-
type Story = StoryObj<typeof meta>;
|
|
53
|
-
|
|
54
|
-
export const Default: Story = {
|
|
55
|
-
args: {
|
|
56
|
-
items: filterObjectsSync(objects, match),
|
|
57
|
-
match,
|
|
58
|
-
},
|
|
59
|
-
};
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2023 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import React, { type FC, forwardRef } from 'react';
|
|
6
|
-
|
|
7
|
-
import { Surface } from '@dxos/app-framework/react';
|
|
8
|
-
import { Obj } from '@dxos/echo';
|
|
9
|
-
import { Card } from '@dxos/react-ui-stack';
|
|
10
|
-
import { ghostHover } from '@dxos/react-ui-theme';
|
|
11
|
-
|
|
12
|
-
import { type SearchResult } from '../../types';
|
|
13
|
-
|
|
14
|
-
export type SearchResultsProps = {
|
|
15
|
-
items: SearchResult[];
|
|
16
|
-
match?: RegExp;
|
|
17
|
-
selected?: string;
|
|
18
|
-
onSelect?: (id: string) => void;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
// TODO(burdon): Key cursor up/down.
|
|
22
|
-
// TODO(burdon): Use stack (should be virtualized).
|
|
23
|
-
export const SearchResults = ({ items }: SearchResultsProps) => {
|
|
24
|
-
return (
|
|
25
|
-
<div className='overflow-y-auto'>
|
|
26
|
-
<div className='flex flex-col'>
|
|
27
|
-
{items
|
|
28
|
-
// TODO(burdon): Hack to reduce noise from system objects.
|
|
29
|
-
.filter((item) => Obj.getLabel(item.object))
|
|
30
|
-
.map((item) => (
|
|
31
|
-
<div key={item.id} role='none' className='pli-2 first:pbs-2 pbe-2'>
|
|
32
|
-
<Surface role='card' data={{ subject: item.object }} limit={1} />
|
|
33
|
-
</div>
|
|
34
|
-
))}
|
|
35
|
-
</div>
|
|
36
|
-
</div>
|
|
37
|
-
);
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
export type SearchItemProps = SearchResult & { selected: boolean } & Pick<SearchResultsProps, 'onSelect'>;
|
|
41
|
-
|
|
42
|
-
export const SearchItem = forwardRef<HTMLDivElement, SearchItemProps>((item, forwardRef) => {
|
|
43
|
-
const { id, objectType, label, snippet, match, selected, onSelect } = item;
|
|
44
|
-
|
|
45
|
-
return (
|
|
46
|
-
<Card.StaticRoot
|
|
47
|
-
ref={forwardRef}
|
|
48
|
-
classNames={['mx-2 mt-2 cursor-pointer', selected && '!bg-activeSurface', ghostHover]}
|
|
49
|
-
onClick={() => onSelect?.(id)}
|
|
50
|
-
>
|
|
51
|
-
{objectType && <div className='text-xs text-neutral-400 ml-4'>{objectType}</div>}
|
|
52
|
-
<Card.Heading>{label ?? 'Untitled'}</Card.Heading>
|
|
53
|
-
{snippet && <Snippet text={snippet} match={match} />}
|
|
54
|
-
</Card.StaticRoot>
|
|
55
|
-
);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
export const Snippet: FC<{ text: string; match?: RegExp }> = ({ text, match }) => {
|
|
59
|
-
let content = <>{text}</>;
|
|
60
|
-
if (match) {
|
|
61
|
-
const result = text.match(match);
|
|
62
|
-
if (result?.index !== undefined) {
|
|
63
|
-
// Break near to match.
|
|
64
|
-
const maxOffset = 16;
|
|
65
|
-
let before = text.slice(0, result.index);
|
|
66
|
-
if (before.length > maxOffset) {
|
|
67
|
-
const idx = before.indexOf(' ', result.index - maxOffset);
|
|
68
|
-
before = '… ' + before.slice(idx);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const after = text.slice(result.index + result[0].length);
|
|
72
|
-
content = (
|
|
73
|
-
<>
|
|
74
|
-
{before}
|
|
75
|
-
<span className='text-blue-500'>{result[0]}</span>
|
|
76
|
-
{after}
|
|
77
|
-
</>
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
return <span className='text-xs mb-1 line-clamp-3 text-neutral-300'>{content}</span>;
|
|
83
|
-
};
|