@inshapardaz/likhari-react 0.1.6-dev.48 → 0.1.6-dev.50
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/dist/EditorRoot.d.ts +9 -0
- package/dist/EditorRoot.d.ts.map +1 -1
- package/dist/EditorRoot.js +3 -2
- package/dist/image/ImageDialog.js +3 -3
- package/dist/image/ImageOptionsContext.d.ts +7 -0
- package/dist/image/ImageOptionsContext.d.ts.map +1 -1
- package/dist/image/imageEdit.d.ts +4 -2
- package/dist/image/imageEdit.d.ts.map +1 -1
- package/dist/image/imageEdit.js +9 -6
- package/package.json +1 -1
package/dist/EditorRoot.d.ts
CHANGED
|
@@ -44,6 +44,15 @@ export interface EditorRootProps {
|
|
|
44
44
|
* simple, but they bloat the document (see `images.maxSizeMB`).
|
|
45
45
|
*/
|
|
46
46
|
onImageUpload?: (file: File) => Promise<string>;
|
|
47
|
+
/**
|
|
48
|
+
* Downloads a linked image's bytes when converting it to an embedded copy
|
|
49
|
+
* or applying a crop/rotate/flip. Without it, the browser fetches the URL
|
|
50
|
+
* directly, which fails for any image server that doesn't send CORS
|
|
51
|
+
* headers — that restriction can't be worked around from the browser
|
|
52
|
+
* alone. Provide this to route the request through your own backend (or a
|
|
53
|
+
* CORS proxy) instead.
|
|
54
|
+
*/
|
|
55
|
+
fetchImage?: (url: string) => Promise<Blob>;
|
|
47
56
|
/**
|
|
48
57
|
* Entries for the toolbar's font-family dropdown. Defaults to
|
|
49
58
|
* `DEFAULT_FONT_OPTIONS` (generic Latin faces plus the Urdu/Arabic-script
|
package/dist/EditorRoot.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EditorRoot.d.ts","sourceRoot":"","sources":["../src/EditorRoot.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAS1D,OAAO,KAAK,EAAe,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAyB,KAAK,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AACvF,OAAO,EAAwB,KAAK,mBAAmB,EAAE,KAAK,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAKzH,OAAO,EAAyB,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC;AAIjE,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,OAAO,CAAC,QAAQ,EAAE,cAAc,GAAG,YAAY,CAAC,CAAC;IACzD,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,oBAAoB,CAAC;IACtC,aAAa,CAAC,EAAE,mBAAmB,CAAC;IACpC,aAAa,CAAC,EAAE,uBAAuB,CAAC;IACxC,KAAK,CAAC,EAAE,oBAAoB,CAAC;IAC7B,WAAW,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC/B,MAAM,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,cAAc,CAAC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,IAAI,CAAC;IAClD;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,KAAK,IAAI,CAAC;IACrD;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAChD;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,SAAS;IACxB,UAAU,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,CAAC;IACrC,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,IAAI,CAAC;IAClD,iBAAiB,IAAI,OAAO,CAAC;IAC7B,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACnC,KAAK,IAAI,IAAI,CAAC;CACf;AAQD,eAAO,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"EditorRoot.d.ts","sourceRoot":"","sources":["../src/EditorRoot.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAS1D,OAAO,KAAK,EAAe,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAyB,KAAK,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AACvF,OAAO,EAAwB,KAAK,mBAAmB,EAAE,KAAK,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAKzH,OAAO,EAAyB,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC;AAIjE,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,OAAO,CAAC,QAAQ,EAAE,cAAc,GAAG,YAAY,CAAC,CAAC;IACzD,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,oBAAoB,CAAC;IACtC,aAAa,CAAC,EAAE,mBAAmB,CAAC;IACpC,aAAa,CAAC,EAAE,uBAAuB,CAAC;IACxC,KAAK,CAAC,EAAE,oBAAoB,CAAC;IAC7B,WAAW,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC/B,MAAM,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,cAAc,CAAC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,IAAI,CAAC;IAClD;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,KAAK,IAAI,CAAC;IACrD;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAChD;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,SAAS;IACxB,UAAU,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,CAAC;IACrC,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,IAAI,CAAC;IAClD,iBAAiB,IAAI,OAAO,CAAC;IAC7B,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACnC,KAAK,IAAI,IAAI,CAAC;CACf;AAQD,eAAO,MAAM,UAAU,uGA6IrB,CAAC"}
|
package/dist/EditorRoot.js
CHANGED
|
@@ -23,7 +23,7 @@ function initialEditorStateJson(initialContent) {
|
|
|
23
23
|
const state = defaultFormatRegistry.parse(initialContent.format, initialContent.value);
|
|
24
24
|
return JSON.stringify(state);
|
|
25
25
|
}
|
|
26
|
-
export const EditorRoot = forwardRef(function EditorRoot({ documentId, initialContent, featureConfig, featurePreset, theme, colorScheme, locale = 'en', placeholder = 'Start writing…', height = '480px', onChange, onSave, showSave = Boolean(onSave), onImageUpload, fontOptions, }, ref) {
|
|
26
|
+
export const EditorRoot = forwardRef(function EditorRoot({ documentId, initialContent, featureConfig, featurePreset, theme, colorScheme, locale = 'en', placeholder = 'Start writing…', height = '480px', onChange, onSave, showSave = Boolean(onSave), onImageUpload, fetchImage, fontOptions, }, ref) {
|
|
27
27
|
const config = useMemo(() => resolveFeatureConfig(featureConfig, featurePreset), [featureConfig, featurePreset]);
|
|
28
28
|
// The urdu-web-fonts stylesheets are needed for the font dropdown and for
|
|
29
29
|
// RTL content, whose canvas font (editor.css) is one of those families.
|
|
@@ -37,7 +37,8 @@ export const EditorRoot = forwardRef(function EditorRoot({ documentId, initialCo
|
|
|
37
37
|
allowCaption: config.images.caption,
|
|
38
38
|
maxSizeMB: config.images.maxSizeMB,
|
|
39
39
|
onImageUpload,
|
|
40
|
-
|
|
40
|
+
fetchImage,
|
|
41
|
+
}), [config.images.linked, config.images.embedded, config.images.caption, config.images.maxSizeMB, onImageUpload, fetchImage]);
|
|
41
42
|
const editorStateRef = useRef(null);
|
|
42
43
|
const lastSavedJsonRef = useRef(null);
|
|
43
44
|
const [isDirty, setIsDirty] = useState(false);
|
|
@@ -48,7 +48,7 @@ function useNaturalSize(src) {
|
|
|
48
48
|
* `onImageUpload` when there is one.
|
|
49
49
|
*/
|
|
50
50
|
export function ImageDialog({ mode, opened, initial, intent, onSubmit, onClose }) {
|
|
51
|
-
const { allowLinked, allowEmbedded, allowCaption, maxSizeMB, onImageUpload } = useImageOptions();
|
|
51
|
+
const { allowLinked, allowEmbedded, allowCaption, maxSizeMB, onImageUpload, fetchImage } = useImageOptions();
|
|
52
52
|
const editing = mode === 'edit' && initial !== undefined;
|
|
53
53
|
const defaultSource = editing ? 'keep' : allowLinked ? 'linked' : 'embedded';
|
|
54
54
|
const [tab, setTab] = useState('details');
|
|
@@ -136,7 +136,7 @@ export function ImageDialog({ mode, opened, initial, intent, onSubmit, onClose }
|
|
|
136
136
|
setConverting(true);
|
|
137
137
|
setError(null);
|
|
138
138
|
try {
|
|
139
|
-
const dataUrl = await fetchImageAsDataUrl(src);
|
|
139
|
+
const dataUrl = await fetchImageAsDataUrl(src, fetchImage);
|
|
140
140
|
if (dataUrlBytes(dataUrl) > maxSizeMB * 1024 * 1024)
|
|
141
141
|
throw new Error(`Image is larger than ${maxSizeMB} MB`);
|
|
142
142
|
setSource('embedded');
|
|
@@ -182,7 +182,7 @@ export function ImageDialog({ mode, opened, initial, intent, onSubmit, onClose }
|
|
|
182
182
|
let newPixels = pixelSrc ?? (source === 'embedded' ? fileSrc : null);
|
|
183
183
|
if (!newPixels && source === 'linked' && embedCopy) {
|
|
184
184
|
setBusy(true);
|
|
185
|
-
newPixels = await fetchImageAsDataUrl(effectiveSrc);
|
|
185
|
+
newPixels = await fetchImageAsDataUrl(effectiveSrc, fetchImage);
|
|
186
186
|
}
|
|
187
187
|
if (newPixels) {
|
|
188
188
|
if (dataUrlBytes(newPixels) > maxSizeMB * 1024 * 1024) {
|
|
@@ -11,6 +11,13 @@ export interface ImageOptions {
|
|
|
11
11
|
maxSizeMB: number;
|
|
12
12
|
/** Host upload handler; without it, uploads are embedded as base64 data URIs. */
|
|
13
13
|
onImageUpload?: (file: File) => Promise<string>;
|
|
14
|
+
/** Host override for downloading a linked image's bytes, used when converting
|
|
15
|
+
* a link to an embedded image or applying a crop/rotate/flip. Without it, the
|
|
16
|
+
* browser fetches the URL directly, which fails for any server that doesn't
|
|
17
|
+
* send CORS headers. A host can provide this to route the request through
|
|
18
|
+
* its own backend (or a CORS proxy) instead, since that restriction can only
|
|
19
|
+
* be worked around server-side, never from the browser alone. */
|
|
20
|
+
fetchImage?: (url: string) => Promise<Blob>;
|
|
14
21
|
}
|
|
15
22
|
export declare const ImageOptionsContext: import("react").Context<ImageOptions>;
|
|
16
23
|
export declare function useImageOptions(): ImageOptions;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImageOptionsContext.d.ts","sourceRoot":"","sources":["../../src/image/ImageOptionsContext.tsx"],"names":[],"mappings":"AAEA;kFACkF;AAClF,MAAM,WAAW,YAAY;IAC3B,8DAA8D;IAC9D,WAAW,EAAE,OAAO,CAAC;IACrB,kDAAkD;IAClD,aAAa,EAAE,OAAO,CAAC;IACvB,oDAAoD;IACpD,YAAY,EAAE,OAAO,CAAC;IACtB,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,iFAAiF;IACjF,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"ImageOptionsContext.d.ts","sourceRoot":"","sources":["../../src/image/ImageOptionsContext.tsx"],"names":[],"mappings":"AAEA;kFACkF;AAClF,MAAM,WAAW,YAAY;IAC3B,8DAA8D;IAC9D,WAAW,EAAE,OAAO,CAAC;IACrB,kDAAkD;IAClD,aAAa,EAAE,OAAO,CAAC;IACvB,oDAAoD;IACpD,YAAY,EAAE,OAAO,CAAC;IACtB,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,iFAAiF;IACjF,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAChD;;;;;qEAKiE;IACjE,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7C;AAED,eAAO,MAAM,mBAAmB,uCAK9B,CAAC;AAEH,wBAAgB,eAAe,IAAI,YAAY,CAE9C"}
|
|
@@ -26,8 +26,10 @@ export declare function dataUrlBytes(dataUrl: string): number;
|
|
|
26
26
|
export declare function dataUrlToFile(dataUrl: string, name: string): File;
|
|
27
27
|
export declare const CANNOT_DOWNLOAD = "Couldn't download this image (its server doesn't allow it). Download the file and upload it instead.";
|
|
28
28
|
/** Downloads an image and returns it as a base64 data URI, to embed it in the
|
|
29
|
-
* document.
|
|
30
|
-
|
|
29
|
+
* document. Without a `fetchBlob` override, needs the image's server to allow
|
|
30
|
+
* cross-origin reads (CORS) — a host can pass one to route the download
|
|
31
|
+
* through its own backend or a CORS proxy instead. */
|
|
32
|
+
export declare function fetchImageAsDataUrl(url: string, fetchBlob?: (url: string) => Promise<Blob>): Promise<string>;
|
|
31
33
|
export type PixelOp = {
|
|
32
34
|
type: 'rotate';
|
|
33
35
|
direction: 'cw' | 'ccw';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"imageEdit.d.ts","sourceRoot":"","sources":["../../src/image/imageEdit.ts"],"names":[],"mappings":"AAEA,2EAA2E;AAC3E,MAAM,WAAW,QAAQ;IACvB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED;sEACsE;AACtE,wBAAgB,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;;;;;EAMxE;AAED,6EAA6E;AAC7E,wBAAgB,YAAY,CAC1B,OAAO,EAAE,OAAO,GAAG,QAAQ,EAC3B,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,GACpB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAKnC;AAED;mFACmF;AACnF,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAI/C;AASD,gEAAgE;AAChE,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAKpD;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAOjE;AAED,eAAO,MAAM,eAAe,yGAC4E,CAAC;AAEzG;
|
|
1
|
+
{"version":3,"file":"imageEdit.d.ts","sourceRoot":"","sources":["../../src/image/imageEdit.ts"],"names":[],"mappings":"AAEA,2EAA2E;AAC3E,MAAM,WAAW,QAAQ;IACvB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED;sEACsE;AACtE,wBAAgB,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;;;;;EAMxE;AAED,6EAA6E;AAC7E,wBAAgB,YAAY,CAC1B,OAAO,EAAE,OAAO,GAAG,QAAQ,EAC3B,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,GACpB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAKnC;AAED;mFACmF;AACnF,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAI/C;AASD,gEAAgE;AAChE,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAKpD;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAOjE;AAED,eAAO,MAAM,eAAe,yGAC4E,CAAC;AAEzG;;;sDAGsD;AACtD,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,MAAM,EACX,SAAS,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAIpC,GACH,OAAO,CAAC,MAAM,CAAC,CAejB;AAED,MAAM,MAAM,OAAO,GACf;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,IAAI,GAAG,KAAK,CAAA;CAAE,GAC3C;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,YAAY,GAAG,UAAU,CAAA;CAAE,GACjD;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC;AAErC;+EAC+E;AAC/E,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAQhE;AAED,eAAO,MAAM,kBAAkB,iHACiF,CAAC;AAEjH,uFAAuF;AACvF,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAuC5E"}
|
package/dist/image/imageEdit.js
CHANGED
|
@@ -47,16 +47,19 @@ export function dataUrlToFile(dataUrl, name) {
|
|
|
47
47
|
}
|
|
48
48
|
export const CANNOT_DOWNLOAD = "Couldn't download this image (its server doesn't allow it). Download the file and upload it instead.";
|
|
49
49
|
/** Downloads an image and returns it as a base64 data URI, to embed it in the
|
|
50
|
-
* document.
|
|
51
|
-
|
|
50
|
+
* document. Without a `fetchBlob` override, needs the image's server to allow
|
|
51
|
+
* cross-origin reads (CORS) — a host can pass one to route the download
|
|
52
|
+
* through its own backend or a CORS proxy instead. */
|
|
53
|
+
export async function fetchImageAsDataUrl(url, fetchBlob = (u) => fetch(u, { mode: 'cors' }).then((response) => {
|
|
54
|
+
if (!response.ok)
|
|
55
|
+
throw new Error('bad status');
|
|
56
|
+
return response.blob();
|
|
57
|
+
})) {
|
|
52
58
|
if (/^data:image\//i.test(url))
|
|
53
59
|
return url;
|
|
54
60
|
let blob;
|
|
55
61
|
try {
|
|
56
|
-
|
|
57
|
-
if (!response.ok)
|
|
58
|
-
throw new Error('bad status');
|
|
59
|
-
blob = await response.blob();
|
|
62
|
+
blob = await fetchBlob(url);
|
|
60
63
|
}
|
|
61
64
|
catch {
|
|
62
65
|
throw new Error(CANNOT_DOWNLOAD);
|