@manuscripts/body-editor 2.8.79-test-multiple-images.1 → 2.8.79

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.
@@ -22,10 +22,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
22
22
  step((generator = generator.apply(thisArg, _arguments || [])).next());
23
23
  });
24
24
  };
25
- import { ContextMenu, FileCorruptedIcon, ImageDefaultIcon, ImageLeftIcon, ImageRightIcon, PlusIcon, } from '@manuscripts/style-guide';
25
+ import { ContextMenu, FileCorruptedIcon, ImageDefaultIcon, ImageLeftIcon, ImageRightIcon, } from '@manuscripts/style-guide';
26
26
  import { schema } from '@manuscripts/transform';
27
27
  import { NodeSelection } from 'prosemirror-state';
28
- import { findParentNodeOfTypeClosestToPos } from 'prosemirror-utils';
29
28
  import { createElement } from 'react';
30
29
  import { renderToStaticMarkup } from 'react-dom/server';
31
30
  import { FigureOptions, } from '../components/views/FigureDropdown';
@@ -45,146 +44,60 @@ export var figurePositions;
45
44
  export class FigureEditableView extends FigureView {
46
45
  constructor() {
47
46
  super(...arguments);
48
- this.addImageButton = null;
49
- this.imageToolContainers = new Map();
50
- this.upload = (file, index = 0) => __awaiter(this, void 0, void 0, function* () {
51
- try {
52
- const result = yield this.props.fileManagement.upload(file);
53
- this.addImage(result.id, index);
54
- }
55
- catch (error) {
56
- console.error('Upload failed:', error);
57
- throw error;
58
- }
47
+ this.upload = (file) => __awaiter(this, void 0, void 0, function* () {
48
+ const result = yield this.props.fileManagement.upload(file);
49
+ this.setSrc(result.id);
59
50
  });
60
- this.createImg = (src) => {
61
- const img = document.createElement('img');
62
- img.classList.add('figure-image');
63
- img.src = src;
64
- return img;
65
- };
66
- this.createPlaceholder = (index) => {
67
- const element = document.createElement('div');
68
- element.classList.add('figure', 'placeholder');
69
- element.dataset.index = index.toString();
70
- const instructions = document.createElement('div');
71
- instructions.classList.add('instructions');
72
- instructions.innerHTML = `
73
- <p>Drag or click here to upload image <br>
74
- or drag items here from the file inspector tabs <br>
75
- <a data-action='open-other-files'>'Other files'</a> |
76
- <a data-action='open-supplement-files'>'Supplements'</a></p>
77
- `;
78
- const can = this.props.getCapabilities();
79
- if (can.uploadFile && !isDeleted(this.node)) {
80
- const handlePlaceholderClick = (event) => {
81
- var _a;
82
- const target = event.target;
83
- if ((_a = target.dataset) === null || _a === void 0 ? void 0 : _a.action) {
84
- return;
85
- }
86
- const triggerUpload = figureUploader((file) => this.upload(file, index));
87
- triggerUpload();
88
- };
89
- element.addEventListener('click', handlePlaceholderClick);
90
- element.addEventListener('dragenter', (event) => {
91
- event.preventDefault();
92
- event.stopPropagation();
93
- element.classList.add('drag-over');
94
- });
95
- element.addEventListener('dragover', (event) => {
96
- event.preventDefault();
97
- event.stopPropagation();
98
- element.classList.add('drag-over');
99
- if (event.dataTransfer) {
100
- event.dataTransfer.dropEffect = 'copy';
101
- }
102
- });
103
- element.addEventListener('dragleave', (event) => {
104
- event.preventDefault();
105
- event.stopPropagation();
106
- element.classList.remove('drag-over');
107
- });
108
- element.addEventListener('drop', (event) => __awaiter(this, void 0, void 0, function* () {
109
- var _a, _b;
110
- event.preventDefault();
111
- event.stopPropagation();
112
- element.classList.remove('drag-over');
113
- if ((_b = (_a = event.dataTransfer) === null || _a === void 0 ? void 0 : _a.files) === null || _b === void 0 ? void 0 : _b.length) {
114
- const originalContent = instructions.innerHTML;
115
- instructions.innerHTML = '<p>Uploading image...</p>';
116
- try {
117
- yield this.upload(event.dataTransfer.files[0], index);
118
- }
119
- catch (error) {
120
- console.error('Upload failed:', error);
121
- instructions.innerHTML = originalContent;
122
- }
123
- }
124
- }));
125
- element.addEventListener('mouseenter', () => {
126
- element.classList.add('over');
127
- });
128
- element.addEventListener('mouseleave', () => {
129
- element.classList.remove('over');
130
- });
131
- }
132
- element.appendChild(instructions);
133
- return element;
51
+ this.setSrc = (src) => {
52
+ const { tr } = this.view.state;
53
+ const pos = this.getPos();
54
+ tr.setNodeMarkup(pos, undefined, Object.assign(Object.assign({}, this.node.attrs), { src: src }));
55
+ tr.setSelection(NodeSelection.create(tr.doc, pos));
56
+ this.view.dispatch(tr);
134
57
  };
135
- this.createUnsupportedFormat = (file, index) => {
58
+ this.createUnsupportedFormat = (name) => {
136
59
  var _a;
137
60
  const element = document.createElement('div');
138
61
  element.classList.add('figure', 'placeholder');
139
- element.dataset.fileId = file.id;
140
- element.dataset.index = index.toString();
141
62
  const instructions = document.createElement('div');
142
63
  instructions.classList.add('instructions');
143
64
  const iconHtml = renderToStaticMarkup(createElement(FileCorruptedIcon, { className: 'icon' }));
144
65
  instructions.innerHTML = `
145
66
  <div>
146
67
  <div class="unsupported-icon-wrapper">${iconHtml}</div>
147
- <div>${file.name}</div>
68
+ <div>${name}</div>
148
69
  <div class="unsupported-format-label">
149
70
  Unsupported file format
150
71
  </div>
151
72
  <div>
152
73
  ${((_a = this.props.getCapabilities()) === null || _a === void 0 ? void 0 : _a.editArticle)
153
- ? 'Click to replace with supported image'
154
- : 'Unsupported file format'}
74
+ ? 'Click to add image'
75
+ : 'No image here yet…'}
155
76
  </div>
156
77
  </div>
157
78
  `;
158
- const can = this.props.getCapabilities();
159
- if (can.uploadFile && !isDeleted(this.node)) {
160
- element.addEventListener('click', (event) => {
161
- var _a;
162
- const target = event.target;
163
- if ((_a = target.dataset) === null || _a === void 0 ? void 0 : _a.action) {
164
- return;
165
- }
166
- const triggerUpload = figureUploader((newFile) => {
167
- this.detachImage(index);
168
- return this.upload(newFile, index);
169
- });
170
- triggerUpload();
171
- });
172
- element.addEventListener('mouseenter', () => {
173
- element.classList.add('over');
174
- });
175
- element.addEventListener('mouseleave', () => {
176
- element.classList.remove('over');
177
- });
178
- }
179
79
  element.appendChild(instructions);
180
80
  return element;
181
81
  };
182
- this.setSrc = (src) => {
183
- const { tr } = this.view.state;
184
- const pos = this.getPos();
185
- tr.setNodeMarkup(pos, undefined, Object.assign(Object.assign({}, this.node.attrs), { src: src }));
186
- tr.setSelection(NodeSelection.create(tr.doc, pos));
187
- this.view.dispatch(tr);
82
+ this.createImg = (src) => {
83
+ const img = document.createElement('img');
84
+ img.classList.add('figure-image');
85
+ img.src = src;
86
+ return img;
87
+ };
88
+ this.createPlaceholder = () => {
89
+ const element = document.createElement('div');
90
+ element.classList.add('figure', 'placeholder');
91
+ const instructions = document.createElement('div');
92
+ instructions.classList.add('instructions');
93
+ instructions.innerHTML = `
94
+ <p>Drag or click here to upload image <br>
95
+ or drag items here from the file inspector tabs <br>
96
+ <a data-action='open-other-files'>'Other files'</a> |
97
+ <a data-action='open-supplement-files'>'Supplements'</a></p>
98
+ `;
99
+ element.appendChild(instructions);
100
+ return element;
188
101
  };
189
102
  this.createPositionMenuWrapper = () => {
190
103
  const can = this.props.getCapabilities();
@@ -257,120 +170,109 @@ export class FigureEditableView extends FigureView {
257
170
  }
258
171
  updateContents() {
259
172
  super.updateContents();
260
- const src = this.node.attrs.src || '';
261
- const images = Array.isArray(src) ? src : [src];
173
+ const src = this.node.attrs.src;
262
174
  const files = this.props.getFiles();
175
+ const file = src && files.filter((f) => f.id === src)[0];
263
176
  this.figurePosition = this.node.attrs.type;
264
- const can = this.props.getCapabilities();
265
177
  this.container.innerHTML = '';
266
- this.imageToolContainers.clear();
267
- this.imagesContainer = document.createElement('div');
268
- this.imagesContainer.classList.add('figure-images-container');
269
- images.forEach((imageSrc, index) => {
270
- const file = imageSrc && files.find((f) => f.id === imageSrc);
271
- const imgContainer = document.createElement('div');
272
- imgContainer.classList.add('figure-image-container');
273
- const imgElement = imageSrc
274
- ? file
275
- ? this.props.fileManagement.previewLink(file)
276
- ? this.createImg(this.props.fileManagement.previewLink(file))
277
- : this.createUnsupportedFormat(file, index)
278
- : this.createPlaceholder(index)
279
- : this.createPlaceholder(index);
280
- imgContainer.appendChild(imgElement);
281
- if (can.editArticle && !isDeleted(this.node) && file) {
282
- const toolContainer = this.createImageToolContainer(index, file);
283
- imgContainer.appendChild(toolContainer);
284
- this.imageToolContainers.set(index, toolContainer);
285
- }
286
- this.imagesContainer.appendChild(imgContainer);
287
- });
178
+ const can = this.props.getCapabilities();
179
+ const link = file && this.props.fileManagement.previewLink(file);
180
+ const img = link
181
+ ? this.createImg(link)
182
+ : file
183
+ ? this.createUnsupportedFormat(file.name)
184
+ : this.createPlaceholder();
288
185
  if (can.uploadFile && !isDeleted(this.node)) {
289
- const lastImage = images[images.length - 1];
290
- const isLastPlaceholderEmpty = lastImage === '' || !lastImage;
291
- const parent = findParentNodeOfTypeClosestToPos(this.view.state.tr.doc.resolve(this.getPos()), schema.nodes.figure_element);
292
- if (!this.addImageButton) {
293
- this.addImageButton = document.createElement('button');
294
- this.addImageButton.classList.add('add-image-button');
295
- this.addImageButton.innerHTML = renderToStaticMarkup(createElement(PlusIcon, { className: 'icon' }));
296
- this.addImageButton.title = 'Add another image';
297
- this.addImageButton.addEventListener('click', () => {
298
- this.addNewImagePlaceholder();
299
- });
300
- }
301
- if (isLastPlaceholderEmpty) {
302
- this.addImageButton.classList.add('disabled');
303
- }
304
- else {
305
- this.addImageButton.classList.remove('disabled');
306
- }
307
- if (!this.imagesContainer.contains(this.addImageButton) &&
308
- (parent === null || parent === void 0 ? void 0 : parent.node.type) === schema.nodes.figure_element) {
309
- this.imagesContainer.appendChild(this.addImageButton);
310
- }
311
- }
312
- else {
313
- if (this.addImageButton) {
314
- this.addImageButton.remove();
315
- this.addImageButton = null;
316
- }
186
+ const handlePlaceholderClick = (event) => {
187
+ const target = event.target;
188
+ if (target.dataset && target.dataset.action) {
189
+ return;
190
+ }
191
+ const triggerUpload = figureUploader(this.upload);
192
+ triggerUpload();
193
+ };
194
+ img.addEventListener('click', handlePlaceholderClick);
195
+ img.addEventListener('mouseenter', () => {
196
+ img.classList.toggle('over', true);
197
+ });
198
+ img.addEventListener('mouseleave', () => {
199
+ img.classList.toggle('over', false);
200
+ });
201
+ img.addEventListener('dragenter', (event) => {
202
+ event.preventDefault();
203
+ img.classList.toggle('over', true);
204
+ });
205
+ img.addEventListener('dragleave', () => {
206
+ img.classList.toggle('over', false);
207
+ });
208
+ img.addEventListener('dragover', (e) => {
209
+ if (e.dataTransfer && e.dataTransfer.items) {
210
+ for (const item of e.dataTransfer.items) {
211
+ if (item.kind === 'file' && item.type.startsWith('image/')) {
212
+ e.preventDefault();
213
+ e.dataTransfer.dropEffect = 'copy';
214
+ }
215
+ }
216
+ }
217
+ });
218
+ img.addEventListener('drop', (e) => __awaiter(this, void 0, void 0, function* () {
219
+ if (e.dataTransfer && e.dataTransfer.files.length) {
220
+ e.preventDefault();
221
+ yield this.upload(e.dataTransfer.files[0]);
222
+ }
223
+ }));
317
224
  }
318
- this.container.appendChild(this.imagesContainer);
225
+ this.container.innerHTML = '';
226
+ this.container.appendChild(img);
319
227
  this.addTools();
320
228
  }
321
- createImageToolContainer(index, file) {
322
- const toolContainer = document.createElement('div');
323
- toolContainer.classList.add('image-tool-container');
324
- const can = this.props.getCapabilities();
229
+ addTools() {
230
+ this.manageReactTools();
231
+ this.container.appendChild(this.createPositionMenuWrapper());
232
+ }
233
+ manageReactTools() {
234
+ var _a;
235
+ let handleDownload;
236
+ let handleUpload;
237
+ let handleReplace;
238
+ let handleDetach;
239
+ const src = this.node.attrs.src;
325
240
  const files = this.props.getFiles();
326
- const doc = this.view.state.doc;
327
- if (file) {
241
+ const file = src && files.filter((f) => f.id === src)[0];
242
+ const can = this.props.getCapabilities();
243
+ if (src) {
244
+ if (file) {
245
+ handleDownload = () => {
246
+ this.props.fileManagement.download(file);
247
+ };
248
+ }
249
+ handleDetach = () => {
250
+ this.setSrc('');
251
+ };
252
+ }
253
+ if (can.replaceFile) {
254
+ handleReplace = (file) => {
255
+ this.setSrc(file.id);
256
+ };
257
+ }
258
+ if (can.uploadFile) {
259
+ handleUpload = figureUploader(this.upload);
260
+ }
261
+ (_a = this.reactTools) === null || _a === void 0 ? void 0 : _a.remove();
262
+ if (this.props.dispatch && this.props.theme) {
263
+ const files = this.props.getFiles();
264
+ const doc = this.view.state.doc;
328
265
  const componentProps = {
329
266
  can,
330
267
  files: groupFiles(doc, files),
331
- onDownload: () => this.props.fileManagement.download(file),
332
- onUpload: () => {
333
- const triggerUpload = figureUploader((file) => this.upload(file, index));
334
- triggerUpload();
335
- },
336
- onDetach: () => this.detachImage(index),
337
- onReplace: (newFile) => this.addImage(newFile.id, index),
268
+ onDownload: handleDownload,
269
+ onUpload: handleUpload,
270
+ onDetach: handleDetach,
271
+ onReplace: handleReplace,
338
272
  };
339
- const reactTools = ReactSubView(this.props, FigureOptions, componentProps, this.node, this.getPos, this.view);
340
- toolContainer.appendChild(reactTools);
273
+ this.reactTools = ReactSubView(this.props, FigureOptions, componentProps, this.node, this.getPos, this.view);
274
+ this.dom.insertBefore(this.reactTools, this.dom.firstChild);
341
275
  }
342
- return toolContainer;
343
- }
344
- addNewImagePlaceholder() {
345
- const currentImages = this.getCurrentImages();
346
- this.setImages([...currentImages, '']);
347
- }
348
- addImage(src, index) {
349
- const currentImages = this.getCurrentImages();
350
- const newImages = [...currentImages];
351
- newImages[index] = src;
352
- this.setImages(newImages);
353
- }
354
- detachImage(index) {
355
- const currentImages = this.getCurrentImages();
356
- const newImages = [...currentImages];
357
- newImages[index] = '';
358
- this.setImages(newImages);
359
- }
360
- getCurrentImages() {
361
- const src = this.node.attrs.src || '';
362
- return Array.isArray(src) ? src : [src];
363
- }
364
- setImages(images) {
365
- const src = images.length === 1 ? images[0] : images;
366
- const { tr } = this.view.state;
367
- const pos = this.getPos();
368
- tr.setNodeMarkup(pos, undefined, Object.assign(Object.assign({}, this.node.attrs), { src }));
369
- tr.setSelection(NodeSelection.create(tr.doc, pos));
370
- this.view.dispatch(tr);
371
- }
372
- addTools() {
373
- this.container.appendChild(this.createPositionMenuWrapper());
374
276
  }
375
277
  }
376
278
  export default createEditableNodeView(FigureEditableView);
@@ -52,6 +52,7 @@ export interface EditorProps {
52
52
  dispatch?: Dispatch;
53
53
  onEditorClick: (pos: number, node: ManuscriptNode, nodePos: number, event: MouseEvent) => void;
54
54
  lockBody: boolean;
55
+ isViewingMode?: boolean;
55
56
  }
56
57
  export type ExternalProps = Omit<EditorProps, 'popper' | 'dispatch'>;
57
58
  export declare const createEditorState: (props: EditorProps) => EditorState;
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "2.8.79-test-multiple-images.1";
1
+ export declare const VERSION = "2.8.79";
2
2
  export declare const MATHJAX_VERSION = "3.2.2";
@@ -13,7 +13,6 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
- import { FileAttachment } from '../lib/files';
17
16
  import { FigureView } from './figure';
18
17
  export declare enum figurePositions {
19
18
  left = "half-left",
@@ -24,23 +23,15 @@ export declare class FigureEditableView extends FigureView {
24
23
  reactTools: HTMLDivElement;
25
24
  positionMenuWrapper: HTMLDivElement;
26
25
  figurePosition: string;
27
- addImageButton: HTMLButtonElement | null;
28
- imagesContainer: HTMLDivElement;
29
- imageToolContainers: Map<number, HTMLDivElement>;
30
26
  initialise(): void;
31
- upload: (file: File, index?: number) => Promise<void>;
27
+ upload: (file: File) => Promise<void>;
32
28
  updateContents(): void;
33
- private createImageToolContainer;
34
- private addNewImagePlaceholder;
35
- private addImage;
36
- private detachImage;
37
- private getCurrentImages;
38
- private setImages;
39
- protected createImg: (src: string) => HTMLImageElement;
40
- protected createPlaceholder: (index: number) => HTMLDivElement;
41
- protected createUnsupportedFormat: (file: FileAttachment, index: number) => HTMLDivElement;
42
29
  protected addTools(): void;
30
+ private manageReactTools;
43
31
  protected setSrc: (src: string) => void;
32
+ private createUnsupportedFormat;
33
+ protected createImg: (src: string) => HTMLImageElement;
34
+ protected createPlaceholder: () => HTMLDivElement;
44
35
  createPositionMenuWrapper: () => HTMLDivElement;
45
36
  showPositionMenu: () => void;
46
37
  }
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": "2.8.79-test-multiple-images.1",
4
+ "version": "2.8.79",
5
5
  "repository": "github:Atypon-OpenSource/manuscripts-body-editor",
6
6
  "license": "Apache-2.0",
7
7
  "main": "dist/cjs",
@@ -122,8 +122,6 @@
122
122
  text-indent: 0pt;
123
123
  }
124
124
 
125
- /* Figures */
126
-
127
125
  .ProseMirror .figure-block {
128
126
  width: 100%;
129
127
  border: 1px solid #f2f2f2;
@@ -134,11 +132,6 @@
134
132
 
135
133
  grid-template-columns: repeat(3, auto) !important;
136
134
  grid-template-rows: repeat(1, minmax(min-content, max-content)) [caption listing] auto !important;
137
-
138
- margin: 16px 0 0;
139
- box-sizing: border-box;
140
- justify-self: center;
141
- position: relative;
142
135
  }
143
136
 
144
137
  .ProseMirror .figure-group {
@@ -151,134 +144,8 @@
151
144
  width: 100%;
152
145
  position: relative;
153
146
  grid-column: 1/-1;
154
- margin: 0;
155
- display: flex;
156
- flex-direction: column;
157
- justify-content: flex-end;
158
- align-items: center;
159
- }
160
-
161
- .ProseMirror .figure-images-container .figure-image-container {
162
- position: relative;
163
- margin-bottom: 30px;
164
- }
165
-
166
- .ProseMirror .figure-block > figure .figure-images-container .add-image-button {
167
- border: 0px;
168
- left: -18px;
169
- width: 25px;
170
- height: 25px;
171
- cursor: pointer;
172
- border-radius: 50%;
173
- position: absolute;
174
- background-color: #6E6E6E;
175
- }
176
-
177
- .ProseMirror .figure-block > figure .figure-images-container .add-image-button.disabled {
178
- background-color: #E2E2E2 !important;
179
- }
180
-
181
- .ProseMirror .figure-block > figure .figure-images-container .add-image-button svg path {
182
- fill: #FFFFFF !important;
183
- }
184
-
185
-
186
- .ProseMirror .figure-block:hover .options-button {
187
- visibility: visible;
188
- }
189
-
190
- .ProseMirror .block:focus-within .figure-block,
191
- .ProseMirror .block:hover .figure-block {
192
- border-color: #e2e2e2;
193
- }
194
-
195
- .ProseMirror .figure-block[data-alignment='left'] {
196
- justify-self: flex-start;
197
- }
198
-
199
- .ProseMirror .figure-block[data-alignment='right'] {
200
- justify-self: flex-end;
201
- }
202
-
203
- .ProseMirror .figure-block .expanded-listing .executable-attachments {
204
- display: block;
205
- }
206
-
207
- .ProseMirror .figure-block > .listing {
208
- grid-column-start: 1;
209
- grid-column-end: -1;
210
- padding: 0;
211
- min-height: 0;
212
- overflow: visible;
213
- width: 100%;
214
- }
215
-
216
- .ProseMirror .figure-block > figcaption {
217
- grid-column-start: 1;
218
- grid-column-end: -1;
219
- margin-top: 30px;
220
- }
221
-
222
- .ProseMirror .figure-caption {
223
- display: none;
224
147
  }
225
148
 
226
- .ProseMirror .figure.placeholder {
227
- align-items: center;
228
- border-radius: 16px;
229
- border: 1px dashed #e2e2e2;
230
- background-color: #fafafa;
231
- cursor: pointer;
232
- display: flex;
233
- justify-content: center;
234
- text-align: center;
235
- padding: 64px 32px;
236
- max-width: 210px;
237
- min-height: 100px;
238
- white-space: normal;
239
- font-size: 14px;
240
- }
241
-
242
- .ProseMirror .figure.placeholder a {
243
- text-decoration: underline;
244
- }
245
-
246
- .ProseMirror .figure.placeholder.over {
247
- border-color: #bce7f6;
248
- }
249
-
250
- .ProseMirror .figure-image {
251
- max-width: 100%;
252
- object-fit: contain;
253
- }
254
-
255
- .ProseMirror .figure-embed {
256
- width: 640px;
257
- max-width: 90%;
258
- position: relative;
259
- padding-top: 56.25%; /* Player ratio: 100 / (1280 / 720) */
260
- }
261
-
262
- .ProseMirror .figure-embed .figure-embed-object {
263
- position: absolute;
264
- top: 0;
265
- left: 0;
266
- border: none;
267
- }
268
-
269
- .ProseMirror figcaption {
270
- background: white;
271
- font-size: 14px;
272
- margin-top: 1em;
273
- text-align: center;
274
- word-wrap: break-word;
275
- }
276
-
277
- .ProseMirror .block-table_element figcaption {
278
- text-align: left;
279
- }
280
-
281
-
282
149
  .ProseMirror .figure-block > figcaption .figure-label {
283
150
  display: initial !important;
284
151
  }