@performant-software/semantic-components 1.0.1 → 1.0.2-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/build/index.js +1 -1
- package/build/index.js.map +1 -1
- package/build/main.css +26 -0
- package/package.json +6 -3
- package/src/components/BibliographyList.css +3 -0
- package/src/components/BibliographyList.js +286 -0
- package/src/components/BibliographyModal.js +125 -0
- package/src/components/BibliographySearchInput.css +13 -0
- package/src/components/BibliographySearchInput.js +86 -0
- package/src/components/Citation.js +78 -0
- package/src/components/CreatorField.css +11 -0
- package/src/components/CreatorField.js +137 -0
- package/src/components/Creators.js +97 -0
- package/src/components/List.js +7 -2
- package/src/components/SortSelector.js +91 -0
- package/src/components/StyleSelector.js +75 -0
- package/src/constants/Sort.js +2 -0
- package/src/context/ZoteroTranslateContext.js +7 -0
- package/src/i18n/en.json +29 -0
- package/src/index.js +1 -0
- package/src/resources/BibliographyTypes.json +117 -0
- package/src/resources/CitationStyles.json +25 -0
- package/src/utils/Bibliography.js +191 -0
- package/types/components/BibliographyList.js.flow +286 -0
- package/types/components/BibliographyModal.js.flow +125 -0
- package/types/components/BibliographySearchInput.js.flow +86 -0
- package/types/components/Citation.js.flow +78 -0
- package/types/components/CreatorField.js.flow +137 -0
- package/types/components/Creators.js.flow +97 -0
- package/types/components/List.js.flow +7 -2
- package/types/components/SortSelector.js.flow +91 -0
- package/types/components/StyleSelector.js.flow +75 -0
- package/types/constants/Sort.js.flow +2 -0
- package/types/context/ZoteroTranslateContext.js.flow +7 -0
- package/types/index.js.flow +1 -0
- package/types/utils/Bibliography.js.flow +191 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import React, { useCallback, useEffect, useMemo } from 'react';
|
|
4
|
+
import { Dropdown, Form } from 'semantic-ui-react';
|
|
5
|
+
import _ from 'underscore';
|
|
6
|
+
import i18n from '../i18n/i18n';
|
|
7
|
+
import './CreatorField.css';
|
|
8
|
+
|
|
9
|
+
const NameTypes = {
|
|
10
|
+
single: 0,
|
|
11
|
+
full: 1
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
type Props = {
|
|
15
|
+
allowDelete?: boolean,
|
|
16
|
+
creatorTypes: Array<any>,
|
|
17
|
+
creator: any,
|
|
18
|
+
onAdd: () => void,
|
|
19
|
+
onDelete: () => void,
|
|
20
|
+
onUpdate: (props: any) => void
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const CreatorField = (props: Props) => {
|
|
24
|
+
/**
|
|
25
|
+
* Updates the passed attribute for the current creator.
|
|
26
|
+
*
|
|
27
|
+
* @type {function(string, ?Event, *): *}
|
|
28
|
+
*/
|
|
29
|
+
const onUpdate = useCallback((attribute: string, e: ?Event, { value }: any) => (
|
|
30
|
+
props.onUpdate({ ...props.creator || {}, [attribute]: value })
|
|
31
|
+
), [props.creator, props.onUpdate]);
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Updates the passed attributes for the current creator.
|
|
35
|
+
*
|
|
36
|
+
* @type {function(*): *}
|
|
37
|
+
*/
|
|
38
|
+
const onUpdateAttributes = useCallback((attributes) => (
|
|
39
|
+
props.onUpdate({ ...props.creator || {}, ...attributes })
|
|
40
|
+
), [props.creator, props.onUpdate]);
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Sets the label attribute as a dropdown of the passed creatorTypes prop.
|
|
44
|
+
*
|
|
45
|
+
* @type {unknown}
|
|
46
|
+
*/
|
|
47
|
+
const label = useMemo(() => (
|
|
48
|
+
// eslint-disable-next-line jsx-a11y/label-has-associated-control
|
|
49
|
+
<label>
|
|
50
|
+
<Dropdown
|
|
51
|
+
onChange={onUpdate.bind(this, 'creatorType')}
|
|
52
|
+
options={_.map(props.creatorTypes, (ct) => ({
|
|
53
|
+
key: ct.value,
|
|
54
|
+
value: ct.value,
|
|
55
|
+
text: ct.label
|
|
56
|
+
}))}
|
|
57
|
+
value={props.creator.creatorType}
|
|
58
|
+
/>
|
|
59
|
+
</label>
|
|
60
|
+
), [props.creator.creatorType, props.creatorTypes]);
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Default the nameType property to full (first name/last name).
|
|
64
|
+
*/
|
|
65
|
+
useEffect(() => {
|
|
66
|
+
if (!_.has(props.creator, 'nameType')) {
|
|
67
|
+
onUpdateAttributes({ nameType: NameTypes.full });
|
|
68
|
+
}
|
|
69
|
+
}, [props.creator, onUpdateAttributes]);
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Convert between firstName/lastName and name attributes depending on the name type.
|
|
73
|
+
*/
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
if (props.creator.name && props.creator.nameType === NameTypes.full) {
|
|
76
|
+
const [firstName, lastName] = props.creator.name.split(' ');
|
|
77
|
+
onUpdateAttributes({ name: null, firstName, lastName });
|
|
78
|
+
} else if ((props.creator.firstName || props.creator.lastName) && props.creator.nameType === NameTypes.single) {
|
|
79
|
+
const name = _.compact([props.creator.firstName, props.creator.lastName]).join(' ');
|
|
80
|
+
onUpdateAttributes({ firstName: null, lastName: null, name });
|
|
81
|
+
}
|
|
82
|
+
}, [props.creator.nameType]);
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<Form.Group
|
|
86
|
+
className='creator-field'
|
|
87
|
+
>
|
|
88
|
+
{ props.creator.nameType === NameTypes.full && (
|
|
89
|
+
<>
|
|
90
|
+
<Form.Input
|
|
91
|
+
className='flex'
|
|
92
|
+
label={label}
|
|
93
|
+
onChange={onUpdate.bind(this, 'firstName')}
|
|
94
|
+
placeholder={i18n.t('CreatorField.labels.firstName')}
|
|
95
|
+
value={props.creator.firstName}
|
|
96
|
+
/>
|
|
97
|
+
<Form.Input
|
|
98
|
+
className='flex'
|
|
99
|
+
onChange={onUpdate.bind(this, 'lastName')}
|
|
100
|
+
placeholder={i18n.t('CreatorField.labels.lastName')}
|
|
101
|
+
value={props.creator.lastName}
|
|
102
|
+
/>
|
|
103
|
+
<Form.Button
|
|
104
|
+
icon='exchange'
|
|
105
|
+
onClick={() => onUpdateAttributes({ nameType: NameTypes.single })}
|
|
106
|
+
/>
|
|
107
|
+
</>
|
|
108
|
+
)}
|
|
109
|
+
{ props.creator.nameType === NameTypes.single && (
|
|
110
|
+
<>
|
|
111
|
+
<Form.Input
|
|
112
|
+
className='flex'
|
|
113
|
+
label={label}
|
|
114
|
+
onChange={onUpdate.bind(this, 'name')}
|
|
115
|
+
placeholder={i18n.t('CreatorField.labels.name')}
|
|
116
|
+
value={props.creator.name}
|
|
117
|
+
/>
|
|
118
|
+
<Form.Button
|
|
119
|
+
icon='exchange'
|
|
120
|
+
onClick={() => onUpdateAttributes({ nameType: NameTypes.full })}
|
|
121
|
+
/>
|
|
122
|
+
</>
|
|
123
|
+
)}
|
|
124
|
+
<Form.Button
|
|
125
|
+
icon='plus'
|
|
126
|
+
onClick={props.onAdd}
|
|
127
|
+
/>
|
|
128
|
+
<Form.Button
|
|
129
|
+
disabled={!props.allowDelete}
|
|
130
|
+
icon='minus'
|
|
131
|
+
onClick={props.onDelete}
|
|
132
|
+
/>
|
|
133
|
+
</Form.Group>
|
|
134
|
+
);
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
export default CreatorField;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import React, { useCallback, useEffect, useMemo } from 'react';
|
|
4
|
+
import _ from 'underscore';
|
|
5
|
+
import CreatorField from './CreatorField';
|
|
6
|
+
|
|
7
|
+
type Props = {
|
|
8
|
+
creatorTypes: Array<any>,
|
|
9
|
+
onChange: (creators: Array<any>) => void,
|
|
10
|
+
value: Array<any>
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const Creators = (props: Props) => {
|
|
14
|
+
/**
|
|
15
|
+
* Sets the default creator type.
|
|
16
|
+
*
|
|
17
|
+
* @type {unknown}
|
|
18
|
+
*/
|
|
19
|
+
const defaultCreatorType = useMemo(() => (
|
|
20
|
+
props.creatorTypes && props.creatorTypes.length && props.creatorTypes[0].value
|
|
21
|
+
), [props.creatorTypes]);
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Adds a new creator record with the default type.
|
|
25
|
+
*
|
|
26
|
+
* @type {function(): *}
|
|
27
|
+
*/
|
|
28
|
+
const onAddCreator = useCallback(() => props.onChange([
|
|
29
|
+
...(props.value || []),
|
|
30
|
+
{ creatorType: defaultCreatorType }
|
|
31
|
+
]), [props.onChange, props.value]);
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Deletes the creator at the passed index.
|
|
35
|
+
*
|
|
36
|
+
* @type {function(*): *}
|
|
37
|
+
*/
|
|
38
|
+
const onDeleteCreator = useCallback((index) => props.onChange(
|
|
39
|
+
_.filter(props.value, (v, i) => i !== index)
|
|
40
|
+
), [props.onChange, props.value]);
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Updates the creator at the passed index.
|
|
44
|
+
*
|
|
45
|
+
* @type {function(*, *): *}
|
|
46
|
+
*/
|
|
47
|
+
const onUpdateCreator = useCallback((index, value) => props.onChange(
|
|
48
|
+
_.map(props.value, (v, i) => (i === index ? value : v))
|
|
49
|
+
), [props.onChange, props.value]);
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Updates the creator type on the items if the selected value is not longer valid.
|
|
53
|
+
*
|
|
54
|
+
* @type {(function(*): (*))|*}
|
|
55
|
+
*/
|
|
56
|
+
const onUpdateCreatorType = useCallback((item) => {
|
|
57
|
+
const creatorType = _.findWhere(props.creatorTypes, { value: item.creatorType });
|
|
58
|
+
if (creatorType) {
|
|
59
|
+
return item;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
...item,
|
|
64
|
+
creatorType: defaultCreatorType
|
|
65
|
+
};
|
|
66
|
+
}, [props.creatorTypes, defaultCreatorType]);
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Add the first creator when the component is mounted.
|
|
70
|
+
*/
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
onAddCreator();
|
|
73
|
+
}, []);
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* If the list of creator types changes, reset any invalid creator types to the default value.
|
|
77
|
+
*/
|
|
78
|
+
useEffect(() => {
|
|
79
|
+
if (props.value && props.value.length) {
|
|
80
|
+
props.onChange(_.map(props.value, onUpdateCreatorType));
|
|
81
|
+
}
|
|
82
|
+
}, [onUpdateCreatorType, props.creatorTypes]);
|
|
83
|
+
|
|
84
|
+
return _.map(props.value, (creator, index) => (
|
|
85
|
+
<CreatorField
|
|
86
|
+
allowDelete={props.value.length > 1}
|
|
87
|
+
creator={creator}
|
|
88
|
+
creatorTypes={props.creatorTypes}
|
|
89
|
+
key={index}
|
|
90
|
+
onAdd={() => onAddCreator()}
|
|
91
|
+
onDelete={() => onDeleteCreator(index)}
|
|
92
|
+
onUpdate={(value) => onUpdateCreator(index, value)}
|
|
93
|
+
/>
|
|
94
|
+
));
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
export default Creators;
|
package/src/components/List.js
CHANGED
|
@@ -41,8 +41,11 @@ type Props = {
|
|
|
41
41
|
addButton: {
|
|
42
42
|
basic: boolean,
|
|
43
43
|
color: string,
|
|
44
|
+
content?: string,
|
|
45
|
+
inverted?: boolean,
|
|
44
46
|
location: string,
|
|
45
|
-
onClick?: () => void
|
|
47
|
+
onClick?: () => void,
|
|
48
|
+
secondary?: boolean
|
|
46
49
|
},
|
|
47
50
|
buttons: Array<ListButton>,
|
|
48
51
|
count: number,
|
|
@@ -378,10 +381,12 @@ const useList = (WrappedComponent: ComponentType<any>) => (
|
|
|
378
381
|
basic={this.props.addButton.basic !== false}
|
|
379
382
|
color={this.props.addButton.color}
|
|
380
383
|
key={BUTTON_KEY_ADD}
|
|
384
|
+
inverted={this.props.addButton.inverted}
|
|
381
385
|
onClick={this.onAddButton.bind(this)}
|
|
386
|
+
secondary={this.props.addButton.secondary}
|
|
382
387
|
>
|
|
383
388
|
<Icon name='plus' />
|
|
384
|
-
{ i18n.t('List.buttons.add') }
|
|
389
|
+
{ this.props.addButton.content || i18n.t('List.buttons.add') }
|
|
385
390
|
</Button>
|
|
386
391
|
);
|
|
387
392
|
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import React, { useCallback, useEffect, useRef } from 'react';
|
|
4
|
+
import { Button, Dropdown } from 'semantic-ui-react';
|
|
5
|
+
import _ from 'underscore';
|
|
6
|
+
import { SORT_ASCENDING, SORT_DESCENDING } from '../constants/Sort';
|
|
7
|
+
|
|
8
|
+
type Option = {
|
|
9
|
+
key: string,
|
|
10
|
+
value: string,
|
|
11
|
+
text: string
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
type Sort = Option & {
|
|
15
|
+
direction?: string
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
type Props = {
|
|
19
|
+
defaultValue?: string,
|
|
20
|
+
direction: string,
|
|
21
|
+
onChange: (sort: Sort) => void,
|
|
22
|
+
options: Array<Option>,
|
|
23
|
+
text: string,
|
|
24
|
+
value: string
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// TODO: Add this to ItemsToggle component
|
|
28
|
+
const SortSelector = (props: Props) => {
|
|
29
|
+
const sortRef = useRef();
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Calls the onChange prop with the direction, text, and value of the selected sort.
|
|
33
|
+
*
|
|
34
|
+
* @type {(function(*): void)|*}
|
|
35
|
+
*/
|
|
36
|
+
const onSelection = useCallback((option) => {
|
|
37
|
+
const direction = props.value === option.value && props.direction === SORT_ASCENDING
|
|
38
|
+
? SORT_DESCENDING
|
|
39
|
+
: SORT_ASCENDING;
|
|
40
|
+
|
|
41
|
+
props.onChange({ ...option, direction });
|
|
42
|
+
}, [props.direction, props.onChange, props.value]);
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Set the default sort to the passed default value or the first option in the list.
|
|
46
|
+
*/
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
if (!props.value) {
|
|
49
|
+
let defaultSort;
|
|
50
|
+
|
|
51
|
+
if (props.defaultValue) {
|
|
52
|
+
defaultSort = _.findWhere(props.options, { value: props.defaultValue });
|
|
53
|
+
} else {
|
|
54
|
+
defaultSort = _.first(props.options);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
onSelection(defaultSort);
|
|
58
|
+
}
|
|
59
|
+
}, []);
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<Button.Group
|
|
63
|
+
basic
|
|
64
|
+
className='sort-selector'
|
|
65
|
+
style={{
|
|
66
|
+
fontSize: 'inherit'
|
|
67
|
+
}}
|
|
68
|
+
>
|
|
69
|
+
<Button
|
|
70
|
+
aria-label='Sort by'
|
|
71
|
+
content={props.text}
|
|
72
|
+
icon={props.direction === SORT_ASCENDING ? 'sort alphabet up' : 'sort alphabet down'}
|
|
73
|
+
onClick={(e) => sortRef.current.handleClick(e)}
|
|
74
|
+
/>
|
|
75
|
+
<Dropdown
|
|
76
|
+
aria-label='Sort'
|
|
77
|
+
className='button icon'
|
|
78
|
+
floating
|
|
79
|
+
options={_.map(props.options, (option) => ({
|
|
80
|
+
...option,
|
|
81
|
+
onClick: () => onSelection(option)
|
|
82
|
+
}))}
|
|
83
|
+
ref={sortRef}
|
|
84
|
+
trigger={<></>}
|
|
85
|
+
value={props.value}
|
|
86
|
+
/>
|
|
87
|
+
</Button.Group>
|
|
88
|
+
);
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export default SortSelector;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import React, {
|
|
4
|
+
useCallback,
|
|
5
|
+
useEffect,
|
|
6
|
+
useMemo,
|
|
7
|
+
useState
|
|
8
|
+
} from 'react';
|
|
9
|
+
import { Dropdown } from 'semantic-ui-react';
|
|
10
|
+
import _ from 'underscore';
|
|
11
|
+
import CitationStyles from '../resources/CitationStyles.json';
|
|
12
|
+
|
|
13
|
+
type Props = {
|
|
14
|
+
onChange: (name: string, xml: string) => void,
|
|
15
|
+
value: ?string
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const StyleSelector = (props: Props) => {
|
|
19
|
+
const [stylesCache, setStylesCache] = useState({});
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Build the list of available style options.
|
|
23
|
+
*
|
|
24
|
+
* @type {{}}
|
|
25
|
+
*/
|
|
26
|
+
const styles = useMemo(() => CitationStyles.coreCitationStyles, []);
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Sets the style to the selected value. Styles are cached on the state so they do not need to be fetched
|
|
30
|
+
* more than once per render.
|
|
31
|
+
*
|
|
32
|
+
* @type {(function(*, {value: *}): void)|*}
|
|
33
|
+
*/
|
|
34
|
+
const onChange = useCallback((e, { value }) => {
|
|
35
|
+
if (_.has(stylesCache, value)) {
|
|
36
|
+
props.onChange(value, stylesCache[value]);
|
|
37
|
+
} else {
|
|
38
|
+
fetch(`https://www.zotero.org/styles/${value}`)
|
|
39
|
+
.then((response) => response.text())
|
|
40
|
+
.then((xml) => {
|
|
41
|
+
props.onChange(value, xml);
|
|
42
|
+
setStylesCache((prevCache) => ({ ...prevCache, [value]: xml }));
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}, [stylesCache]);
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Default the selected style on component mount.
|
|
49
|
+
*/
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
const { name } = _.findWhere(styles, { isDefault: true });
|
|
52
|
+
onChange(null, { value: name });
|
|
53
|
+
}, []);
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<Dropdown
|
|
57
|
+
onChange={onChange}
|
|
58
|
+
options={_.map(styles, (style) => ({
|
|
59
|
+
key: style.name,
|
|
60
|
+
value: style.name,
|
|
61
|
+
text: style.title
|
|
62
|
+
}))}
|
|
63
|
+
search
|
|
64
|
+
searchInput={{
|
|
65
|
+
'aria-label': 'Search styles',
|
|
66
|
+
}}
|
|
67
|
+
selectOnBlur={false}
|
|
68
|
+
selection
|
|
69
|
+
text={_.findWhere(styles, { name: props.value })?.title}
|
|
70
|
+
value={props.value}
|
|
71
|
+
/>
|
|
72
|
+
);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export default StyleSelector;
|
package/src/i18n/en.json
CHANGED
|
@@ -16,6 +16,26 @@
|
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
},
|
|
19
|
+
"BibliographyList": {
|
|
20
|
+
"sort": {
|
|
21
|
+
"author": "Author",
|
|
22
|
+
"date": "Date",
|
|
23
|
+
"title": "Title"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"BibliographyModal": {
|
|
27
|
+
"title": "Add Entry"
|
|
28
|
+
},
|
|
29
|
+
"BibliographySearchInput": {
|
|
30
|
+
"labels": {
|
|
31
|
+
"placeholder": "Enter a URL, ISBN, DOI, PMID, arXiv ID"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"Citation": {
|
|
35
|
+
"labels": {
|
|
36
|
+
"untitled": "Untitled"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
19
39
|
"Common": {
|
|
20
40
|
"buttons": {
|
|
21
41
|
"add": "Add",
|
|
@@ -28,6 +48,7 @@
|
|
|
28
48
|
"ok": "OK",
|
|
29
49
|
"open": "Open",
|
|
30
50
|
"save": "Save",
|
|
51
|
+
"search": "Search",
|
|
31
52
|
"upload": "Upload"
|
|
32
53
|
},
|
|
33
54
|
"errors": {
|
|
@@ -41,12 +62,20 @@
|
|
|
41
62
|
"header": "Oops!"
|
|
42
63
|
},
|
|
43
64
|
"loading": "Loading",
|
|
65
|
+
"noResults": "No results found.",
|
|
44
66
|
"save": {
|
|
45
67
|
"content": "Your changes have been saved.",
|
|
46
68
|
"header": "Success!"
|
|
47
69
|
}
|
|
48
70
|
}
|
|
49
71
|
},
|
|
72
|
+
"CreatorField": {
|
|
73
|
+
"labels": {
|
|
74
|
+
"firstName": "First name",
|
|
75
|
+
"lastName": "Last name",
|
|
76
|
+
"name": "Name"
|
|
77
|
+
}
|
|
78
|
+
},
|
|
50
79
|
"EditContainer": {
|
|
51
80
|
"errors": {
|
|
52
81
|
"general": "Something went wrong while saving the record. Please make sure all required fields are filled out.",
|
package/src/index.js
CHANGED
|
@@ -10,6 +10,7 @@ export { default as AccordionSelector } from './components/AccordionSelector';
|
|
|
10
10
|
export { default as ArrowButtons } from './components/ArrowButtons';
|
|
11
11
|
export { default as AssociatedDropdown } from './components/AssociatedDropdown';
|
|
12
12
|
export { default as AudioPlayer } from './components/AudioPlayer';
|
|
13
|
+
export { default as BibliographyList } from './components/BibliographyList';
|
|
13
14
|
export { default as BooleanIcon } from './components/BooleanIcon';
|
|
14
15
|
export { default as CancelButton } from './components/CancelButton';
|
|
15
16
|
export { default as ColorButton } from './components/ColorButton';
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
{
|
|
2
|
+
"artwork": {
|
|
3
|
+
"medium": "artworkMedium"
|
|
4
|
+
},
|
|
5
|
+
"audioRecording": {
|
|
6
|
+
"medium": "audioRecordingFormat",
|
|
7
|
+
"publisher": "label"
|
|
8
|
+
},
|
|
9
|
+
"bill": {
|
|
10
|
+
"number": "billNumber",
|
|
11
|
+
"volume": "codeVolume",
|
|
12
|
+
"pages": "codePages"
|
|
13
|
+
},
|
|
14
|
+
"blogPost": {
|
|
15
|
+
"publicationTitle": "blogTitle",
|
|
16
|
+
"type": "websiteType"
|
|
17
|
+
},
|
|
18
|
+
"bookSection": {
|
|
19
|
+
"publicationTitle": "bookTitle"
|
|
20
|
+
},
|
|
21
|
+
"case": {
|
|
22
|
+
"title": "caseName",
|
|
23
|
+
"date": "dateDecided",
|
|
24
|
+
"number": "docketNumber",
|
|
25
|
+
"volume": "reporterVolume",
|
|
26
|
+
"pages": "firstPage"
|
|
27
|
+
},
|
|
28
|
+
"computerProgram": {
|
|
29
|
+
"publisher": "company"
|
|
30
|
+
},
|
|
31
|
+
"conferencePaper": {
|
|
32
|
+
"publicationTitle": "proceedingsTitle"
|
|
33
|
+
},
|
|
34
|
+
"dictionaryEntry": {
|
|
35
|
+
"publicationTitle": "dictionaryTitle"
|
|
36
|
+
},
|
|
37
|
+
"email": {
|
|
38
|
+
"title": "subject"
|
|
39
|
+
},
|
|
40
|
+
"encyclopediaArticle": {
|
|
41
|
+
"publicationTitle": "encyclopediaTitle"
|
|
42
|
+
},
|
|
43
|
+
"film": {
|
|
44
|
+
"publisher": "distributor",
|
|
45
|
+
"type": "genre",
|
|
46
|
+
"medium": "videoRecordingFormat"
|
|
47
|
+
},
|
|
48
|
+
"forumPost": {
|
|
49
|
+
"publicationTitle": "forumTitle",
|
|
50
|
+
"type": "postType"
|
|
51
|
+
},
|
|
52
|
+
"hearing": {
|
|
53
|
+
"number": "documentNumber"
|
|
54
|
+
},
|
|
55
|
+
"interview": {
|
|
56
|
+
"medium": "interviewMedium"
|
|
57
|
+
},
|
|
58
|
+
"letter": {
|
|
59
|
+
"type": "letterType"
|
|
60
|
+
},
|
|
61
|
+
"manuscript": {
|
|
62
|
+
"type": "manuscriptType"
|
|
63
|
+
},
|
|
64
|
+
"map": {
|
|
65
|
+
"type": "mapType"
|
|
66
|
+
},
|
|
67
|
+
"patent": {
|
|
68
|
+
"number": "patentNumber",
|
|
69
|
+
"date": "issueDate"
|
|
70
|
+
},
|
|
71
|
+
"podcast": {
|
|
72
|
+
"number": "episodeNumber",
|
|
73
|
+
"medium": "audioFileType"
|
|
74
|
+
},
|
|
75
|
+
"preprint": {
|
|
76
|
+
"type": "genre",
|
|
77
|
+
"publisher": "repository",
|
|
78
|
+
"number": "archiveID"
|
|
79
|
+
},
|
|
80
|
+
"presentation": {
|
|
81
|
+
"type": "presentationType"
|
|
82
|
+
},
|
|
83
|
+
"radioBroadcast": {
|
|
84
|
+
"publicationTitle": "programTitle",
|
|
85
|
+
"number": "episodeNumber",
|
|
86
|
+
"medium": "audioRecordingFormat",
|
|
87
|
+
"publisher": "network"
|
|
88
|
+
},
|
|
89
|
+
"report": {
|
|
90
|
+
"number": "reportNumber",
|
|
91
|
+
"type": "reportType",
|
|
92
|
+
"publisher": "institution"
|
|
93
|
+
},
|
|
94
|
+
"statute": {
|
|
95
|
+
"title": "nameOfAct",
|
|
96
|
+
"number": "publicLawNumber",
|
|
97
|
+
"date": "dateEnacted"
|
|
98
|
+
},
|
|
99
|
+
"thesis": {
|
|
100
|
+
"type": "thesisType",
|
|
101
|
+
"publisher": "university"
|
|
102
|
+
},
|
|
103
|
+
"tvBroadcast": {
|
|
104
|
+
"publicationTitle": "programTitle",
|
|
105
|
+
"number": "episodeNumber",
|
|
106
|
+
"medium": "videoRecordingFormat",
|
|
107
|
+
"publisher": "network"
|
|
108
|
+
},
|
|
109
|
+
"videoRecording": {
|
|
110
|
+
"medium": "videoRecordingFormat",
|
|
111
|
+
"publisher": "studio"
|
|
112
|
+
},
|
|
113
|
+
"webpage": {
|
|
114
|
+
"publicationTitle": "websiteTitle",
|
|
115
|
+
"type": "websiteType"
|
|
116
|
+
}
|
|
117
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"coreCitationStyles": [
|
|
3
|
+
{
|
|
4
|
+
"isDefault": false,
|
|
5
|
+
"name": "apa",
|
|
6
|
+
"title": "American Psychological Association 7th edition"
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"isDefault": false,
|
|
10
|
+
"name": "chicago-note-bibliography",
|
|
11
|
+
"title": "Chicago Manual of Style 17th edition (note)"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"isDefault": true,
|
|
15
|
+
"name": "modern-language-association",
|
|
16
|
+
"title": "Modern Language Association 9th edition"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"isDefault": false,
|
|
20
|
+
"name": "turabian-fullnote-bibliography",
|
|
21
|
+
"title": "Turabian 8th edition (full note)"
|
|
22
|
+
}
|
|
23
|
+
],
|
|
24
|
+
"citationStylesCount": 10349
|
|
25
|
+
}
|