@manuscripts/body-editor 3.12.2 → 3.12.4

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 (65) hide show
  1. package/dist/cjs/components/affiliations/AffiliationItem.js +7 -11
  2. package/dist/cjs/components/affiliations/AffiliationList.js +3 -5
  3. package/dist/cjs/components/affiliations/AffiliationsModal.js +13 -4
  4. package/dist/cjs/components/authors/AuthorList.js +4 -2
  5. package/dist/cjs/components/authors/AuthorsModal.js +10 -3
  6. package/dist/cjs/components/authors/DraggableAuthor.js +7 -11
  7. package/dist/cjs/components/awards/AwardForm.js +108 -100
  8. package/dist/cjs/components/hooks/use-debounce.js +15 -0
  9. package/dist/cjs/components/modal-drawer/GenericDrawerGroup.js +1 -0
  10. package/dist/cjs/components/references/CitationEditor.js +6 -7
  11. package/dist/cjs/components/references/ImportBibliographyForm.js +12 -3
  12. package/dist/cjs/components/references/ReferenceForm/PersonDropDown.js +1 -1
  13. package/dist/cjs/components/references/ReferenceForm/styled-components.js +12 -3
  14. package/dist/cjs/components/references/ReferenceSearch.js +2 -2
  15. package/dist/cjs/components/references/ReferenceSearchResults.js +58 -11
  16. package/dist/cjs/components/references/ReferenceSearchSection.js +3 -11
  17. package/dist/cjs/components/references/ReferencesModal.js +5 -4
  18. package/dist/cjs/components/toolbar/InsertTableDialog.js +11 -3
  19. package/dist/cjs/components/views/CrossReferenceItems.js +8 -14
  20. package/dist/cjs/components/views/FootnotesSelector.js +6 -6
  21. package/dist/cjs/components/views/InsertSpecialCharacter.js +24 -10
  22. package/dist/cjs/components/views/LinkForm.js +8 -1
  23. package/dist/cjs/lib/popper.js +4 -2
  24. package/dist/cjs/versions.js +1 -1
  25. package/dist/cjs/views/cross_reference_editable.js +1 -0
  26. package/dist/cjs/views/equation_editable.js +6 -0
  27. package/dist/cjs/views/footnote.js +6 -6
  28. package/dist/cjs/views/inline_equation_editable.js +6 -0
  29. package/dist/cjs/views/inline_footnote.js +1 -0
  30. package/dist/es/components/affiliations/AffiliationItem.js +8 -12
  31. package/dist/es/components/affiliations/AffiliationList.js +3 -5
  32. package/dist/es/components/affiliations/AffiliationsModal.js +14 -5
  33. package/dist/es/components/authors/AuthorList.js +4 -2
  34. package/dist/es/components/authors/AuthorsModal.js +11 -4
  35. package/dist/es/components/authors/DraggableAuthor.js +8 -12
  36. package/dist/es/components/awards/AwardForm.js +110 -102
  37. package/dist/es/components/hooks/use-debounce.js +15 -1
  38. package/dist/es/components/modal-drawer/GenericDrawerGroup.js +2 -1
  39. package/dist/es/components/references/CitationEditor.js +7 -8
  40. package/dist/es/components/references/ImportBibliographyForm.js +14 -5
  41. package/dist/es/components/references/ReferenceForm/PersonDropDown.js +1 -1
  42. package/dist/es/components/references/ReferenceForm/styled-components.js +13 -4
  43. package/dist/es/components/references/ReferenceSearch.js +3 -3
  44. package/dist/es/components/references/ReferenceSearchResults.js +26 -12
  45. package/dist/es/components/references/ReferenceSearchSection.js +4 -12
  46. package/dist/es/components/references/ReferencesModal.js +6 -5
  47. package/dist/es/components/toolbar/InsertTableDialog.js +11 -3
  48. package/dist/es/components/views/CrossReferenceItems.js +9 -15
  49. package/dist/es/components/views/FootnotesSelector.js +7 -7
  50. package/dist/es/components/views/InsertSpecialCharacter.js +25 -11
  51. package/dist/es/components/views/LinkForm.js +9 -2
  52. package/dist/es/lib/popper.js +4 -2
  53. package/dist/es/versions.js +1 -1
  54. package/dist/es/views/cross_reference_editable.js +1 -0
  55. package/dist/es/views/equation_editable.js +6 -0
  56. package/dist/es/views/footnote.js +6 -6
  57. package/dist/es/views/inline_equation_editable.js +6 -0
  58. package/dist/es/views/inline_footnote.js +1 -0
  59. package/dist/types/components/hooks/use-debounce.d.ts +1 -0
  60. package/dist/types/components/references/ReferenceForm/styled-components.d.ts +11 -1
  61. package/dist/types/components/references/ReferenceSearchResults.d.ts +20 -2
  62. package/dist/types/versions.d.ts +1 -1
  63. package/dist/types/views/footnote.d.ts +2 -2
  64. package/package.json +2 -2
  65. package/styles/popper.css +2 -0
@@ -40,7 +40,7 @@ exports.AffiliationItem = void 0;
40
40
  const style_guide_1 = require("@manuscripts/style-guide");
