@performant-software/core-data 1.2.0-beta.1
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 +21 -0
- package/README.md +0 -0
- package/build/index.js +2 -0
- package/build/index.js.map +1 -0
- package/build/main.css +133 -0
- package/index.js +1 -0
- package/package.json +29 -0
- package/src/components/LoadAnimation.css +40 -0
- package/src/components/LoadAnimation.js +24 -0
- package/src/components/MediaGallery.css +64 -0
- package/src/components/MediaGallery.js +80 -0
- package/src/components/PlaceDetailsPanel.css +37 -0
- package/src/components/PlaceDetailsPanel.js +113 -0
- package/src/components/PlaceMarker.js +59 -0
- package/src/components/RelatedItemsList.js +94 -0
- package/src/components/RelatedList.js +46 -0
- package/src/components/RelatedMedia.js +52 -0
- package/src/components/RelatedOrganizations.js +28 -0
- package/src/components/RelatedPeople.js +28 -0
- package/src/components/RelatedPlaces.js +28 -0
- package/src/components/RelatedTaxonomies.js +28 -0
- package/src/index.js +14 -0
- package/src/types/Annotation.js +13 -0
- package/src/types/MediaContent.js +13 -0
- package/src/types/Organization.js +8 -0
- package/src/types/Person.js +11 -0
- package/src/types/Place.js +9 -0
- package/src/types/RelatedItems.js +12 -0
- package/src/types/Taxonomy.js +7 -0
- package/src/types/UserDefinedField.js +6 -0
- package/types/components/LoadAnimation.js.flow +24 -0
- package/types/components/MediaGallery.js.flow +80 -0
- package/types/components/PlaceDetailsPanel.js.flow +113 -0
- package/types/components/PlaceMarker.js.flow +59 -0
- package/types/components/RelatedItemsList.js.flow +94 -0
- package/types/components/RelatedList.js.flow +46 -0
- package/types/components/RelatedMedia.js.flow +52 -0
- package/types/components/RelatedOrganizations.js.flow +28 -0
- package/types/components/RelatedPeople.js.flow +28 -0
- package/types/components/RelatedPlaces.js.flow +28 -0
- package/types/components/RelatedTaxonomies.js.flow +28 -0
- package/types/index.js.flow +14 -0
- package/types/types/Annotation.js.flow +13 -0
- package/types/types/MediaContent.js.flow +13 -0
- package/types/types/Organization.js.flow +8 -0
- package/types/types/Person.js.flow +11 -0
- package/types/types/Place.js.flow +9 -0
- package/types/types/RelatedItems.js.flow +12 -0
- package/types/types/Taxonomy.js.flow +7 -0
- package/types/types/UserDefinedField.js.flow +6 -0
- package/webpack.config.js +3 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import { LocationMarker } from '@performant-software/geospatial';
|
|
4
|
+
import React, { useCallback, useEffect, useState } from 'react';
|
|
5
|
+
|
|
6
|
+
type Props = {
|
|
7
|
+
/**
|
|
8
|
+
* The URL of the Core Data place record.
|
|
9
|
+
*/
|
|
10
|
+
url: string
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* This component renders a map marker for a given Core Data Place record.
|
|
15
|
+
*/
|
|
16
|
+
const PlaceMarker = (props: Props) => {
|
|
17
|
+
const [place, setPlace] = useState();
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Converts the passed data to a feature collection and sets it on the state.
|
|
21
|
+
*
|
|
22
|
+
* @type {(function(*): void)|*}
|
|
23
|
+
*/
|
|
24
|
+
const onLoad = useCallback((data) => {
|
|
25
|
+
const featureCollection = {
|
|
26
|
+
type: 'FeatureCollection',
|
|
27
|
+
features: [{
|
|
28
|
+
...data,
|
|
29
|
+
properties: {
|
|
30
|
+
...data.properties,
|
|
31
|
+
record_id: data.record_id
|
|
32
|
+
}
|
|
33
|
+
}]
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
setPlace(featureCollection);
|
|
37
|
+
}, []);
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Fetch the place record from the passed URL.
|
|
41
|
+
*/
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
fetch(props.url)
|
|
44
|
+
.then((res) => res.json())
|
|
45
|
+
.then(onLoad);
|
|
46
|
+
}, [props.url]);
|
|
47
|
+
|
|
48
|
+
if (!place) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<LocationMarker
|
|
54
|
+
data={place}
|
|
55
|
+
/>
|
|
56
|
+
);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export default PlaceMarker;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import * as Accordion from '@radix-ui/react-accordion';
|
|
4
|
+
import { AlertCircle, ChevronDown } from 'lucide-react';
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import _ from 'underscore';
|
|
7
|
+
import LoadAnimation from './LoadAnimation';
|
|
8
|
+
import RelatedMedia from './RelatedMedia';
|
|
9
|
+
import RelatedOrganizations from './RelatedOrganizations';
|
|
10
|
+
import RelatedPeople from './RelatedPeople';
|
|
11
|
+
import RelatedPlaces from './RelatedPlaces';
|
|
12
|
+
import RelatedTaxonomies from './RelatedTaxonomies';
|
|
13
|
+
import type { RelatedItems } from '../types/RelatedItems';
|
|
14
|
+
|
|
15
|
+
type Props = {
|
|
16
|
+
items: Array<RelatedItems>
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const RelatedItemsList = (props: Props) => {
|
|
20
|
+
if (_.isEmpty(props.items)) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<Accordion.Root type='multiple'>
|
|
26
|
+
{ _.map(props.items, ({ data, error, ...conf }) => (
|
|
27
|
+
<Accordion.Item
|
|
28
|
+
key={conf.endpoint}
|
|
29
|
+
value={conf.endpoint}
|
|
30
|
+
>
|
|
31
|
+
<Accordion.Header>
|
|
32
|
+
<Accordion.Trigger
|
|
33
|
+
className='accordion-trigger border-black/20 border border-t border-b-0 border-l-0 border-r-0 border-solid
|
|
34
|
+
rounded-none w-full flex justify-between items-center px-3 py-3 text-sm'
|
|
35
|
+
>
|
|
36
|
+
<div>
|
|
37
|
+
{ conf.ui_label }
|
|
38
|
+
{ data && (
|
|
39
|
+
<span className='ml-1'>
|
|
40
|
+
({ data.items.length })
|
|
41
|
+
</span>
|
|
42
|
+
)}
|
|
43
|
+
{ error && (
|
|
44
|
+
<AlertCircle
|
|
45
|
+
className='inline ml-1.5 h-4 w-4 text-red-600 align-text-bottom'
|
|
46
|
+
/>
|
|
47
|
+
)}
|
|
48
|
+
{ !(data || error) && (
|
|
49
|
+
<LoadAnimation
|
|
50
|
+
className='text-muted/60 ml-4'
|
|
51
|
+
/>
|
|
52
|
+
)}
|
|
53
|
+
</div>
|
|
54
|
+
<ChevronDown
|
|
55
|
+
className='accordion-chevron h-4 w-4'
|
|
56
|
+
/>
|
|
57
|
+
</Accordion.Trigger>
|
|
58
|
+
</Accordion.Header>
|
|
59
|
+
<Accordion.Content
|
|
60
|
+
className='accordion-content text-sm leading-6'
|
|
61
|
+
>
|
|
62
|
+
{ conf.endpoint === 'media_contents' && (
|
|
63
|
+
<RelatedMedia
|
|
64
|
+
data={data}
|
|
65
|
+
/>
|
|
66
|
+
)}
|
|
67
|
+
{ conf.endpoint === 'organizations' && (
|
|
68
|
+
<RelatedOrganizations
|
|
69
|
+
data={data}
|
|
70
|
+
/>
|
|
71
|
+
)}
|
|
72
|
+
{ conf.endpoint === 'people' && (
|
|
73
|
+
<RelatedPeople
|
|
74
|
+
data={data}
|
|
75
|
+
/>
|
|
76
|
+
)}
|
|
77
|
+
{ conf.endpoint === 'places' && (
|
|
78
|
+
<RelatedPlaces
|
|
79
|
+
data={data}
|
|
80
|
+
/>
|
|
81
|
+
)}
|
|
82
|
+
{ conf.endpoint === 'taxonomies' && (
|
|
83
|
+
<RelatedTaxonomies
|
|
84
|
+
data={data}
|
|
85
|
+
/>
|
|
86
|
+
)}
|
|
87
|
+
</Accordion.Content>
|
|
88
|
+
</Accordion.Item>
|
|
89
|
+
))}
|
|
90
|
+
</Accordion.Root>
|
|
91
|
+
);
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export default RelatedItemsList;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import { AnnotationPage } from '@peripleo/peripleo';
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import _ from 'underscore';
|
|
6
|
+
|
|
7
|
+
type Item = {
|
|
8
|
+
id: string
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
type Props = {
|
|
12
|
+
data: AnnotationPage<Item>,
|
|
13
|
+
emptyMessage?: string,
|
|
14
|
+
renderItem: (item: Item) => JSX.Element
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const RelatedList = (props: Props) => {
|
|
18
|
+
const { items } = props.data;
|
|
19
|
+
|
|
20
|
+
if (_.isEmpty(items)) {
|
|
21
|
+
return (
|
|
22
|
+
<div
|
|
23
|
+
className='pt-6 pl-3 pr-6 pb-8 flex items-center justify-center text-muted/50 italic'
|
|
24
|
+
>
|
|
25
|
+
{ props.emptyMessage }
|
|
26
|
+
</div>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<ul
|
|
32
|
+
className='p-3 pt-1 pb-4'
|
|
33
|
+
>
|
|
34
|
+
{ _.map(items, (item) => (
|
|
35
|
+
<li
|
|
36
|
+
key={item.id}
|
|
37
|
+
className='flex items-center'
|
|
38
|
+
>
|
|
39
|
+
{ props.renderItem(item) }
|
|
40
|
+
</li>
|
|
41
|
+
))}
|
|
42
|
+
</ul>
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export default RelatedList;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import { AnnotationPage } from '@peripleo/peripleo';
|
|
4
|
+
import { Thumbnail } from '@samvera/clover-iiif/primitives';
|
|
5
|
+
import React, { useState } from 'react';
|
|
6
|
+
import _ from 'underscore';
|
|
7
|
+
import type { MediaContent } from '../types/MediaContent';
|
|
8
|
+
import MediaGallery from './MediaGallery';
|
|
9
|
+
|
|
10
|
+
type Props = {
|
|
11
|
+
data: AnnotationPage<MediaContent>,
|
|
12
|
+
thumbnailHeight?: number,
|
|
13
|
+
thumbnailWidth?: number
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const DEFAULT_THUMBNAIL_HEIGHT = 80;
|
|
17
|
+
const DEFAULT_THUMBNAIL_WIDTH = 80;
|
|
18
|
+
|
|
19
|
+
const RelatedMedia = (props: Props) => {
|
|
20
|
+
const [showGallery, setShowGallery] = useState<MediaContent>();
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<div
|
|
24
|
+
className='p-3 pb-4 grid grid-cols-3 gap-1'
|
|
25
|
+
>
|
|
26
|
+
{ _.map(props.data?.items, (item) => (
|
|
27
|
+
<Thumbnail
|
|
28
|
+
key={item.body.id}
|
|
29
|
+
className='rounded shadow cursor-pointer'
|
|
30
|
+
onClick={() => setShowGallery(item.body)}
|
|
31
|
+
thumbnail={[{
|
|
32
|
+
id: item.body.content_thumbnail_url,
|
|
33
|
+
type: 'Image',
|
|
34
|
+
width: props.thumbnailWidth,
|
|
35
|
+
height: props.thumbnailHeight
|
|
36
|
+
}]}
|
|
37
|
+
/>
|
|
38
|
+
))}
|
|
39
|
+
<MediaGallery
|
|
40
|
+
defaultItem={showGallery}
|
|
41
|
+
onClose={() => setShowGallery(undefined)}
|
|
42
|
+
/>
|
|
43
|
+
</div>
|
|
44
|
+
);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
RelatedMedia.defaultProps = {
|
|
48
|
+
thumbnailHeight: DEFAULT_THUMBNAIL_HEIGHT,
|
|
49
|
+
thumbnailWidth: DEFAULT_THUMBNAIL_WIDTH
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export default RelatedMedia;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import { AnnotationPage } from '@peripleo/peripleo';
|
|
4
|
+
import { Building2 } from 'lucide-react';
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import type { Organization } from '../types/Organization';
|
|
7
|
+
import RelatedList from './RelatedList';
|
|
8
|
+
|
|
9
|
+
type Props = {
|
|
10
|
+
data: AnnotationPage<Organization>
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const RelatedOrganizations = (props: Props) => (
|
|
14
|
+
<RelatedList
|
|
15
|
+
data={props.data}
|
|
16
|
+
emptyMessage={'No related organization'}
|
|
17
|
+
renderItem={(organization) => (
|
|
18
|
+
<>
|
|
19
|
+
<Building2
|
|
20
|
+
className='h-4 w-4 mr-1.5'
|
|
21
|
+
/>
|
|
22
|
+
{ organization.body.title }
|
|
23
|
+
</>
|
|
24
|
+
)}
|
|
25
|
+
/>
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
export default RelatedOrganizations;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import { AnnotationPage } from '@peripleo/peripleo';
|
|
4
|
+
import { UserCircle } from 'lucide-react';
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import type { Person } from '../types/Person';
|
|
7
|
+
import RelatedList from './RelatedList';
|
|
8
|
+
|
|
9
|
+
type Props = {
|
|
10
|
+
data: AnnotationPage<Person>
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const RelatedPeople = (props: Props) => (
|
|
14
|
+
<RelatedList
|
|
15
|
+
data={props.data}
|
|
16
|
+
emptyMessage={'No related people'}
|
|
17
|
+
renderItem={(person) => (
|
|
18
|
+
<>
|
|
19
|
+
<UserCircle
|
|
20
|
+
className='h-4 w-4 mr-1.5'
|
|
21
|
+
/>
|
|
22
|
+
{ person.body.title }
|
|
23
|
+
</>
|
|
24
|
+
)}
|
|
25
|
+
/>
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
export default RelatedPeople;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import { AnnotationPage } from '@peripleo/peripleo';
|
|
4
|
+
import { MapPin } from 'lucide-react';
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import type { Place } from '../types/Place';
|
|
7
|
+
import RelatedList from './RelatedList';
|
|
8
|
+
|
|
9
|
+
type Props = {
|
|
10
|
+
data: AnnotationPage<Place>
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const RelatedPlaces = (props: Props) => (
|
|
14
|
+
<RelatedList
|
|
15
|
+
data={props.data}
|
|
16
|
+
emptyMessage={'No related places'}
|
|
17
|
+
renderItem={(place) => (
|
|
18
|
+
<>
|
|
19
|
+
<MapPin
|
|
20
|
+
className='h-4 w-4 mr-0.5 inline-block mb-0.5'
|
|
21
|
+
/>
|
|
22
|
+
{ place.body.title }
|
|
23
|
+
</>
|
|
24
|
+
)}
|
|
25
|
+
/>
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
export default RelatedPlaces;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import { AnnotationPage } from '@peripleo/peripleo';
|
|
4
|
+
import { ListTree } from 'lucide-react';
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import RelatedList from './RelatedList';
|
|
7
|
+
import type { Taxonomy } from '../types/Taxonomy';
|
|
8
|
+
|
|
9
|
+
type Props = {
|
|
10
|
+
data: AnnotationPage<Taxonomy>
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const RelatedTaxonomies = (props: Props) => (
|
|
14
|
+
<RelatedList
|
|
15
|
+
data={props.data}
|
|
16
|
+
emptyMessage={'No related taxonomies'}
|
|
17
|
+
renderItem={(taxonomy) => (
|
|
18
|
+
<>
|
|
19
|
+
<ListTree
|
|
20
|
+
className='h-4 w-4 mr-1.5'
|
|
21
|
+
/>
|
|
22
|
+
{ taxonomy.body.title }
|
|
23
|
+
</>
|
|
24
|
+
)}
|
|
25
|
+
/>
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
export default RelatedTaxonomies;
|
package/src/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
// Components
|
|
4
|
+
export { default as LoadAnimation } from './components/LoadAnimation';
|
|
5
|
+
export { default as MediaGallery } from './components/MediaGallery';
|
|
6
|
+
export { default as PlaceDetailsPanel } from './components/PlaceDetailsPanel';
|
|
7
|
+
export { default as PlaceMarker } from './components/PlaceMarker';
|
|
8
|
+
export { default as RelatedItemsList } from './components/RelatedItemsList';
|
|
9
|
+
export { default as RelatedList } from './components/RelatedList';
|
|
10
|
+
export { default as RelatedMedia } from './components/RelatedMedia';
|
|
11
|
+
export { default as RelatedOrganization } from './components/RelatedOrganizations';
|
|
12
|
+
export { default as RelatedPeople } from './components/RelatedPeople';
|
|
13
|
+
export { default as RelatedPlaces } from './components/RelatedPlaces';
|
|
14
|
+
export { default as RelatedTaxonomies } from './components/RelatedTaxonomies';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import type { Annotation } from './Annotation';
|
|
4
|
+
|
|
5
|
+
export type MediaContent = Annotation & {
|
|
6
|
+
content_download_url: string,
|
|
7
|
+
content_iiif_url: string,
|
|
8
|
+
content_preview_url: string,
|
|
9
|
+
content_thumbnail_url: string,
|
|
10
|
+
content_url: string,
|
|
11
|
+
manifest_url: string,
|
|
12
|
+
type: 'MediaContent'
|
|
13
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import { AnnotationPage } from '@peripleo/peripleo';
|
|
4
|
+
import type { Annotation } from './Annotation';
|
|
5
|
+
|
|
6
|
+
export type RelatedItems = {
|
|
7
|
+
endpoint: string,
|
|
8
|
+
ui_label: string,
|
|
9
|
+
default_open?: boolean,
|
|
10
|
+
data?: AnnotationPage<Annotation>,
|
|
11
|
+
error?: Error
|
|
12
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import './LoadAnimation.css';
|
|
5
|
+
|
|
6
|
+
type Props = {
|
|
7
|
+
/**
|
|
8
|
+
* Additional class name to apply to the element.
|
|
9
|
+
*/
|
|
10
|
+
className?: string
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* This component renders a basic loading animation.
|
|
15
|
+
*/
|
|
16
|
+
const LoadAnimation = (props: Props) => {
|
|
17
|
+
const className = `${props.className || ''} loader three-dots`.trim();
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<span className={className} />
|
|
21
|
+
);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export default LoadAnimation;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import * as Dialog from '@radix-ui/react-dialog';
|
|
4
|
+
import Viewer from '@samvera/clover-iiif/viewer';
|
|
5
|
+
import { Image, X } from 'lucide-react';
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import type { MediaContent } from '../types/MediaContent';
|
|
8
|
+
|
|
9
|
+
import './MediaGallery.css';
|
|
10
|
+
|
|
11
|
+
type Props = {
|
|
12
|
+
/**
|
|
13
|
+
* The MediaContent record contain the IIIF manifest URL.
|
|
14
|
+
*/
|
|
15
|
+
defaultItem: MediaContent,
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Callback fired when the dialog is closed.
|
|
19
|
+
*/
|
|
20
|
+
onClose: () => void,
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Title text to display at the top of the dialog.
|
|
24
|
+
*/
|
|
25
|
+
title?: string
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* This component renders a IIIF Viewer for the passed MediaContent record.
|
|
30
|
+
*/
|
|
31
|
+
const MediaGallery = (props: Props) => (
|
|
32
|
+
<Dialog.Root
|
|
33
|
+
onOpenChange={props.onClose}
|
|
34
|
+
open={Boolean(props.defaultItem)}
|
|
35
|
+
>
|
|
36
|
+
<Dialog.Portal>
|
|
37
|
+
<Dialog.Overlay
|
|
38
|
+
className='dialog-overlay'
|
|
39
|
+
/>
|
|
40
|
+
<Dialog.Content
|
|
41
|
+
className='dialog-content'
|
|
42
|
+
>
|
|
43
|
+
<Dialog.Title
|
|
44
|
+
className='dialog-title flex items-center'
|
|
45
|
+
>
|
|
46
|
+
<Image
|
|
47
|
+
className='h-4 w-4 mr-1.5'
|
|
48
|
+
/>
|
|
49
|
+
{ props.title }
|
|
50
|
+
</Dialog.Title>
|
|
51
|
+
<div
|
|
52
|
+
className='pt-6 pb-2 text-sm w-full text-muted min-h-20'
|
|
53
|
+
>
|
|
54
|
+
{ Boolean(props.defaultItem) && (
|
|
55
|
+
<Viewer
|
|
56
|
+
iiifContent={props.defaultItem.manifest_url}
|
|
57
|
+
options={{
|
|
58
|
+
informationPanel: {
|
|
59
|
+
open: false
|
|
60
|
+
}
|
|
61
|
+
}}
|
|
62
|
+
/>
|
|
63
|
+
)}
|
|
64
|
+
</div>
|
|
65
|
+
<Dialog.Close
|
|
66
|
+
asChild
|
|
67
|
+
>
|
|
68
|
+
<button
|
|
69
|
+
className='dialog-close rounded-full'
|
|
70
|
+
type='button'
|
|
71
|
+
>
|
|
72
|
+
<X className='h-7 w-7 p-1.5' />
|
|
73
|
+
</button>
|
|
74
|
+
</Dialog.Close>
|
|
75
|
+
</Dialog.Content>
|
|
76
|
+
</Dialog.Portal>
|
|
77
|
+
</Dialog.Root>
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
export default MediaGallery;
|