@manuscripts/style-guide 1.6.2 → 1.7.0-LEAN-3092-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.
Files changed (67) hide show
  1. package/dist/cjs/components/Dialog.js +3 -3
  2. package/dist/cjs/components/References/BibliographyItemSource.js +91 -0
  3. package/dist/cjs/components/References/CitationEditor.js +146 -0
  4. package/dist/cjs/components/References/CitationViewer.js +69 -0
  5. package/dist/cjs/components/References/ReferenceForm.js +415 -0
  6. package/dist/cjs/components/References/ReferenceLine.js +52 -0
  7. package/dist/cjs/components/References/ReferenceSearch.js +124 -0
  8. package/dist/cjs/components/References/ReferenceSearchResults.js +68 -0
  9. package/dist/cjs/components/References/ReferenceSearchResultsPlaceholder.js +43 -0
  10. package/dist/cjs/components/References/ReferenceSearchSection.js +118 -0
  11. package/dist/cjs/components/References/ReferencesModal.js +219 -0
  12. package/dist/cjs/components/References/SearchInput.js +103 -0
  13. package/dist/cjs/components/References/index.js +20 -0
  14. package/dist/cjs/components/SelectField.js +25 -0
  15. package/dist/cjs/components/Sidebar.js +44 -0
  16. package/dist/cjs/components/StyledModal.js +80 -3
  17. package/dist/cjs/components/icons/delete-icon.js +15 -0
  18. package/dist/cjs/components/icons/link-icon.js +11 -0
  19. package/dist/cjs/components/icons/template-icon.js +11 -0
  20. package/dist/cjs/hooks/use-scroll-detection.js +53 -0
  21. package/dist/cjs/index.js +1 -1
  22. package/dist/es/components/Dialog.js +2 -2
  23. package/dist/es/components/References/BibliographyItemSource.js +64 -0
  24. package/dist/es/components/References/CitationEditor.js +116 -0
  25. package/dist/es/components/References/CitationViewer.js +39 -0
  26. package/dist/es/components/References/ReferenceForm.js +385 -0
  27. package/dist/es/components/References/ReferenceLine.js +42 -0
  28. package/dist/es/components/References/ReferenceSearch.js +94 -0
  29. package/dist/es/components/References/ReferenceSearchResults.js +61 -0
  30. package/dist/es/components/References/ReferenceSearchResultsPlaceholder.js +36 -0
  31. package/dist/es/components/References/ReferenceSearchSection.js +88 -0
  32. package/dist/es/components/References/ReferencesModal.js +188 -0
  33. package/dist/es/components/References/SearchInput.js +73 -0
  34. package/dist/es/components/References/index.js +4 -0
  35. package/dist/es/components/SelectField.js +18 -0
  36. package/dist/es/components/Sidebar.js +18 -0
  37. package/dist/es/components/StyledModal.js +81 -3
  38. package/dist/es/components/icons/delete-icon.js +8 -0
  39. package/dist/es/components/icons/link-icon.js +4 -0
  40. package/dist/es/components/icons/template-icon.js +4 -0
  41. package/dist/es/hooks/use-scroll-detection.js +49 -0
  42. package/dist/es/index.js +1 -1
  43. package/dist/types/components/Dialog.d.ts +1 -1
  44. package/dist/types/components/References/BibliographyItemSource.d.ts +38 -0
  45. package/dist/types/components/References/CitationEditor.d.ts +18 -0
  46. package/dist/types/components/References/CitationViewer.d.ts +24 -0
  47. package/dist/types/components/References/ReferenceForm.d.ts +35 -0
  48. package/dist/types/components/References/ReferenceLine.d.ts +10 -0
  49. package/dist/types/components/References/ReferenceSearch.d.ts +26 -0
  50. package/dist/types/components/References/ReferenceSearchResults.d.ts +26 -0
  51. package/dist/types/components/References/ReferenceSearchResultsPlaceholder.d.ts +2 -0
  52. package/dist/types/components/References/ReferenceSearchSection.d.ts +25 -0
  53. package/dist/types/components/References/ReferencesModal.d.ts +14 -0
  54. package/dist/types/components/References/SearchInput.d.ts +18 -0
  55. package/dist/types/components/References/index.d.ts +4 -0
  56. package/dist/types/components/SelectField.d.ts +27 -0
  57. package/dist/types/components/Sidebar.d.ts +2 -0
  58. package/dist/types/components/StyledModal.d.ts +26 -4
  59. package/dist/types/components/icons/delete-icon.d.ts +2 -0
  60. package/dist/types/components/icons/link-icon.d.ts +2 -0
  61. package/dist/types/components/icons/template-icon.d.ts +2 -0
  62. package/dist/types/hooks/use-scroll-detection.d.ts +22 -0
  63. package/dist/types/index.d.ts +1 -1
  64. package/package.json +4 -3
  65. package/dist/cjs/components/SimpleModal.js +0 -95
  66. package/dist/es/components/SimpleModal.js +0 -88
  67. package/dist/types/components/SimpleModal.d.ts +0 -41