41
41
  const react_1 = __importStar(require("react"));
42
42
  const styled_components_1 = __importDefault(require("styled-components"));
43
- const AffiliationContainer = styled_components_1.default.div `
43
+ const AffiliationContainer = (0, style_guide_1.withNavigableListItem)(styled_components_1.default.div `
44
44
  padding: ${(props) => props.theme.grid.unit * 2}px 0
45
45
  ${(props) => props.theme.grid.unit * 2}px;
46
46
  display: flex;
@@ -58,7 +58,7 @@ const AffiliationContainer = styled_components_1.default.div `
58
58
  &.active {
59
59
  border-color: ${(props) => props.theme.colors.border.primary};
60
60
  }
61
- `;
61
+ `);
62
62
  const AffiliationName = styled_components_1.default.div `
63
63
  margin-left: 12px;
64
64
  flex: 1;
@@ -82,15 +82,11 @@ const AffiliationBox = styled_components_1.default.div `
82
82
  flex-direction: column;
83
83
  margin-left: 4px;
84
84
  `;
85
- const RemoveButton = styled_components_1.default.div `
86
- display: flex;
87
- align-items: center;
88
- margin-right: 8px;
85
+ const RemoveButton = (0, styled_components_1.default)(style_guide_1.SecondaryIconButton) `
89
86
  svg {
90
- cursor: pointer;
91
- }
92
- .icon_element {
93
- fill: #6e6e6e;
87
+ path[fill='white'] {
88
+ fill: white;
89
+ }
94
90
  }
95
91
  `;
96
92
  const AffiliationItem = ({ affiliation, isSelected, onClick, onDelete, showSuccessIcon, }) => {
@@ -114,7 +110,7 @@ const AffiliationItem = ({ affiliation, isSelected, onClick, onDelete, showSucce
114
110
  affiliation.country ? ', ' : '')),
115
111
  affiliation.country && react_1.default.createElement(react_1.default.Fragment, null, affiliation.country))),
116
112
  showSuccessIcon && (react_1.default.createElement(style_guide_1.CrclTickAnimation, { size: 36, style: { position: 'absolute', left: '10px' } })),
117
- isSelected && (react_1.default.createElement(RemoveButton, { onClick: () => onDelete(), "data-tooltip-content": "Delete" },
113
+ isSelected && (react_1.default.createElement(RemoveButton, { size: 13, onClick: () => onDelete(), "data-tooltip-content": "Delete" },
118
114
  react_1.default.createElement(style_guide_1.DeleteIcon, { fill: '#6E6E6E' })))));
119
115
  };
120
116
  exports.AffiliationItem = AffiliationItem;
@@ -22,18 +22,16 @@ exports.AffiliationList = void 0;
22
22
  const react_1 = __importDefault(require("react"));
23
23
  const styled_components_1 = __importDefault(require("styled-components"));
24
24
  const AffiliationItem_1 = require("./AffiliationItem");
25
- const AffiliationListContainer = styled_components_1.default.div `
25
+ const style_guide_1 = require("@manuscripts/style-guide");
26
+ const AffiliationListContainer = (0, style_guide_1.withListNavigation)(styled_components_1.default.div `
26
27
  flex: 1;
27
28
  overflow-y: visible;
28
- margin-left: 16px;
29
- `;
29
+ `);
30
30
  const AffiliationListTitle = styled_components_1.default.h2 `
31
31
  color: #6e6e6e;
32
32
  font-size: 18px;
33
33
  font-weight: 400;
34
34
  line-height: 24px;
35
- margin-left: 14px;
36
- margin-top: 20px;
37
35
  `;
38
36
  const AffiliationList = ({ affiliation, affiliations, onSelect, onDelete, lastSavedAffiliationId, }) => {
39
37
  return (react_1.default.createElement(react_1.default.Fragment, null,
@@ -367,7 +367,9 @@ const AffiliationsModal = ({ authors: $authors, affiliations: $affiliations, aff
367
367
  react_1.default.createElement(AffiliationList_1.AffiliationList, { affiliation: selection, affiliations: affiliations, onSelect: handleSelect, onDelete: handleShowDeleteDialog, lastSavedAffiliationId: savedAffiliationId }))),
368
368
  react_1.default.createElement(style_guide_1.ScrollableModalContent, { "data-cy": "affiliations-modal-content" }, selection ? (react_1.default.createElement(react_1.default.Fragment, null,
369
369
  react_1.default.createElement(AffiliationTabs, null,
370
- react_1.default.createElement(ModalFormActions_1.ModalFormActions, { type: 'affiliation', form: 'affiliation-form', onDelete: handleDeleteAffiliation, showingDeleteDialog: showingDeleteDialog, showDeleteDialog: handleShowDeleteDialog, newEntity: newAffiliation, isDisableSave: isDisableSave }),
370
+ react_1.default.createElement(ModalFormActions_1.ModalFormActions, { type: 'affiliation', form: 'affiliation-form', onDelete: handleDeleteAffiliation, showingDeleteDialog: showingDeleteDialog &&
371
+ !(showConfirmationDialog ||
372
+ showRequiredFieldConfirmationDialog), showDeleteDialog: handleShowDeleteDialog, newEntity: newAffiliation, isDisableSave: isDisableSave }),
371
373
  react_1.default.createElement(style_guide_1.InspectorTabList, null,
372
374
  react_1.default.createElement(style_guide_1.InspectorTab, null, "Details"),
373
375
  react_1.default.createElement(style_guide_1.InspectorTab, null, "Authors")),
@@ -403,9 +405,15 @@ function createEmptyAffiliation(priority) {
403
405
  };
404
406
  }
405
407
  const StyledSidebarContent = (0, styled_components_1.default)(style_guide_1.SidebarContent) `
406
- padding: 0;
408
+ padding: 8px;
407
409
  `;
408
- const AddAffiliationButton = styled_components_1.default.div `
410
+ const AddAffiliationButton = styled_components_1.default.button `
411
+ background: none;
412
+ border: none;
413
+ margin: 0;
414
+ font: inherit;
415
+ color: inherit;
416
+ width: 100%;
409
417
  display: flex;
410
418
  align-items: center;
411
419
  padding: 12px 8px 12px 12px;
@@ -416,6 +424,7 @@ const AddAffiliationButton = styled_components_1.default.div `
416
424
  border-left: 0;
417
425
  border-right: 0;
418
426
  }
