sanity-plugin-taxonomy-manager 4.7.2 → 5.0.0
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 +1 -1
- package/README.md +13 -108
- package/{lib → dist}/index.d.ts +66 -48
- package/dist/index.js +106 -0
- package/dist/index.js.map +1 -0
- package/package.json +40 -46
- package/src/components/Children.tsx +4 -3
- package/src/components/Concepts.tsx +2 -2
- package/src/components/Hierarchy.test.tsx +92 -0
- package/src/components/Hierarchy.tsx +65 -30
- package/src/components/TopConcepts.tsx +2 -2
- package/src/components/TreeStructure.tsx +3 -3
- package/src/components/inputs/ArrayHierarchyInput.test.tsx +102 -0
- package/src/components/inputs/ArrayHierarchyInput.tsx +23 -24
- package/src/components/inputs/Identifier.tsx +1 -1
- package/src/components/inputs/InputHierarchy.test.tsx +38 -0
- package/src/components/inputs/InputHierarchy.tsx +20 -68
- package/src/components/inputs/ReferenceHierarchyInput.test.tsx +109 -0
- package/src/components/inputs/ReferenceHierarchyInput.tsx +24 -25
- package/src/components/interactions/ConceptDetailLink.tsx +0 -1
- package/src/components/interactions/ConceptEditAction.tsx +1 -1
- package/src/components/interactions/ConceptSelectLink.test.tsx +49 -0
- package/src/components/interactions/ConceptSelectLink.tsx +10 -6
- package/src/context.ts +34 -14
- package/src/core/__snapshots__/queries.test.ts.snap +386 -0
- package/src/core/__snapshots__/semanticRecommendations.test.ts.snap +10 -0
- package/src/core/createId.test.ts +35 -0
- package/src/core/filters.test.ts +64 -0
- package/src/core/filters.ts +68 -0
- package/src/core/ids.test.ts +68 -0
- package/src/core/ids.ts +61 -0
- package/src/core/mutations.test.ts +114 -0
- package/src/core/mutations.ts +105 -0
- package/src/core/ports.ts +59 -0
- package/src/core/queries.test.ts +50 -0
- package/src/{queries.ts → core/queries.ts} +7 -6
- package/src/core/semanticRecommendations.test.ts +160 -0
- package/src/core/semanticRecommendations.ts +127 -0
- package/src/core/tree/annotateRecommendations.test.ts +43 -0
- package/src/core/tree/annotateRecommendations.ts +30 -0
- package/src/core/tree/pruneConcepts.test.ts +77 -0
- package/src/core/tree/pruneConcepts.ts +72 -0
- package/src/core/validation.test.ts +42 -0
- package/src/core/validation.ts +42 -0
- package/src/helpers/baseIriField.ts +22 -0
- package/src/helpers/branchFilter.test.ts +48 -0
- package/src/helpers/branchFilter.ts +17 -26
- package/src/helpers/schemeFilter.test.ts +51 -0
- package/src/helpers/schemeFilter.ts +11 -23
- package/src/hooks/index.ts +1 -1
- package/src/hooks/useCreateConcept.tsx +33 -110
- package/src/hooks/useRemoveConcept.tsx +24 -36
- package/src/hooks/useSemanticRecommendations.tsx +75 -0
- package/src/index.test.ts +31 -0
- package/src/index.ts +2 -6
- package/src/seams/StudioDataAdapter.ts +81 -0
- package/src/seams/TaxonomyPortContext.tsx +33 -0
- package/src/skosConcept.tsx +23 -234
- package/src/skosConceptScheme.tsx +2 -4
- package/src/structure.tsx +60 -0
- package/src/test/FakeDataPort.test.ts +62 -0
- package/src/test/FakeDataPort.ts +69 -0
- package/src/test/inputHarness.tsx +71 -0
- package/src/test/renderWithUi.test.tsx +14 -0
- package/src/test/renderWithUi.tsx +24 -0
- package/src/test-setup.ts +35 -0
- package/src/types.tsx +30 -11
- package/src/views/ConceptUseView.tsx +4 -10
- package/lib/index.esm.d.mts +0 -492
- package/lib/index.esm.esm.js +0 -182
- package/lib/index.esm.esm.js.map +0 -1
- package/lib/index.esm.mjs +0 -182
- package/lib/index.esm.mjs.map +0 -1
- package/lib/index.js +0 -182
- package/lib/index.js.map +0 -1
- package/sanity.json +0 -8
- package/src/config.ts +0 -16
- package/src/helpers/baseIriField.tsx +0 -42
- package/src/hooks/useEmbeddingsRecs.tsx +0 -75
- package/src/skosConcept.module.css +0 -10
- package/src/structure.ts +0 -40
- package/v2-incompatible.js +0 -11
- /package/src/{helpers → core}/createId.ts +0 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import '@testing-library/jest-dom/vitest'
|
|
2
|
+
|
|
3
|
+
import {cleanup, configure} from '@testing-library/react'
|
|
4
|
+
import {afterEach} from 'vitest'
|
|
5
|
+
|
|
6
|
+
// CI runners (Linux especially) can be several times slower than local; give
|
|
7
|
+
// findBy*/waitFor assertions headroom so async UI doesn't flake.
|
|
8
|
+
configure({asyncUtilTimeout: 5000})
|
|
9
|
+
|
|
10
|
+
// Vitest runs with globals: false, so Testing Library's automatic cleanup does
|
|
11
|
+
// not fire. Clean the rendered DOM after each test to avoid query collisions.
|
|
12
|
+
afterEach(() => cleanup())
|
|
13
|
+
|
|
14
|
+
// jsdom does not implement matchMedia; @sanity/ui's responsive hooks call it.
|
|
15
|
+
if (typeof window !== 'undefined' && typeof window.matchMedia !== 'function') {
|
|
16
|
+
window.matchMedia = ((query: string) => ({
|
|
17
|
+
matches: false,
|
|
18
|
+
media: query,
|
|
19
|
+
onchange: null,
|
|
20
|
+
addListener: () => {},
|
|
21
|
+
removeListener: () => {},
|
|
22
|
+
addEventListener: () => {},
|
|
23
|
+
removeEventListener: () => {},
|
|
24
|
+
dispatchEvent: () => false,
|
|
25
|
+
})) as unknown as typeof window.matchMedia
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// jsdom does not implement ResizeObserver; some @sanity/ui primitives use it.
|
|
29
|
+
if (typeof globalThis.ResizeObserver === 'undefined') {
|
|
30
|
+
globalThis.ResizeObserver = class {
|
|
31
|
+
observe(): void {}
|
|
32
|
+
unobserve(): void {}
|
|
33
|
+
disconnect(): void {}
|
|
34
|
+
} as unknown as typeof ResizeObserver
|
|
35
|
+
}
|
package/src/types.tsx
CHANGED
|
@@ -18,7 +18,8 @@ export interface ChildConceptTerm {
|
|
|
18
18
|
_originalId?: string
|
|
19
19
|
level?: number
|
|
20
20
|
isOrphan?: boolean
|
|
21
|
-
|
|
21
|
+
/** True when this concept is among the current semantic recommendations. */
|
|
22
|
+
recommended?: boolean
|
|
22
23
|
hasMatchingDescendant?: boolean
|
|
23
24
|
childConcepts?: ChildConceptTerm[]
|
|
24
25
|
}
|
|
@@ -27,7 +28,8 @@ export interface TopConceptTerm {
|
|
|
27
28
|
prefLabel: string
|
|
28
29
|
id: string
|
|
29
30
|
_originalId?: string
|
|
30
|
-
|
|
31
|
+
/** True when this concept is among the current semantic recommendations. */
|
|
32
|
+
recommended?: boolean
|
|
31
33
|
hasMatchingDescendant?: boolean
|
|
32
34
|
childConcepts?: ChildConceptTerm[]
|
|
33
35
|
}
|
|
@@ -39,7 +41,7 @@ export interface DocumentConcepts {
|
|
|
39
41
|
|
|
40
42
|
export interface PrefLabelValue {
|
|
41
43
|
value: string
|
|
42
|
-
|
|
44
|
+
|
|
43
45
|
renderDefault: (props: PrefLabelValue) => React.ReactElement
|
|
44
46
|
}
|
|
45
47
|
|
|
@@ -103,17 +105,34 @@ export interface ConceptSchemeDocument extends SanityDocument {
|
|
|
103
105
|
}
|
|
104
106
|
}
|
|
105
107
|
|
|
106
|
-
|
|
108
|
+
/**
|
|
109
|
+
* A semantic match score for a single concept, keyed by its published document id.
|
|
110
|
+
* Produced by the recommendations seam and merged into the hierarchy tree by
|
|
111
|
+
* `annotateRecommendations`. The GROQ `text::semanticSimilarity()` projection owns
|
|
112
|
+
* this shape directly — no wrapper object, no document type.
|
|
113
|
+
*/
|
|
114
|
+
export interface ConceptRecommendation {
|
|
115
|
+
conceptId: string
|
|
107
116
|
score: number
|
|
108
|
-
value: {
|
|
109
|
-
documentId: string
|
|
110
|
-
type: string
|
|
111
|
-
}
|
|
112
117
|
}
|
|
113
118
|
|
|
114
|
-
|
|
115
|
-
|
|
119
|
+
/**
|
|
120
|
+
* Configuration for the input components' semantic term recommendations. When
|
|
121
|
+
* provided, opening the tree browser scores concepts against the dataset's
|
|
122
|
+
* embeddings (via `text::semanticSimilarity()`) using the current values of the
|
|
123
|
+
* referenced fields, and annotates matching terms with a relevance score.
|
|
124
|
+
*
|
|
125
|
+
* Requires [dataset embeddings](https://www.sanity.io/docs/content-lake/dataset-embeddings)
|
|
126
|
+
* to be enabled; without them the tree still renders, just without scores.
|
|
127
|
+
*/
|
|
128
|
+
export interface SemanticSearchConfig {
|
|
129
|
+
/**
|
|
130
|
+
* Field names on the current document whose values are concatenated into the
|
|
131
|
+
* search query. Every listed field must hold a value when the tree is opened;
|
|
132
|
+
* empty fields surface a message in the tree view instead of scores.
|
|
133
|
+
*/
|
|
116
134
|
fieldReferences: string[]
|
|
135
|
+
/** Maximum number of matching terms to return. Defaults to `3`. */
|
|
117
136
|
maxResults?: number
|
|
118
137
|
}
|
|
119
138
|
|
|
@@ -123,6 +142,6 @@ export interface TreeViewProps {
|
|
|
123
142
|
selectConcept?: (conceptId: {_ref: string; _type: 'reference'; _originalId?: string}) => void
|
|
124
143
|
inputComponent?: boolean
|
|
125
144
|
expanded?: boolean
|
|
126
|
-
conceptRecs?:
|
|
145
|
+
conceptRecs?: ConceptRecommendation[]
|
|
127
146
|
recsError?: string | null
|
|
128
147
|
}
|
|
@@ -2,7 +2,6 @@ import {Flex, Spinner, Stack, Box, Card, Inline, Text, Button} from '@sanity/ui'
|
|
|
2
2
|
import {fromString as pathFromString} from '@sanity/util/paths'
|
|
3
3
|
import {useCallback} from 'react'
|
|
4
4
|
import {Preview, useSchema, usePerspective, getPublishedId} from 'sanity'
|
|
5
|
-
import type {SanityDocument} from 'sanity'
|
|
6
5
|
import type {UserViewComponent} from 'sanity/structure'
|
|
7
6
|
import {usePaneRouter} from 'sanity/structure'
|
|
8
7
|
import {Feedback, useListeningQuery} from 'sanity-plugin-utils'
|
|
@@ -36,22 +35,18 @@ export const ConceptUseView: UserViewComponent<Record<string, never>> = ({
|
|
|
36
35
|
template: {id},
|
|
37
36
|
})
|
|
38
37
|
},
|
|
39
|
-
[routerPanesState, groupIndex, handleEditReference]
|
|
38
|
+
[routerPanesState, groupIndex, handleEditReference],
|
|
40
39
|
)
|
|
41
40
|
|
|
42
|
-
const {data, loading, error} = useListeningQuery<
|
|
41
|
+
const {data, loading, error} = useListeningQuery<TagReference[]>(
|
|
43
42
|
`*[!(_type in ["skosConcept","skosConceptScheme"]) && references($refId)]{_id,_type,title}`,
|
|
44
43
|
{
|
|
45
44
|
params: {refId},
|
|
46
45
|
options: {
|
|
47
46
|
perspective: selectedPerspectiveName ? [selectedPerspectiveName] : 'drafts',
|
|
48
47
|
},
|
|
49
|
-
}
|
|
50
|
-
)
|
|
51
|
-
data: TagReference[]
|
|
52
|
-
loading: boolean
|
|
53
|
-
error: Error | null
|
|
54
|
-
}
|
|
48
|
+
},
|
|
49
|
+
)
|
|
55
50
|
|
|
56
51
|
if (loading) {
|
|
57
52
|
return (
|
|
@@ -106,7 +101,6 @@ export const ConceptUseView: UserViewComponent<Record<string, never>> = ({
|
|
|
106
101
|
schemaType && (
|
|
107
102
|
<Button
|
|
108
103
|
key={d._id}
|
|
109
|
-
// eslint-disable-next-line react/jsx-no-bind
|
|
110
104
|
onClick={() => handleClick(d._id, d._type)}
|
|
111
105
|
padding={2}
|
|
112
106
|
mode="bleed"
|
package/lib/index.esm.d.mts
DELETED
|
@@ -1,492 +0,0 @@
|
|
|
1
|
-
import type {ArrayFieldProps} from 'sanity'
|
|
2
|
-
import type {FieldDefinition} from 'sanity'
|
|
3
|
-
import {JSX} from 'react'
|
|
4
|
-
import type {ObjectFieldProps} from 'sanity'
|
|
5
|
-
import {Plugin as Plugin_2} from 'sanity'
|
|
6
|
-
import type {Reference} from 'sanity'
|
|
7
|
-
import type {SanityDocument} from 'sanity'
|
|
8
|
-
import type {useClient} from 'sanity'
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Input component that replaces Sanity's default array field input with a
|
|
12
|
-
* hierarchical taxonomy tree browser. Studio users can browse taxonomy terms
|
|
13
|
-
* organized in their scheme hierarchy and select terms to add to the array field.
|
|
14
|
-
*
|
|
15
|
-
* @remarks
|
|
16
|
-
* - Must be used with a `schemeFilter` or `branchFilter` helper in the field's
|
|
17
|
-
* `options.filter`. Rendering without a filter will display a configuration warning.
|
|
18
|
-
* - Supports only **single-schema arrays** (i.e., `of: [{type: 'reference'}]`). Arrays
|
|
19
|
-
* with multiple schema types will render a warning and fall back to the default input.
|
|
20
|
-
* - Taxonomy selection is disabled when viewing the published perspective.
|
|
21
|
-
* - When `browseOnly` is set in the filter configuration, Sanity's default search input
|
|
22
|
-
* is suppressed and only the tree browser is available for term selection.
|
|
23
|
-
* - When `expanded` is set in the filter configuration, the hierarchy tree loads open
|
|
24
|
-
* by default instead of collapsed.
|
|
25
|
-
*
|
|
26
|
-
* @param props - Standard Sanity `ArrayFieldProps` extended with an optional
|
|
27
|
-
* `embeddingsIndex` configuration object.
|
|
28
|
-
* @param props.embeddingsIndex - Optional configuration for AI-assisted term
|
|
29
|
-
* recommendations via a Sanity Embeddings Index. When provided, opening the tree
|
|
30
|
-
* browser queries the specified index and annotates matching taxonomy terms with
|
|
31
|
-
* a relevance score to help authors identify the most appropriate terms.
|
|
32
|
-
* @param props.embeddingsIndex.indexName - The name of the Sanity Embeddings Index
|
|
33
|
-
* to query. Must be an index that includes `skosConcept` documents.
|
|
34
|
-
* @param props.embeddingsIndex.fieldReferences - An array of field names from the
|
|
35
|
-
* current document whose values are concatenated and sent as the embeddings search
|
|
36
|
-
* query. All listed fields must contain values when the tree browser is opened;
|
|
37
|
-
* empty fields will display an error message in the tree view rather than scores.
|
|
38
|
-
* @param props.embeddingsIndex.maxResults - Maximum number of semantically matching
|
|
39
|
-
* terms to return from the embeddings index. Defaults to `3`.
|
|
40
|
-
*
|
|
41
|
-
* @example
|
|
42
|
-
* Basic usage with a scheme filter:
|
|
43
|
-
* ```js
|
|
44
|
-
* import {ArrayHierarchyInput, schemeFilter} from 'sanity-plugin-taxonomy-manager'
|
|
45
|
-
*
|
|
46
|
-
* defineField({
|
|
47
|
-
* name: 'categories',
|
|
48
|
-
* title: 'Categories',
|
|
49
|
-
* type: 'array',
|
|
50
|
-
* of: [
|
|
51
|
-
* {
|
|
52
|
-
* type: 'reference',
|
|
53
|
-
* to: {type: 'skosConcept'},
|
|
54
|
-
* options: {
|
|
55
|
-
* filter: schemeFilter({schemeId: 'f3deba'}),
|
|
56
|
-
* disableNew: true,
|
|
57
|
-
* },
|
|
58
|
-
* },
|
|
59
|
-
* ],
|
|
60
|
-
* components: {field: ArrayHierarchyInput},
|
|
61
|
-
* })
|
|
62
|
-
* ```
|
|
63
|
-
*
|
|
64
|
-
* @example
|
|
65
|
-
* Branch filter with tree expanded by default:
|
|
66
|
-
* ```js
|
|
67
|
-
* import {ArrayHierarchyInput, branchFilter} from 'sanity-plugin-taxonomy-manager'
|
|
68
|
-
*
|
|
69
|
-
* defineField({
|
|
70
|
-
* name: 'habitats',
|
|
71
|
-
* title: 'Habitats',
|
|
72
|
-
* type: 'array',
|
|
73
|
-
* of: [
|
|
74
|
-
* {
|
|
75
|
-
* type: 'reference',
|
|
76
|
-
* to: {type: 'skosConcept'},
|
|
77
|
-
* options: {
|
|
78
|
-
* filter: branchFilter({schemeId: 'cf76c1', branchId: '1e5e6c', expanded: true}),
|
|
79
|
-
* disableNew: true,
|
|
80
|
-
* },
|
|
81
|
-
* },
|
|
82
|
-
* ],
|
|
83
|
-
* components: {field: ArrayHierarchyInput},
|
|
84
|
-
* })
|
|
85
|
-
* ```
|
|
86
|
-
*
|
|
87
|
-
* @example
|
|
88
|
-
* Browse-only mode (suppresses the default Sanity search input):
|
|
89
|
-
* ```js
|
|
90
|
-
* import {ArrayHierarchyInput, branchFilter} from 'sanity-plugin-taxonomy-manager'
|
|
91
|
-
*
|
|
92
|
-
* defineField({
|
|
93
|
-
* name: 'habitats',
|
|
94
|
-
* title: 'Habitats',
|
|
95
|
-
* type: 'array',
|
|
96
|
-
* of: [
|
|
97
|
-
* {
|
|
98
|
-
* type: 'reference',
|
|
99
|
-
* to: {type: 'skosConcept'},
|
|
100
|
-
* options: {
|
|
101
|
-
* filter: branchFilter({schemeId: 'cf76c1', branchId: '1e5e6c', browseOnly: true}),
|
|
102
|
-
* disableNew: true,
|
|
103
|
-
* },
|
|
104
|
-
* },
|
|
105
|
-
* ],
|
|
106
|
-
* components: {field: ArrayHierarchyInput},
|
|
107
|
-
* })
|
|
108
|
-
* ```
|
|
109
|
-
*
|
|
110
|
-
* @example
|
|
111
|
-
* AI-assisted recommendations via an embeddings index:
|
|
112
|
-
* ```jsx
|
|
113
|
-
* import {ArrayHierarchyInput, branchFilter} from 'sanity-plugin-taxonomy-manager'
|
|
114
|
-
*
|
|
115
|
-
* defineField({
|
|
116
|
-
* name: 'categories',
|
|
117
|
-
* title: 'Categories',
|
|
118
|
-
* type: 'array',
|
|
119
|
-
* of: [
|
|
120
|
-
* {
|
|
121
|
-
* type: 'reference',
|
|
122
|
-
* to: [{type: 'skosConcept'}],
|
|
123
|
-
* options: {
|
|
124
|
-
* filter: branchFilter({schemeId: 'f3deba', branchId: '25f826'}),
|
|
125
|
-
* disableNew: true,
|
|
126
|
-
* },
|
|
127
|
-
* },
|
|
128
|
-
* ],
|
|
129
|
-
* components: {
|
|
130
|
-
* field: (props) => (
|
|
131
|
-
* <ArrayHierarchyInput
|
|
132
|
-
* {...props}
|
|
133
|
-
* embeddingsIndex={{
|
|
134
|
-
* indexName: 'my-taxonomy-index',
|
|
135
|
-
* fieldReferences: ['title', 'description'],
|
|
136
|
-
* maxResults: 4,
|
|
137
|
-
* }}
|
|
138
|
-
* />
|
|
139
|
-
* ),
|
|
140
|
-
* },
|
|
141
|
-
* })
|
|
142
|
-
* ```
|
|
143
|
-
*
|
|
144
|
-
* @see {@link ReferenceHierarchyInput} for single-value `reference` fields
|
|
145
|
-
* @see {@link schemeFilter} for filtering by a full concept scheme
|
|
146
|
-
* @see {@link branchFilter} for filtering by a branch within a concept scheme
|
|
147
|
-
*/
|
|
148
|
-
export declare function ArrayHierarchyInput(props: ArrayHierarchyInputProps): JSX.Element
|
|
149
|
-
|
|
150
|
-
declare type ArrayHierarchyInputProps = ArrayFieldProps & {
|
|
151
|
-
embeddingsIndex?: EmbeddingsIndexConfig
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* #### Reference Field Scheme & Branch Filter
|
|
156
|
-
* A pluggable Function for Filtering to a Top Concept Branch within a SKOS Concept Scheme
|
|
157
|
-
* @param {string} schemeId - The unique six character concept identifier for
|
|
158
|
-
* the Concept Scheme to which you wish to filter.
|
|
159
|
-
* @param {string} branchId - The unique six character concept identifier of
|
|
160
|
-
* a branch. Child concepts will be returned.
|
|
161
|
-
* @param {boolean} [expanded] - Set to `true` to display open hierarchy trees for
|
|
162
|
-
* input components. Input component trees load closed by default.
|
|
163
|
-
* @param {boolean} [browseOnly] - Set to `true` to hide the default Sanity search
|
|
164
|
-
* input and display only the "Browse Taxonomy Tree" button for selecting terms.
|
|
165
|
-
* @returns A reference type filter for the child concepts of the designated branch in the selected Concept Scheme
|
|
166
|
-
* @example
|
|
167
|
-
* ```ts
|
|
168
|
-
* import { branchFilter } from 'sanity-plugin-taxonomy-manager'
|
|
169
|
-
* ...
|
|
170
|
-
* {
|
|
171
|
-
* name: 'test',
|
|
172
|
-
* type: 'array',
|
|
173
|
-
* of: [
|
|
174
|
-
* {
|
|
175
|
-
* type: 'reference',
|
|
176
|
-
* to: {type: 'skosConcept'},
|
|
177
|
-
* options: {
|
|
178
|
-
* filter: branchFilter({
|
|
179
|
-
* schemeId: 'a1b2c3',
|
|
180
|
-
* branchId: 'd4e5f6',
|
|
181
|
-
* expanded: true, // optional; defaults to false (closed tree)
|
|
182
|
-
* browseOnly: true, // optional; hides search input
|
|
183
|
-
* }),
|
|
184
|
-
* disableNew: true,
|
|
185
|
-
* },
|
|
186
|
-
* },
|
|
187
|
-
* ],
|
|
188
|
-
* }
|
|
189
|
-
* ```
|
|
190
|
-
*/
|
|
191
|
-
export declare const branchFilter: (
|
|
192
|
-
options: BranchOptions,
|
|
193
|
-
) => ({
|
|
194
|
-
getClient,
|
|
195
|
-
}: {
|
|
196
|
-
getClient: (clientOptions: {apiVersion: string}) => ReturnType<typeof useClient>
|
|
197
|
-
}) => Promise<BranchFilterResult>
|
|
198
|
-
|
|
199
|
-
declare type BranchFilterResult = {
|
|
200
|
-
filter: string
|
|
201
|
-
params: {
|
|
202
|
-
schemeId: string
|
|
203
|
-
branchId: string
|
|
204
|
-
concepts: string[]
|
|
205
|
-
}
|
|
206
|
-
expanded?: boolean
|
|
207
|
-
browseOnly?: boolean
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
declare type BranchOptions = {
|
|
211
|
-
schemeId: string
|
|
212
|
-
branchId: string
|
|
213
|
-
expanded?: boolean
|
|
214
|
-
browseOnly?: boolean
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
declare interface ConceptSchemeDocument extends SanityDocument {
|
|
218
|
-
displayed: {
|
|
219
|
-
_id: string
|
|
220
|
-
_type: 'skosConceptScheme'
|
|
221
|
-
title?: string
|
|
222
|
-
description?: string
|
|
223
|
-
baseIri?: string
|
|
224
|
-
schemeId?: string
|
|
225
|
-
topConcepts?: Array<{
|
|
226
|
-
_key: string
|
|
227
|
-
_ref: string
|
|
228
|
-
_type: 'reference'
|
|
229
|
-
}>
|
|
230
|
-
concepts?: Array<{
|
|
231
|
-
_key: string
|
|
232
|
-
_ref: string
|
|
233
|
-
_type: 'reference'
|
|
234
|
-
}>
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
declare interface EmbeddingsIndexConfig {
|
|
239
|
-
indexName: string
|
|
240
|
-
fieldReferences: string[]
|
|
241
|
-
maxResults?: number
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
declare interface EmbeddingsResult {
|
|
245
|
-
score: number
|
|
246
|
-
value: {
|
|
247
|
-
documentId: string
|
|
248
|
-
type: string
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
declare type HierarchyInput = ObjectFieldProps<Reference> & {
|
|
253
|
-
embeddingsIndex?: EmbeddingsIndexConfig
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
declare interface Options {
|
|
257
|
-
baseUri?: string
|
|
258
|
-
customConceptFields?: FieldDefinition[]
|
|
259
|
-
customSchemeFields?: FieldDefinition[]
|
|
260
|
-
ident?: {
|
|
261
|
-
pattern?: string
|
|
262
|
-
length?: number
|
|
263
|
-
prefix?: string
|
|
264
|
-
regenUi?: boolean
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
/**
|
|
269
|
-
* Input component that replaces Sanity's default reference field input with a
|
|
270
|
-
* hierarchical taxonomy tree browser. Studio users can browse taxonomy terms
|
|
271
|
-
* organized in their scheme hierarchy and select a single term for the field.
|
|
272
|
-
*
|
|
273
|
-
* @remarks
|
|
274
|
-
* - Must be used with a `schemeFilter` or `branchFilter` helper in the field's
|
|
275
|
-
* `options.filter`. Rendering without a filter will display a configuration warning.
|
|
276
|
-
* - Taxonomy selection is disabled when viewing the published perspective.
|
|
277
|
-
* - When `browseOnly` is set in the filter configuration, Sanity's default search input
|
|
278
|
-
* is suppressed and only the tree browser is available for term selection.
|
|
279
|
-
* - When `expanded` is set in the filter configuration, the hierarchy tree loads open
|
|
280
|
-
* by default instead of collapsed.
|
|
281
|
-
*
|
|
282
|
-
* @param props - Standard Sanity `ObjectFieldProps<Reference>` extended with an optional
|
|
283
|
-
* `embeddingsIndex` configuration object.
|
|
284
|
-
* @param props.embeddingsIndex - Optional configuration for AI-assisted term
|
|
285
|
-
* recommendations via a Sanity Embeddings Index. When provided, opening the tree
|
|
286
|
-
* browser queries the specified index and annotates matching taxonomy terms with
|
|
287
|
-
* a relevance score to help authors identify the most appropriate term.
|
|
288
|
-
* @param props.embeddingsIndex.indexName - The name of the Sanity Embeddings Index
|
|
289
|
-
* to query. Must be an index that includes `skosConcept` documents.
|
|
290
|
-
* @param props.embeddingsIndex.fieldReferences - An array of field names from the
|
|
291
|
-
* current document whose values are concatenated and sent as the embeddings search
|
|
292
|
-
* query. All listed fields must contain values when the tree browser is opened;
|
|
293
|
-
* empty fields will display an error message in the tree view rather than scores.
|
|
294
|
-
* @param props.embeddingsIndex.maxResults - Maximum number of semantically matching
|
|
295
|
-
* terms to return from the embeddings index. Defaults to `3`.
|
|
296
|
-
*
|
|
297
|
-
* @example
|
|
298
|
-
* Basic usage with a scheme filter:
|
|
299
|
-
* ```js
|
|
300
|
-
* import {ReferenceHierarchyInput, schemeFilter} from 'sanity-plugin-taxonomy-manager'
|
|
301
|
-
*
|
|
302
|
-
* defineField({
|
|
303
|
-
* name: 'gradeLevel',
|
|
304
|
-
* title: 'Grade Level',
|
|
305
|
-
* type: 'reference',
|
|
306
|
-
* to: {type: 'skosConcept'},
|
|
307
|
-
* options: {
|
|
308
|
-
* filter: schemeFilter({schemeId: 'f3deba'}),
|
|
309
|
-
* disableNew: true,
|
|
310
|
-
* },
|
|
311
|
-
* components: {field: ReferenceHierarchyInput},
|
|
312
|
-
* })
|
|
313
|
-
* ```
|
|
314
|
-
*
|
|
315
|
-
* @example
|
|
316
|
-
* Branch filter with tree expanded by default:
|
|
317
|
-
* ```js
|
|
318
|
-
* import {ReferenceHierarchyInput, branchFilter} from 'sanity-plugin-taxonomy-manager'
|
|
319
|
-
*
|
|
320
|
-
* defineField({
|
|
321
|
-
* name: 'topics',
|
|
322
|
-
* title: 'Topics',
|
|
323
|
-
* type: 'reference',
|
|
324
|
-
* to: {type: 'skosConcept'},
|
|
325
|
-
* options: {
|
|
326
|
-
* filter: branchFilter({schemeId: 'cf76c1', branchId: '1e5e6c', expanded: true}),
|
|
327
|
-
* disableNew: true,
|
|
328
|
-
* },
|
|
329
|
-
* components: {field: ReferenceHierarchyInput},
|
|
330
|
-
* })
|
|
331
|
-
* ```
|
|
332
|
-
*
|
|
333
|
-
* @example
|
|
334
|
-
* Browse-only mode (suppresses the default Sanity search input):
|
|
335
|
-
* ```js
|
|
336
|
-
* import {ReferenceHierarchyInput, branchFilter} from 'sanity-plugin-taxonomy-manager'
|
|
337
|
-
*
|
|
338
|
-
* defineField({
|
|
339
|
-
* name: 'topics',
|
|
340
|
-
* title: 'Topics',
|
|
341
|
-
* type: 'reference',
|
|
342
|
-
* to: {type: 'skosConcept'},
|
|
343
|
-
* options: {
|
|
344
|
-
* filter: branchFilter({schemeId: 'cf76c1', branchId: '1e5e6c', browseOnly: true}),
|
|
345
|
-
* disableNew: true,
|
|
346
|
-
* },
|
|
347
|
-
* components: {field: ReferenceHierarchyInput},
|
|
348
|
-
* })
|
|
349
|
-
* ```
|
|
350
|
-
*
|
|
351
|
-
* @example
|
|
352
|
-
* AI-assisted recommendations via an embeddings index:
|
|
353
|
-
* ```jsx
|
|
354
|
-
* import {ReferenceHierarchyInput, schemeFilter} from 'sanity-plugin-taxonomy-manager'
|
|
355
|
-
*
|
|
356
|
-
* defineField({
|
|
357
|
-
* name: 'topics',
|
|
358
|
-
* title: 'Topics',
|
|
359
|
-
* type: 'reference',
|
|
360
|
-
* to: [{type: 'skosConcept'}],
|
|
361
|
-
* options: {
|
|
362
|
-
* filter: schemeFilter({schemeId: 'f3deba'}),
|
|
363
|
-
* disableNew: true,
|
|
364
|
-
* },
|
|
365
|
-
* components: {
|
|
366
|
-
* field: (props) => (
|
|
367
|
-
* <ReferenceHierarchyInput
|
|
368
|
-
* {...props}
|
|
369
|
-
* embeddingsIndex={{
|
|
370
|
-
* indexName: 'my-taxonomy-index',
|
|
371
|
-
* fieldReferences: ['title', 'metaDescription'],
|
|
372
|
-
* maxResults: 4,
|
|
373
|
-
* }}
|
|
374
|
-
* />
|
|
375
|
-
* ),
|
|
376
|
-
* },
|
|
377
|
-
* })
|
|
378
|
-
* ```
|
|
379
|
-
*
|
|
380
|
-
* @see {@link ArrayHierarchyInput} for multi-value `array` fields
|
|
381
|
-
* @see {@link schemeFilter} for filtering by a full concept scheme
|
|
382
|
-
* @see {@link branchFilter} for filtering by a branch within a concept scheme
|
|
383
|
-
*/
|
|
384
|
-
export declare function ReferenceHierarchyInput(props: HierarchyInput): JSX.Element
|
|
385
|
-
|
|
386
|
-
/**
|
|
387
|
-
* #### Reference Field Scheme Filter
|
|
388
|
-
* Pluggable Function for Filtering to a Single SKOS Concept Scheme.
|
|
389
|
-
* @param {string} schemeId - The unique six character concept identifier for
|
|
390
|
-
* the Concept Scheme to which you wish to filter.
|
|
391
|
-
* @param {boolean} [expanded] - Set to `true` to display open hierarchy trees for
|
|
392
|
-
* input components. Input component trees load closed by default.
|
|
393
|
-
* @param {boolean} [browseOnly] - Set to `true` to hide the default Sanity search
|
|
394
|
-
* input and display only the "Browse Taxonomy Tree" button for selecting terms.
|
|
395
|
-
* @returns A reference type filter for Concepts and Top Concepts in
|
|
396
|
-
* the selected Concept Scheme test
|
|
397
|
-
* @example
|
|
398
|
-
* ```ts
|
|
399
|
-
* import { schemeFilter } from 'sanity-plugin-taxonomy-manager'
|
|
400
|
-
* ...
|
|
401
|
-
* {
|
|
402
|
-
* name: 'test',
|
|
403
|
-
* type: 'array',
|
|
404
|
-
* of: [
|
|
405
|
-
* {
|
|
406
|
-
* type: 'reference',
|
|
407
|
-
* to: {type: 'skosConcept'},
|
|
408
|
-
* options: {
|
|
409
|
-
* filter: schemeFilter({
|
|
410
|
-
* schemeId: 'a1b2c3',
|
|
411
|
-
* expanded: true, // optional; defaults to false (closed tree)
|
|
412
|
-
* browseOnly: true, // optional; hides search input
|
|
413
|
-
* }),
|
|
414
|
-
* disableNew: true,
|
|
415
|
-
* },
|
|
416
|
-
* },
|
|
417
|
-
* ],
|
|
418
|
-
* }
|
|
419
|
-
* ```
|
|
420
|
-
*/
|
|
421
|
-
export declare const schemeFilter: (
|
|
422
|
-
options: SchemeOptions,
|
|
423
|
-
) => ({
|
|
424
|
-
getClient,
|
|
425
|
-
}: {
|
|
426
|
-
getClient: (clientOptions: {apiVersion: string}) => ReturnType<typeof useClient>
|
|
427
|
-
}) => Promise<SchemeFilterResult>
|
|
428
|
-
|
|
429
|
-
declare type SchemeFilterResult = {
|
|
430
|
-
filter: string
|
|
431
|
-
params: {
|
|
432
|
-
schemeId: string
|
|
433
|
-
concepts: string[]
|
|
434
|
-
topConcepts: string[]
|
|
435
|
-
}
|
|
436
|
-
expanded?: boolean
|
|
437
|
-
browseOnly?: boolean
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
declare type SchemeOptions = {
|
|
441
|
-
schemeId: string
|
|
442
|
-
expanded?: boolean
|
|
443
|
-
browseOnly?: boolean
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
/**
|
|
447
|
-
* #### Sanity Taxonomy Manager
|
|
448
|
-
* Defines a Sanity plugin for managing SKOS compliant taxonomies in Sanity Studio.
|
|
449
|
-
* #### Options
|
|
450
|
-
* @param baseUri - The base URI to use for SKOS concepts and concept schemes. BaseURI should follow an IANA http/s scheme and should terminate with either a / or #.
|
|
451
|
-
* @param customConceptFields - An array of additional fields to add to the skosConcept type.
|
|
452
|
-
* @param customSchemeFields - An array of additional fields to add to the skosConceptScheme type.
|
|
453
|
-
* #### Identifier Configuration
|
|
454
|
-
* @param ident.pattern - The character set to use for identifiers (default: '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz').
|
|
455
|
-
* @param ident.length - The length of the generated identifier (default: 6).
|
|
456
|
-
* @param ident.prefix - A prefix to prepend to generated identifiers, for example to use Wikidata style IDs like "Q27521" (default: '').
|
|
457
|
-
* @param ident.regenUi - Whether to display the "Create Unique Identifier" button in the UI by default.
|
|
458
|
-
* @returns A Sanity plugin object.
|
|
459
|
-
*/
|
|
460
|
-
export declare const taxonomyManager: Plugin_2<Options | undefined>
|
|
461
|
-
|
|
462
|
-
/**
|
|
463
|
-
* #### Tree View Component Wrapper
|
|
464
|
-
* This is the view component for the hierarchy tree. It is the
|
|
465
|
-
* top level of concept scheme views and is passed into Desk
|
|
466
|
-
* structure to render the primary view for taxonomy documents.
|
|
467
|
-
* @param document - The document to render.
|
|
468
|
-
* @param branchId - The branch ID to fetch concepts from.
|
|
469
|
-
* @param inputComponent - Specifies whether the component is Studio input component, which will hide tree view controls and chrome.
|
|
470
|
-
* @param selectConcept - The function to call when a concept is selected.
|
|
471
|
-
*/
|
|
472
|
-
export declare const TreeView: ({
|
|
473
|
-
document,
|
|
474
|
-
branchId,
|
|
475
|
-
inputComponent,
|
|
476
|
-
selectConcept,
|
|
477
|
-
expanded,
|
|
478
|
-
conceptRecs,
|
|
479
|
-
recsError,
|
|
480
|
-
}: TreeViewProps) => JSX.Element
|
|
481
|
-
|
|
482
|
-
declare interface TreeViewProps {
|
|
483
|
-
document?: ConceptSchemeDocument
|
|
484
|
-
branchId?: string | null
|
|
485
|
-
selectConcept?: (conceptId: {_ref: string; _type: 'reference'; _originalId?: string}) => void
|
|
486
|
-
inputComponent?: boolean
|
|
487
|
-
expanded?: boolean
|
|
488
|
-
conceptRecs?: EmbeddingsResult[]
|
|
489
|
-
recsError?: string | null
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
export {}
|