@8btc/xcanvas 0.0.14-beta.1 → 0.0.14-beta.10

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/index.d.ts CHANGED
@@ -13,6 +13,7 @@ export declare interface XCanvasAPI {
13
13
  insertImgs: (url: string[]) => Promise<void>;
14
14
  /** 追加多张图片到画布末尾, 如果画布中存在对应图片(url相同),则不做任何操作 */
15
15
  appendImgs: (urls: string[]) => Promise<void>;
16
+ appendImgsForMaze: (urls: string[]) => Promise<void>;
16
17
  /** 保存canvas数据 */
17
18
  save: () => any;
18
19
  /** 从数据中恢复canvas画布 */
@@ -66,6 +67,10 @@ export declare interface XCanvasAPI {
66
67
  * 裁切图片
67
68
  */
68
69
  cropImage: () => void;
70
+ /**
71
+ * 删除选区里的全部元素
72
+ */
73
+ deleteSelection: () => void;
69
74
  }
70
75
 
71
76
  export declare interface XcanvasProps extends ExcalidrawProps {
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { atom, useAtom, useAtomValue, useSetAtom } from "jotai";
3
3
  import { Excalidraw, convertToExcalidrawElements, exportToCanvas } from "@8btc/excalidraw";
4
4
  import { useEffect } from "react";
5
- const version = "0.0.14-beta.1";
5
+ const version = "0.0.14-beta.10";
6
6
  const packageJson = {
7
7
  version
8
8
  };
@@ -40,7 +40,7 @@ function CustomExcalidraw(props) {
40
40
  function fetchImageAsDataUrl(src) {
41
41
  return new Promise((resolve, reject) => {
42
42
  const img = new Image();
43
- img.crossOrigin = "Anonymous";
43
+ img.crossOrigin = "anonymous";
44
44
  img.onload = () => {
45
45
  const canvas = document.createElement("canvas");
46
46
  canvas.width = img.naturalWidth;
@@ -118,15 +118,18 @@ function ApiFactory() {
118
118
  };
119
119
  })
120
120
  );
121
+ const files = excalidrawAPI.getFiles();
121
122
  rets.forEach((it) => {
122
- excalidrawAPI.addFiles([
123
- {
124
- mimeType: "image/png",
125
- id: it.url,
126
- dataURL: it.dataUrl,
127
- created: Date.now()
128
- }
129
- ]);
123
+ if (!files[it.url]) {
124
+ excalidrawAPI.addFiles([
125
+ {
126
+ mimeType: "image/png",
127
+ id: it.url,
128
+ dataURL: it.dataUrl,
129
+ created: Date.now()
130
+ }
131
+ ]);
132
+ }
130
133
  });
131
134
  const places = findPlaceForNewElements(
132
135
  excalidrawAPI.getAppState(),
@@ -172,9 +175,47 @@ function ApiFactory() {
172
175
  },
173
176
  insertImgs,
174
177
  appendImgs: async (urls) => {
175
- const files = excalidrawAPI.getFiles();
176
- const newUrls = urls.filter((it) => !files[it]);
177
- await insertImgs(newUrls);
178
+ const els = excalidrawAPI.getSceneElements();
179
+ const imgEls = els.filter((el) => el.type === "image");
180
+ const idSet = /* @__PURE__ */ new Set();
181
+ const intersecitonEls = [];
182
+ imgEls.forEach((el) => {
183
+ idSet.add(el.fileId);
184
+ if (urls.includes(el.fileId)) {
185
+ intersecitonEls.push(el);
186
+ }
187
+ });
188
+ const newUrls = urls.filter((url) => !idSet.has(url));
189
+ if (newUrls.length !== 0) {
190
+ await insertImgs(newUrls);
191
+ } else {
192
+ excalidrawAPI.scrollToContent(intersecitonEls, {
193
+ animate: els.length === 0 ? false : true
194
+ });
195
+ }
196
+ },
197
+ // 插入的图片后缀会自动带上时间戳后缀,用于解决maze跨域问题
198
+ // `${it}?t=${Date.now()}`;
199
+ appendImgsForMaze: async (urls) => {
200
+ const els = excalidrawAPI.getSceneElements();
201
+ const imgEls = els.filter((el) => el.type === "image");
202
+ const idSet = /* @__PURE__ */ new Set();
203
+ const intersecitonEls = [];
204
+ imgEls.forEach((el) => {
205
+ let elFileId = el.fileId.split("?t=")[0];
206
+ idSet.add(elFileId);
207
+ if (urls.includes(elFileId)) {
208
+ intersecitonEls.push(el);
209
+ }
210
+ });
211
+ const newUrls = urls.filter((url) => !idSet.has(url)).map((url) => `${url}?t=${Date.now()}`);
212
+ if (newUrls.length !== 0) {
213
+ await insertImgs(newUrls);
214
+ } else {
215
+ excalidrawAPI.scrollToContent(intersecitonEls, {
216
+ animate: els.length === 0 ? false : true
217
+ });
218
+ }
178
219
  },
179
220
  save: () => {
180
221
  const appState = excalidrawAPI.getAppState();
@@ -297,8 +338,7 @@ function ApiFactory() {
297
338
  throw "没有选中任何元素";
298
339
  }
299
340
  const files = excalidrawAPI.getFiles();
300
- if (selectedElements.length === 1 && selectedElements[0].type === "image" && selectedElements[0].fileId) {
301
- console.log(files[selectedElements[0].fileId].dataURL);
341
+ if (selectedElements.length === 1 && selectedElements[0].type === "image" && selectedElements[0].fileId && !selectedElements[0].crop) {
302
342
  if (selectedElements[0].fileId.startsWith("http")) {
303
343
  return selectedElements[0].fileId;
304
344
  }
@@ -351,18 +391,18 @@ function ApiFactory() {
351
391
  y: minY,
352
392
  width: h,
353
393
  height: h,
354
- ...customPos,
355
- id: `loading-${Date.now()}`,
356
- link: data.link ?? "https://www.google.com",
357
394
  // 添加必需的基本样式属性
358
- strokeColor: "#ffffff",
395
+ strokeColor: "#ffffff00",
359
396
  backgroundColor: "transparent",
360
397
  fillStyle: "solid",
361
- strokeWidth: 1,
398
+ strokeWidth: 2,
362
399
  strokeStyle: "solid",
363
400
  roundness: null,
364
- roughness: 1,
401
+ roughness: 0,
365
402
  opacity: 100,
403
+ ...customPos,
404
+ id: `loading-${Date.now()}`,
405
+ link: data.link ?? "https://www.google.com",
366
406
  // 添加必需的变换属性
367
407
  angle: 0,
368
408
  seed: Math.random(),
@@ -414,6 +454,21 @@ function ApiFactory() {
414
454
  croppingElementId: selectedElements[0].id
415
455
  }
416
456
  });
457
+ },
458
+ deleteSelection: () => {
459
+ const appState = excalidrawAPI.getAppState();
460
+ const selectedIds = appState.selectedElementIds;
461
+ const currentElements = excalidrawAPI.getSceneElements();
462
+ const newElements = currentElements.filter((el) => {
463
+ return !selectedIds[el.id];
464
+ });
465
+ excalidrawAPI.updateScene({
466
+ elements: [...newElements],
467
+ appState: {
468
+ ...appState,
469
+ selectedElementIds: {}
470
+ }
471
+ });
417
472
  }
418
473
  });
419
474
  }, [excalidrawAPI, setApi]);
@@ -2,7 +2,7 @@
2
2
  typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("react/jsx-runtime"), require("jotai"), require("@8btc/excalidraw"), require("react")) : typeof define === "function" && define.amd ? define(["exports", "react/jsx-runtime", "jotai", "@8btc/excalidraw", "react"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.XCanvas = {}, global.jsxRuntime, global.Jotai, global.Excalidraw, global.React));
3
3
  })(this, (function(exports2, jsxRuntime, jotai, excalidraw, react) {
4
4
  "use strict";
5
- const version = "0.0.14-beta.1";
5
+ const version = "0.0.14-beta.10";
6
6
  const packageJson = {
7
7
  version
8
8
  };
@@ -40,7 +40,7 @@
40
40
  function fetchImageAsDataUrl(src) {
41
41
  return new Promise((resolve, reject) => {
42
42
  const img = new Image();
43
- img.crossOrigin = "Anonymous";
43
+ img.crossOrigin = "anonymous";
44
44
  img.onload = () => {
45
45
  const canvas = document.createElement("canvas");
46
46
  canvas.width = img.naturalWidth;
@@ -118,15 +118,18 @@
118
118
  };
119
119
  })
120
120
  );
121
+ const files = excalidrawAPI.getFiles();
121
122
  rets.forEach((it) => {
122
- excalidrawAPI.addFiles([
123
- {
124
- mimeType: "image/png",
125
- id: it.url,
126
- dataURL: it.dataUrl,
127
- created: Date.now()
128
- }
129
- ]);
123
+ if (!files[it.url]) {
124
+ excalidrawAPI.addFiles([
125
+ {
126
+ mimeType: "image/png",
127
+ id: it.url,
128
+ dataURL: it.dataUrl,
129
+ created: Date.now()
130
+ }
131
+ ]);
132
+ }
130
133
  });
131
134
  const places = findPlaceForNewElements(
132
135
  excalidrawAPI.getAppState(),
@@ -172,9 +175,47 @@
172
175
  },
173
176
  insertImgs,
174
177
  appendImgs: async (urls) => {
175
- const files = excalidrawAPI.getFiles();
176
- const newUrls = urls.filter((it) => !files[it]);
177
- await insertImgs(newUrls);
178
+ const els = excalidrawAPI.getSceneElements();
179
+ const imgEls = els.filter((el) => el.type === "image");
180
+ const idSet = /* @__PURE__ */ new Set();
181
+ const intersecitonEls = [];
182
+ imgEls.forEach((el) => {
183
+ idSet.add(el.fileId);
184
+ if (urls.includes(el.fileId)) {
185
+ intersecitonEls.push(el);
186
+ }
187
+ });
188
+ const newUrls = urls.filter((url) => !idSet.has(url));
189
+ if (newUrls.length !== 0) {
190
+ await insertImgs(newUrls);
191
+ } else {
192
+ excalidrawAPI.scrollToContent(intersecitonEls, {
193
+ animate: els.length === 0 ? false : true
194
+ });
195
+ }
196
+ },
197
+ // 插入的图片后缀会自动带上时间戳后缀,用于解决maze跨域问题
198
+ // `${it}?t=${Date.now()}`;
199
+ appendImgsForMaze: async (urls) => {
200
+ const els = excalidrawAPI.getSceneElements();
201
+ const imgEls = els.filter((el) => el.type === "image");
202
+ const idSet = /* @__PURE__ */ new Set();
203
+ const intersecitonEls = [];
204
+ imgEls.forEach((el) => {
205
+ let elFileId = el.fileId.split("?t=")[0];
206
+ idSet.add(elFileId);
207
+ if (urls.includes(elFileId)) {
208
+ intersecitonEls.push(el);
209
+ }
210
+ });
211
+ const newUrls = urls.filter((url) => !idSet.has(url)).map((url) => `${url}?t=${Date.now()}`);
212
+ if (newUrls.length !== 0) {
213
+ await insertImgs(newUrls);
214
+ } else {
215
+ excalidrawAPI.scrollToContent(intersecitonEls, {
216
+ animate: els.length === 0 ? false : true
217
+ });
218
+ }
178
219
  },
179
220
  save: () => {
180
221
  const appState = excalidrawAPI.getAppState();
@@ -297,8 +338,7 @@
297
338
  throw "没有选中任何元素";
298
339
  }
299
340
  const files = excalidrawAPI.getFiles();
300
- if (selectedElements.length === 1 && selectedElements[0].type === "image" && selectedElements[0].fileId) {
301
- console.log(files[selectedElements[0].fileId].dataURL);
341
+ if (selectedElements.length === 1 && selectedElements[0].type === "image" && selectedElements[0].fileId && !selectedElements[0].crop) {
302
342
  if (selectedElements[0].fileId.startsWith("http")) {
303
343
  return selectedElements[0].fileId;
304
344
  }
@@ -351,18 +391,18 @@
351
391
  y: minY,
352
392
  width: h,
353
393
  height: h,
354
- ...customPos,
355
- id: `loading-${Date.now()}`,
356
- link: data.link ?? "https://www.google.com",
357
394
  // 添加必需的基本样式属性
358
- strokeColor: "#ffffff",
395
+ strokeColor: "#ffffff00",
359
396
  backgroundColor: "transparent",
360
397
  fillStyle: "solid",
361
- strokeWidth: 1,
398
+ strokeWidth: 2,
362
399
  strokeStyle: "solid",
363
400
  roundness: null,
364
- roughness: 1,
401
+ roughness: 0,
365
402
  opacity: 100,
403
+ ...customPos,
404
+ id: `loading-${Date.now()}`,
405
+ link: data.link ?? "https://www.google.com",
366
406
  // 添加必需的变换属性
367
407
  angle: 0,
368
408
  seed: Math.random(),
@@ -414,6 +454,21 @@
414
454
  croppingElementId: selectedElements[0].id
415
455
  }
416
456
  });
457
+ },
458
+ deleteSelection: () => {
459
+ const appState = excalidrawAPI.getAppState();
460
+ const selectedIds = appState.selectedElementIds;
461
+ const currentElements = excalidrawAPI.getSceneElements();
462
+ const newElements = currentElements.filter((el) => {
463
+ return !selectedIds[el.id];
464
+ });
465
+ excalidrawAPI.updateScene({
466
+ elements: [...newElements],
467
+ appState: {
468
+ ...appState,
469
+ selectedElementIds: {}
470
+ }
471
+ });
417
472
  }
418
473
  });
419
474
  }, [excalidrawAPI, setApi]);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@8btc/xcanvas",
3
3
  "private": false,
4
- "version": "0.0.14-beta.1",
4
+ "version": "0.0.14-beta.10",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
7
7
  "exports": {