427
+ ${style_guide_1.outlineStyle}
419
428
  `;
420
429
  const ActionTitle = styled_components_1.default.div `
421
430
  padding-left: ${(props) => props.theme.grid.unit * 2}px;
@@ -423,7 +432,7 @@ const ActionTitle = styled_components_1.default.div `
423
432
  const AffiliationTabs = (0, styled_components_1.default)(style_guide_1.InspectorTabs) `
424
433
  position: relative;
425
434
  `;
426
- const AffiliationTabPanel = (0, styled_components_1.default)(style_guide_1.InspectorTabPanel).attrs({ unmount: false }) `
435
+ const AffiliationTabPanel = (0, styled_components_1.default)(style_guide_1.InspectorTabPanel).attrs({ tabIndex: -1, unmount: false }) `
427
436
  margin-top: ${(props) => props.theme.grid.unit * 4}px;
428
437
  `;
429
438
  const StyledModalBody = (0, styled_components_1.default)(style_guide_1.ModalBody) `
@@ -24,10 +24,12 @@ const react_dnd_1 = require("react-dnd");
24
24
  const react_dnd_html5_backend_1 = require("react-dnd-html5-backend");
25
25
  const styled_components_1 = __importDefault(require("styled-components"));
26
26
  const DraggableAuthor_1 = require("./DraggableAuthor");
27
- const AuthorListContainer = styled_components_1.default.div `
27
+ const style_guide_1 = require("@manuscripts/style-guide");
28
+ const AuthorListContainer = (0, style_guide_1.withListNavigation)(styled_components_1.default.div `
28
29
  flex: 1;
29
30
  overflow-y: visible;
30
- `;
31
+ padding: 0 6px;
32
+ `);
31
33
  const AuthorListTitle = styled_components_1.default.h2 `
32
34
  color: #6e6e6e;
33
35
  font-size: 18px;
@@ -386,7 +386,13 @@ function createEmptyAuthor(priority) {
386
386
  prefix: '',
387
387
  };
388
388
  }
389
- const AddAuthorButton = styled_components_1.default.div `
389
+ const AddAuthorButton = styled_components_1.default.button `
390
+ background: none;
391
+ border: none;
392
+ margin: 0;
393
+ font: inherit;
394
+ color: inherit;
395
+ width: 100%;
390
396
  display: flex;
391
397
  align-items: center;
392
398
  padding: 12px 8px 12px 12px;
@@ -397,6 +403,7 @@ const AddAuthorButton = styled_components_1.default.div `
397
403
  border-left: 0;
398
404
  border-right: 0;
399
405
  }
406
+ ${style_guide_1.outlineStyle}
400
407
  `;
401
408
  const ActionTitle = styled_components_1.default.div `
402
409
  padding-left: ${(props) => props.theme.grid.unit * 2}px;
@@ -404,11 +411,11 @@ const ActionTitle = styled_components_1.default.div `
404
411
  const AuthorTabs = (0, styled_components_1.default)(style_guide_1.InspectorTabs) `
405
412
  position: relative;
406
413
  `;
407
- const AuthorTabPanel = (0, styled_components_1.default)(style_guide_1.InspectorTabPanel).attrs({ unmount: false }) `
414
+ const AuthorTabPanel = (0, styled_components_1.default)(style_guide_1.InspectorTabPanel).attrs({ tabIndex: -1, unmount: false }) `
408
415
  margin-top: ${(props) => props.theme.grid.unit * 4}px;
409
416
  `;
410
417
  const StyledSidebarContent = (0, styled_components_1.default)(style_guide_1.SidebarContent) `
411
- padding: 0;
418
+ padding: 8px;
412
419
  `;
413
420
  const StyledModalBody = (0, styled_components_1.default)(style_guide_1.ModalBody) `
414
421
  position: relative;
@@ -58,7 +58,7 @@ const react_dnd_1 = require("react-dnd");
58
58
  const styled_components_1 = __importDefault(require("styled-components"));
59
59
  const authors_1 = require("../../lib/authors");
