@configuratorware/configurator-frontendgui 1.57.11 → 1.57.12

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.
@@ -22,6 +22,7 @@ var _Selectors2 = require("../../../../Reducers/DesignData/Selectors");
22
22
  var _i18n = require("../../../../../Framework/i18n");
23
23
  var _Transformers = require("../../Utils/Transformers");
24
24
  var _reactRedux = require("react-redux");
25
+ var _ServiceLocator = require("../../../../ServiceLocator");
25
26
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
26
27
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
27
28
  function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
@@ -224,7 +225,7 @@ var DesignerSelectionToolbox = function DesignerSelectionToolbox(props) {
224
225
  toggleCustomFontOverlay(true);
225
226
  return;
226
227
  }
227
- canvas.selectedObject.fontItem = (0, _fontItemUtils.createFontItemProps)(fontItem);
228
+ _ServiceLocator.Services.designer.changeTextFontItem(canvas.selectedObject, (0, _fontItemUtils.createFontItemProps)(fontItem));
228
229
  },
229
230
  minSize: selectedObject.fontSizeMin,
230
231
  maxSize: 1000,
@@ -322,7 +323,7 @@ var DesignerSelectionToolbox = function DesignerSelectionToolbox(props) {
322
323
  isCustomFont: true
323
324
  });
324
325
  addCustomFont(fontItem);
325
- canvas.selectedObject.fontItem = (0, _fontItemUtils.createFontItemProps)(fontItem);
326
+ _ServiceLocator.Services.designer.changeTextFontItem(canvas.selectedObject, (0, _fontItemUtils.createFontItemProps)(fontItem));
326
327
  toggleCustomFontOverlay(false);
327
328
  }
328
329
  }));
@@ -417,6 +417,40 @@ var DesignerService = exports["default"] = /*#__PURE__*/function () {
417
417
  text.fitCanvas();
418
418
  }
419
419
  }
