sanity-plugin-taxonomy-manager 4.7.1 → 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 +36 -32
- 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 +37 -33
- 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 -186
- package/lib/index.esm.esm.js.map +0 -1
- package/lib/index.esm.mjs +0 -186
- package/lib/index.esm.mjs.map +0 -1
- package/lib/index.js +0 -186
- 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
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Sanity Taxonomy Manager
|
|
2
2
|
|
|
3
|
-

|
|
4
|
+

|
|
5
5
|
|
|
6
6
|
### Create and manage SKOS compliant taxonomies, thesauri, and classification schemes in Sanity Studio.
|
|
7
7
|
|
|
@@ -26,15 +26,15 @@ For full documentation, visit [sanitytaxonomymanager.com](https://sanitytaxonomy
|
|
|
26
26
|
|
|
27
27
|
## Installation
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
> Compatible with **Sanity Studio v5 and v6** (React 19).
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
npm i sanity-plugin-taxonomy-manager
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
or
|
|
31
|
+
In your Sanity project folder, run:
|
|
36
32
|
|
|
37
33
|
```bash
|
|
34
|
+
npm install sanity-plugin-taxonomy-manager
|
|
35
|
+
# or
|
|
36
|
+
pnpm add sanity-plugin-taxonomy-manager
|
|
37
|
+
# or
|
|
38
38
|
yarn add sanity-plugin-taxonomy-manager
|
|
39
39
|
```
|
|
40
40
|
|
|
@@ -113,110 +113,15 @@ export default defineConfig({
|
|
|
113
113
|
})
|
|
114
114
|
```
|
|
115
115
|
|
|
116
|
-
##
|
|
117
|
-
|
|
118
|
-
See something that could be improved (or a bug that should be fixed)? Please feel free to pitch in.
|
|
119
|
-
|
|
120
|
-
- This plugin uses [@sanity/plugin-kit](https://github.com/sanity-io/plugin-kit)
|
|
121
|
-
with default configuration for build & watch scripts.
|
|
122
|
-
|
|
123
|
-
- See [Testing a plugin in Sanity Studio](https://github.com/sanity-io/plugin-kit#testing-a-plugin-in-sanity-studio)
|
|
124
|
-
on how to run the plugin with hot-reload in the studio.
|
|
125
|
-
|
|
126
|
-
### Component Diagrams
|
|
127
|
-
|
|
128
|
-
The following diagrams map out the relationships between the components used in this plugin and are intended to help those interested in contributing to the project orient themselves. The Taxonomy Manager tree view is designed to support polyhierarchy, and to provide UI affordances common to other taxonomy management tools, both of which lend some complexity to the component structure.
|
|
129
|
-
|
|
130
|
-
> [!TIP]
|
|
131
|
-
> You **do not** need to understand any of this to use the plugin!
|
|
116
|
+
## Development
|
|
132
117
|
|
|
133
|
-
|
|
134
|
-
<Summary><h4>Tree View</h4></Summary>
|
|
118
|
+
This repo bundles a dev Studio as a workspace member (`studio/`). Run it and open the **Taxonomy** tool:
|
|
135
119
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
```mermaid
|
|
139
|
-
graph BT
|
|
140
|
-
subgraph SchemeContext.Provider
|
|
141
|
-
direction BT
|
|
142
|
-
Hierarchy.tsx-->TreeView.tsx
|
|
143
|
-
subgraph TreeContext.Provider
|
|
144
|
-
direction BT
|
|
145
|
-
TreeStructure.tsx-->Hierarchy.tsx
|
|
146
|
-
TopConcepts.tsx[
|
|
147
|
-
TopConcepts.tsx
|
|
148
|
-
<i style="color: gray; font-size: small">uses SchemeContext</i>
|
|
149
|
-
<i style="color: gray; font-size: small">uses TreeContext</i>
|
|
150
|
-
]-->TreeStructure.tsx
|
|
151
|
-
Concepts.tsx[
|
|
152
|
-
Concepts.tsx
|
|
153
|
-
<i style="color: gray; font-size: small">uses SchemeContext</i>
|
|
154
|
-
<i style="color: gray; font-size: small">uses TreeContext</i>
|
|
155
|
-
]-->TreeStructure.tsx
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
%% Sequence below maintains RTL ordering:
|
|
159
|
-
ConceptDetailLink.tsx-->TopConcepts.tsx
|
|
160
|
-
ConceptDetailLink.tsx-->Concepts.tsx
|
|
161
|
-
|
|
162
|
-
ChildConcepts.tsx-->TopConcepts.tsx
|
|
163
|
-
ChildConcepts.tsx-->Concepts.tsx
|
|
164
|
-
Children.tsx-->ChildConcepts.tsx
|
|
165
|
-
|
|
166
|
-
ConceptDetailDialogue.tsx-->Concepts.tsx
|
|
167
|
-
ConceptDetailDialogue.tsx-->TopConcepts.tsx
|
|
168
|
-
|
|
169
|
-
ConceptDetailLink.tsx-->Children.tsx
|
|
170
|
-
ConceptDetailDialogue.tsx-->Children.tsx
|
|
171
|
-
end
|
|
172
|
-
end
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
</Details>
|
|
176
|
-
|
|
177
|
-
<Details>
|
|
178
|
-
<Summary><h4>Input Components</h4></Summary>
|
|
179
|
-
|
|
180
|
-
The [ReferenceHierarchyInput and ArrayHierarchyInput components](https://sanitytaxonomymanager.com/#/?id=tree-view-input-component) afford a field-level hierarchical browse and selection experience for taxonomy terms. Both components draw on filter options supplied by the `schemeFilter` and `branchFilter` helper functions.
|
|
181
|
-
|
|
182
|
-
```mermaid
|
|
183
|
-
graph BT
|
|
184
|
-
subgraph Input Components
|
|
185
|
-
direction BT
|
|
186
|
-
TreeView.tsx-->ArrayHierarchyInput.tsx[
|
|
187
|
-
ArrayHierarchyInput.tsx
|
|
188
|
-
<i style="color: gray; font-size: small">requires schemeFilter</i>
|
|
189
|
-
<i style="color: gray; font-size: small">or branchFilter helper</i>
|
|
190
|
-
]
|
|
191
|
-
TreeView.tsx-->ReferenceHierarchyInput.tsx[
|
|
192
|
-
ReferenceHierarchyInput.tsx
|
|
193
|
-
<i style="color: gray; font-size: small">requires schemeFilter</i>
|
|
194
|
-
<i style="color: gray; font-size: small">or branchFilter helper</i>
|
|
195
|
-
]
|
|
196
|
-
subgraph SchemeContext.Provider
|
|
197
|
-
InputHierarchy.tsx-->TreeView.tsx
|
|
198
|
-
subgraph TreeContext.Provider
|
|
199
|
-
direction BT
|
|
200
|
-
TreeStructure.tsx-->InputHierarchy.tsx
|
|
201
|
-
TopConcepts.tsx[
|
|
202
|
-
TopConcepts.tsx
|
|
203
|
-
<i style="color: gray; font-size: small">uses SchemeContext</i>
|
|
204
|
-
<i style="color: gray; font-size: small">uses TreeContext</i>
|
|
205
|
-
]-->TreeStructure.tsx
|
|
206
|
-
Concepts.tsx[
|
|
207
|
-
Concepts.tsx
|
|
208
|
-
<i style="color: gray; font-size: small">uses SchemeContext</i>
|
|
209
|
-
<i style="color: gray; font-size: small">uses TreeContext</i>
|
|
210
|
-
]-->TreeStructure.tsx
|
|
211
|
-
ChildConcepts.tsx-->TopConcepts.tsx
|
|
212
|
-
ChildConcepts.tsx-->Concepts.tsx
|
|
213
|
-
Children.tsx-->ChildConcepts.tsx
|
|
214
|
-
end
|
|
215
|
-
end
|
|
216
|
-
end
|
|
120
|
+
```bash
|
|
121
|
+
pnpm dev
|
|
217
122
|
```
|
|
218
123
|
|
|
219
|
-
|
|
124
|
+
See the [development docs](docs/development/README.md) for details on plugin design intent, architecture, and functional composition.
|
|
220
125
|
|
|
221
126
|
## License
|
|
222
127
|
|
package/{lib → dist}/index.d.ts
RENAMED
|
@@ -24,19 +24,18 @@ import type {useClient} from 'sanity'
|
|
|
24
24
|
* by default instead of collapsed.
|
|
25
25
|
*
|
|
26
26
|
* @param props - Standard Sanity `ArrayFieldProps` extended with an optional
|
|
27
|
-
* `
|
|
28
|
-
* @param props.
|
|
29
|
-
* recommendations
|
|
30
|
-
*
|
|
31
|
-
* a relevance score to help authors
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
* terms to return from the embeddings index. Defaults to `3`.
|
|
27
|
+
* `semanticSearch` configuration object.
|
|
28
|
+
* @param props.semanticSearch - Optional configuration for AI-assisted term
|
|
29
|
+
* recommendations. When provided, opening the tree browser scores `skosConcept`
|
|
30
|
+
* documents against the dataset's embeddings (`text::semanticSimilarity()`) and
|
|
31
|
+
* annotates matching taxonomy terms with a relevance score to help authors
|
|
32
|
+
* identify the most appropriate terms. Requires dataset embeddings to be enabled.
|
|
33
|
+
* @param props.semanticSearch.fieldReferences - An array of field names from the
|
|
34
|
+
* current document whose values are concatenated and sent as the search query.
|
|
35
|
+
* All listed fields must contain values when the tree browser is opened; empty
|
|
36
|
+
* fields will display a message in the tree view rather than scores.
|
|
37
|
+
* @param props.semanticSearch.maxResults - Maximum number of semantically matching
|
|
38
|
+
* terms to return. Defaults to `3`.
|
|
40
39
|
*
|
|
41
40
|
* @example
|
|
42
41
|
* Basic usage with a scheme filter:
|
|
@@ -130,8 +129,7 @@ import type {useClient} from 'sanity'
|
|
|
130
129
|
* field: (props) => (
|
|
131
130
|
* <ArrayHierarchyInput
|
|
132
131
|
* {...props}
|
|
133
|
-
*
|
|
134
|
-
* indexName: 'my-taxonomy-index',
|
|
132
|
+
* semanticSearch={{
|
|
135
133
|
* fieldReferences: ['title', 'description'],
|
|
136
134
|
* maxResults: 4,
|
|
137
135
|
* }}
|
|
@@ -148,7 +146,7 @@ import type {useClient} from 'sanity'
|
|
|
148
146
|
export declare function ArrayHierarchyInput(props: ArrayHierarchyInputProps): JSX.Element
|
|
149
147
|
|
|
150
148
|
declare type ArrayHierarchyInputProps = ArrayFieldProps & {
|
|
151
|
-
|
|
149
|
+
semanticSearch?: SemanticSearchConfig
|
|
152
150
|
}
|
|
153
151
|
|
|
154
152
|
/**
|
|
@@ -214,6 +212,17 @@ declare type BranchOptions = {
|
|
|
214
212
|
browseOnly?: boolean
|
|
215
213
|
}
|
|
216
214
|
|
|
215
|
+
/**
|
|
216
|
+
* A semantic match score for a single concept, keyed by its published document id.
|
|
217
|
+
* Produced by the recommendations seam and merged into the hierarchy tree by
|
|
218
|
+
* `annotateRecommendations`. The GROQ `text::semanticSimilarity()` projection owns
|
|
219
|
+
* this shape directly — no wrapper object, no document type.
|
|
220
|
+
*/
|
|
221
|
+
declare interface ConceptRecommendation {
|
|
222
|
+
conceptId: string
|
|
223
|
+
score: number
|
|
224
|
+
}
|
|
225
|
+
|
|
217
226
|
declare interface ConceptSchemeDocument extends SanityDocument {
|
|
218
227
|
displayed: {
|
|
219
228
|
_id: string
|
|
@@ -235,22 +244,8 @@ declare interface ConceptSchemeDocument extends SanityDocument {
|
|
|
235
244
|
}
|
|
236
245
|
}
|
|
237
246
|
|
|
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
247
|
declare type HierarchyInput = ObjectFieldProps<Reference> & {
|
|
253
|
-
|
|
248
|
+
semanticSearch?: SemanticSearchConfig
|
|
254
249
|
}
|
|
255
250
|
|
|
256
251
|
declare interface Options {
|
|
@@ -280,19 +275,18 @@ declare interface Options {
|
|
|
280
275
|
* by default instead of collapsed.
|
|
281
276
|
*
|
|
282
277
|
* @param props - Standard Sanity `ObjectFieldProps<Reference>` extended with an optional
|
|
283
|
-
* `
|
|
284
|
-
* @param props.
|
|
285
|
-
* recommendations
|
|
286
|
-
*
|
|
287
|
-
* a relevance score to help authors
|
|
288
|
-
*
|
|
289
|
-
*
|
|
290
|
-
*
|
|
291
|
-
*
|
|
292
|
-
*
|
|
293
|
-
*
|
|
294
|
-
*
|
|
295
|
-
* terms to return from the embeddings index. Defaults to `3`.
|
|
278
|
+
* `semanticSearch` configuration object.
|
|
279
|
+
* @param props.semanticSearch - Optional configuration for AI-assisted term
|
|
280
|
+
* recommendations. When provided, opening the tree browser scores `skosConcept`
|
|
281
|
+
* documents against the dataset's embeddings (`text::semanticSimilarity()`) and
|
|
282
|
+
* annotates matching taxonomy terms with a relevance score to help authors
|
|
283
|
+
* identify the most appropriate term. Requires dataset embeddings to be enabled.
|
|
284
|
+
* @param props.semanticSearch.fieldReferences - An array of field names from the
|
|
285
|
+
* current document whose values are concatenated and sent as the search query.
|
|
286
|
+
* All listed fields must contain values when the tree browser is opened; empty
|
|
287
|
+
* fields will display a message in the tree view rather than scores.
|
|
288
|
+
* @param props.semanticSearch.maxResults - Maximum number of semantically matching
|
|
289
|
+
* terms to return. Defaults to `3`.
|
|
296
290
|
*
|
|
297
291
|
* @example
|
|
298
292
|
* Basic usage with a scheme filter:
|
|
@@ -349,7 +343,7 @@ declare interface Options {
|
|
|
349
343
|
* ```
|
|
350
344
|
*
|
|
351
345
|
* @example
|
|
352
|
-
* AI-assisted recommendations via
|
|
346
|
+
* AI-assisted recommendations via dataset embeddings:
|
|
353
347
|
* ```jsx
|
|
354
348
|
* import {ReferenceHierarchyInput, schemeFilter} from 'sanity-plugin-taxonomy-manager'
|
|
355
349
|
*
|
|
@@ -366,8 +360,7 @@ declare interface Options {
|
|
|
366
360
|
* field: (props) => (
|
|
367
361
|
* <ReferenceHierarchyInput
|
|
368
362
|
* {...props}
|
|
369
|
-
*
|
|
370
|
-
* indexName: 'my-taxonomy-index',
|
|
363
|
+
* semanticSearch={{
|
|
371
364
|
* fieldReferences: ['title', 'metaDescription'],
|
|
372
365
|
* maxResults: 4,
|
|
373
366
|
* }}
|
|
@@ -426,6 +419,11 @@ export declare const schemeFilter: (
|
|
|
426
419
|
getClient: (clientOptions: {apiVersion: string}) => ReturnType<typeof useClient>
|
|
427
420
|
}) => Promise<SchemeFilterResult>
|
|
428
421
|
|
|
422
|
+
/**
|
|
423
|
+
* Pure halves of the reference-field filters. The public `schemeFilter` /
|
|
424
|
+
* `branchFilter` factories (in ../helpers) keep the impure GROQ fetch; the
|
|
425
|
+
* validation and result-assembly below are pure and unit-tested here.
|
|
426
|
+
*/
|
|
429
427
|
declare type SchemeFilterResult = {
|
|
430
428
|
filter: string
|
|
431
429
|
params: {
|
|
@@ -443,6 +441,26 @@ declare type SchemeOptions = {
|
|
|
443
441
|
browseOnly?: boolean
|
|
444
442
|
}
|
|
445
443
|
|
|
444
|
+
/**
|
|
445
|
+
* Configuration for the input components' semantic term recommendations. When
|
|
446
|
+
* provided, opening the tree browser scores concepts against the dataset's
|
|
447
|
+
* embeddings (via `text::semanticSimilarity()`) using the current values of the
|
|
448
|
+
* referenced fields, and annotates matching terms with a relevance score.
|
|
449
|
+
*
|
|
450
|
+
* Requires [dataset embeddings](https://www.sanity.io/docs/content-lake/dataset-embeddings)
|
|
451
|
+
* to be enabled; without them the tree still renders, just without scores.
|
|
452
|
+
*/
|
|
453
|
+
declare interface SemanticSearchConfig {
|
|
454
|
+
/**
|
|
455
|
+
* Field names on the current document whose values are concatenated into the
|
|
456
|
+
* search query. Every listed field must hold a value when the tree is opened;
|
|
457
|
+
* empty fields surface a message in the tree view instead of scores.
|
|
458
|
+
*/
|
|
459
|
+
fieldReferences: string[]
|
|
460
|
+
/** Maximum number of matching terms to return. Defaults to `3`. */
|
|
461
|
+
maxResults?: number
|
|
462
|
+
}
|
|
463
|
+
|
|
446
464
|
/**
|
|
447
465
|
* #### Sanity Taxonomy Manager
|
|
448
466
|
* Defines a Sanity plugin for managing SKOS compliant taxonomies in Sanity Studio.
|
|
@@ -485,7 +503,7 @@ declare interface TreeViewProps {
|
|
|
485
503
|
selectConcept?: (conceptId: {_ref: string; _type: 'reference'; _originalId?: string}) => void
|
|
486
504
|
inputComponent?: boolean
|
|
487
505
|
expanded?: boolean
|
|
488
|
-
conceptRecs?:
|
|
506
|
+
conceptRecs?: ConceptRecommendation[]
|
|
489
507
|
recsError?: string | null
|
|
490
508
|
}
|
|
491
509
|
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import{useFormValue as e,set as n,useDocumentStore as t,useClient as i,useGetFormValue as o,usePerspective as r,isDraftId as c,FormField as s,isVersionId as d,unset as a,defineField as l,defineType as p,defineArrayMember as h,useSchema as m,getPublishedId as u,Preview as f,definePlugin as g}from"sanity";import{usePaneRouter as y,structureTool as b}from"sanity/structure";import{jsxs as C,jsx as I,Fragment as w}from"react/jsx-runtime";import{GenerateIcon as v,InfoOutlineIcon as _,TrashIcon as x,AddCircleIcon as V,ErrorOutlineIcon as k,ToggleArrowRightIcon as T,AddIcon as z,EditIcon as L,DocumentsIcon as S}from"@sanity/icons";import{Stack as H,Text as $,useToast as N,Button as M,Card as P,Box as E,Flex as R,Tooltip as A,Dialog as O,Label as D,Badge as Z,Inline as B,TextInput as U,TextArea as F,Spinner as j,Container as q,Grid as G}from"@sanity/ui";import{useCallback as K,createContext as W,useState as Y,useRef as X,useEffect as Q,useMemo as J,useContext as ee}from"react";import{customAlphabet as ne,nanoid as te}from"nanoid";import{c as ie}from"react/compiler-runtime";import oe from"react-fast-compare";import{distinctUntilChanged as re,catchError as ce}from"rxjs/operators";import{getPublishedId as se,DocumentId as de,isVersionId as ae,getVersionNameFromId as le,getVersionId as pe,getDraftId as he,isPublishedId as me}from"@sanity/id-utils";import{uuid as ue}from"@sanity/uuid";import{RouterContext as fe}from"sanity/router";import{AiOutlineTags as ge,AiOutlineTag as ye}from"react-icons/ai";function be(e){const n=e?.pattern||"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",t=e?.length||6;return(e?.prefix||"")+ne(n,t)()}const Ce=e=>{const{onChange:t,ident:i}=e,o=N(),r=K(()=>{const e=be(i);t(n(e)),o.push({status:"success",title:"Identifier created.",closable:!0})},[t,o,i]);/* @__PURE__ */
|
|
2
|
+
return I(H,{space:2,children:/* @__PURE__ */I(M,{icon:v,mode:"ghost",width:"fill",onClick:r,text:"Generate identifier"})})};Ce.defaultProps={ident:void 0};const Ie=W(null),we=W({editControls:!1}),ve=W(void 0),_e=W({}),xe=W({markRemoved:()=>{},unmarkRemoved:()=>{}});function Ve(e,n){const t=n.has(se(e.id)),i=e.childConcepts?.map(e=>Ve(e,n)),o=i?.some(e=>e.recommended||e.hasMatchingDescendant)??!1;return{...e,...t?{recommended:!0}:{},...o?{hasMatchingDescendant:!0}:{},...i?{childConcepts:i}:{}}}const ke={tone:"primary"};function Te(e){let n,t=ie(12);t[0]===e?n=t[1]:(n={...ke,...e},t[0]=e,t[1]=n);let i,o,r,{title:c,description:s,icon:d,tone:a,children:l}=n,p=d?"display icon":null;return t[2]!==l||t[3]!==s||t[4]!==c?(i=l||/* @__PURE__ */I(E,{flex:1,children:/* @__PURE__ */C(H,{gap:4,children:[c?/* @__PURE__ */I($,{weight:"semibold",children:c}):null,s?/* @__PURE__ */I($,{size:2,children:s}):null]})}),t[2]=l,t[3]=s,t[4]=c,t[5]=i):i=t[5],t[6]!==p||t[7]!==i?(o=/* @__PURE__ */C(R,{children:[p,i]}),t[6]=p,t[7]=i,t[8]=o):o=t[8],t[9]!==o||t[10]!==a?(r=/* @__PURE__ */I(P,{tone:a,padding:4,radius:3,border:!0,children:o}),t[9]=o,t[10]=a,t[11]=r):r=t[11],r}const ze={},Le={apiVersion:"v2023-05-01"};function Se(e){let n,t=ie(4);t[0]===e?n=t[1]:(n=JSON.stringify(e||{}),t[0]=e,t[1]=n);let i,o=n;return t[2]===o?i=t[3]:(i=JSON.parse(o),t[2]=o,t[3]=i),i}function He(e,n){let i,o,r,c=ie(11),{params:s,options:d,initialValue:a}=n,l=void 0===s?ze:s,p=void 0===d?Le:d,h=void 0===a?null:a,[m,u]=Y(!0),[f,g]=Y(null),[y,b]=Y(h),C=Se(l),I=Se(p),w=X(null),v=t();return c[0]!==v||c[1]!==f||c[2]!==I||c[3]!==C||c[4]!==e?(i=()=>{if(e&&!f&&!w.current)try{w.current=v.listenQuery(e,C,I).pipe(re(oe),ce(e=>(console.error(e),g(e),u(!1),b(null),e))).subscribe(e=>{b(n=>oe(n,e)?n:e),u(!1),g(null)})}catch(e){let n=e;console.error(n),u(!1),g(n)}return f&&w.current&&w.current.unsubscribe(),()=>{w.current&&=(w?.current?.unsubscribe(),null)}},o=[e,f,C,I,v],c[0]=v,c[1]=f,c[2]=I,c[3]=C,c[4]=e,c[5]=i,c[6]=o):(i=c[5],o=c[6]),Q(i,o),c[7]!==y||c[8]!==f||c[9]!==m?(r={data:y,loading:m,error:f},c[7]=y,c[8]=f,c[9]=m,c[10]=r):r=c[10],r}const $e=(e=1)=>{let n="^.^.concepts[]._ref",t=1;for(;e>t;)n=`^.${n}`,t++;return e>6?"":`"childConcepts": *[_id in ${n} && ^._id in broader[]._ref]|order(prefLabel)\n {\n "id": _id,\n "level": ${e},\n _originalId,\n prefLabel,\n definition,\n example,\n scopeNote,\n ${$e(e+1)||""}\n }`},Ne=3,Me=W({useWatchTree:function(e){const n="input"===e.mode,t=He({fetch:n?`\n select($branchId != null => \n *[_id == $id][0] {\n _updatedAt,\n "concepts": concepts[$branchId in @->broader[]->.conceptId]->|order(prefLabel) {\n "id": _id,\n "level": 0,\n "isOrphan": true,\n _originalId,\n prefLabel,\n definition,\n example,\n scopeNote,\n ${$e()||""}\n }\n },\n *[_id == $id][0] {\n _updatedAt,\n "topConcepts":topConcepts[]->|order(prefLabel){\n "id": _id,\n "level": 0,\n _originalId,\n prefLabel,\n definition,\n example,\n scopeNote,\n ${$e()||""}\n }, \n "concepts": concepts[]->|order(prefLabel){\n "id": _id,\n "level": 0,\n "isOrphan": \n coalesce(\n !array::intersects(\n broader[]._ref, (\n coalesce(^.concepts[]._ref, []) + coalesce(^.topConcepts[]._ref, [])\n )\n ), \n true),\n _originalId,\n prefLabel,\n definition,\n example,\n scopeNote,\n ${$e()||""}\n }\n }\n )`:`*[_id == $id][0] {\n _updatedAt,\n "topConcepts": topConcepts[]->|order(prefLabel) {\n "id": _id,\n "level": 0,\n _originalId,\n prefLabel,\n definition,\n example,\n scopeNote,\n ${$e()||""}\n },\n "concepts": concepts[]->|order(prefLabel) {\n "id": _id,\n "level": 0,\n "isOrphan": \n coalesce(\n !array::intersects(\n broader[]._ref, (\n coalesce(^.concepts[]._ref, []) + coalesce(^.topConcepts[]._ref, [])\n )\n ),\n true),\n _originalId,\n prefLabel,\n definition,\n example,\n scopeNote,\n ${$e()||""}\n }\n }`,listen:n?'*[_type == "skosConcept" || _id == $id]':'*[_type == "skosConcept" || _type == "skosConceptScheme" ]'},{params:n?{id:e.documentId,branchId:e.branchId}:{id:e.documentId},options:{perspective:void 0===e.perspective?"drafts":[e.perspective]}});return{data:t.data??null,loading:t.loading,error:t.error?t.error:null}},useApplyConceptPlan:function(){const e=i({apiVersion:"2025-02-19"});return K(async n=>{"remove"!==n.kind?await e.transaction().createIfNotExists(n.createIfNotExists).create(n.create).patch(n.schemeId,e=>e.setIfMissing({[n.appendField]:[]}).append(n.appendField,[n.reference])).commit({autoGenerateArrayKeys:!0}):await e.transaction().createIfNotExists(n.createIfNotExists).patch(n.schemeId,e=>e.unset(n.unsetPaths)).commit()},[e])},useSemanticRecommendations:function(e){const n=i({apiVersion:"vX"}),t=J(()=>n.withConfig({perspective:"published"}),[n]),r=o(),[c,s]=Y([]),[d,a]=Y(null);return{conceptRecs:c,recsError:d,triggerSearch:K(n=>{if(a(null),!e||!n)return;const{fieldReferences:i,maxResults:o=Ne}=e;let c;try{c=function(e){const n=[],t=[];for(const{name:i,value:o}of e)"string"==typeof o&&""!==o.trim()?n.push(o):t.push(i);if(1===t.length)throw new Error(`Please fill out the ${t[0]} field to enable match scores.`);if(t.length>1)throw new Error(`The following fields must be filled out to enable match scores: ${t.join(", ")}`);return n.join(" ")}(i.map(e=>({name:e,value:r([e])})))}catch(e){return void a(e instanceof Error?e.message:"One or more required fields are empty")}t.fetch('*[_type == "skosConcept" && _id in *[_type == "skosConceptScheme" && schemeId == $schemeId][0]{\n "ids": coalesce(topConcepts[]._ref, []) + coalesce(concepts[]._ref, [])\n }.ids] | score(text::semanticSimilarity($searchQuery)) | order(_score desc) [0...$maxResults] {\n "conceptId": _id,\n "score": _score\n }',{searchQuery:c,maxResults:o,schemeId:n}).then(e=>s(function(e){if(!e)return[];const n=[];for(const t of e)!t||"string"!=typeof t.conceptId||""===t.conceptId||"number"==typeof t.score&&n.push({conceptId:se(t.conceptId),score:t.score});return n}(e))).catch(e=>{console.error("Error fetching semantic recommendations: ",e),a(function(e){const n=e instanceof Error?e.message:"string"==typeof e?e:"";return/embedding/i.test(n)?"Semantic recommendations aren't enabled for this dataset.":"Unable to load semantic recommendations."}(e))})},[t,r,e])}}});function Pe(){return ee(Me)}const Ee={type:"skosConcept",template:{id:"skosConcept"}};function Re(e){const n=de(e),t=ae(n),i=t?le(n):void 0;return{isInRelease:t,releaseName:i,schemeId:t?pe(n,i):he(n)}}function Ae(e){const n=N(),t=function(){const e=ee(fe),{routerPanesState:n,groupIndex:t}=y();return K(i=>{if(!e||!i)return;const o=[...n];o.splice(t+1,t+1,[{id:i,params:{type:"skosConcept"}}]);const r=e.resolvePathFromState({panes:o});e.navigateUrl({path:r})},[e,n,t])}(),i=Pe().useApplyConceptPlan(),{ident:o}=ee(_e),r=e.displayed.baseIri;return K((c,s)=>{const d=function(e){const n=Re(e.scheme._id),t=function(e,n){const t=de(e);return n.isInRelease?pe(t,n.releaseName):he(t)}(e.newConceptUuid,n),i={_id:t,_type:"skosConcept",conceptId:e.conceptId,prefLabel:"",baseIri:e.schemeBaseIri,broader:[],related:[]};var o;e.broaderConcept&&(i.broader=[{_key:e.broaderKey,_ref:se(de(e.broaderConcept.id)),_type:"reference",...(o=e.broaderConcept._originalId,me(de(o))?{_weak:!1}:{_weak:!0,_strengthenOnPublish:Ee})}]);const r={_ref:se(de(t)),_type:"reference",_key:e.newConceptKey,_strengthenOnPublish:Ee,_weak:!0};return{kind:"create",schemeId:n.schemeId,newConceptId:t,createIfNotExists:{...e.scheme,_id:n.schemeId},create:i,appendField:"topConcept"===e.conceptType?"topConcepts":"concepts",reference:r}}({scheme:e.displayed,conceptType:c,broaderConcept:s?.id?{id:s.id,_originalId:s._originalId??""}:void 0,newConceptUuid:ue(),conceptId:be(o),schemeBaseIri:r,newConceptKey:ue(),broaderKey:ue()});i(d).then(()=>{n.push({closable:!0,status:"success",title:"Created new concept"}),t(d.newConceptId)}).catch(e=>{n.push({closable:!0,status:"error",title:"Error creating concept",description:e instanceof Error?e.message:"Unknown error occurred"})})},[e.displayed,o,r,i,n,t])}function Oe(e){const n=N(),t=Pe().useApplyConceptPlan(),{markRemoved:i,unmarkRemoved:o}=ee(xe);return K((r,c,s)=>{const d=function(e){const n="topConcept"===e.conceptType?"topConcepts":"concepts",{schemeId:t}=Re(e.scheme._id);return{kind:"remove",schemeId:t,createIfNotExists:{...e.scheme,_id:t},unsetPaths:[`${n}[_ref=="${e.conceptRef}"]`]}}({scheme:e.displayed,conceptRef:r,conceptType:c});i(r),t(d).then(()=>{n.push({closable:!0,status:"success",title:(s?`"${s}"`:"Concept")+" removed from scheme"})}).catch(e=>{o(r),n.push({closable:!0,status:"error",title:"Error removing concept",description:e instanceof Error?e.message:"Unknown error occurred"})})},[t,e.displayed,n,i,o])}const De=({title:e,message:n})=>/* @__PURE__ */C(H,{space:2,children:[
|
|
3
|
+
/* @__PURE__ */I(D,{size:1,children:e}),
|
|
4
|
+
/* @__PURE__ */I($,{size:2,muted:!0,style:{whiteSpace:"pre-wrap"},children:n})]}),Ze=({concept:e})=>{const[n,t]=Y(!1),i=K(()=>t(!1),[]),o=K(()=>t(!0),[]);return e&&(e.definition||e.example||e.scopeNote)?/* @__PURE__ */C(w,{children:[
|
|
5
|
+
/* @__PURE__ */I(A,{delay:{open:750},content:/* @__PURE__ */I(E,{padding:1,sizing:"content",children:/* @__PURE__ */I($,{muted:!0,size:1,children:"View concept details"})}),fallbackPlacements:["right","left"],placement:"top",portal:!0,children:/* @__PURE__ */I(M,{icon:_,mode:"bleed",onClick:o,tone:"default"})}),n&&/* @__PURE__ */I(O,{header:e.prefLabel,id:"dialog-example",onClose:i,zOffset:1e3,width:1,children:/* @__PURE__ */I(E,{padding:4,paddingTop:2,paddingBottom:5,children:/* @__PURE__ */C(H,{space:4,children:[e.definition&&/* @__PURE__ */I(De,{title:"Definition",message:e.definition}),e.example&&/* @__PURE__ */I(De,{title:"Examples",message:e.example}),e.scopeNote&&/* @__PURE__ */I(De,{title:"Scope Notes",message:e.scopeNote})]})})})]}):null};function Be({concept:e,topConcept:n=!1,orphan:t=!1}){const i=ee(fe),{routerPanesState:o,groupIndex:r}=y(),{id:c,prefLabel:s}=e??{},d=s||"[new concept]",a=K(()=>{if(!i||!c)return;const e=[...o];e.splice(r+1,r+1,[{id:c,params:{type:"skosConcept"}}]);const n=i.resolvePathFromState({panes:e});i.navigateUrl({path:n})},[c,i,o,r]);/* @__PURE__ */
|
|
6
|
+
return I(A,{delay:{open:750},content:/* @__PURE__ */I(E,{padding:1,sizing:"content",children:/* @__PURE__ */I($,{muted:!0,size:1,children:`View "${s}"`})}),fallbackPlacements:["right","left"],placement:"top",children:/* @__PURE__ */I(M,{mode:"bleed",paddingLeft:0,onClick:a,width:"fill",justify:"flex-start",children:/* @__PURE__ */C($,{size:2,weight:n?"bold":"regular",textOverflow:"ellipsis",children:[d,(n||t)&&/* @__PURE__ */I(Z,{fontSize:0,marginLeft:3,style:{verticalAlign:"middle"},children:n?"top concept":"orphan"})]})})})}const Ue=({action:e,handler:n})=>{const t={add:{message:"Add a child concept below this concept",icon:V,tone:"positive"},remove:{message:"Remove this concept from this scheme",icon:x,tone:"critical"}};/* @__PURE__ */
|
|
7
|
+
return I(A,{delay:{open:750},content:/* @__PURE__ */I(E,{padding:1,sizing:"content",children:/* @__PURE__ */I($,{muted:!0,size:1,children:t[e].message})}),fallbackPlacements:["right","left"],placement:"top",children:/* @__PURE__ */I(M,{icon:t[e].icon,mode:"bleed",onClick:n,tone:t[e].tone,"aria-label":t[e].message})})};function Fe({concept:e,topConcept:n=!1,orphan:t=!1,selectConcept:i}){const{prefLabel:o,id:r,_originalId:c,recommended:s}=e??{},d=o||"[new concept]",a=K(()=>{i&&i({_ref:r,_type:"reference",_originalId:c})},[r,c,i]);/* @__PURE__ */
|
|
8
|
+
return I(w,{children:i&&/* @__PURE__ */I(A,{delay:{open:750},content:/* @__PURE__ */I(E,{padding:1,sizing:"content",children:/* @__PURE__ */C($,{muted:!0,size:1,children:[`Select "${o}"`,s&&" (recommended)"]})}),fallbackPlacements:["right","left","bottom"],placement:"top",portal:!0,children:/* @__PURE__ */I(M,{mode:"bleed",paddingLeft:0,onClick:a,width:"fill",justify:"flex-start",children:/* @__PURE__ */C($,{size:2,weight:n?"bold":"regular",textOverflow:"ellipsis",children:[d,(n||t)&&/* @__PURE__ */I(Z,{fontSize:0,marginLeft:3,style:{verticalAlign:"middle"},children:n?"top concept":"orphan"}),s&&/* @__PURE__ */I(Z,{tone:"positive",fontSize:0,marginLeft:3,style:{verticalAlign:"middle"},children:"recommended"})]})})})})}const je=({message:e,title:n,type:t})=>{const[i,o]=Y(!1),r=K(()=>o(!1),[]),c=K(()=>o(!0),[]);/* @__PURE__ */
|
|
9
|
+
return C(w,{children:[
|
|
10
|
+
/* @__PURE__ */I(A,{delay:{open:750},content:/* @__PURE__ */I(E,{padding:1,sizing:"content",children:/* @__PURE__ */I($,{muted:!0,size:1,children:n})}),fallbackPlacements:["right","left"],placement:"top",portal:!0,children:/* @__PURE__ */I(M,{icon:"error"==t?k:_,mode:"bleed",onClick:c,tone:{info:"default",warn:"caution",error:"critical"}[t]})}),i&&/* @__PURE__ */I(O,{header:n,id:"dialog-example",onClose:r,zOffset:1e3,width:1,children:/* @__PURE__ */I(E,{padding:4,paddingBottom:5,children:/* @__PURE__ */I($,{children:e})})})]})};function qe({handler:e,visibility:n}){/* @__PURE__ */
|
|
11
|
+
return I(M,{icon:T,mode:"bleed","aria-expanded":"open"==n,onClick:e,className:"ToggleButton-module_toggleButton__4X-Gs"})}!function(e,n){void 0===n&&(n={});var t=n.insertAt;if(!(typeof document>"u")){var i=document.head||document.getElementsByTagName("head")[0],o=document.createElement("style");o.type="text/css","top"===t&&i.firstChild?i.insertBefore(o,i.firstChild):i.appendChild(o),o.styleSheet?o.styleSheet.cssText=e:o.appendChild(document.createTextNode(e))}}(".ToggleButton-module_toggleButton__4X-Gs[aria-expanded='true'] svg {\n rotate: 90deg;\n}\n");const Ge=({concept:e,selectConcept:n,inputComponent:t=!1})=>{const i=ee(Ie)||{},o=ee(ve),{globalVisibility:{treeVisibility:r}={treeVisibility:"open"}}=ee(we)||{},c=Ae(i),s=Oe(i),d=K(()=>{c("concept",e)},[e,c]),a=K(()=>{s(e.id,"concept",e?.prefLabel)},[e.id,e?.prefLabel,s]),[l,p]=Y("closed"===r&&e.hasMatchingDescendant?"open":r||"open"),h=K(()=>{"open"==l?p("closed"):"closed"==l&&p("open")},[l]);/* @__PURE__ */
|
|
12
|
+
return C(E,{className:l,children:[
|
|
13
|
+
/* @__PURE__ */C(R,{align:"center",justify:"space-between",wrap:"nowrap",children:[
|
|
14
|
+
/* @__PURE__ */C(R,{align:"center",gap:0,flex:1,style:{minWidth:0},children:[e?.childConcepts&&e.childConcepts.length>0&&/* @__PURE__ */I(qe,{handler:h,visibility:l}),!e?.prefLabel&&/* @__PURE__ */I(E,{flex:1,marginLeft:e?.childConcepts&&0!=e.childConcepts.length?0:5,children:/* @__PURE__ */I(Be,{concept:e})}),e?.prefLabel&&/* @__PURE__ */I(E,{flex:1,marginLeft:e?.childConcepts&&0!=e.childConcepts.length?0:5,children:t?/* @__PURE__ */I(Fe,{concept:e,selectConcept:n}):/* @__PURE__ */I(Be,{concept:e})})]}),t&&/* @__PURE__ */I(Ze,{concept:e}),!t&&"published"!==o&&e?.level&&e.level<5&&/* @__PURE__ */C(B,{children:[
|
|
15
|
+
/* @__PURE__ */I(Ue,{action:"add",handler:d}),
|
|
16
|
+
/* @__PURE__ */I(Ue,{action:"remove",handler:a})]}),!t&&"published"!==o&&0==e.childConcepts?.length&&5==e.level&&/* @__PURE__ */C(B,{children:[
|
|
17
|
+
/* @__PURE__ */I(je,{type:"warn",title:"Taxonomy Manager structure notice",message:"This concept is at the maximum Taxonomy Manager hierarchy depth of 5 levels. Additional child terms are not shown in the hierarchy tree."}),
|
|
18
|
+
/* @__PURE__ */I(Ue,{action:"remove",handler:a})]}),e?.childConcepts&&e?.childConcepts?.length>0&&5==e.level&&/* @__PURE__ */C(B,{children:[
|
|
19
|
+
/* @__PURE__ */I(je,{type:"error",title:"Taxonomy Manager structure warning",message:"This concept has unlisted child concepts. The maximum validated hierarchy depth is 5 levels."}),!t&&"published"!==o&&/* @__PURE__ */I(Ue,{action:"remove",handler:a})]})]}),e?.childConcepts&&e.childConcepts.length>0&&e?.level&&e.level<5&&/* @__PURE__ */I(Ke,{concepts:e.childConcepts,selectConcept:n,inputComponent:t,childVisibility:l})]})},Ke=({concepts:e,inputComponent:n=!1,selectConcept:t,childVisibility:i})=>
|
|
20
|
+
/* @__PURE__ */I(E,{marginLeft:4,marginTop:2,display:"closed"==i?"none":"block",children:/* @__PURE__ */I(H,{space:3,children:e.map(e=>/* @__PURE__ */I(Ge,{concept:e,selectConcept:t,inputComponent:n},e.id))})}),We=({concept:e,treeVisibility:n,inputComponent:t,selectConcept:i})=>{const o=ee(Ie)||{},r=ee(ve),c=!!o.displayed?.topConcepts?.length&&!t,s=Ae(o),d=Oe(o),[a,l]=Y("closed"===n&&e.hasMatchingDescendant?"open":n),p=K(()=>{"open"==a?l("closed"):"closed"==a&&l("open")},[a]),h=K(()=>{s("concept",e)},[e,s]),m=K(()=>{d(e.id,"concept",e?.prefLabel)},[e.id,e?.prefLabel,d]);/* @__PURE__ */
|
|
21
|
+
return C(E,{className:a,children:[
|
|
22
|
+
/* @__PURE__ */C(R,{align:"center",justify:"space-between",wrap:"nowrap",children:[
|
|
23
|
+
/* @__PURE__ */C(R,{align:"center",gap:0,flex:1,style:{minWidth:0},children:[e?.childConcepts&&e.childConcepts.length>0&&/* @__PURE__ */I(qe,{handler:p,visibility:a}),!e?.prefLabel&&/* @__PURE__ */I(E,{flex:1,marginLeft:e?.childConcepts&&0!=e.childConcepts.length?0:5,children:/* @__PURE__ */I(Be,{concept:e,orphan:c})}),e?.prefLabel&&/* @__PURE__ */I(E,{flex:1,marginLeft:e?.childConcepts&&0!=e.childConcepts.length?0:5,children:t?/* @__PURE__ */I(Fe,{concept:e,selectConcept:i,orphan:c}):/* @__PURE__ */I(Be,{concept:e,orphan:c})})]}),t&&/* @__PURE__ */I(Ze,{concept:e}),!t&&"published"!==r&&/* @__PURE__ */C(B,{children:[
|
|
24
|
+
/* @__PURE__ */I(Ue,{action:"add",handler:h}),
|
|
25
|
+
/* @__PURE__ */I(Ue,{action:"remove",handler:m})]})]}),e?.childConcepts&&e.childConcepts.length>0&&/* @__PURE__ */I(Ke,{concepts:e.childConcepts,selectConcept:i,inputComponent:t,childVisibility:a})]})},Ye=({document:e})=>{const[n,t]=Y(!1),[o,r]=Y(""),[c,s]=Y(""),d=K(()=>t(!1),[]),a=K(()=>t(!0),[]),l=K(e=>{r(e.currentTarget.value)},[]),p=K(e=>{s(e.currentTarget.value)},[]),h=function(){const e=N(),n=i({apiVersion:"2021-10-21"});return K((t,i,o)=>{const r=t.displayed?._id,c=t.displayed?.baseIri,s=t.displayed?.schemeId,d={_id:`drafts.${r}`,_type:"skosConceptScheme",schemeId:s,baseIri:c,title:i,description:o||""};n.createIfNotExists(d).then(n=>o?e.push({closable:!0,status:"success",title:"Title and Description added."}):e.push({closable:!0,status:"success",title:"Title added."})).catch(n=>{e.push({closable:!0,status:"error",title:"There has been an error",description:n.message})})},[n,e])}(),m=K(()=>{h(e,o,c)},[h,c,e,o]);/* @__PURE__ */
|
|
26
|
+
return C("div",{style:{marginTop:"2rem"},children:[
|
|
27
|
+
/* @__PURE__ */I(P,{padding:[3,3,4],radius:2,shadow:1,tone:"primary",children:/* @__PURE__ */C(H,{space:6,children:[
|
|
28
|
+
/* @__PURE__ */C(H,{space:4,children:[
|
|
29
|
+
/* @__PURE__ */I(D,{size:4,children:"New Concept Scheme"}),
|
|
30
|
+
/* @__PURE__ */I($,{size:2,children:'To start using hierarchy view taxonomy builder, first give your concept scheme a name and optional description. You can also use the "Editor" tab to add concepts to the tree manually.'})]}),
|
|
31
|
+
/* @__PURE__ */I(M,{tone:"primary",fontSize:2,icon:z,onClick:a,text:"Add Title"})]})}),n&&/* @__PURE__ */I(O,{header:"Title & Description",id:"title-description",onClose:d,zOffset:1e3,width:1,children:/* @__PURE__ */I(E,{padding:4,children:/* @__PURE__ */C(H,{space:4,children:[
|
|
32
|
+
/* @__PURE__ */C(H,{space:2,children:[
|
|
33
|
+
/* @__PURE__ */I(D,{size:1,children:"Title"}),
|
|
34
|
+
/* @__PURE__ */I($,{size:1,muted:!0,children:"Describe the concept scheme in one or two words."})]}),
|
|
35
|
+
/* @__PURE__ */I(U,{fontSize:2,onChange:l,padding:3,placeholder:"",value:o}),
|
|
36
|
+
/* @__PURE__ */C(H,{space:2,children:[
|
|
37
|
+
/* @__PURE__ */I(D,{size:1,children:"Description (optional)"}),
|
|
38
|
+
/* @__PURE__ */I($,{size:1,muted:!0,children:"Describe the intended use of this concept scheme."})]}),
|
|
39
|
+
/* @__PURE__ */I(F,{fontSize:2,onChange:p,padding:3,placeholder:"",value:c,rows:3}),
|
|
40
|
+
/* @__PURE__ */I(M,{tone:"primary",fontSize:2,onClick:m,text:"Save"})]})})})]})},Xe=()=>/* @__PURE__ */I("div",{style:{marginTop:"2rem"},children:/* @__PURE__ */I(P,{padding:[3,3,4],radius:2,shadow:1,tone:"primary",children:/* @__PURE__ */C(H,{space:4,children:[
|
|
41
|
+
/* @__PURE__ */I(D,{size:4,children:"No Concepts"}),
|
|
42
|
+
/* @__PURE__ */I($,{size:2,children:"There are not yet any concepts assigned to this scheme. To create a multi-level hierarchy with specific entry points, create Top Concepts first, then add child concepts to them. To create a flat list of concepts, create Concepts directly."})]})})}),Qe=({concept:e,treeVisibility:n,inputComponent:t,selectConcept:i})=>{const o=ee(Ie)||{},r=ee(ve),c=Ae(o),s=Oe(o),[d,a]=Y("closed"===n&&e.hasMatchingDescendant?"open":n),l=K(()=>{"open"==d?a("closed"):"closed"==d&&a("open")},[d]),p=K(()=>{c("concept",e)},[e,c]),h=K(()=>{s(e?.id,"topConcept",e?.prefLabel)},[e?.id,e?.prefLabel,s]);/* @__PURE__ */
|
|
43
|
+
return C(E,{className:d,children:[
|
|
44
|
+
/* @__PURE__ */C(R,{align:"center",justify:"space-between",wrap:"nowrap",children:[
|
|
45
|
+
/* @__PURE__ */C(R,{align:"center",gap:0,flex:1,style:{minWidth:0},children:[e?.childConcepts&&e.childConcepts.length>0&&/* @__PURE__ */I(qe,{handler:l,visibility:d}),!e?.prefLabel&&/* @__PURE__ */I(E,{flex:1,marginLeft:e?.childConcepts&&0!=e.childConcepts.length?0:5,children:/* @__PURE__ */I(Be,{concept:e,topConcept:!0})}),e?.prefLabel&&/* @__PURE__ */I(E,{flex:1,marginLeft:e?.childConcepts&&0!=e.childConcepts.length?0:5,children:t?/* @__PURE__ */I(Fe,{concept:e,selectConcept:i,topConcept:!0}):/* @__PURE__ */I(Be,{concept:e,topConcept:!0})})]}),t&&/* @__PURE__ */I(Ze,{concept:e}),!t&&"published"!==r&&/* @__PURE__ */C(B,{children:[
|
|
46
|
+
/* @__PURE__ */I(Ue,{action:"add",handler:p}),
|
|
47
|
+
/* @__PURE__ */I(Ue,{action:"remove",handler:h})]})]}),e?.childConcepts&&e.childConcepts.length>0&&/* @__PURE__ */I(Ke,{concepts:e.childConcepts,selectConcept:i,inputComponent:t,childVisibility:d})]})},Je=({concepts:e,inputComponent:n,selectConcept:t})=>{const{globalVisibility:{treeId:i,treeVisibility:o}={treeId:"default",treeVisibility:"open"}}=ee(we)||{};return e?.topConcepts?.length||e?.concepts?.length?/* @__PURE__ */I(E,{paddingTop:4,children:/* @__PURE__ */C(H,{space:3,style:{listStyle:"none",paddingLeft:"0",marginBlockStart:"0"},children:[e?.topConcepts?.map(e=>/* @__PURE__ */I(Qe,{concept:e,treeVisibility:o,inputComponent:n,selectConcept:t},`${e?.id}+${i}`)),e?.concepts?.filter(e=>e?.isOrphan).map(e=>/* @__PURE__ */I(We,{concept:e,treeVisibility:o,inputComponent:n,selectConcept:t},`${e.id}+${i}`))]})}):/* @__PURE__ */I(Xe,{})},en=({branchId:e="",selectConcept:n,inputComponent:t,expanded:i,conceptRecs:o,recsError:r})=>{const c=ee(Ie)||{},s=se(c.displayed?._id),d=ee(ve),a=i?"open":"closed",l=Pe(),{data:p,loading:h,error:m}=l.useWatchTree({mode:"input",documentId:s,branchId:e,perspective:d}),u=J(()=>new Set((o??[]).map(e=>e.conceptId)),[o]),f=J(()=>te(6),[u]),g=J(()=>!p||0===u.size||r?p:{topConcepts:p.topConcepts?.map(e=>Ve(e,u)),concepts:p.concepts?.map(e=>Ve(e,u))},[p,u,r]);return h?/* @__PURE__ */I(E,{padding:5,children:/* @__PURE__ */C(R,{align:"center",direction:"column",gap:5,height:"fill",justify:"center",style:{paddingTop:"1rem"},children:[
|
|
48
|
+
/* @__PURE__ */I(j,{muted:!0}),
|
|
49
|
+
/* @__PURE__ */I($,{muted:!0,size:1,children:"Loading hierarchy…"})]})}):m?(console.warn(m),/* @__PURE__ */I(E,{padding:4,children:/* @__PURE__ */I(P,{padding:[3],radius:2,shadow:1,tone:"caution",children:/* @__PURE__ */I($,{size:1,children:"There was a problem loading terms. Please check the scheme configuration and try again."})})})):p?/* @__PURE__ */I(we.Provider,{value:{globalVisibility:{treeId:f,treeVisibility:a}},children:/* @__PURE__ */C(E,{padding:4,paddingTop:0,children:[r&&/* @__PURE__ */I(P,{marginTop:2,padding:3,radius:2,shadow:1,tone:"caution",children:/* @__PURE__ */I($,{size:2,children:r})}),
|
|
50
|
+
/* @__PURE__ */I(Je,{concepts:g,inputComponent:t||!1,selectConcept:n||(()=>{})})]})}):/* @__PURE__ */I(E,{padding:4,children:/* @__PURE__ */I(P,{padding:[3],radius:2,shadow:1,tone:"caution",children:/* @__PURE__ */I($,{size:1,children:"This configuration does not have any terms associated with it. Please check the scheme and branch supplied and try again."})})})};function nn(){/* @__PURE__ */
|
|
51
|
+
return I("svg",{"data-sanity-icon":!0,width:"25",height:"25",viewBox:"0 0 25 25",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:/* @__PURE__ */I("path",{d:"M5.5 6.5V5.9H4.9V6.5H5.5ZM11.5 6.5H12.1V5.9H11.5V6.5ZM5.5 9H4.9V9.6H5.5V9ZM11.5 9V9.6H12.1V9H11.5ZM13.5 11V10.4H12.9V11H13.5ZM19.5 11H20.1V10.4H19.5V11ZM13.5 13.5H12.9V14.1H13.5V13.5ZM19.5 13.5V14.1H20.1V13.5H19.5ZM13.5 16V15.4H12.9V16H13.5ZM19.5 16H20.1V15.4H19.5V16ZM13.5 18.5H12.9V19.1H13.5V18.5ZM19.5 18.5V19.1H20.1V18.5H19.5ZM5.5 7.1H11.5V5.9H5.5V7.1ZM6.1 9V6.5H4.9V9H6.1ZM11.5 8.4H5.5V9.6H11.5V8.4ZM10.9 6.5V9H12.1V6.5H10.9ZM13.5 11.6H19.5V10.4H13.5V11.6ZM14.1 13.5V11H12.9V13.5H14.1ZM19.5 12.9H13.5V14.1H19.5V12.9ZM18.9 11V13.5H20.1V11H18.9ZM13.5 16.6H19.5V15.4H13.5V16.6ZM14.1 18.5V16H12.9V18.5H14.1ZM19.5 17.9H13.5V19.1H19.5V17.9ZM18.9 16V18.5H20.1V16H18.9ZM8 17.85H13.5V16.65H8V17.85ZM8 12.85H13.5V11.65H8V12.85ZM7.9 9.5V17.85H9.1V9.5H7.9Z",fill:"currentColor"})})}function tn(e,n){return e.filter(e=>!n.has(e.id)).map(e=>e.childConcepts?{...e,childConcepts:tn(e.childConcepts,n)}:e)}const on=({inputComponent:e=!1,selectConcept:n})=>{const t=ee(Ie)||{},i=se(t.displayed?._id),o=ee(ve),r=Pe(),c=Ae(t),s=K(()=>{c("topConcept")},[c]),d=K(()=>{c("concept")},[c]),[a,l]=Y({treeId:te(6),treeVisibility:"open"}),p=K(()=>{l({treeId:te(6),treeVisibility:"open"})},[]),h=K(()=>{l({treeId:te(6),treeVisibility:"closed"})},[]),[m,u]=Y(()=>/* @__PURE__ */new Set),f=K(e=>{u(n=>{if(n.has(e))return n;const t=new Set(n);return t.add(e),t})},[]),g=K(e=>{u(n=>{if(!n.has(e))return n;const t=new Set(n);return t.delete(e),t})},[]),y=J(()=>({markRemoved:f,unmarkRemoved:g}),[f,g]),{data:b,loading:v,error:_}=r.useWatchTree({mode:"trunk",documentId:i,perspective:o});Q(()=>{u(e=>{if(0===e.size)return e;const n=function(e){const n=/* @__PURE__ */new Set,t=e=>{if(e)for(const i of e)n.add(i.id),t(i.childConcepts)};return e&&(t(e.topConcepts),t(e.concepts)),n}(b),t=new Set([...e].filter(e=>n.has(e)));return t.size===e.size?e:t})},[b]);const x=J(()=>function(e,n){return e&&0!==n.size?{...e,topConcepts:(e.topConcepts??[]).filter(e=>!n.has(e.id)).map(e=>e.childConcepts?{...e,childConcepts:tn(e.childConcepts,n)}:e),concepts:(e.concepts??[]).filter(e=>!n.has(e.id)).map(e=>e.childConcepts?{...e,childConcepts:tn(e.childConcepts,n)}:e)}:e}(b,m),[b,m]);return v?/* @__PURE__ */I(E,{padding:4,paddingTop:6,children:/* @__PURE__ */C(R,{align:"center",direction:"column",gap:5,height:"fill",justify:"center",children:[
|
|
52
|
+
/* @__PURE__ */I(j,{muted:!0}),
|
|
53
|
+
/* @__PURE__ */I($,{muted:!0,size:1,children:"Loading hierarchy…"})]})}):_?(console.error(_),/* @__PURE__ */I("div",{children:"Error here"})):x?/* @__PURE__ */I(we.Provider,{value:{globalVisibility:a},children:/* @__PURE__ */I(E,{padding:4,children:/* @__PURE__ */C(w,{children:[
|
|
54
|
+
/* @__PURE__ */I(H,{space:4,children:/* @__PURE__ */I(P,{borderBottom:!0,paddingBottom:1,display:"flex",flex:1,children:/* @__PURE__ */C(R,{justify:"space-between",flex:1,children:[
|
|
55
|
+
/* @__PURE__ */I(P,{children:(x.topConcepts?.filter(e=>(e?.childConcepts?.length??0)>0).length>0||x.concepts?.filter(e=>(e?.childConcepts?.length??0)>0).length>0)&&/* @__PURE__ */C(B,{space:1,children:[
|
|
56
|
+
/* @__PURE__ */I(M,{text:"Collapse",paddingY:2,mode:"bleed",onClick:h}),
|
|
57
|
+
/* @__PURE__ */I($,{weight:"semibold",muted:!0,size:1,children:"|"}),
|
|
58
|
+
/* @__PURE__ */I(M,{text:"Expand",paddingY:2,mode:"bleed",onClick:p})]})}),
|
|
59
|
+
/* @__PURE__ */I(P,{children:"published"!==o&&/* @__PURE__ */C(B,{space:1,children:[
|
|
60
|
+
/* @__PURE__ */I(M,{text:"Add Top Concept",icon:V,mode:"bleed",tone:"positive",paddingY:2,onClick:s}),
|
|
61
|
+
/* @__PURE__ */I(M,{text:"Add Concept",icon:V,mode:"bleed",tone:"positive",paddingY:2,onClick:d})]})})]})})}),
|
|
62
|
+
/* @__PURE__ */I(xe.Provider,{value:y,children:/* @__PURE__ */I(Je,{concepts:x,inputComponent:e,selectConcept:n||(()=>{})})})]})})}):/* @__PURE__ */I(Ye,{document:t})},rn=({document:e,branchId:n,inputComponent:t=!1,selectConcept:i,expanded:o,conceptRecs:c,recsError:s})=>{const{selectedPerspectiveName:d}=r();/* @__PURE__ */
|
|
63
|
+
return I(Ie.Provider,{value:e||{},children:/* @__PURE__ */I(ve.Provider,{value:d,children:t?/* @__PURE__ */I(en,{inputComponent:t,branchId:n,selectConcept:i,expanded:o,conceptRecs:c,recsError:s}):/* @__PURE__ */C(q,{width:1,children:[e?.displayed?.description&&/* @__PURE__ */I(E,{padding:4,paddingTop:6,children:/* @__PURE__ */I(H,{space:4,children:/* @__PURE__ */C(H,{space:2,children:[
|
|
64
|
+
/* @__PURE__ */I($,{size:1,weight:"semibold",children:"Description"}),
|
|
65
|
+
/* @__PURE__ */I($,{size:2,muted:!0,children:e?.displayed.description})]})})}),
|
|
66
|
+
/* @__PURE__ */I(on,{inputComponent:t,branchId:n})]})})})};function cn(n){const t=i({apiVersion:"vX"}),o=e(["_id"]),{name:d,title:a,value:l,semanticSearch:p}=n,h=Pe(),{conceptRecs:m,recsError:u,triggerSearch:f}=h.useSemanticRecommendations(p),g=ae(o),y=c(o),{selectedPerspectiveName:b}=r(),[w,v]=Y(!0),[_,x]=Y(!0),[V,k]=Y(!1),[T,z]=Y(void 0),[L,S]=Y(),{schemeId:N,branchId:A=null}=L?.params||{},{filter:D}=n.schemaType.options;Q(()=>{(async function(){try{const e=await D({getClient:()=>t});S(e),x(!1)}catch(e){console.error("Error fetching filter values: ",e)}})().catch(e=>console.error("Error fetching filter values: ",e))},[D,t]),Q(()=>{N&&t.fetch('{"displayed": *[schemeId == $schemeId][0]}',{schemeId:N}).then(e=>{e?.displayed&&(z(e),v(!1))}).catch(e=>console.warn(e))},[t,N]);const Z=K(()=>{k(!0),f(N)},[f,N]),B=K(()=>{k(!1)},[]),U=K(e=>{(c(e?._originalId)||ae(e?._originalId))&&(e._strengthenOnPublish={type:"skosConcept",template:{id:"skosConcept"}},e._weak=!0),delete e._originalId,y||g?t.patch(o).set({[d]:e}).commit().then(()=>k(!1)).catch(e=>console.error(e)):t.fetch("*[_id == $id][0]",{id:o}).then(n=>{n._id=`drafts.${n._id}`,n[d]=e,t.create(n).catch(e=>console.error("Error creating draft: ",e))}).then(()=>k(!1)).catch(e=>console.error(e))},[t,o,y,g,d]);if(!n.schemaType.options?.filter)/* @__PURE__ */return C(H,{space:3,children:[n.renderDefault(n),
|
|
67
|
+
/* @__PURE__ */I(E,{padding:4,children:/* @__PURE__ */I(P,{padding:[3],radius:2,shadow:1,tone:"caution",children:/* @__PURE__ */C($,{size:1,children:["The ",
|
|
68
|
+
/* @__PURE__ */I("code",{children:"ReferenceHierarchyInput()"})," component must be used with an accompanying"," ",
|
|
69
|
+
/* @__PURE__ */I("code",{children:"schemeFilter()"})," or ",
|
|
70
|
+
/* @__PURE__ */I("code",{children:"branchFilter()"}),". Please add an appropriate filter to the configuration for the ",a," field."]})})})]});if(0===n.schemaType.options?.filter.length)/* @__PURE__ */
|
|
71
|
+
return C(H,{space:3,children:[n.renderDefault(n),
|
|
72
|
+
/* @__PURE__ */I(E,{padding:4,children:/* @__PURE__ */I(P,{padding:[3],radius:2,shadow:1,tone:"caution",children:/* @__PURE__ */C($,{size:1,children:["There was a problem loading your filter settings. Please check the"," ",
|
|
73
|
+
/* @__PURE__ */I("code",{children:"schemeFilter()"})," or ",
|
|
74
|
+
/* @__PURE__ */I("code",{children:"branchFilter()"})," configuration for the"," ",a," field."]})})})]});if(w||_)/* @__PURE__ */
|
|
75
|
+
return I(E,{padding:5,children:/* @__PURE__ */C(R,{align:"center",direction:"column",gap:5,height:"fill",justify:"center",style:{paddingTop:"1rem"},children:[
|
|
76
|
+
/* @__PURE__ */I(j,{muted:!0}),
|
|
77
|
+
/* @__PURE__ */I($,{muted:!0,size:1,children:"Loading input component…"})]})});const F="published"===b;/* @__PURE__ */
|
|
78
|
+
return C(H,{space:4,children:[L?.browseOnly?l?n.renderDefault(n):/* @__PURE__ */I(s,{title:a,path:n.path,description:n.description,level:n.level,validation:n.validation,__unstable_presence:n.presence,children:/* @__PURE__ */I(P,{padding:3,radius:2,border:!0,children:/* @__PURE__ */I($,{muted:!0,align:"center",size:1,children:"No items"})})}):n.renderDefault(n),
|
|
79
|
+
/* @__PURE__ */I(G,{columns:1,gap:3,children:/* @__PURE__ */I(M,{disabled:F,icon:nn,text:"Browse taxonomy tree",mode:"ghost",onClick:Z})}),V&&T&&/* @__PURE__ */I(O,{header:a,id:"concept-select-dialog",onClose:B,zOffset:900,width:1,children:/* @__PURE__ */I(E,{padding:10,children:/* @__PURE__ */I(rn,{document:T,branchId:A,inputComponent:!0,selectConcept:U,expanded:L?.expanded,conceptRecs:m,recsError:u})})})]})}function sn(n){const t=i({apiVersion:"2025-02-19"}),o=e(["_id"]),{name:a,title:l,value:p=[],semanticSearch:h}=n,m=d(o),u=c(o),{selectedPerspectiveName:f}=r(),[g,y]=Y(!0),[b,w]=Y(!0),[v,_]=Y(!1),[x,V]=Y({}),[k,T]=Y(),{schemeId:z,branchId:L=null}=k?.params||{},{filter:S}=n.schemaType.of[0].options,A=Pe(),{conceptRecs:Z,recsError:B,triggerSearch:U}=A.useSemanticRecommendations(h),F=N();Q(()=>{(async function(){try{const e=await S({getClient:()=>t});T(e),w(!1)}catch(e){console.error("Error fetching filter values: ",e)}})().catch(e=>console.error("Error fetching filter values: ",e))},[S,t]),Q(()=>{z&&t.fetch(`{"displayed": *[schemeId == "${z}"][0]}`).then(e=>{e?.displayed&&(V(e),y(!1))}).catch(e=>console.warn(e))},[t,z]);const q=K(()=>{_(!0),U(z)},[U,z]),W=K(()=>{_(!1)},[]),X=K(e=>{if((c(e?._originalId)||d(e?._originalId))&&(e._strengthenOnPublish={type:"skosConcept",template:{id:"skosConcept"}},e._weak=!0),delete e._originalId,p?.map(e=>e._ref).includes(e._ref))return _(!1),void F.push({status:"warning",title:"Taxonomy Term Not Added",description:"The selected concept is already included in this field.",duration:5e3,closable:!0});u||m?t.patch(o).setIfMissing({[a]:[]}).append(a,[e]).commit({autoGenerateArrayKeys:!0}).then(()=>_(!1)).catch(e=>console.error(e)):t.fetch(`*[_id == "${o}"][0]`).then(e=>{e._id=`drafts.${e._id}`,t.create(e).catch(e=>console.error("Error creating draft: ",e))}).then(()=>{t.patch(`drafts.${o}`).setIfMissing({[a]:[]}).append(a,[e]).commit({autoGenerateArrayKeys:!0}).then(()=>_(!1)).catch(e=>console.error(e))}).catch(e=>console.error(e))},[p,u,m,t,o,F,a]);if(!n.schemaType.of[0].options?.filter)/* @__PURE__ */return C(H,{space:3,children:[n.renderDefault(n),
|
|
80
|
+
/* @__PURE__ */I(E,{padding:4,children:/* @__PURE__ */I(P,{padding:[3],radius:2,shadow:1,tone:"caution",children:/* @__PURE__ */C($,{size:1,children:["The ",
|
|
81
|
+
/* @__PURE__ */I("code",{children:"ArrayHierarchyInput()"})," component must be used with an accompanying"," ",
|
|
82
|
+
/* @__PURE__ */I("code",{children:"schemeFilter()"})," or ",
|
|
83
|
+
/* @__PURE__ */I("code",{children:"branchFilter()"}),". Please add an appropriate filter to the configuration for the ",l," field."]})})})]});if(0===n.schemaType.of[0].options?.filter?.length)/* @__PURE__ */
|
|
84
|
+
return C(H,{space:3,children:[n.renderDefault(n),
|
|
85
|
+
/* @__PURE__ */I(E,{padding:4,children:/* @__PURE__ */I(P,{padding:[3],radius:2,shadow:1,tone:"caution",children:/* @__PURE__ */C($,{size:1,children:["There was a problem loading your filter settings. Please check the"," ",
|
|
86
|
+
/* @__PURE__ */I("code",{children:"schemeFilter()"})," or ",
|
|
87
|
+
/* @__PURE__ */I("code",{children:"branchFilter()"})," configuration for the"," ",l," field."]})})})]});if(n.schemaType.of.length>1)/* @__PURE__ */
|
|
88
|
+
return C(H,{space:3,children:[n.renderDefault(n),
|
|
89
|
+
/* @__PURE__ */I(P,{padding:[3],radius:2,shadow:1,tone:"caution",children:/* @__PURE__ */I(H,{space:4,children:/* @__PURE__ */C(H,{space:2,children:[
|
|
90
|
+
/* @__PURE__ */I(D,{size:2,children:"Input Component Not Supported for Multi-Schema Arrays"}),
|
|
91
|
+
/* @__PURE__ */C($,{size:1,children:["The Sanity Taxonomy Manager Hierarchy Input Component is not designed to support array inputs with more than one schema type. Please see the"," ",
|
|
92
|
+
/* @__PURE__ */I("a",{href:"https://sanitytaxonomymanager.com",children:"Taxonomy Manager docs"})," for more information."]})]})})})]});if(g||b)/* @__PURE__ */
|
|
93
|
+
return I(E,{padding:5,children:/* @__PURE__ */C(R,{align:"center",direction:"column",gap:5,height:"fill",justify:"center",style:{paddingTop:"1rem"},children:[
|
|
94
|
+
/* @__PURE__ */I(j,{muted:!0}),
|
|
95
|
+
/* @__PURE__ */I($,{muted:!0,size:1,children:"Loading input component…"})]})});const J="published"===f;/* @__PURE__ */
|
|
96
|
+
return C(H,{space:3,children:[k?.browseOnly?p.length>0?n.renderDefault(n):/* @__PURE__ */I(s,{title:l,path:n.path,description:n.description,level:n.level,validation:n.validation,__unstable_presence:n.presence,children:/* @__PURE__ */I(P,{padding:3,radius:2,border:!0,children:/* @__PURE__ */I($,{muted:!0,align:"center",size:1,children:"No items"})})}):n.renderDefault(n),
|
|
97
|
+
/* @__PURE__ */I(G,{columns:1,gap:3,children:/* @__PURE__ */I(M,{disabled:J,icon:nn,text:"Browse taxonomy tree",mode:"ghost",onClick:q})}),v&&/* @__PURE__ */I(O,{header:l,id:"concept-select-dialog",onClose:W,zOffset:900,width:1,children:/* @__PURE__ */I(E,{children:/* @__PURE__ */I(rn,{document:x,branchId:L,inputComponent:!0,selectConcept:X,expanded:k?.expanded,conceptRecs:Z,recsError:B})})})]})}const dn=e=>{const{onChange:n}=e,t=N(),i=K(()=>{n(a()),t.push({status:"success",title:"Value removed.",duration:2500,closable:!0})},[n,t]);/* @__PURE__ */
|
|
98
|
+
return I(H,{space:2,children:/* @__PURE__ */C(B,{space:[3,3,4],children:[e.renderDefault(e),
|
|
99
|
+
/* @__PURE__ */I(M,{tone:"primary",fontSize:2,onClick:i,text:"Remove Value"})]})})};function an(e){if(!e||"string"!=typeof e)throw new Error("Invalid or missing schemeId: scheme Id must be a string")}const ln=e=>{const{schemeId:n}=e||{};return an(n),async t=>{const i=t?.getClient({apiVersion:"2025-02-19"});if(!i)throw new Error("Client not available");const{concepts:o,topConcepts:r}=await i.fetch(`{\n "concepts": *[_type=="skosConceptScheme" && schemeId == "${n}"].concepts[]._ref,\n "topConcepts": *[_type=="skosConceptScheme" && schemeId == "${n}"].topConcepts[]._ref\n }`);return function(e){const{schemeId:n,concepts:t,topConcepts:i,expanded:o,browseOnly:r}=e;return{filter:"(_id in $concepts\n || _id in $topConcepts)",params:{concepts:t,topConcepts:i,schemeId:n},expanded:o,browseOnly:r}}({schemeId:n,concepts:o,topConcepts:r,expanded:e?.expanded,browseOnly:e?.browseOnly})}},pn=e=>{const{schemeId:n,branchId:t=null}=e||{};return an(n),function(e){if(!e||"string"!=typeof e)throw new Error("Invalid or missing branchId: branch Id must be a string")}(t),async i=>{const o=i?.getClient({apiVersion:"2023-01-01"});if(!o)throw new Error("Client not available");const{concepts:r}=await o.fetch('{ \n "concepts": *[\n _id in *[_type=="skosConceptScheme" && schemeId == $schemeId].concepts[]._ref\n && ($branchId in broader[]->conceptId\n || $branchId in broader[]->broader[]->conceptId\n || $branchId in broader[]->broader[]->broader[]->conceptId\n || $branchId in broader[]->broader[]->broader[]->broader[]->conceptId\n || $branchId in broader[]->broader[]->broader[]->broader[]->broader[]->conceptId)\n ]._id\n }',{schemeId:n,branchId:t});return function(e){const{schemeId:n,branchId:t,concepts:i,expanded:o,browseOnly:r}=e;return{filter:"_id in $concepts",params:{concepts:i,schemeId:n,branchId:t},expanded:o,browseOnly:r}}({schemeId:n,branchId:t,concepts:r,expanded:e?.expanded,browseOnly:e?.browseOnly})}};function hn({document:e}){return{filter:"!(_id in $broader || _id in $related || _id == $self)",params:{self:se(de(e._id)),broader:Array.isArray(e?.broader)?e.broader.map(({_ref:e})=>e):[],related:Array.isArray(e?.related)?e.related.map(({_ref:e})=>e):[]}}}var mn=[l({name:"baseIri",title:"Base URI",type:"url",validation:e=>e.required().error("Please supply a base URI in the format 'http://example.com/'"),description:"The root URI (Uniform Resource Identifier) used to create unique concept identifiers.",components:{input:function(n){const t=e(["conceptId"]),i=e(["schemeId"]);/* @__PURE__ */
|
|
100
|
+
return C(H,{space:2,children:[n.renderDefault(n),
|
|
101
|
+
/* @__PURE__ */I($,{muted:!0,size:1,children:/* @__PURE__ */C(w,{children:[
|
|
102
|
+
/* @__PURE__ */I("strong",{children:"RDF URI: "}),n.value?n.value:"[base URI not defined] ",t||i||" [identifier not assigned]"]})})]})}}})];function un(e,n=[],t){return p({name:"skosConcept",title:"Concept",type:"document",icon:ge,initialValue:async(n,t)=>{if(e)return{baseIri:e,broader:[],related:[]};const{getClient:i}=t;return{baseIri:await i({apiVersion:"2021-03-25"}).fetch("\n *[(_type == 'skosConcept' || _type == 'skosConceptScheme') && defined(baseIri)]| order(_createdAt desc)[0].baseIri\n ")??void 0,broader:[],related:[]}},fields:[l({name:"prefLabel",title:"Preferred Label",type:"string",description:"The preferred lexical label for this concept.",validation:e=>e.required().custom((e,n)=>{const{getClient:t}=n;return t({apiVersion:"2025-06-10"}).withConfig({perspective:"raw"}).fetch(`*[_type == "skosConcept" && prefLabel == "${e}" && !(_id in path("drafts.**") || _id in path("versions.**"))][0]._id`).then(e=>{return t=e,i=n.document?._id,!(t&&!i?.includes(t))||"Preferred Label must be unique.";var t,i})})}),l({name:"definition",title:"Definition",type:"text",description:"A complete explanation of the intended meaning of the concept.",rows:3}),l({name:"example",title:"Examples",type:"text",description:"An example of the use of the concept.",rows:3}),l({name:"scopeNote",title:"Scope Note",type:"text",description:"A brief statement on the intended meaning of this concept, especially as an indication of how the use of the concept is limited in indexing practice.",rows:3}),l({name:"altLabel",title:"Alternate Label(s)",type:"array",description:"Synonyms, near-synonyms, abbreviations, and acronyms to a concept.",of:[{type:"string"}],validation:e=>e.unique()}),l({name:"hiddenLabel",title:"Hidden Label(s)",type:"array",description:"Character strings that need to be accessible to applications performing text-based indexing and search operations, but which should not be displayed to end users.",of:[{type:"string"}],validation:e=>e.unique()}),...mn,l({name:"conceptId",title:"Identifier",description:"Generate or re-generate the identifier for this concept according to parameters set in Taxonomy Manager plugin options. Note that this changes the concept's URI, which is not advisable if the concept is already in use in production. Use with caution.",type:"string",initialValue:be(t),hidden:({document:e})=>!!e?.conceptId&&!t?.regenUi,readOnly:({document:e})=>!!e?.conceptId,components:{input:e=>/* @__PURE__ */I(Ce,{...e,ident:t})}}),l({name:"broader",title:"Broader Concept(s)",description:"Create hierarchy between concepts, for example to create category/subcategory, part/whole, or class/instance relationships.",type:"array",of:[{type:"reference",to:{type:"skosConcept"},options:{filter:hn}}]}),l({name:"related",title:"Related Concept(s)",description:'Indicate that two concepts are inherently "related", but that one is not in any way more general than the other.',type:"array",of:[{type:"reference",to:[{type:"skosConcept"}],options:{filter:hn}}]}),...n,l({name:"historyNote",title:"History Notes",type:"text",description:"Significant changes to the meaning or the form of this concept.",rows:3}),l({name:"editorialNote",title:"Editorial Notes",type:"text",description:"Information to aid in administrative housekeeping, such as reminders of editorial work still to be done, or warnings in the event that future editorial changes might be made.",rows:3}),l({name:"changeNote",title:"Change Notes",type:"text",description:"Fine-grained changes to a concept, for the purposes of administration and maintenance.",rows:3})],orderings:[{title:"Top Concepts",name:"topConcept",by:[{field:"topConcept",direction:"desc"},{field:"prefLabel",direction:"asc"}]},{title:"Preferred Label",name:"prefLabel",by:[{field:"prefLabel",direction:"asc"}]}],preview:{select:{title:"prefLabel"},prepare:({title:e})=>({title:e,media:ye})}})}function fn(e,n=[],t){return p({name:"skosConceptScheme",title:"Concept Scheme",type:"document",icon:nn,initialValue:async(n,t)=>{if(e)return{baseIri:e};const{getClient:i}=t;return{baseIri:await i({apiVersion:"2021-03-25"}).fetch("\n *[(_type == 'skosConcept' || _type == 'skosConceptScheme') && defined(baseIri)]| order(_createdAt desc)[0].baseIri\n ")??void 0}},fields:[l({name:"title",title:"Title",type:"string",description:"Taxonomy schemes group concepts into defined sets, such as thesauri, classification schemes, or facets. Concepts may belong to many (or no) concept schemes, and you may create as many (or few) concept schemes as you like"}),l({name:"description",title:"Description",type:"text",rows:5,description:"Describe the intended use of this scheme."}),l({name:"controls",title:"Concept Management Controls",deprecated:{reason:"This field was used for a previous version of the plugin and is no longer needed. Remove the value to hide this field."},type:"boolean",readOnly:!0,hidden:({document:e})=>void 0===e?.controls,components:{input:dn}}),...mn,l({name:"schemeId",title:"Identifier",description:"Generate or re-generate the identifier for this scheme according to parameters set in Taxonomy Manager plugin options. Note that this changes the scheme's URI, which is not advisable if the scheme already is use in production. Use with caution.",type:"string",initialValue:be(t),hidden:({document:e})=>!!e?.schemeId&&!t?.regenUi,readOnly:({document:e})=>!!e?.schemeId,components:{input:e=>/* @__PURE__ */I(Ce,{...e,ident:t})}}),l({name:"topConcepts",title:"Top Concepts",type:"array",validation:e=>e.unique(),of:[h({type:"reference",to:[{type:"skosConcept"}]})],options:{sortable:!1}}),l({name:"concepts",title:"Concepts",type:"array",validation:e=>e.unique(),of:[h({type:"reference",to:[{type:"skosConcept"}]})],options:{sortable:!1}}),...n],preview:{select:{title:"title"},prepare:({title:e})=>({title:e,media:nn})}})}const gn=/_key\s*==\s*['"](.*)['"]/,yn=/^\d*:\d*$/,bn=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,Cn=/_key\s*==\s*['"](.*)['"]/;function In(e){if("string"!=typeof e)throw new Error("Path is not a string");const n=e.match(bn);if(!n)throw new Error("Invalid path string");return n.map(wn)}function wn(e){return function(e){return"number"==typeof e||"string"==typeof e&&/^\[\d+\]$/.test(e)}(e)?function(e){return Number(e.replace(/[^\d]/g,""))}(e):function(e){return"string"==typeof e?gn.test(e.trim()):"object"==typeof e&&"_key"in e}(e)?function(e){return{_key:e.match(Cn)[1]}}(e):function(e){if("string"==typeof e&&yn.test(e))return!0;if(!Array.isArray(e)||2!==e.length)return!1;const[n,t]=e;return!("number"!=typeof n&&""!==n||"number"!=typeof t&&""!==t)}(e)?function(e){const[n,t]=e.split(":").map(e=>""===e?e:Number(e));return[n,t]}(e):e}const vn=({document:e})=>{const{selectedPerspectiveName:n}=r(),{routerPanesState:t,groupIndex:i,handleEditReference:o}=y(),c=m(),s=u(e.displayed?._id??""),d=K((e,n)=>{const r=t[i+1]?.[0].params||{},{parentRefPath:c}=r;o({id:e,type:n,parentRefPath:c?In(c):[""],template:{id:e}})},[t,i,o]),{data:a,loading:l,error:p}=He('*[!(_type in ["skosConcept","skosConceptScheme"]) && references($refId)]{_id,_type,title}',{params:{refId:s},options:{perspective:n?[n]:"drafts"}});return l?/* @__PURE__ */I(E,{padding:5,children:/* @__PURE__ */C(R,{align:"center",direction:"column",gap:5,height:"fill",justify:"center",style:{paddingTop:"1rem"},children:[
|
|
103
|
+
/* @__PURE__ */I(j,{muted:!0}),
|
|
104
|
+
/* @__PURE__ */I($,{muted:!0,size:1,children:"Loading usage…"})]})}):p?/* @__PURE__ */I(H,{padding:4,space:5,children:/* @__PURE__ */I(Te,{tone:"caution",children:"There was en error fetching use data"})}):a?.length?/* @__PURE__ */I(E,{padding:4,paddingTop:4,children:/* @__PURE__ */C(H,{space:2,children:[
|
|
105
|
+
/* @__PURE__ */I(P,{borderBottom:!0,paddingTop:3,paddingBottom:3,children:/* @__PURE__ */I(B,{paddingTop:1,children:/* @__PURE__ */C($,{weight:"semibold",muted:!0,size:1,children:["Resource count (all schemes): ",a.length]})})}),
|
|
106
|
+
/* @__PURE__ */I(H,{space:1,children:a?.map(e=>{const n=c.get(e._type);return n&&/* @__PURE__ */I(M,{onClick:()=>d(e._id,e._type),padding:2,mode:"bleed",children:/* @__PURE__ */I(f,{value:e,schemaType:n,layout:"block"})},e._id)})})]})}):/* @__PURE__ */I(H,{padding:4,space:5,children:/* @__PURE__ */I(Te,{children:"This concept is not currently in use"})})},_n=e=>e.list().title("Taxonomy Manager").items([e.documentTypeListItem("skosConceptScheme").title("Concept Schemes"),e.documentTypeListItem("skosConcept").title("Concepts")]),xn=(e={})=>{const n=n=>/* @__PURE__ */I(_e.Provider,{value:{ident:e.ident},children:/* @__PURE__ */I(rn,{...n})});return(e,{schemaType:t})=>{switch(t){case"skosConceptScheme":return e.document().views([e.view.component(n).title("Tree View").icon(nn),e.view.form().icon(L)]);case"skosConcept":return e.document().views([e.view.form().icon(L),e.view.component(vn).title("Tagged Resources").icon(S)]);default:return e.document().views([e.view.form().icon(L)])}}},Vn=g(e=>{const{baseUri:n,customConceptFields:t,customSchemeFields:i,ident:o}=e||{};return{name:"taxonomyManager",options:e,schema:{types:[un(n,t,o),fn(n,i,o)]},plugins:[b({name:"taxonomy",title:"Taxonomy",structure:_n,defaultDocumentNode:xn({ident:o}),icon:nn})]}});export{sn as ArrayHierarchyInput,cn as ReferenceHierarchyInput,rn as TreeView,pn as branchFilter,ln as schemeFilter,Vn as taxonomyManager};//# sourceMappingURL=index.js.map
|