60
60
  const dnd_1 = require("../../lib/dnd");
61
- const AuthorContainer = styled_components_1.default.div `
61
+ const AuthorContainer = (0, style_guide_1.withNavigableListItem)(styled_components_1.default.div `
62
62
  padding: ${(props) => props.theme.grid.unit * 2}px 0
63
63
  ${(props) => props.theme.grid.unit * 2}px;
64
64
  display: flex;
@@ -92,7 +92,7 @@ const AuthorContainer = styled_components_1.default.div `
92
92
  cursor: grabbing;
93
93
  border-bottom-color: ${(props) => props.theme.colors.brand.dark};
94
94
  }
95
- `;
95
+ `);
96
96
  const AvatarContainer = styled_components_1.default.div `
97
97
  display: inline-flex;
98
98
  position: relative;
@@ -125,15 +125,11 @@ const DragHandle = (0, styled_components_1.default)(style_guide_1.DraggableIcon)
125
125
  margin-left: -4px;
126
126
  margin-right: -12px;
127
127
  `;
128
- const RemoveButton = styled_components_1.default.div `
129
- display: flex;
130
- align-items: center;
131
- margin-right: 8px;
128
+ const RemoveButton = (0, styled_components_1.default)(style_guide_1.SecondaryIconButton) `
132
129
  svg {
133
- cursor: pointer;
134
- }
135
- .icon_element {
136
- fill: #6e6e6e;
130
+ path[fill='white'] {
131
+ fill: white;
132
+ }
137
133
  }
138
134
  `;