420
+ }, {
421
+ key: "changeTextFontItem",
422
+ value: function changeTextFontItem(text, fontItemProps) {
423
+ if (!text || text.type !== 'Text') {
424
+ return;
425
+ }
426
+ if ((0, _configuration.getConf)('designer.autoShrinkTextOnFontChange', true)) {
427
+ this.shrinkTextAfterFontChange(text, fontItemProps);
428
+ } else {
429
+ text.fontItem = fontItemProps;
430
+ }
431
+ }
432
+ }, {
433
+ key: "shrinkTextAfterFontChange",
434
+ value: function shrinkTextAfterFontChange(text, fontItemProps) {
435
+ var wasInside = text.isFullyInsideCanvas();
436
+ var maxEffectiveFontSize = text.fontSize * text.scaling;
437
+ text.fontItem = fontItemProps;
438
+ if (!wasInside || text.locked || text.autoFit) {
439
+ return;
440
+ }
441
+ if (text.isFullyInsideCanvas()) {
442
+ return;
443
+ }
444
+ var maxScaling = maxEffectiveFontSize / text.fontSize;
445
+ text.shrinkToFitCanvas({
446
+ enlarge: false,
447
+ updatePosition: false,
448
+ maxScaling: maxScaling
449
+ });
450
+ if (typeof text.commitScalingToFontSize === 'function') {
451
+ text.commitScalingToFontSize(maxEffectiveFontSize);
452
+ }
453
+ }
420
454
  }, {
421
455
  key: "checkDesignElementRestrictions",
422
456
  value: function checkDesignElementRestrictions(targetElementType) {
@@ -222,7 +222,9 @@ var applicationConfiguration = {
222
222
  // the image formats users can upload to designareas / designer items
223
223
  includeMetricContentSize: false,
224
224
  // set true to include the metric content size in the design data
225
- bulkNamesPerNameDesignFiles: false // set true to generate individual production svgs (-> production pdf in zip download) for each bulk name
225
+ bulkNamesPerNameDesignFiles: false,
226
+ // set true to generate individual production svgs (-> production pdf in zip download) for each bulk name
227
+ autoShrinkTextOnFontChange: true // shrink text to stay inside the canvas when changing to a wider/taller font
226
228
  },
227
229
 
228
230
  vectorizeImageQuality: 45000,
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@configuratorware/configurator-frontendgui",
3
- "version": "1.57.11",
3
+ "version": "1.57.12",
4
4
  "license": "UNLICENSED",
5
5
  "private": false,
6
6
  "main": "./index.js",
7
7
  "dependencies": {
8
8
  "@babel/polyfill": "^7.12.1",
9
- "@configuratorware/scripts": "1.57.11",
9
+ "@configuratorware/scripts": "1.57.12",
10
10
  "@material-ui/core": "^4.12.4",
11
11
  "@material-ui/icons": "^4.11.3",
12
12
  "@material-ui/lab": "^4.0.0-alpha.61",
@@ -36,8 +36,8 @@
36
36
  "react-router-dom": "^5.3.4",
37
37
  "react-swipeable": "^5.5.1",
38
38
  "react-zoom-pan-pinch": "^2.1.3",
39
- "redhotmagma-graphics-editor": "1.57.11",
40
- "redhotmagma-visualization": "1.57.11",
39
+ "redhotmagma-graphics-editor": "1.57.12",
40
+ "redhotmagma-visualization": "1.57.12",
41
41
  "redux": "^4.1.0",
42
42
  "redux-logger": "^3.0.6",
43
43
  "redux-persist": "^5.10.0",
@@ -154,6 +154,7 @@ const externalConfiguration = {
154
154
  allowedImageUploadFormats: 'jpg,jpeg,svg,png,pdf,bmp,tif,tiff,eps,ai,gif', // the image formats users can upload to designareas / designer items
155
155
  includeMetricContentSize: false, // set true to include the metric content size in the design data
156
156
  bulkNamesPerNameDesignFiles: false, // set true to generate individual production svgs (-> production pdf in zip download) for each bulk name
157
+ // autoShrinkTextOnFontChange: true, // shrink text to stay inside the canvas when changing to a wider/taller font
157
158
  },*/
158
159
 
159
160
  //vectorizeImageQuality: 45000,
@@ -16,6 +16,7 @@ import { hasBackgroundColor } from 'App/Reducers/DesignData/Selectors';
16
16
  import { t } from 'Framework/i18n';
17
17
  import { isOriginalVector } from '../../Utils/Transformers';
18
18
  import { useSelector } from 'react-redux';
19
+ import { Services } from 'App/ServiceLocator';
19
20
 
20
21
  const styles = theme => ({
21
22
  root: {
@@ -222,8 +223,9 @@ const DesignerSelectionToolbox = props => {
222
223
  return;
223
224
  }
224
225
 
225
- canvas.selectedObject.fontItem = createFontItemProps(
226
- fontItem
226
+ Services.designer.changeTextFontItem(
227
+ canvas.selectedObject,
228
+ createFontItemProps(fontItem)
227
229
  );
228
230
  }}
229
231
  minSize={selectedObject.fontSizeMin}
@@ -366,8 +368,9 @@ const DesignerSelectionToolbox = props => {
366
368
  isCustomFont: true,
367
369
  };
368
370
  addCustomFont(fontItem);
369
- canvas.selectedObject.fontItem = createFontItemProps(
370
- fontItem
371
+ Services.designer.changeTextFontItem(
372
+ canvas.selectedObject,
373
+ createFontItemProps(fontItem)
371
374
  );
372
375
  toggleCustomFontOverlay(false);
373
376
  }}
@@ -267,6 +267,45 @@ export default class DesignerService {
267
267
  }
268
268
  }
269
269
 
270
+ changeTextFontItem(text, fontItemProps) {
271
+ if (!text || text.type !== 'Text') {
272
+ return;
273
+ }
274
+
275
+ if (getConf('designer.autoShrinkTextOnFontChange', true)) {
276
+ this.shrinkTextAfterFontChange(text, fontItemProps);
277
+ } else {
278
+ text.fontItem = fontItemProps;
279
+ }
280
+ }
281
+
282
+ shrinkTextAfterFontChange(text, fontItemProps) {
283
+ const wasInside = text.isFullyInsideCanvas();
284
+ const maxEffectiveFontSize = text.fontSize * text.scaling;
285
+
286
+ text.fontItem = fontItemProps;
287
+
288
+ if (!wasInside || text.locked || text.autoFit) {
289
+ return;
290
+ }
291
+
292
+ if (text.isFullyInsideCanvas()) {
293
+ return;
294
+ }
295
+
296
+ const maxScaling = maxEffectiveFontSize / text.fontSize;
297
+
298
+ text.shrinkToFitCanvas({
299
+ enlarge: false,
300
+ updatePosition: false,
301
+ maxScaling,
302
+ });
303
+
304
+ if (typeof text.commitScalingToFontSize === 'function') {
305
+ text.commitScalingToFontSize(maxEffectiveFontSize);
306
+ }
307
+ }
308
+
270
309
  checkDesignElementRestrictions(targetElementType) {
271
310
  const state = Services.store.state;
272
311
  const designData = getDesignDataForSelectedDesignArea(state);
@@ -2,6 +2,11 @@ import DesignerService from '../DesignerService';
2
2
  import ServiceLocator from '../../ServiceLocator';
3
3
  import { SET_SELECTED_IMAGE } from '../../Reducers/ImageGallery/Actions';
4
4
  import DesignDataService from '../DesignDataService';
5
+ import { getConf } from '../../configuration';
6
+
7
+ jest.mock('../../configuration', () => ({
8
+ getConf: jest.fn((key, defaultValue) => defaultValue),
9
+ }));
5
10
 
6
11
  describe('Services/DesignerService', () => {
7
12
  it('openImageEditDialog selects the edited image and loads the tags and gallery images', async () => {
@@ -170,4 +175,102 @@ describe('Services/DesignerService', () => {
170
175
  `"<span data-placeholder=\\"true\\"><span style='color: #f73429; font-family: \\"Lobster\\"; font-weight: normal; font-style: normal;' data-color='{\\"color\\":\\"red\\",\\"palette\\":\\"default\\"}'>sample text to be replaced</span></span>"`
171
176
  );
172
177
  });
178
+
179
+ describe('changeTextFontItem', () => {
180
+ const createTextMock = (overrides = {}) => ({
181
+ type: 'Text',
182
+ fontSize: 20,
183
+ scaling: 1,
184
+ x: 30,
185
+ y: 40,
186
+ locked: false,
187
+ autoFit: false,
188
+ fontItem: {},
189
+ isFullyInsideCanvas: jest.fn(() => true),
190
+ shrinkToFitCanvas: jest.fn(),
191
+ commitScalingToFontSize: jest.fn(),
192
+ ...overrides,
193
+ });
194
+
195
+ beforeEach(() => {
196
+ getConf.mockImplementation((key, defaultValue) => defaultValue);
197
+ });
198
+
199
+ it('applies font item and shrinks when text was inside but overflows after font change', () => {
200
+ const service = new DesignerService();
201
+ const text = createTextMock({
202
+ isFullyInsideCanvas: jest
203
+ .fn()
204
+ .mockReturnValueOnce(true)
205
+ .mockReturnValueOnce(false),
206
+ });
207
+ const fontItemProps = { family: 'Arial' };
208
+
209
+ service.changeTextFontItem(text, fontItemProps);
210
+
211
+ expect(text.fontItem).toBe(fontItemProps);
212
+ expect(text.isFullyInsideCanvas).toHaveBeenCalledTimes(2);
213
+ expect(text.shrinkToFitCanvas).toHaveBeenCalledWith({
214
+ enlarge: false,
215
+ updatePosition: false,
216
+ maxScaling: 1,
217
+ });
218
+ expect(text.commitScalingToFontSize).toHaveBeenCalledWith(20);
219
+ });
220
+
221
+ it('does not shrink when text still fits inside the canvas after font change', () => {
222
+ const service = new DesignerService();
223
+ const text = createTextMock({
224
+ isFullyInsideCanvas: jest.fn(() => true),
225
+ });
226
+
227
+ service.changeTextFontItem(text, { family: 'Arial' });
228
+
229
+ expect(text.fontItem).toEqual({ family: 'Arial' });
230
+ expect(text.isFullyInsideCanvas).toHaveBeenCalledTimes(2);
231
+ expect(text.shrinkToFitCanvas).not.toHaveBeenCalled();
232
+ expect(text.commitScalingToFontSize).not.toHaveBeenCalled();
233
+ });
234
+
235
+ it('does not shrink when text was not fully inside the canvas', () => {
236
+ const service = new DesignerService();
237
+ const text = createTextMock({
238
+ isFullyInsideCanvas: jest.fn(() => false),
239
+ });
240
+
241
+ service.changeTextFontItem(text, { family: 'Arial' });
242
+
243
+ expect(text.shrinkToFitCanvas).not.toHaveBeenCalled();
244
+ });
245
+
246
+ it('does not shrink locked or autoFit text', () => {
247
+ const service = new DesignerService();
248
+ const fontItemProps = { family: 'Arial' };
249
+ const lockedText = createTextMock({ locked: true });
250
+ service.shrinkTextAfterFontChange(lockedText, fontItemProps);
251
+ expect(lockedText.fontItem).toBe(fontItemProps);
252
+ expect(lockedText.shrinkToFitCanvas).not.toHaveBeenCalled();
253
+
254
+ const autoFitText = createTextMock({ autoFit: true });
255
+ service.shrinkTextAfterFontChange(autoFitText, fontItemProps);
256
+ expect(autoFitText.fontItem).toBe(fontItemProps);
257
+ expect(autoFitText.shrinkToFitCanvas).not.toHaveBeenCalled();
258
+ });
259
+
260
+ it('skips shrink when autoShrinkTextOnFontChange is disabled', () => {
261
+ getConf.mockImplementation((key, defaultValue) => {
262
+ if (key === 'designer.autoShrinkTextOnFontChange') {
263
+ return false;
264
+ }
265
+ return defaultValue;
266
+ });
267
+ const service = new DesignerService();
268
+ const text = createTextMock();
269
+
270
+ service.changeTextFontItem(text, { family: 'Arial' });
271
+
272
+ expect(text.isFullyInsideCanvas).not.toHaveBeenCalled();
273
+ expect(text.shrinkToFitCanvas).not.toHaveBeenCalled();
274
+ });
275
+ });
173
276
  });
@@ -229,6 +229,7 @@ let applicationConfiguration = {
229
229
  allowedImageUploadFormats: 'jpg,jpeg,svg,png,pdf,bmp,tif,tiff,eps,ai,gif', // the image formats users can upload to designareas / designer items
230
230
  includeMetricContentSize: false, // set true to include the metric content size in the design data
231
231
  bulkNamesPerNameDesignFiles: false, // set true to generate individual production svgs (-> production pdf in zip download) for each bulk name
232
+ autoShrinkTextOnFontChange: true, // shrink text to stay inside the canvas when changing to a wider/taller font
232
233
  },
233
234
 
234
235
  vectorizeImageQuality: 45000,