fabric 6.0.0-beta7 → 6.0.0-beta8

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.
Files changed (39) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/fabric.d.ts +3 -0
  3. package/dist/index.js +405 -399
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.min.js +1 -1
  6. package/dist/index.mjs +404 -400
  7. package/dist/index.mjs.map +1 -1
  8. package/dist/index.node.cjs +407 -413
  9. package/dist/index.node.cjs.map +1 -1
  10. package/dist/index.node.d.ts +0 -2
  11. package/dist/index.node.mjs +406 -414
  12. package/dist/index.node.mjs.map +1 -1
  13. package/dist/src/canvas/DOMManagers/CanvasDOMManager.d.ts +29 -0
  14. package/dist/src/canvas/DOMManagers/StaticCanvasDOMManager.d.ts +29 -0
  15. package/dist/src/canvas/DOMManagers/util.d.ts +24 -0
  16. package/dist/src/canvas/DOMManagers/util.spec.d.ts +1 -0
  17. package/dist/src/canvas/SelectableCanvas.d.ts +9 -33
  18. package/dist/src/canvas/StaticCanvas.d.ts +12 -38
  19. package/dist/src/constants.d.ts +1 -0
  20. package/dist/src/shapes/IText/ITextClickBehavior.d.ts +0 -7
  21. package/dist/src/util/dom_misc.d.ts +0 -29
  22. package/dist/src/util/index.d.ts +0 -2
  23. package/fabric.ts +6 -0
  24. package/index.node.ts +3 -15
  25. package/package.json +1 -1
  26. package/rollup.config.mjs +6 -7
  27. package/src/canvas/DOMManagers/CanvasDOMManager.ts +124 -0
  28. package/src/canvas/DOMManagers/StaticCanvasDOMManager.ts +80 -0
  29. package/src/canvas/DOMManagers/util.spec.ts +23 -0
  30. package/src/canvas/DOMManagers/util.ts +98 -0
  31. package/src/canvas/SelectableCanvas.ts +23 -127
  32. package/src/canvas/StaticCanvas.ts +37 -119
  33. package/src/canvas/TextEditingManager.ts +7 -1
  34. package/src/constants.ts +2 -0
  35. package/src/shapes/IText/ITextClickBehavior.ts +4 -21
  36. package/src/shapes/Text/constants.ts +2 -2
  37. package/src/util/dom_misc.ts +0 -83
  38. package/src/util/index.ts +0 -7
  39. package/src/util/misc/textStyles.ts +2 -1
package/dist/index.js CHANGED
@@ -416,7 +416,7 @@
416
416
  }
417
417
  const cache = new Cache();
418
418
 
419
- var version = "6.0.0-beta7";
419
+ var version = "6.0.0-beta8";
420
420
 
421
421
  // use this syntax so babel plugin see this import here
422
422
  const VERSION = version;
@@ -440,6 +440,7 @@
440
440
  const BOTTOM = 'bottom';
441
441
  const RIGHT = 'right';
442
442
  const NONE = 'none';
443
+ const reNewline = /\r?\n/;
443
444
 
444
445
  /*
445
446
  * This Map connects the objects type value with their
@@ -1521,133 +1522,6 @@
1521
1522
  return getFabricWindow().cancelAnimationFrame(handle);
1522
1523
  }
1523
1524
 
1524
- /**
1525
- * Wraps element with another element
1526
- * @param {HTMLElement} element Element to wrap
1527
- * @param {HTMLElement|String} wrapper Element to wrap with
1528
- * @param {Object} [attributes] Attributes to set on a wrapper
1529
- * @return {HTMLElement} wrapper
1530
- */
1531
- function wrapElement(element, wrapper) {
1532
- if (element.parentNode) {
1533
- element.parentNode.replaceChild(wrapper, element);
1534
- }
1535
- wrapper.appendChild(element);
1536
- return wrapper;
1537
- }
1538
-
1539
- /**
1540
- * Returns element scroll offsets
1541
- * @param {HTMLElement} element Element to operate on
1542
- * @return {Object} Object with left/top values
1543
- */
1544
- function getScrollLeftTop(element) {
1545
- let left = 0,
1546
- top = 0;
1547
- const doc = getDocumentFromElement(element);
1548
- const docElement = doc.documentElement,
1549
- body = doc.body || {
1550
- scrollLeft: 0,
1551
- scrollTop: 0
1552
- };
1553
- // While loop checks (and then sets element to) .parentNode OR .host
1554
- // to account for ShadowDOM. We still want to traverse up out of ShadowDOM,
1555
- // but the .parentNode of a root ShadowDOM node will always be null, instead
1556
- // it should be accessed through .host. See http://stackoverflow.com/a/24765528/4383938
1557
- // @ts-expect-error Set element to element parent, or 'host' in case of ShadowDOM
1558
- while (element && (element.parentNode || element.host)) {
1559
- // @ts-expect-error Set element to element parent, or 'host' in case of ShadowDOM
1560
- element = element.parentNode || element.host;
1561
- // @ts-expect-error because element is typed as HTMLElement but it can go up to document
1562
- if (element === doc) {
1563
- left = body.scrollLeft || docElement.scrollLeft || 0;
1564
- top = body.scrollTop || docElement.scrollTop || 0;
1565
- } else {
1566
- left += element.scrollLeft || 0;
1567
- top += element.scrollTop || 0;
1568
- }
1569
- if (element.nodeType === 1 && element.style.position === 'fixed') {
1570
- break;
1571
- }
1572
- }
1573
- return {
1574
- left,
1575
- top
1576
- };
1577
- }
1578
-
1579
- /**
1580
- * Returns offset for a given element
1581
- * @param {HTMLElement} element Element to get offset for
1582
- * @return {Object} Object with "left" and "top" properties
1583
- */
1584
- function getElementOffset(element) {
1585
- var _getWindowFromElement;
1586
- let box = {
1587
- left: 0,
1588
- top: 0
1589
- };
1590
- const doc = element && getDocumentFromElement(element),
1591
- offset = {
1592
- left: 0,
1593
- top: 0
1594
- },
1595
- offsetAttributes = {
1596
- borderLeftWidth: LEFT,
1597
- borderTopWidth: TOP,
1598
- paddingLeft: LEFT,
1599
- paddingTop: TOP
1600
- };
1601
- if (!doc) {
1602
- return offset;
1603
- }
1604
- const elemStyle = ((_getWindowFromElement = getWindowFromElement(element)) === null || _getWindowFromElement === void 0 ? void 0 : _getWindowFromElement.getComputedStyle(element, null)) || {};
1605
- for (const attr in offsetAttributes) {
1606
- // @ts-expect-error TS learn to iterate!
1607
- offset[offsetAttributes[attr]] += parseInt(elemStyle[attr], 10) || 0;
1608
- }
1609
- const docElem = doc.documentElement;
1610
- if (typeof element.getBoundingClientRect !== 'undefined') {
1611
- box = element.getBoundingClientRect();
1612
- }
1613
- const scrollLeftTop = getScrollLeftTop(element);
1614
- return {
1615
- left: box.left + scrollLeftTop.left - (docElem.clientLeft || 0) + offset.left,
1616
- top: box.top + scrollLeftTop.top - (docElem.clientTop || 0) + offset.top
1617
- };
1618
- }
1619
-
1620
- /**
1621
- * Makes element unselectable
1622
- * @param {HTMLElement} element Element to make unselectable
1623
- * @return {HTMLElement} Element that was passed in
1624
- */
1625
- function makeElementUnselectable(element) {
1626
- if (typeof element.onselectstart !== 'undefined') {
1627
- element.onselectstart = () => false;
1628
- }
1629
- element.style.userSelect = NONE;
1630
- return element;
1631
- }
1632
-
1633
- /**
1634
- * Makes element selectable
1635
- * @param {HTMLElement} element Element to make selectable
1636
- * @return {HTMLElement} Element that was passed in
1637
- */
1638
- function makeElementSelectable(element) {
1639
- if (typeof element.onselectstart !== 'undefined') {
1640
- element.onselectstart = null;
1641
- }
1642
- element.style.userSelect = '';
1643
- return element;
1644
- }
1645
- const getDocumentFromElement = el => el.ownerDocument || null;
1646
- const getWindowFromElement = el => {
1647
- var _el$ownerDocument;
1648
- return ((_el$ownerDocument = el.ownerDocument) === null || _el$ownerDocument === void 0 ? void 0 : _el$ownerDocument.defaultView) || null;
1649
- };
1650
-
1651
1525
  let id = 0;