139
135
  const StyledCrclTickAnimation = (0, styled_components_1.default)(style_guide_1.CrclTickAnimation) `
@@ -201,6 +197,6 @@ exports.DraggableAuthor = react_1.default.memo(({ author, isSelected, onClick, o
201
197
  react_1.default.createElement(AuthorNotes, { "data-cy": "author-notes" }, author.isCorresponding && (react_1.default.createElement(AuthorBadge, null,
202
198
  react_1.default.createElement(style_guide_1.CorrespondingAuthorIcon, null))))),
203
199
  react_1.default.createElement(AuthorName, { "data-cy": "author-name" }, (0, authors_1.authorLabel)(author)),
204
- isSelected && (react_1.default.createElement(RemoveButton, { onClick: () => onDelete(), "data-tooltip-content": "Delete" },
200
+ isSelected && (react_1.default.createElement(RemoveButton, { size: 13, onClick: () => onDelete(), "data-tooltip-content": "Delete" },
205
201
  react_1.default.createElement(style_guide_1.DeleteIcon, { fill: '#6E6E6E' })))));
206
202
  });
@@ -55,55 +55,46 @@ exports.AwardForm = void 0;
55
55
  const style_guide_1 = require("@manuscripts/style-guide");
56
56
  const formik_1 = require("formik");
57
57
  const react_1 = __importStar(require("react"));
58
- const styled_components_1 = __importDefault(require("styled-components"));
58
+ const styled_components_1 = __importStar(require("styled-components"));
59
59
  const ChangeHandlingForm_1 = require("../ChangeHandlingForm");
60
- const use_debounce_1 = require("../hooks/use-debounce");
60
+ const react_select_1 = require("react-select");
61
+ const async_creatable_1 = __importDefault(require("react-select/async-creatable"));
62
+ const use_debounce_1 = __importDefault(require("../hooks/use-debounce"));
63
+ const loadOptions = async (inputValue) => {
64
+ try {
65
+ const formattedQuery = inputValue.replace(/\s+/g, '+');
66
+ const response = await fetch(`https://api.crossref.org/funders?query=${encodeURIComponent(formattedQuery)}`);
67
+ if (!response.ok) {
68
+ console.log(`HTTP error! status: ${response.status}`);
69
+ return [];
70
+ }
71
+ const data = await response.json();
72
+ const funderOptions = data.message.items.map((funder) => ({
73
+ value: funder.name,
74
+ label: funder.name,
75
+ }));
76
+ return funderOptions.sort((a, b) => a.label.localeCompare(b.label));
77
+ }
78
+ catch (e) {
79
+ console.error('Error fetching funders:', e);
80
+ return [];
81
+ }
82
+ };
61
83
  const AwardForm = ({ values, onSave, onCancel, onChange, }) => {
62
- const [funders, setFunders] = (0, react_1.useState)([]);
63
- const [isLoading, setIsLoading] = (0, react_1.useState)(false);
64
- const [searchQuery, setSearchQuery] = (0, react_1.useState)('');
65
84
  const formRef = (0, react_1.useRef)(null);
66
85
  const primaryButtonText = values.source ? 'Update funder' : 'Add funder';
67
- const debouncedSearchQuery = (0, use_debounce_1.useDebounce)(searchQuery, 300);
68
- (0, react_1.useEffect)(() => {
69
- const searchFunders = async () => {
70
- const query = debouncedSearchQuery;
71
- if (!query) {
72
- setFunders([]);
73
- return;
74
- }
75
- setIsLoading(true);
76
- try {
77
- const formattedQuery = query.replace(/\s+/g, '+');
78
- const response = await fetch(`https://api.crossref.org/funders?query=${encodeURIComponent(formattedQuery)}`);
79
- if (!response.ok) {
80
- throw new Error(`HTTP error! status: ${response.status}`);
81
- }
82
- const data = await response.json();
83
- const funderOptions = data.message.items.map((funder) => ({
84
- value: funder.name,
85
- label: funder.name,
86
- }));
87
- funderOptions.sort((a, b) => a.label.localeCompare(b.label));
88
- setFunders(funderOptions);
89
- }
90
- catch (error) {
91
- console.error('Error fetching funders:', error);
92
- setFunders([]);
93
- }
94
- finally {
95
- setIsLoading(false);
96
- }
97
- };
98
- searchFunders();
99
- }, [debouncedSearchQuery]);
100
- const handleFunderSearch = (event) => {
101
- setSearchQuery(event.target.value);
102
- };
86
+ const themes = (0, styled_components_1.useTheme)();
87
+ const customStyles = (0, react_1.useMemo)(() => getCustomStyles(themes), [themes]);
88
+ const handleOnLoadFunders = (0, use_debounce_1.default)(async (inputValue) => loadOptions(inputValue), 300);
103
89
  const handleCancel = () => {
104
90
  formRef.current?.resetForm();
105
91
  onCancel();
106
92
  };
93
+ const handleInputChange = (value, action) => {
94
+ if (action.action === 'input-change') {
95
+ formRef.current?.setFieldValue('source', value);
96
+ }
97
+ };
107
98
  const validate = (values) => {
108
99
  const errors = {};
109
100
  if (!values.source) {
@@ -119,18 +110,14 @@ const AwardForm = ({ values, onSave, onCancel, onChange, }) => {
119
110
  react_1.default.createElement(formik_1.Field, { type: "hidden", name: "id" }),
120
111
  react_1.default.createElement(style_guide_1.FormRow, null,
121
112
  react_1.default.createElement(style_guide_1.Label, { htmlFor: 'source' }, "Funder name"),
122
- react_1.default.createElement(SearchContainer, null,
123
- react_1.default.createElement(SearchIconContainer, null,
124
- react_1.default.createElement(style_guide_1.SearchIcon, null)),
125
- react_1.default.createElement(formik_1.Field, { name: "source" }, (props) => (react_1.default.createElement(StyledTextField, { id: "source", placeholder: "Search for funder...", onChange: (e) => {
126
- props.field.onChange(e);
127
- handleFunderSearch(e);
128
- }, value: props.field.value || '' }))),
129
- isLoading && react_1.default.createElement(LoadingText, null, "Loading..."),
130
- funders.length > 0 && (react_1.default.createElement(SearchResults, null, funders.map((funder) => (react_1.default.createElement(SearchResultItem, { key: funder.value, onClick: () => {
131
- formik.setFieldValue('source', funder.value);
132
- setFunders([]);
133
- } }, funder.label)))))),
113
+ react_1.default.createElement(formik_1.Field, { name: "source" }, (props) => (react_1.default.createElement(async_creatable_1.default, { inputId: 'source', loadOptions: handleOnLoadFunders, onInputChange: handleInputChange, autoFocus: true, onChange: (option) => option &&
114
+ formRef.current?.setFieldValue('source', option.value), inputValue: props.field.value, value: null, isValidNewOption: () => false, components: {
115
+ Input,
116
+ Control,
117
+ Option,
118
+ DropdownIndicator: null,
119
+ IndicatorSeparator: null,
120
+ }, styles: customStyles, placeholder: "Search for funder..." }))),
134
121
  formik.errors.source && formik.touched.source && (react_1.default.createElement(ErrorText, null, formik.errors.source))),
135
122
  react_1.default.createElement(style_guide_1.FormRow, null,
136
123
  react_1.default.createElement(style_guide_1.Label, { htmlFor: 'code' }, "Grant number"),
@@ -141,69 +128,90 @@ const AwardForm = ({ values, onSave, onCancel, onChange, }) => {
141
128
  react_1.default.createElement(style_guide_1.Label, { htmlFor: 'recipient' }, "Recipient name"),
142
129
  react_1.default.createElement(formik_1.Field, { name: "recipient" }, (props) => (react_1.default.createElement(style_guide_1.TextField, { id: "recipient", placeholder: "Enter full name", ...props.field })))),
143
130
  react_1.default.createElement(style_guide_1.FormRow, null,
144
- react_1.default.createElement(style_guide_1.FormActionsBar, null,
131
+ react_1.default.createElement(FormActions, null,
145
132
  react_1.default.createElement(style_guide_1.SecondaryButton, { onClick: handleCancel }, "Cancel"),
146
133
  react_1.default.createElement(style_guide_1.PrimaryButton, { type: "submit", disabled: !formik.dirty || formik.isSubmitting }, primaryButtonText)))));
147
134
  }));
148
135
  };
149
136
  exports.AwardForm = AwardForm;
