@inshapardaz/likhari-react 0.1.6-dev.50 → 0.1.6-dev.54
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImageComponent.d.ts","sourceRoot":"","sources":["../../src/image/ImageComponent.tsx"],"names":[],"mappings":"AAKA,OAAO,EASL,KAAK,OAAO,EACb,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"ImageComponent.d.ts","sourceRoot":"","sources":["../../src/image/ImageComponent.tsx"],"names":[],"mappings":"AAKA,OAAO,EASL,KAAK,OAAO,EACb,MAAM,SAAS,CAAC;AAIjB,OAAO,KAAK,EAAE,aAAa,EAAa,MAAM,aAAa,CAAC;AAU5D,UAAU,mBAAmB;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,aAAa,CAAC;IACxB,yFAAyF;IACzF,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,mBAAmB,+BA4N9G"}
|
|
@@ -7,6 +7,7 @@ import { useLexicalNodeSelection } from '@lexical/react/useLexicalNodeSelection'
|
|
|
7
7
|
import { $getNodeByKey, $getSelection, $isNodeSelection, CLICK_COMMAND, COMMAND_PRIORITY_LOW, KEY_BACKSPACE_COMMAND, KEY_DELETE_COMMAND, } from 'lexical';
|
|
8
8
|
import { ImageDialog } from './ImageDialog.js';
|
|
9
9
|
import { useImageOptions } from './ImageOptionsContext.js';
|
|
10
|
+
import { dataUrlBytes, fetchImageAsDataUrl } from './imageEdit.js';
|
|
10
11
|
// A type-only import of ImageNode (ImageNode itself imports this file), so the
|
|
11
12
|
// node is recognised by its type string rather than `instanceof`.
|
|
12
13
|
function isImageNode(node) {
|
|
@@ -71,6 +72,23 @@ export function ImageComponent({ nodeKey, src, altText, caption, linkType, width
|
|
|
71
72
|
change(node);
|
|
72
73
|
});
|
|
73
74
|
};
|
|
75
|
+
// Converting from the context menu (as opposed to the "Crop & size" tab's
|
|
76
|
+
// checkbox) needs no review: just download and swap the source in place.
|
|
77
|
+
// Only on failure do we fall back to the full dialog, which shows the error
|
|
78
|
+
// and lets the person retry or pick a different image.
|
|
79
|
+
const convertToEmbedded = useCallback(async () => {
|
|
80
|
+
try {
|
|
81
|
+
const dataUrl = await fetchImageAsDataUrl(src, options.fetchImage);
|
|
82
|
+
if (dataUrlBytes(dataUrl) > options.maxSizeMB * 1024 * 1024) {
|
|
83
|
+
throw new Error(`Image is larger than ${options.maxSizeMB} MB`);
|
|
84
|
+
}
|
|
85
|
+
updateNode((node) => node.setSource(dataUrl, 'embedded'));
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
setDialog({ intent: 'convert' });
|
|
89
|
+
}
|
|
90
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
91
|
+
}, [src, options.fetchImage, options.maxSizeMB]);
|
|
74
92
|
const applyEdit = (value) => {
|
|
75
93
|
updateNode((node) => {
|
|
76
94
|
node.setSource(value.src, value.linkType);
|
|
@@ -126,7 +144,7 @@ export function ImageComponent({ nodeKey, src, altText, caption, linkType, width
|
|
|
126
144
|
}, children: [_jsxs("span", { className: "likhari-image-wrap", children: [_jsx("img", { ref: imageRef, className: "likhari-image", src: src, alt: altText, width: shownWidth, draggable: false }), isSelected && linkType === 'embedded' && (_jsx("span", { className: "likhari-image-resize-handle", role: "separator", "aria-label": "Resize image", onPointerDown: onResizeDown, onPointerMove: onResizeMove, onPointerUp: onResizeUp, onPointerCancel: onResizeUp }))] }), caption && _jsx("figcaption", { className: "likhari-image-caption", children: caption }), _jsxs(Menu, { opened: menu !== null, onChange: (opened) => {
|
|
127
145
|
if (!opened)
|
|
128
146
|
setMenu(null);
|
|
129
|
-
}, position: "bottom-start", withinPortal: true, shadow: "sm", width: 200, children: [_jsx(Menu.Target, { children: _jsx("span", { "aria-hidden": "true", style: { position: 'fixed', left: menu?.x ?? -9999, top: menu?.y ?? -9999, width: 1, height: 1, pointerEvents: 'none' } }) }), _jsxs(Menu.Dropdown, { children: [_jsx(Menu.Item, { leftSection: _jsx(IconPhotoEdit, { size: 16, stroke: 1.75 }), onClick: () => setDialog({}), children: "Edit image\u2026" }), linkType === 'linked' && options.allowEmbedded && (_jsx(Menu.Item, { leftSection: _jsx(IconPhotoDown, { size: 16, stroke: 1.75 }), onClick: () =>
|
|
147
|
+
}, position: "bottom-start", withinPortal: true, shadow: "sm", width: 200, children: [_jsx(Menu.Target, { children: _jsx("span", { "aria-hidden": "true", style: { position: 'fixed', left: menu?.x ?? -9999, top: menu?.y ?? -9999, width: 1, height: 1, pointerEvents: 'none' } }) }), _jsxs(Menu.Dropdown, { children: [_jsx(Menu.Item, { leftSection: _jsx(IconPhotoEdit, { size: 16, stroke: 1.75 }), onClick: () => setDialog({}), children: "Edit image\u2026" }), linkType === 'linked' && options.allowEmbedded && (_jsx(Menu.Item, { leftSection: _jsx(IconPhotoDown, { size: 16, stroke: 1.75 }), onClick: () => void convertToEmbedded(), children: "Convert to embedded image" })), options.allowCaption && (_jsx(Menu.Item, { leftSection: _jsx(IconTextCaption, { size: 16, stroke: 1.75 }), onClick: () => setDialog({ intent: 'caption' }), children: caption ? 'Edit caption…' : 'Add caption…' })), options.allowCaption && caption && (_jsx(Menu.Item, { leftSection: _jsx(IconX, { size: 16, stroke: 1.75 }), onClick: () => updateNode((node) => node.setCaption(null)), children: "Remove caption" })), _jsx(Menu.Divider, {}), _jsx(Menu.Item, { color: "red", leftSection: _jsx(IconTrash, { size: 16, stroke: 1.75 }), onClick: removeImage, children: "Delete image" })] })] }), _jsx(ImageDialog, { mode: "edit", opened: dialog !== null, initial: { src, altText, caption, linkType, width, height }, intent: dialog?.intent, onSubmit: applyEdit, onClose: () => {
|
|
130
148
|
setDialog(null);
|
|
131
149
|
editor.focus();
|
|
132
150
|
} })] }));
|