@knotx/plugins-canvas 0.3.5 → 0.3.7

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.cjs CHANGED
@@ -7,6 +7,79 @@ const lodashEs = require('lodash-es');
7
7
  const react = require('react');
8
8
  const reactZoomPanPinch = require('react-zoom-pan-pinch');
9
9
 
10
+ function calculateTransform({
11
+ node,
12
+ container,
13
+ transform,
14
+ scale,
15
+ block = "nearest",
16
+ inline = "nearest",
17
+ offset = 0
18
+ }) {
19
+ var _a, _b, _c, _d, _e, _f;
20
+ const nodeX = node.position.x;
21
+ const nodeY = node.position.y;
22
+ const nodeWidth = (_b = (_a = node.measured) == null ? void 0 : _a.width) != null ? _b : 0;
23
+ const nodeHeight = (_d = (_c = node.measured) == null ? void 0 : _c.height) != null ? _d : 0;
24
+ const viewportWidth = container.width;
25
+ const viewportHeight = container.height;
26
+ let positionX = -transform.positionX;
27
+ let positionY = -transform.positionY;
28
+ const offsetX = typeof offset === "number" ? offset : (_e = offset.x) != null ? _e : 0;
29
+ const offsetY = typeof offset === "number" ? offset : (_f = offset.y) != null ? _f : 0;
30
+ switch (inline) {
31
+ case "center":
32
+ positionX = (nodeX + nodeWidth / 2) * scale - viewportWidth / 2;
33
+ break;
34
+ case "start":
35
+ positionX = nodeX * scale - offsetX;
36
+ break;
37
+ case "end":
38
+ positionX = (nodeX + nodeWidth) * scale - viewportWidth + offsetX;
39
+ break;
40
+ case "nearest": {
41
+ const nodeRight = (nodeX + nodeWidth) * scale;
42
+ const nodeLeft = nodeX * scale;
43
+ const currentLeft = -transform.positionX;
44
+ const currentRight = currentLeft + viewportWidth;
45
+ if (nodeRight > currentRight) {
46
+ positionX = nodeRight - viewportWidth + offsetX;
47
+ } else if (nodeLeft < currentLeft) {
48
+ positionX = nodeLeft - offsetX;
49
+ }
50
+ break;
51
+ }
52
+ }
53
+ switch (block) {
54
+ case "center":
55
+ positionY = (nodeY + nodeHeight / 2) * scale - viewportHeight / 2;
56
+ break;
57
+ case "start":
58
+ positionY = nodeY * scale - offsetY;
59
+ break;
60
+ case "end":
61
+ positionY = (nodeY + nodeHeight) * scale - viewportHeight + offsetY;
62
+ break;
63
+ case "nearest": {
64
+ const nodeBottom = (nodeY + nodeHeight) * scale;
65
+ const nodeTop = nodeY * scale;
66
+ const currentTop = -transform.positionY;
67
+ const currentBottom = currentTop + viewportHeight;
68
+ if (nodeBottom > currentBottom) {
69
+ positionY = nodeBottom - viewportHeight + offsetY;
70
+ } else if (nodeTop < currentTop) {
71
+ positionY = nodeTop - offsetY;
72
+ }
73
+ break;
74
+ }
75
+ }
76
+ return {
77
+ scale,
78
+ positionX,
79
+ positionY
80
+ };
81
+ }
82
+
10
83
  var __create = Object.create;
11
84
  var __defProp = Object.defineProperty;
12
85
  var __defProps = Object.defineProperties;