@@ -0,0 +1,88 @@
1
+ /*!
2
+ * © 2023 Atypon Systems LLC
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
17
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
18
+ return new (P || (P = Promise))(function (resolve, reject) {
19
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
20
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
21
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
22
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
23
+ });
24
+ };
25
+ import ArrowDownUp from '@manuscripts/assets/react/ArrowDownUp';
26
+ import React, { useEffect, useState } from 'react';
27
+ import styled from 'styled-components';
28
+ import { ReferenceSearchResults } from './ReferenceSearchResults';
29
+ import { ReferenceSearchResultsPlaceholder } from './ReferenceSearchResultsPlaceholder';
30
+ const SearchSourceLabel = styled.div `
31
+ margin: 0 ${(props) => props.theme.grid.unit * 4}px
32
+ ${(props) => props.theme.grid.unit * 2}px;
33
+ color: ${(props) => props.theme.colors.text.secondary};
34
+ cursor: pointer;
35
+
36
+ &:hover {
37
+ color: ${(props) => props.theme.colors.text.muted};
38
+ }
39
+ `;
40
+ export const Arrow = styled(ArrowDownUp) `
41
+ margin-right: 16px;
42
+ margin-left: 10px;
43
+
44
+ user-select: none;
45
+
46
+ transform: rotate(180deg);
47
+
48
+ &.open {
49
+ transform: rotate(0deg);
50
+ }
51
+ `;
52
+ export const ReferenceSearchSection = ({ query, source, isSelected, onSelect }) => {
53
+ const [expanded, setExpanded] = useState(true);
54
+ const [state, setState] = useState();
55
+ const [limit, setLimit] = useState(3);
56
+ const toggleExpanded = () => {
57
+ setExpanded((value) => !value);
58
+ };
59
+ useEffect(() => {
60
+ const search = () => __awaiter(void 0, void 0, void 0, function* () {
61
+ const job = source.search(query, limit);
62
+ setState((s) => {
63
+ if ((s === null || s === void 0 ? void 0 : s.type) === 'running' && s.job.cancel) {
64
+ s.job.cancel();
65
+ }
66
+ return {
67
+ type: 'running',
68
+ job,
69
+ };
70
+ });
71
+ const response = yield job.response;
72
+ if (job.isCancelled) {
73
+ return;
74
+ }
75
+ setState(Object.assign({ type: 'completed' }, response));
76
+ });
77
+ search();
78
+ }, [source, query, limit]);
79
+ const handleShowMore = () => {
80
+ setLimit(25);
81
+ };
82
+ return (React.createElement(React.Fragment, null,
83
+ React.createElement(SearchSourceLabel, { onClick: toggleExpanded },
84
+ React.createElement(Arrow, { className: expanded ? 'open' : '' }),
85
+ source.label),
86
+ expanded && (state === null || state === void 0 ? void 0 : state.type) === 'running' && (React.createElement(ReferenceSearchResultsPlaceholder, null)),
87
+ expanded && (state === null || state === void 0 ? void 0 : state.type) === 'completed' && (React.createElement(ReferenceSearchResults, { items: state.items, total: state.total, isSelected: isSelected, onSelect: onSelect, onShowMore: handleShowMore }))));
88
+ };
@@ -0,0 +1,188 @@
1
+ import ReferenceLibraryIcon from '@manuscripts/assets/react/ReferenceLibraryIcon';
2
+ import { isEqual } from 'lodash';
3
+ import React, { useEffect, useRef, useState } from 'react';
4
+ import ReactTooltip from 'react-tooltip';
5
+ import styled from 'styled-components';
6
+ import { useScrollDetection } from '../../hooks/use-scroll-detection';
7
+ import { Category, Dialog } from '../Dialog';
8
+ import { SidebarContent } from '../Sidebar';
9
+ import { CloseButton, ModalBody, ModalContainer, ModalHeader, ModalSidebar, ModalSidebarHeader, ModalSidebarTitle, ScrollableModalContent, StyledModal, } from '../StyledModal';
10
+ import { ReferenceForm, } from './ReferenceForm';
11
+ import { ReferenceLine } from './ReferenceLine';
12
+ const ReferencesModalContainer = styled(ModalContainer) `
13
+ min-width: 960px;
14
+ `;
15
+ const ReferencesSidebar = styled(ModalSidebar) `
16
+ width: 70%;
17
+ `;
18
+ const ReferencesSidebarContent = styled(SidebarContent) `
19
+ overflow-y: auto;
20
+ `;
21
+ const ReferencesInnerWrapper = styled.div `
22
+ width: 100%;
23
+ `;
24
+ const ReferenceButton = styled.div `
25
+ cursor: pointer;
26
+ display: flex;
27
+ justify-content: flex-start;
28
+ padding: ${(props) => props.theme.grid.unit * 4}px 0;
29
+ border-top: 1px solid transparent;
30
+ border-bottom: 1px solid transparent;
31
+
32
+ path {
33
+ fill: #c9c9c9;
34
+ }
35
+
36
+ :hover {
37
+ background: ${(props) => props.theme.colors.background.info};
38
+ }
39
+
40
+ &.selected {
41
+ background: ${(props) => props.theme.colors.background.info};
42
+ border-top-color: #bce7f6;
43
+ border-bottom-color: #bce7f6;
44
+ }
45
+
46
+ .tooltip {
47
+ max-width: ${(props) => props.theme.grid.unit * 25}px;
48
+ padding: ${(props) => props.theme.grid.unit * 2}px;
49
+ border-radius: 6px;
50
+ }
51
+ `;
52
+ const IconContainer = styled.div `
53
+ padding-right: ${(props) => props.theme.grid.unit * 5}px;
54
+ position: relative;
55
+ `;
56
+ const CitationCount = styled.div `
57
+ border-radius: 50%;
58
+ width: 12px;
59
+ height: 12px;
60
+ position: absolute;
61
+ color: #ffffff;
62
+ background-color: #bce7f6;
63
+ text-align: center;
64
+ vertical-align: top;
65
+ top: 0;
66
+ left: 16px;
67
+ font-size: 9px;
68
+
69
+ &.unused {
70
+ background-color: #fe8f1f;
71
+ }
72
+ `;
73
+ const selectionTopOffset = 10;
74
+ const pageSize = 12;
75
+ const topTrigger = 0.2;
76
+ const bottomTrigger = 0.8;
77
+ const dropLimit = 36;
78
+ export const normalize = (item) => ({
79
+ _id: item._id,
80
+ title: item.title || '',
81
+ author: item.author || [],
82
+ DOI: item.DOI || '',
83
+ issued: item.issued,
84
+ type: item.type || '',
85
+ 'container-title': item['container-title'] || '',
86
+ URL: item.URL || '',
87
+ issue: item.issue ? String(item.issue) : '',
88
+ volume: item.volume ? String(item.volume) : '',
89
+ supplement: item.supplement ? String(item.supplement) : '',
90
+ page: item.page ? String(item.page) : '',
91
+ });
92
+ export const ReferencesModal = ({ isOpen, onCancel, items, item, citationCounts, onSave, onDelete, }) => {
93
+ const [confirm, setConfirm] = useState(false);
94
+ const valuesRef = useRef();
95
+ const [selection, setSelection] = useState();
96
+ const selectionRef = useRef(null);
97
+ const isSelected = (item) => {
98
+ return item._id === (selection === null || selection === void 0 ? void 0 : selection._id);
99
+ };
100
+ const selectionIndex = items.findIndex(isSelected);
101
+ useEffect(() => {
102
+ setSelection(item);
103
+ }, [item]);
104
+ useEffect(() => {
105
+ setTimeout(() => {
106
+ var _a;
107
+ (_a = selectionRef.current) === null || _a === void 0 ? void 0 : _a.scrollIntoView({
108
+ block: 'center',
109
+ behavior: 'auto',
110
+ });
111
+ }, 100);
112
+ }, [selectionIndex]);
113
+ const { ref, triggers } = useScrollDetection(topTrigger, bottomTrigger);
114
+ const [startIndex, setStartIndex] = useState(Math.max(0, selectionIndex - selectionTopOffset));
115
+ const [endIndex, setEndIndex] = useState(pageSize);
116
+ useEffect(() => {
117
+ const base = Math.max(0, selectionIndex - selectionTopOffset);
118
+ setStartIndex(base);
119
+ setEndIndex(Math.min(items.length - 1, base + pageSize));
120
+ }, [selectionIndex, items]);
121
+ useEffect(() => {
122
+ if (triggers.top) {
123
+ const newFirst = Math.max(0, startIndex - pageSize);
124
+ setStartIndex(newFirst);
125
+ setEndIndex(Math.min(newFirst + dropLimit, endIndex));
126
+ }
127
+ if (triggers.bottom) {
128
+ const newLast = Math.min(items.length - 1, endIndex + pageSize);
129
+ setEndIndex(newLast);
130
+ setStartIndex(Math.max(newLast - dropLimit, startIndex));
131
+ }
132
+ }, [triggers, items]);
133
+ const actionsRef = useRef();
134
+ const reset = () => {
135
+ var _a;
136
+ (_a = actionsRef.current) === null || _a === void 0 ? void 0 : _a.reset();
137
+ setConfirm(false);
138
+ };
139
+ const save = (values) => {
140
+ if (!values || !selection) {
141
+ return;
142
+ }
143
+ const item = Object.assign(Object.assign({}, selection), values);
144
+ onSave(item);
145
+ setSelection(item);
146
+ setConfirm(false);
147
+ };
148
+ const handleItemClick = (item) => {
149
+ const values = valuesRef.current;
150
+ if (values && selection && !isEqual(values, normalize(selection))) {
151
+ setConfirm(true);
152
+ return;
153
+ }
154
+ setSelection(item);
155
+ };
156
+ const handleChange = (values) => {
157
+ valuesRef.current = values;
158
+ };
159
+ if (items.length <= 0) {
160
+ return React.createElement(React.Fragment, null);
161
+ }
162
+ return (React.createElement(StyledModal, { isOpen: isOpen, onRequestClose: onCancel },
163
+ React.createElement(Dialog, { isOpen: confirm, category: Category.confirmation, header: "You've made changes to this option", message: "Would you like to save or discard your changes?", actions: {
164
+ secondary: {
165
+ action: () => reset(),
166
+ title: 'Discard',
167
+ },
168
+ primary: {
169
+ action: () => save(valuesRef.current),
170
+ title: 'Save',
171
+ },
172
+ } }),
173
+ React.createElement(ReferencesModalContainer, null,
174
+ React.createElement(ModalHeader, null,
175
+ React.createElement(CloseButton, { onClick: onCancel })),
176
+ React.createElement(ModalBody, null,
177
+ React.createElement(ReferencesSidebar, null,
178
+ React.createElement(ModalSidebarHeader, null,
179
+ React.createElement(ModalSidebarTitle, null, "References")),
180
+ React.createElement(ReferencesSidebarContent, { ref: ref },
181
+ React.createElement(ReferencesInnerWrapper, null, items.slice(startIndex, endIndex + 1).map((item) => (React.createElement(ReferenceButton, { key: item._id, id: item._id, className: isSelected(item) ? 'selected' : '', onClick: () => handleItemClick(item), ref: isSelected(item) ? selectionRef : null },
182
+ React.createElement(IconContainer, { "data-tip": true, "data-for": 'citation-count' },
183
+ React.createElement(ReferenceLibraryIcon, null),
184
+ React.createElement(CitationCount, { className: citationCounts.get(item._id) ? '' : 'unused' }, citationCounts.get(item._id) || 0),
185
+ React.createElement(ReactTooltip, { disable: (citationCounts.get(item._id) || 0) < 1, id: "citation-count", place: "bottom", effect: "solid", offset: { top: 40 }, className: "tooltip" }, "Number of times used in the document")),
186
+ React.createElement(ReferenceLine, { item: item }))))))),
187
+ React.createElement(ScrollableModalContent, null, selection && (React.createElement(ReferenceForm, { values: normalize(selection), showDelete: !citationCounts.get(selection._id), onChange: handleChange, onCancel: onCancel, onDelete: () => onDelete(selection), onSave: save, actionsRef: actionsRef })))))));
188
+ };
@@ -0,0 +1,73 @@
1
+ /*!
2
+ * © 2023 Atypon Systems LLC
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import SearchIconNoBGc from '@manuscripts/assets/react/SearchIconNoBG';
17
+ import React, { useState } from 'react';
18
+ import styled from 'styled-components';
19
+ import { TextField } from '../TextField';
20
+ const SearchContainer = styled.div `
21
+ align-items: center;
22
+ display: flex;
23
+ flex: 1 0 auto;
24
+ position: relative;
25
+ margin: 12px;
26
+ `;
27
+ const SearchIconContainer = styled.span `
28
+ display: flex;
29
+ left: ${(props) => props.theme.grid.unit * 4}px;
30
+ position: absolute;
31
+ z-index: 2;
32
+
33
+ path {
34
+ fill: ${(props) => props.theme.colors.text.primary};
35
+ }
36
+
37
+ &.active path {
38
+ fill: ${(props) => props.theme.colors.brand.medium};
39
+ }
40
+ `;
41
+ const SearchTextField = styled(TextField) `
42
+ -webkit-appearance: textfield;
43
+ padding-left: ${(props) => props.theme.grid.unit * 11}px;
44
+ &:hover,
45
+ &:focus {
46
+ background-color: ${(props) => props.theme.colors.background.fifth};
47
+ }
48
+ `;
49
+ export const SearchWrapper = styled.div `
50
+ display: flex;
51
+ align-items: center;
52
+ padding: ${(props) => props.theme.grid.unit * 3}px;
53
+ `;
54
+ export const SearchInput = (props) => {
55
+ const [hover, setHover] = useState(false);
56
+ const [focus, setFocus] = useState(false);
57
+ const onFocus = () => {
58
+ setFocus(true);
59
+ };
60
+ const onBlur = () => {
61
+ setFocus(false);
62
+ };
63
+ const onMouseEnter = () => {
64
+ setHover(true);
65
+ };
66
+ const onMouseLeave = () => {
67
+ setHover(false);
68
+ };
69
+ return (React.createElement(SearchContainer, { onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onFocus: onFocus, onBlur: onBlur },
70
+ React.createElement(SearchIconContainer, { className: hover || focus ? 'active' : '' },
71
+ React.createElement(SearchIconNoBGc, null)),
72
+ React.createElement(SearchTextField, Object.assign({}, props, { type: "search", placeholder: "Search", autoComplete: "off" }))));
73
+ };
@@ -0,0 +1,4 @@
1
+ export * from './CitationEditor';
2
+ export * from './CitationViewer';
3
+ export * from './ReferencesModal';
4
+ export * from './BibliographyItemSource';
@@ -0,0 +1,18 @@
1
+ /*!
2
+ * © 2024 Atypon Systems LLC
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import React from 'react';
17
+ import Select from 'react-select';
18
+ export const SelectField = ({ id, options, field, form, }) => (React.createElement(Select, { inputId: id, options: options, name: field.name, value: options === null || options === void 0 ? void 0 : options.find((option) => option.value === field.value), onChange: (option) => form.setFieldValue(field.name, option === null || option === void 0 ? void 0 : option.value), onBlur: field.onBlur }));
@@ -0,0 +1,18 @@
1
+ import styled, { css } from 'styled-components';
2
+ export const SidebarStyles = css `
3
+ box-sizing: border-box;
4
+ display: flex;
5
+ flex-direction: column;
6
+ height: 100%;
7
+ padding: ${(props) => props.theme.grid.unit * 4}px
8
+ ${(props) => props.theme.grid.unit * 2}px;
9
+ width: 100%;
10
+ overflow: hidden;
11
+ `;
12
+ export const SidebarContent = styled.div `
13
+ flex: 1;
14
+ padding: 0 ${(props) => props.theme.grid.unit * 3}px;
15
+ position: relative;
16
+ flex-shrink: 0;
17
+ overflow-y: auto;
18
+ `;
@@ -25,15 +25,93 @@ var __rest = (this && this.__rest) || function (s, e) {
25
25
  return t;
26
26
  };
27
27
  import React from 'react';
28
- import Modal from 'react-modal';
28
+ import ReactModal from 'react-modal';
29
29
  import styled from 'styled-components';
30
+ import { RoundIconButton } from './Button';
31
+ import { SidebarStyles } from './Sidebar';
30
32
  const totalTransitionTime = 800;
31
33
  const transitionDelay = 300;
32
34
  const delayedTransitionTime = totalTransitionTime - transitionDelay;
33
- export const ReactModalAdapter = (_a) => {
35
+ const ReactModalAdapter = (_a) => {
34
36
  var { className, modalClassName } = _a, props = __rest(_a, ["className", "modalClassName"]);
35
- return (React.createElement(Modal, Object.assign({ className: modalClassName, portalClassName: className, closeTimeoutMS: totalTransitionTime, appElement: document.getElementById('root') }, props)));
37
+ return (React.createElement(ReactModal, Object.assign({ className: modalClassName, portalClassName: className, closeTimeoutMS: totalTransitionTime, appElement: document.getElementById('root') }, props)));
36
38
  };
39
+ export const ModalContainer = styled.div `
40
+ background: ${(props) => props.theme.colors.background.primary};
41
+ border-radius: ${(props) => props.theme.grid.radius.default};
42
+ box-shadow: ${(props) => props.theme.shadow.dropShadow};
43
+ font-family: ${(props) => props.theme.font.family.sans};
44
+ overflow: hidden;
45
+ margin: ${(props) => props.theme.grid.unit * 3}px;
46
+ `;
47
+ export const ModalHeader = styled.div `
48
+ position: absolute;
49
+ right: 0;
50
+ top: 0;
51
+ z-index: 1;
52
+ `;
53
+ export const CloseButton = styled(RoundIconButton) `
54
+ box-shadow: none;
55
+ text-indent: -99999px;
56
+
57
+ ::before,
58
+ ::after {
59
+ background-color: ${(props) => props.theme.colors.text.secondary};
60
+ border-radius: 2px;
61
+ content: ' ';
62
+ display: block;
63
+ height: 14px;
64
+ transform: rotate(-45deg);
65
+ width: 2px;
66
+ position: absolute;
67
+ top: calc(50% - 7px);
68
+ left: calc(50% - 1px);
69
+ }
70
+ ::after {
71
+ transform: rotate(45deg);
72
+ }
73
+ `;
74
+ export const ModalBody = styled.div `
75
+ align-items: stretch;
76
+ display: flex;
77
+ flex: 1;
78
+ height: 90vh;
79
+ max-height: 680px;
80
+ `;
81
+ export const ModalSidebar = styled.div `
82
+ ${SidebarStyles};
83
+ background-color: ${(props) => props.theme.colors.background.secondary};
84
+ border-top-left-radius: ${(props) => props.theme.grid.radius.default};
85
+ border-bottom-left-radius: ${(props) => props.theme.grid.radius.default};
86
+ max-width: 40vw;
87
+ overflow: auto;
88
+ width: 340px;
89
+ `;
90
+ export const ModalSidebarHeader = styled.div `
91
+ align-items: flex-start;
92
+ display: flex;
93
+ flex-shrink: 0;
94
+ justify-content: space-between;
95
+ padding: 0 ${(props) => props.theme.grid.unit * 3}px;
96
+ margin-bottom: ${(props) => props.theme.grid.unit * 6}px;
97
+ `;
98
+ export const ModalSidebarTitle = styled.div `
99
+ font-size: ${(props) => props.theme.font.size.xlarge};
100
+ font-weight: ${(props) => props.theme.font.weight.semibold};
101
+ color: ${(props) => props.theme.colors.text.primary};
102
+ user-select: none;
103
+ white-space: nowrap;
104
+ width: 100%;
105
+ `;
106
+ export const ModelContent = styled.div `
107
+ padding: ${(props) => props.theme.grid.unit * 4}px;
108
+ box-sizing: border-box;
109
+ max-width: 60vw;
110
+ width: 480px;
111
+ `;
112
+ export const ScrollableModalContent = styled(ModelContent) `
113
+ overflow-y: auto;
114
+ `;
37
115
  export const StyledModal = styled(ReactModalAdapter).attrs({
38
116
  closeTimeoutMS: totalTransitionTime,
39
117
  overlayClassName: {
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ export const DeleteIcon = () => (React.createElement("svg", { width: "13", height: "16", viewBox: "0 0 13 16", fill: "none", xmlns: "http://www.w3.org/2000/svg" },
3
+ React.createElement("path", { className: "icon_element", fillRule: "evenodd", clipRule: "evenodd", d: "M2.00001 2.99995C2 3.0013 2 3.00265 2 3.00399V13.004C2 13.5563 2.44772 14.004 3 14.004H10C10.5523 14.004 11 13.5563 11 13.004V3.00399C11 3.00265 11 3.0013 11 2.99995C11.5978 3.34576 12 3.99211 12 4.73239V13.004C12 14.1086 11.1046 15.004 10 15.004H3C1.89543 15.004 1 14.1086 1 13.004V4.73239C1 3.99211 1.4022 3.34576 2.00001 2.99995Z", fill: "#F35143" }),
4
+ React.createElement("path", { className: "icon_element", fillRule: "evenodd", clipRule: "evenodd", d: "M4.5 0C3.67157 0 3 0.671573 3 1.5V3.5C3 4.32843 3.67157 5 4.5 5H8.5C9.32843 5 10 4.32843 10 3.5V1.5C10 0.671573 9.32843 0 8.5 0H4.5ZM9 1.5C9 1.22386 8.77614 1 8.5 1H4.5C4.22386 1 4 1.22386 4 1.5C4 1.77614 4.22386 2 4.5 2H8.5C8.77614 2 9 1.77614 9 1.5Z", fill: "#F35143" }),
5
+ React.createElement("rect", { className: "icon_element", y: "2", width: "13", height: "3", rx: "1.5", fill: "#F35143" }),
6
+ React.createElement("path", { className: "icon_element", fillRule: "evenodd", clipRule: "evenodd", d: "M8 7.5C8 7.22386 8.22386 7 8.5 7C8.77614 7 9 7.22386 9 7.5V11.5C9 11.7761 8.77614 12 8.5 12C8.22386 12 8 11.7761 8 11.5V7.5Z", fill: "#F35143" }),
7
+ React.createElement("path", { className: "icon_element", fillRule: "evenodd", clipRule: "evenodd", d: "M4 7.5C4 7.22386 4.22386 7 4.5 7C4.77614 7 5 7.22386 5 7.5V11.5C5 11.7761 4.77614 12 4.5 12C4.22386 12 4 11.7761 4 11.5V7.5Z", fill: "#F35143" }),
8
+ React.createElement("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M11.5 3C11.7761 3 12 3.22386 12 3.5C12 3.77614 11.7761 4 11.5 4L1.5 4C1.22386 4 1 3.77614 1 3.5C1 3.22386 1.22386 3 1.5 3L11.5 3Z", fill: "white" })));
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ export const LinkIcon = () => (React.createElement("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg" },
3
+ React.createElement("path", { d: "M6.63317 12.1949L4.74782 14.0803C3.9662 14.8619 2.70042 14.8619 1.91945 14.0804C1.13832 13.2993 1.13832 12.0334 1.91929 11.2524L5.69063 7.48109C6.4716 6.70009 7.73751 6.70009 8.51848 7.48109C8.77882 7.74143 9.20095 7.74143 9.46129 7.48109C9.72163 7.22075 9.72163 6.79862 9.46129 6.53828C8.1596 5.23659 6.04951 5.23659 4.74782 6.53828L0.97651 10.3096C-0.325178 11.6113 -0.325178 13.7214 0.97651 15.0231C2.27804 16.3254 4.38829 16.3254 5.69067 15.0231L7.57601 13.1377C7.83635 12.8774 7.83635 12.4552 7.57601 12.1949C7.31567 11.9346 6.89351 11.9346 6.63317 12.1949Z", fill: "#6E6E6E" }),
4
+ React.createElement("path", { d: "M15.0235 0.976266C13.7218 -0.325422 11.6111 -0.325422 10.3094 0.976266L8.04737 3.23827C7.78702 3.49861 7.78702 3.92073 8.04737 4.18108C8.30771 4.44142 8.72984 4.44142 8.99018 4.18108L11.2522 1.91908C12.0331 1.13808 13.2997 1.13808 14.0807 1.91908C14.8617 2.70005 14.8617 3.96595 14.0807 4.74692L9.93271 8.89495C9.15171 9.67595 7.88584 9.67595 7.10487 8.89495C6.84452 8.63461 6.4224 8.63461 6.16205 8.89495C5.90171 9.1553 5.90171 9.57742 6.16205 9.83777C7.46374 11.1395 9.57384 11.1395 10.8755 9.83777L15.0235 5.68977C16.3252 4.38808 16.3252 2.27795 15.0235 0.976266Z", fill: "#6E6E6E" })));
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ export const TemplateIcon = () => (React.createElement("svg", { width: "16", height: "18", viewBox: "0 0 16 18", fill: "none", xmlns: "http://www.w3.org/2000/svg" },
3
+ React.createElement("rect", { x: "1.25", y: "1.25", width: "13.5", height: "15.5", rx: "1.75", fill: "white", stroke: "#6E6E6E", strokeWidth: "1.5" }),
4
+ React.createElement("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M9 6.5C9 6.08579 8.66421 5.75 8.25 5.75H7.25V4.75C7.25 4.33579 6.91421 4 6.5 4C6.08579 4 5.75 4.33579 5.75 4.75V5.75H4.75C4.33579 5.75 4 6.08579 4 6.5C4 6.91421 4.33579 7.25 4.75 7.25H5.75V8.25C5.75 8.66421 6.08579 9 6.5 9C6.91421 9 7.25 8.66421 7.25 8.25V7.25H8.25C8.66421 7.25 9 6.91421 9 6.5Z", fill: "#6E6E6E" })));
@@ -0,0 +1,49 @@
1
+ /*!
2
+ * © 2023 Atypon Systems LLC
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import { useRef, useState } from 'react';
17
+ export const useScrollDetection = (topTrigger, bottomTrigger) => {
18
+ const refRoot = useRef();
19
+ const observer = useRef();
20
+ const [triggers, setTriggers] = useState({ bottom: false, top: false });
21
+ const ref = (node) => {
22
+ if (!node) {
23
+ return;
24
+ }
25
+ refRoot.current = node;
26
+ if (refRoot.current && !observer.current) {
27
+ const listener = () => {
28
+ if (!refRoot.current) {
29
+ return;
30
+ }
31
+ const node = refRoot.current;
32
+ if (node.scrollTop == 0) {
33
+ node.scrollTop = 1;
34
+ }
35
+ const topRatio = node.scrollTop / node.offsetHeight;
36
+ const bottomRatio = 1 -
37
+ (node.scrollHeight - node.offsetHeight - node.scrollTop) /
38
+ node.offsetHeight;
39
+ const newVal = { top: false, bottom: false };
40
+ newVal.top = topRatio <= topTrigger;
41
+ newVal.bottom = Math.round(bottomRatio * 100) / 100 >= bottomTrigger;
42
+ setTriggers(newVal);
43
+ };
44
+ refRoot.current.addEventListener('scroll', listener);
45
+ observer.current = listener;
46
+ }
47
+ };
48
+ return { ref, triggers };
49
+ };
package/dist/es/index.js CHANGED
@@ -33,7 +33,6 @@ export * from './components/FileManager';
33
33
  export * from './components/FileManager/util';
34
34
  export * from './components/Resizer';
35
35
  export * from './components/SaveStatus';
36
- export * from './components/SimpleModal';
37
36
  export * from './components/StyledModal';
38
37
  export * from './components/TextField';
39
38
  export * from './components/TextFieldContainer';
@@ -53,6 +52,7 @@ export * from './components/Text';
53
52
  export * from './components/ManuscriptNoteList';
54
53
  export * from './components/Comments';
55
54
  export * from './components/RelativeDate';
55
+ export * from './components/References';
56
56
  export * from './components/Menus';
57
57
  export * from './hooks/use-dropdown';
58
58
  export * from './hooks/use-files';
@@ -14,7 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
  import React from 'react';
17
- export declare const ModalBody: import("styled-components").StyledComponent<"div", import("styled-components").DefaultTheme, {}, never>;
17
+ export declare const DialogModalBody: import("styled-components").StyledComponent<"div", import("styled-components").DefaultTheme, {}, never>;
18
18
  export declare const MessageContainer: import("styled-components").StyledComponent<"div", import("styled-components").DefaultTheme, {}, never>;
19
19
  interface DialogState {
20
20
  primaryActionDisabled: boolean;
@@ -0,0 +1,38 @@
1
+ /*!
2
+ * © 2023 Atypon Systems LLC
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import { BibliographyItem } from '@manuscripts/json-schema';
17
+ export interface BibliographyItemSource {
18
+ id: string;
19
+ label: string;
20
+ search: (query: string, limit: number) => Job<BibliographyItemSearchResponse>;
21
+ find?: () => Job<BibliographyItem>;
22
+ }
23
+ export type Job<T> = {
24
+ response: Promise<T>;
25
+ cancel?: () => void;
26
+ isCancelled?: boolean;
27
+ };
28
+ export type BibliographyItemSearchResponse = {
29
+ items: BibliographyItem[];
30
+ total: number;
31
+ };
32
+ export declare class DocumentReferenceSource implements BibliographyItemSource {
33
+ id: string;
34
+ label: string;
35
+ private items;
36
+ constructor(items: BibliographyItem[]);
37
+ search(query: string, limit: number): Job<BibliographyItemSearchResponse>;
38
+ }
@@ -0,0 +1,18 @@
1
+ import { BibliographyItem } from '@manuscripts/json-schema';
2
+ import React from 'react';
3
+ import { BibliographyItemSource } from './BibliographyItemSource';
4
+ export interface CitationEditorProps {
5
+ query?: string;
6
+ rids: string[];
7
+ items: BibliographyItem[];
8
+ citationCounts: Map<string, number>;
9
+ sources: BibliographyItemSource[];
10
+ onCite: (items: BibliographyItem[]) => void;
11
+ onUncite: (id: string) => void;
12
+ onSave: (item: BibliographyItem) => void;
13
+ onDelete: (item: BibliographyItem) => void;
14
+ onComment: () => void;
15
+ onCancel: () => void;
16
+ canEdit: boolean;
17
+ }
18
+ export declare const CitationEditor: React.FC<CitationEditorProps>;