1652
1526
  const uid = () => id++;
1653
1527
 
@@ -2890,6 +2764,228 @@
2890
2764
  return !!fabricObject && typeof fabricObject.onDragStart === 'function' && typeof fabricObject.shouldStartDragging === 'function';
2891
2765
  };
2892
2766
 
2767
+ /**
2768
+ * Returns element scroll offsets
2769
+ * @param {HTMLElement} element Element to operate on
2770
+ * @return {Object} Object with left/top values
2771
+ */
2772
+ function getScrollLeftTop(element) {
2773
+ let left = 0,
2774
+ top = 0;
2775
+ const doc = getDocumentFromElement(element);
2776
+ const docElement = doc.documentElement,
2777
+ body = doc.body || {
2778
+ scrollLeft: 0,
2779
+ scrollTop: 0
2780
+ };
2781
+ // While loop checks (and then sets element to) .parentNode OR .host
2782
+ // to account for ShadowDOM. We still want to traverse up out of ShadowDOM,
2783
+ // but the .parentNode of a root ShadowDOM node will always be null, instead
2784
+ // it should be accessed through .host. See http://stackoverflow.com/a/24765528/4383938
2785
+ // @ts-expect-error Set element to element parent, or 'host' in case of ShadowDOM
2786
+ while (element && (element.parentNode || element.host)) {
2787
+ // @ts-expect-error Set element to element parent, or 'host' in case of ShadowDOM
2788
+ element = element.parentNode || element.host;
2789
+ // @ts-expect-error because element is typed as HTMLElement but it can go up to document
2790
+ if (element === doc) {
2791
+ left = body.scrollLeft || docElement.scrollLeft || 0;
2792
+ top = body.scrollTop || docElement.scrollTop || 0;
2793
+ } else {
2794
+ left += element.scrollLeft || 0;
2795
+ top += element.scrollTop || 0;
2796
+ }
2797
+ if (element.nodeType === 1 && element.style.position === 'fixed') {
2798
+ break;
2799
+ }
2800
+ }
2801
+ return {
2802
+ left,
2803
+ top
2804
+ };
2805
+ }
2806
+ const getDocumentFromElement = el => el.ownerDocument || null;
2807
+ const getWindowFromElement = el => {
2808
+ var _el$ownerDocument;
2809
+ return ((_el$ownerDocument = el.ownerDocument) === null || _el$ownerDocument === void 0 ? void 0 : _el$ownerDocument.defaultView) || null;
2810
+ };
2811
+
2812
+ //@ts-nocheck
2813
+ // TODO this file needs to go away, cross browser style support is not fabricjs domain.
2814
+
2815
+ /**
2816
+ * wrapper for setting element's style
2817
+ * @param {HTMLElement} element
2818
+ * @param {Object | string} styles
2819
+ */
2820
+ function setStyle(element, styles) {
2821
+ const elementStyle = element.style;
2822
+ if (!elementStyle) {
2823
+ return;
2824
+ } else if (typeof styles === 'string') {
2825
+ element.style.cssText += ';' + styles;
2826
+ } else {
2827
+ Object.entries(styles).forEach(_ref => {
2828
+ let [property, value] = _ref;
2829
+ return elementStyle.setProperty(property, value);
2830
+ });
2831
+ }
2832
+ }
2833
+
2834
+ const setCanvasDimensions = function (el, ctx, _ref) {
2835
+ let {
2836
+ width,
2837
+ height
2838
+ } = _ref;
2839
+ let retinaScaling = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1;
2840
+ el.width = width;
2841
+ el.height = height;
2842
+ if (retinaScaling > 1) {
2843
+ el.setAttribute('width', (width * retinaScaling).toString());
2844
+ el.setAttribute('height', (height * retinaScaling).toString());
2845
+ ctx.scale(retinaScaling, retinaScaling);
2846
+ }
2847
+ };
2848
+ function allowTouchScrolling(element, allow) {
2849
+ const touchAction = allow ? 'manipulation' : NONE;
2850
+ setStyle(element, {
2851
+ 'touch-action': touchAction,
2852
+ '-ms-touch-action': touchAction
2853
+ });
2854
+ }
2855
+ const setCSSDimensions = (el, _ref2) => {
2856
+ let {
2857
+ width,
2858
+ height
2859
+ } = _ref2;
2860
+ width && (el.style.width = typeof width === 'number' ? "".concat(width, "px") : width);
2861
+ height && (el.style.height = typeof height === 'number' ? "".concat(height, "px") : height);
2862
+ };
2863
+
2864
+ /**
2865
+ * Returns offset for a given element
2866
+ * @param {HTMLElement} element Element to get offset for
2867
+ * @return {Object} Object with "left" and "top" properties
2868
+ */
2869
+ function getElementOffset(element) {
2870
+ var _getWindowFromElement;
2871
+ let box = {
2872
+ left: 0,
2873
+ top: 0
2874
+ };
2875
+ const doc = element && getDocumentFromElement(element),
2876
+ offset = {
2877
+ left: 0,
2878
+ top: 0
2879
+ },
2880
+ offsetAttributes = {
2881
+ borderLeftWidth: LEFT,
2882
+ borderTopWidth: TOP,
2883
+ paddingLeft: LEFT,
2884
+ paddingTop: TOP
2885
+ };
2886
+ if (!doc) {
2887
+ return offset;
2888
+ }
2889
+ const elemStyle = ((_getWindowFromElement = getWindowFromElement(element)) === null || _getWindowFromElement === void 0 ? void 0 : _getWindowFromElement.getComputedStyle(element, null)) || {};
2890
+ for (const attr in offsetAttributes) {
2891
+ // @ts-expect-error TS learn to iterate!
2892
+ offset[offsetAttributes[attr]] += parseInt(elemStyle[attr], 10) || 0;
2893
+ }
2894
+ const docElem = doc.documentElement;
2895
+ if (typeof element.getBoundingClientRect !== 'undefined') {
2896
+ box = element.getBoundingClientRect();
2897
+ }
2898
+ const scrollLeftTop = getScrollLeftTop(element);
2899
+ return {
2900
+ left: box.left + scrollLeftTop.left - (docElem.clientLeft || 0) + offset.left,
2901
+ top: box.top + scrollLeftTop.top - (docElem.clientTop || 0) + offset.top
2902
+ };
2903
+ }
2904
+
2905
+ /**
2906
+ * Makes element unselectable
2907
+ * @param {HTMLElement} element Element to make unselectable
2908
+ * @return {HTMLElement} Element that was passed in
2909
+ */
2910
+ function makeElementUnselectable(element) {
2911
+ if (typeof element.onselectstart !== 'undefined') {
2912
+ element.onselectstart = () => false;
2913
+ }
2914
+ element.style.userSelect = NONE;
2915
+ return element;
2916
+ }
2917
+
2918
+ class StaticCanvasDOMManager {
2919
+ /**
2920
+ * Keeps a copy of the canvas style before setting retina scaling and other potions
2921
+ * in order to return it to original state on dispose
2922
+ * @type string
2923
+ */
2924
+
2925
+ constructor(arg0) {
2926
+ _defineProperty(this, "_originalCanvasStyle", void 0);
2927
+ _defineProperty(this, "lower", void 0);
2928
+ const el = this.createLowerCanvas(arg0);
2929
+ this.lower = {
2930
+ el,
2931
+ ctx: el.getContext('2d')
2932
+ };
2933
+ }
2934
+ createLowerCanvas(arg0) {
2935
+ // canvasEl === 'HTMLCanvasElement' does not work on jsdom/node
2936
+ const el = isHTMLCanvas(arg0) ? arg0 : getFabricDocument().getElementById(arg0) || createCanvasElement();
2937
+ if (el.hasAttribute('data-fabric')) {
2938
+ /* _DEV_MODE_START_ */
2939
+ throw new Error('fabric.js: trying to initialize a canvas that has already been initialized');
2940
+ /* _DEV_MODE_END_ */
2941
+ }
2942
+
2943
+ this._originalCanvasStyle = el.style.cssText;
2944
+ el.setAttribute('data-fabric', 'main');
2945
+ el.classList.add('lower-canvas');
2946
+ return el;
2947
+ }
2948
+ cleanupDOM(_ref) {
2949
+ let {
2950
+ width,
2951
+ height
2952
+ } = _ref;
2953
+ const {
2954
+ el
2955
+ } = this.lower;
2956
+ // restore canvas style and attributes
2957
+ el.classList.remove('lower-canvas');
2958
+ el.removeAttribute('data-fabric');
2959
+ // restore canvas size to original size in case retina scaling was applied
2960
+ el.setAttribute('width', "".concat(width));
2961
+ el.setAttribute('height', "".concat(height));
2962
+ el.style.cssText = this._originalCanvasStyle || '';
2963
+ this._originalCanvasStyle = undefined;
2964
+ }
2965
+ setDimensions(size, retinaScaling) {
2966
+ const {
2967
+ el,
2968
+ ctx
2969
+ } = this.lower;
2970
+ setCanvasDimensions(el, ctx, size, retinaScaling);
2971
+ }
2972
+ setCSSDimensions(size) {
2973
+ setCSSDimensions(this.lower.el, size);
2974
+ }
2975
+
2976
+ /**
2977
+ * Calculates canvas element offset relative to the document
2978
+ */
2979
+ calcOffset() {
2980
+ return getElementOffset(this.lower.el);
2981
+ }
2982
+ dispose() {
2983
+ getEnv().dispose(this.lower.el);
2984
+ // @ts-expect-error disposing
2985
+ delete this.lower;
2986
+ }
2987
+ }
2988
+
2893
2989
  const StaticCanvasDefaults = {
2894
2990
  backgroundColor: '',
2895
2991
  backgroundImage: null,
@@ -3051,6 +3147,14 @@
3051
3147
  * Can be use to read the raw pixels, but never write or manipulate
3052
3148
  * @type HTMLCanvasElement
3053
3149
  */
3150
+ get lowerCanvasEl() {
3151
+ var _this$elements$lower;
3152
+ return (_this$elements$lower = this.elements.lower) === null || _this$elements$lower === void 0 ? void 0 : _this$elements$lower.el;
3153
+ }
3154
+ get contextContainer() {
3155
+ var _this$elements$lower2;
3156
+ return (_this$elements$lower2 = this.elements.lower) === null || _this$elements$lower2 === void 0 ? void 0 : _this$elements$lower2.ctx;
3157
+ }
3054
3158
 
3055
3159
  /**
3056
3160
  * Width in virtual/logical pixels of the canvas.
@@ -3076,12 +3180,6 @@
3076
3180
  * @type boolean
3077
3181
  */
3078
3182
 
3079
- /**
3080
- * Keeps a copy of the canvas style before setting retina scaling and other potions
3081
- * in order to return it to original state on dispose
3082
- * @type string
3083
- */
3084
-
3085
3183
  // reference to
3086
3184
 
3087
3185
  static getDefaults() {
@@ -3094,15 +3192,14 @@
3094
3192
  this.set(options);
3095
3193
  this.initElements(el);
3096
3194
  this._setDimensionsImpl({
3097
- width: this.width || this.lowerCanvasEl.width || 0,
3098
- height: this.height || this.lowerCanvasEl.height || 0
3195
+ width: this.width || this.elements.lower.el.width || 0,
3196
+ height: this.height || this.elements.lower.el.height || 0
3099
3197
  });
3100
3198
  this.viewportTransform = [...this.viewportTransform];
3101
3199
  this.calcViewportBoundaries();
3102
3200
  }
3103
3201
  initElements(el) {
3104
- this._createLowerCanvas(el);
3105
- this._originalCanvasStyle = this.lowerCanvasEl.style.cssText;
3202
+ this.elements = new StaticCanvasDOMManager(el);
3106
3203
  }
3107
3204
  add() {
3108
3205
  const size = super.add(...arguments);
@@ -3165,45 +3262,13 @@
3165
3262
  getRetinaScaling() {
3166
3263
  return this._isRetinaScaling() ? Math.max(1, config.devicePixelRatio) : 1;
3167
3264
  }
3168
- _initRetinaScaling() {
3169
- this.__initRetinaScaling(this.lowerCanvasEl, this.contextContainer);
3170
- }
3171
- __initRetinaScaling(canvas, context) {
3172
- const scaleRatio = config.devicePixelRatio;
3173
- canvas.setAttribute('width', (this.width * scaleRatio).toString());
3174
- canvas.setAttribute('height', (this.height * scaleRatio).toString());
3175
- context.scale(scaleRatio, scaleRatio);
3176
- }
3177
3265
 
3178
3266
  /**
3179
3267
  * Calculates canvas element offset relative to the document
3180
3268
  * This method is also attached as "resize" event handler of window
3181
3269
  */
3182
3270
  calcOffset() {
3183
- return this._offset = getElementOffset(this.lowerCanvasEl);
3184
- }
3185
-
3186
- /**
3187
- * Creates a bottom canvas
3188
- * @private
3189
- * @param {HTMLElement} [canvasEl]
3190
- */
3191
- _createLowerCanvas(canvasEl) {
3192
- // canvasEl === 'HTMLCanvasElement' does not work on jsdom/node
3193
- if (isHTMLCanvas(canvasEl)) {
3194
- this.lowerCanvasEl = canvasEl;
3195
- } else {
3196
- this.lowerCanvasEl = getFabricDocument().getElementById(canvasEl) || createCanvasElement();
3197
- }
3198
- if (this.lowerCanvasEl.hasAttribute('data-fabric')) {
3199
- /* _DEV_MODE_START_ */
3200
- throw new Error('fabric.js: trying to initialize a canvas that has already been initialized');
3201
- /* _DEV_MODE_END_ */
3202
- }
3203
-
3204
- this.lowerCanvasEl.classList.add('lower-canvas');
3205
- this.lowerCanvasEl.setAttribute('data-fabric', 'main');
3206
- this.contextContainer = this.lowerCanvasEl.getContext('2d');
3271
+ return this._offset = this.elements.calcOffset();
3207
3272
  }
3208
3273
 
3209
3274
  /**
@@ -3259,19 +3324,19 @@
3259
3324
  cssOnly = false,
3260
3325
  backstoreOnly = false
3261
3326
  } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
3262
- Object.entries(dimensions).forEach(_ref => {
3263
- let [prop, value] = _ref;
3264
- let cssValue = "".concat(value);
3265
- if (!cssOnly) {
3266
- this._setBackstoreDimension(prop, value);
3267
- cssValue += 'px';
3268
- this.hasLostContext = true;
3269
- }
3270
- if (!backstoreOnly) {
3271
- this._setCssDimension(prop, cssValue);
3272
- }
3273
- });
3274
- this._isRetinaScaling() && this._initRetinaScaling();
3327
+ if (!cssOnly) {
3328
+ const size = _objectSpread2({
3329
+ width: this.width,
3330
+ height: this.height
3331
+ }, dimensions);
3332
+ this.elements.setDimensions(size, this.getRetinaScaling());
3333
+ this.hasLostContext = true;
3334
+ this.width = size.width;
3335
+ this.height = size.height;
3336
+ }
3337
+ if (!backstoreOnly) {
3338
+ this.elements.setCSSDimensions(dimensions);
3339
+ }
3275
3340
  this.calcOffset();
3276
3341
  }
3277
3342
 
@@ -3298,29 +3363,6 @@
3298
3363
  }
3299
3364
  }
3300
3365
 
3301
- /**
3302
- * Helper for setting width/height
3303
- * @private
3304
- * @param {String} prop property (width|height)
3305
- * @param {Number} value value to set property to
3306
- * @todo subclass in canvas and handle upperCanvasEl there.
3307
- */
3308
- _setBackstoreDimension(prop, value) {
3309
- this.lowerCanvasEl[prop] = value;
3310
- this[prop] = value;
3311
- }
3312
-
3313
- /**
3314
- * Helper for setting css width/height
3315
- * @private
3316
- * @param {String} prop property (width|height)
3317
- * @param {String} value value to set property to
3318
- * @todo subclass in canvas and handle upperCanvasEl there.
3319
- */
3320
- _setCssDimension(prop, value) {
3321
- this.lowerCanvasEl.style[prop] = value;
3322
- }
3323
-
3324
3366
  /**
3325
3367
  * Returns canvas zoom level
3326
3368
  * @return {Number}
@@ -3405,7 +3447,7 @@
3405
3447
  * @return {HTMLCanvasElement}
3406
3448
  */
3407
3449
  getElement() {
3408
- return this.lowerCanvasEl;
3450
+ return this.elements.lower.el;
3409
3451
  }
3410
3452
 
3411
3453
  /**
@@ -3421,7 +3463,7 @@
3421
3463
  * @return {CanvasRenderingContext2D}
3422
3464
  */
3423
3465
  getContext() {
3424
- return this.contextContainer;
3466
+ return this.elements.lower.ctx;
3425
3467
  }
3426
3468
 
3427
3469
  /**
@@ -3433,7 +3475,7 @@
3433
3475
  this.overlayImage = null;
3434
3476
  this.backgroundColor = '';
3435
3477
  this.overlayColor = '';
3436
- this.clearContext(this.contextContainer);
3478
+ this.clearContext(this.getContext());
3437
3479
  this.fire('canvas:cleared');
3438
3480
  this.renderOnAddRemove && this.requestRenderAll();
3439
3481
  }
@@ -3446,7 +3488,7 @@
3446
3488
  if (this.destroyed) {
3447
3489
  return;
3448
3490
  }
3449
- this.renderCanvas(this.contextContainer, this._objects);
3491
+ this.renderCanvas(this.getContext(), this._objects);
3450
3492
  }
3451
3493
 
3452
3494
  /**
@@ -4013,10 +4055,10 @@
4013
4055
  return;
4014
4056
  }
4015
4057
  Object.values(styles).forEach(styleRow => {
4016
- Object.values(styleRow).forEach(_ref2 => {
4058
+ Object.values(styleRow).forEach(_ref => {
4017
4059
  let {
4018
4060
  fontFamily = ''
4019
- } = _ref2;
4061
+ } = _ref;
4020
4062
  if (!fontList[fontFamily] && fontPaths[fontFamily]) {
4021
4063
  fontList[fontFamily] = true;
4022
4064
  }
@@ -4138,8 +4180,8 @@
4138
4180
  clipPath
4139
4181
  }, {
4140
4182
  signal
4141
- })]).then(_ref3 => {
4142
- let [enlived, enlivedMap] = _ref3;
4183
+ })]).then(_ref2 => {
4184
+ let [enlived, enlivedMap] = _ref2;
4143
4185
  this.clear();
4144
4186
  this.add(...enlived);
4145
4187
  this.set(serialized);
@@ -4278,7 +4320,10 @@
4278
4320
  * @throws if aborted by a consequent call
4279
4321
  */
4280
4322
  dispose() {
4281
- !this.disposed && this.cleanupDOM();
4323
+ !this.disposed && this.elements.cleanupDOM({
4324
+ width: this.width,
4325
+ height: this.height
4326
+ });
4282
4327
  this.disposed = true;
4283
4328
  return new Promise((resolve, reject) => {
4284
4329
  const task = () => {
@@ -4299,21 +4344,6 @@
4299
4344
  });
4300
4345
  }
4301
4346
 
4302
- /**
4303
- * Invoked as part of the **sync** operation of {@link dispose}.
4304
- */
4305
- cleanupDOM() {
4306
- const canvasElement = this.lowerCanvasEl;
4307
- // restore canvas style and attributes
4308
- canvasElement.classList.remove('lower-canvas');
4309
- canvasElement.removeAttribute('data-fabric');
4310
- // restore canvas size to original size in case retina scaling was applied
4311
- canvasElement.setAttribute('width', "".concat(this.width));
4312
- canvasElement.setAttribute('height', "".concat(this.height));
4313
- canvasElement.style.cssText = this._originalCanvasStyle || '';
4314
- this._originalCanvasStyle = undefined;
4315
- }
4316
-
4317
4347
  /**
4318
4348
  * Clears the canvas element, disposes objects and frees resources.
4319
4349
  *
@@ -4341,10 +4371,7 @@
4341
4371
  this.overlayImage.dispose();
4342
4372
  }
4343
4373
  this.overlayImage = null;
4344
- // @ts-expect-error disposing
4345
- this.contextContainer = null;
4346
- // @ts-expect-error disposing
4347
- this.lowerCanvasEl = undefined;
4374
+ this.elements.dispose();
4348
4375
  }
4349
4376
 
4350
4377
  /**
@@ -10084,28 +10111,6 @@
10084
10111
  return true;
10085
10112
  };
10086
10113
 
10087
- //@ts-nocheck
10088
- // TODO this file needs to go away, cross browser style support is not fabricjs domain.
10089
-
10090
- /**
10091
- * wrapper for setting element's style
10092
- * @param {HTMLElement} element
10093
- * @param {Object | string} styles
10094
- */
10095
- function setStyle(element, styles) {
10096
- const elementStyle = element.style;
10097
- if (!elementStyle) {
10098
- return;
10099
- } else if (typeof styles === 'string') {
10100
- element.style.cssText += ';' + styles;
10101
- } else {
10102
- Object.entries(styles).forEach(_ref => {
10103
- let [property, value] = _ref;
10104
- return elementStyle.setProperty(property, value);
10105
- });
10106
- }
10107
- }
10108
-
10109
10114
  /**
10110
10115
  * Attributes parsed from all SVG elements
10111
10116
  * @type array
@@ -12168,7 +12173,7 @@
12168
12173
  // clone to prevent mutation
12169
12174
  return cloneDeep(styles);
12170
12175
  }
12171
- const textLines = text.split('\n'),
12176
+ const textLines = text.split(reNewline),
12172
12177
  stylesObject = {};
12173
12178
  let charIndex = -1,
12174
12179
  styleIndex = 0;
@@ -13314,7 +13319,6 @@
13314
13319
  findScaleToFit: findScaleToFit,
13315
13320
  getBisector: getBisector,
13316
13321
  getBoundsOfCurve: getBoundsOfCurve,
13317
- getElementOffset: getElementOffset,
13318
13322
  getPathSegmentsInfo: getPathSegmentsInfo,
13319
13323
  getPointOnPath: getPointOnPath,
13320
13324
  getPointer: getPointer,
@@ -13332,8 +13336,6 @@
13332
13336
  joinPath: joinPath,
13333
13337
  loadImage: loadImage,
13334
13338
  makeBoundingBoxFromPoints: makeBoundingBoxFromPoints,
13335
- makeElementSelectable: makeElementSelectable,
13336
- makeElementUnselectable: makeElementUnselectable,
13337
13339
  makePathSimpler: makePathSimpler,
13338
13340
  matrixToSVG: matrixToSVG,
13339
13341
  mergeClipPaths: mergeClipPaths,
@@ -13367,10 +13369,120 @@
13367
13369
  toFixed: toFixed,
13368
13370
  transformPath: transformPath,
13369
13371
  transformPoint: transformPoint,
13370
- transformPointRelativeToCanvas: transformPointRelativeToCanvas,
13371
- wrapElement: wrapElement
13372
+ transformPointRelativeToCanvas: transformPointRelativeToCanvas
13372
13373
  });
13373
13374
 
13375
+ class CanvasDOMManager extends StaticCanvasDOMManager {
13376
+ constructor(arg0) {
13377
+ let {
13378
+ allowTouchScrolling = false,
13379
+ containerClass = ''
13380
+ } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
13381
+ super(arg0);
13382
+ _defineProperty(this, "upper", void 0);
13383
+ _defineProperty(this, "container", void 0);
13384
+ const {
13385
+ el: lowerCanvasEl
13386
+ } = this.lower;
13387
+ const upperCanvasEl = this.createUpperCanvas();
13388
+ this.upper = {
13389
+ el: upperCanvasEl,
13390
+ ctx: upperCanvasEl.getContext('2d')
13391
+ };
13392
+ this.applyCanvasStyle(lowerCanvasEl, {
13393
+ allowTouchScrolling
13394
+ });
13395
+ this.applyCanvasStyle(upperCanvasEl, {
13396
+ allowTouchScrolling
13397
+ });
13398
+ const container = this.createContainerElement();
13399
+ container.classList.add(containerClass);
13400
+ if (lowerCanvasEl.parentNode) {
13401
+ lowerCanvasEl.parentNode.replaceChild(container, lowerCanvasEl);
13402
+ }
13403
+ container.append(lowerCanvasEl, upperCanvasEl);
13404
+ this.container = container;
13405
+ }
13406
+ createUpperCanvas() {
13407
+ const {
13408
+ el: lowerCanvasEl
13409
+ } = this.lower;
13410
+ const el = createCanvasElement();
13411
+ // we assign the same classname of the lowerCanvas
13412
+ el.className = lowerCanvasEl.className;
13413
+ // but then we remove the lower-canvas specific className
13414
+ el.classList.remove('lower-canvas');
13415
+ // we add the specific upper-canvas class
13416
+ el.classList.add('upper-canvas');
13417
+ el.setAttribute('data-fabric', 'top');
13418
+ el.style.cssText = lowerCanvasEl.style.cssText;
13419
+ el.setAttribute('draggable', 'true');
13420
+ return el;
13421
+ }
13422
+ createContainerElement() {
13423
+ const container = getFabricDocument().createElement('div');
13424
+ container.setAttribute('data-fabric', 'wrapper');
13425
+ setStyle(container, {
13426
+ position: 'relative'
13427
+ });
13428
+ makeElementUnselectable(container);
13429
+ return container;
13430
+ }
13431
+
13432
+ /**
13433
+ * @private
13434
+ * @param {HTMLCanvasElement} element canvas element to apply styles on
13435
+ */
13436
+ applyCanvasStyle(element, _ref) {
13437
+ let {
13438
+ allowTouchScrolling: allow
13439
+ } = _ref;
13440
+ setStyle(element, {
13441
+ position: 'absolute',
13442
+ left: 0,
13443
+ top: 0
13444
+ });
13445
+ allowTouchScrolling(element, allow);
13446
+ makeElementUnselectable(element);
13447
+ }
13448
+ setDimensions(size, retinaScaling) {
13449
+ super.setDimensions(size, retinaScaling);
13450
+ const {
13451
+ el,
13452
+ ctx
13453
+ } = this.upper;
13454
+ setCanvasDimensions(el, ctx, size, retinaScaling);
13455
+ }
13456
+ setCSSDimensions(size) {
13457
+ super.setCSSDimensions(size);
13458
+ setCSSDimensions(this.upper.el, size);
13459
+ setCSSDimensions(this.container, size);
13460
+ }
13461
+ cleanupDOM(size) {
13462
+ const container = this.container,
13463
+ {
13464
+ el: lowerCanvasEl
13465
+ } = this.lower,
13466
+ {
13467
+ el: upperCanvasEl
13468
+ } = this.upper;
13469
+ super.cleanupDOM(size);
13470
+ container.removeChild(upperCanvasEl);
13471
+ container.removeChild(lowerCanvasEl);
13472
+ if (container.parentNode) {
13473
+ container.parentNode.replaceChild(lowerCanvasEl, container);
13474
+ }
13475
+ }
13476
+ dispose() {
13477
+ super.dispose();
13478
+ getEnv().dispose(this.upper.el);
13479
+ // @ts-expect-error disposing
13480
+ delete this.upper;
13481
+ // @ts-expect-error disposing
13482
+ delete this.container;
13483
+ }
13484
+ }
13485
+
13374
13486
  const DefaultCanvasProperties = {
13375
13487
  uniformScaling: true,
13376
13488
  uniScaleKey: 'shiftKey',
@@ -13655,6 +13767,7 @@
13655
13767
  * Default element class that's given to wrapper (div) element of canvas
13656
13768
  * @type String
13657
13769
  * @default
13770
+ * @deprecated customize {@link CanvasDOMManager} instead or access {@link elements} directly
13658
13771
  */
13659
13772
 
13660
13773
  /**
@@ -13787,6 +13900,17 @@
13787
13900
  static getDefaults() {
13788
13901
  return _objectSpread2(_objectSpread2({}, super.getDefaults()), SelectableCanvas.ownDefaults);
13789
13902
  }
13903
+ get upperCanvasEl() {
13904
+ var _this$elements$upper;
13905
+ return (_this$elements$upper = this.elements.upper) === null || _this$elements$upper === void 0 ? void 0 : _this$elements$upper.el;
13906
+ }
13907
+ get contextTop() {
13908
+ var _this$elements$upper2;
13909
+ return (_this$elements$upper2 = this.elements.upper) === null || _this$elements$upper2 === void 0 ? void 0 : _this$elements$upper2.ctx;
13910
+ }
13911
+ get wrapperEl() {
13912
+ return this.elements.container;
13913
+ }
13790
13914
  constructor(el) {
13791
13915
  let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
13792
13916
  super(el, options);
@@ -13803,16 +13927,12 @@
13803
13927
  });
13804
13928
  }
13805
13929
  initElements(el) {
13806
- super.initElements(el);
13807
- this._applyCanvasStyle(this.lowerCanvasEl);
13808
- this._initWrapperElement();
13809
- this._createUpperCanvas();
13930
+ this.elements = new CanvasDOMManager(el, {
13931
+ allowTouchScrolling: this.allowTouchScrolling,
13932
+ containerClass: this.containerClass
13933
+ });
13810
13934
  this._createCacheCanvas();
13811
13935
  }
13812
- _initRetinaScaling() {
13813
- super._initRetinaScaling();
13814
- this.__initRetinaScaling(this.upperCanvasEl, this.contextTop);
13815
- }
13816
13936
 
13817
13937
  /**
13818
13938
  * @private
@@ -13876,7 +13996,7 @@
13876
13996
  this.hasLostContext = false;
13877
13997
  }
13878
13998
  !this._objectsToRender && (this._objectsToRender = this._chooseObjectsToRender());
13879
- this.renderCanvas(this.contextContainer, this._objectsToRender);
13999
+ this.renderCanvas(this.getContext(), this._objectsToRender);
13880
14000
  }
13881
14001
 
13882
14002
  /**
@@ -14340,55 +14460,6 @@
14340
14460
  this.freeDrawingBrush && this.freeDrawingBrush._setBrushStyles(this.contextTop);
14341
14461
  }
14342
14462
  }
14343
-
14344
- /**
14345
- * Helper for setting width/height
14346
- * @private
14347
- * @param {String} prop property (width|height)
14348
- * @param {Number} value value to set property to
14349
- */
14350
- _setBackstoreDimension(prop, value) {
14351
- super._setBackstoreDimension(prop, value);
14352
- this.upperCanvasEl[prop] = value;
14353
- }
14354
-
14355
- /**
14356
- * Helper for setting css width/height
14357
- * @private
14358
- * @param {String} prop property (width|height)
14359
- * @param {String} value value to set property to
14360
- */
14361
- _setCssDimension(prop, value) {
14362
- super._setCssDimension(prop, value);
14363
- this.upperCanvasEl.style[prop] = value;
14364
- this.wrapperEl.style[prop] = value;
14365
- }
14366
-
14367
- /**
14368
- * @private
14369
- * @throws {CANVAS_INIT_ERROR} If canvas can not be initialized
14370
- */
14371
- _createUpperCanvas() {
14372
- const lowerCanvasEl = this.lowerCanvasEl;
14373
-
14374
- // if there is no upperCanvas (most common case) we create one.
14375
- if (!this.upperCanvasEl) {
14376
- this.upperCanvasEl = createCanvasElement();
14377
- }
14378
- const upperCanvasEl = this.upperCanvasEl;
14379
- // we assign the same classname of the lowerCanvas
14380
- upperCanvasEl.className = lowerCanvasEl.className;
14381
- // but then we remove the lower-canvas specific className
14382
- upperCanvasEl.classList.remove('lower-canvas');
14383
- // we add the specific upper-canvas class
14384
- upperCanvasEl.classList.add('upper-canvas');
14385
- upperCanvasEl.setAttribute('data-fabric', 'top');
14386
- this.wrapperEl.appendChild(upperCanvasEl);
14387
- upperCanvasEl.style.cssText = lowerCanvasEl.style.cssText;
14388
- this._applyCanvasStyle(upperCanvasEl);
14389
- upperCanvasEl.setAttribute('draggable', 'true');
14390
- this.contextTop = upperCanvasEl.getContext('2d');
14391
- }
14392
14463
  _createCacheCanvas() {
14393
14464
  this.pixelFindCanvasEl = createCanvasElement();
14394
14465
  this.pixelFindContext = this.pixelFindCanvasEl.getContext('2d', {
@@ -14396,46 +14467,13 @@
14396
14467
  });
14397
14468
  this.setTargetFindTolerance(this.targetFindTolerance);
14398
14469
  }
14399
- _initWrapperElement() {
14400
- const container = getFabricDocument().createElement('div');
14401
- container.classList.add(this.containerClass);
14402
- this.wrapperEl = wrapElement(this.lowerCanvasEl, container);
14403
- this.wrapperEl.setAttribute('data-fabric', 'wrapper');
14404
- setStyle(this.wrapperEl, {
14405
- width: "".concat(this.width, "px"),
14406
- height: "".concat(this.height, "px"),
14407
- position: 'relative'
14408
- });
14409
- makeElementUnselectable(this.wrapperEl);
14410
- }
14411
-
14412
- /**
14413
- * @private
14414
- * @param {HTMLCanvasElement} element canvas element to apply styles on
14415
- */
14416
- _applyCanvasStyle(element) {
14417
- const width = this.width || element.width,
14418
- height = this.height || element.height;
14419
- setStyle(element, {
14420
- position: 'absolute',
14421
- width: width + 'px',
14422
- height: height + 'px',
14423
- left: 0,
14424
- top: 0,
14425
- 'touch-action': this.allowTouchScrolling ? 'manipulation' : NONE,
14426
- '-ms-touch-action': this.allowTouchScrolling ? 'manipulation' : NONE
14427
- });
14428
- element.width = width;
14429
- element.height = height;
14430
- makeElementUnselectable(element);
14431
- }
14432
14470
 
14433
14471
  /**
14434
14472
  * Returns context of top canvas where interactions are drawn
14435
14473
  * @returns {CanvasRenderingContext2D}
14436
14474
  */
14437
14475
  getTopContext() {
14438
- return this.contextTop;
14476
+ return this.elements.upper.ctx;
14439
14477
  }
14440
14478
 
14441
14479
  /**
@@ -14444,7 +14482,7 @@
14444
14482
  * @return {CanvasRenderingContext2D}
14445
14483
  */
14446
14484
  getSelectionContext() {
14447
- return this.contextTop;
14485
+ return this.elements.upper.ctx;
14448
14486
  }
14449
14487
 
14450
14488
  /**
@@ -14452,7 +14490,7 @@
14452
14490
  * @return {HTMLCanvasElement}
14453
14491
  */
14454
14492
  getSelectionElement() {
14455
- return this.upperCanvasEl;
14493
+ return this.elements.upper.el;
14456
14494
  }
14457
14495
 
14458
14496
  /**
@@ -14646,17 +14684,6 @@
14646
14684
  activeObject.setCoords();
14647
14685
  }
14648
14686
  }
14649
- cleanupDOM() {
14650
- const wrapperEl = this.wrapperEl,
14651
- lowerCanvasEl = this.lowerCanvasEl,
14652
- upperCanvasEl = this.upperCanvasEl;
14653
- super.cleanupDOM();
14654
- wrapperEl.removeChild(upperCanvasEl);
14655
- wrapperEl.removeChild(lowerCanvasEl);
14656
- if (wrapperEl.parentNode) {
14657
- wrapperEl.parentNode.replaceChild(lowerCanvasEl, wrapperEl);
14658
- }
14659
- }
14660
14687
 
14661
14688
  /**
14662
14689
  * @override clears active selection ref and interactive canvas elements and contexts
@@ -14672,20 +14699,11 @@
14672
14699
 
14673
14700
  // free resources
14674
14701
 
14675
- // top canvas
14676
- // @ts-expect-error disposing
14677
- this.contextTop = null;
14678
- // @ts-expect-error disposing
14679
- this.upperCanvasEl = undefined;
14680
-
14681
14702
  // pixel find canvas
14682
14703
  // @ts-expect-error disposing
14683
14704
  this.pixelFindContext = null;
14684
14705
  // @ts-expect-error disposing
14685
14706
  this.pixelFindCanvasEl = undefined;
14686
-
14687
- // @ts-expect-error disposing
14688
- this.wrapperEl = undefined;
14689
14707
  }
14690
14708
 
14691
14709
  /**
@@ -14764,8 +14782,10 @@
14764
14782
  _defineProperty(this, "targets", []);
14765
14783
  _defineProperty(this, "__disposer", void 0);
14766
14784
  const cb = () => {
14767
- var _this$target, _this$target$hiddenTe;
14768
- return (_this$target = this.target) === null || _this$target === void 0 ? void 0 : (_this$target$hiddenTe = _this$target.hiddenTextarea) === null || _this$target$hiddenTe === void 0 ? void 0 : _this$target$hiddenTe.focus();
14785
+ const activeObject = canvas.getActiveObject();
14786
+ if (isInteractiveTextObject(activeObject)) {
14787
+ activeObject.hiddenTextarea && activeObject.hiddenTextarea.focus();
14788
+ }
14769
14789
  };
14770
14790
  const el = canvas.upperCanvasEl;
14771
14791
  el.addEventListener('click', cb);
@@ -14795,8 +14815,8 @@
14795
14815
  }
14796
14816
  }
14797
14817
  onMouseMove(e) {
14798
- var _this$target2;
14799
- ((_this$target2 = this.target) === null || _this$target2 === void 0 ? void 0 : _this$target2.isEditing) && this.target.updateSelectionOnMouseMove(e);
14818
+ var _this$target;
14819
+ ((_this$target = this.target) === null || _this$target === void 0 ? void 0 : _this$target.isEditing) && this.target.updateSelectionOnMouseMove(e);
14800
14820
  }
14801
14821
  clear() {
14802
14822
  this.targets = [];
@@ -18781,7 +18801,7 @@
18781
18801
  // regexes, list of properties that are not suppose to change by instances, magic consts.
18782
18802
  // this will be a separated effort
18783
18803
  const textDefaultValues = {
18784
- _reNewline: /\r?\n/,
18804
+ _reNewline: reNewline,
18785
18805
  _reSpacesAndTabs: /[ \t\r]/g,
18786
18806
  _reSpaceAndTab: /[ \t\r]/,
18787
18807
  _reWords: /\S+/g,
@@ -22740,22 +22760,13 @@
22740
22760
  }
22741
22761
  }
22742
22762
 
22743
- /**
22744
- * Returns coordinates of a pointer relative to object's top left corner in object's plane
22745
- * @param {Point} [pointer] Pointer to operate upon
22746
- * @return {Point} Coordinates of a pointer (x, y)
22747
- */
22748
- getLocalPointer(pointer) {
22749
- return transformPoint(pointer, invertTransform(this.calcTransformMatrix())).add(new Point(this.width / 2, this.height / 2));
22750
- }
22751
-
22752
22763
  /**
22753
22764
  * Returns index of a character corresponding to where an object was clicked
22754
22765
  * @param {TPointerEvent} e Event object
22755
22766
  * @return {Number} Index of a character
22756
22767
  */
22757
22768
  getSelectionStartFromPointer(e) {
22758
- const mouseOffset = this.getLocalPointer(this.canvas.getPointer(e));
22769
+ const mouseOffset = this.canvas.getPointer(e).transform(invertTransform(this.calcTransformMatrix())).add(new Point(-this._getLeftOffset(), -this._getTopOffset()));
22759
22770
  let height = 0,
22760
22771
  charIndex = 0,
22761
22772
  lineIndex = 0;
@@ -22773,13 +22784,6 @@
22773
22784
  const lineLeftOffset = Math.abs(this._getLineLeftOffset(lineIndex));
22774
22785
  let width = lineLeftOffset;
22775
22786
  const jlen = this._textLines[lineIndex].length;
22776
- // handling of RTL: in order to get things work correctly,
22777
- // we assume RTL writing is mirrored compared to LTR writing.
22778
- // so in position detection we mirror the X offset, and when is time
22779
- // of rendering it, we mirror it again.
22780
- if (this.direction === 'rtl') {
22781
- mouseOffset.x = this.width - mouseOffset.x;
22782
- }
22783
22787
  let prevWidth = 0;
22784
22788
  for (let j = 0; j < jlen; j++) {
22785
22789
  prevWidth = width;
@@ -28322,6 +28326,7 @@
28322
28326
  exports.BaseBrush = BaseBrush;
28323
28327
  exports.Canvas = Canvas;
28324
28328
  exports.Canvas2dFilterBackend = Canvas2dFilterBackend;
28329
+ exports.CanvasDOMManager = CanvasDOMManager;
28325
28330
  exports.Circle = Circle;
28326
28331
  exports.CircleBrush = CircleBrush;
28327
28332
  exports.Color = Color;
@@ -28346,6 +28351,7 @@
28346
28351
  exports.Shadow = Shadow;
28347
28352
  exports.SprayBrush = SprayBrush;
28348
28353
  exports.StaticCanvas = StaticCanvas;
28354
+ exports.StaticCanvasDOMManager = StaticCanvasDOMManager;
28349
28355
  exports.Text = Text;
28350
28356
  exports.Textbox = Textbox;
28351
28357
  exports.Triangle = Triangle;