@quadrats/common 0.7.3 → 1.0.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 (91) hide show
  1. package/accordion/constants.d.ts +5 -0
  2. package/accordion/constants.js +10 -0
  3. package/accordion/createAccordion.d.ts +6 -0
  4. package/accordion/createAccordion.js +62 -0
  5. package/accordion/index.cjs.js +76 -0
  6. package/accordion/index.d.ts +3 -0
  7. package/accordion/index.js +2 -0
  8. package/accordion/package.json +7 -0
  9. package/accordion/typings.d.ts +18 -0
  10. package/align/constants.d.ts +1 -0
  11. package/align/constants.js +3 -0
  12. package/align/createAlign.d.ts +9 -0
  13. package/align/createAlign.js +41 -0
  14. package/align/index.cjs.js +45 -0
  15. package/align/index.d.ts +3 -0
  16. package/align/index.js +2 -0
  17. package/align/package.json +7 -0
  18. package/align/typings.d.ts +1 -0
  19. package/blockquote/createBlockquote.js +1 -1
  20. package/bold/createBold.d.ts +1 -1
  21. package/card/constants.d.ts +6 -0
  22. package/card/constants.js +11 -0
  23. package/card/createCard.d.ts +15 -0
  24. package/card/createCard.js +147 -0
  25. package/card/getFilesFromInput.d.ts +4 -0
  26. package/card/index.cjs.js +163 -0
  27. package/card/index.d.ts +3 -0
  28. package/card/index.js +2 -0
  29. package/card/package.json +7 -0
  30. package/card/typings.d.ts +73 -0
  31. package/carousel/_virtual/_tslib.js +33 -0
  32. package/carousel/constants.d.ts +6 -0
  33. package/carousel/constants.js +11 -0
  34. package/carousel/createCarousel.d.ts +16 -0
  35. package/carousel/createCarousel.js +127 -0
  36. package/carousel/getFilesFromInput.d.ts +4 -0
  37. package/carousel/getFilesFromInput.js +30 -0
  38. package/carousel/index.cjs.js +202 -0
  39. package/carousel/index.d.ts +3 -0
  40. package/carousel/index.js +2 -0
  41. package/carousel/package.json +7 -0
  42. package/carousel/typings.d.ts +58 -0
  43. package/embed/constants.d.ts +1 -0
  44. package/embed/constants.js +2 -1
  45. package/embed/createEmbed.js +27 -4
  46. package/embed/index.cjs.js +32 -9
  47. package/embed/index.js +1 -1
  48. package/embed/serializeEmbedCode.d.ts +1 -1
  49. package/embed/serializeEmbedCode.js +5 -7
  50. package/embed/strategies/podcast-apple/index.cjs.js +1 -1
  51. package/embed/strategies/podcast-apple/index.js +1 -1
  52. package/embed/strategies/twitter/index.cjs.js +1 -1
  53. package/embed/strategies/twitter/index.js +1 -1
  54. package/embed/typings.d.ts +16 -1
  55. package/file-uploader/constants.d.ts +1 -0
  56. package/file-uploader/constants.js +2 -1
  57. package/file-uploader/createFileUploader.d.ts +3 -1
  58. package/file-uploader/createFileUploader.js +85 -63
  59. package/file-uploader/getFilesFromInput.js +3 -0
  60. package/file-uploader/index.cjs.js +89 -60
  61. package/file-uploader/index.d.ts +1 -1
  62. package/file-uploader/index.js +2 -2
  63. package/file-uploader/typings.d.ts +8 -2
  64. package/footnote/createFootnote.js +1 -1
  65. package/heading/constants.d.ts +1 -1
  66. package/heading/createHeading.js +2 -2
  67. package/heading/typings.d.ts +1 -0
  68. package/highlight/createHighlight.d.ts +1 -1
  69. package/image/createImage.js +13 -12
  70. package/image/getImageFigureElementCommonProps.d.ts +2 -0
  71. package/image/getImageFigureElementCommonProps.js +28 -2
  72. package/image/index.cjs.js +40 -13
  73. package/image/typings.d.ts +2 -0
  74. package/input-block/createInputBlock.js +1 -1
  75. package/italic/createItalic.d.ts +1 -1
  76. package/link/createLink.js +1 -1
  77. package/list/createList.d.ts +1 -0
  78. package/list/createList.js +4 -1
  79. package/list/index.cjs.js +3 -0
  80. package/list/typings.d.ts +1 -0
  81. package/package.json +4 -4
  82. package/paragraph/createParagraph.d.ts +2 -0
  83. package/paragraph/createParagraph.js +24 -0
  84. package/paragraph/index.cjs.js +26 -0
  85. package/paragraph/index.d.ts +2 -0
  86. package/paragraph/index.js +1 -0
  87. package/paragraph/package.json +7 -0
  88. package/paragraph/typings.d.ts +9 -0
  89. package/read-more/createReadMore.js +1 -1
  90. package/strikethrough/createStrikethrough.d.ts +1 -1
  91. package/underline/createUnderline.d.ts +1 -1
