@netless/forge-slide 1.2.0-beta.0 → 1.3.0-beta.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/dist/slide.esm.js CHANGED
@@ -58606,7 +58606,7 @@ var require_lodash = __commonJS2({
58606
58606
  result2.__values__ = wrapper.__values__;
58607
58607
  return result2;
58608
58608
  }
58609
- function chunk7(array, size2, guard) {
58609
+ function chunk8(array, size2, guard) {
58610
58610
  if (guard ? isIterateeCall(array, size2, guard) : size2 === undefined2) {
58611
58611
  size2 = 1;
58612
58612
  } else {
@@ -60478,7 +60478,7 @@ var require_lodash = __commonJS2({
60478
60478
  lodash.bindKey = bindKey;
60479
60479
  lodash.castArray = castArray;
60480
60480
  lodash.chain = chain;
60481
- lodash.chunk = chunk7;
60481
+ lodash.chunk = chunk8;
60482
60482
  lodash.compact = compact;
60483
60483
  lodash.concat = concat;
60484
60484
  lodash.cond = cond;
@@ -60956,6 +60956,7 @@ var require_lodash = __commonJS2({
60956
60956
  }
60957
60957
  });
60958
60958
  var import_paper = __toESM2(require_paper_full(), 1);
60959
+ var import_lodash = __toESM2(require_lodash(), 1);
60959
60960
  function $(e, t, u, x = (h) => h) {
60960
60961
  return e * x(0.5 - t * (0.5 - u));
60961
60962
  }
@@ -61102,6 +61103,8 @@ function me(e, t = {}) {
61102
61103
  function ae(e, t = {}) {
61103
61104
  return ce(me(e, t), t);
61104
61105
  }
61106
+ var elementsUndoOrigin = "elementsUndoOrigin";
61107
+ var backgroundElementsUndoOrigin = "backgroundElementsUndoOrigin";
61105
61108
  function _defineProperty(e, r, t) {
61106
61109
  return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: true, configurable: true, writable: true }) : e[r] = t, e;
61107
61110
  }
@@ -61131,6 +61134,12 @@ var ElementModel = class _ElementModel {
61131
61134
  get type() {
61132
61135
  return this.root.get("type");
61133
61136
  }
61137
+ get role() {
61138
+ return this.root.get("role") ?? "normal";
61139
+ }
61140
+ get isBackground() {
61141
+ return this.role === "background";
61142
+ }
61134
61143
  get strokeWidth() {
61135
61144
  return this.root.get(_ElementModel.KEYS.strokeWidth);
61136
61145
  }
@@ -61189,6 +61198,9 @@ var ElementModel = class _ElementModel {
61189
61198
  get isPerformanceEnvironment() {
61190
61199
  return this.isPerformanceMode() && this.shouldUseLocalPoints;
61191
61200
  }
61201
+ isAttached() {
61202
+ return this.root.has(_ElementModel.KEYS.uuid);
61203
+ }
61192
61204
  constructor(root, scope, liveCursor, isPerformanceMode) {
61193
61205
  _defineProperty(this, "shadowEmitter", null);
61194
61206
  _defineProperty(this, "root", void 0);
@@ -61274,16 +61286,12 @@ var ElementModel = class _ElementModel {
61274
61286
  }
61275
61287
  }
61276
61288
  bindObserver() {
61277
- const beforeL = this.root._eH?.l?.length ?? -1;
61278
- const beforeDL = this.root._dEH?.l?.length ?? -1;
61279
61289
  removeDeepObserver(this.root, this.handlePropChange);
61280
61290
  this.subBindObserver();
61281
- const afterRemoveL = this.root._eH?.l?.length ?? -1;
61282
- const afterRemoveDL = this.root._dEH?.l?.length ?? -1;
61283
61291
  this.root.observeDeep(this.handlePropChange);
61284
- const afterAddL = this.root._eH?.l?.length ?? -1;
61285
- const afterAddDL = this.root._dEH?.l?.length ?? -1;
61286
- console.log(`[][][] bindObserver uuid=${this.uuid} doc=${!!this.root.doc} _eH: ${beforeL}->${afterRemoveL}->${afterAddL} _dEH: ${beforeDL}->${afterRemoveDL}->${afterAddDL}`);
61292
+ }
61293
+ mutationOrigin() {
61294
+ return elementsUndoOrigin;
61287
61295
  }
61288
61296
  subBindObserver() {
61289
61297
  }
@@ -61322,62 +61330,81 @@ var ElementModel = class _ElementModel {
61322
61330
  this.item.data.uuid = this.uuid;
61323
61331
  this.item.data.index = this.index;
61324
61332
  this.item.data.type = this.root.get("type");
61333
+ this.item.data.role = this.role;
61325
61334
  this.item.data.ownerId = this.ownerId;
61326
61335
  this.item.applyMatrix = false;
61327
61336
  }
61328
61337
  }
61329
61338
  appendPoints(points) {
61330
61339
  if (this.isPerformanceEnvironment) {
61331
- this.appendPointsPerformance(points);
61340
+ return this.appendPointsPerformance(points);
61332
61341
  } else {
61333
- this.appendPointsDirect(points);
61342
+ return this.appendPointsDirect(points);
61334
61343
  }
61335
61344
  }
61345
+ getPointsArray() {
61346
+ const yArray = this.root.get(_ElementModel.KEYS.points);
61347
+ return yArray instanceof Y.Array ? yArray : null;
61348
+ }
61336
61349
  appendPointsDirect(points) {
61337
- this.root.get(_ElementModel.KEYS.points).push(points);
61350
+ const yArray = this.getPointsArray();
61351
+ if (!yArray) {
61352
+ return false;
61353
+ }
61354
+ yArray.push(points);
61355
+ return true;
61338
61356
  }
61339
61357
  appendPointsPerformance(points) {
61358
+ const yArray = this.getPointsArray();
61359
+ if (!yArray) {
61360
+ return false;
61361
+ }
61340
61362
  this.localPoints = this.localPoints.concat(points);
61341
61363
  this.onVectorUpdate();
61342
61364
  if (this.appendPointsTimer) {
61343
61365
  window.clearTimeout(this.appendPointsTimer);
61344
61366
  }
61345
61367
  if (this.localPoints.length % 80 === 0) {
61346
- const yArray = this.root.get(_ElementModel.KEYS.points);
61347
61368
  yArray?.push(this.localPoints.slice(yArray.length));
61348
61369
  }
61349
61370
  this.appendPointsTimer = window.setTimeout(() => {
61350
61371
  this.appendPointsTimer = null;
61351
61372
  if (this.localPoints.length > 0) {
61352
- const yArray = this.root.get(_ElementModel.KEYS.points);
61353
- yArray?.push(this.localPoints.slice(yArray.length));
61373
+ const nextArray = this.getPointsArray();
61374
+ nextArray?.push(this.localPoints.slice(nextArray.length));
61354
61375
  }
61355
61376
  }, 100);
61377
+ return true;
61356
61378
  }
61357
61379
  setPoints(points) {
61358
61380
  if (this.isPerformanceEnvironment) {
61359
- this.setPointsPerformance(points);
61381
+ return this.setPointsPerformance(points);
61360
61382
  } else {
61361
- this.setPointsDirect(points);
61383
+ return this.setPointsDirect(points);
61362
61384
  }
61363
61385
  }
61364
61386
  setPointsDirect(points) {
61365
61387
  if (this.root.doc) {
61388
+ const yArray = this.getPointsArray();
61389
+ if (!yArray) {
61390
+ return false;
61391
+ }
61366
61392
  this.root.doc.transact(() => {
61367
- const yArray = this.root.get(_ElementModel.KEYS.points);
61368
- if (yArray) {
61369
- yArray.delete(0, yArray.length);
61370
- yArray.push(points);
61371
- }
61372
- });
61393
+ yArray.delete(0, yArray.length);
61394
+ yArray.push(points);
61395
+ }, this.mutationOrigin());
61373
61396
  } else {
61374
- const yArray = this.root.get(_ElementModel.KEYS.points) || new Y.Array();
61397
+ const yArray = this.getPointsArray() || new Y.Array();
61375
61398
  yArray.delete(0, yArray.length);
61376
61399
  yArray.push(points);
61377
61400
  this.root.set(_ElementModel.KEYS.points, yArray);
61378
61401
  }
61402
+ return true;
61379
61403
  }
61380
61404
  setPointsPerformance(points) {
61405
+ if (this.root.doc && !this.getPointsArray()) {
61406
+ return false;
61407
+ }
61381
61408
  this.localPoints = points;
61382
61409
  this.onVectorUpdate();
61383
61410
  if (this.setPointsTimer) {
@@ -61385,25 +61412,33 @@ var ElementModel = class _ElementModel {
61385
61412
  }
61386
61413
  this.setPointsTimer = window.setTimeout(() => {
61387
61414
  if (this.root.doc) {
61415
+ const yArray = this.getPointsArray();
61416
+ if (!yArray) {
61417
+ return;
61418
+ }
61388
61419
  this.root.doc.transact(() => {
61389
- const yArray = this.root.get(_ElementModel.KEYS.points);
61390
- if (yArray) {
61391
- yArray.delete(0, yArray.length);
61392
- yArray.push(points);
61393
- }
61394
- });
61420
+ yArray.delete(0, yArray.length);
61421
+ yArray.push(points);
61422
+ }, this.mutationOrigin());
61395
61423
  } else {
61396
- const yArray = this.root.get(_ElementModel.KEYS.points) || new Y.Array();
61424
+ const yArray = this.getPointsArray() || new Y.Array();
61397
61425
  yArray.delete(0, yArray.length);
61398
61426
  yArray.push(points);
61399
61427
  this.root.set(_ElementModel.KEYS.points, yArray);
61400
61428
  }
61401
61429
  }, 100);
61430
+ return true;
61402
61431
  }
61403
61432
  appendPointsMatrix(matrix) {
61404
61433
  const current = new this.scope.Matrix(this.pointsMatrix);
61405
61434
  const next = matrix.appended(current);
61406
- this.root.set(_ElementModel.KEYS.pointsMatrix, [next.a, next.b, next.c, next.d, next.tx, next.ty]);
61435
+ if (this.root.doc) {
61436
+ this.root.doc.transact(() => {
61437
+ this.root.set(_ElementModel.KEYS.pointsMatrix, [next.a, next.b, next.c, next.d, next.tx, next.ty]);
61438
+ }, this.mutationOrigin());
61439
+ } else {
61440
+ this.root.set(_ElementModel.KEYS.pointsMatrix, [next.a, next.b, next.c, next.d, next.tx, next.ty]);
61441
+ }
61407
61442
  }
61408
61443
  rotateByOffset(angle, centerX, centerY) {
61409
61444
  const current = new this.scope.Matrix(this.pointsMatrix);
@@ -61417,7 +61452,13 @@ var ElementModel = class _ElementModel {
61417
61452
  matrix2.rotate(delta, centerX, centerY);
61418
61453
  next = matrix2.appended(next);
61419
61454
  }
61420
- this.root.set(_ElementModel.KEYS.pointsMatrix, [next.a, next.b, next.c, next.d, next.tx, next.ty]);
61455
+ if (this.root.doc) {
61456
+ this.root.doc.transact(() => {
61457
+ this.root.set(_ElementModel.KEYS.pointsMatrix, [next.a, next.b, next.c, next.d, next.tx, next.ty]);
61458
+ }, this.mutationOrigin());
61459
+ } else {
61460
+ this.root.set(_ElementModel.KEYS.pointsMatrix, [next.a, next.b, next.c, next.d, next.tx, next.ty]);
61461
+ }
61421
61462
  return next.rotation;
61422
61463
  }
61423
61464
  getStyleKeys() {
@@ -61428,7 +61469,6 @@ var ElementModel = class _ElementModel {
61428
61469
  this.subDispose();
61429
61470
  }
61430
61471
  disposeObserver() {
61431
- console.log(`[][][] disposeObserver uuid=${this.uuid}`);
61432
61472
  removeDeepObserver(this.root, this.handlePropChange);
61433
61473
  }
61434
61474
  };
@@ -61467,6 +61507,7 @@ var EditorConfig = class _EditorConfig {
61467
61507
  constructor() {
61468
61508
  _defineProperty2(this, "resizeModel", () => "eight");
61469
61509
  _defineProperty2(this, "uniformScale", () => false);
61510
+ _defineProperty2(this, "translatable", () => true);
61470
61511
  _defineProperty2(this, "controlPoints", []);
61471
61512
  }
61472
61513
  merge(other) {
@@ -61475,6 +61516,7 @@ var EditorConfig = class _EditorConfig {
61475
61516
  const j = RESIZE_MODEL_LEVEL.findIndex((v) => v === other.resizeModel());
61476
61517
  next.resizeModel = () => RESIZE_MODEL_LEVEL[Math.max(i, j)];
61477
61518
  next.uniformScale = this.uniformScale || other.uniformScale;
61519
+ next.translatable = () => this.translatable() && other.translatable();
61478
61520
  next.controlPoints = [];
61479
61521
  return next;
61480
61522
  }
@@ -61503,7 +61545,7 @@ var CurveModel = class extends ElementModel {
61503
61545
  _defineProperty3(this, "debug", false);
61504
61546
  _defineProperty3(this, "clearLocalPointsWhenYPointsChange", false);
61505
61547
  _defineProperty3(this, "shouldUseLocalPoints", true);
61506
- _defineProperty3(this, "localPointsPick", 6);
61548
+ _defineProperty3(this, "localPointsPick", 4);
61507
61549
  if (!this.root.doc || !this.root.has("type")) {
61508
61550
  this.root.set("type", "curve");
61509
61551
  }
@@ -61515,7 +61557,6 @@ var CurveModel = class extends ElementModel {
61515
61557
  return (a2 + b2) / 2;
61516
61558
  }
61517
61559
  parsePoints(points) {
61518
- const hasRealPressure = points.some((p) => p.length >= 3 && p[2] > 0);
61519
61560
  const viewScale = this.scope.project.view.matrix.scaling.x || 1;
61520
61561
  const taper = this.strokeWidth * 5 / viewScale;
61521
61562
  const streamline = Math.min(0.7, 0.7 * viewScale);
@@ -61524,7 +61565,7 @@ var CurveModel = class extends ElementModel {
61524
61565
  smoothing: 0.7,
61525
61566
  thinning: 0.5,
61526
61567
  streamline,
61527
- simulatePressure: !hasRealPressure,
61568
+ simulatePressure: true,
61528
61569
  start: {
61529
61570
  taper,
61530
61571
  cap: true
@@ -61535,36 +61576,13 @@ var CurveModel = class extends ElementModel {
61535
61576
  }
61536
61577
  });
61537
61578
  }
61538
- isPressureValue(value) {
61539
- return typeof value === "number" && Number.isFinite(value) && value >= 0 && value <= 1;
61540
- }
61541
- pointStride(points) {
61542
- if (points.length >= 3 && points.length % 3 === 0) {
61543
- let hasPressureSlot = false;
61544
- for (let i = 2; i < points.length; i += 3) {
61545
- if (!this.isPressureValue(points[i])) {
61546
- return 2;
61547
- }
61548
- hasPressureSlot = true;
61549
- }
61550
- if (hasPressureSlot) {
61551
- return 3;
61552
- }
61553
- }
61554
- return 2;
61555
- }
61556
61579
  matrixedPoints() {
61557
61580
  const points = this.localPoints.length === 0 ? this.points : this.localPoints;
61558
61581
  const matrix = new this.scope.Matrix(this.pointsMatrix);
61559
- const output = [];
61560
- const stride = this.pointStride(points);
61561
- for (let i = 0, len = points.length; i + 1 < len; i += stride) {
61562
- const p = new this.scope.Point(points[i], points[i + 1]);
61563
- const tp = p.transform(matrix);
61564
- const pressure = stride === 3 ? points[i + 2] ?? 0 : 0;
61565
- output.push([tp.x, tp.y, pressure]);
61566
- }
61567
- return output;
61582
+ return (0, import_lodash.chunk)(points, 2).filter((point) => point.length === 2).map((_ref) => {
61583
+ let [x, y] = _ref;
61584
+ return new this.scope.Point(x, y).transform(matrix);
61585
+ }).map((point) => [point.x, point.y]);
61568
61586
  }
61569
61587
  createPath(points) {
61570
61588
  const path = new this.scope.Path();
@@ -61638,12 +61656,11 @@ var CurveModel = class extends ElementModel {
61638
61656
  liveCursorPoint() {
61639
61657
  const yArray = this.root.get(ElementModel.KEYS.points);
61640
61658
  const points = yArray.toArray();
61641
- const stride = this.pointStride(points);
61642
- if (points.length < stride) {
61659
+ if (points.length < 2) {
61643
61660
  return null;
61644
61661
  }
61645
61662
  const len = points.length;
61646
- const point = new this.scope.Point(points[len - stride], points[len - stride + 1]);
61663
+ const point = new this.scope.Point(points[len - 2], points[len - 1]);
61647
61664
  return point.transform(new this.scope.Matrix(this.pointsMatrix));
61648
61665
  }
61649
61666
  onStyleKeyUpdate(key) {
@@ -61736,7 +61753,7 @@ var SelectorModel = class extends ElementModel {
61736
61753
  onStyleKeyUpdate(_key) {
61737
61754
  }
61738
61755
  };
61739
- var import_lodash = __toESM2(require_lodash(), 1);
61756
+ var import_lodash2 = __toESM2(require_lodash(), 1);
61740
61757
  function _defineProperty5(e, r, t) {
61741
61758
  return (r = _toPropertyKey5(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: true, configurable: true, writable: true }) : e[r] = t, e;
61742
61759
  }
@@ -61769,7 +61786,7 @@ function serializePath(path) {
61769
61786
  }, []);
61770
61787
  }
61771
61788
  function deserializePath(points, scope, matrix) {
61772
- const segmentGroup = (0, import_lodash.chunk)(points, 6);
61789
+ const segmentGroup = (0, import_lodash2.chunk)(points, 6);
61773
61790
  const path = new scope.Path();
61774
61791
  path.segments = segmentGroup.map((v) => deserializeSegment(v, scope, matrix));
61775
61792
  return path;
@@ -61907,7 +61924,7 @@ var SegmentsModel = class extends ElementModel {
61907
61924
  onStyleKeyUpdate(_key) {
61908
61925
  }
61909
61926
  };
61910
- var import_lodash3 = __toESM2(require_lodash(), 1);
61927
+ var import_lodash4 = __toESM2(require_lodash(), 1);
61911
61928
  function _defineProperty7(e, r, t) {
61912
61929
  return (r = _toPropertyKey7(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: true, configurable: true, writable: true }) : e[r] = t, e;
61913
61930
  }
@@ -61950,7 +61967,14 @@ var WhiteboardTool = class {
61950
61967
  }
61951
61968
  this.pendingDragEvent = null;
61952
61969
  this.shadowEmitter.setActive(true);
61953
- this.onMouseDown(event);
61970
+ try {
61971
+ this.onMouseDown(event);
61972
+ } catch (error) {
61973
+ this.cancelCurrentAction();
61974
+ this.eventAvailable = false;
61975
+ this.shadowEmitter.setActive(false);
61976
+ throw error;
61977
+ }
61954
61978
  });
61955
61979
  _defineProperty7(this, "flushPendingDrag", () => {
61956
61980
  this.dragRafId = 0;
@@ -61958,7 +61982,14 @@ var WhiteboardTool = class {
61958
61982
  this.lastDragTime = performance.now();
61959
61983
  const event = this.pendingDragEvent;
61960
61984
  this.pendingDragEvent = null;
61961
- this.onMouseDrag(event);
61985
+ try {
61986
+ this.onMouseDrag(event);
61987
+ } catch (error) {
61988
+ this.cancelCurrentAction();
61989
+ this.eventAvailable = false;
61990
+ this.shadowEmitter.setActive(false);
61991
+ throw error;
61992
+ }
61962
61993
  }
61963
61994
  });
61964
61995
  _defineProperty7(this, "onMouseDragSelf", (event) => {
@@ -61969,7 +62000,14 @@ var WhiteboardTool = class {
61969
62000
  if (now - this.lastDragTime >= DRAG_FRAME_MS) {
61970
62001
  this.lastDragTime = now;
61971
62002
  this.pendingDragEvent = null;
61972
- this.onMouseDrag(event);
62003
+ try {
62004
+ this.onMouseDrag(event);
62005
+ } catch (error) {
62006
+ this.cancelCurrentAction();
62007
+ this.eventAvailable = false;
62008
+ this.shadowEmitter.setActive(false);
62009
+ throw error;
62010
+ }
61973
62011
  } else {
61974
62012
  this.pendingDragEvent = event;
61975
62013
  if (!this.dragRafId) {
@@ -61986,11 +62024,26 @@ var WhiteboardTool = class {
61986
62024
  this.dragRafId = 0;
61987
62025
  }
61988
62026
  if (this.pendingDragEvent) {
61989
- this.onMouseDrag(this.pendingDragEvent);
61990
- this.pendingDragEvent = null;
62027
+ try {
62028
+ this.onMouseDrag(this.pendingDragEvent);
62029
+ this.pendingDragEvent = null;
62030
+ } catch (error) {
62031
+ this.pendingDragEvent = null;
62032
+ this.cancelCurrentAction();
62033
+ this.eventAvailable = false;
62034
+ this.shadowEmitter.setActive(false);
62035
+ throw error;
62036
+ }
62037
+ }
62038
+ try {
62039
+ this.onMouseUp(event);
62040
+ } catch (error) {
62041
+ this.cancelCurrentAction();
62042
+ this.eventAvailable = false;
62043
+ throw error;
62044
+ } finally {
62045
+ this.shadowEmitter.setActive(false);
61991
62046
  }
61992
- this.onMouseUp(event);
61993
- this.shadowEmitter.setActive(false);
61994
62047
  });
61995
62048
  this.modelGetter = modelGetter;
61996
62049
  this.enableToolEvent = enableToolEvent;
@@ -62001,8 +62054,10 @@ var WhiteboardTool = class {
62001
62054
  this.tool.onMouseDrag = this.onMouseDragSelf;
62002
62055
  this.tool.onMouseUp = this.onMouseUpSelf;
62003
62056
  }
62057
+ cancelCurrentAction() {
62058
+ }
62004
62059
  };
62005
- var import_lodash2 = __toESM2(require_lodash(), 1);
62060
+ var import_lodash3 = __toESM2(require_lodash(), 1);
62006
62061
  function _defineProperty8(e, r, t) {
62007
62062
  return (r = _toPropertyKey8(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: true, configurable: true, writable: true }) : e[r] = t, e;
62008
62063
  }
@@ -62051,7 +62106,7 @@ var LineTool = class extends WhiteboardTool {
62051
62106
  const point = path.getPointAt(distance);
62052
62107
  return [point.x, point.y];
62053
62108
  });
62054
- this.elementModel.setPoints((0, import_lodash2.flattenDeep)(points));
62109
+ this.elementModel.setPoints((0, import_lodash3.flattenDeep)(points));
62055
62110
  }
62056
62111
  }
62057
62112
  onMouseUp(_event) {
@@ -62132,7 +62187,7 @@ var LineModel = class extends ElementModel {
62132
62187
  }
62133
62188
  renderLine() {
62134
62189
  const matrix = new this.scope.Matrix(this.pointsMatrix);
62135
- const papperPoints = (0, import_lodash3.chunk)(this.drawPoints, 2).map((item) => {
62190
+ const papperPoints = (0, import_lodash4.chunk)(this.drawPoints, 2).map((item) => {
62136
62191
  return new this.scope.Point(item[0], item[1]).transform(matrix);
62137
62192
  });
62138
62193
  const path = new this.scope.Path();
@@ -62268,7 +62323,7 @@ var LineControlPoint = class {
62268
62323
  const invertedPoint = point.transform(pointsMatrix.inverted());
62269
62324
  const points = this.model["drawPoints"];
62270
62325
  this.position = invertedPoint;
62271
- const clonedPoints = (0, import_lodash3.cloneDeep)(points);
62326
+ const clonedPoints = (0, import_lodash4.cloneDeep)(points);
62272
62327
  clonedPoints[this.options.index * 2] = invertedPoint.x;
62273
62328
  clonedPoints[this.options.index * 2 + 1] = invertedPoint.y;
62274
62329
  this.model.setPoints(clonedPoints);
@@ -62373,7 +62428,6 @@ var PointTextModel = class extends ElementModel {
62373
62428
  if (!this.item) {
62374
62429
  return null;
62375
62430
  }
62376
- console.log("[][][] drawPoints", this.drawPoints);
62377
62431
  const bounds = this.item.internalBounds;
62378
62432
  const matrix = new this.scope.Matrix(this.pointsMatrix);
62379
62433
  const topLeft = new this.scope.Point(this.drawPoints[0], this.drawPoints[1]).transform(matrix);
@@ -62737,8 +62791,7 @@ var RectangleModel = class extends ElementModel {
62737
62791
  onStyleKeyUpdate(_key) {
62738
62792
  }
62739
62793
  };
62740
- var elementsUndoOrigin = "elementsUndoOrigin";
62741
- var import_lodash4 = __toESM2(require_lodash(), 1);
62794
+ var import_lodash5 = __toESM2(require_lodash(), 1);
62742
62795
  function _defineProperty13(e, r, t) {
62743
62796
  return (r = _toPropertyKey13(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: true, configurable: true, writable: true }) : e[r] = t, e;
62744
62797
  }
@@ -62806,7 +62859,7 @@ var EraserModel = class extends ElementModel {
62806
62859
  return path;
62807
62860
  }
62808
62861
  parsePoints(points) {
62809
- const groupPoints = (0, import_lodash4.chunk)(points, 2);
62862
+ const groupPoints = (0, import_lodash5.chunk)(points, 2);
62810
62863
  return ae(groupPoints, {
62811
62864
  size: this.strokeWidth,
62812
62865
  smoothing: 0.5,
@@ -62824,7 +62877,7 @@ var EraserModel = class extends ElementModel {
62824
62877
  });
62825
62878
  }
62826
62879
  matrixedPoints() {
62827
- const currentPoints = (0, import_lodash4.chunk)(this.drawPoints, 2).slice(this.sliceBegin);
62880
+ const currentPoints = (0, import_lodash5.chunk)(this.drawPoints, 2).slice(this.sliceBegin);
62828
62881
  return currentPoints.map((_ref) => {
62829
62882
  let [x, y] = _ref;
62830
62883
  return new this.scope.Point(x, y);
@@ -62887,7 +62940,7 @@ var EraserModel = class extends ElementModel {
62887
62940
  return point.transform(new this.scope.Matrix(this.pointsMatrix));
62888
62941
  }
62889
62942
  };
62890
- var import_lodash5 = __toESM2(require_lodash(), 1);
62943
+ var import_lodash6 = __toESM2(require_lodash(), 1);
62891
62944
  function _defineProperty14(e, r, t) {
62892
62945
  return (r = _toPropertyKey14(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: true, configurable: true, writable: true }) : e[r] = t, e;
62893
62946
  }
@@ -63012,8 +63065,7 @@ var LaserPointerModel = class extends ElementModel {
63012
63065
  matrixedPoints() {
63013
63066
  const matrix = new this.scope.Matrix(this.pointsMatrix);
63014
63067
  const points = this.cachedPoints || this.points;
63015
- console.log("[][][] ,", this.points.length, this.cachedPoints?.length, this.localPoints.length);
63016
- const groupPoints = (0, import_lodash5.chunk)(points, 2).slice(this.sliceBegin);
63068
+ const groupPoints = (0, import_lodash6.chunk)(points, 2).slice(this.sliceBegin);
63017
63069
  return groupPoints.map((_ref) => {
63018
63070
  let [x, y] = _ref;
63019
63071
  return matrix.transform([x, y]);
@@ -63087,7 +63139,7 @@ var WhiteboardPermissions = class extends AbstractApplicationPermissions {
63087
63139
  return [WhiteboardPermissionFlag.draw, WhiteboardPermissionFlag.editSelf, WhiteboardPermissionFlag.editOthers, WhiteboardPermissionFlag.deleteSelf, WhiteboardPermissionFlag.deleteOthers, WhiteboardPermissionFlag.mainView, WhiteboardPermissionFlag.setOthersView].filter((v) => (v & value) !== 0);
63088
63140
  }
63089
63141
  };
63090
- var import_lodash6 = __toESM2(require_lodash(), 1);
63142
+ var import_lodash7 = __toESM2(require_lodash(), 1);
63091
63143
  function _defineProperty15(e, r, t) {
63092
63144
  return (r = _toPropertyKey15(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: true, configurable: true, writable: true }) : e[r] = t, e;
63093
63145
  }
@@ -63146,7 +63198,7 @@ var StraightLineModel = class extends ElementModel {
63146
63198
  }
63147
63199
  renderLine() {
63148
63200
  const matrix = new this.scope.Matrix(this.pointsMatrix);
63149
- const papperPoints = (0, import_lodash6.chunk)(this.drawPoints, 2).map((item) => {
63201
+ const papperPoints = (0, import_lodash7.chunk)(this.drawPoints, 2).map((item) => {
63150
63202
  return new this.scope.Point(item[0], item[1]).transform(matrix);
63151
63203
  });
63152
63204
  const path = new this.scope.Path();
@@ -63274,6 +63326,7 @@ var ImageModel = class extends ElementModel {
63274
63326
  this.item = new this.scope.Raster(this.uuid);
63275
63327
  const matrix = new this.scope.Matrix(this.pointsMatrix);
63276
63328
  this.item.matrix = matrix;
63329
+ this.item.data.role = this.role;
63277
63330
  }
63278
63331
  onVectorUpdate() {
63279
63332
  const matrix = new this.scope.Matrix(this.pointsMatrix);
@@ -63302,8 +63355,12 @@ var ImageModel = class extends ElementModel {
63302
63355
  const cfg = new EditorConfig();
63303
63356
  cfg.resizeModel = () => "four-corner";
63304
63357
  cfg.uniformScale = () => true;
63358
+ cfg.translatable = () => !this.isBackground;
63305
63359
  return cfg;
63306
63360
  }
63361
+ mutationOrigin() {
63362
+ return this.isBackground ? backgroundElementsUndoOrigin : elementsUndoOrigin;
63363
+ }
63307
63364
  liveCursorPoint() {
63308
63365
  return null;
63309
63366
  }
@@ -63384,6 +63441,7 @@ var RenderableModel = class extends EventEmitter {
63384
63441
  flushRenderables() {
63385
63442
  this.emit("elementClear");
63386
63443
  const elements = Array.from(this.elements.values()).map((v) => this.convertToModel(v)).filter((v) => !!v);
63444
+ elements.sort((a2, b2) => this.compareElements(a2, b2));
63387
63445
  this.maxIndex = elements.reduce((r, n) => Math.max(r, n.index), -1);
63388
63446
  const clearIds = [];
63389
63447
  elements.forEach((model) => {
@@ -63445,7 +63503,32 @@ var RenderableModel = class extends EventEmitter {
63445
63503
  initElement(element) {
63446
63504
  element.shadowEmitter = this.shadowEmitter;
63447
63505
  }
63506
+ compareElementRole(roleA, roleB) {
63507
+ const a2 = roleA === "background" ? 0 : 1;
63508
+ const b2 = roleB === "background" ? 0 : 1;
63509
+ return a2 - b2;
63510
+ }
63511
+ compareElements(a2, b2) {
63512
+ const roleCompare = this.compareElementRole(a2.role, b2.role);
63513
+ if (roleCompare !== 0) {
63514
+ return roleCompare;
63515
+ }
63516
+ if (a2.index !== b2.index) {
63517
+ return a2.index - b2.index;
63518
+ }
63519
+ return a2.uuid.localeCompare(b2.uuid);
63520
+ }
63521
+ isBackgroundElement(uuid) {
63522
+ const element = this.elements.get(uuid);
63523
+ if (!element) {
63524
+ return false;
63525
+ }
63526
+ return (element.get("role") ?? "normal") === "background";
63527
+ }
63448
63528
  removeElementItem(uuid) {
63529
+ if (this.isBackgroundElement(uuid)) {
63530
+ return;
63531
+ }
63449
63532
  this.elements.delete(uuid);
63450
63533
  }
63451
63534
  confirmPermission() {
@@ -63456,15 +63539,21 @@ var RenderableModel = class extends EventEmitter {
63456
63539
  return hasPermission;
63457
63540
  }
63458
63541
  createImage(src) {
63542
+ let fit = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "legacy";
63543
+ let role = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : "normal";
63459
63544
  if (!this.confirmPermission()) {
63460
63545
  return;
63461
63546
  }
63547
+ if (role === "background") {
63548
+ return this.upsertBackgroundImage(src, fit);
63549
+ }
63462
63550
  const yMap = new Y12.Map();
63463
63551
  this.elements.doc?.transact(() => {
63464
63552
  const uuid = this.uuid;
63465
63553
  yMap.set(ElementModel.KEYS.index, ++this.maxIndex);
63466
63554
  yMap.set(ElementModel.KEYS.uuid, uuid);
63467
63555
  yMap.set("type", "image");
63556
+ yMap.set("role", role);
63468
63557
  yMap.set(ElementModel.KEYS.ownerId, this.userManager.selfId);
63469
63558
  this.elements.set(uuid, yMap);
63470
63559
  }, elementsUndoOrigin);
@@ -63472,9 +63561,47 @@ var RenderableModel = class extends EventEmitter {
63472
63561
  model.bindObserver();
63473
63562
  model.root.set("src", src);
63474
63563
  model.ownerId = this.userManager.selfId;
63475
- this.fitImageToViewport(src, model);
63564
+ this.fitImageToViewport(src, model, fit);
63565
+ }
63566
+ upsertBackgroundImage(src, fit) {
63567
+ const backgroundEntries = Array.from(this.elements.entries()).filter((_ref) => {
63568
+ let [, elementMap] = _ref;
63569
+ return elementMap.get("type") === "image" && (elementMap.get("role") ?? "normal") === "background";
63570
+ });
63571
+ let targetMap = backgroundEntries[0]?.[1] ?? null;
63572
+ if (this.elements.doc) {
63573
+ this.elements.doc.transact(() => {
63574
+ backgroundEntries.slice(1).forEach((_ref2) => {
63575
+ let [key] = _ref2;
63576
+ return this.elements.delete(key);
63577
+ });
63578
+ if (!targetMap) {
63579
+ targetMap = new Y12.Map();
63580
+ const uuid = this.uuid;
63581
+ targetMap.set(ElementModel.KEYS.index, -1);
63582
+ targetMap.set(ElementModel.KEYS.uuid, uuid);
63583
+ targetMap.set("type", "image");
63584
+ targetMap.set("role", "background");
63585
+ targetMap.set(ElementModel.KEYS.ownerId, this.userManager.selfId);
63586
+ this.elements.set(uuid, targetMap);
63587
+ } else {
63588
+ targetMap.set("role", "background");
63589
+ targetMap.set(ElementModel.KEYS.ownerId, this.userManager.selfId);
63590
+ }
63591
+ }, backgroundElementsUndoOrigin);
63592
+ }
63593
+ if (!targetMap) {
63594
+ return;
63595
+ }
63596
+ const model = this.convertToModel(targetMap);
63597
+ if (!model || !(model instanceof ImageModel)) {
63598
+ return;
63599
+ }
63600
+ model.root.set("src", src);
63601
+ model.ownerId = this.userManager.selfId;
63602
+ this.fitImageToViewport(src, model, fit);
63476
63603
  }
63477
- fitImageToViewport(src, model) {
63604
+ fitImageToViewport(src, model, fit) {
63478
63605
  const center = this.scope.project.view.center;
63479
63606
  const fallbackMatrix = new this.scope.Matrix();
63480
63607
  fallbackMatrix.translate({
@@ -63491,9 +63618,9 @@ var RenderableModel = class extends EventEmitter {
63491
63618
  return;
63492
63619
  }
63493
63620
  const viewportBounds = this.scope.project.view.bounds;
63494
- const maxWidth = viewportBounds.width * 2 / 3;
63495
- const maxHeight = viewportBounds.height * 2 / 3;
63496
- const fitScale = Math.min(maxWidth / naturalWidth, maxHeight / naturalHeight, 1);
63621
+ const maxWidth = fit === "contain" ? viewportBounds.width : viewportBounds.width * 2 / 3;
63622
+ const maxHeight = fit === "contain" ? viewportBounds.height : viewportBounds.height * 2 / 3;
63623
+ const fitScale = fit === "contain" ? Math.min(maxWidth / naturalWidth, maxHeight / naturalHeight) : Math.min(maxWidth / naturalWidth, maxHeight / naturalHeight, 1);
63497
63624
  const nextMatrix = new this.scope.Matrix();
63498
63625
  nextMatrix.translate({
63499
63626
  x: center.x,
@@ -63516,7 +63643,7 @@ var RenderableModel = class extends EventEmitter {
63516
63643
  if (model.root.doc) {
63517
63644
  model.root.doc.transact(() => {
63518
63645
  model.root.set(ElementModel.KEYS.pointsMatrix, values);
63519
- }, elementsUndoOrigin);
63646
+ }, model.isBackground ? backgroundElementsUndoOrigin : elementsUndoOrigin);
63520
63647
  } else {
63521
63648
  model.root.set(ElementModel.KEYS.pointsMatrix, values);
63522
63649
  }
@@ -63776,7 +63903,7 @@ var RenderableModel = class extends EventEmitter {
63776
63903
  if (shadow) {
63777
63904
  yMap.set(ElementModel.KEYS.shadow, "layer");
63778
63905
  }
63779
- yMap.set(ElementModel.KEYS.points, new Y12.Array());
63906
+ yMap.set(ElementModel.KEYS.points, Y12.Array.from([x, y]));
63780
63907
  yMap.set(ElementModel.KEYS.strokeWidth, this.toolbarModel.strokeWidth);
63781
63908
  yMap.set(ElementModel.KEYS.strokeColor, this.toolbarModel.strokeColor);
63782
63909
  yMap.set(ElementModel.KEYS.fillColor, this.toolbarModel.fillColor);
@@ -63784,7 +63911,6 @@ var RenderableModel = class extends EventEmitter {
63784
63911
  this.elements.set(uuid, yMap);
63785
63912
  }, elementsUndoOrigin);
63786
63913
  pointTextModel.bindObserver();
63787
- pointTextModel.setPoints([x, y]);
63788
63914
  pointTextModel.fontSize = this.toolbarModel.fontSize;
63789
63915
  pointTextModel.fontFamily = this.toolbarModel.fontFamily;
63790
63916
  this.initElement(pointTextModel);
@@ -63816,7 +63942,7 @@ var RenderableModel = class extends EventEmitter {
63816
63942
  });
63817
63943
  }
63818
63944
  };
63819
- var import_lodash7 = __toESM2(require_lodash(), 1);
63945
+ var import_lodash8 = __toESM2(require_lodash(), 1);
63820
63946
  function Point(x, y) {
63821
63947
  this.X = x;
63822
63948
  this.Y = y;
@@ -64059,7 +64185,7 @@ var Recognizer = class {
64059
64185
  let maxX = -Number.MAX_VALUE;
64060
64186
  let minY = Number.MAX_VALUE;
64061
64187
  let maxY = -Number.MAX_VALUE;
64062
- const result = this.dollar.Recognize((0, import_lodash7.chunk)(points, 3).map((v) => {
64188
+ const result = this.dollar.Recognize((0, import_lodash8.chunk)(points, 2).map((v) => {
64063
64189
  minX = Math.min(minX, v[0]);
64064
64190
  maxX = Math.max(maxX, v[0]);
64065
64191
  minY = Math.min(minY, v[1]);
@@ -64107,22 +64233,33 @@ var CurveTool = class extends WhiteboardTool {
64107
64233
  _defineProperty19(this, "flushPendingPoints", () => {
64108
64234
  this.flushRafId = 0;
64109
64235
  if (this.elementModel && this.pendingPoints.length > 0) {
64110
- this.elementModel.appendPoints(this.pendingPoints);
64236
+ const appended = this.elementModel.appendPoints(this.pendingPoints);
64237
+ if (!appended) {
64238
+ this.resetStrokeState();
64239
+ return;
64240
+ }
64111
64241
  this.pendingPoints = [];
64112
64242
  }
64113
64243
  });
64114
64244
  }
64115
- onMouseDown(_event) {
64245
+ resetStrokeState() {
64116
64246
  this.pointCount = 0;
64117
64247
  this.pendingPoints = [];
64118
64248
  if (this.flushRafId) {
64119
64249
  cancelAnimationFrame(this.flushRafId);
64120
64250
  this.flushRafId = 0;
64121
64251
  }
64122
- if (this.elementModel) {
64123
- this.elementModel.dispose();
64124
- }
64125
64252
  this.elementModel = null;
64253
+ }
64254
+ cancelCurrentAction() {
64255
+ this.resetStrokeState();
64256
+ }
64257
+ onMouseDown(_event) {
64258
+ const previousElement = this.elementModel;
64259
+ this.resetStrokeState();
64260
+ if (previousElement) {
64261
+ previousElement.dispose();
64262
+ }
64126
64263
  this.modelGetter().then((model) => {
64127
64264
  if (model) {
64128
64265
  this.elementModel = model.createCurve(true);
@@ -64135,24 +64272,26 @@ var CurveTool = class extends WhiteboardTool {
64135
64272
  }
64136
64273
  const MIN_DISTANCE = 2;
64137
64274
  if (this.elementModel) {
64275
+ if (!this.elementModel.isAttached()) {
64276
+ this.resetStrokeState();
64277
+ return;
64278
+ }
64138
64279
  let lastX = 0;
64139
64280
  let lastY = 0;
64140
- if (this.pendingPoints.length >= 3) {
64141
- lastX = this.pendingPoints[this.pendingPoints.length - 3];
64142
- lastY = this.pendingPoints[this.pendingPoints.length - 2];
64281
+ if (this.pendingPoints.length >= 2) {
64282
+ lastX = this.pendingPoints[this.pendingPoints.length - 2];
64283
+ lastY = this.pendingPoints[this.pendingPoints.length - 1];
64143
64284
  } else {
64144
64285
  const len = this.elementModel.points.length;
64145
- if (len >= 3) {
64146
- lastX = this.elementModel.points[len - 3];
64147
- lastY = this.elementModel.points[len - 2];
64286
+ if (len >= 2) {
64287
+ lastX = this.elementModel.points[len - 2];
64288
+ lastY = this.elementModel.points[len - 1];
64148
64289
  }
64149
64290
  }
64150
64291
  const dist = Math.max(Math.abs(lastX - event.point.x), Math.abs(lastY - event.point.y));
64151
64292
  if (dist >= MIN_DISTANCE) {
64152
64293
  this.pointCount += 1;
64153
- const nativeEvent = event.event;
64154
- const pressure = nativeEvent.pointerType === "pen" && nativeEvent.pressure > 0 ? nativeEvent.pressure : 0;
64155
- this.pendingPoints.push(event.point.x, event.point.y, pressure);
64294
+ this.pendingPoints.push(event.point.x, event.point.y);
64156
64295
  if (!this.flushRafId) {
64157
64296
  this.flushRafId = requestAnimationFrame(this.flushPendingPoints);
64158
64297
  }
@@ -64165,22 +64304,27 @@ var CurveTool = class extends WhiteboardTool {
64165
64304
  this.flushRafId = 0;
64166
64305
  }
64167
64306
  this.flushPendingPoints();
64307
+ if (!this.elementModel || !this.elementModel.isAttached()) {
64308
+ this.resetStrokeState();
64309
+ return;
64310
+ }
64311
+ const currentElement = this.elementModel;
64312
+ const currentUuid = currentElement.uuid;
64313
+ const currentPointCount = this.pointCount;
64168
64314
  this.modelGetter().then((model) => {
64169
64315
  if (!model) {
64170
64316
  return;
64171
64317
  }
64172
- if (this.pointCount < 3 && this.elementModel) {
64173
- if (this.elementModel) {
64174
- model.removeElementItem(this.elementModel.uuid);
64175
- }
64318
+ if (currentPointCount < 3) {
64319
+ model.removeElementItem(currentUuid);
64176
64320
  }
64177
- if (this.elementModel) {
64178
- this.elementModel.shadow = "";
64321
+ if (currentElement.isAttached()) {
64322
+ currentElement.shadow = "";
64179
64323
  }
64180
- if (this.elementModel && event.event.metaKey) {
64181
- const result = this.recognizer.recognize(this.elementModel.points);
64324
+ if (currentElement.isAttached() && event.event.metaKey) {
64325
+ const result = this.recognizer.recognize(currentElement.points);
64182
64326
  if (result) {
64183
- model.removeElementItem(this.elementModel.uuid);
64327
+ model.removeElementItem(currentUuid);
64184
64328
  if (/^rectangle/.test(result.shape)) {
64185
64329
  const rect = model.createRectangle(false);
64186
64330
  rect?.setPoints([result.minX, result.minY, result.maxX, result.maxY]);
@@ -64199,6 +64343,9 @@ var CurveTool = class extends WhiteboardTool {
64199
64343
  }
64200
64344
  }
64201
64345
  }
64346
+ if (this.elementModel === currentElement) {
64347
+ this.resetStrokeState();
64348
+ }
64202
64349
  });
64203
64350
  }
64204
64351
  };
@@ -64388,6 +64535,9 @@ var SelectorTool = class extends WhiteboardTool {
64388
64535
  _defineProperty22(this, "showLiveCursor", false);
64389
64536
  this.selectElementsModel = selectElementsModel;
64390
64537
  }
64538
+ isSelectableItem(item) {
64539
+ return !!item.data.type && ["selector", "eraser", "laser"].indexOf(item.data.type) < 0 && item.data.role !== "background";
64540
+ }
64391
64541
  onMouseDown(event) {
64392
64542
  this.from = null;
64393
64543
  this.to = null;
@@ -64413,7 +64563,7 @@ var SelectorTool = class extends WhiteboardTool {
64413
64563
  this.elementModel.setPoints([rect.topLeft.x, rect.topLeft.y, rect.size.width, rect.size.height]);
64414
64564
  this.selectElementsModel.clearSelectElementForSelf();
64415
64565
  this.scope.project.activeLayer.children.forEach((item) => {
64416
- if (item.data.type && ["selector", "eraser", "laser"].indexOf(item.data.type) < 0) {
64566
+ if (this.isSelectableItem(item)) {
64417
64567
  if (rect.contains(item.bounds)) {
64418
64568
  this.selectElements.set(item.data.uuid, item.data.ownerId);
64419
64569
  } else {
@@ -64439,7 +64589,7 @@ var SelectorTool = class extends WhiteboardTool {
64439
64589
  return result;
64440
64590
  }, []);
64441
64591
  const hitResult = this.scope.project.hitTest(event.point);
64442
- if (hitResult && hitResult.item.data.uuid) {
64592
+ if (hitResult && hitResult.item.data.uuid && this.isSelectableItem(hitResult.item)) {
64443
64593
  elements.push({
64444
64594
  elementId: hitResult.item.data.uuid,
64445
64595
  ownerId: hitResult.item.data.ownerId
@@ -64966,7 +65116,7 @@ var Editor = class extends EventEmitter5 {
64966
65116
  };
64967
65117
  this.rootView.style.opacity = "0";
64968
65118
  }
64969
- if (target === this.frame) {
65119
+ if (target === this.frame && this.editorConfig?.translatable()) {
64970
65120
  evt.preventDefault();
64971
65121
  this.editMode = "translate";
64972
65122
  this.lastEditPoint = {
@@ -65271,7 +65421,6 @@ var Editor = class extends EventEmitter5 {
65271
65421
  this.shadowContainer.remove();
65272
65422
  this.shadowScope.project.activeLayer.addChild(this.shadowContainer);
65273
65423
  this.targets.forEach((model) => {
65274
- console.log("[][][] translateShadow model", model.root._dEH);
65275
65424
  model.shadow = this.shadowContainer.data.uuid;
65276
65425
  });
65277
65426
  }
@@ -66132,6 +66281,9 @@ var EraserTool = class extends WhiteboardTool {
66132
66281
  this.elementModel.appendPoints([event.point.x, event.point.y]);
66133
66282
  }
66134
66283
  this.scope.project.activeLayer.children.forEach((item) => {
66284
+ if (item.data.role === "background") {
66285
+ return;
66286
+ }
66135
66287
  if (item.data.type && ["selector", "eraser", "laser"].indexOf(item.data.type) < 0 && item.hitTest(event.point, {
66136
66288
  segments: true,
66137
66289
  stroke: true,
@@ -66142,6 +66294,9 @@ var EraserTool = class extends WhiteboardTool {
66142
66294
  }
66143
66295
  });
66144
66296
  this.shadowScope.project.activeLayer.children.forEach((item) => {
66297
+ if (item.data.role === "background") {
66298
+ return;
66299
+ }
66145
66300
  if (item.data.type && ["selector", "eraser", "laser"].indexOf(item.data.type) < 0 && item.hitTest(event.point, {
66146
66301
  segments: true,
66147
66302
  stroke: true,
@@ -66583,16 +66738,7 @@ var IndexedNavigation = class extends EventEmitter11 {
66583
66738
  return this.pageModel.pageList().filter((id) => /^_i_/.test(id));
66584
66739
  }
66585
66740
  get head() {
66586
- const headId = Object.keys(this.list).find((key) => {
66587
- return this.list[key] && this.list[key].prev === "";
66588
- });
66589
- if (!headId) {
66590
- log3("indexed navigation confusion", {
66591
- list: JSON.stringify(this.list)
66592
- }, "error");
66593
- throw new Error("indexed navigation confusion");
66594
- }
66595
- return headId;
66741
+ return this.ensureValidList().head;
66596
66742
  }
66597
66743
  get lastNodeId() {
66598
66744
  let currentId = this.head;
@@ -66612,7 +66758,8 @@ var IndexedNavigation = class extends EventEmitter11 {
66612
66758
  _defineProperty36(this, "list", {});
66613
66759
  _defineProperty36(this, "hasPermission", void 0);
66614
66760
  _defineProperty36(this, "handleIndexedPageMapUpdate", (_evt) => {
66615
- this.list = this.indexedPageMap.get("list");
66761
+ this.list = this.normalizeList(this.indexedPageMap.get("list")) ?? {};
66762
+ this.ensureValidList("update");
66616
66763
  const needRemoveList = this.pageModel.pageList().filter((v) => /^_i_/.test(v) && Object.keys(this.list).indexOf(v) < 0);
66617
66764
  const needAddList = Object.keys(this.list).filter((v) => this.pageModel.pageList().indexOf(v) < 0);
66618
66765
  this.indexedPageMap.doc.transact(() => {
@@ -66645,11 +66792,156 @@ var IndexedNavigation = class extends EventEmitter11 {
66645
66792
  this.indexedPageMap.set("list", this.list);
66646
66793
  this.idPool.add("_i_");
66647
66794
  } else {
66648
- this.list = this.indexedPageMap.get("list");
66795
+ this.list = this.normalizeList(this.indexedPageMap.get("list")) ?? {};
66649
66796
  Object.keys(this.list).forEach((id) => this.idPool.add(id));
66797
+ this.ensureValidList("constructor");
66650
66798
  }
66651
66799
  this.indexedPageMap.observe(this.handleIndexedPageMapUpdate);
66652
66800
  }
66801
+ normalizeList(list) {
66802
+ if (!list || typeof list !== "object" || Array.isArray(list)) {
66803
+ return null;
66804
+ }
66805
+ const nextList = {};
66806
+ for (const [id, node] of Object.entries(list)) {
66807
+ if (!/^_i_/.test(id) || !node || typeof node !== "object") {
66808
+ return null;
66809
+ }
66810
+ const {
66811
+ prev,
66812
+ next
66813
+ } = node;
66814
+ if (typeof prev !== "string" || typeof next !== "string") {
66815
+ return null;
66816
+ }
66817
+ nextList[id] = {
66818
+ prev,
66819
+ next
66820
+ };
66821
+ }
66822
+ return nextList;
66823
+ }
66824
+ validateList(list) {
66825
+ const ids = Object.keys(list);
66826
+ if (ids.length === 0) {
66827
+ return {
66828
+ valid: false,
66829
+ reason: "empty list"
66830
+ };
66831
+ }
66832
+ const heads = ids.filter((id) => list[id].prev === "");
66833
+ if (heads.length !== 1) {
66834
+ return {
66835
+ valid: false,
66836
+ reason: `expected one head, got ${heads.length}`
66837
+ };
66838
+ }
66839
+ for (const id of ids) {
66840
+ const node = list[id];
66841
+ if (node.prev && !list[node.prev]) {
66842
+ return {
66843
+ valid: false,
66844
+ reason: `missing prev node ${node.prev}`
66845
+ };
66846
+ }
66847
+ if (node.next && !list[node.next]) {
66848
+ return {
66849
+ valid: false,
66850
+ reason: `missing next node ${node.next}`
66851
+ };
66852
+ }
66853
+ if (node.prev && list[node.prev].next !== id) {
66854
+ return {
66855
+ valid: false,
66856
+ reason: `prev link mismatch for ${id}`
66857
+ };
66858
+ }
66859
+ if (node.next && list[node.next].prev !== id) {
66860
+ return {
66861
+ valid: false,
66862
+ reason: `next link mismatch for ${id}`
66863
+ };
66864
+ }
66865
+ }
66866
+ const visited = /* @__PURE__ */ new Set();
66867
+ let currentId = heads[0];
66868
+ while (currentId) {
66869
+ if (visited.has(currentId)) {
66870
+ return {
66871
+ valid: false,
66872
+ reason: `cycle at ${currentId}`
66873
+ };
66874
+ }
66875
+ visited.add(currentId);
66876
+ currentId = list[currentId].next;
66877
+ }
66878
+ if (visited.size !== ids.length) {
66879
+ return {
66880
+ valid: false,
66881
+ reason: "detached nodes"
66882
+ };
66883
+ }
66884
+ return {
66885
+ valid: true,
66886
+ head: heads[0]
66887
+ };
66888
+ }
66889
+ createList(ids) {
66890
+ return ids.reduce((list, id, index) => {
66891
+ list[id] = {
66892
+ prev: ids[index - 1] ?? "",
66893
+ next: ids[index + 1] ?? ""
66894
+ };
66895
+ return list;
66896
+ }, {});
66897
+ }
66898
+ repairList(reason) {
66899
+ const pageIds = this.idList;
66900
+ const ids = pageIds.length > 0 ? pageIds : Object.keys(this.list).filter((id) => /^_i_/.test(id));
66901
+ const nextIds = ids.length > 0 ? ids : ["_i_"];
66902
+ const nextList = this.createList(nextIds);
66903
+ log3("indexed navigation recovered", {
66904
+ reason,
66905
+ pageList: JSON.stringify(this.pageModel.pageList()),
66906
+ list: JSON.stringify(this.list),
66907
+ nextList: JSON.stringify(nextList)
66908
+ }, "warn");
66909
+ const apply = () => {
66910
+ for (const id of nextIds) {
66911
+ if (this.pageModel.pageList().indexOf(id) < 0) {
66912
+ this.pageModel.addPage(id);
66913
+ }
66914
+ }
66915
+ this.list = nextList;
66916
+ this.indexedPageMap.set("list", nextList);
66917
+ };
66918
+ if (this.indexedPageMap.doc) {
66919
+ this.indexedPageMap.doc.transact(apply);
66920
+ } else {
66921
+ apply();
66922
+ }
66923
+ nextIds.forEach((id) => this.idPool.add(id));
66924
+ return nextIds[0];
66925
+ }
66926
+ ensureValidList() {
66927
+ let context = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : "read";
66928
+ const normalized = this.normalizeList(this.list);
66929
+ if (!normalized) {
66930
+ return {
66931
+ head: this.repairList(`${context}: invalid list`)
66932
+ };
66933
+ }
66934
+ this.list = normalized;
66935
+ const validation = this.validateList(this.list);
66936
+ if (!validation.valid) {
66937
+ return {
66938
+ head: this.repairList(`${context}: ${validation.reason}`)
66939
+ };
66940
+ }
66941
+ return {
66942
+ head: validation.head
66943
+ };
66944
+ }
66653
66945
  getNextId() {
66654
66946
  const cache = Array.from(this.idPool).filter((id) => this.idList.indexOf(id) < 0);
66655
66947
  if (cache.length > 0) {
@@ -67581,7 +67873,6 @@ var WhiteboardApplication = class _WhiteboardApplication extends AbstractApplica
67581
67873
  this.emitter.emit("elementDeselected", userId);
67582
67874
  return;
67583
67875
  }
67584
- editor.show();
67585
67876
  const targetLayerId = this.userMap(userId).get(WhiteboardKeys.currentPage);
67586
67877
  const selfLayerId = this.userMap(this.userId).get(WhiteboardKeys.currentPage);
67587
67878
  if (targetLayerId !== selfLayerId || !this.layers.has(targetLayerId)) {
@@ -67589,7 +67880,13 @@ var WhiteboardApplication = class _WhiteboardApplication extends AbstractApplica
67589
67880
  }
67590
67881
  const elementModels = elements.map((id) => {
67591
67882
  return this.layers.get(targetLayerId).elementModels.get(id);
67592
- }).filter((v) => !!v);
67883
+ }).filter((model) => !!model && !model.isBackground);
67884
+ if (elementModels.length === 0) {
67885
+ editor.hidden();
67886
+ this.emitter.emit("elementDeselected", userId);
67887
+ return;
67888
+ }
67889
+ editor.show();
67593
67890
  editor.setTargets(elementModels);
67594
67891
  if (elementModels.length === 1) {
67595
67892
  const model = elementModels[0];
@@ -67781,14 +68078,17 @@ var WhiteboardApplication = class _WhiteboardApplication extends AbstractApplica
67781
68078
  this.camera.resetViewMatrixToMain();
67782
68079
  }
67783
68080
  };
67784
- this.emitter.insertImage = (src, pageId) => {
68081
+ this.emitter.insertImage = (src, options) => {
67785
68082
  if (!/https/.test(src)) {
67786
68083
  log4("[@netless/forge-whiteboard] invalid image url, src needs to be in the HTTPS protocol.", {
67787
68084
  src
67788
68085
  }, "warn");
67789
68086
  return;
67790
68087
  }
67791
- let targetPageId = pageId;
68088
+ const normalizedOptions = typeof options === "string" ? {
68089
+ pageId: options
68090
+ } : options ?? {};
68091
+ let targetPageId = normalizedOptions.pageId;
67792
68092
  if (!targetPageId) {
67793
68093
  targetPageId = this.pageModel.getCurrentPage(this.userManager.selfId);
67794
68094
  }
@@ -67796,13 +68096,16 @@ var WhiteboardApplication = class _WhiteboardApplication extends AbstractApplica
67796
68096
  log4("[@netless/forge-whiteboard] page not found", {}, "warn");
67797
68097
  return;
67798
68098
  }
67799
- this.layers.get(targetPageId)?.createImage(src);
68099
+ this.layers.get(targetPageId)?.createImage(src, normalizedOptions.fit ?? "legacy", normalizedOptions.role ?? "normal");
67800
68100
  };
67801
68101
  this.emitter.removeElement = (pageId, elementId) => {
67802
68102
  if (!this.layers.has(pageId)) {
67803
68103
  log4("[@netless/forge-whiteboard] page not found", {}, "warn");
67804
68104
  return;
67805
68105
  }
68106
+ if (this.layers.get(pageId)?.isBackgroundElement(elementId)) {
68107
+ return;
68108
+ }
67806
68109
  this.layers.get(pageId)?.removeElementItem(elementId);
67807
68110
  };
67808
68111
  this.emitter.getViewModel = (userId) => {
@@ -67853,7 +68156,11 @@ var WhiteboardApplication = class _WhiteboardApplication extends AbstractApplica
67853
68156
  if (model) {
67854
68157
  if (model.elements.doc) {
67855
68158
  model.elements.doc.transact(() => {
67856
- model.elements.clear();
68159
+ for (const key of Array.from(model.elements.keys())) {
68160
+ if (!model.isBackgroundElement(key)) {
68161
+ model.elements.delete(key);
68162
+ }
68163
+ }
67857
68164
  }, elementsUndoOrigin);
67858
68165
  } else {
67859
68166
  model.elementModels.clear();
@@ -68265,7 +68572,9 @@ var WhiteboardApplication = class _WhiteboardApplication extends AbstractApplica
68265
68572
  const at = this.findElementIndex(element.data.index, parent);
68266
68573
  for (let i = at; i >= 0; i--) {
68267
68574
  const child = children[i - 1];
68268
- if (!child || child.data.index < element.data.index || child.data.uuid < element.data.uuid) {
68575
+ const childRole = child?.data.role === "background" ? 0 : 1;
68576
+ const elementRole = element.data.role === "background" ? 0 : 1;
68577
+ if (!child || childRole < elementRole || childRole === elementRole && child.data.index < element.data.index || childRole === elementRole && child.data.index === element.data.index && child.data.uuid < element.data.uuid) {
68269
68578
  parent.insertChild(i, element);
68270
68579
  break;
68271
68580
  }