@limetech/lime-elements 38.2.3 → 38.3.1
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.
- package/CHANGELOG.md +18 -0
- package/dist/cjs/files-c08d24d4.js +44 -0
- package/dist/cjs/files-c08d24d4.js.map +1 -0
- package/dist/cjs/index.cjs.js +9 -0
- package/dist/cjs/index.cjs.js.map +1 -1
- package/dist/cjs/limel-action-bar_2.cjs.entry.js +1 -1
- package/dist/cjs/limel-callout.cjs.entry.js +1 -1
- package/dist/cjs/limel-chart.cjs.entry.js +1 -1
- package/dist/cjs/limel-chip_2.cjs.entry.js +1 -1
- package/dist/cjs/limel-file-dropzone_2.cjs.entry.js +8 -43
- package/dist/cjs/limel-file-dropzone_2.cjs.entry.js.map +1 -1
- package/dist/cjs/limel-file-viewer.cjs.entry.js +1 -1
- package/dist/cjs/limel-file.cjs.entry.js +1 -1
- package/dist/cjs/limel-flatpickr-adapter.cjs.entry.js +1 -1
- package/dist/cjs/limel-linear-progress.cjs.entry.js +1 -1
- package/dist/cjs/limel-prosemirror-adapter.cjs.entry.js +404 -19
- package/dist/cjs/limel-prosemirror-adapter.cjs.entry.js.map +1 -1
- package/dist/cjs/limel-snackbar.cjs.entry.js +1 -1
- package/dist/cjs/limel-text-editor.cjs.entry.js +11 -1
- package/dist/cjs/limel-text-editor.cjs.entry.js.map +1 -1
- package/dist/cjs/text-editor.types-5e5567e2.js +13 -0
- package/dist/cjs/text-editor.types-5e5567e2.js.map +1 -0
- package/dist/cjs/{translations-0d53f9bc.js → translations-b5da5dcd.js} +55 -4
- package/dist/cjs/translations-b5da5dcd.js.map +1 -0
- package/dist/collection/components/text-editor/prosemirror-adapter/plugins/image/inserter.js +195 -0
- package/dist/collection/components/text-editor/prosemirror-adapter/plugins/image/inserter.js.map +1 -0
- package/dist/collection/components/text-editor/prosemirror-adapter/plugins/image/node.js +128 -0
- package/dist/collection/components/text-editor/prosemirror-adapter/plugins/image/node.js.map +1 -0
- package/dist/collection/components/text-editor/prosemirror-adapter/plugins/image/view.js +139 -0
- package/dist/collection/components/text-editor/prosemirror-adapter/plugins/image/view.js.map +1 -0
- package/dist/collection/components/text-editor/prosemirror-adapter/prosemirror-adapter.css +187 -0
- package/dist/collection/components/text-editor/prosemirror-adapter/prosemirror-adapter.js +60 -3
- package/dist/collection/components/text-editor/prosemirror-adapter/prosemirror-adapter.js.map +1 -1
- package/dist/collection/components/text-editor/text-editor.js +63 -1
- package/dist/collection/components/text-editor/text-editor.js.map +1 -1
- package/dist/collection/components/text-editor/text-editor.types.js +9 -1
- package/dist/collection/components/text-editor/text-editor.types.js.map +1 -1
- package/dist/collection/components/text-editor/utils/html-converter.js +7 -4
- package/dist/collection/components/text-editor/utils/html-converter.js.map +1 -1
- package/dist/collection/components/text-editor/utils/markdown-converter.js +8 -8
- package/dist/collection/components/text-editor/utils/markdown-converter.js.map +1 -1
- package/dist/collection/global/translations.js +9 -2
- package/dist/collection/global/translations.js.map +1 -1
- package/dist/collection/translations/da.js +6 -0
- package/dist/collection/translations/da.js.map +1 -1
- package/dist/collection/translations/de.js +5 -0
- package/dist/collection/translations/de.js.map +1 -1
- package/dist/collection/translations/en.js +5 -0
- package/dist/collection/translations/en.js.map +1 -1
- package/dist/collection/translations/fi.js +7 -1
- package/dist/collection/translations/fi.js.map +1 -1
- package/dist/collection/translations/fr.js +5 -0
- package/dist/collection/translations/fr.js.map +1 -1
- package/dist/collection/translations/nl.js +6 -0
- package/dist/collection/translations/nl.js.map +1 -1
- package/dist/collection/translations/no.js +6 -0
- package/dist/collection/translations/no.js.map +1 -1
- package/dist/collection/translations/sv.js +5 -0
- package/dist/collection/translations/sv.js.map +1 -1
- package/dist/esm/files-2be62a61.js +41 -0
- package/dist/esm/files-2be62a61.js.map +1 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/limel-action-bar_2.entry.js +1 -1
- package/dist/esm/limel-callout.entry.js +1 -1
- package/dist/esm/limel-chart.entry.js +1 -1
- package/dist/esm/limel-chip_2.entry.js +1 -1
- package/dist/esm/limel-file-dropzone_2.entry.js +2 -37
- package/dist/esm/limel-file-dropzone_2.entry.js.map +1 -1
- package/dist/esm/limel-file-viewer.entry.js +1 -1
- package/dist/esm/limel-file.entry.js +1 -1
- package/dist/esm/limel-flatpickr-adapter.entry.js +1 -1
- package/dist/esm/limel-linear-progress.entry.js +1 -1
- package/dist/esm/limel-prosemirror-adapter.entry.js +404 -19
- package/dist/esm/limel-prosemirror-adapter.entry.js.map +1 -1
- package/dist/esm/limel-snackbar.entry.js +1 -1
- package/dist/esm/limel-text-editor.entry.js +11 -1
- package/dist/esm/limel-text-editor.entry.js.map +1 -1
- package/dist/esm/text-editor.types-e82469d1.js +13 -0
- package/dist/esm/text-editor.types-e82469d1.js.map +1 -0
- package/dist/esm/{translations-7ad188e0.js → translations-8b7272f2.js} +55 -4
- package/dist/esm/translations-8b7272f2.js.map +1 -0
- package/dist/lime-elements/index.esm.js +1 -1
- package/dist/lime-elements/index.esm.js.map +1 -1
- package/dist/lime-elements/lime-elements.esm.js +1 -1
- package/dist/lime-elements/{p-fc7f9e93.entry.js → p-24a46d85.entry.js} +2 -2
- package/dist/lime-elements/{p-54b4a06b.entry.js → p-2ca8f253.entry.js} +2 -2
- package/dist/lime-elements/{p-0468e34c.entry.js → p-3479aa66.entry.js} +2 -2
- package/dist/lime-elements/{p-b78a9a5c.entry.js → p-54710fb8.entry.js} +2 -2
- package/dist/lime-elements/{p-180675a5.entry.js → p-5ac99c32.entry.js} +2 -2
- package/dist/lime-elements/{p-7fdab6b0.entry.js → p-62a21e92.entry.js} +2 -2
- package/dist/lime-elements/p-62a21e92.entry.js.map +1 -0
- package/dist/lime-elements/{p-28c6b698.entry.js → p-8c15a058.entry.js} +2 -2
- package/dist/lime-elements/p-9ca516ed.js +2 -0
- package/dist/lime-elements/p-9ca516ed.js.map +1 -0
- package/dist/lime-elements/{p-fefef194.entry.js → p-ae417884.entry.js} +2 -2
- package/dist/lime-elements/{p-ffe954d4.entry.js → p-bda61285.entry.js} +2 -2
- package/dist/lime-elements/{p-8ada443f.entry.js → p-c348740c.entry.js} +2 -2
- package/dist/lime-elements/p-dbcde7db.entry.js +2 -0
- package/dist/lime-elements/p-dbcde7db.entry.js.map +1 -0
- package/dist/lime-elements/p-dc3d2ee1.js +2 -0
- package/dist/lime-elements/p-dc3d2ee1.js.map +1 -0
- package/dist/lime-elements/p-e3d7aba7.js +2 -0
- package/dist/lime-elements/p-e3d7aba7.js.map +1 -0
- package/dist/lime-elements/p-f641bcb0.entry.js +2 -0
- package/dist/lime-elements/p-f641bcb0.entry.js.map +1 -0
- package/dist/types/components/text-editor/prosemirror-adapter/plugins/image/inserter.d.ts +15 -0
- package/dist/types/components/text-editor/prosemirror-adapter/plugins/image/node.d.ts +14 -0
- package/dist/types/components/text-editor/prosemirror-adapter/plugins/image/view.d.ts +4 -0
- package/dist/types/components/text-editor/prosemirror-adapter/prosemirror-adapter.d.ts +14 -0
- package/dist/types/components/text-editor/text-editor.d.ts +18 -0
- package/dist/types/components/text-editor/text-editor.types.d.ts +51 -0
- package/dist/types/components/text-editor/utils/markdown-converter.d.ts +2 -1
- package/dist/types/components.d.ts +34 -2
- package/dist/types/global/translations.d.ts +1 -1
- package/dist/types/translations/da.d.ts +6 -0
- package/dist/types/translations/de.d.ts +5 -0
- package/dist/types/translations/en.d.ts +5 -0
- package/dist/types/translations/fi.d.ts +7 -1
- package/dist/types/translations/fr.d.ts +5 -0
- package/dist/types/translations/nl.d.ts +6 -0
- package/dist/types/translations/no.d.ts +6 -0
- package/dist/types/translations/sv.d.ts +5 -0
- package/package.json +1 -1
- package/dist/cjs/translations-0d53f9bc.js.map +0 -1
- package/dist/collection/components/text-editor/prosemirror-adapter/plugins/image-remover-plugin.js +0 -78
- package/dist/collection/components/text-editor/prosemirror-adapter/plugins/image-remover-plugin.js.map +0 -1
- package/dist/esm/translations-7ad188e0.js.map +0 -1
- package/dist/lime-elements/p-7fdab6b0.entry.js.map +0 -1
- package/dist/lime-elements/p-ad9801f8.entry.js +0 -2
- package/dist/lime-elements/p-ad9801f8.entry.js.map +0 -1
- package/dist/lime-elements/p-e5545944.entry.js +0 -2
- package/dist/lime-elements/p-e5545944.entry.js.map +0 -1
- package/dist/lime-elements/p-efd753ba.js +0 -2
- package/dist/lime-elements/p-efd753ba.js.map +0 -1
- package/dist/types/components/text-editor/prosemirror-adapter/plugins/image-remover-plugin.d.ts +0 -4
- /package/dist/lime-elements/{p-fc7f9e93.entry.js.map → p-24a46d85.entry.js.map} +0 -0
- /package/dist/lime-elements/{p-54b4a06b.entry.js.map → p-2ca8f253.entry.js.map} +0 -0
- /package/dist/lime-elements/{p-0468e34c.entry.js.map → p-3479aa66.entry.js.map} +0 -0
- /package/dist/lime-elements/{p-b78a9a5c.entry.js.map → p-54710fb8.entry.js.map} +0 -0
- /package/dist/lime-elements/{p-180675a5.entry.js.map → p-5ac99c32.entry.js.map} +0 -0
- /package/dist/lime-elements/{p-28c6b698.entry.js.map → p-8c15a058.entry.js.map} +0 -0
- /package/dist/lime-elements/{p-fefef194.entry.js.map → p-ae417884.entry.js.map} +0 -0
- /package/dist/lime-elements/{p-ffe954d4.entry.js.map → p-bda61285.entry.js.map} +0 -0
- /package/dist/lime-elements/{p-8ada443f.entry.js.map → p-c348740c.entry.js.map} +0 -0
package/dist/collection/components/text-editor/prosemirror-adapter/plugins/image/inserter.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inserter.js","sourceRoot":"","sources":["../../../../../../src/components/text-editor/prosemirror-adapter/plugins/image/inserter.ts"],"names":[],"mappings":"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","sourcesContent":["import { Plugin, PluginKey, Transaction, StateField } from 'prosemirror-state';\nimport { EditorView } from 'prosemirror-view';\nimport { createFileInfo } from '../../../../../util/files';\nimport { FileInfo } from '../../../../../global/shared-types/file.types';\nimport {\n ImageInserter,\n ImageInfo,\n ImageState,\n} from '../../../text-editor.types';\nimport { Node, Slice, Fragment } from 'prosemirror-model';\nimport { imageCache } from './node';\n\nexport const pluginKey = new PluginKey('imageInserterPlugin');\n\ntype ImagePastedCallback = (data: ImageInserter) => CustomEvent<ImageInserter>;\n\ntype ImageRemovedCallback = (data: ImageInfo) => CustomEvent<ImageInfo>;\n\ntype PluginState = {\n insertedImages: Record<string, Node>;\n};\n\nexport const createImageInserterPlugin = (\n imagePastedCallback: ImagePastedCallback,\n imageRemovedCallback: ImageRemovedCallback,\n) => {\n return new Plugin({\n key: pluginKey,\n props: {\n handlePaste: (view, event, slice) => {\n return processPasteEvent(view, event, slice);\n },\n handleDOMEvents: {\n imagePasted: (_, event) => {\n imagePastedCallback(event.detail);\n },\n },\n },\n state: {\n init: (): PluginState => {\n return { insertedImages: {} };\n },\n apply: (tr, pluginState): PluginState => {\n const newState = { ...pluginState };\n\n newState.insertedImages = getImagesFromTransaction(tr);\n findAndHandleRemovedImages(\n imageRemovedCallback,\n pluginState.insertedImages,\n newState.insertedImages,\n );\n\n return newState;\n },\n } as StateField<PluginState>,\n });\n};\n\nconst getImagesFromTransaction = (tr: Transaction): Record<string, Node> => {\n const images: Record<string, Node> = {};\n tr.doc.descendants((node) => {\n if (node.type.name === 'image') {\n images[node.attrs.fileInfoId] = node;\n }\n });\n\n return images;\n};\n\nconst findAndHandleRemovedImages = (\n imageRemovedCallback: ImageRemovedCallback,\n previousImages: Record<string, Node>,\n newImages: Record<string, Node>,\n) => {\n const removedKeys = Object.keys(previousImages).filter(\n (key) => !(key in newImages),\n );\n\n for (const removedKey of removedKeys) {\n const removedImage = previousImages[removedKey];\n const imageInfo: ImageInfo = {\n fileInfoId: removedImage.attrs.fileInfoId,\n src: removedImage.attrs.src,\n state: removedImage.attrs.state,\n };\n imageRemovedCallback(imageInfo);\n\n imageCache.delete(removedImage.attrs.fileInfoId);\n }\n};\n\nexport const imageInserterFactory = (\n view: EditorView,\n base64Data: string,\n fileInfo: FileInfo,\n): ImageInserter => {\n return {\n fileInfo: fileInfo,\n insertThumbnail: createThumbnailInserter(view, base64Data, fileInfo),\n insertImage: createImageInserter(view, fileInfo),\n insertFailedThumbnail: createFailedThumbnailInserter(view, fileInfo),\n };\n};\n\nconst createThumbnailInserter =\n (view: EditorView, base64Data: string, fileInfo: FileInfo) => () => {\n const { state, dispatch } = view;\n const { schema } = state;\n\n const placeholderNode = schema.nodes.image.create({\n src: base64Data,\n alt: fileInfo.filename,\n fileInfoId: fileInfo.id,\n state: ImageState.LOADING,\n });\n\n const transaction = state.tr.replaceSelectionWith(placeholderNode);\n\n dispatch(transaction);\n };\n\nconst createImageInserter =\n (view: EditorView, fileInfo: FileInfo) => (src?: string) => {\n const { state, dispatch } = view;\n const { schema } = state;\n\n const tr = state.tr;\n state.doc.descendants((node, pos) => {\n if (node.attrs.fileInfoId === fileInfo.id) {\n const imageNode = schema.nodes.image.create({\n src: src ? src : node.attrs.src,\n alt: fileInfo.filename,\n fileInfoId: fileInfo.id,\n state: ImageState.SUCCESS,\n });\n\n tr.replaceWith(pos, pos + node.nodeSize, imageNode);\n\n return false;\n }\n });\n\n dispatch(tr);\n };\n\nconst createFailedThumbnailInserter =\n (view: EditorView, fileInfo: FileInfo) => () => {\n const { state, dispatch } = view;\n const { schema } = state;\n\n const tr = state.tr;\n state.doc.descendants((node, pos) => {\n if (node.attrs.fileInfoId === fileInfo.id) {\n const errorPlaceholderNode = schema.nodes.image.create({\n src: node.attrs.src,\n alt: fileInfo.filename,\n fileInfoId: fileInfo.id,\n state: ImageState.FAILED,\n });\n\n tr.replaceWith(pos, pos + node.nodeSize, errorPlaceholderNode);\n\n return false;\n }\n });\n\n dispatch(tr);\n };\n\n/**\n * Check if a given ProseMirror node or fragment contains any image nodes.\n * @param node - The ProseMirror node or fragment to check.\n * @returns A boolean indicating whether the node contains any image nodes.\n */\nconst isImageNode = (node: Node | Fragment): boolean => {\n if (node instanceof Node) {\n if (node.type.name === 'image') {\n return true;\n }\n\n let found = false;\n node.content.forEach((child) => {\n if (isImageNode(child)) {\n found = true;\n }\n });\n\n return found;\n } else if (node instanceof Fragment) {\n let found = false;\n node.forEach((child) => {\n if (isImageNode(child)) {\n found = true;\n }\n });\n\n return found;\n }\n\n return false;\n};\n\n/**\n * Filter out image nodes from a ProseMirror fragment.\n * @param fragment - The ProseMirror fragment to filter.\n * @returns A new fragment with image nodes removed.\n */\nconst filterImageNodes = (fragment: Fragment): Fragment => {\n const filteredChildren: Node[] = [];\n\n fragment.forEach((child) => {\n if (!isImageNode(child)) {\n if (child.content.size > 0) {\n const filteredContent = filterImageNodes(child.content);\n const newNode = child.copy(filteredContent);\n filteredChildren.push(newNode);\n } else {\n filteredChildren.push(child);\n }\n }\n });\n\n return Fragment.fromArray(filteredChildren);\n};\n\n/**\n * Process a paste event and trigger an imagePasted event if an image file is pasted.\n * If an HTML image element is pasted, this image is filtered out from the slice content.\n *\n * @param view - The ProseMirror editor view.\n * @param event - The paste event.\n * @returns A boolean; True if an image file was pasted to prevent default paste behavior, otherwise false.\n */\nconst processPasteEvent = (\n view: EditorView,\n event: ClipboardEvent,\n slice: Slice,\n): boolean => {\n const clipboardData = event.clipboardData;\n if (!clipboardData) {\n return false;\n }\n\n const files = Array.from(clipboardData.files || []);\n for (const file of files) {\n if (file.type.startsWith('image/')) {\n const reader = new FileReader();\n reader.onloadend = () => {\n view.dom.dispatchEvent(\n new CustomEvent('imagePasted', {\n detail: imageInserterFactory(\n view,\n reader.result as string,\n createFileInfo(file),\n ),\n }),\n );\n };\n\n reader.readAsDataURL(file);\n }\n }\n\n const filteredSlice = new Slice(\n filterImageNodes(slice.content),\n slice.openStart,\n slice.openEnd,\n );\n\n if (filteredSlice.content.childCount < slice.content.childCount) {\n const { state, dispatch } = view;\n const tr = state.tr.replaceSelection(filteredSlice);\n dispatch(tr);\n\n return true;\n }\n\n return files.length > 0;\n};\n"]}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { ImageState } from '../../../text-editor.types';
|
|
2
|
+
import translate from 'src/global/translations';
|
|
3
|
+
export const imageCache = new Map();
|
|
4
|
+
export function getImageNode(language) {
|
|
5
|
+
return { image: createImageNodeSpec(language) };
|
|
6
|
+
}
|
|
7
|
+
export function getImageNodeMarkdownSerializer(language) {
|
|
8
|
+
return { image: createImageNodeMarkdownSerializer(language) };
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Recursively checks if a ProseMirror node or
|
|
12
|
+
* any of its child nodes is an image node.
|
|
13
|
+
*/
|
|
14
|
+
export function hasImageNode(node) {
|
|
15
|
+
if (node.type.name === 'image') {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
19
|
+
const childNode = node.child(i);
|
|
20
|
+
if (hasImageNode(childNode)) {
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
function createImageNodeMarkdownSerializer(language) {
|
|
27
|
+
return (state, node) => {
|
|
28
|
+
if (node.attrs.state === ImageState.FAILED) {
|
|
29
|
+
const text = translate.get('editor-image-view.failed', language, {
|
|
30
|
+
filename: node.attrs.alt || 'file',
|
|
31
|
+
});
|
|
32
|
+
state.write(`<span>${text}</span>`);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
else if (node.attrs.state === ImageState.LOADING) {
|
|
36
|
+
const text = translate.get('editor-image-view.loading', language, {
|
|
37
|
+
filename: node.attrs.alt || 'file',
|
|
38
|
+
});
|
|
39
|
+
state.write(`<span>${text}</span>`);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
let imageHTML = `<img src="${node.attrs.src}"`;
|
|
43
|
+
if (node.attrs.alt) {
|
|
44
|
+
imageHTML += ` alt="${node.attrs.alt}"`;
|
|
45
|
+
}
|
|
46
|
+
const style = [];
|
|
47
|
+
if (node.attrs.width) {
|
|
48
|
+
style.push(`width: ${node.attrs.width};`);
|
|
49
|
+
}
|
|
50
|
+
if (node.attrs.maxWidth) {
|
|
51
|
+
style.push(`max-width: ${node.attrs.maxWidth};`);
|
|
52
|
+
}
|
|
53
|
+
if (style.length > 0) {
|
|
54
|
+
imageHTML += ` style="${style.join(' ')}"`;
|
|
55
|
+
}
|
|
56
|
+
imageHTML += ' />';
|
|
57
|
+
state.write(imageHTML);
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function createImageNodeSpec(language) {
|
|
61
|
+
return {
|
|
62
|
+
group: 'inline',
|
|
63
|
+
inline: true,
|
|
64
|
+
attrs: {
|
|
65
|
+
src: { default: '' },
|
|
66
|
+
alt: { default: '' },
|
|
67
|
+
fileInfoId: { default: '' },
|
|
68
|
+
width: { default: '' },
|
|
69
|
+
maxWidth: { default: '100%' },
|
|
70
|
+
state: { default: '' },
|
|
71
|
+
},
|
|
72
|
+
toDOM: (node) => {
|
|
73
|
+
if (node.attrs.state === ImageState.FAILED) {
|
|
74
|
+
return createStatusSpan('failed', node, language);
|
|
75
|
+
}
|
|
76
|
+
else if (node.attrs.state === ImageState.LOADING) {
|
|
77
|
+
return createStatusSpan('loading', node, language);
|
|
78
|
+
}
|
|
79
|
+
let img = imageCache.get(node.attrs.fileInfoId);
|
|
80
|
+
if (img) {
|
|
81
|
+
updateImageElement(img, node);
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
img = createImageElement(node);
|
|
85
|
+
imageCache.set(node.attrs.fileInfoId, img);
|
|
86
|
+
}
|
|
87
|
+
return img;
|
|
88
|
+
},
|
|
89
|
+
parseDOM: [
|
|
90
|
+
{
|
|
91
|
+
tag: 'img',
|
|
92
|
+
getAttrs: (dom) => {
|
|
93
|
+
return {
|
|
94
|
+
src: dom.getAttribute('src') || '',
|
|
95
|
+
alt: dom.getAttribute('alt') || 'file',
|
|
96
|
+
width: dom.style.width || '',
|
|
97
|
+
maxWidth: '100%',
|
|
98
|
+
state: ImageState.SUCCESS,
|
|
99
|
+
fileInfoId: crypto.randomUUID(),
|
|
100
|
+
};
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function createStatusSpan(key, node, language) {
|
|
107
|
+
const text = translate.get(`editor-image-view.${key}`, language, {
|
|
108
|
+
filename: node.attrs.alt || 'file',
|
|
109
|
+
});
|
|
110
|
+
const span = document.createElement('span');
|
|
111
|
+
span.textContent = text;
|
|
112
|
+
return span;
|
|
113
|
+
}
|
|
114
|
+
function updateImageElement(img, node) {
|
|
115
|
+
img.alt = node.attrs.alt;
|
|
116
|
+
img.style.maxWidth = node.attrs.maxWidth;
|
|
117
|
+
img.style.width = node.attrs.width;
|
|
118
|
+
return img;
|
|
119
|
+
}
|
|
120
|
+
function createImageElement(node) {
|
|
121
|
+
const img = document.createElement('img');
|
|
122
|
+
img.src = node.attrs.src;
|
|
123
|
+
img.alt = node.attrs.alt;
|
|
124
|
+
img.style.maxWidth = node.attrs.maxWidth;
|
|
125
|
+
img.style.width = node.attrs.width;
|
|
126
|
+
return img;
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=node.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node.js","sourceRoot":"","sources":["../../../../../../src/components/text-editor/prosemirror-adapter/plugins/image/node.ts"],"names":[],"mappings":"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","sourcesContent":["import { NodeSpec, Node, Attrs, DOMOutputSpec } from 'prosemirror-model';\nimport { ImageState } from '../../../text-editor.types';\nimport { MarkdownSerializerState } from 'prosemirror-markdown';\nimport { Languages } from '../../../../date-picker/date.types';\nimport translate from 'src/global/translations';\n\nexport const imageCache = new Map<string, HTMLImageElement>();\n\ntype MarkdownSerializerFunction = (\n state: MarkdownSerializerState,\n node: Node,\n) => void;\n\nexport function getImageNode(language: Languages): Record<string, NodeSpec> {\n return { image: createImageNodeSpec(language) };\n}\n\nexport function getImageNodeMarkdownSerializer(\n language: Languages,\n): Record<string, MarkdownSerializerFunction> {\n return { image: createImageNodeMarkdownSerializer(language) };\n}\n\n/**\n * Recursively checks if a ProseMirror node or\n * any of its child nodes is an image node.\n */\nexport function hasImageNode(node: Node): boolean {\n if (node.type.name === 'image') {\n return true;\n }\n\n for (let i = 0; i < node.childCount; i++) {\n const childNode = node.child(i);\n if (hasImageNode(childNode)) {\n return true;\n }\n }\n\n return false;\n}\n\nfunction createImageNodeMarkdownSerializer(\n language: Languages,\n): MarkdownSerializerFunction {\n return (state: MarkdownSerializerState, node: Node) => {\n if (node.attrs.state === ImageState.FAILED) {\n const text = translate.get('editor-image-view.failed', language, {\n filename: node.attrs.alt || 'file',\n });\n state.write(`<span>${text}</span>`);\n\n return;\n } else if (node.attrs.state === ImageState.LOADING) {\n const text = translate.get('editor-image-view.loading', language, {\n filename: node.attrs.alt || 'file',\n });\n state.write(`<span>${text}</span>`);\n\n return;\n }\n\n let imageHTML = `<img src=\"${node.attrs.src}\"`;\n\n if (node.attrs.alt) {\n imageHTML += ` alt=\"${node.attrs.alt}\"`;\n }\n\n const style = [];\n\n if (node.attrs.width) {\n style.push(`width: ${node.attrs.width};`);\n }\n\n if (node.attrs.maxWidth) {\n style.push(`max-width: ${node.attrs.maxWidth};`);\n }\n\n if (style.length > 0) {\n imageHTML += ` style=\"${style.join(' ')}\"`;\n }\n\n imageHTML += ' />';\n\n state.write(imageHTML);\n };\n}\n\nfunction createImageNodeSpec(language: Languages): NodeSpec {\n return {\n group: 'inline',\n inline: true,\n attrs: {\n src: { default: '' },\n alt: { default: '' },\n fileInfoId: { default: '' },\n width: { default: '' },\n maxWidth: { default: '100%' },\n state: { default: '' },\n },\n toDOM: (node): DOMOutputSpec => {\n if (node.attrs.state === ImageState.FAILED) {\n return createStatusSpan('failed', node, language);\n } else if (node.attrs.state === ImageState.LOADING) {\n return createStatusSpan('loading', node, language);\n }\n\n let img = imageCache.get(node.attrs.fileInfoId);\n if (img) {\n updateImageElement(img, node);\n } else {\n img = createImageElement(node);\n imageCache.set(node.attrs.fileInfoId, img);\n }\n\n return img;\n },\n parseDOM: [\n {\n tag: 'img',\n getAttrs: (dom: HTMLElement): Attrs => {\n return {\n src: dom.getAttribute('src') || '',\n alt: dom.getAttribute('alt') || 'file',\n width: dom.style.width || '',\n maxWidth: '100%',\n state: ImageState.SUCCESS,\n fileInfoId: crypto.randomUUID(),\n };\n },\n },\n ],\n };\n}\n\nfunction createStatusSpan(\n key: string,\n node: Node,\n language: Languages,\n): HTMLSpanElement {\n const text = translate.get(`editor-image-view.${key}`, language, {\n filename: node.attrs.alt || 'file',\n });\n const span = document.createElement('span');\n span.textContent = text;\n\n return span;\n}\n\nfunction updateImageElement(\n img: HTMLImageElement,\n node: Node,\n): HTMLImageElement {\n img.alt = node.attrs.alt;\n img.style.maxWidth = node.attrs.maxWidth;\n img.style.width = node.attrs.width;\n\n return img;\n}\n\nfunction createImageElement(node: Node): HTMLImageElement {\n const img = document.createElement('img');\n img.src = node.attrs.src;\n img.alt = node.attrs.alt;\n img.style.maxWidth = node.attrs.maxWidth;\n img.style.width = node.attrs.width;\n\n return img;\n}\n"]}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { Plugin } from 'prosemirror-state';
|
|
2
|
+
import { ImageState } from '../../../text-editor.types';
|
|
3
|
+
import translate from 'src/global/translations';
|
|
4
|
+
const MIN_WIDTH = 10;
|
|
5
|
+
export const createImageViewPlugin = (language) => {
|
|
6
|
+
return new Plugin({
|
|
7
|
+
props: {
|
|
8
|
+
nodeViews: {
|
|
9
|
+
image: (node, view, getPos) => {
|
|
10
|
+
return new ImageView(node, view, getPos, language);
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
class ImageView {
|
|
17
|
+
constructor(node, view, getPos, language) {
|
|
18
|
+
this.createResizeHandle = (position) => {
|
|
19
|
+
const handle = document.createElement('div');
|
|
20
|
+
handle.className = `resize-handle ${position}`;
|
|
21
|
+
handle.setAttribute('role', 'slider');
|
|
22
|
+
handle.setAttribute('aria-label', translate.get('editor-image-view.resize-handle', this.language));
|
|
23
|
+
handle.setAttribute('tabindex', '0');
|
|
24
|
+
handle.setAttribute('aria-valuemin', MIN_WIDTH.toString());
|
|
25
|
+
handle.setAttribute('aria-valuenow', this.img.offsetWidth.toString());
|
|
26
|
+
handle.setAttribute('aria-valuetext', `${this.img.offsetWidth} pixels`);
|
|
27
|
+
handle.setAttribute('aria-grabbed', 'false');
|
|
28
|
+
handle.addEventListener('pointerdown', (e) => {
|
|
29
|
+
handle.setAttribute('aria-grabbed', 'true');
|
|
30
|
+
this.onResizeStart(e, position);
|
|
31
|
+
});
|
|
32
|
+
return handle;
|
|
33
|
+
};
|
|
34
|
+
this.onResizeStart = (event, position) => {
|
|
35
|
+
event.preventDefault();
|
|
36
|
+
const handle = event.target;
|
|
37
|
+
const startX = event.clientX;
|
|
38
|
+
const startWidth = this.img.offsetWidth;
|
|
39
|
+
const onPointerMove = (e) => {
|
|
40
|
+
const delta = e.clientX - startX;
|
|
41
|
+
const widthDelta = position === 'top-left' ? -delta : delta;
|
|
42
|
+
const newWidth = Math.max(MIN_WIDTH, startWidth + widthDelta);
|
|
43
|
+
this.img.style.width = `${newWidth}px`;
|
|
44
|
+
const handles = this.dom.querySelectorAll('.resize-handle');
|
|
45
|
+
handles.forEach((resizeHandle) => {
|
|
46
|
+
resizeHandle.setAttribute('aria-valuenow', newWidth.toString());
|
|
47
|
+
resizeHandle.setAttribute('aria-valuetext', `${newWidth} pixels`);
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
const onPointerUp = () => {
|
|
51
|
+
window.removeEventListener('pointermove', onPointerMove);
|
|
52
|
+
window.removeEventListener('pointerup', onPointerUp);
|
|
53
|
+
handle.setAttribute('aria-grabbed', 'false');
|
|
54
|
+
this.view.dispatch(this.view.state.tr.setNodeMarkup(this.getPos(), undefined, Object.assign(Object.assign({}, this.node.attrs), { width: this.img.style.width, height: this.node.attrs.height })));
|
|
55
|
+
};
|
|
56
|
+
window.addEventListener('pointermove', onPointerMove);
|
|
57
|
+
window.addEventListener('pointerup', onPointerUp);
|
|
58
|
+
};
|
|
59
|
+
this.createLoadingState = () => {
|
|
60
|
+
this.dom.setAttribute('aria-live', 'polite');
|
|
61
|
+
this.dom.setAttribute('aria-busy', 'true');
|
|
62
|
+
this.dom.setAttribute('aria-label', translate.get('editor-image-view.loading', this.language, {
|
|
63
|
+
filename: this.node.attrs.alt || 'file',
|
|
64
|
+
}));
|
|
65
|
+
const spinnerElement = document.createElement('limel-linear-progress');
|
|
66
|
+
spinnerElement.setAttribute('indeterminate', 'true');
|
|
67
|
+
this.dom.appendChild(spinnerElement);
|
|
68
|
+
};
|
|
69
|
+
this.createSuccessState = () => {
|
|
70
|
+
this.dom.setAttribute('aria-live', 'polite');
|
|
71
|
+
this.dom.setAttribute('aria-busy', 'false');
|
|
72
|
+
this.dom.setAttribute('aria-label', translate.get('editor-image-view.success', this.language, {
|
|
73
|
+
filename: this.node.attrs.alt || 'file',
|
|
74
|
+
}));
|
|
75
|
+
const bottomRightHandle = this.createResizeHandle('bottom-right');
|
|
76
|
+
const topLeftHandle = this.createResizeHandle('top-left');
|
|
77
|
+
this.dom.appendChild(bottomRightHandle);
|
|
78
|
+
this.dom.appendChild(topLeftHandle);
|
|
79
|
+
};
|
|
80
|
+
this.createFailedState = () => {
|
|
81
|
+
this.dom.setAttribute('aria-live', 'assertive');
|
|
82
|
+
this.dom.setAttribute('aria-busy', 'false');
|
|
83
|
+
this.dom.setAttribute('aria-label', translate.get('editor-image-view.failed', this.language, {
|
|
84
|
+
filename: this.node.attrs.alt || 'file',
|
|
85
|
+
}));
|
|
86
|
+
};
|
|
87
|
+
this.cleanUpPreviousState = () => {
|
|
88
|
+
Array.from(this.dom.childNodes).forEach((child) => {
|
|
89
|
+
if (!(child instanceof HTMLImageElement)) {
|
|
90
|
+
child.remove();
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
};
|
|
94
|
+
this.transitionBetweenStates = () => {
|
|
95
|
+
this.cleanUpPreviousState();
|
|
96
|
+
this.dom.className = `image-wrapper state-${this.node.attrs.state}`;
|
|
97
|
+
if (this.node.attrs.state === ImageState.LOADING) {
|
|
98
|
+
this.createLoadingState();
|
|
99
|
+
}
|
|
100
|
+
else if (this.node.attrs.state === ImageState.SUCCESS) {
|
|
101
|
+
this.createSuccessState();
|
|
102
|
+
}
|
|
103
|
+
else if (this.node.attrs.state === ImageState.FAILED) {
|
|
104
|
+
this.createFailedState();
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
this.transitioningBetweenSuccessStates = (newNode) => {
|
|
108
|
+
return (this.node.attrs.state === ImageState.SUCCESS &&
|
|
109
|
+
newNode.attrs.state === ImageState.SUCCESS);
|
|
110
|
+
};
|
|
111
|
+
this.node = node;
|
|
112
|
+
this.view = view;
|
|
113
|
+
this.getPos = getPos;
|
|
114
|
+
this.language = language;
|
|
115
|
+
this.dom = document.createElement('div');
|
|
116
|
+
this.dom.className = `image-wrapper state-${node.attrs.state}`;
|
|
117
|
+
this.img = document.createElement('img');
|
|
118
|
+
this.img.src = node.attrs.src;
|
|
119
|
+
this.img.alt = node.attrs.alt;
|
|
120
|
+
this.img.style.maxWidth = node.attrs.maxWidth;
|
|
121
|
+
this.img.style.width = node.attrs.width;
|
|
122
|
+
this.dom.appendChild(this.img);
|
|
123
|
+
this.transitionBetweenStates();
|
|
124
|
+
}
|
|
125
|
+
// Ensure that the existing NodeView is reused rather than recreated.
|
|
126
|
+
// Recreating the NodeView will cause flickering between states.
|
|
127
|
+
update(node) {
|
|
128
|
+
if (!this.transitioningBetweenSuccessStates(node)) {
|
|
129
|
+
this.img.src = node.attrs.src;
|
|
130
|
+
this.img.alt = node.attrs.alt;
|
|
131
|
+
this.img.style.maxWidth = node.attrs.maxWidth;
|
|
132
|
+
this.img.style.width = node.attrs.width;
|
|
133
|
+
}
|
|
134
|
+
this.node = node;
|
|
135
|
+
this.transitionBetweenStates();
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=view.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"view.js","sourceRoot":"","sources":["../../../../../../src/components/text-editor/prosemirror-adapter/plugins/image/view.ts"],"names":[],"mappings":"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","sourcesContent":["import { EditorView, NodeView } from 'prosemirror-view';\nimport { Node } from 'prosemirror-model';\nimport { Plugin } from 'prosemirror-state';\nimport { ImageState } from '../../../text-editor.types';\nimport translate from 'src/global/translations';\nimport { Languages } from '../../../../date-picker/date.types';\n\nconst MIN_WIDTH = 10;\n\nexport const createImageViewPlugin = (language: Languages) => {\n return new Plugin({\n props: {\n nodeViews: {\n image: (node, view, getPos) => {\n return new ImageView(node, view, getPos, language);\n },\n },\n },\n });\n};\n\nclass ImageView implements NodeView {\n node: Node;\n view: EditorView;\n getPos: () => number;\n dom: HTMLDivElement;\n img: HTMLImageElement;\n language: Languages;\n\n public constructor(\n node: Node,\n view: EditorView,\n getPos: () => number,\n language: Languages,\n ) {\n this.node = node;\n this.view = view;\n this.getPos = getPos;\n this.language = language;\n\n this.dom = document.createElement('div');\n this.dom.className = `image-wrapper state-${node.attrs.state}`;\n\n this.img = document.createElement('img');\n this.img.src = node.attrs.src;\n this.img.alt = node.attrs.alt;\n this.img.style.maxWidth = node.attrs.maxWidth;\n this.img.style.width = node.attrs.width;\n\n this.dom.appendChild(this.img);\n\n this.transitionBetweenStates();\n }\n\n private createResizeHandle = (position: 'bottom-right' | 'top-left') => {\n const handle = document.createElement('div');\n handle.className = `resize-handle ${position}`;\n handle.setAttribute('role', 'slider');\n handle.setAttribute(\n 'aria-label',\n translate.get('editor-image-view.resize-handle', this.language),\n );\n handle.setAttribute('tabindex', '0');\n handle.setAttribute('aria-valuemin', MIN_WIDTH.toString());\n handle.setAttribute('aria-valuenow', this.img.offsetWidth.toString());\n handle.setAttribute('aria-valuetext', `${this.img.offsetWidth} pixels`);\n handle.setAttribute('aria-grabbed', 'false');\n\n handle.addEventListener('pointerdown', (e: PointerEvent) => {\n handle.setAttribute('aria-grabbed', 'true');\n this.onResizeStart(e, position);\n });\n\n return handle;\n };\n\n private onResizeStart = (\n event: PointerEvent,\n position: 'bottom-right' | 'top-left',\n ) => {\n event.preventDefault();\n const handle = event.target as HTMLElement;\n\n const startX = event.clientX;\n const startWidth = this.img.offsetWidth;\n\n const onPointerMove = (e: PointerEvent) => {\n const delta = e.clientX - startX;\n const widthDelta = position === 'top-left' ? -delta : delta;\n const newWidth = Math.max(MIN_WIDTH, startWidth + widthDelta);\n\n this.img.style.width = `${newWidth}px`;\n\n const handles = this.dom.querySelectorAll('.resize-handle');\n handles.forEach((resizeHandle) => {\n resizeHandle.setAttribute('aria-valuenow', newWidth.toString());\n resizeHandle.setAttribute(\n 'aria-valuetext',\n `${newWidth} pixels`,\n );\n });\n };\n\n const onPointerUp = () => {\n window.removeEventListener('pointermove', onPointerMove);\n window.removeEventListener('pointerup', onPointerUp);\n handle.setAttribute('aria-grabbed', 'false');\n\n this.view.dispatch(\n this.view.state.tr.setNodeMarkup(this.getPos(), undefined, {\n ...this.node.attrs,\n width: this.img.style.width,\n height: this.node.attrs.height,\n }),\n );\n };\n\n window.addEventListener('pointermove', onPointerMove);\n window.addEventListener('pointerup', onPointerUp);\n };\n\n private createLoadingState = () => {\n this.dom.setAttribute('aria-live', 'polite');\n this.dom.setAttribute('aria-busy', 'true');\n this.dom.setAttribute(\n 'aria-label',\n translate.get('editor-image-view.loading', this.language, {\n filename: this.node.attrs.alt || 'file',\n }),\n );\n\n const spinnerElement = document.createElement('limel-linear-progress');\n spinnerElement.setAttribute('indeterminate', 'true');\n this.dom.appendChild(spinnerElement);\n };\n\n private createSuccessState = () => {\n this.dom.setAttribute('aria-live', 'polite');\n this.dom.setAttribute('aria-busy', 'false');\n this.dom.setAttribute(\n 'aria-label',\n translate.get('editor-image-view.success', this.language, {\n filename: this.node.attrs.alt || 'file',\n }),\n );\n\n const bottomRightHandle = this.createResizeHandle('bottom-right');\n const topLeftHandle = this.createResizeHandle('top-left');\n\n this.dom.appendChild(bottomRightHandle);\n this.dom.appendChild(topLeftHandle);\n };\n\n private createFailedState = () => {\n this.dom.setAttribute('aria-live', 'assertive');\n this.dom.setAttribute('aria-busy', 'false');\n this.dom.setAttribute(\n 'aria-label',\n translate.get('editor-image-view.failed', this.language, {\n filename: this.node.attrs.alt || 'file',\n }),\n );\n };\n\n private cleanUpPreviousState = () => {\n Array.from(this.dom.childNodes).forEach((child) => {\n if (!(child instanceof HTMLImageElement)) {\n child.remove();\n }\n });\n };\n\n private transitionBetweenStates = () => {\n this.cleanUpPreviousState();\n this.dom.className = `image-wrapper state-${this.node.attrs.state}`;\n\n if (this.node.attrs.state === ImageState.LOADING) {\n this.createLoadingState();\n } else if (this.node.attrs.state === ImageState.SUCCESS) {\n this.createSuccessState();\n } else if (this.node.attrs.state === ImageState.FAILED) {\n this.createFailedState();\n }\n };\n\n private transitioningBetweenSuccessStates = (newNode: Node): boolean => {\n return (\n this.node.attrs.state === ImageState.SUCCESS &&\n newNode.attrs.state === ImageState.SUCCESS\n );\n };\n\n // Ensure that the existing NodeView is reused rather than recreated.\n // Recreating the NodeView will cause flickering between states.\n public update(node: Node): boolean {\n if (!this.transitioningBetweenSuccessStates(node)) {\n this.img.src = node.attrs.src;\n this.img.alt = node.attrs.alt;\n this.img.style.maxWidth = node.attrs.maxWidth;\n this.img.style.width = node.attrs.width;\n }\n\n this.node = node;\n this.transitionBetweenStates();\n\n return true;\n }\n}\n"]}
|
|
@@ -621,4 +621,191 @@ kbd {
|
|
|
621
621
|
img {
|
|
622
622
|
max-width: 100%;
|
|
623
623
|
border-radius: 0.25rem;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
/**
|
|
627
|
+
* Note! This file is exported to `dist/scss/` in the published
|
|
628
|
+
* node module, for consumer projects to import.
|
|
629
|
+
* That means this file cannot import from any file that isn't
|
|
630
|
+
* also exported, keeping the same relative path.
|
|
631
|
+
*
|
|
632
|
+
* Or, just don't import anything, that works too.
|
|
633
|
+
*/
|
|
634
|
+
/**
|
|
635
|
+
* This can be used on a trigger element that opens a dropdown menu or a popover.
|
|
636
|
+
*/
|
|
637
|
+
/**
|
|
638
|
+
* This mixin will mask out the content that is close to
|
|
639
|
+
* the edges of a scrollable area.
|
|
640
|
+
* - If the scrollable content has `overflow-y`, use `vertically`
|
|
641
|
+
* as an argument for `$direction`.
|
|
642
|
+
- If the scrollable content has `overflow-x`, use `horizontally`
|
|
643
|
+
* as an argument for `$direction`.
|
|
644
|
+
*
|
|
645
|
+
* For the visual effect to work smoothly, we need to make sure that
|
|
646
|
+
* the size of the fade-out edge effect is the same as the
|
|
647
|
+
* internal paddings of the scrollable area. Otherwise, content of a
|
|
648
|
+
* scrollable area that does not have a padding will fade out before
|
|
649
|
+
* any scrolling has been done.
|
|
650
|
+
* This is why this mixin already adds paddings, which automatically
|
|
651
|
+
* default to the size of the fade-out effect.
|
|
652
|
+
* This size defaults to `1rem`, but to override the size use
|
|
653
|
+
* `--limel-top-edge-fade-height` & `--limel-bottom-edge-fade-height`
|
|
654
|
+
* when `vertically` argument is set, and use
|
|
655
|
+
* `--limel-left-edge-fade-width` & `--limel-right-edge-fade-width`
|
|
656
|
+
* when `horizontally` argument is set.
|
|
657
|
+
* Of course you can also programmatically increase and decrease the
|
|
658
|
+
* size of these variables for each edge, based on the amount of
|
|
659
|
+
* scrolling that has been done by the user. In this case, make sure
|
|
660
|
+
* to add a custom padding where the mixin is used, to override
|
|
661
|
+
* the paddings that are automatically added by the mixin in the
|
|
662
|
+
* compiled CSS code.
|
|
663
|
+
*/
|
|
664
|
+
/**
|
|
665
|
+
* This mixin will add an animated underline to the bottom of an `a` elements.
|
|
666
|
+
* Note that you may need to add `all: unset;` –depending on your use case–
|
|
667
|
+
* before using this mixin.
|
|
668
|
+
*/
|
|
669
|
+
/**
|
|
670
|
+
* This mixin creates a cross-browser font stack.
|
|
671
|
+
* - `sans-serif` can be used for the UI of the components.
|
|
672
|
+
* - `monospace` can be used for code.
|
|
673
|
+
*
|
|
674
|
+
* ⚠️ If we change the font stacks, we need to update
|
|
675
|
+
* 1. the consumer documentation in `README.md`, and
|
|
676
|
+
* 2. the CSS variables of `--kompendium-example-font-family`
|
|
677
|
+
* in the `<style>` tag of `index.html`.
|
|
678
|
+
*/
|
|
679
|
+
/**
|
|
680
|
+
* This mixin is a hack, using old CSS syntax
|
|
681
|
+
* to enable you to truncate a piece of text,
|
|
682
|
+
* after a certain number of lines.
|
|
683
|
+
*/
|
|
684
|
+
.image-wrapper {
|
|
685
|
+
display: inline-flex;
|
|
686
|
+
position: relative;
|
|
687
|
+
}
|
|
688
|
+
.image-wrapper limel-linear-progress {
|
|
689
|
+
position: absolute;
|
|
690
|
+
inset: 0.25rem auto auto 0.25rem;
|
|
691
|
+
width: calc(100% - 0.5rem);
|
|
692
|
+
}
|
|
693
|
+
.image-wrapper img {
|
|
694
|
+
transition: opacity 0.2s ease, scale 0.6s ease;
|
|
695
|
+
}
|
|
696
|
+
.image-wrapper.state-failed, .image-wrapper.state-loading {
|
|
697
|
+
background: url("data:image/svg+xml;charset=utf-8, <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8' style='fill-rule:evenodd;'><path fill='rgba(186,186,192,0.16)' d='M0 0h4v4H0zM4 4h4v4H4z'/></svg>");
|
|
698
|
+
background-size: 0.5rem;
|
|
699
|
+
}
|
|
700
|
+
.image-wrapper.state-failed img, .image-wrapper.state-loading img {
|
|
701
|
+
opacity: 0.3;
|
|
702
|
+
scale: 0.98;
|
|
703
|
+
}
|
|
704
|
+
.image-wrapper::before {
|
|
705
|
+
pointer-events: none;
|
|
706
|
+
content: "";
|
|
707
|
+
display: block;
|
|
708
|
+
position: absolute;
|
|
709
|
+
inset: 0;
|
|
710
|
+
border-radius: 0.25rem;
|
|
711
|
+
transition: border-color 0.4s ease, opacity 0.2s ease, box-shadow 0.6s ease;
|
|
712
|
+
border: 1px dashed transparent;
|
|
713
|
+
opacity: 0.2;
|
|
714
|
+
}
|
|
715
|
+
.image-wrapper.state-failed img {
|
|
716
|
+
filter: grayscale(0.8);
|
|
717
|
+
}
|
|
718
|
+
.image-wrapper.state-failed:before {
|
|
719
|
+
opacity: 0.8;
|
|
720
|
+
box-shadow: var(--shadow-error-state);
|
|
721
|
+
}
|
|
722
|
+
.image-wrapper:hover::before {
|
|
723
|
+
opacity: 0.8;
|
|
724
|
+
box-shadow: var(--shadow-depth-8);
|
|
725
|
+
}
|
|
726
|
+
.image-wrapper:has(.resize-handle[aria-grabbed=true])::before {
|
|
727
|
+
border-color: var(--mdc-theme-primary);
|
|
728
|
+
opacity: 0.8;
|
|
729
|
+
box-shadow: var(--shadow-depth-16), var(--shadow-depth-8);
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
.resize-handle {
|
|
733
|
+
transition: color var(--limel-clickable-transition-speed, 0.4s) ease, background-color var(--limel-clickable-transition-speed, 0.4s) ease, box-shadow var(--limel-clickable-transform-speed, 0.4s) ease, transform var(--limel-clickable-transform-speed, 0.4s) var(--limel-clickable-transform-timing-function, ease);
|
|
734
|
+
cursor: pointer;
|
|
735
|
+
color: var(--mdc-theme-on-surface);
|
|
736
|
+
background-color: rgb(var(--contrast-900));
|
|
737
|
+
box-shadow: var(--button-shadow-normal);
|
|
738
|
+
cursor: nwse-resize;
|
|
739
|
+
position: absolute;
|
|
740
|
+
display: flex;
|
|
741
|
+
align-items: center;
|
|
742
|
+
justify-content: center;
|
|
743
|
+
width: 0.5rem;
|
|
744
|
+
height: 0.5rem;
|
|
745
|
+
border-radius: 50%;
|
|
746
|
+
opacity: 0.6;
|
|
747
|
+
}
|
|
748
|
+
.resize-handle:hover, .resize-handle:focus, .resize-handle:focus-visible {
|
|
749
|
+
will-change: color, background-color, box-shadow, transform;
|
|
750
|
+
}
|
|
751
|
+
.resize-handle:hover {
|
|
752
|
+
transform: translate3d(0, -0.04rem, 0);
|
|
753
|
+
color: var(--mdc-theme-on-surface);
|
|
754
|
+
background-color: var(--lime-elevated-surface-background-color);
|
|
755
|
+
box-shadow: var(--button-shadow-hovered);
|
|
756
|
+
}
|
|
757
|
+
.resize-handle:active {
|
|
758
|
+
--limel-clickable-transform-timing-function: cubic-bezier(
|
|
759
|
+
0.83,
|
|
760
|
+
-0.15,
|
|
761
|
+
0.49,
|
|
762
|
+
1.16
|
|
763
|
+
);
|
|
764
|
+
transform: translate3d(0, 0.05rem, 0);
|
|
765
|
+
box-shadow: var(--button-shadow-pressed);
|
|
766
|
+
}
|
|
767
|
+
.resize-handle:hover, .resize-handle:active {
|
|
768
|
+
--limel-clickable-transition-speed: 0.2s;
|
|
769
|
+
--limel-clickable-transform-speed: 0.16s;
|
|
770
|
+
}
|
|
771
|
+
.resize-handle:focus {
|
|
772
|
+
outline: none;
|
|
773
|
+
}
|
|
774
|
+
.resize-handle:focus-visible {
|
|
775
|
+
outline: none;
|
|
776
|
+
box-shadow: var(--shadow-depth-8-focused);
|
|
777
|
+
}
|
|
778
|
+
.resize-handle.top-left {
|
|
779
|
+
left: -0.25rem;
|
|
780
|
+
top: -0.25rem;
|
|
781
|
+
translate: -50%, -50%;
|
|
782
|
+
}
|
|
783
|
+
.resize-handle.bottom-right {
|
|
784
|
+
right: -0.25rem;
|
|
785
|
+
bottom: -0.25rem;
|
|
786
|
+
translate: 50%, 50%;
|
|
787
|
+
}
|
|
788
|
+
.resize-wrapper:has(.resize-handle[aria-grabbed=true]) .resize-handle, .resize-wrapper:hover .resize-handle, .resize-handle:hover, .resize-handle:focus-visible {
|
|
789
|
+
opacity: 1;
|
|
790
|
+
}
|
|
791
|
+
.resize-handle[aria-grabbed=true], .resize-handle:hover, .resize-handle:focus-visible {
|
|
792
|
+
opacity: 1;
|
|
793
|
+
background-color: var(--mdc-theme-primary);
|
|
794
|
+
}
|
|
795
|
+
.resize-handle:hover, .resize-handle[aria-grabbed=true] {
|
|
796
|
+
scale: 1.4;
|
|
797
|
+
}
|
|
798
|
+
.resize-handle:hover:before, .resize-handle[aria-grabbed=true]:before {
|
|
799
|
+
background-color: rgb(var(--color-white));
|
|
800
|
+
}
|
|
801
|
+
.resize-handle:before {
|
|
802
|
+
content: "";
|
|
803
|
+
display: block;
|
|
804
|
+
position: absolute;
|
|
805
|
+
inset: 0;
|
|
806
|
+
margin: auto;
|
|
807
|
+
border-radius: 50%;
|
|
808
|
+
width: 0.25rem;
|
|
809
|
+
height: 0.25rem;
|
|
810
|
+
background-color: rgb(var(--contrast-100));
|
|
624
811
|
}
|
|
@@ -17,12 +17,14 @@ import { isItem } from 'src/components/action-bar/isItem';
|
|
|
17
17
|
import { cloneDeep, debounce } from 'lodash-es';
|
|
18
18
|
import { strikethrough } from './menu/menu-schema-extender';
|
|
19
19
|
import { createLinkPlugin, } from './plugins/link-plugin';
|
|
20
|
-
import {
|
|
20
|
+
import { createImageInserterPlugin } from './plugins/image/inserter';
|
|
21
|
+
import { createImageViewPlugin } from './plugins/image/view';
|
|
21
22
|
import { createMenuStateTrackingPlugin } from './plugins/menu-state-tracking-plugin';
|
|
22
23
|
import { createActionBarInteractionPlugin } from './plugins/menu-action-interaction-plugin';
|
|
23
24
|
import { createNodeSpec } from '../utils/plugin-factory';
|
|
24
25
|
import { createTriggerPlugin } from './plugins/trigger/factory';
|
|
25
26
|
import { getTableNodes, getTableEditingPlugins } from './plugins/table-plugin';
|
|
27
|
+
import { getImageNode, imageCache } from './plugins/image/node';
|
|
26
28
|
const DEBOUNCE_TIMEOUT = 300;
|
|
27
29
|
/**
|
|
28
30
|
* The ProseMirror adapter offers a rich text editing experience with markdown support.
|
|
@@ -180,6 +182,7 @@ export class ProsemirrorAdapter {
|
|
|
180
182
|
}
|
|
181
183
|
disconnectedCallback() {
|
|
182
184
|
var _a, _b, _c;
|
|
185
|
+
imageCache.clear();
|
|
183
186
|
this.host.removeEventListener('open-editor-link-menu', this.handleOpenLinkMenu);
|
|
184
187
|
(_b = (_a = this.view) === null || _a === void 0 ? void 0 : _a.dom) === null || _b === void 0 ? void 0 : _b.removeEventListener('blur', this.handleBlur);
|
|
185
188
|
(_c = this.view) === null || _c === void 0 ? void 0 : _c.destroy();
|
|
@@ -195,7 +198,7 @@ export class ProsemirrorAdapter {
|
|
|
195
198
|
}
|
|
196
199
|
setupContentConverter() {
|
|
197
200
|
if (this.contentType === 'markdown') {
|
|
198
|
-
this.contentConverter = new MarkdownConverter(this.customElements);
|
|
201
|
+
this.contentConverter = new MarkdownConverter(this.customElements, this.language);
|
|
199
202
|
}
|
|
200
203
|
else if (this.contentType === 'html') {
|
|
201
204
|
this.contentConverter = new HTMLConverter(this.customElements);
|
|
@@ -228,6 +231,7 @@ export class ProsemirrorAdapter {
|
|
|
228
231
|
if (this.contentType === 'html') {
|
|
229
232
|
nodes = nodes.append(getTableNodes());
|
|
230
233
|
}
|
|
234
|
+
nodes = nodes.append(getImageNode(this.language));
|
|
231
235
|
return new Schema({
|
|
232
236
|
nodes: nodes,
|
|
233
237
|
marks: schema.spec.marks.append({
|
|
@@ -254,7 +258,8 @@ export class ProsemirrorAdapter {
|
|
|
254
258
|
keymap(this.menuCommandFactory.buildKeymap()),
|
|
255
259
|
createTriggerPlugin(this.triggerCharacters, this.contentConverter),
|
|
256
260
|
createLinkPlugin(this.handleNewLinkSelection),
|
|
257
|
-
|
|
261
|
+
createImageInserterPlugin(this.imagePasted.emit, this.imageRemoved.emit),
|
|
262
|
+
createImageViewPlugin(this.language),
|
|
258
263
|
createMenuStateTrackingPlugin(editorMenuTypesArray, this.menuCommandFactory, this.updateActiveActionBarItems),
|
|
259
264
|
createActionBarInteractionPlugin(this.menuCommandFactory),
|
|
260
265
|
...getTableEditingPlugins(this.contentType === 'html'),
|
|
@@ -443,6 +448,58 @@ export class ProsemirrorAdapter {
|
|
|
443
448
|
"resolved": "string",
|
|
444
449
|
"references": {}
|
|
445
450
|
}
|
|
451
|
+
}, {
|
|
452
|
+
"method": "imagePasted",
|
|
453
|
+
"name": "imagePasted",
|
|
454
|
+
"bubbles": true,
|
|
455
|
+
"cancelable": true,
|
|
456
|
+
"composed": true,
|
|
457
|
+
"docs": {
|
|
458
|
+
"tags": [{
|
|
459
|
+
"name": "private",
|
|
460
|
+
"text": undefined
|
|
461
|
+
}, {
|
|
462
|
+
"name": "alpha",
|
|
463
|
+
"text": undefined
|
|
464
|
+
}],
|
|
465
|
+
"text": "Dispatched when a image is pasted into the editor"
|
|
466
|
+
},
|
|
467
|
+
"complexType": {
|
|
468
|
+
"original": "ImageInserter",
|
|
469
|
+
"resolved": "ImageInserter",
|
|
470
|
+
"references": {
|
|
471
|
+
"ImageInserter": {
|
|
472
|
+
"location": "import",
|
|
473
|
+
"path": "../text-editor.types"
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}, {
|
|
478
|
+
"method": "imageRemoved",
|
|
479
|
+
"name": "imageRemoved",
|
|
480
|
+
"bubbles": true,
|
|
481
|
+
"cancelable": true,
|
|
482
|
+
"composed": true,
|
|
483
|
+
"docs": {
|
|
484
|
+
"tags": [{
|
|
485
|
+
"name": "private",
|
|
486
|
+
"text": undefined
|
|
487
|
+
}, {
|
|
488
|
+
"name": "alpha",
|
|
489
|
+
"text": undefined
|
|
490
|
+
}],
|
|
491
|
+
"text": "Dispatched when a image is removed from the editor"
|
|
492
|
+
},
|
|
493
|
+
"complexType": {
|
|
494
|
+
"original": "ImageInfo",
|
|
495
|
+
"resolved": "ImageInfo",
|
|
496
|
+
"references": {
|
|
497
|
+
"ImageInfo": {
|
|
498
|
+
"location": "import",
|
|
499
|
+
"path": "../text-editor.types"
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
}
|
|
446
503
|
}];
|
|
447
504
|
}
|
|
448
505
|
static get elementRef() { return "host"; }
|