@manuscripts/body-editor 3.16.1 → 3.16.3

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 (63) hide show
  1. package/dist/cjs/components/references/CitationEditor.js +13 -19
  2. package/dist/cjs/components/references/ImportBibliography.js +77 -0
  3. package/dist/cjs/components/references/ImportBibliographyForm.js +1 -1
  4. package/dist/cjs/components/references/ImportBibliographyModal.js +12 -81
  5. package/dist/cjs/components/references/ImportReferencesConfirmation.js +113 -0
  6. package/dist/cjs/components/references/ImportSuccessPlaceholder.js +56 -0
  7. package/dist/cjs/components/references/ReferenceSearch.js +2 -5
  8. package/dist/cjs/components/references/ReferencesEditor.js +18 -2
  9. package/dist/cjs/components/references/ReferencesModal.js +86 -33
  10. package/dist/cjs/lib/view.js +39 -1
  11. package/dist/cjs/versions.js +1 -1
  12. package/dist/cjs/views/bibliography_element.js +1 -2
  13. package/dist/cjs/views/citation_editable.js +2 -29
  14. package/dist/cjs/views/equation.js +2 -0
  15. package/dist/cjs/views/equation_editable.js +2 -0
  16. package/dist/cjs/views/inline_equation.js +2 -0
  17. package/dist/cjs/views/inline_equation_editable.js +2 -0
  18. package/dist/es/components/references/CitationEditor.js +13 -19
  19. package/dist/es/components/references/ImportBibliography.js +70 -0
  20. package/dist/es/components/references/ImportBibliographyForm.js +1 -1
  21. package/dist/es/components/references/ImportBibliographyModal.js +13 -79
  22. package/dist/es/components/references/ImportReferencesConfirmation.js +73 -0
  23. package/dist/es/components/references/ImportSuccessPlaceholder.js +49 -0
  24. package/dist/es/components/references/ReferenceSearch.js +3 -6
  25. package/dist/es/components/references/ReferencesEditor.js +19 -3
  26. package/dist/es/components/references/ReferencesModal.js +88 -35
  27. package/dist/es/lib/view.js +36 -0
  28. package/dist/es/versions.js +1 -1
  29. package/dist/es/views/bibliography_element.js +2 -3
  30. package/dist/es/views/citation_editable.js +3 -30
  31. package/dist/es/views/equation.js +2 -0
  32. package/dist/es/views/equation_editable.js +2 -0
  33. package/dist/es/views/inline_equation.js +2 -0
  34. package/dist/es/views/inline_equation_editable.js +2 -0
  35. package/dist/types/components/references/CitationEditor.d.ts +1 -1
  36. package/dist/types/components/references/ImportBibliography.d.ts +7 -0
  37. package/dist/types/components/references/ImportReferencesConfirmation.d.ts +8 -0
  38. package/dist/types/components/references/ImportSuccessPlaceholder.d.ts +5 -0
  39. package/dist/types/components/references/ReferenceSearch.d.ts +0 -1
  40. package/dist/types/components/references/ReferencesEditor.d.ts +4 -1
  41. package/dist/types/components/references/ReferencesModal.d.ts +1 -0
  42. package/dist/types/lib/view.d.ts +3 -1
  43. package/dist/types/versions.d.ts +1 -1
  44. package/dist/types/views/citation_editable.d.ts +0 -1
  45. package/package.json +1 -1
  46. package/src/components/references/CitationEditor.tsx +16 -25
  47. package/src/components/references/ImportBibliography.tsx +119 -0
  48. package/src/components/references/ImportBibliographyForm.tsx +1 -1
  49. package/src/components/references/ImportBibliographyModal.tsx +34 -110
  50. package/src/components/references/ImportReferencesConfirmation.tsx +133 -0
  51. package/src/components/references/ImportSuccessPlaceholder.tsx +93 -0
  52. package/src/components/references/ReferenceSearch.tsx +0 -7
  53. package/src/components/references/ReferencesEditor.tsx +35 -6
  54. package/src/components/references/ReferencesModal.tsx +164 -78
  55. package/src/lib/view.ts +65 -0
  56. package/src/versions.ts +1 -1
  57. package/src/views/bibliography_element.ts +3 -4
  58. package/src/views/citation_editable.ts +5 -50
  59. package/src/views/equation.ts +5 -0
  60. package/src/views/equation_editable.ts +3 -0
  61. package/src/views/inline_equation.ts +5 -0
  62. package/src/views/inline_equation_editable.ts +3 -0
  63. package/styles/Editor.css +2 -1
