@dxos/plugin-search 0.8.4-main.fd6878d → 0.8.4-staging.60fe92afc8
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/PLUGIN.mdl +291 -0
- 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-ADB5LBS5.mjs +71 -0
- package/dist/lib/neutral/app-graph-builder-ADB5LBS5.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-2XHA22US.mjs +9 -0
- package/dist/lib/neutral/chunk-2XHA22US.mjs.map +7 -0
- package/dist/lib/neutral/chunk-BST37VRI.mjs +34 -0
- package/dist/lib/neutral/chunk-BST37VRI.mjs.map +7 -0
- package/dist/lib/neutral/chunk-GT3AGVU6.mjs +28 -0
- package/dist/lib/neutral/chunk-GT3AGVU6.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-M7FWWQKQ.mjs +282 -0
- package/dist/lib/neutral/chunk-M7FWWQKQ.mjs.map +7 -0
- package/dist/lib/neutral/chunk-Q2F6YOOZ.mjs +41 -0
- package/dist/lib/neutral/chunk-Q2F6YOOZ.mjs.map +7 -0
- package/dist/lib/neutral/chunk-TN4G3MZZ.mjs +8 -0
- package/dist/lib/neutral/chunk-TN4G3MZZ.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-Y6OUELN3.mjs +23 -0
- package/dist/lib/neutral/open-search-Y6OUELN3.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-3IXL3EOJ.mjs +61 -0
- package/dist/lib/neutral/react-surface-3IXL3EOJ.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 +3 -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/containers/SearchArticle/SearchArticle.stories.d.ts +14 -0
- 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/containers/SearchDialog/SearchDialog.stories.d.ts +16 -0
- 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/index.d.ts +1 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- 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 +3 -4
- 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 +115 -50
- package/src/SearchPlugin.tsx +20 -48
- package/src/capabilities/app-graph-builder.ts +55 -68
- package/src/capabilities/index.ts +8 -4
- package/src/capabilities/operation-handler.ts +16 -0
- package/src/capabilities/react-surface.tsx +65 -52
- 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 +9 -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/index.ts +2 -0
- package/src/hooks/sync.test.ts +9 -7
- package/src/hooks/sync.ts +33 -34
- package/src/hooks/useGlobalSearch.tsx +32 -13
- package/src/hooks/useSearchResults.ts +9 -6
- package/src/hooks/useWebSearch.ts +25 -14
- package/src/index.ts +2 -2
- package/src/meta.ts +29 -8
- 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 +9 -11
- package/src/search/exa.ts +22 -19
- package/src/testing.ts +7 -0
- package/src/translations.ts +10 -9
- package/src/types/SearchOperation.ts +20 -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/src/vite-env.d.ts +10 -0
- package/dist/lib/browser/app-graph-builder-D2QQTIIR.mjs +0 -77
- package/dist/lib/browser/app-graph-builder-D2QQTIIR.mjs.map +0 -7
- package/dist/lib/browser/chunk-JVMYGOKS.mjs +0 -21
- package/dist/lib/browser/chunk-JVMYGOKS.mjs.map +0 -7
- package/dist/lib/browser/chunk-KNS62YL2.mjs +0 -20
- package/dist/lib/browser/chunk-KNS62YL2.mjs.map +0 -7
- package/dist/lib/browser/chunk-VKV5ZDB4.mjs +0 -190
- package/dist/lib/browser/chunk-VKV5ZDB4.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-NXFDPFHC.mjs +0 -22
- package/dist/lib/browser/intent-resolver-NXFDPFHC.mjs.map +0 -7
- package/dist/lib/browser/meta.json +0 -1
- package/dist/lib/browser/react-surface-B2XYD6JN.mjs +0 -468
- package/dist/lib/browser/react-surface-B2XYD6JN.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 -15
- 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 -7
- 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 +0 -12
- 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 -14
- package/dist/types/src/components/Searchbar/Searchbar.d.ts.map +0 -1
- package/dist/types/src/components/Searchbar/Searchbar.stories.d.ts +0 -11
- 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 -67
- package/src/components/SearchDialog.tsx +0 -124
- package/src/components/SearchMain.tsx +0 -68
- package/src/components/SearchResults/SearchResults.stories.tsx +0 -58
- package/src/components/SearchResults/SearchResults.tsx +0 -86
- package/src/components/SearchResults/index.ts +0 -5
- package/src/components/Searchbar/Searchbar.stories.tsx +0 -28
- package/src/components/Searchbar/Searchbar.tsx +0 -67
- package/src/components/Searchbar/index.ts +0 -5
- package/src/types/action.tsx +0 -16
package/LICENSE
CHANGED
|
@@ -1,8 +1,105 @@
|
|
|
1
|
-
|
|
2
|
-
Copyright (c) 2022 DXOS
|
|
1
|
+
# Functional Source License, Version 1.1, ALv2 Future License
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
## Abbreviation
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
FSL-1.1-Apache-2.0
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
## Notice
|
|
8
|
+
|
|
9
|
+
Copyright 2026 DXOS
|
|
10
|
+
|
|
11
|
+
## Terms and Conditions
|
|
12
|
+
|
|
13
|
+
### Licensor ("We")
|
|
14
|
+
|
|
15
|
+
The party offering the Software under these Terms and Conditions.
|
|
16
|
+
|
|
17
|
+
### The Software
|
|
18
|
+
|
|
19
|
+
The "Software" is each version of the software that we make available under
|
|
20
|
+
these Terms and Conditions, as indicated by our inclusion of these Terms and
|
|
21
|
+
Conditions with the Software.
|
|
22
|
+
|
|
23
|
+
### License Grant
|
|
24
|
+
|
|
25
|
+
Subject to your compliance with this License Grant and the Patents,
|
|
26
|
+
Redistribution and Trademark clauses below, we hereby grant you the right to
|
|
27
|
+
use, copy, modify, create derivative works, publicly perform, publicly display
|
|
28
|
+
and redistribute the Software for any Permitted Purpose identified below.
|
|
29
|
+
|
|
30
|
+
### Permitted Purpose
|
|
31
|
+
|
|
32
|
+
A Permitted Purpose is any purpose other than a Competing Use. A Competing Use
|
|
33
|
+
means making the Software available to others in a commercial product or
|
|
34
|
+
service that:
|
|
35
|
+
|
|
36
|
+
1. substitutes for the Software;
|
|
37
|
+
|
|
38
|
+
2. substitutes for any other product or service we offer using the Software
|
|
39
|
+
that exists as of the date we make the Software available; or
|
|
40
|
+
|
|
41
|
+
3. offers the same or substantially similar functionality as the Software.
|
|
42
|
+
|
|
43
|
+
Permitted Purposes specifically include using the Software:
|
|
44
|
+
|
|
45
|
+
1. for your internal use and access;
|
|
46
|
+
|
|
47
|
+
2. for non-commercial education;
|
|
48
|
+
|
|
49
|
+
3. for non-commercial research; and
|
|
50
|
+
|
|
51
|
+
4. in connection with professional services that you provide to a licensee
|
|
52
|
+
using the Software in accordance with these Terms and Conditions.
|
|
53
|
+
|
|
54
|
+
### Patents
|
|
55
|
+
|
|
56
|
+
To the extent your use for a Permitted Purpose would necessarily infringe our
|
|
57
|
+
patents, the license grant above includes a license under our patents. If you
|
|
58
|
+
make a claim against any party that the Software infringes or contributes to
|
|
59
|
+
the infringement of any patent, then your patent license to the Software ends
|
|
60
|
+
immediately.
|
|
61
|
+
|
|
62
|
+
### Redistribution
|
|
63
|
+
|
|
64
|
+
The Terms and Conditions apply to all copies, modifications and derivatives of
|
|
65
|
+
the Software.
|
|
66
|
+
|
|
67
|
+
If you redistribute any copies, modifications or derivatives of the Software,
|
|
68
|
+
you must include a copy of or a link to these Terms and Conditions and not
|
|
69
|
+
remove any copyright notices provided in or with the Software.
|
|
70
|
+
|
|
71
|
+
### Disclaimer
|
|
72
|
+
|
|
73
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR
|
|
74
|
+
IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF FITNESS FOR A PARTICULAR
|
|
75
|
+
PURPOSE, MERCHANTABILITY, TITLE OR NON-INFRINGEMENT.
|
|
76
|
+
|
|
77
|
+
IN NO EVENT WILL WE HAVE ANY LIABILITY TO YOU ARISING OUT OF OR RELATED TO THE
|
|
78
|
+
SOFTWARE, INCLUDING INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES,
|
|
79
|
+
EVEN IF WE HAVE BEEN INFORMED OF THEIR POSSIBILITY IN ADVANCE.
|
|
80
|
+
|
|
81
|
+
### Trademarks
|
|
82
|
+
|
|
83
|
+
Except for displaying the License Details and identifying us as the origin of
|
|
84
|
+
the Software, you have no right under these Terms and Conditions to use our
|
|
85
|
+
trademarks, trade names, service marks or product names.
|
|
86
|
+
|
|
87
|
+
## Grant of Future License
|
|
88
|
+
|
|
89
|
+
We hereby irrevocably grant you an additional license to use the Software under
|
|
90
|
+
the Apache License, Version 2.0 that is effective on the second anniversary of
|
|
91
|
+
the date we make the Software available. On or after that date, you may use the
|
|
92
|
+
Software under the Apache License, Version 2.0, in which case the following
|
|
93
|
+
will apply:
|
|
94
|
+
|
|
95
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
|
96
|
+
this file except in compliance with the License.
|
|
97
|
+
|
|
98
|
+
You may obtain a copy of the License at
|
|
99
|
+
|
|
100
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
101
|
+
|
|
102
|
+
Unless required by applicable law or agreed to in writing, software distributed
|
|
103
|
+
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
104
|
+
CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
|
105
|
+
specific language governing permissions and limitations under the License.
|
package/PLUGIN.mdl
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: org.dxos.plugin.search
|
|
3
|
+
name: SearchPlugin
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
A full-text search and web-search plugin for `DXOS` Composer that lets users locate objects
|
|
8
|
+
across all spaces and pull in structured data from the web.
|
|
9
|
+
|
|
10
|
+
## Extensions
|
|
11
|
+
|
|
12
|
+
The following extension dialects are used in this document.
|
|
13
|
+
Each extension is defined in the Appendix or resolved via its URI.
|
|
14
|
+
|
|
15
|
+
| Term | URI |
|
|
16
|
+
|-------------|--------------------------------|
|
|
17
|
+
| `type` | `org.dxos.mdl.type@1.0` |
|
|
18
|
+
| `feat` | `org.dxos.mdl.feat@1.0` |
|
|
19
|
+
| `test` | `org.dxos.mdl.test@1.0` |
|
|
20
|
+
| `component` | `org.dxos.mdl.component@1.0` |
|
|
21
|
+
| `op` | `org.dxos.mdl.op@1.0` |
|
|
22
|
+
|
|
23
|
+
## Types
|
|
24
|
+
|
|
25
|
+
```mdl
|
|
26
|
+
type SearchQuery
|
|
27
|
+
fields:
|
|
28
|
+
text: string # raw query string entered by the user
|
|
29
|
+
spaceId?: string # optional scope; omit to search all spaces
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
```mdl
|
|
33
|
+
type MatchField
|
|
34
|
+
fields:
|
|
35
|
+
key: string # field name that matched (e.g. "title", "body")
|
|
36
|
+
value: string # full field value containing the match
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
```mdl
|
|
40
|
+
type SearchResult
|
|
41
|
+
fields:
|
|
42
|
+
objectId: string # ECHO object DXN
|
|
43
|
+
typeName: string # schema typename of the matched object
|
|
44
|
+
fields: MatchField[] # list of fields where the query matched
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
```mdl
|
|
48
|
+
type WebSearchResult
|
|
49
|
+
fields:
|
|
50
|
+
url: string
|
|
51
|
+
title: string
|
|
52
|
+
snippet: string
|
|
53
|
+
publishedDate?: string
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Components
|
|
57
|
+
|
|
58
|
+
```mdl
|
|
59
|
+
component SearchDialog
|
|
60
|
+
desc: |
|
|
61
|
+
Modal command-palette style dialog invoked globally via the OpenSearch operation.
|
|
62
|
+
Renders a search input at the top; results populate below in real time.
|
|
63
|
+
props:
|
|
64
|
+
space: Space # current active space to scope the search
|
|
65
|
+
state:
|
|
66
|
+
query: string # live query text
|
|
67
|
+
results: SearchResult[] # objects matching the current query
|
|
68
|
+
pending: boolean # true while debounced search is in-flight
|
|
69
|
+
slots:
|
|
70
|
+
empty?: ReactNode # shown when query is non-empty but results are empty
|
|
71
|
+
actions:
|
|
72
|
+
submitQuery(text: string)
|
|
73
|
+
clearQuery()
|
|
74
|
+
selectResult(result: SearchResult)
|
|
75
|
+
emits:
|
|
76
|
+
onSelect(result: SearchResult)
|
|
77
|
+
layout: |
|
|
78
|
+
┌─────────────────────────────┐
|
|
79
|
+
│ 🔍 [search input] │
|
|
80
|
+
├─────────────────────────────┤
|
|
81
|
+
│ result row │
|
|
82
|
+
│ result row │
|
|
83
|
+
│ result row │
|
|
84
|
+
│ [empty slot] │
|
|
85
|
+
└─────────────────────────────┘
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
```mdl
|
|
89
|
+
component SearchArticle
|
|
90
|
+
desc: |
|
|
91
|
+
Inline search panel mounted in the deck companion (sidebar) and in the
|
|
92
|
+
search-input role. Shares the same SearchContextProvider as SearchDialog
|
|
93
|
+
so the active query filters objects across the whole Composer deck.
|
|
94
|
+
props:
|
|
95
|
+
space: Space
|
|
96
|
+
state:
|
|
97
|
+
query: string
|
|
98
|
+
results: SearchResult[]
|
|
99
|
+
actions:
|
|
100
|
+
submitQuery(text: string)
|
|
101
|
+
clearQuery()
|
|
102
|
+
layout: |
|
|
103
|
+
┌─────────────────────────────┐
|
|
104
|
+
│ [search input] │
|
|
105
|
+
├─────────────────────────────┤
|
|
106
|
+
│ result list │
|
|
107
|
+
└─────────────────────────────┘
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Operations
|
|
111
|
+
|
|
112
|
+
```mdl
|
|
113
|
+
op OpenSearch
|
|
114
|
+
desc: |
|
|
115
|
+
Opens the global SearchDialog by dispatching a LayoutOperation.UpdateDialog
|
|
116
|
+
event. No input parameters required; the dialog manages its own query state.
|
|
117
|
+
input: void
|
|
118
|
+
output: void
|
|
119
|
+
effects: [layout:dialog]
|
|
120
|
+
note: Registered as SearchOperation.OpenSearch; triggered from the command palette.
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Features
|
|
124
|
+
|
|
125
|
+
```mdl
|
|
126
|
+
feat F-1: Local Object Search
|
|
127
|
+
|
|
128
|
+
req F-1.1: User can open SearchDialog from anywhere in Composer via the OpenSearch operation.
|
|
129
|
+
|
|
130
|
+
req F-1.2:
|
|
131
|
+
when: user types into the search input
|
|
132
|
+
then: query is debounced (400 ms) then matched against all ECHO objects in the active space
|
|
133
|
+
|
|
134
|
+
req F-1.3:
|
|
135
|
+
when: an object's field value matches the query regex
|
|
136
|
+
then: result entry shown with the object type, matched field key, and field value snippet
|
|
137
|
+
|
|
138
|
+
req F-1.4:
|
|
139
|
+
when: query is empty or cleared
|
|
140
|
+
then: results list is empty; no search is executed
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
```mdl
|
|
144
|
+
feat F-2: Global Filter Integration
|
|
145
|
+
|
|
146
|
+
req F-2.1:
|
|
147
|
+
when: SearchContextProvider is mounted
|
|
148
|
+
then: active query is propagated to GlobalFilterProvider so all views using
|
|
149
|
+
useGlobalFilteredObjects automatically show only matching objects
|
|
150
|
+
|
|
151
|
+
req F-2.2:
|
|
152
|
+
when: query is cleared
|
|
153
|
+
then: GlobalFilterProvider returns all objects unfiltered
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
```mdl
|
|
157
|
+
feat F-3: Deck Companion Search Panel
|
|
158
|
+
|
|
159
|
+
req F-3.1:
|
|
160
|
+
when: user opens the deck companion panel with role deck-companion--search
|
|
161
|
+
then: SearchArticle is rendered scoped to the active Space
|
|
162
|
+
|
|
163
|
+
req F-3.2:
|
|
164
|
+
when: user types in SearchArticle
|
|
165
|
+
then: results update in real time using the same debounced filter as SearchDialog
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
```mdl
|
|
169
|
+
feat F-4: Web Search (Exa)
|
|
170
|
+
|
|
171
|
+
req F-4.1:
|
|
172
|
+
when: the Exa API key is configured
|
|
173
|
+
then: external web-search is available and returns WebSearchResult objects
|
|
174
|
+
|
|
175
|
+
req F-4.2:
|
|
176
|
+
when: web search returns results
|
|
177
|
+
then: results are ranked by relevance and returned with url, title, and snippet
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Acceptance
|
|
181
|
+
|
|
182
|
+
```mdl
|
|
183
|
+
test T-1: OpenSearch operation opens dialog
|
|
184
|
+
given: user is in Composer with an active space
|
|
185
|
+
when: user triggers the OpenSearch operation (e.g. ⌘K)
|
|
186
|
+
then:
|
|
187
|
+
- SearchDialog is visible
|
|
188
|
+
- search input has focus
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
```mdl
|
|
192
|
+
test T-2: Query returns matching objects
|
|
193
|
+
given: space contains a document with title "Meeting Notes"
|
|
194
|
+
when: user types "meeting" into SearchDialog
|
|
195
|
+
then:
|
|
196
|
+
- result row for the document appears
|
|
197
|
+
- matched field key is "title"
|
|
198
|
+
- field value contains "Meeting Notes"
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
```mdl
|
|
202
|
+
test T-3: Empty query shows no results
|
|
203
|
+
given: SearchDialog is open
|
|
204
|
+
when: user clears the query string
|
|
205
|
+
then: results list is empty; pending is false
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
```mdl
|
|
209
|
+
test T-4: GlobalFilter propagation
|
|
210
|
+
given: SearchContextProvider is mounted in the deck
|
|
211
|
+
when: user types "budget" in SearchArticle
|
|
212
|
+
then: all views using useGlobalFilteredObjects show only objects matching "budget"
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
```mdl
|
|
216
|
+
test T-5: Non-matching query shows empty state
|
|
217
|
+
given: space has no objects matching "xyzzy"
|
|
218
|
+
when: user types "xyzzy"
|
|
219
|
+
then:
|
|
220
|
+
- results list is empty
|
|
221
|
+
- empty slot is rendered
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## Appendix: Extension Definitions
|
|
227
|
+
|
|
228
|
+
Extension block types used in this document are defined below using
|
|
229
|
+
the core `ext` primitive — the only construct the base language provides.
|
|
230
|
+
|
|
231
|
+
```mdl
|
|
232
|
+
ext type
|
|
233
|
+
uri: org.dxos.mdl.type@1.0
|
|
234
|
+
desc: A named data structure with typed fields and optional literals.
|
|
235
|
+
fields:
|
|
236
|
+
desc?: Prose
|
|
237
|
+
fields?: FieldMap # name[?]: TypeExpr (# inline comment)
|
|
238
|
+
literals?: UnionList # a | b | c
|
|
239
|
+
extends?: TypeRef[]
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
```mdl
|
|
243
|
+
ext feat
|
|
244
|
+
uri: org.dxos.mdl.feat@1.0
|
|
245
|
+
desc: A named feature grouping one or more requirements.
|
|
246
|
+
fields:
|
|
247
|
+
desc?: Prose
|
|
248
|
+
req: RequirementList
|
|
249
|
+
nesting: self # feat blocks may contain feat blocks
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
```mdl
|
|
253
|
+
ext test
|
|
254
|
+
uri: org.dxos.mdl.test@1.0
|
|
255
|
+
desc: An acceptance scenario expressed as given / when / then steps.
|
|
256
|
+
fields:
|
|
257
|
+
given?: Step | Step[]
|
|
258
|
+
when?: Step | Step[]
|
|
259
|
+
then: Step | Step[]
|
|
260
|
+
tags?: TagList
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
```mdl
|
|
264
|
+
ext component
|
|
265
|
+
uri: org.dxos.mdl.component@1.0
|
|
266
|
+
desc: A UI component with props, internal state, slots, actions, and events.
|
|
267
|
+
fields:
|
|
268
|
+
desc?: Prose
|
|
269
|
+
props?: FieldMap # external inputs (immutable inside component)
|
|
270
|
+
state?: FieldMap # internal reactive state
|
|
271
|
+
slots?: FieldMap # named ReactNode injection points
|
|
272
|
+
actions?: ActionMap # methods the component exposes or handles
|
|
273
|
+
emits?: EventMap # events the component raises to its parent
|
|
274
|
+
layout?: CodeBlock # ASCII sketch of visual structure (non-normative)
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
```mdl
|
|
278
|
+
ext op
|
|
279
|
+
uri: org.dxos.mdl.op@1.0
|
|
280
|
+
desc: |
|
|
281
|
+
A named operation with typed inputs, outputs, and declared errors.
|
|
282
|
+
Pure ops have no effects or requires. Effectful ops declare both.
|
|
283
|
+
fields:
|
|
284
|
+
desc?: Prose
|
|
285
|
+
input?: FieldMap # named input parameters
|
|
286
|
+
output?: TypeExpr # return type
|
|
287
|
+
errors?: ErrorMap # name: Prose (when this error occurs)
|
|
288
|
+
effects?: EffectList # echo:read | echo:write | http | fs | ...
|
|
289
|
+
requires?: ServiceList # injected service dependencies
|
|
290
|
+
note?: Prose # implementation guidance (non-normative)
|
|
291
|
+
```
|
package/README.md
CHANGED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import "./chunk-J5LGTIGS.mjs";
|
|
2
|
+
|
|
3
|
+
// src/containers/SearchArticle/SearchArticle.tsx
|
|
4
|
+
import React, { useCallback, useMemo, useState } from "react";
|
|
5
|
+
import { Entity, Filter, Query } from "@dxos/echo";
|
|
6
|
+
import { useQuery } from "@dxos/react-client/echo";
|
|
7
|
+
import { Panel, Toolbar } from "@dxos/react-ui";
|
|
8
|
+
import { SearchList } from "@dxos/react-ui-search";
|
|
9
|
+
import { Text } from "@dxos/schema";
|
|
10
|
+
import { isTauri, getHostPlatform } from "@dxos/util";
|
|
11
|
+
import { SearchResultStack } from "#components";
|
|
12
|
+
import { useGlobalSearch, useGlobalSearchResults, useWebSearch } from "#hooks";
|
|
13
|
+
var SearchArticle = ({ space }) => {
|
|
14
|
+
const [query, setQuery] = useState();
|
|
15
|
+
const objects = useQuery(space.db, query === void 0 ? Query.select(Filter.nothing()) : Query.select(Filter.not(Filter.type(Text.Text))));
|
|
16
|
+
const { setMatch } = useGlobalSearch();
|
|
17
|
+
const results = useGlobalSearchResults(objects);
|
|
18
|
+
const { results: webResults } = useWebSearch({
|
|
19
|
+
query
|
|
20
|
+
});
|
|
21
|
+
const allResults = useMemo(() => [
|
|
22
|
+
...results,
|
|
23
|
+
...webResults
|
|
24
|
+
].filter(({ object }) => object && Entity.getLabel(object)), [
|
|
25
|
+
results,
|
|
26
|
+
webResults
|
|
27
|
+
]);
|
|
28
|
+
const handleSearch = useCallback((text) => {
|
|
29
|
+
setQuery(text);
|
|
30
|
+
setMatch?.(text);
|
|
31
|
+
}, [
|
|
32
|
+
setMatch
|
|
33
|
+
]);
|
|
34
|
+
const autoFocus = !isTauri() || getHostPlatform() !== "ios";
|
|
35
|
+
return /* @__PURE__ */ React.createElement(SearchList.Root, {
|
|
36
|
+
onSearch: handleSearch
|
|
37
|
+
}, /* @__PURE__ */ React.createElement(Panel.Root, null, /* @__PURE__ */ React.createElement(Panel.Content, {
|
|
38
|
+
asChild: true
|
|
39
|
+
}, /* @__PURE__ */ React.createElement(SearchResultStack, {
|
|
40
|
+
results: allResults
|
|
41
|
+
})), /* @__PURE__ */ React.createElement(Panel.Statusbar, {
|
|
42
|
+
asChild: true
|
|
43
|
+
}, /* @__PURE__ */ React.createElement(Toolbar.Root, null, /* @__PURE__ */ React.createElement(SearchList.Input, {
|
|
44
|
+
placeholder: "Search...",
|
|
45
|
+
autoFocus
|
|
46
|
+
})))));
|
|
47
|
+
};
|
|
48
|
+
export {
|
|
49
|
+
SearchArticle as default
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=SearchArticle-CQMZ46ZS.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/containers/SearchArticle/SearchArticle.tsx"],
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport React, { useCallback, useMemo, useState } from 'react';\n\nimport { AppSurface } from '@dxos/app-toolkit/ui';\nimport { Entity, Filter, Query } from '@dxos/echo';\nimport { useQuery } from '@dxos/react-client/echo';\nimport { Panel, Toolbar } from '@dxos/react-ui';\nimport { SearchList } from '@dxos/react-ui-search';\nimport { Text } from '@dxos/schema';\nimport { isTauri, getHostPlatform } from '@dxos/util';\n\nimport { SearchResultStack } from '#components';\nimport { useGlobalSearch, useGlobalSearchResults, useWebSearch } from '#hooks';\n\nexport const SearchArticle = ({ space }: AppSurface.SpaceArticleProps) => {\n // TODO(burdon): Option to query across spaces.\n const [query, setQuery] = useState<string>();\n // TODO(burdon): Re-enable full-text search when indexer is available in all environments.\n const objects = useQuery(\n space.db,\n query === undefined ? Query.select(Filter.nothing()) : Query.select(Filter.not(Filter.type(Text.Text))),\n );\n\n const { setMatch } = useGlobalSearch();\n const results = useGlobalSearchResults(objects);\n const { results: webResults } = useWebSearch({ query });\n const allResults = useMemo(\n () => [...results, ...webResults].filter(({ object }) => object && Entity.getLabel(object)),\n [results, webResults],\n );\n\n const handleSearch = useCallback(\n (text: string) => {\n setQuery(text);\n setMatch?.(text);\n },\n [setMatch],\n );\n\n const autoFocus = !isTauri() || getHostPlatform() !== 'ios';\n\n // TODO(burdon): Move current up/down without losing focus.\n return (\n <SearchList.Root onSearch={handleSearch}>\n <Panel.Root>\n <Panel.Content asChild>\n <SearchResultStack results={allResults} />\n </Panel.Content>\n <Panel.Statusbar asChild>\n <Toolbar.Root>\n <SearchList.Input placeholder='Search...' autoFocus={autoFocus} />\n </Toolbar.Root>\n </Panel.Statusbar>\n </Panel.Root>\n </SearchList.Root>\n );\n};\n"],
|
|
5
|
+
"mappings": ";;;AAIA,OAAOA,SAASC,aAAaC,SAASC,gBAAgB;AAGtD,SAASC,QAAQC,QAAQC,aAAa;AACtC,SAASC,gBAAgB;AACzB,SAASC,OAAOC,eAAe;AAC/B,SAASC,kBAAkB;AAC3B,SAASC,YAAY;AACrB,SAASC,SAASC,uBAAuB;AAEzC,SAASC,yBAAyB;AAClC,SAASC,iBAAiBC,wBAAwBC,oBAAoB;AAE/D,IAAMC,gBAAgB,CAAC,EAAEC,MAAK,MAAgC;AAEnE,QAAM,CAACC,OAAOC,QAAAA,IAAYlB,SAAAA;AAE1B,QAAMmB,UAAUf,SACdY,MAAMI,IACNH,UAAUI,SAAYlB,MAAMmB,OAAOpB,OAAOqB,QAAO,CAAA,IAAMpB,MAAMmB,OAAOpB,OAAOsB,IAAItB,OAAOuB,KAAKjB,KAAKA,IAAI,CAAA,CAAA,CAAA;AAGtG,QAAM,EAAEkB,SAAQ,IAAKd,gBAAAA;AACrB,QAAMe,UAAUd,uBAAuBM,OAAAA;AACvC,QAAM,EAAEQ,SAASC,WAAU,IAAKd,aAAa;IAAEG;EAAM,CAAA;AACrD,QAAMY,aAAa9B,QACjB,MAAM;OAAI4B;OAAYC;IAAYE,OAAO,CAAC,EAAEC,OAAM,MAAOA,UAAU9B,OAAO+B,SAASD,MAAAA,CAAAA,GACnF;IAACJ;IAASC;GAAW;AAGvB,QAAMK,eAAenC,YACnB,CAACoC,SAAAA;AACChB,aAASgB,IAAAA;AACTR,eAAWQ,IAAAA;EACb,GACA;IAACR;GAAS;AAGZ,QAAMS,YAAY,CAAC1B,QAAAA,KAAaC,gBAAAA,MAAsB;AAGtD,SACE,sBAAA,cAACH,WAAW6B,MAAI;IAACC,UAAUJ;KACzB,sBAAA,cAAC5B,MAAM+B,MAAI,MACT,sBAAA,cAAC/B,MAAMiC,SAAO;IAACC,SAAAA;KACb,sBAAA,cAAC5B,mBAAAA;IAAkBgB,SAASE;OAE9B,sBAAA,cAACxB,MAAMmC,WAAS;IAACD,SAAAA;KACf,sBAAA,cAACjC,QAAQ8B,MAAI,MACX,sBAAA,cAAC7B,WAAWkC,OAAK;IAACC,aAAY;IAAYP;;AAMtD;",
|
|
6
|
+
"names": ["React", "useCallback", "useMemo", "useState", "Entity", "Filter", "Query", "useQuery", "Panel", "Toolbar", "SearchList", "Text", "isTauri", "getHostPlatform", "SearchResultStack", "useGlobalSearch", "useGlobalSearchResults", "useWebSearch", "SearchArticle", "space", "query", "setQuery", "objects", "db", "undefined", "select", "nothing", "not", "type", "setMatch", "results", "webResults", "allResults", "filter", "object", "getLabel", "handleSearch", "text", "autoFocus", "Root", "onSearch", "Content", "asChild", "Statusbar", "Input", "placeholder"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import "./chunk-J5LGTIGS.mjs";
|
|
2
|
+
|
|
3
|
+
// src/containers/SearchDialog/SearchDialog.tsx
|
|
4
|
+
import React, { useCallback, useMemo, useState } from "react";
|
|
5
|
+
import { useOperationInvoker } from "@dxos/app-framework/ui";
|
|
6
|
+
import { getObjectPathFromObject, LayoutOperation } from "@dxos/app-toolkit";
|
|
7
|
+
import { useLayout } from "@dxos/app-toolkit/ui";
|
|
8
|
+
import { Entity, Filter, Obj, Query } from "@dxos/echo";
|
|
9
|
+
import { useQuery } from "@dxos/react-client/echo";
|
|
10
|
+
import { Dialog, useTranslation } from "@dxos/react-ui";
|
|
11
|
+
import { SearchList } from "@dxos/react-ui-search";
|
|
12
|
+
import { Text } from "@dxos/schema";
|
|
13
|
+
import { useGlobalSearch, useGlobalSearchResults } from "#hooks";
|
|
14
|
+
import { meta } from "#meta";
|
|
15
|
+
var SearchDialog = ({ space, pivotId: pivotIdProp }) => {
|
|
16
|
+
const { t } = useTranslation(meta.id);
|
|
17
|
+
const { invokePromise } = useOperationInvoker();
|
|
18
|
+
const { setMatch } = useGlobalSearch();
|
|
19
|
+
const layout = useLayout();
|
|
20
|
+
const pivotId = pivotIdProp ?? layout.active[layout.active.length - 1];
|
|
21
|
+
const [query, setQuery] = useState();
|
|
22
|
+
const objects = useQuery(space?.db, query === void 0 ? Query.select(Filter.nothing()) : Query.select(Filter.not(Filter.type(Text.Text))));
|
|
23
|
+
const results = useGlobalSearchResults(objects);
|
|
24
|
+
const allResults = useMemo(() => results.filter(({ object }) => object && Entity.getLabel(object)), [
|
|
25
|
+
results
|
|
26
|
+
]);
|
|
27
|
+
const handleSearch = useCallback((text) => {
|
|
28
|
+
setQuery(text);
|
|
29
|
+
setMatch?.(text);
|
|
30
|
+
}, [
|
|
31
|
+
setMatch
|
|
32
|
+
]);
|
|
33
|
+
const handleSelect = useCallback(async (result) => {
|
|
34
|
+
if (!result.object || !Obj.isObject(result.object)) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const qualifiedPath = getObjectPathFromObject(result.object);
|
|
38
|
+
await invokePromise(LayoutOperation.UpdateDialog, {
|
|
39
|
+
state: false
|
|
40
|
+
});
|
|
41
|
+
await invokePromise(LayoutOperation.Open, {
|
|
42
|
+
subject: [
|
|
43
|
+
qualifiedPath
|
|
44
|
+
],
|
|
45
|
+
pivotId,
|
|
46
|
+
positioning: "end"
|
|
47
|
+
});
|
|
48
|
+
}, [
|
|
49
|
+
pivotId,
|
|
50
|
+
invokePromise
|
|
51
|
+
]);
|
|
52
|
+
return /* @__PURE__ */ React.createElement(Dialog.Content, null, /* @__PURE__ */ React.createElement(Dialog.Header, null, /* @__PURE__ */ React.createElement(Dialog.Title, null, t("search-dialog.title")), /* @__PURE__ */ React.createElement(Dialog.Close, {
|
|
53
|
+
asChild: true
|
|
54
|
+
}, /* @__PURE__ */ React.createElement(Dialog.ActionIconButton, {
|
|
55
|
+
action: "close"
|
|
56
|
+
}))), /* @__PURE__ */ React.createElement(SearchList.Root, {
|
|
57
|
+
onSearch: handleSearch
|
|
58
|
+
}, /* @__PURE__ */ React.createElement(SearchList.Input, {
|
|
59
|
+
classNames: "px-0",
|
|
60
|
+
autoFocus: true,
|
|
61
|
+
placeholder: t("search.placeholder")
|
|
62
|
+
}), /* @__PURE__ */ React.createElement(SearchList.Viewport, {
|
|
63
|
+
classNames: "max-h-[24rem]"
|
|
64
|
+
}, allResults.map((result) => /* @__PURE__ */ React.createElement(SearchList.Item, {
|
|
65
|
+
key: result.id,
|
|
66
|
+
classNames: "flex gap-2 items-center",
|
|
67
|
+
value: result.id,
|
|
68
|
+
label: result.label ?? (result.object ? Entity.getLabel(result.object) : void 0) ?? result.id,
|
|
69
|
+
icon: result.icon,
|
|
70
|
+
onSelect: () => void handleSelect(result)
|
|
71
|
+
})), query && allResults.length === 0 && /* @__PURE__ */ React.createElement(SearchList.Empty, null))));
|
|
72
|
+
};
|
|
73
|
+
export {
|
|
74
|
+
SearchDialog as default
|
|
75
|
+
};
|
|
76
|
+
//# sourceMappingURL=SearchDialog-IFMA5UP5.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/containers/SearchDialog/SearchDialog.tsx"],
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport React, { useCallback, useMemo, useState } from 'react';\n\nimport { useOperationInvoker } from '@dxos/app-framework/ui';\nimport { getObjectPathFromObject, LayoutOperation } from '@dxos/app-toolkit';\nimport { type AppSurface } from '@dxos/app-toolkit/ui';\nimport { useLayout } from '@dxos/app-toolkit/ui';\nimport { Entity, Filter, Obj, Query } from '@dxos/echo';\nimport { useQuery } from '@dxos/react-client/echo';\nimport { Dialog, useTranslation } from '@dxos/react-ui';\nimport { SearchList } from '@dxos/react-ui-search';\nimport { Text } from '@dxos/schema';\n\nimport { useGlobalSearch, useGlobalSearchResults } from '#hooks';\nimport { meta } from '#meta';\nimport { type SearchResult } from '#types';\n\nexport type SearchDialogProps = AppSurface.SpaceArticleProps<{\n pivotId?: string;\n}>;\n\nexport const SearchDialog = ({ space, pivotId: pivotIdProp }: SearchDialogProps) => {\n const { t } = useTranslation(meta.id);\n const { invokePromise } = useOperationInvoker();\n const { setMatch } = useGlobalSearch();\n const layout = useLayout();\n const pivotId = pivotIdProp ?? layout.active[layout.active.length - 1];\n const [query, setQuery] = useState<string>();\n\n // TODO(burdon): Re-enable full-text search when indexer is available in all environments.\n const objects = useQuery(\n space?.db,\n query === undefined ? Query.select(Filter.nothing()) : Query.select(Filter.not(Filter.type(Text.Text))),\n );\n\n const results = useGlobalSearchResults(objects);\n const allResults = useMemo(() => results.filter(({ object }) => object && Entity.getLabel(object)), [results]);\n\n const handleSearch = useCallback(\n (text: string) => {\n setQuery(text);\n setMatch?.(text);\n },\n [setMatch],\n );\n\n const handleSelect = useCallback(\n async (result: SearchResult) => {\n if (!result.object || !Obj.isObject(result.object)) {\n return;\n }\n\n const qualifiedPath = getObjectPathFromObject(result.object);\n await invokePromise(LayoutOperation.UpdateDialog, { state: false });\n await invokePromise(LayoutOperation.Open, {\n subject: [qualifiedPath],\n pivotId,\n positioning: 'end',\n });\n },\n [pivotId, invokePromise],\n );\n\n return (\n <Dialog.Content>\n <Dialog.Header>\n <Dialog.Title>{t('search-dialog.title')}</Dialog.Title>\n <Dialog.Close asChild>\n <Dialog.ActionIconButton action='close' />\n </Dialog.Close>\n </Dialog.Header>\n <SearchList.Root onSearch={handleSearch}>\n <SearchList.Input classNames='px-0' autoFocus placeholder={t('search.placeholder')} />\n <SearchList.Viewport classNames='max-h-[24rem]'>\n {allResults.map((result) => (\n <SearchList.Item\n key={result.id}\n classNames='flex gap-2 items-center'\n value={result.id}\n label={result.label ?? (result.object ? Entity.getLabel(result.object) : undefined) ?? result.id}\n icon={result.icon}\n onSelect={() => void handleSelect(result)}\n />\n ))}\n {query && allResults.length === 0 && <SearchList.Empty />}\n </SearchList.Viewport>\n </SearchList.Root>\n </Dialog.Content>\n );\n};\n"],
|
|
5
|
+
"mappings": ";;;AAIA,OAAOA,SAASC,aAAaC,SAASC,gBAAgB;AAEtD,SAASC,2BAA2B;AACpC,SAASC,yBAAyBC,uBAAuB;AAEzD,SAASC,iBAAiB;AAC1B,SAASC,QAAQC,QAAQC,KAAKC,aAAa;AAC3C,SAASC,gBAAgB;AACzB,SAASC,QAAQC,sBAAsB;AACvC,SAASC,kBAAkB;AAC3B,SAASC,YAAY;AAErB,SAASC,iBAAiBC,8BAA8B;AACxD,SAASC,YAAY;AAOd,IAAMC,eAAe,CAAC,EAAEC,OAAOC,SAASC,YAAW,MAAqB;AAC7E,QAAM,EAAEC,EAAC,IAAKV,eAAeK,KAAKM,EAAE;AACpC,QAAM,EAAEC,cAAa,IAAKtB,oBAAAA;AAC1B,QAAM,EAAEuB,SAAQ,IAAKV,gBAAAA;AACrB,QAAMW,SAASrB,UAAAA;AACf,QAAMe,UAAUC,eAAeK,OAAOC,OAAOD,OAAOC,OAAOC,SAAS,CAAA;AACpE,QAAM,CAACC,OAAOC,QAAAA,IAAY7B,SAAAA;AAG1B,QAAM8B,UAAUrB,SACdS,OAAOa,IACPH,UAAUI,SAAYxB,MAAMyB,OAAO3B,OAAO4B,QAAO,CAAA,IAAM1B,MAAMyB,OAAO3B,OAAO6B,IAAI7B,OAAO8B,KAAKvB,KAAKA,IAAI,CAAA,CAAA,CAAA;AAGtG,QAAMwB,UAAUtB,uBAAuBe,OAAAA;AACvC,QAAMQ,aAAavC,QAAQ,MAAMsC,QAAQE,OAAO,CAAC,EAAEC,OAAM,MAAOA,UAAUnC,OAAOoC,SAASD,MAAAA,CAAAA,GAAU;IAACH;GAAQ;AAE7G,QAAMK,eAAe5C,YACnB,CAAC6C,SAAAA;AACCd,aAASc,IAAAA;AACTnB,eAAWmB,IAAAA;EACb,GACA;IAACnB;GAAS;AAGZ,QAAMoB,eAAe9C,YACnB,OAAO+C,WAAAA;AACL,QAAI,CAACA,OAAOL,UAAU,CAACjC,IAAIuC,SAASD,OAAOL,MAAM,GAAG;AAClD;IACF;AAEA,UAAMO,gBAAgB7C,wBAAwB2C,OAAOL,MAAM;AAC3D,UAAMjB,cAAcpB,gBAAgB6C,cAAc;MAAEC,OAAO;IAAM,CAAA;AACjE,UAAM1B,cAAcpB,gBAAgB+C,MAAM;MACxCC,SAAS;QAACJ;;MACV5B;MACAiC,aAAa;IACf,CAAA;EACF,GACA;IAACjC;IAASI;GAAc;AAG1B,SACE,sBAAA,cAACb,OAAO2C,SAAO,MACb,sBAAA,cAAC3C,OAAO4C,QAAM,MACZ,sBAAA,cAAC5C,OAAO6C,OAAK,MAAElC,EAAE,qBAAA,CAAA,GACjB,sBAAA,cAACX,OAAO8C,OAAK;IAACC,SAAAA;KACZ,sBAAA,cAAC/C,OAAOgD,kBAAgB;IAACC,QAAO;QAGpC,sBAAA,cAAC/C,WAAWgD,MAAI;IAACC,UAAUnB;KACzB,sBAAA,cAAC9B,WAAWkD,OAAK;IAACC,YAAW;IAAOC,WAAAA;IAAUC,aAAa5C,EAAE,oBAAA;MAC7D,sBAAA,cAACT,WAAWsD,UAAQ;IAACH,YAAW;KAC7BzB,WAAW6B,IAAI,CAACtB,WACf,sBAAA,cAACjC,WAAWwD,MAAI;IACdC,KAAKxB,OAAOvB;IACZyC,YAAW;IACXO,OAAOzB,OAAOvB;IACdiD,OAAO1B,OAAO0B,UAAU1B,OAAOL,SAASnC,OAAOoC,SAASI,OAAOL,MAAM,IAAIR,WAAca,OAAOvB;IAC9FkD,MAAM3B,OAAO2B;IACbC,UAAU,MAAM,KAAK7B,aAAaC,MAAAA;OAGrCjB,SAASU,WAAWX,WAAW,KAAK,sBAAA,cAACf,WAAW8D,OAAK,IAAA,CAAA,CAAA,CAAA;AAKhE;",
|
|
6
|
+
"names": ["React", "useCallback", "useMemo", "useState", "useOperationInvoker", "getObjectPathFromObject", "LayoutOperation", "useLayout", "Entity", "Filter", "Obj", "Query", "useQuery", "Dialog", "useTranslation", "SearchList", "Text", "useGlobalSearch", "useGlobalSearchResults", "meta", "SearchDialog", "space", "pivotId", "pivotIdProp", "t", "id", "invokePromise", "setMatch", "layout", "active", "length", "query", "setQuery", "objects", "db", "undefined", "select", "nothing", "not", "type", "results", "allResults", "filter", "object", "getLabel", "handleSearch", "text", "handleSelect", "result", "isObject", "qualifiedPath", "UpdateDialog", "state", "Open", "subject", "positioning", "Content", "Header", "Title", "Close", "asChild", "ActionIconButton", "action", "Root", "onSearch", "Input", "classNames", "autoFocus", "placeholder", "Viewport", "map", "Item", "key", "value", "label", "icon", "onSelect", "Empty"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import "./chunk-J5LGTIGS.mjs";
|
|
2
|
+
|
|
3
|
+
// src/capabilities/app-graph-builder.ts
|
|
4
|
+
import * as Effect from "effect/Effect";
|
|
5
|
+
import { Capability } from "@dxos/app-framework";
|
|
6
|
+
import { AppCapabilities, AppNode, getSpaceIdFromPath } from "@dxos/app-toolkit";
|
|
7
|
+
import { Operation } from "@dxos/compute";
|
|
8
|
+
import { ClientCapabilities } from "@dxos/plugin-client";
|
|
9
|
+
import { GraphBuilder, NodeMatcher } from "@dxos/plugin-graph";
|
|
10
|
+
import { linkedSegment } from "@dxos/react-ui-attention";
|
|
11
|
+
import { meta } from "#meta";
|
|
12
|
+
import { SearchOperation } from "#types";
|
|
13
|
+
var app_graph_builder_default = Capability.makeModule(Effect.fnUntraced(function* () {
|
|
14
|
+
const extensions = yield* Effect.all([
|
|
15
|
+
GraphBuilder.createExtension({
|
|
16
|
+
id: "spaceSearch",
|
|
17
|
+
match: NodeMatcher.whenRoot,
|
|
18
|
+
connector: Effect.fnUntraced(function* (node, get) {
|
|
19
|
+
const client = yield* Capability.get(ClientCapabilities.Client);
|
|
20
|
+
const layoutAtom = get(yield* Capability.atom(AppCapabilities.Layout))[0];
|
|
21
|
+
const layout = layoutAtom ? get(layoutAtom) : void 0;
|
|
22
|
+
const spaceId = layout?.workspace ? getSpaceIdFromPath(layout.workspace) : void 0;
|
|
23
|
+
const space = spaceId ? client.spaces.get(spaceId) : null;
|
|
24
|
+
return [
|
|
25
|
+
AppNode.makeDeckCompanion({
|
|
26
|
+
id: linkedSegment("search"),
|
|
27
|
+
label: [
|
|
28
|
+
"search.label",
|
|
29
|
+
{
|
|
30
|
+
ns: meta.id
|
|
31
|
+
}
|
|
32
|
+
],
|
|
33
|
+
icon: "ph--magnifying-glass--regular",
|
|
34
|
+
data: space
|
|
35
|
+
})
|
|
36
|
+
];
|
|
37
|
+
})
|
|
38
|
+
}),
|
|
39
|
+
GraphBuilder.createExtension({
|
|
40
|
+
id: "root",
|
|
41
|
+
match: NodeMatcher.whenRoot,
|
|
42
|
+
actions: () => Effect.succeed([
|
|
43
|
+
{
|
|
44
|
+
id: SearchOperation.OpenSearch.meta.key,
|
|
45
|
+
data: Effect.fnUntraced(function* () {
|
|
46
|
+
yield* Operation.invoke(SearchOperation.OpenSearch);
|
|
47
|
+
return false;
|
|
48
|
+
}),
|
|
49
|
+
properties: {
|
|
50
|
+
label: [
|
|
51
|
+
"search-action.label",
|
|
52
|
+
{
|
|
53
|
+
ns: meta.id
|
|
54
|
+
}
|
|
55
|
+
],
|
|
56
|
+
icon: "ph--magnifying-glass--regular",
|
|
57
|
+
keyBinding: {
|
|
58
|
+
macos: "shift+meta+f",
|
|
59
|
+
windows: "shift+alt+f"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
])
|
|
64
|
+
})
|
|
65
|
+
]);
|
|
66
|
+
return Capability.contributes(AppCapabilities.AppGraphBuilder, extensions);
|
|
67
|
+
}));
|
|
68
|
+
export {
|
|
69
|
+
app_graph_builder_default as default
|
|
70
|
+
};
|
|
71
|
+
//# sourceMappingURL=app-graph-builder-ADB5LBS5.mjs.map
|