150
- const SearchContainer = styled_components_1.default.div `
151
- position: relative;
152
- width: 100%;
153
- `;
154
137
  const SearchIconContainer = styled_components_1.default.span `
155
138
  display: flex;
156
- left: ${(props) => props.theme.grid.unit * 4}px;
157
- position: absolute;
158
- top: 50%;
159
- transform: translateY(-50%);
160
- z-index: 2;
139
+ align-items: center;
140
+ padding-left: ${(props) => props.theme.grid.unit * 4}px;
141
+ padding-right: ${(props) => props.theme.grid.unit * 2}px;
161
142
 
162
143
  path {
163
- stroke: ${(props) => props.theme.colors.text.primary};
144
+ stroke: ${(props) => props.isFocused
145
+ ? props.theme.colors.brand.medium
146
+ : props.theme.colors.text.primary};
164
147
  }
148
+ `;
149
+ const OptionWrapper = styled_components_1.default.div `
150
+ padding-left: ${(props) => props.theme.grid.unit * 4}px;
151
+ padding-top: ${(props) => props.theme.grid.unit * 2}px;
152
+ padding-bottom: ${(props) => props.theme.grid.unit * 2}px;
165
153
 
166
- ${SearchContainer}:hover &,
167
- ${SearchContainer}:focus-within & {
168
- path {
169
- stroke: ${(props) => props.theme.colors.brand.medium};
154
+ background-color: ${(props) => {
155
+ if (props.selected) {
156
+ return props.theme.colors.background.selected;
170
157
  }
171
- }
172
- `;
173
- const StyledTextField = (0, styled_components_1.default)(style_guide_1.TextField) `
174
- padding-left: ${(props) => props.theme.grid.unit * 11}px;
175
- &:hover,
176
- &:focus {
177
- background-color: ${(props) => props.theme.colors.background.fifth};
178
- }
179
- `;
180
- const SearchResults = styled_components_1.default.div `
181
- position: absolute;
182
- top: 100%;
183
- left: 0;
184
- right: 0;
185
- max-height: 200px;
186
- overflow-y: auto;
187
- background: white;
188
- border: 1px solid ${(props) => props.theme.colors.border.secondary};
189
- border-radius: 4px;
190
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
191
- z-index: 1000;
192
- `;
193
- const SearchResultItem = styled_components_1.default.div `
194
- padding: 8px 12px;
195
- cursor: pointer;
158
+ if (props.focused) {
159
+ return props.theme.colors.background.fifth;
160
+ }
161
+ return 'transparent';
162
+ }};
163
+
196
164
  &:hover {
197
165
  background-color: ${(props) => props.theme.colors.background.fifth};
198
166
  }
199
167
  `;
200
- const LoadingText = styled_components_1.default.div `
201
- position: absolute;
202
- right: 12px;
203
- top: 50%;
204
- transform: translateY(-50%);
205
- color: ${(props) => props.theme.colors.text.secondary};
206
- font-size: ${(props) => props.theme.font.size.small};
168
+ const Option = ({ innerProps, innerRef, data, isFocused, isSelected, }) => {
169
+ return (react_1.default.createElement(OptionWrapper, { ...innerProps, ref: innerRef, focused: isFocused, selected: isSelected }, data.label));
170
+ };
171
+ const Control = ({ children, ...props }) => {
172
+ return (react_1.default.createElement(react_select_1.components.Control, { ...props },
173
+ react_1.default.createElement(SearchIconContainer, { isFocused: props.isFocused },
174
+ react_1.default.createElement(style_guide_1.SearchIcon, null)),
175
+ children));
176
+ };
177
+ const Input = (props) => (react_1.default.createElement(react_select_1.components.Input, { ...props, isHidden: false }));
178
+ const getCustomStyles = (theme) => ({
179
+ control: (provided, state) => ({
180
+ ...provided,
181
+ minHeight: '40px',
182
+ borderRadius: '4px',
183
+ border: `${state.isFocused ? '2px' : '1px'} solid ${state.isFocused ? theme.colors.brand.default : theme.colors.border.secondary}`,
184
+ backgroundColor: state.isFocused || state.menuIsOpen
185
+ ? theme.colors.background.fifth
186
+ : theme.colors.background.primary,
187
+ boxShadow: 'none',
188
+ cursor: 'text',
189
+ transition: 'background-color 0.2s',
190
+ '&:hover': {
191
+ backgroundColor: theme.colors.background.fifth,
192
+ },
193
+ }),
194
+ input: (provided) => ({
195
+ ...provided,
196
+ margin: 0,
197
+ padding: 0,
198
+ color: theme.colors.text.primary,
199
+ fontSize: theme.font.size.normal,
200
+ fontFamily: theme.font.family.sans,
201
+ }),
202
+ placeholder: (provided, state) => ({
203
+ ...provided,
204
+ margin: 0,
205
+ fontStyle: 'italic',
206
+ color: state.isFocused ? '#c9c9c9' : theme.colors.text.secondary,
207
+ fontSize: theme.font.size.medium,
208
+ fontFamily: theme.font.family.sans,
209
+ fontWeight: theme.font.weight.normal,
210
+ lineHeight: theme.font.lineHeight.large,
211
+ }),
212
+ });
213
+ const FormActions = (0, styled_components_1.default)(style_guide_1.ButtonGroup) `
214
+ margin: ${(props) => props.theme.grid.unit * 2}px;
207
215
  `;
208
216
  const ErrorText = styled_components_1.default.div `