@@ -75,8 +148,8 @@ var __privateIn = (member, obj) => Object(obj) !== obj ? __typeError('Cannot use
75
148
  var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
76
149
  var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
77
150
  var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
78
- var _init_dec, _render_dec, _setTransform_dec, _zoomOut_dec, _zoomIn_dec, _scrollNodeIntoView_dec, _removeListener_dec, _addListener_dec, _interaction_dec, _container_dec, _getNode_dec, _edgeScroll_dec, _transform_dec, _ref_dec, _a, _init;
79
- class Canvas extends (_a = core.BasePlugin, _ref_dec = [decorators.register("ref")], _transform_dec = [decorators.register("transform")], _edgeScroll_dec = [decorators.register("edgeScroll")], _getNode_dec = [decorators.inject.getNode()], _container_dec = [decorators.inject.container()], _interaction_dec = [decorators.inject.interaction()], _addListener_dec = [decorators.register("addListener")], _removeListener_dec = [decorators.register("removeListener")], _scrollNodeIntoView_dec = [decorators.tool("Scroll node into viewport center", {
151
+ var _init_dec, _render_dec, _setTransform_dec, _zoomOut_dec, _zoomIn_dec, _scrollNodeIntoView_dec, _removeListener_dec, _addListener_dec, _interaction_dec, _container_dec, _getNode_dec, _edgeScroll_dec, _updateContentSize_dec, _contentSize_dec, _transform_dec, _ref_dec, _a, _init;
152
+ class Canvas extends (_a = core.BasePlugin, _ref_dec = [decorators.register("ref")], _transform_dec = [decorators.register("transform")], _contentSize_dec = [decorators.register("contentSize")], _updateContentSize_dec = [decorators.register("updateContentSize")], _edgeScroll_dec = [decorators.register("edgeScroll")], _getNode_dec = [decorators.inject.getNode()], _container_dec = [decorators.inject.container()], _interaction_dec = [decorators.inject.interaction()], _addListener_dec = [decorators.register("addListener")], _removeListener_dec = [decorators.register("removeListener")], _scrollNodeIntoView_dec = [decorators.tool("Scroll node into view", {
80
153
  type: "object",
81
154
  properties: {
82
155
  nodeId: { type: "string" },
@@ -122,7 +195,11 @@ class Canvas extends (_a = core.BasePlugin, _ref_dec = [decorators.register("ref
122
195
  __publicField(this, "name", "canvas");
123
196
  __publicField(this, "ref", __runInitializers(_init, 8, this, null)), __runInitializers(_init, 11, this);
124
197
  __publicField(this, "transform", __runInitializers(_init, 12, this)), __runInitializers(_init, 15, this);
125
- __publicField(this, "edgeScroll", __runInitializers(_init, 16, this, {
198
+ __publicField(this, "contentSize", __runInitializers(_init, 16, this)), __runInitializers(_init, 19, this);
199
+ __publicField(this, "updateContentSize", __runInitializers(_init, 20, this, (contentSize) => {
200
+ this.contentSize = contentSize;
201
+ })), __runInitializers(_init, 23, this);
202
+ __publicField(this, "edgeScroll", __runInitializers(_init, 24, this, {
126
203
  config: {
127
204
  enabled: false,
128
205
  edgeSize: 50,
@@ -136,22 +213,22 @@ class Canvas extends (_a = core.BasePlugin, _ref_dec = [decorators.register("ref
136
213
  this.edgeScrollAnimationFrame = null;
137
214
  }
138
215
  }
139
- })), __runInitializers(_init, 19, this);
140
- __publicField(this, "getNode", __runInitializers(_init, 20, this)), __runInitializers(_init, 23, this);
141
- __publicField(this, "container", __runInitializers(_init, 24, this)), __runInitializers(_init, 27, this);
142
- __publicField(this, "interaction", __runInitializers(_init, 28, this)), __runInitializers(_init, 31, this);
216
+ })), __runInitializers(_init, 27, this);
217
+ __publicField(this, "getNode", __runInitializers(_init, 28, this)), __runInitializers(_init, 31, this);
218
+ __publicField(this, "container", __runInitializers(_init, 32, this)), __runInitializers(_init, 35, this);
219
+ __publicField(this, "interaction", __runInitializers(_init, 36, this)), __runInitializers(_init, 39, this);
143
220
  __publicField(this, "listeners", {
144
221
  click: /* @__PURE__ */ new Set(),
145
222
  contextmenu: /* @__PURE__ */ new Set()
146
223
  });
147
224
  __publicField(this, "edgeScrollAnimationFrame", null);
148
225
  __publicField(this, "mousePosition", null);
149
- __publicField(this, "addListener", __runInitializers(_init, 32, this, (type, listener) => {
226
+ __publicField(this, "addListener", __runInitializers(_init, 40, this, (type, listener) => {
150
227
  this.listeners[type].add(listener);
151
- })), __runInitializers(_init, 35, this);
152
- __publicField(this, "removeListener", __runInitializers(_init, 36, this, (type, listener) => {
228
+ })), __runInitializers(_init, 43, this);
229
+ __publicField(this, "removeListener", __runInitializers(_init, 44, this, (type, listener) => {
153
230
  this.listeners[type].delete(listener);
154
- })), __runInitializers(_init, 39, this);
231
+ })), __runInitializers(_init, 47, this);
155
232
  __publicField(this, "handleEdgeScroll", () => {
156
233
  if (!this.edgeScroll.config.enabled || !this.mousePosition || !this.ref) {
157
234
  return;
@@ -193,69 +270,22 @@ class Canvas extends (_a = core.BasePlugin, _ref_dec = [decorators.register("ref
193
270
  this.edgeScrollAnimationFrame = requestAnimationFrame(this.handleEdgeScroll);
194
271
  });
195
272
  }
196
- scrollNodeIntoView({ nodeId, scale = this.transform.scale, block = "nearest", inline = "nearest", offset = 0, animationTime }) {
197
- var _a2, _b, _c, _d, _e, _f, _g;
273
+ scrollNodeIntoView({ nodeId, scale = this.transform.scale, block, inline, offset, animationTime }) {
274
+ var _a2;
198
275
  const node = nodeId && this.getNode({ id: nodeId });
199
276
  if (!node) {
200
277
  return;
201
278
  }
202
- const nodeX = node.position.x;
203
- const nodeY = node.position.y;
204
- const nodeWidth = (_b = (_a2 = node.measured) == null ? void 0 : _a2.width) != null ? _b : 0;
205
- const nodeHeight = (_d = (_c = node.measured) == null ? void 0 : _c.height) != null ? _d : 0;
206
- const viewportWidth = this.container.width;
207
- const viewportHeight = this.container.height;
208
- let positionX = -this.transform.positionX;
209
- let positionY = -this.transform.positionY;
210
- const offsetX = typeof offset === "number" ? offset : (_e = offset.x) != null ? _e : 0;
211
- const offsetY = typeof offset === "number" ? offset : (_f = offset.y) != null ? _f : 0;
212
- switch (inline) {
213
- case "center":
214
- positionX = (nodeX + nodeWidth / 2) * scale - viewportWidth / 2;
215
- break;
216
- case "start":
217
- positionX = nodeX * scale - offsetX;
218
- break;
219
- case "end":
220
- positionX = (nodeX + nodeWidth) * scale - viewportWidth + offsetX;
221
- break;
222
- case "nearest": {
223
- const nodeRight = (nodeX + nodeWidth) * scale;
224
- const nodeLeft = nodeX * scale;
225
- const currentLeft = -this.transform.positionX;
226
- const currentRight = currentLeft + viewportWidth;
227
- if (nodeRight > currentRight) {
228
- positionX = nodeRight - viewportWidth + offsetX;
229
- } else if (nodeLeft < currentLeft) {
230
- positionX = nodeLeft - offsetX;
231
- }
232
- break;
233
- }
234
- }
235
- switch (block) {
236
- case "center":
237
- positionY = (nodeY + nodeHeight / 2) * scale - viewportHeight / 2;
238
- break;
239
- case "start":
240
- positionY = nodeY * scale - offsetY;
241
- break;
242
- case "end":
243
- positionY = (nodeY + nodeHeight) * scale - viewportHeight + offsetY;
244
- break;
245
- case "nearest": {
246
- const nodeBottom = (nodeY + nodeHeight) * scale;
247
- const nodeTop = nodeY * scale;
248
- const currentTop = -this.transform.positionY;
249
- const currentBottom = currentTop + viewportHeight;
250
- if (nodeBottom > currentBottom) {
251
- positionY = nodeBottom - viewportHeight + offsetY;
252
- } else if (nodeTop < currentTop) {
253
- positionY = nodeTop - offsetY;
254
- }
255
- break;
256
- }
257
- }
258
- (_g = this.ref) == null ? void 0 : _g.setTransform(-positionX, -positionY, scale, animationTime);
279
+ const { positionX, positionY, scale: newScale } = calculateTransform({
280
+ node,
281
+ container: this.container,
282
+ transform: this.transform,
283
+ scale,
284
+ block,
285
+ inline,
286
+ offset
287
+ });
288
+ (_a2 = this.ref) == null ? void 0 : _a2.setTransform(-positionX, -positionY, newScale, animationTime);
259
289
  }
260
290
  zoomIn({ step = 0.1, animationTime }) {
261
291
  var _a2;
@@ -270,15 +300,36 @@ class Canvas extends (_a = core.BasePlugin, _ref_dec = [decorators.register("ref
270
300
  (_a2 = this.ref) == null ? void 0 : _a2.setTransform(positionX != null ? positionX : this.transform.positionX, positionY != null ? positionY : this.transform.positionY, scale != null ? scale : this.transform.scale, animationTime);
271
301
  }
272
302
  render({ children } = { children: null }) {
273
- const [transformRef, setTransformRef] = react.useReducer((prevRef, ref) => {
274
- this.ref = ref;
275
- if (!prevRef && ref.instance.isInitialized && this.config.defaultLocated) {
276
- this.scrollNodeIntoView(__spreadValues({
277
- inline: "center",
278
- block: "center",
279
- scale: 1,
280
- animationTime: 0
281
- }, this.config.defaultLocated));
303
+ var _a2, _b, _c, _d;
304
+ const defaultTransform = react.useMemo(() => {
305
+ const defaultLocated = this.config.defaultLocated;
306
+ if (!(defaultLocated == null ? void 0 : defaultLocated.nodeId)) {
307
+ return this.transform;
308
+ }
309
+ const node = this.getNode({ id: defaultLocated.nodeId });
310
+ if (!node) {
311
+ return this.transform;
312
+ }
313
+ defaultLocated.inline || (defaultLocated.inline = "center");
314
+ defaultLocated.block || (defaultLocated.block = "center");
315
+ defaultLocated.scale || (defaultLocated.scale = this.transform.scale);
316
+ const { positionX, positionY, scale: newScale } = calculateTransform(__spreadValues({
317
+ node,
318
+ container: this.container,
319
+ transform: this.transform
320
+ }, defaultLocated));
321
+ const newTransform = {
322
+ previousScale: this.transform.scale,
323
+ scale: newScale,
324
+ positionX: -positionX,
325
+ positionY: -positionY
326
+ };
327
+ this.transform = newTransform;
328
+ return newTransform;
329
+ }, []);
330
+ const [transformRef, setTransformRef] = react.useReducer((_, ref) => {
331
+ if (this.ref !== ref) {
332
+ this.ref = ref;
282
333
  }
283
334
  return ref;
284
335
  }, null);
@@ -297,31 +348,33 @@ class Canvas extends (_a = core.BasePlugin, _ref_dec = [decorators.register("ref
297
348
  }
298
349
  return [fixedLayers2, childrenLayers2];
299
350
  }, [children]);
300
- react.useEffect(() => {
351
+ react.useLayoutEffect(() => {
301
352
  const wrapperElement = transformRef == null ? void 0 : transformRef.instance.wrapperComponent;
302
- if (!wrapperElement) {
303
- return;
353
+ if (wrapperElement) {
354
+ Object.defineProperty(wrapperElement, "scrollTop", {
355
+ get() {
356
+ return -transformRef.instance.transformState.positionY;
357
+ },
358
+ set(value) {
359
+ transformRef.instance.setTransformState(transformRef.instance.transformState.scale, transformRef.instance.transformState.positionX, -value);
360
+ }
361
+ });
362
+ Object.defineProperty(wrapperElement, "scrollLeft", {
363
+ get() {
364
+ return -transformRef.instance.transformState.positionX;
365
+ },
366
+ set(value) {
367
+ transformRef.instance.setTransformState(transformRef.instance.transformState.scale, -value, transformRef.instance.transformState.positionY);
368
+ }
369
+ });
304
370
  }
305
- Object.defineProperty(wrapperElement, "scrollTop", {
306
- get() {
307
- return -transformRef.instance.transformState.positionY;
308
- },
309
- set(value) {
310
- transformRef.instance.setTransformState(transformRef.instance.transformState.scale, transformRef.instance.transformState.positionX, -value);
311
- }
312
- });
313
- Object.defineProperty(wrapperElement, "scrollLeft", {
314
- get() {
315
- return -transformRef.instance.transformState.positionX;
316
- },
317
- set(value) {
318
- transformRef.instance.setTransformState(transformRef.instance.transformState.scale, -value, transformRef.instance.transformState.positionY);
319
- }
320
- });
321
371
  let frame;
322
372
  return transformRef == null ? void 0 : transformRef.instance.onChange((ref) => {
323
373
  cancelAnimationFrame(frame);
324
374
  frame = requestAnimationFrame(() => {
375
+ if (lodashEs.isEqual(this.transform, ref.state)) {
376
+ return;
377
+ }
325
378
  this.transform = __spreadValues({}, ref.state);
326
379
  });
327
380
  });
@@ -371,6 +424,9 @@ class Canvas extends (_a = core.BasePlugin, _ref_dec = [decorators.register("ref
371
424
  reactZoomPanPinch.TransformWrapper,
372
425
  __spreadProps(__spreadValues({}, this.config), {
373
426
  ref: setTransformRef,
427
+ initialPositionX: defaultTransform.positionX,
428
+ initialPositionY: defaultTransform.positionY,
429
+ initialScale: defaultTransform.scale,
374
430
  children: [
375
431
  /* @__PURE__ */ jsxRuntime.jsx(react.Fragment, { children: fixedLayers }),
376
432
  /* @__PURE__ */ jsxRuntime.jsx(react.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -392,8 +448,8 @@ class Canvas extends (_a = core.BasePlugin, _ref_dec = [decorators.register("ref
392
448
  contentClass: core.bem(this.name, "content"),
393
449
  contentStyle: {
394
450
  position: "relative",
395
- width: "100%",
396
- height: "100%",
451
+ width: (_b = (_a2 = this.contentSize) == null ? void 0 : _a2.width) != null ? _b : "100%",
452
+ height: (_d = (_c = this.contentSize) == null ? void 0 : _c.height) != null ? _d : "100%",
397
453
  willChange: "auto"
398
454
  },
399
455
  children: childrenLayers
@@ -436,6 +492,8 @@ __decorateElement(_init, 1, "render", _render_dec, Canvas);
436
492
  __decorateElement(_init, 1, "init", _init_dec, Canvas);
437
493
  __decorateElement(_init, 5, "ref", _ref_dec, Canvas);
438
494
  __decorateElement(_init, 5, "transform", _transform_dec, Canvas);
495
+ __decorateElement(_init, 5, "contentSize", _contentSize_dec, Canvas);
496
+ __decorateElement(_init, 5, "updateContentSize", _updateContentSize_dec, Canvas);
439
497
  __decorateElement(_init, 5, "edgeScroll", _edgeScroll_dec, Canvas);
440
498
  __decorateElement(_init, 5, "getNode", _getNode_dec, Canvas);
441
499
  __decorateElement(_init, 5, "container", _container_dec, Canvas);
package/dist/index.d.cts CHANGED
@@ -16,6 +16,10 @@ type CanvasConfig = ReactZoomPanPinchProps & {
16
16
  animationTime?: number;
17
17
  };
18
18
  };
19
+ interface CanvasContentSize {
20
+ width: number;
21
+ height: number;
22
+ }
19
23
  type CanvasTransformState = ReactZoomPanPinchState;
20
24
  type CanvasRef = ReactZoomPanPinchContentRef;
21
25
  interface EdgeScrollConfig {
@@ -29,6 +33,8 @@ declare module '@knotx/core' {
29
33
  canvas: {
30
34
  ref: CanvasRef | null;
31
35
  transform: CanvasTransformState;
36
+ contentSize: CanvasContentSize | undefined;
37
+ updateContentSize: (contentSize: CanvasContentSize) => void;
32
38
  addListener: (event: CanvasEventType, listener: CanvasEventListener) => void;
33
39
  removeListener: (event: CanvasEventType, listener: CanvasEventListener) => void;
34
40
  edgeScroll: {
@@ -74,6 +80,8 @@ declare class Canvas extends BasePlugin<'canvas', CanvasConfig> {
74
80
  name: "canvas";
75
81
  ref: CanvasRef | null;
76
82
  transform: CanvasTransformState;
83
+ contentSize: CanvasContentSize | undefined;
84
+ updateContentSize: (contentSize: CanvasContentSize) => void;
77
85
  edgeScroll: {
78
86
  config: EdgeScrollConfig;
79
87
  setConfig: (config: Partial<EdgeScrollConfig>) => void;
@@ -167,4 +175,4 @@ declare class Canvas extends BasePlugin<'canvas', CanvasConfig> {
167
175
  private isCanvasEvent;
168
176
  }
169
177
 
170
- export { Canvas, type CanvasConfig, type CanvasEventListener, type CanvasEventType, type CanvasRef, type CanvasTransformState, type EdgeScrollConfig };
178
+ export { Canvas, type CanvasConfig, type CanvasContentSize, type CanvasEventListener, type CanvasEventType, type CanvasRef, type CanvasTransformState, type EdgeScrollConfig };
package/dist/index.d.mts CHANGED
@@ -16,6 +16,10 @@ type CanvasConfig = ReactZoomPanPinchProps & {
16
16
  animationTime?: number;
17
17
  };
18
18
  };
19
+ interface CanvasContentSize {
20
+ width: number;
21
+ height: number;
22
+ }
19
23
  type CanvasTransformState = ReactZoomPanPinchState;
20
24
  type CanvasRef = ReactZoomPanPinchContentRef;
21
25
  interface EdgeScrollConfig {
@@ -29,6 +33,8 @@ declare module '@knotx/core' {
29
33
  canvas: {
30
34
  ref: CanvasRef | null;
31
35
  transform: CanvasTransformState;
36
+ contentSize: CanvasContentSize | undefined;
37
+ updateContentSize: (contentSize: CanvasContentSize) => void;
32
38
  addListener: (event: CanvasEventType, listener: CanvasEventListener) => void;
33
39
  removeListener: (event: CanvasEventType, listener: CanvasEventListener) => void;
34
40
  edgeScroll: {
@@ -74,6 +80,8 @@ declare class Canvas extends BasePlugin<'canvas', CanvasConfig> {
74
80
  name: "canvas";
75
81
  ref: CanvasRef | null;
76
82
  transform: CanvasTransformState;
83
+ contentSize: CanvasContentSize | undefined;
84
+ updateContentSize: (contentSize: CanvasContentSize) => void;
77
85
  edgeScroll: {
78
86
  config: EdgeScrollConfig;
79
87
  setConfig: (config: Partial<EdgeScrollConfig>) => void;
@@ -167,4 +175,4 @@ declare class Canvas extends BasePlugin<'canvas', CanvasConfig> {
167
175
  private isCanvasEvent;
168
176
  }
169
177
 
170
- export { Canvas, type CanvasConfig, type CanvasEventListener, type CanvasEventType, type CanvasRef, type CanvasTransformState, type EdgeScrollConfig };
178
+ export { Canvas, type CanvasConfig, type CanvasContentSize, type CanvasEventListener, type CanvasEventType, type CanvasRef, type CanvasTransformState, type EdgeScrollConfig };
package/dist/index.d.ts CHANGED
@@ -16,6 +16,10 @@ type CanvasConfig = ReactZoomPanPinchProps & {
16
16
  animationTime?: number;
17
17
  };
18
18
  };
19
+ interface CanvasContentSize {
20
+ width: number;
21
+ height: number;
22
+ }
19
23
  type CanvasTransformState = ReactZoomPanPinchState;
20
24
  type CanvasRef = ReactZoomPanPinchContentRef;
21
25
  interface EdgeScrollConfig {
@@ -29,6 +33,8 @@ declare module '@knotx/core' {
29
33
  canvas: {
30
34
  ref: CanvasRef | null;
31
35
  transform: CanvasTransformState;
36
+ contentSize: CanvasContentSize | undefined;
37
+ updateContentSize: (contentSize: CanvasContentSize) => void;
32
38
  addListener: (event: CanvasEventType, listener: CanvasEventListener) => void;
33
39
  removeListener: (event: CanvasEventType, listener: CanvasEventListener) => void;
34
40
  edgeScroll: {
@@ -74,6 +80,8 @@ declare class Canvas extends BasePlugin<'canvas', CanvasConfig> {
74
80
  name: "canvas";
75
81
  ref: CanvasRef | null;
76
82
  transform: CanvasTransformState;
83
+ contentSize: CanvasContentSize | undefined;
84
+ updateContentSize: (contentSize: CanvasContentSize) => void;
77
85
  edgeScroll: {
78
86
  config: EdgeScrollConfig;
79
87
  setConfig: (config: Partial<EdgeScrollConfig>) => void;
@@ -167,4 +175,4 @@ declare class Canvas extends BasePlugin<'canvas', CanvasConfig> {
167
175
  private isCanvasEvent;
168
176
  }
169
177
 
170
- export { Canvas, type CanvasConfig, type CanvasEventListener, type CanvasEventType, type CanvasRef, type CanvasTransformState, type EdgeScrollConfig };
178
+ export { Canvas, type CanvasConfig, type CanvasContentSize, type CanvasEventListener, type CanvasEventType, type CanvasRef, type CanvasTransformState, type EdgeScrollConfig };
package/dist/index.js CHANGED
@@ -1,10 +1,83 @@
1
1
  import { jsxs, jsx } from '@knotx/jsx/jsx-runtime';
2
2
  import { Layer, InteractionPriority, bem, BasePlugin } from '@knotx/core';
3
3
  import { register, inject, tool, layer, OnInit } from '@knotx/decorators';
4
- import { merge } from 'lodash-es';
5
- import { useReducer, useMemo, useEffect, useCallback, Fragment } from 'react';
4
+ import { isEqual, merge } from 'lodash-es';
5
+ import { useMemo, useReducer, useLayoutEffect, useCallback, Fragment } from 'react';
6
6
  import { TransformWrapper, TransformComponent } from 'react-zoom-pan-pinch';
7
7
 
8
+ function calculateTransform({
9
+ node,
10
+ container,
11
+ transform,
12
+ scale,
13
+ block = "nearest",
14
+ inline = "nearest",
15
+ offset = 0
16
+ }) {
17
+ var _a, _b, _c, _d, _e, _f;
18
+ const nodeX = node.position.x;
19
+ const nodeY = node.position.y;
20
+ const nodeWidth = (_b = (_a = node.measured) == null ? void 0 : _a.width) != null ? _b : 0;
21
+ const nodeHeight = (_d = (_c = node.measured) == null ? void 0 : _c.height) != null ? _d : 0;
22
+ const viewportWidth = container.width;
23
+ const viewportHeight = container.height;
24
+ let positionX = -transform.positionX;
25
+ let positionY = -transform.positionY;
26
+ const offsetX = typeof offset === "number" ? offset : (_e = offset.x) != null ? _e : 0;
27
+ const offsetY = typeof offset === "number" ? offset : (_f = offset.y) != null ? _f : 0;
28
+ switch (inline) {
29
+ case "center":
30
+ positionX = (nodeX + nodeWidth / 2) * scale - viewportWidth / 2;
31
+ break;
32
+ case "start":
33
+ positionX = nodeX * scale - offsetX;
34
+ break;
35
+ case "end":
36
+ positionX = (nodeX + nodeWidth) * scale - viewportWidth + offsetX;
37
+ break;
38
+ case "nearest": {
39
+ const nodeRight = (nodeX + nodeWidth) * scale;
40
+ const nodeLeft = nodeX * scale;
41
+ const currentLeft = -transform.positionX;
42
+ const currentRight = currentLeft + viewportWidth;
43
+ if (nodeRight > currentRight) {
44
+ positionX = nodeRight - viewportWidth + offsetX;
45
+ } else if (nodeLeft < currentLeft) {
46
+ positionX = nodeLeft - offsetX;
47
+ }
48
+ break;
49
+ }
50
+ }
51
+ switch (block) {
52
+ case "center":
53
+ positionY = (nodeY + nodeHeight / 2) * scale - viewportHeight / 2;
54
+ break;
55
+ case "start":
56
+ positionY = nodeY * scale - offsetY;
57
+ break;
58
+ case "end":
59
+ positionY = (nodeY + nodeHeight) * scale - viewportHeight + offsetY;
60
+ break;
61
+ case "nearest": {
62
+ const nodeBottom = (nodeY + nodeHeight) * scale;
63
+ const nodeTop = nodeY * scale;
64
+ const currentTop = -transform.positionY;
65
+ const currentBottom = currentTop + viewportHeight;
66
+ if (nodeBottom > currentBottom) {
67
+ positionY = nodeBottom - viewportHeight + offsetY;
68
+ } else if (nodeTop < currentTop) {
69
+ positionY = nodeTop - offsetY;
70
+ }
71
+ break;
72
+ }
73
+ }
74
+ return {
75
+ scale,
76
+ positionX,
77
+ positionY
78
+ };
79
+ }
80
+
8
81
  var __create = Object.create;
9
82
  var __defProp = Object.defineProperty;
10
83
  var __defProps = Object.defineProperties;
@@ -73,8 +146,8 @@ var __privateIn = (member, obj) => Object(obj) !== obj ? __typeError('Cannot use
73
146
  var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
74
147
  var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
75
148
  var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
76
- var _init_dec, _render_dec, _setTransform_dec, _zoomOut_dec, _zoomIn_dec, _scrollNodeIntoView_dec, _removeListener_dec, _addListener_dec, _interaction_dec, _container_dec, _getNode_dec, _edgeScroll_dec, _transform_dec, _ref_dec, _a, _init;
77
- class Canvas extends (_a = BasePlugin, _ref_dec = [register("ref")], _transform_dec = [register("transform")], _edgeScroll_dec = [register("edgeScroll")], _getNode_dec = [inject.getNode()], _container_dec = [inject.container()], _interaction_dec = [inject.interaction()], _addListener_dec = [register("addListener")], _removeListener_dec = [register("removeListener")], _scrollNodeIntoView_dec = [tool("Scroll node into viewport center", {
149
+ var _init_dec, _render_dec, _setTransform_dec, _zoomOut_dec, _zoomIn_dec, _scrollNodeIntoView_dec, _removeListener_dec, _addListener_dec, _interaction_dec, _container_dec, _getNode_dec, _edgeScroll_dec, _updateContentSize_dec, _contentSize_dec, _transform_dec, _ref_dec, _a, _init;
150
+ class Canvas extends (_a = BasePlugin, _ref_dec = [register("ref")], _transform_dec = [register("transform")], _contentSize_dec = [register("contentSize")], _updateContentSize_dec = [register("updateContentSize")], _edgeScroll_dec = [register("edgeScroll")], _getNode_dec = [inject.getNode()], _container_dec = [inject.container()], _interaction_dec = [inject.interaction()], _addListener_dec = [register("addListener")], _removeListener_dec = [register("removeListener")], _scrollNodeIntoView_dec = [tool("Scroll node into view", {
78
151
  type: "object",
79
152
  properties: {
80
153
  nodeId: { type: "string" },
@@ -120,7 +193,11 @@ class Canvas extends (_a = BasePlugin, _ref_dec = [register("ref")], _transform_
120
193
  __publicField(this, "name", "canvas");
121
194
  __publicField(this, "ref", __runInitializers(_init, 8, this, null)), __runInitializers(_init, 11, this);
122
195
  __publicField(this, "transform", __runInitializers(_init, 12, this)), __runInitializers(_init, 15, this);
123
- __publicField(this, "edgeScroll", __runInitializers(_init, 16, this, {
196
+ __publicField(this, "contentSize", __runInitializers(_init, 16, this)), __runInitializers(_init, 19, this);
197
+ __publicField(this, "updateContentSize", __runInitializers(_init, 20, this, (contentSize) => {
198
+ this.contentSize = contentSize;
199
+ })), __runInitializers(_init, 23, this);
200
+ __publicField(this, "edgeScroll", __runInitializers(_init, 24, this, {
124
201
  config: {
125
202
  enabled: false,
126
203
  edgeSize: 50,
@@ -134,22 +211,22 @@ class Canvas extends (_a = BasePlugin, _ref_dec = [register("ref")], _transform_
134
211
  this.edgeScrollAnimationFrame = null;
135
212
  }
136
213
  }
137
- })), __runInitializers(_init, 19, this);
138
- __publicField(this, "getNode", __runInitializers(_init, 20, this)), __runInitializers(_init, 23, this);
139
- __publicField(this, "container", __runInitializers(_init, 24, this)), __runInitializers(_init, 27, this);
140
- __publicField(this, "interaction", __runInitializers(_init, 28, this)), __runInitializers(_init, 31, this);
214
+ })), __runInitializers(_init, 27, this);
215
+ __publicField(this, "getNode", __runInitializers(_init, 28, this)), __runInitializers(_init, 31, this);
216
+ __publicField(this, "container", __runInitializers(_init, 32, this)), __runInitializers(_init, 35, this);
217
+ __publicField(this, "interaction", __runInitializers(_init, 36, this)), __runInitializers(_init, 39, this);
141
218
  __publicField(this, "listeners", {
142
219
  click: /* @__PURE__ */ new Set(),
143
220
  contextmenu: /* @__PURE__ */ new Set()
144
221
  });
145
222
  __publicField(this, "edgeScrollAnimationFrame", null);
146
223
  __publicField(this, "mousePosition", null);
147
- __publicField(this, "addListener", __runInitializers(_init, 32, this, (type, listener) => {
224
+ __publicField(this, "addListener", __runInitializers(_init, 40, this, (type, listener) => {
148
225
  this.listeners[type].add(listener);
149
- })), __runInitializers(_init, 35, this);
150
- __publicField(this, "removeListener", __runInitializers(_init, 36, this, (type, listener) => {
226
+ })), __runInitializers(_init, 43, this);
227
+ __publicField(this, "removeListener", __runInitializers(_init, 44, this, (type, listener) => {
151
228
  this.listeners[type].delete(listener);
152
- })), __runInitializers(_init, 39, this);
229
+ })), __runInitializers(_init, 47, this);
153
230
  __publicField(this, "handleEdgeScroll", () => {
154
231
  if (!this.edgeScroll.config.enabled || !this.mousePosition || !this.ref) {
155
232
  return;
@@ -191,69 +268,22 @@ class Canvas extends (_a = BasePlugin, _ref_dec = [register("ref")], _transform_
191
268
  this.edgeScrollAnimationFrame = requestAnimationFrame(this.handleEdgeScroll);
192
269
  });
193
270
  }
194
- scrollNodeIntoView({ nodeId, scale = this.transform.scale, block = "nearest", inline = "nearest", offset = 0, animationTime }) {
195
- var _a2, _b, _c, _d, _e, _f, _g;
271
+ scrollNodeIntoView({ nodeId, scale = this.transform.scale, block, inline, offset, animationTime }) {
272
+ var _a2;
196
273
  const node = nodeId && this.getNode({ id: nodeId });
197
274
  if (!node) {
198
275
  return;
199
276
  }
200
- const nodeX = node.position.x;
201
- const nodeY = node.position.y;
202
- const nodeWidth = (_b = (_a2 = node.measured) == null ? void 0 : _a2.width) != null ? _b : 0;
203
- const nodeHeight = (_d = (_c = node.measured) == null ? void 0 : _c.height) != null ? _d : 0;
204
- const viewportWidth = this.container.width;
205
- const viewportHeight = this.container.height;
206
- let positionX = -this.transform.positionX;
207
- let positionY = -this.transform.positionY;
208
- const offsetX = typeof offset === "number" ? offset : (_e = offset.x) != null ? _e : 0;
209
- const offsetY = typeof offset === "number" ? offset : (_f = offset.y) != null ? _f : 0;
210
- switch (inline) {
211
- case "center":
212
- positionX = (nodeX + nodeWidth / 2) * scale - viewportWidth / 2;
213
- break;
214
- case "start":
215
- positionX = nodeX * scale - offsetX;
216
- break;
217
- case "end":
218
- positionX = (nodeX + nodeWidth) * scale - viewportWidth + offsetX;
219
- break;
220
- case "nearest": {
221
- const nodeRight = (nodeX + nodeWidth) * scale;
222
- const nodeLeft = nodeX * scale;
223
- const currentLeft = -this.transform.positionX;
224
- const currentRight = currentLeft + viewportWidth;
225
- if (nodeRight > currentRight) {
226
- positionX = nodeRight - viewportWidth + offsetX;
227
- } else if (nodeLeft < currentLeft) {
228
- positionX = nodeLeft - offsetX;
229
- }
230
- break;
231
- }
232
- }
233
- switch (block) {
234
- case "center":
235
- positionY = (nodeY + nodeHeight / 2) * scale - viewportHeight / 2;
236
- break;
237
- case "start":
238
- positionY = nodeY * scale - offsetY;
239
- break;
240
- case "end":
241
- positionY = (nodeY + nodeHeight) * scale - viewportHeight + offsetY;
242
- break;
243
- case "nearest": {
244
- const nodeBottom = (nodeY + nodeHeight) * scale;
245
- const nodeTop = nodeY * scale;
246
- const currentTop = -this.transform.positionY;
247
- const currentBottom = currentTop + viewportHeight;
248
- if (nodeBottom > currentBottom) {
249
- positionY = nodeBottom - viewportHeight + offsetY;
250
- } else if (nodeTop < currentTop) {
251
- positionY = nodeTop - offsetY;
252
- }
253
- break;
254
- }
255
- }
256
- (_g = this.ref) == null ? void 0 : _g.setTransform(-positionX, -positionY, scale, animationTime);
277
+ const { positionX, positionY, scale: newScale } = calculateTransform({
278
+ node,
279
+ container: this.container,
280
+ transform: this.transform,
281
+ scale,
282
+ block,
283
+ inline,
284
+ offset
285
+ });
286
+ (_a2 = this.ref) == null ? void 0 : _a2.setTransform(-positionX, -positionY, newScale, animationTime);
257
287
  }
258
288
  zoomIn({ step = 0.1, animationTime }) {
259
289
  var _a2;
@@ -268,15 +298,36 @@ class Canvas extends (_a = BasePlugin, _ref_dec = [register("ref")], _transform_
268
298
  (_a2 = this.ref) == null ? void 0 : _a2.setTransform(positionX != null ? positionX : this.transform.positionX, positionY != null ? positionY : this.transform.positionY, scale != null ? scale : this.transform.scale, animationTime);
269
299
  }
270
300
  render({ children } = { children: null }) {
271
- const [transformRef, setTransformRef] = useReducer((prevRef, ref) => {
272
- this.ref = ref;
273
- if (!prevRef && ref.instance.isInitialized && this.config.defaultLocated) {
274
- this.scrollNodeIntoView(__spreadValues({
275
- inline: "center",
276
- block: "center",
277
- scale: 1,
278
- animationTime: 0
279
- }, this.config.defaultLocated));
301
+ var _a2, _b, _c, _d;
302
+ const defaultTransform = useMemo(() => {
303
+ const defaultLocated = this.config.defaultLocated;
304
+ if (!(defaultLocated == null ? void 0 : defaultLocated.nodeId)) {
305
+ return this.transform;
306
+ }
307
+ const node = this.getNode({ id: defaultLocated.nodeId });
308
+ if (!node) {
309
+ return this.transform;
310
+ }
311
+ defaultLocated.inline || (defaultLocated.inline = "center");
312
+ defaultLocated.block || (defaultLocated.block = "center");
313
+ defaultLocated.scale || (defaultLocated.scale = this.transform.scale);
314
+ const { positionX, positionY, scale: newScale } = calculateTransform(__spreadValues({
315
+ node,
316
+ container: this.container,
317
+ transform: this.transform
318
+ }, defaultLocated));
319
+ const newTransform = {
320
+ previousScale: this.transform.scale,
321
+ scale: newScale,
322
+ positionX: -positionX,
323
+ positionY: -positionY
324
+ };
325
+ this.transform = newTransform;
326
+ return newTransform;
327
+ }, []);
328
+ const [transformRef, setTransformRef] = useReducer((_, ref) => {
329
+ if (this.ref !== ref) {
330
+ this.ref = ref;
280
331
  }
281
332
  return ref;
282
333
  }, null);
@@ -295,31 +346,33 @@ class Canvas extends (_a = BasePlugin, _ref_dec = [register("ref")], _transform_
295
346
  }
296
347
  return [fixedLayers2, childrenLayers2];
297
348
  }, [children]);
298
- useEffect(() => {
349
+ useLayoutEffect(() => {
299
350
  const wrapperElement = transformRef == null ? void 0 : transformRef.instance.wrapperComponent;
300
- if (!wrapperElement) {
301
- return;
351
+ if (wrapperElement) {
352
+ Object.defineProperty(wrapperElement, "scrollTop", {
353
+ get() {
354
+ return -transformRef.instance.transformState.positionY;
355
+ },
356
+ set(value) {
357
+ transformRef.instance.setTransformState(transformRef.instance.transformState.scale, transformRef.instance.transformState.positionX, -value);
358
+ }
359
+ });
360
+ Object.defineProperty(wrapperElement, "scrollLeft", {
361
+ get() {
362
+ return -transformRef.instance.transformState.positionX;
363
+ },
364
+ set(value) {
365
+ transformRef.instance.setTransformState(transformRef.instance.transformState.scale, -value, transformRef.instance.transformState.positionY);
366
+ }
367
+ });
302
368
  }
303
- Object.defineProperty(wrapperElement, "scrollTop", {
304
- get() {
305
- return -transformRef.instance.transformState.positionY;
306
- },
307
- set(value) {
308
- transformRef.instance.setTransformState(transformRef.instance.transformState.scale, transformRef.instance.transformState.positionX, -value);
309
- }
310
- });
311
- Object.defineProperty(wrapperElement, "scrollLeft", {
312
- get() {
313
- return -transformRef.instance.transformState.positionX;
314
- },
315
- set(value) {
316
- transformRef.instance.setTransformState(transformRef.instance.transformState.scale, -value, transformRef.instance.transformState.positionY);
317
- }
318
- });
319
369
  let frame;
320
370
  return transformRef == null ? void 0 : transformRef.instance.onChange((ref) => {
321
371
  cancelAnimationFrame(frame);
322
372
  frame = requestAnimationFrame(() => {
373
+ if (isEqual(this.transform, ref.state)) {
374
+ return;
375
+ }
323
376
  this.transform = __spreadValues({}, ref.state);
324
377
  });
325
378
  });
@@ -369,6 +422,9 @@ class Canvas extends (_a = BasePlugin, _ref_dec = [register("ref")], _transform_
369
422
  TransformWrapper,
370
423
  __spreadProps(__spreadValues({}, this.config), {
371
424
  ref: setTransformRef,
425
+ initialPositionX: defaultTransform.positionX,
426
+ initialPositionY: defaultTransform.positionY,
427
+ initialScale: defaultTransform.scale,
372
428
  children: [
373
429
  /* @__PURE__ */ jsx(Fragment, { children: fixedLayers }),
374
430
  /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(
@@ -390,8 +446,8 @@ class Canvas extends (_a = BasePlugin, _ref_dec = [register("ref")], _transform_
390
446
  contentClass: bem(this.name, "content"),
391
447
  contentStyle: {
392
448
  position: "relative",
393
- width: "100%",
394
- height: "100%",
449
+ width: (_b = (_a2 = this.contentSize) == null ? void 0 : _a2.width) != null ? _b : "100%",
450
+ height: (_d = (_c = this.contentSize) == null ? void 0 : _c.height) != null ? _d : "100%",
395
451
  willChange: "auto"
396
452
  },
397
453
  children: childrenLayers
@@ -434,6 +490,8 @@ __decorateElement(_init, 1, "render", _render_dec, Canvas);
434
490
  __decorateElement(_init, 1, "init", _init_dec, Canvas);
435
491
  __decorateElement(_init, 5, "ref", _ref_dec, Canvas);
436
492
  __decorateElement(_init, 5, "transform", _transform_dec, Canvas);
493
+ __decorateElement(_init, 5, "contentSize", _contentSize_dec, Canvas);
494
+ __decorateElement(_init, 5, "updateContentSize", _updateContentSize_dec, Canvas);
437
495
  __decorateElement(_init, 5, "edgeScroll", _edgeScroll_dec, Canvas);
438
496
  __decorateElement(_init, 5, "getNode", _getNode_dec, Canvas);
439
497
  __decorateElement(_init, 5, "container", _container_dec, Canvas);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@knotx/plugins-canvas",
3
- "version": "0.3.5",
3
+ "version": "0.3.7",
4
4
  "description": "Canvas Plugin for Knotx",
5
5
  "author": "boenfu",
6
6
  "license": "MIT",
@@ -29,23 +29,23 @@
29
29
  ],
30
30
  "peerDependencies": {
31
31
  "react": ">=17.0.0",
32
- "@knotx/jsx": "0.3.5"
32
+ "@knotx/jsx": "0.3.7"
33
33
  },
34
34
  "dependencies": {
35
35
  "lodash-es": "^4.17.21",
36
36
  "react-zoom-pan-pinch": "^3.7.0",
37
37
  "rxjs": "^7.8.1",
38
- "@knotx/core": "0.3.5",
39
- "@knotx/decorators": "0.3.5"
38
+ "@knotx/core": "0.3.7",
39
+ "@knotx/decorators": "0.3.7"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/lodash-es": "^4.17.12",
43
43
  "@types/react": "^17.0.0",
44
44
  "react": "^17.0.0",
45
- "@knotx/build-config": "0.3.5",
46
- "@knotx/eslint-config": "0.3.5",
47
- "@knotx/jsx": "0.3.5",
48
- "@knotx/typescript-config": "0.3.5"
45
+ "@knotx/build-config": "0.3.7",
46
+ "@knotx/eslint-config": "0.3.7",
47
+ "@knotx/jsx": "0.3.7",
48
+ "@knotx/typescript-config": "0.3.7"
49
49
  },
50
50
  "scripts": {
51
51
  "build": "unbuild",