@@ -1,93 +1,115 @@
1
1
  import { __awaiter } from './_virtual/_tslib.js';
2
2
  import { readFileAsDataURL } from '@quadrats/utils';
3
- import { HistoryEditor, Transforms, isAboveBlockEmpty, createParagraphElement } from '@quadrats/core';
4
- import { FILE_UPLOADER_TYPE } from './constants.js';
3
+ import { isAboveBlockEmpty, Transforms, createParagraphElement, Element, Editor, HistoryEditor } from '@quadrats/core';
4
+ import { FILE_UPLOADER_TYPE, FILE_UPLOADER_PLACEHOLDER_TYPE } from './constants.js';
5
5
  import { getFilesFromInput } from './getFilesFromInput.js';
6
6
 
7
- function createFileUploader(options = {}) {
8
- const { type = FILE_UPLOADER_TYPE } = options;
9
- const createFileUploaderElement = (editor, file, options) => __awaiter(this, void 0, void 0, function* () {
10
- const { createElement, getBody, getHeaders, getUrl, uploader, } = options;
11
- const [mime] = file.type.split('/');
12
- const createByMime = createElement[mime];
13
- if (!createByMime) {
14
- return;
15
- }
16
- const { dataURL: createElementByDataURL, response: createElementByResponse } = createByMime;
17
- const headers = yield (getHeaders === null || getHeaders === void 0 ? void 0 : getHeaders(file));
18
- const xhr = uploader || new XMLHttpRequest();
19
- const dataURL = yield readFileAsDataURL(file);
20
- let sent = false;
21
- const fileUploaderElement = {
22
- type,
23
- register: (getPath, onProgress) => {
24
- xhr.onload = () => {
25
- if (xhr.status < 400) {
26
- const path = getPath();
27
- if (path) {
28
- HistoryEditor.withoutSaving(editor, () => {
29
- Transforms.removeNodes(editor, { at: path });
30
- Transforms.insertNodes(editor, createElementByResponse(xhr.response), { at: path });
31
- });
32
- }
33
- }
34
- else {
35
- throw xhr.response;
7
+ const createFileUploaderElementByType = type => (editor, file, options) => __awaiter(void 0, void 0, void 0, function* () {
8
+ const { createElement, getBody, getHeaders, getUrl, uploader, } = options;
9
+ const [mime] = file.type.split('/');
10
+ const createByMime = createElement[mime];
11
+ if (!createByMime) {
12
+ return;
13
+ }
14
+ const { dataURL: createElementByDataURL, response: createElementByResponse } = createByMime;
15
+ const headers = yield (getHeaders === null || getHeaders === void 0 ? void 0 : getHeaders(file));
16
+ const xhr = uploader || new XMLHttpRequest();
17
+ const dataURL = yield readFileAsDataURL(file);
18
+ let sent = false;
19
+ const fileUploaderElement = {
20
+ type,
21
+ register: (getPath, onProgress) => {
22
+ xhr.onload = () => {
23
+ if (xhr.status < 400) {
24
+ const path = getPath();
25
+ if (path) {
26
+ HistoryEditor.withoutSaving(editor, () => {
27
+ Transforms.removeNodes(editor, { at: path });
28
+ Transforms.insertNodes(editor, createElementByResponse(xhr.response), { at: path });
29
+ });
36
30
  }
37
- };
38
- xhr.upload.onprogress = ({ loaded, total }) => onProgress((loaded * 100) / total);
39
- if (!sent) {
40
- sent = true;
41
- xhr.send(getBody(file));
42
31
  }
43
- return () => {
44
- xhr.onload = null;
45
- xhr.upload.onprogress = null;
46
- };
47
- },
48
- children: [createElementByDataURL(dataURL)],
49
- };
50
- xhr.open('POST', getUrl(file));
51
- if (headers) {
52
- for (const headerName in headers) {
53
- xhr.setRequestHeader(headerName, headers[headerName]);
32
+ else {
33
+ throw xhr.response;
34
+ }
35
+ };
36
+ xhr.upload.onprogress = ({ loaded, total }) => onProgress((loaded * 100) / total);
37
+ if (!sent) {
38
+ sent = true;
39
+ xhr.send(getBody(file));
54
40
  }
41
+ return () => {
42
+ xhr.onload = null;
43
+ xhr.upload.onprogress = null;
44
+ };
45
+ },
46
+ children: [createElementByDataURL(dataURL)],
47
+ };
48
+ xhr.open('POST', getUrl(file));
49
+ if (headers) {
50
+ for (const headerName in headers) {
51
+ xhr.setRequestHeader(headerName, headers[headerName]);
55
52
  }
56
- return fileUploaderElement;
57
- });
53
+ }
54
+ return fileUploaderElement;
55
+ });
56
+ function insertFileUploaderElement(editor, fileUploaderElement) {
57
+ var _a, _b, _c;
58
+ if (fileUploaderElement) {
59
+ // Clear empty node
60
+ if (isAboveBlockEmpty(editor)) {
61
+ Transforms.removeNodes(editor, {
62
+ at: (_a = editor.selection) === null || _a === void 0 ? void 0 : _a.anchor,
63
+ });
64
+ }
65
+ Transforms.insertNodes(editor, [fileUploaderElement, createParagraphElement()], {
66
+ at: ((_b = editor.selection) === null || _b === void 0 ? void 0 : _b.anchor.path.length) ? [((_c = editor.selection) === null || _c === void 0 ? void 0 : _c.anchor.path[0]) + 1] : undefined,
67
+ });
68
+ Transforms.move(editor);
69
+ }
70
+ }
71
+ function createFileUploader(options = {}) {
72
+ const { type = FILE_UPLOADER_TYPE } = options;
73
+ const createFileUploaderElement = createFileUploaderElementByType(type);
74
+ const removeUploaderPlaceholder = (editor) => {
75
+ Transforms.removeNodes(editor, {
76
+ match: node => Element.isElement(node) && node.type === FILE_UPLOADER_PLACEHOLDER_TYPE,
77
+ });
78
+ };
58
79
  const upload = (editor, options) => __awaiter(this, void 0, void 0, function* () {
59
80
  const { accept, multiple } = options;
60
81
  const files = yield getFilesFromInput({ accept, multiple });
61
82
  if (!files) {
83
+ removeUploaderPlaceholder(editor);
62
84
  return;
63
85
  }
86
+ removeUploaderPlaceholder(editor);
64
87
  files.reduce((prev, file) => __awaiter(this, void 0, void 0, function* () {
65
88
  yield prev;
66
89
  return createFileUploaderElement(editor, file, options).then((fileUploaderElement) => {
67
- var _a, _b, _c;
68
- if (fileUploaderElement) {
69
- // Clear empty node
70
- if (isAboveBlockEmpty(editor)) {
71
- Transforms.removeNodes(editor, {
72
- at: (_a = editor.selection) === null || _a === void 0 ? void 0 : _a.anchor,
73
- });
74
- }
75
- Transforms.insertNodes(editor, [fileUploaderElement, createParagraphElement()], {
76
- at: ((_b = editor.selection) === null || _b === void 0 ? void 0 : _b.anchor.path.length) ? [((_c = editor.selection) === null || _c === void 0 ? void 0 : _c.anchor.path[0]) + 1] : undefined,
77
- });
78
- Transforms.move(editor);
79
- }
90
+ insertFileUploaderElement(editor, fileUploaderElement);
80
91
  });
81
92
  }), Promise.resolve());
82
93
  });
94
+ const insertUploaderPlaceholder = (editor) => {
95
+ const uploaderPlaceholderElement = {
96
+ type: FILE_UPLOADER_PLACEHOLDER_TYPE,
97
+ children: [{ text: '' }],
98
+ };
99
+ Editor.withoutNormalizing(editor, () => {
100
+ Transforms.insertNodes(editor, uploaderPlaceholderElement);
101
+ });
102
+ };
83
103
  return {
84
104
  type,
85
105
  createFileUploaderElement,
86
106
  upload,
107
+ insertUploaderPlaceholder,
108
+ removeUploaderPlaceholder,
87
109
  with(editor) {
88
110
  return editor;
89
111
  },
90
112
  };
91
113
  }
92
114
 
93
- export { createFileUploader };
115
+ export { createFileUploader, createFileUploaderElementByType, insertFileUploaderElement };
@@ -7,6 +7,9 @@ function getFilesFromInput(options = {}) {
7
7
  }
8
8
  inputEl.multiple = !!multiple;
9
9
  inputEl.type = 'file';
10
+ inputEl.addEventListener('cancel', () => {
11
+ resolve(undefined);
12
+ });
10
13
  inputEl.addEventListener('change', () => {
11
14
  const { files: fileList } = inputEl;
12
15
  if (!fileList || !fileList.length) {
@@ -4,6 +4,7 @@ var utils = require('@quadrats/utils');
4
4
  var core = require('@quadrats/core');
5
5
 
6
6
  const FILE_UPLOADER_TYPE = 'file_uploader';
7
+ const FILE_UPLOADER_PLACEHOLDER_TYPE = 'file_uploader_placeholder';
7
8
 
8
9
  function getFilesFromInput(options = {}) {
9
10
  const { accept, multiple } = options;
@@ -14,6 +15,9 @@ function getFilesFromInput(options = {}) {
14
15
  }
15
16
  inputEl.multiple = !!multiple;
16
17
  inputEl.type = 'file';
18
+ inputEl.addEventListener('cancel', () => {
19
+ resolve(undefined);
20
+ });
17
21
  inputEl.addEventListener('change', () => {
18
22
  const { files: fileList } = inputEl;
19
23
  if (!fileList || !fileList.length) {
@@ -63,92 +67,117 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
63
67
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
64
68
  };
65
69
 
66
- function createFileUploader(options = {}) {
67
- const { type = FILE_UPLOADER_TYPE } = options;
68
- const createFileUploaderElement = (editor, file, options) => __awaiter(this, void 0, void 0, function* () {
69
- const { createElement, getBody, getHeaders, getUrl, uploader, } = options;
70
- const [mime] = file.type.split('/');
71
- const createByMime = createElement[mime];
72
- if (!createByMime) {
73
- return;
74
- }
75
- const { dataURL: createElementByDataURL, response: createElementByResponse } = createByMime;
76
- const headers = yield (getHeaders === null || getHeaders === void 0 ? void 0 : getHeaders(file));
77
- const xhr = uploader || new XMLHttpRequest();
78
- const dataURL = yield utils.readFileAsDataURL(file);
79
- let sent = false;
80
- const fileUploaderElement = {
81
- type,
82
- register: (getPath, onProgress) => {
83
- xhr.onload = () => {
84
- if (xhr.status < 400) {
85
- const path = getPath();
86
- if (path) {
87
- core.HistoryEditor.withoutSaving(editor, () => {
88
- core.Transforms.removeNodes(editor, { at: path });
89
- core.Transforms.insertNodes(editor, createElementByResponse(xhr.response), { at: path });
90
- });
91
- }
92
- }
93
- else {
94
- throw xhr.response;
70
+ const createFileUploaderElementByType = type => (editor, file, options) => __awaiter(void 0, void 0, void 0, function* () {
71
+ const { createElement, getBody, getHeaders, getUrl, uploader, } = options;
72
+ const [mime] = file.type.split('/');
73
+ const createByMime = createElement[mime];
74
+ if (!createByMime) {
75
+ return;
76
+ }
77
+ const { dataURL: createElementByDataURL, response: createElementByResponse } = createByMime;
78
+ const headers = yield (getHeaders === null || getHeaders === void 0 ? void 0 : getHeaders(file));
79
+ const xhr = uploader || new XMLHttpRequest();
80
+ const dataURL = yield utils.readFileAsDataURL(file);
81
+ let sent = false;
82
+ const fileUploaderElement = {
83
+ type,
84
+ register: (getPath, onProgress) => {
85
+ xhr.onload = () => {
86
+ if (xhr.status < 400) {
87
+ const path = getPath();
88
+ if (path) {
89
+ core.HistoryEditor.withoutSaving(editor, () => {
90
+ core.Transforms.removeNodes(editor, { at: path });
91
+ core.Transforms.insertNodes(editor, createElementByResponse(xhr.response), { at: path });
92
+ });
95
93
  }
96
- };
97
- xhr.upload.onprogress = ({ loaded, total }) => onProgress((loaded * 100) / total);
98
- if (!sent) {
99
- sent = true;
100
- xhr.send(getBody(file));
101
94
  }
102
- return () => {
103
- xhr.onload = null;
104
- xhr.upload.onprogress = null;
105
- };
106
- },
107
- children: [createElementByDataURL(dataURL)],
108
- };
109
- xhr.open('POST', getUrl(file));
110
- if (headers) {
111
- for (const headerName in headers) {
112
- xhr.setRequestHeader(headerName, headers[headerName]);
95
+ else {
96
+ throw xhr.response;
97
+ }
98
+ };
99
+ xhr.upload.onprogress = ({ loaded, total }) => onProgress((loaded * 100) / total);
100
+ if (!sent) {
101
+ sent = true;
102
+ xhr.send(getBody(file));
113
103
  }
104
+ return () => {
105
+ xhr.onload = null;
106
+ xhr.upload.onprogress = null;
107
+ };
108
+ },
109
+ children: [createElementByDataURL(dataURL)],
110
+ };
111
+ xhr.open('POST', getUrl(file));
112
+ if (headers) {
113
+ for (const headerName in headers) {
114
+ xhr.setRequestHeader(headerName, headers[headerName]);
114
115
  }
115
- return fileUploaderElement;
116
- });
116
+ }
117
+ return fileUploaderElement;
118
+ });
119
+ function insertFileUploaderElement(editor, fileUploaderElement) {
120
+ var _a, _b, _c;
121
+ if (fileUploaderElement) {
122
+ // Clear empty node
123
+ if (core.isAboveBlockEmpty(editor)) {
124
+ core.Transforms.removeNodes(editor, {
125
+ at: (_a = editor.selection) === null || _a === void 0 ? void 0 : _a.anchor,
126
+ });
127
+ }
128
+ core.Transforms.insertNodes(editor, [fileUploaderElement, core.createParagraphElement()], {
129
+ at: ((_b = editor.selection) === null || _b === void 0 ? void 0 : _b.anchor.path.length) ? [((_c = editor.selection) === null || _c === void 0 ? void 0 : _c.anchor.path[0]) + 1] : undefined,
130
+ });
131
+ core.Transforms.move(editor);
132
+ }
133
+ }
134
+ function createFileUploader(options = {}) {
135
+ const { type = FILE_UPLOADER_TYPE } = options;
136
+ const createFileUploaderElement = createFileUploaderElementByType(type);
137
+ const removeUploaderPlaceholder = (editor) => {
138
+ core.Transforms.removeNodes(editor, {
139
+ match: node => core.Element.isElement(node) && node.type === FILE_UPLOADER_PLACEHOLDER_TYPE,
140
+ });
141
+ };
117
142
  const upload = (editor, options) => __awaiter(this, void 0, void 0, function* () {
118
143
  const { accept, multiple } = options;
119
144
  const files = yield getFilesFromInput({ accept, multiple });
120
145
  if (!files) {
146
+ removeUploaderPlaceholder(editor);
121
147
  return;
122
148
  }
149
+ removeUploaderPlaceholder(editor);
123
150
  files.reduce((prev, file) => __awaiter(this, void 0, void 0, function* () {
124
151
  yield prev;
125
152
  return createFileUploaderElement(editor, file, options).then((fileUploaderElement) => {
126
- var _a, _b, _c;
127
- if (fileUploaderElement) {
128
- // Clear empty node
129
- if (core.isAboveBlockEmpty(editor)) {
130
- core.Transforms.removeNodes(editor, {
131
- at: (_a = editor.selection) === null || _a === void 0 ? void 0 : _a.anchor,
132
- });
133
- }
134
- core.Transforms.insertNodes(editor, [fileUploaderElement, core.createParagraphElement()], {
135
- at: ((_b = editor.selection) === null || _b === void 0 ? void 0 : _b.anchor.path.length) ? [((_c = editor.selection) === null || _c === void 0 ? void 0 : _c.anchor.path[0]) + 1] : undefined,
136
- });
137
- core.Transforms.move(editor);
138
- }
153
+ insertFileUploaderElement(editor, fileUploaderElement);
139
154
  });
140
155
  }), Promise.resolve());
141
156
  });
157
+ const insertUploaderPlaceholder = (editor) => {
158
+ const uploaderPlaceholderElement = {
159
+ type: FILE_UPLOADER_PLACEHOLDER_TYPE,
160
+ children: [{ text: '' }],
161
+ };
162
+ core.Editor.withoutNormalizing(editor, () => {
163
+ core.Transforms.insertNodes(editor, uploaderPlaceholderElement);
164
+ });
165
+ };
142
166
  return {
143
167
  type,
144
168
  createFileUploaderElement,
145
169
  upload,
170
+ insertUploaderPlaceholder,
171
+ removeUploaderPlaceholder,
146
172
  with(editor) {
147
173
  return editor;
148
174
  },
149
175
  };
150
176
  }
151
177
 
178
+ exports.FILE_UPLOADER_PLACEHOLDER_TYPE = FILE_UPLOADER_PLACEHOLDER_TYPE;
152
179
  exports.FILE_UPLOADER_TYPE = FILE_UPLOADER_TYPE;
153
180
  exports.createFileUploader = createFileUploader;
181
+ exports.createFileUploaderElementByType = createFileUploaderElementByType;
154
182
  exports.getFilesFromInput = getFilesFromInput;
183
+ exports.insertFileUploaderElement = insertFileUploaderElement;
@@ -1,4 +1,4 @@
1
1
  export * from './typings';
2
2
  export * from './constants';
3
3
  export { GetFilesFromInputOptions, getFilesFromInput } from './getFilesFromInput';
4
- export { CreateFileUploaderOptions, createFileUploader } from './createFileUploader';
4
+ export { CreateFileUploaderOptions, createFileUploaderElementByType, insertFileUploaderElement, createFileUploader, } from './createFileUploader';
@@ -1,3 +1,3 @@
1
- export { FILE_UPLOADER_TYPE } from './constants.js';
1
+ export { FILE_UPLOADER_PLACEHOLDER_TYPE, FILE_UPLOADER_TYPE } from './constants.js';
2
2
  export { getFilesFromInput } from './getFilesFromInput.js';
3
- export { createFileUploader } from './createFileUploader.js';
3
+ export { createFileUploader, createFileUploaderElementByType, insertFileUploaderElement } from './createFileUploader.js';
@@ -1,5 +1,6 @@
1
- import { Editor, QuadratsElement, Path, TransformsInsertNodesOptions, Withable } from '@quadrats/core';
1
+ import { Editor, QuadratsElement, Path, TransformsInsertNodesOptions, Withable, WithElementType, Text } from '@quadrats/core';
2
2
  import { GetFilesFromInputOptions } from './getFilesFromInput';
3
+ export type ImageAccept = 'image/jpeg' | 'image/jpg' | 'image/png';
3
4
  export interface XHRUploadHeaders {
4
5
  [name: string]: string;
5
6
  }
@@ -25,7 +26,7 @@ interface FileUploaderUploadImplementOnProgressArgs {
25
26
  interface FileUploaderUploadImplement {
26
27
  onprogress: ((options: FileUploaderUploadImplementOnProgressArgs) => void) | null;
27
28
  }
28
- interface FileUploaderImplement {
29
+ export interface FileUploaderImplement {
29
30
  onload: (() => void) | null;
30
31
  open: (method: string, url: string | URL) => void;
31
32
  setRequestHeader: (key: string, value: string) => void;
@@ -34,6 +35,9 @@ interface FileUploaderImplement {
34
35
  readonly response: any;
35
36
  readonly upload: FileUploaderUploadImplement;
36
37
  }
38
+ export interface UploaderPlaceholderElement extends QuadratsElement, WithElementType {
39
+ children: [Text];
40
+ }
37
41
  export interface FileUploaderCreateFileUploaderElementOptions {
38
42
  createElement: {
39
43
  [mime in string]?: {
@@ -51,5 +55,7 @@ export interface FileUploader<T extends Editor = Editor> extends Withable {
51
55
  type: string;
52
56
  createFileUploaderElement(editor: T, file: File, options: FileUploaderCreateFileUploaderElementOptions): Promise<FileUploaderElement | undefined>;
53
57
  upload(editor: T, options: FileUploaderUploadOptions): Promise<void>;
58
+ insertUploaderPlaceholder(editor: T): void;
59
+ removeUploaderPlaceholder(editor: T): void;
54
60
  }
55
61
  export {};
@@ -1,4 +1,4 @@
1
- import { isNodesTypeIn, getNodes, Transforms, unwrapNodesByTypes, wrapNodesWithUnhangRange } from '@quadrats/core';
1
+ import { isNodesTypeIn, Transforms, wrapNodesWithUnhangRange, unwrapNodesByTypes, getNodes } from '@quadrats/core';
2
2
  import { FOOTNOTE_TYPE } from './constants.js';
3
3
 
4
4
  /* eslint-disable max-len */
@@ -1,3 +1,3 @@
1
1
  import { HeadingLevel } from './typings';
2
2
  export declare const HEADING_TYPE = "heading";
3
- export declare const HEADING_LEVELS: readonly HeadingLevel[];
3
+ export declare const HEADING_LEVELS: ReadonlyArray<HeadingLevel>;
@@ -1,5 +1,5 @@
1
- import { Element, Transforms, PARAGRAPH_TYPE, normalizeOnlyInlineOrTextInChildren, getNodes } from '@quadrats/core';
2
- import { HEADING_TYPE, HEADING_LEVELS } from './constants.js';
1
+ import { PARAGRAPH_TYPE, getNodes, Element, Transforms, normalizeOnlyInlineOrTextInChildren } from '@quadrats/core';
2
+ import { HEADING_LEVELS, HEADING_TYPE } from './constants.js';
3
3
 
4
4
  function createHeading({ type = HEADING_TYPE, enabledLevels = HEADING_LEVELS, } = {}) {
5
5
  const getHeadingNodes = (editor, level, options = {}) => getNodes(editor, Object.assign(Object.assign({}, options), { match: node => node.type === type && node.level === level }));
@@ -2,6 +2,7 @@ import { Editor, QuadratsElement, GetNodesOptions, Node, NodeEntry, Withable, Wi
2
2
  export type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
3
3
  export interface HeadingElement extends QuadratsElement, WithElementType {
4
4
  level: HeadingLevel;
5
+ align?: 'left' | 'center' | 'right';
5
6
  }
6
7
  export interface WithEnabledHeadingLevels<L extends HeadingLevel> {
7
8
  /**
@@ -1,2 +1,2 @@
1
1
  import { Editor } from '@quadrats/core';
2
- export declare function createHighlight<E extends Editor = Editor>(variant?: string): ({ type, variant }?: import("@quadrats/common/toggle-mark").CreateToggleMarkOptions | undefined) => import("@quadrats/common/toggle-mark").ToggleMark<E>;
2
+ export declare function createHighlight<E extends Editor = Editor>(variant?: string): ({ type, variant }?: import("@quadrats/common/toggle-mark").CreateToggleMarkOptions) => import("@quadrats/common/toggle-mark").ToggleMark<E>;
@@ -1,9 +1,9 @@
1
1
  import { isImageUrl } from '@quadrats/utils';
2
- import { Editor, Transforms, createParagraphElement, Element, normalizeVoidElementChildren, normalizeOnlyInlineOrTextInChildren, getAboveByTypes, isNodesTypeIn, Range } from '@quadrats/core';
2
+ import { Range, isNodesTypeIn, getAboveByTypes, Editor, Transforms, createParagraphElement, Element, normalizeVoidElementChildren, normalizeOnlyInlineOrTextInChildren } from '@quadrats/core';
3
3
  import { IMAGE_TYPES } from './constants.js';
4
4
 
5
5
  function resolveSizeSteps(steps) {
6
- let sortedSteps = steps.filter(step => step > 0 && step < 100).sort();
6
+ let sortedSteps = steps.filter((step) => step > 0 && step < 100).sort();
7
7
  if (!sortedSteps.includes(100)) {
8
8
  sortedSteps = [...sortedSteps, 100];
9
9
  }
@@ -16,12 +16,13 @@ function createImage(options = {}) {
16
16
  const getAboveImageFigure = (editor, options) => getAboveByTypes(editor, [types.figure], options);
17
17
  const getAboveImageCaption = (editor, options) => getAboveByTypes(editor, [types.caption], options);
18
18
  const isNodesInImage = (editor, options) => isNodesTypeIn(editor, [types.image], options);
19
- const isSelectionInImage = editor => isNodesInImage(editor);
20
- const isSelectionInImageCaption = editor => isNodesTypeIn(editor, [types.caption]);
21
- const isCollapsedOnImage = editor => !!editor.selection && Range.isCollapsed(editor.selection) && isSelectionInImage(editor);
19
+ const isSelectionInImage = (editor) => isNodesInImage(editor);
20
+ const isSelectionInImageCaption = (editor) => isNodesTypeIn(editor, [types.caption]);
21
+ const isCollapsedOnImage = (editor) => !!editor.selection && Range.isCollapsed(editor.selection) && isSelectionInImage(editor);
22
22
  const createImageElement = (src, hosting) => {
23
23
  const imageElement = {
24
24
  type: types.image,
25
+ figureType: types.figure,
25
26
  src,
26
27
  hosting,
27
28
  children: [{ text: '' }],
@@ -51,7 +52,7 @@ function createImage(options = {}) {
51
52
  if (!sizeSteps) {
52
53
  return percentage;
53
54
  }
54
- const lowerIndex = sizeSteps.findIndex(step => step >= percentage) - 1;
55
+ const lowerIndex = sizeSteps.findIndex((step) => step >= percentage) - 1;
55
56
  const upperIndex = lowerIndex + 1;
56
57
  if (lowerIndex < 0) {
57
58
  return sizeSteps[0];
@@ -89,7 +90,7 @@ function createImage(options = {}) {
89
90
  insertImage,
90
91
  resizeImage,
91
92
  with(editor) {
92
- const { deleteBackward, deleteForward, insertBreak, isVoid, normalizeNode, } = editor;
93
+ const { deleteBackward, deleteForward, insertBreak, isVoid, normalizeNode } = editor;
93
94
  const deleteCollapsed = (origin, isEdgeMethodName) => {
94
95
  const { selection } = editor;
95
96
  /**
@@ -97,7 +98,7 @@ function createImage(options = {}) {
97
98
  */
98
99
  if (selection && Range.isCollapsed(selection)) {
99
100
  const [, captionPath] = getAboveImageCaption(editor) || [];
100
- if ((captionPath && Editor[isEdgeMethodName](editor, selection.focus, captionPath))) {
101
+ if (captionPath && Editor[isEdgeMethodName](editor, selection.focus, captionPath)) {
101
102
  return;
102
103
  }
103
104
  }
@@ -128,7 +129,7 @@ function createImage(options = {}) {
128
129
  }
129
130
  insertBreak();
130
131
  };
131
- editor.isVoid = element => element.type === types.image || isVoid(element);
132
+ editor.isVoid = (element) => element.type === types.image || isVoid(element);
132
133
  editor.normalizeNode = (entry) => {
133
134
  const [node, path] = entry;
134
135
  if (Element.isElement(node)) {
@@ -140,9 +141,9 @@ function createImage(options = {}) {
140
141
  }
141
142
  else if (node.type === types.image) {
142
143
  const { src, width, hosting } = node;
143
- if (typeof src !== 'string'
144
- || !(width == null || typeof width === 'number')
145
- || !(hosting == null || typeof hosting === 'string')) {
144
+ if (typeof src !== 'string' ||
145
+ !(width == null || typeof width === 'number') ||
146
+ !(hosting == null || typeof hosting === 'string')) {
146
147
  const [, figurePath] = getAboveImageFigure(editor, { at: path }) || [];
147
148
  if (figurePath) {
148
149
  Transforms.removeNodes(editor, { at: figurePath });
@@ -1,6 +1,8 @@
1
1
  import { ImageFigureElement } from './typings';
2
2
  export declare function getImageFigureElementCommonProps(element: ImageFigureElement): {
3
3
  style?: {
4
+ '--qdr-image-align': 'flex-start' | 'center' | 'flex-end';
5
+ '--qdr-image-caption-align': 'left' | 'center' | 'right';
4
6
  width: string;
5
7
  };
6
8
  };
@@ -1,7 +1,33 @@
1
1
  function getImageFigureElementCommonProps(element) {
2
- const { width } = element;
2
+ const { width, align } = element;
3
3
  return {
4
- style: typeof width === 'number' ? { width: `${width}%` } : undefined,
4
+ style: {
5
+ width: typeof width === 'number' ? `${width}%` : 'unset',
6
+ '--qdr-image-align': (() => {
7
+ switch (align) {
8
+ case 'start':
9
+ return 'flex-start';
10
+ case 'center':
11
+ return 'center';
12
+ case 'end':
13
+ return 'flex-end';
14
+ default:
15
+ return 'flex-start';
16
+ }
17
+ })(),
18
+ '--qdr-image-caption-align': (() => {
19
+ switch (align) {
20
+ case 'start':
21
+ return 'left';
22
+ case 'center':
23
+ return 'center';
24
+ case 'end':
25
+ return 'right';
26
+ default:
27
+ return 'left';
28
+ }
29
+ })(),
30
+ },
5
31
  };
6
32
  }
7
33