209
217
  color: ${(props) => props.theme.colors.text.error};
@@ -16,6 +16,7 @@
16
16
  */
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
18
  exports.useDebounce = void 0;
19
+ exports.default = useDebounced;
19
20
  const react_1 = require("react");
20
21
  const useDebounce = (value, delay) => {
21
22
  const [debouncedValue, setDebouncedValue] = (0, react_1.useState)(value);
@@ -30,3 +31,17 @@ const useDebounce = (value, delay) => {
30
31
  return debouncedValue;
31
32
  };
32
33
  exports.useDebounce = useDebounce;
34
+ function useDebounced(fn, delay) {
35
+ const timeoutRef = (0, react_1.useRef)(null);
36
+ return (0, react_1.useCallback)((arg) => {
37
+ const timeout = timeoutRef.current;
38
+ if (timeout) {
39
+ clearTimeout(timeout);
40
+ }
41
+ return new Promise((resolve) => {
42
+ timeoutRef.current = setTimeout(async () => {
43
+ resolve(await fn(arg));
44
+ }, delay);
45
+ });
46
+ }, [fn, delay]);
47
+ }
@@ -50,4 +50,5 @@ exports.AssignButton = styled_components_1.default.button `
50
50
  &:hover {
51
51
  opacity: 0.8;
52
52
  }
53
+ ${style_guide_1.outlineStyle}
53
54
  `;
@@ -48,6 +48,7 @@ const ImportBibliographyModal_1 = require("./ImportBibliographyModal");
48
48
  const ReferenceLine_1 = require("./ReferenceLine");
49
49
  const ReferenceSearch_1 = require("./ReferenceSearch");
50
50
  const ReferencesModal_1 = require("./ReferencesModal");
51
+ const Container = (0, style_guide_1.withFocusTrap)(styled_components_1.default.div ``);
51
52
  const CitedItemActions = styled_components_1.default.div `
52
53
  display: flex;
53
54
  align-items: center;
@@ -80,10 +81,10 @@ const ActionButton = (0, styled_components_1.default)(style_guide_1.IconButton).
80
81
  const EditReferenceButton = (0, styled_components_1.default)(ActionButton) `
81
82
  margin-right: ${(props) => props.theme.grid.unit * 3}px;
82
83
  `;
83
- const Actions = styled_components_1.default.div `
84
+ const Actions = (0, styled_components_1.default)(style_guide_1.ButtonGroup) `
84
85
  margin: ${(props) => props.theme.grid.unit * 4}px;
85
86
  display: flex;
86
- justify-content: space-between;
87
+ justify-content: flex-end;
87
88
  align-items: center;
88
89
  `;
89
90
  const itemsReducer = (0, array_reducer_1.attrsReducer)();
@@ -171,7 +172,7 @@ const CitationEditor = ({ query, rids: $rids, items: $items, citationCounts, sou
171
172
  if (!rids.length) {
172
173
  return (react_1.default.createElement(ReferenceSearch_1.ReferenceSearch, { query: query, sources: sources, items: items, onAdd: handleAdd, onImport: handleImport, onCite: handleCite, onCancel: onCancel }));
173
174
  }
174
- return (react_1.default.createElement(react_1.default.Fragment, null,
175
+ return (react_1.default.createElement(Container, null,
175
176
  react_1.default.createElement(style_guide_1.Dialog, { isOpen: deleteDialog.show, category: style_guide_1.Category.confirmation, header: "Remove cited item", message: "Are you sure you want to remove this cited item? It will still exist in the reference list.", actions: {
176
177
  secondary: {
177
178
  action: () => {
@@ -195,9 +196,7 @@ const CitationEditor = ({ query, rids: $rids, items: $items, citationCounts, sou
195
196
  react_1.default.createElement(ActionButton, { disabled: !canEdit, onClick: () => setDeleteDialog({ show: true, id: item.id }) },
196
197
  react_1.default.createElement(style_guide_1.DeleteSolidIcon, { className: 'remove-icon' }))))))),
197
198
  react_1.default.createElement(Actions, null,
198
- react_1.default.createElement(style_guide_1.IconTextButton, null),
199
- react_1.default.createElement(style_guide_1.ButtonGroup, null,
200
- react_1.default.createElement(style_guide_1.SecondaryButton, { onClick: onCancel }, "Done"),
201
- react_1.default.createElement(style_guide_1.PrimaryButton, { disabled: !canEdit, onClick: () => setSearching(true) }, "Add Citation")))));
199
+ react_1.default.createElement(style_guide_1.SecondaryButton, { onClick: onCancel }, "Done"),
200
+ react_1.default.createElement(style_guide_1.PrimaryButton, { disabled: !canEdit, onClick: () => setSearching(true) }, "Add Citation"))));
202
201
  };
203
202
  exports.CitationEditor = CitationEditor;
@@ -58,6 +58,7 @@ const references_1 = require("../../lib/references");
58
58
  const ReferenceLine_1 = require("./ReferenceLine");
59
59
  const ImportBibliographyForm = ({ onCancel, onSave, }) => {
60
60
  const [dragging, setDragging] = (0, react_1.useState)(false);
61
+ const fileInputRef = (0, react_1.useRef)(null);
61
62
  const formik = (0, formik_1.useFormik)({
62
63
  initialValues: {
63
64
  content: '',
@@ -116,13 +117,19 @@ const ImportBibliographyForm = ({ onCancel, onSave, }) => {
116
117
  };
117
118
  reader.readAsText(file);
118
119
  };
120
+ const handleOnKeyDown = (e) => {
121
+ if (e.key === 'Enter' || e.key === ' ') {
122
+ e.preventDefault();
123
+ fileInputRef?.current?.click();
124
+ }
125
+ };
119
126
  return (react_1.default.createElement("form", { onSubmit: formik.handleSubmit, onReset: formik.handleReset },
120
127
  react_1.default.createElement(style_guide_1.FormRow, null,
121
- react_1.default.createElement(DropContainer, { onDrop: handleDrop, onDragOver: (e) => {
128
+ react_1.default.createElement(DropContainer, { tabIndex: 0, role: "button", onDrop: handleDrop, onDragOver: (e) => {
122
129
  e.preventDefault();
123
130
  setDragging(true);
124
- }, onDragLeave: () => setDragging(false), active: dragging },
125
- react_1.default.createElement("input", { id: "file", name: "file", type: "file", onChange: handleFileChange, style: { display: 'none' } }),
131
+ }, onDragLeave: () => setDragging(false), onKeyDown: handleOnKeyDown, active: dragging },
132
+ react_1.default.createElement("input", { id: "file", name: "file", type: "file", ref: fileInputRef, onChange: handleFileChange, style: { display: 'none' } }),
126
133
  react_1.default.createElement(style_guide_1.Label, { htmlFor: "file" }, "Drag & Drop or Click here to upload a file."))),
127
134
  react_1.default.createElement(style_guide_1.FormRow, null,
128
135
  react_1.default.createElement(style_guide_1.Label, { htmlFor: "content" }, "Alternatively, you can directly Copy&Paste below, the text of the bibliography items."),
@@ -171,4 +178,6 @@ const DropContainer = styled_components_1.default.div `
171
178
  font-family: ${(props) => props.theme.font.family.Lato};
172
179
  color: ${(props) => props.theme.colors.text.onLight};
173
180
  }
181
+
182
+ ${style_guide_1.outlineStyle}
174
183
  `;
@@ -49,7 +49,7 @@ const PersonDropDown = (props) => {
49
49
  react_1.default.createElement(styled_components_1.ToggleButton, { type: "button", onClick: () => setIsOpen(!isOpen), isOpen: isOpen },
50
50
  react_1.default.createElement(styled_components_1.DropdownIndicator, null),
51
51
  title),
52
- react_1.default.createElement(styled_components_1.RemoveButton, { type: "button", "aria-label": "Delete this editor", onClick: () => remove(index) },
52
+ react_1.default.createElement(styled_components_1.RemoveButton, { size: 13, type: "button", "aria-label": "Delete this editor", onClick: () => remove(index) },
53
53
  react_1.default.createElement(style_guide_1.DeleteIcon, null))),
54
54
  isOpen && (react_1.default.createElement(styled_components_1.PersonForm, null,
55
55
  react_1.default.createElement(style_guide_1.FormRow, null,
@@ -92,7 +92,7 @@ exports.ToggleButton = styled_components_1.default.button `
92
92
  text-align: left;
93
93
  font-family: ${(props) => props.theme.font.family.sans};
94
94
  font-size: 1rem;
95
- padding: 0.6em 0.5em;
95
+ margin: 0.6em;
96
96
 
97
97
  outline: none;
98
98
 
@@ -103,11 +103,20 @@ exports.ToggleButton = styled_components_1.default.button `
103
103
  svg {
104
104
  transform: ${(props) => (props.isOpen ? 'rotateX(180deg)' : 'initial')};
105
105
  }
106
+ ${style_guide_1.outlineStyle}
106
107
  `;
107
- exports.RemoveButton = styled_components_1.default.button `
108
+ exports.RemoveButton = (0, styled_components_1.default)(style_guide_1.SecondaryIconButton) `
108
109
  border: none;
109
110
  background: transparent;
110
111
  padding: 0;
111
-
112
112
  outline: none;
113
+ svg {
114
+ path[fill='white'] {
115
+ fill: white;
116
+ }
117
+ rect[fill],
118
+ path:not([fill='white']) {
119
+ fill: #f35143;
120
+ }
121
+ }
113
122
  `;
@@ -70,10 +70,10 @@ const Actions = (0, styled_components_1.default)(style_guide_1.ButtonGroup) `
70
70
  justify-content: space-between;
71
71
  padding: ${(props) => props.theme.grid.unit * 4}px;
72
72
  `;
73
- const Container = styled_components_1.default.div `
73
+ const Container = (0, style_guide_1.withFocusTrap)(styled_components_1.default.div `
74
74
  flex: 1;
75
75
  font-family: ${(props) => props.theme.font.family.sans};
76
- `;
76
+ `);
77
77
  const AddReferenceActions = (0, styled_components_1.default)(style_guide_1.ButtonGroup) `
78
78
  button {
79
79
  margin-right: ${(props) => props.theme.grid.unit * 8}px;