@performant-software/semantic-components 1.0.8-beta.2 → 1.0.9-beta.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@performant-software/semantic-components",
3
- "version": "1.0.8-beta.2",
3
+ "version": "1.0.9-beta.0",
4
4
  "description": "A package of shared components based on the Semantic UI Framework.",
5
5
  "license": "MIT",
6
6
  "main": "./build/index.js",
@@ -12,10 +12,9 @@
12
12
  "build": "webpack --mode production && flow-copy-source -v src types"
13
13
  },
14
14
  "dependencies": {
15
- "@performant-software/shared-components": "^1.0.8-beta.2",
15
+ "@performant-software/shared-components": "^1.0.9-beta.0",
16
16
  "@react-google-maps/api": "^2.8.1",
17
17
  "axios": "^0.26.1",
18
- "citeproc": "^2.4.62",
19
18
  "i18next": "^19.4.4",
20
19
  "react-calendar": "^3.3.0",
21
20
  "react-color": "^2.18.1",
@@ -1,5 +1,6 @@
1
1
  // @flow
2
2
 
3
+ import { Citation } from '@performant-software/shared-components';
3
4
  import React, {
4
5
  useCallback,
5
6
  useEffect,
@@ -17,7 +18,6 @@ import {
17
18
  import _ from 'underscore';
18
19
  import BibliographyModal from './BibliographyModal';
19
20
  import BibliographySearchInput from './BibliographySearchInput';
20
- import Citation from './Citation';
21
21
  import i18n from '../i18n/i18n';
22
22
  import SortSelector from './SortSelector';
23
23
  import { SORT_DESCENDING } from '../constants/Sort';
@@ -196,7 +196,6 @@ const BibliographyList = (props: Props) => {
196
196
  <>
197
197
  <StyleSelector
198
198
  onChange={(name, xml) => setStyle({ name, xml })}
199
- value={style && style.name}
200
199
  />
201
200
  <SortSelector
202
201
  direction={sort.direction}
@@ -1,14 +1,9 @@
1
1
  // @flow
2
2
 
3
- import React, {
4
- useCallback,
5
- useEffect,
6
- useMemo,
7
- useState
8
- } from 'react';
3
+ import useCitationStyles from '@performant-software/shared-components';
4
+ import React, { useEffect } from 'react';
9
5
  import { Dropdown } from 'semantic-ui-react';
10
6
  import _ from 'underscore';
11
- import CitationStyles from '../resources/CitationStyles.json';
12
7
 
13
8
  type Props = {
14
9
  onChange: (name: string, xml: string) => void,
@@ -16,49 +11,24 @@ type Props = {
16
11
  };
17
12
 
18
13
  const StyleSelector = (props: Props) => {
19
- const [stylesCache, setStylesCache] = useState({});
14
+ const { onStyleChange, style, styles } = useCitationStyles(props.value);
20
15
 
21
16
  /**
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.
17
+ * Call the onChange prop when the style changes.
49
18
  */
50
19
  useEffect(() => {
51
- const { name } = _.findWhere(styles, { isDefault: true });
52
- onChange(null, { value: name });
53
- }, []);
20
+ if (style?.name && style?.xml) {
21
+ props.onChange(style.name, style.xml);
22
+ }
23
+ }, [style]);
54
24
 
55
25
  return (
56
26
  <Dropdown
57
- onChange={onChange}
58
- options={_.map(styles, (style) => ({
59
- key: style.name,
60
- value: style.name,
61
- text: style.title
27
+ onChange={(e, { value }) => onStyleChange(value)}
28
+ options={_.map(styles, ({ name, title }) => ({
29
+ key: name,
30
+ value: name,
31
+ text: title
62
32
  }))}
63
33
  search
64
34
  searchInput={{
@@ -66,8 +36,8 @@ const StyleSelector = (props: Props) => {
66
36
  }}
67
37
  selectOnBlur={false}
68
38
  selection
69
- text={_.findWhere(styles, { name: props.value })?.title}
70
- value={props.value}
39
+ text={style?.title}
40
+ value={style?.name || ''}
71
41
  />
72
42
  );
73
43
  };
@@ -1,5 +1,6 @@
1
1
  // @flow
2
2
 
3
+ import { Citation } from '@performant-software/shared-components';
3
4
  import React, {
4
5
  useCallback,
5
6
  useEffect,
@@ -17,7 +18,6 @@ import {
17
18
  import _ from 'underscore';
18
19
  import BibliographyModal from './BibliographyModal';
19
20
  import BibliographySearchInput from './BibliographySearchInput';
20
- import Citation from './Citation';
21
21
  import i18n from '../i18n/i18n';
22
22
  import SortSelector from './SortSelector';
23
23
  import { SORT_DESCENDING } from '../constants/Sort';
@@ -196,7 +196,6 @@ const BibliographyList = (props: Props) => {
196
196
  <>
197
197
  <StyleSelector
198
198
  onChange={(name, xml) => setStyle({ name, xml })}
199
- value={style && style.name}
200
199
  />
201
200
  <SortSelector
202
201
  direction={sort.direction}
@@ -1,14 +1,9 @@
1
1
  // @flow
2
2
 
3
- import React, {
4
- useCallback,
5
- useEffect,
6
- useMemo,
7
- useState
8
- } from 'react';
3
+ import useCitationStyles from '@performant-software/shared-components';
4
+ import React, { useEffect } from 'react';
9
5
  import { Dropdown } from 'semantic-ui-react';
10
6
  import _ from 'underscore';
11
- import CitationStyles from '../resources/CitationStyles.json';
12
7
 
13
8
  type Props = {
14
9
  onChange: (name: string, xml: string) => void,
@@ -16,49 +11,24 @@ type Props = {
16
11
  };
17
12
 
18
13
  const StyleSelector = (props: Props) => {
19
- const [stylesCache, setStylesCache] = useState({});
14
+ const { onStyleChange, style, styles } = useCitationStyles(props.value);
20
15
 
21
16
  /**
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.
17
+ * Call the onChange prop when the style changes.
49
18
  */
50
19
  useEffect(() => {
51
- const { name } = _.findWhere(styles, { isDefault: true });
52
- onChange(null, { value: name });
53
- }, []);
20
+ if (style?.name && style?.xml) {
21
+ props.onChange(style.name, style.xml);
22
+ }
23
+ }, [style]);
54
24
 
55
25
  return (
56
26
  <Dropdown
57
- onChange={onChange}
58
- options={_.map(styles, (style) => ({
59
- key: style.name,
60
- value: style.name,
61
- text: style.title
27
+ onChange={(e, { value }) => onStyleChange(value)}
28
+ options={_.map(styles, ({ name, title }) => ({
29
+ key: name,
30
+ value: name,
31
+ text: title
62
32
  }))}
63
33
  search
64
34
  searchInput={{
@@ -66,8 +36,8 @@ const StyleSelector = (props: Props) => {
66
36
  }}
67
37
  selectOnBlur={false}
68
38
  selection
69
- text={_.findWhere(styles, { name: props.value })?.title}
70
- value={props.value}
39
+ text={style?.title}
40
+ value={style?.name || ''}
71
41
  />
72
42
  );
73
43
  };
@@ -1,78 +0,0 @@
1
- // @flow
2
-
3
- import CSL from 'citeproc';
4
- import React, { useCallback, useEffect, useState } from 'react';
5
- import _ from 'underscore';
6
- import ZoteroTranslationClient from 'zotero-translation-client';
7
- import i18n from '../i18n/i18n';
8
-
9
- type Props = {
10
- item: {
11
- uid: string,
12
- data: any
13
- },
14
- locale: string,
15
- style: string
16
- };
17
-
18
- const Citation = (props: Props) => {
19
- const [formattedCitation, setFormattedCitation] = useState();
20
-
21
- /**
22
- * Validates the passed item.
23
- *
24
- * @param item
25
- *
26
- * @returns {*}
27
- */
28
- const validateItem = useCallback((item) => {
29
- const validItem = { ...item };
30
-
31
- // Handle completely empty record
32
- if (_.isEmpty(validItem.title) && _.isEmpty(validItem.creators) && _.isEmpty(validItem.issue)) {
33
- _.extend(validItem, { title: i18n.t('Citation.labels.untitled') });
34
- }
35
-
36
- return validItem;
37
- }, []);
38
-
39
- /**
40
- * Format the citation record by coverting the Zotero JSON to CSL.
41
- */
42
- useEffect(() => {
43
- if (props.locale && props.style && props.item) {
44
- // Translate from Zotero JSON to CSL
45
- const { uid, ...rest } = props.item;
46
-
47
- const translator = new ZoteroTranslationClient({
48
- initialItems: [{ key: uid, ...validateItem(rest) }],
49
- persist: false
50
- });
51
-
52
- const item = _.first(translator.itemsCSL);
53
-
54
- // Use the CSL engine to format the item
55
- const sys = {
56
- retrieveLocale: () => props.locale,
57
- retrieveItem: () => item
58
- };
59
-
60
- const citeproc = new CSL.Engine(sys, props.style);
61
- citeproc.updateItems([item.id]);
62
-
63
- // Save the citation on the state.
64
- const result = citeproc.makeBibliography();
65
- setFormattedCitation(_.last(result));
66
- }
67
- }, [validateItem, props.item, props.locale, props.style]);
68
-
69
- return (
70
- <div
71
- dangerouslySetInnerHTML={{
72
- __html: formattedCitation
73
- }}
74
- />
75
- );
76
- };
77
-
78
- export default Citation;