@@ -13,7 +13,7 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
- import { ManuscriptEditorView, ManuscriptNodeType } from '@manuscripts/transform';
16
+ import { BibliographyItemAttrs, ManuscriptEditorView, ManuscriptNodeType } from '@manuscripts/transform';
17
17
  import { Attrs } from 'prosemirror-model';
18
18
  import * as utils from 'prosemirror-utils';
19
19
  export declare const findChildByID: (view: ManuscriptEditorView, id: string) => utils.NodeWithPos | undefined;
@@ -22,3 +22,5 @@ export declare const findChildrenByType: (view: ManuscriptEditorView, type: Manu
22
22
  export declare const findChildrenAttrsByType: <T extends Attrs>(view: ManuscriptEditorView, type: ManuscriptNodeType) => T[];
23
23
  export declare const updateNodeAttrs: (view: ManuscriptEditorView, type: ManuscriptNodeType, attrs: Attrs) => boolean;
24
24
  export declare const deleteNode: (view: ManuscriptEditorView, id: string) => void;
25
+ export declare const insertBibliographyItems: (view: ManuscriptEditorView, items: BibliographyItemAttrs[]) => void;
26
+ export declare const saveBibliographyItem: (view: ManuscriptEditorView, attrs: BibliographyItemAttrs[]) => void;
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "3.16.1";
1
+ export declare const VERSION = "3.16.3";
2
2
  export declare const MATHJAX_VERSION = "3.2.2";
@@ -31,7 +31,6 @@ export declare class CitationEditableView extends CitationView {
31
31
  private handleUncite;
32
32
  private handleCite;
33
33
  private handleDelete;
34
- private insertBibliographyNode;
35
34
  }
36
35
  declare const _default: (props: import("../configs/ManuscriptsEditor").EditorProps, dispatch?: import("..").Dispatch) => import("../types").NodeViewCreator<CitationEditableView>;
37
36
  export default _default;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@manuscripts/body-editor",
3
3
  "description": "Prosemirror components for editing and viewing manuscripts",
4
- "version": "3.16.1",
4
+ "version": "3.16.3",
5
5
  "repository": "github:Atypon-OpenSource/manuscripts-body-editor",
6
6
  "license": "Apache-2.0",
7
7
  "main": "dist/cjs",
@@ -36,7 +36,6 @@ import { arrayReducer, attrsReducer } from '../../lib/array-reducer'
36
36
  import { cleanItemValues } from '../../lib/utils'
37
37
  import { BibliographyItemSource } from './BibliographyItemSource'
38
38
  import { CitedItem, CitedItems } from './CitationViewer'
39
- import { ImportBibliographyModal } from './ImportBibliographyModal'
40
39
  import { ReferenceLine } from './ReferenceLine'
41
40
  import { ReferenceSearch } from './ReferenceSearch'
42
41
  import { ReferencesModal } from './ReferencesModal'
@@ -92,7 +91,7 @@ export interface CitationEditorProps {
92
91
  sources: BibliographyItemSource[]
93
92
  onCite: (items: BibliographyItemAttrs[]) => void
94
93
  onUncite: (id: string) => void
95
- onSave: (item: BibliographyItemAttrs) => void
94
+ onSave: (item: BibliographyItemAttrs[]) => void
96
95
  onDelete: (item: BibliographyItemAttrs) => void
97
96
  onCancel: () => void
98
97
  canEdit: boolean
@@ -118,7 +117,7 @@ export const CitationEditor: React.FC<CitationEditorProps> = ({
118
117
  const [rids, dispatchRids] = useReducer(ridsReducer, $rids)
119
118
  const handleSave = (item: BibliographyItemAttrs) => {
120
119
  const cleanedItem = cleanItemValues(item)
121
- onSave(cleanedItem)
120
+ onSave([cleanedItem])
122
121
  dispatchItems({
123
122
  type: 'update',
124
123
  items: [cleanedItem],
@@ -163,7 +162,6 @@ export const CitationEditor: React.FC<CitationEditorProps> = ({
163
162
  })
164
163
 
165
164
  const [searching, setSearching] = useState(false)
166
- const [importing, setImporting] = useState(false)
167
165
 
168
166
  const handleAdd = () => {
169
167
  setSearching(false)
@@ -178,16 +176,19 @@ export const CitationEditor: React.FC<CitationEditorProps> = ({
178
176
  setEditingForm({ show: true, item: item })
179
177
  }
180
178
 
181
- const handleImport = () => {
182
- setSearching(false)
183
- setImporting(true)
184
- }
185
- const handleSaveImport = (data: BibliographyItemAttrs[]) => {
186
- data.forEach((item) => {
187
- const newItem = { ...item }
188
- newItem.id = generateNodeID(schema.nodes.bibliography_item)
189
- handleSave(newItem)
190
- handleCite([newItem])
179
+ const handleImport = (data: BibliographyItemAttrs[]) => {
180
+ const newItems = data.map((item) =>
181
+ cleanItemValues({
182
+ ...item,
183
+ id: generateNodeID(schema.nodes.bibliography_item),
184
+ })
185
+ )
186
+
187
+ onSave(newItems)
188
+
189
+ dispatchItems({
190
+ type: 'set',
191
+ state: [...items, ...newItems],
191
192
  })
192
193
  }
193
194
 
@@ -205,15 +206,7 @@ export const CitationEditor: React.FC<CitationEditorProps> = ({
205
206
  item={editingForm.item}
206
207
  onSave={handleSave}
207
208
  onDelete={handleDelete}
208
- />
209
- )
210
- }
211
-
212
- if (importing) {
213
- return (
214
- <ImportBibliographyModal
215
- onCancel={() => setImporting(false)}
216
- onSave={handleSaveImport}
209
+ handleImport={handleImport}
217
210
  />
218
211
  )
219
212
  }
@@ -223,7 +216,6 @@ export const CitationEditor: React.FC<CitationEditorProps> = ({
223
216
  sources={sources}
224
217
  items={items}
225
218
  onAdd={handleAdd}
226
- onImport={handleImport}
227
219
  onCite={(items) => {
228
220
  setSearching(false)
229
221
  handleCite(items)
@@ -239,7 +231,6 @@ export const CitationEditor: React.FC<CitationEditorProps> = ({
239
231
  sources={sources}
240
232
  items={items}
241
233
  onAdd={handleAdd}
242
- onImport={handleImport}
243
234
  onCite={handleCite}
244
235
  onCancel={onCancel}
245
236
  />
@@ -0,0 +1,119 @@
1
+ /*!
2
+ * © 2026 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 { ModalTitle, Tooltip } from '@manuscripts/style-guide'
17
+ import { BibliographyItemAttrs } from '@manuscripts/transform'
18
+ import React from 'react'
19
+ import styled from 'styled-components'
20
+
21
+ import { ImportBibliographyForm } from './ImportBibliographyForm'
22
+
23
+ const exampleBibtex = `@book{abramowitz+stegun,
24
+ author = "Milton {Abramowitz} and Irene A. {Stegun}",
25
+ title = "Handbook of Mathematical Functions with Formulas, Graphs, and Mathematical Tables",
26
+ publisher = "Dover",
27
+ year = 1964,
28
+ address = "New York City",
29
+ edition = "ninth Dover printing, tenth GPO printing"
30
+ }`
31
+
32
+ const examplePubmed = `Example Identifiers:
33
+ pmid:17170128
34
+ PMC1852221`
35
+
36
+ const exampleRis = `TY - JOUR
37
+ AU - Shannon, Claude E.
38
+ PY - 1948
39
+ DA - July
40
+ TI - A Mathematical Theory of Communication
41
+ T2 - Bell System Technical Journal
42
+ SP - 379
43
+ EP - 423
44
+ VL - 27
45
+ ER - `
46
+
47
+ const exampleEnw = `%0 Journal Article
48
+ %D 2018
49
+ %@ 0903-4641
50
+ %A Abbassi-Daloii, Tooba
51
+ %A Yousefi, Soheil
52
+ %A Sekhavati, Mohammad Hadi
53
+ %A Tahmoorespur, Mojtaba
54
+ %J APMIS
55
+ %N 1
56
+ %P 65-75
57
+ %T Impact of heat shock protein 60KD in combination with outer membrane proteins on immune response against Brucella melitensis
58
+ %R https://doi.org/10.1111/apm.12778
59
+ %U https://onlinelibrary.wiley.com/doi/abs/10.1111/apm.12778
60
+ %V 126
61
+ %X Lorem ipsum dolor sit amet`
62
+
63
+ const exampleDoi = `Example DOI Identifiers:
64
+ 10.1080/15588742.2015.1017684
65
+ http://dx.doi.org/10.1080/15588742.2015.1017684`
66
+
67
+ const supportedFormats = [
68
+ { label: 'BibTex', example: exampleBibtex },
69
+ { label: 'PubMed', example: examplePubmed },
70
+ { label: 'RIS', example: exampleRis },
71
+ { label: 'ENW', example: exampleEnw },
72
+ { label: 'DOI', example: exampleDoi },
73
+ ] as const
74
+
75
+ export interface ImportBibliographyProps {
76
+ onCancel: () => void
77
+ onContinue: (data: BibliographyItemAttrs[]) => void
78
+ }
79
+
80
+ export const ImportBibliography: React.FC<ImportBibliographyProps> = ({
81
+ onCancel,
82
+ onContinue,
83
+ }) => (
84
+ <>
85
+ <ModalTitle>Import Bibliography</ModalTitle>
86
+ <p>
87
+ {supportedFormats.map(({ label, example }, index) => (
88
+ <React.Fragment key={label}>
89
+ {index > 0 &&
90
+ (index === supportedFormats.length - 1 ? ' and ' : ', ')}
91
+ <SpanWithExample
92
+ data-tooltip-id="import-example-tooltip"
93
+ data-tooltip-content={example}
94
+ >
95
+ {label}
96
+ </SpanWithExample>
97
+ </React.Fragment>
98
+ ))}{' '}
99
+ formats are supported
100
+ </p>
101
+ <ImportBibliographyForm onCancel={onCancel} onSave={onContinue} />
102
+ <Example
103
+ id="import-example-tooltip"
104
+ place="bottom"
105
+ render={(s) => <pre>{s.content}</pre>}
106
+ />
107
+ </>
108
+ )
109
+
110
+ const SpanWithExample = styled.span`
111
+ text-decoration: underline dotted;
112
+ text-underline-offset: 4px;
113
+ `
114
+
115
+ const Example = styled(Tooltip)`
116
+ text-align: left !important;
117
+ max-width: 480px !important;
118
+ overflow: hidden !important;
119
+ `
@@ -182,7 +182,7 @@ export const ImportBibliographyForm = ({
182
182
  !formik.dirty || formik.isSubmitting || !formik.values.data.length
183
183
  }
184
184
  >
185
- Save
185
+ Import References
186
186
  </PrimaryButton>
187
187
  </FormActionsBar>
188
188
  </form>
@@ -18,142 +18,66 @@ import {
18
18
  ModalCardBody,
19
19
  ModalContainer,
20
20
  ModalHeader,
21
- ModalTitle,
22
21
  StyledModal,
23
- Tooltip,
24
22
  } from '@manuscripts/style-guide'
25
23
  import { BibliographyItemAttrs } from '@manuscripts/transform'
26
24
  import React, { useState } from 'react'
27
- import styled from 'styled-components'
28
25
 
29
- import { ImportBibliographyForm } from './ImportBibliographyForm'
26
+ import { ImportBibliography } from './ImportBibliography'
27
+ import { ImportReferencesConfirmation } from './ImportReferencesConfirmation'
28
+
30
29
  export interface ImportBibliographyModalProps {
31
30
  onCancel: () => void
32
31
  onSave: (data: BibliographyItemAttrs[]) => void
33
32
  }
34
33
 
35
- const exampleBibtex = `@book{abramowitz+stegun,
36
- author = "Milton {Abramowitz} and Irene A. {Stegun}",
37
- title = "Handbook of Mathematical Functions with Formulas, Graphs, and Mathematical Tables",
38
- publisher = "Dover",
39
- year = 1964,
40
- address = "New York City",
41
- edition = "ninth Dover printing, tenth GPO printing"
42
- }`
43
-
44
- const examplePubmed = `Example Identifiers:
45
- pmid:17170128
46
- PMC1852221`
47
-
48
- const exampleRis = `TY - JOUR
49
- AU - Shannon, Claude E.
50
- PY - 1948
51
- DA - July
52
- TI - A Mathematical Theory of Communication
53
- T2 - Bell System Technical Journal
54
- SP - 379
55
- EP - 423
56
- VL - 27
57
- ER - `
58
-
59
- const exampleEnw = `%0 Journal Article
60
- %D 2018
61
- %@ 0903-4641
62
- %A Abbassi-Daloii, Tooba
63
- %A Yousefi, Soheil
64
- %A Sekhavati, Mohammad Hadi
65
- %A Tahmoorespur, Mojtaba
66
- %J APMIS
67
- %N 1
68
- %P 65-75
69
- %T Impact of heat shock protein 60KD in combination with outer membrane proteins on immune response against Brucella melitensis
70
- %R https://doi.org/10.1111/apm.12778
71
- %U https://onlinelibrary.wiley.com/doi/abs/10.1111/apm.12778
72
- %V 126
73
- %X Lorem ipsum dolor sit amet`
74
-
75
- const exampleDoi = `Example DOI Identifiers:
76
- 10.1080/15588742.2015.1017684
77
- http://dx.doi.org/10.1080/15588742.2015.1017684`
78
-
79
34
  export const ImportBibliographyModal: React.FC<
80
35
  ImportBibliographyModalProps
81
36
  > = ({ onCancel, onSave }) => {
82
37
  const [isOpen, setOpen] = useState(true)
38
+ const [pendingItems, setPendingItems] = useState<
39
+ BibliographyItemAttrs[] | null
40
+ >(null)
83
41
 
84
- const handleCancel = () => {
85
- handleClose()
86
- }
42
+ const isConfirming = pendingItems !== null
87
43
  const handleClose = () => setOpen(false)
44
+ const handleBack = () => setPendingItems(null)
88
45
 
89
- const handleSave = (data: BibliographyItemAttrs[]) => {
90
- onSave(data)
46
+ const handleConfirm = (items: BibliographyItemAttrs[]) => {
47
+ onSave(items)
91
48
  handleClose()
92
49
  }
93
50
 
94
51
  return (
95
52
  <StyledModal isOpen={isOpen} onRequestClose={onCancel}>
96
- <ModalContainer data-cy="import-bibliography-modal">
53
+ <ModalContainer
54
+ data-cy={
55
+ isConfirming
56
+ ? 'import-confirmation-modal'
57
+ : 'import-bibliography-modal'
58
+ }
59
+ >
97
60
  <ModalHeader>
98
- <CloseButton onClick={onCancel} data-cy="modal-close-button" />
99
- </ModalHeader>
100
- <ModalCardBody $width={640}>
101
- <ModalTitle>Import Bibliography</ModalTitle>
102
- <p>
103
- <SpanWithExample
104
- data-tooltip-id="import-example-tooltip"
105
- data-tooltip-content={exampleBibtex}
106
- >
107
- BibTex
108
- </SpanWithExample>
109
- ,{' '}
110
- <SpanWithExample
111
- data-tooltip-id="import-example-tooltip"
112
- data-tooltip-content={examplePubmed}
113
- >
114
- PubMed
115
- </SpanWithExample>
116
- ,{' '}
117
- <SpanWithExample
118
- data-tooltip-id="import-example-tooltip"
119
- data-tooltip-content={exampleRis}
120
- >
121
- RIS
122
- </SpanWithExample>
123
- ,{' '}
124
- <SpanWithExample
125
- data-tooltip-id="import-example-tooltip"
126
- data-tooltip-content={exampleEnw}
127
- >
128
- ENW
129
- </SpanWithExample>{' '}
130
- and{' '}
131
- <SpanWithExample
132
- data-tooltip-id="import-example-tooltip"
133
- data-tooltip-content={exampleDoi}
134
- >
135
- DOI
136
- </SpanWithExample>{' '}
137
- formats are supported
138
- </p>
139
- <ImportBibliographyForm onCancel={handleCancel} onSave={handleSave} />
140
- <Example
141
- id="import-example-tooltip"
142
- place="bottom"
143
- render={(s) => <pre>{s.content}</pre>}
61
+ <CloseButton
62
+ onClick={isConfirming ? handleBack : onCancel}
63
+ data-cy="modal-close-button"
144
64
  />
65
+ </ModalHeader>
66
+ <ModalCardBody $width={724}>
67
+ {pendingItems ? (
68
+ <ImportReferencesConfirmation
69
+ items={pendingItems}
70
+ onCancel={handleBack}
71
+ onConfirm={handleConfirm}
72
+ />
73
+ ) : (
74
+ <ImportBibliography
75
+ onCancel={onCancel}
76
+ onContinue={setPendingItems}
77
+ />
78
+ )}
145
79
  </ModalCardBody>
146
80
  </ModalContainer>
147
81
  </StyledModal>
148
82
  )
149
83
  }
150
-
151
- const SpanWithExample = styled.span`
152
- text-decoration: underline dotted;
153
- text-underline-offset: 4px;
154
- `
155
- const Example = styled(Tooltip)`
156
- text-align: left !important;
157
- max-width: 480px !important;
158
- overflow: hidden !important;
159
- `
@@ -0,0 +1,133 @@
1
+ /*!
2
+ * © 2026 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 {
17
+ CheckboxField,
18
+ CheckboxLabel,
19
+ FormActionsBar,
20
+ ModalTitle,
21
+ PrimaryButton,
22
+ SecondaryButton,
23
+ } from '@manuscripts/style-guide'
24
+ import { BibliographyItemAttrs } from '@manuscripts/transform'
25
+ import React, { useState } from 'react'
26
+ import styled from 'styled-components'
27
+
28
+ import { ReferenceLine } from './ReferenceLine'
29
+
30
+ export interface ImportReferencesConfirmationProps {
31
+ items: BibliographyItemAttrs[]
32
+ onCancel: () => void
33
+ onConfirm: (items: BibliographyItemAttrs[]) => void
34
+ }
35
+
36
+ export const ImportReferencesConfirmation: React.FC<
37
+ ImportReferencesConfirmationProps
38
+ > = ({ items, onCancel, onConfirm }) => {
39
+ const [selected, setSelected] = useState(() => items.map(() => true))
40
+
41
+ const selectedCount = selected.filter(Boolean).length
42
+ const countLabel = selectedCount === 1 ? 'reference' : 'references'
43
+
44
+ const toggleItem = (index: number) => {
45
+ setSelected((current) =>
46
+ current.map((value, i) => (i === index ? !value : value))
47
+ )
48
+ }
49
+
50
+ const handleConfirm = () => {
51
+ onConfirm(items.filter((_, index) => selected[index]))
52
+ }
53
+
54
+ return (
55
+ <>
56
+ <Title>Import References</Title>
57
+ <Subtitle>
58
+ Importing {selectedCount} {countLabel}
59
+ </Subtitle>
60
+ <List>
61
+ {items.map((item, index) => (
62
+ <ListItem key={index}>
63
+ <ItemCheckbox>
64
+ <CheckboxField
65
+ checked={selected[index]}
66
+ aria-label={`Select reference ${index + 1}`}
67
+ onChange={() => toggleItem(index)}
68
+ />
69
+ <div />
70
+ </ItemCheckbox>
71
+ <ReferenceLine item={item} />
72
+ </ListItem>
73
+ ))}
74
+ </List>
75
+ <FormActionsBar>
76
+ <SecondaryButton type="button" onClick={onCancel}>
77
+ Cancel
78
+ </SecondaryButton>
79
+ <PrimaryButton
80
+ type="button"
81
+ disabled={selectedCount === 0}
82
+ onClick={handleConfirm}
83
+ >
84
+ Import {selectedCount} {countLabel}
85
+ </PrimaryButton>
86
+ </FormActionsBar>
87
+ </>
88
+ )
89
+ }
90
+
91
+ const Title = styled(ModalTitle)`
92
+ border-bottom: 1px solid ${(props) => props.theme.colors.border.secondary};
93
+ margin: 0 -${(props) => 6 * props.theme.grid.unit}px 20px;
94
+ padding: 0 ${(props) => 6 * props.theme.grid.unit}px
95
+ ${(props) => props.theme.grid.unit * 4}px;
96
+ `
97
+
98
+ const Subtitle = styled.p`
99
+ color: ${(props) => props.theme.colors.text.secondary};
100
+ font-weight: ${(props) => props.theme.font.weight.bold};
101
+ margin: 0 0 16px;
102
+ font-size: 14px;
103
+ `
104
+
105
+ const List = styled.div`
106
+ display: flex;
107
+ flex-direction: column;
108
+ margin-bottom: ${(props) => props.theme.grid.unit * 5}px;
109
+ overflow-y: auto;
110
+ `
111
+
112
+ const ListItem = styled.div`
113
+ border-bottom: 1px solid ${(props) => props.theme.colors.border.secondary};
114
+ display: flex;
115
+ align-items: flex-start;
116
+ gap: ${(props) => props.theme.grid.unit * 3}px;
117
+ padding: ${(props) => props.theme.grid.unit * 3}px 0;
118
+ `
119
+
120
+ const ItemCheckbox = styled(CheckboxLabel)`
121
+ flex-shrink: 0;
122
+
123
+ > div {
124
+ margin: 0;
125
+
126
+ &::before {
127
+ width: 18px;
128
+ height: 18px;
129
+ border-radius: 4px;
130
+ margin: 0;
131
+ }
132
+ }
133
+ `
@@ -0,0 +1,93 @@
1
+ /*!
2
+ * © 2026 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 styled from 'styled-components'
18
+
19
+ export interface ImportSuccessPlaceholderProps {
20
+ count: number
21
+ }
22
+
23
+ export const ImportSuccessPlaceholder: React.FC<
24
+ ImportSuccessPlaceholderProps
25
+ > = ({ count }) => {
26
+ const countLabel = count === 1 ? 'reference' : 'references'
27
+
28
+ return (
29
+ <Container data-cy="import-success-placeholder">
30
+ <IconCircle>
31
+ <SuccessCheckIcon />
32
+ </IconCircle>
33
+ <Title>Successfully Imported</Title>
34
+ <Message>
35
+ Your library has been updated with {count} new {countLabel}.
36
+ </Message>
37
+ </Container>
38
+ )
39
+ }
40
+
41
+ const SuccessCheckIcon = () => (
42
+ <svg
43
+ width="32"
44
+ height="32"
45
+ viewBox="0 0 32 32"
46
+ fill="none"
47
+ xmlns="http://www.w3.org/2000/svg"
48
+ aria-hidden="true"
49
+ >
50
+ <path
51
+ d="M26.6656 8L12.0004 22.6656L5.3344 15.9994"
52
+ stroke="#36B260"
53
+ strokeWidth="3"
54
+ strokeLinecap="round"
55
+ />
56
+ </svg>
57
+ )
58
+
59
+ const Container = styled.div`
60
+ display: flex;
61
+ flex-direction: column;
62
+ align-items: center;
63
+ justify-content: center;
64
+ gap: ${(props) => props.theme.grid.unit * 4}px;
65
+ height: 100%;
66
+ padding: 40px;
67
+ box-sizing: border-box;
68
+ text-align: center;
69
+ `
70
+
71
+ const IconCircle = styled.div`
72
+ display: flex;
73
+ align-items: center;
74
+ justify-content: center;
75
+ width: 64px;
76
+ height: 64px;
77
+ border-radius: 32px;
78
+ background: #f6ffed;
79
+ `
80
+
81
+ const Title = styled.h2`
82
+ margin: 0;
83
+ font-size: 24px;
84
+ line-height: 32px;
85
+ letter-spacing: -0.37px;
86
+ color: ${(props) => props.theme.colors.text.primary};
87
+ `
88
+
89
+ const Message = styled.p`
90
+ margin: 0;
91
+ line-height: ${(props) => props.theme.font.lineHeight.large};
92
+ color: ${(props) => props.theme.colors.text.secondary};
93
+ `