@arbisoft/react-design-tool 1.0.56 → 1.0.61
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/README.md +75 -70
- package/dist/cjs/index.js +150 -126
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +150 -126
- package/dist/esm/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,19 +12,37 @@ With this tool, you can:
|
|
|
12
12
|
|
|
13
13
|
Perfect for integrating into applications that require user-driven visual content creation.
|
|
14
14
|
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## 🔔 What’s New
|
|
18
|
+
|
|
19
|
+
- **Auto-placement for QR ID**: When enabled, the QR ID text is **automatically positioned above the Location text** (`LOCATION_ELEMENT_ID`).
|
|
20
|
+
If the Location element doesn’t exist, it’s **centered on the canvas**.
|
|
21
|
+
- **Persistent QR ID across template switches**: If the QR ID was visible before switching templates, it stays visible and **reflows** for the new template.
|
|
22
|
+
- **No more “ghost selection”**: Selection is cleared when the selected element no longer exists after a template/elements change.
|
|
23
|
+
- **New imperative API**: `reflowQrId()` lets you programmatically re-snap the QR ID above Location (or center) at any time.
|
|
24
|
+
|
|
25
|
+
> **Heads up:** `qrIdText` **no longer controls placement**. Position is computed automatically from the Location element or canvas center. See the updated “QR ID Controls” section.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
15
29
|
## 🎬 Studio Preview
|
|
16
30
|
|
|
17
31
|
**Live Walkthrough (GIF)**
|
|
18
32
|
|
|
19
33
|

|
|
20
34
|
|
|
35
|
+
---
|
|
36
|
+
|
|
21
37
|
## 🖥️ Demo
|
|
22
38
|
|
|
23
39
|
Check out the live demo here:
|
|
24
40
|
|
|
25
41
|
[](https://codesandbox.io/p/sandbox/fdftlr)
|
|
26
42
|
|
|
27
|
-
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## 📦 Installation (React ≥ 19)
|
|
28
46
|
|
|
29
47
|
```bash
|
|
30
48
|
npm install @arbisoft/react-design-tool
|
|
@@ -40,13 +58,13 @@ yarn add @arbisoft/react-design-tool
|
|
|
40
58
|
#### ⚠️ Important: Installation Guide for React 18 and Below
|
|
41
59
|
|
|
42
60
|
```bash
|
|
43
|
-
npm install @arbisoft/react-design-tool@1.0.
|
|
61
|
+
npm install @arbisoft/react-design-tool@1.0.60
|
|
44
62
|
```
|
|
45
63
|
|
|
46
64
|
OR
|
|
47
65
|
|
|
48
66
|
```bash
|
|
49
|
-
yarn add @arbisoft/react-design-tool@1.0.
|
|
67
|
+
yarn add @arbisoft/react-design-tool@1.0.60
|
|
50
68
|
|
|
51
69
|
```
|
|
52
70
|
|
|
@@ -56,38 +74,45 @@ yarn add @arbisoft/react-design-tool@1.0.55
|
|
|
56
74
|
import React, { useRef } from 'react';
|
|
57
75
|
import { Studio } from '@arbisoft/react-design-tool';
|
|
58
76
|
|
|
59
|
-
function MyComponent() {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
77
|
+
export default function MyComponent() {
|
|
78
|
+
const studioRef = useRef<React.ElementRef<typeof Studio>>(null);
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<>
|
|
82
|
+
{/* Optional: a button to re-snap QR ID above the Location text */}
|
|
83
|
+
<button onClick={() => studioRef.current?.reflowQrId?.()}>
|
|
84
|
+
Realign QR ID
|
|
85
|
+
</button>
|
|
86
|
+
|
|
87
|
+
<Studio
|
|
88
|
+
ref={studioRef}
|
|
89
|
+
defaultTemplatesList={[]}
|
|
90
|
+
customTemplatesList={[]}
|
|
91
|
+
defaultImages={[]}
|
|
92
|
+
customImages={[]}
|
|
93
|
+
uploadImageCallBack={async (file) => {
|
|
94
|
+
// Upload logic here
|
|
95
|
+
return 'https://your-cdn.com/uploaded-image.png';
|
|
96
|
+
}}
|
|
97
|
+
elementsList={[]}
|
|
98
|
+
qrLink="https://example.com"
|
|
99
|
+
showQrIdToggle
|
|
100
|
+
qrId="LOT-22-7B"
|
|
101
|
+
disableWhiteLabel
|
|
102
|
+
title="New Title"
|
|
103
|
+
styleProps={{ primaryColor: 'red' }}
|
|
104
|
+
defaultText="Your Default Text"
|
|
105
|
+
onSave={async (data) => {
|
|
106
|
+
console.log('Saved data:', data);
|
|
107
|
+
// { elements: [...], image: 'data:image/png;base64,...' }
|
|
108
|
+
}}
|
|
109
|
+
saveButtonText="Save Progress"
|
|
110
|
+
locale="en"
|
|
111
|
+
zoomLevel={100}
|
|
112
|
+
/>
|
|
113
|
+
</>
|
|
114
|
+
);
|
|
88
115
|
}
|
|
89
|
-
|
|
90
|
-
export default MyComponent;
|
|
91
116
|
```
|
|
92
117
|
|
|
93
118
|
## Props Configuration
|
|
@@ -415,24 +440,19 @@ Used to set configure allowed images formats for our gallert
|
|
|
415
440
|
<Studio allowedFormats={['png', 'jpg']} />
|
|
416
441
|
```
|
|
417
442
|
|
|
418
|
-
|
|
443
|
+
## 🆕 (Updated) QR ID Controls
|
|
419
444
|
|
|
420
|
-
|
|
445
|
+
### 24. `showQrIdToggle` (boolean)
|
|
421
446
|
|
|
422
|
-
Shows the **“Show QR ID”** toggle in the
|
|
423
|
-
If `true`, the user can add/remove a QR ID text element on the canvas.
|
|
447
|
+
Shows the **“Show QR ID”** toggle in the sidebar.
|
|
424
448
|
|
|
425
|
-
|
|
426
|
-
```jsx
|
|
449
|
+
```tsx
|
|
427
450
|
<Studio showQrIdToggle />
|
|
428
451
|
```
|
|
429
452
|
|
|
430
453
|
#### 25. `qrId` (String | Number)
|
|
431
454
|
|
|
432
|
-
The value
|
|
433
|
-
|
|
434
|
-
- If `qrId` is falsy (`null`, `undefined`, `''`, `0`), enabling the toggle will **not** add the QR ID text.
|
|
435
|
-
- When toggled off and back on, the QR ID text is restored with the **last used** position/style (cached).
|
|
455
|
+
The value rendered in the QR ID text when the toggle is ON.
|
|
436
456
|
|
|
437
457
|
**Example:**
|
|
438
458
|
```jsx
|
|
@@ -441,38 +461,23 @@ The value to render as the **QR ID** when the “Show QR ID” toggle is enabled
|
|
|
441
461
|
qrId="FA-98231"
|
|
442
462
|
/>
|
|
443
463
|
```
|
|
444
|
-
#### 26. `qrIdText` (
|
|
464
|
+
#### 26. `qrIdText` (**deprecated for placement**)
|
|
445
465
|
|
|
446
|
-
|
|
447
|
-
|
|
466
|
+
> **Deprecated for positioning.**
|
|
467
|
+
> The QR ID position is now **computed automatically**:
|
|
448
468
|
|
|
449
|
-
|
|
469
|
+
- If `LOCATION_ELEMENT_ID` (Location text) exists → QR ID is centered **above it**.
|
|
470
|
+
- Otherwise → QR ID is **centered on the canvas**.
|
|
471
|
+
|
|
472
|
+
You may still pass stylistic hints that your theme may read (e.g., `color`),
|
|
473
|
+
but **`x`/`y` positioning fields are ignored** for insert/reflow.
|
|
450
474
|
|
|
451
|
-
| Field | Type | Default | Description |
|
|
452
|
-
|-------------|----------------------------------|-------------|-----------------------------------------------------------------------------------------------|
|
|
453
|
-
| `x` | `number` | — | **Required** for custom placement. X position (base canvas units). |
|
|
454
|
-
| `y` | `number` | — | **Required** for custom placement. Y position (base canvas units). |
|
|
455
|
-
| `color` | `string` | theme text | Text color (e.g., `'#111'`, `'rgba(255,255,255,0.9)'`). |
|
|
456
|
-
| `width` | `number` | `240` | Text box width (enables neat alignment). |
|
|
457
|
-
| `textAlign` | `'left' \| 'center' \| 'right'` | `'center'` | Horizontal alignment within the text box. |
|
|
458
|
-
| `pill` | `boolean` | `false` | If `true`, renders a subtle rounded pill behind the text for readability. |
|
|
459
|
-
| `pillColor` | `string` | auto | Pill fill color. If omitted (and `pill: true`), a sensible default is chosen from text color. |
|
|
460
|
-
| `outline` | `boolean` | `false` | If `true`, adds a thin text stroke and soft shadow for contrast on busy/dark backgrounds. |
|
|
461
475
|
|
|
462
476
|
**Example:**
|
|
463
|
-
|
|
477
|
+
|
|
478
|
+
```tsx
|
|
464
479
|
<Studio
|
|
465
480
|
showQrIdToggle
|
|
466
481
|
qrId="LOT-22-7B"
|
|
467
|
-
qrIdText={{
|
|
468
|
-
x: 420, // base canvas coords (unscaled)
|
|
469
|
-
y: 760,
|
|
470
|
-
width: 180,
|
|
471
|
-
textAlign: 'right',
|
|
472
|
-
color: '#FFFFFF',
|
|
473
|
-
pill: true,
|
|
474
|
-
pillColor: 'rgba(0,0,0,0.45)',
|
|
475
|
-
outline: true,
|
|
476
|
-
}}
|
|
477
482
|
/>
|
|
478
|
-
|
|
483
|
+
|
package/dist/cjs/index.js
CHANGED
|
@@ -146,6 +146,9 @@ function _nonIterableRest() {
|
|
|
146
146
|
function _nonIterableSpread() {
|
|
147
147
|
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
148
148
|
}
|
|
149
|
+
function _objectDestructuringEmpty(t) {
|
|
150
|
+
if (null == t) throw new TypeError("Cannot destructure " + t);
|
|
151
|
+
}
|
|
149
152
|
function ownKeys(e, r) {
|
|
150
153
|
var t = Object.keys(e);
|
|
151
154
|
if (Object.getOwnPropertySymbols) {
|
|
@@ -2075,7 +2078,6 @@ var TEXT_DICTIONARY = {
|
|
|
2075
2078
|
};
|
|
2076
2079
|
var LOCATION_ELEMENT_ID = 'element-location-text';
|
|
2077
2080
|
var QRID_ELEMENT_ID = 'element-qrid-text';
|
|
2078
|
-
var QRID_ELEMENT_PILL = 'element-qrid-text-pill';
|
|
2079
2081
|
|
|
2080
2082
|
var SideBar = function SideBar(_ref) {
|
|
2081
2083
|
var _TEXT_DICTIONARY$lang, _TEXT_DICTIONARY$lang2, _TEXT_DICTIONARY$lang3, _TEXT_DICTIONARY$lang4, _TEXT_DICTIONARY$lang5, _TEXT_DICTIONARY$lang6;
|
|
@@ -2762,7 +2764,7 @@ var StyledText = styled.p(_templateObject2$g || (_templateObject2$g = _taggedTem
|
|
|
2762
2764
|
return "".concat(paddingLeft, "px");
|
|
2763
2765
|
});
|
|
2764
2766
|
|
|
2765
|
-
var _excluded
|
|
2767
|
+
var _excluded = ["image"];
|
|
2766
2768
|
var calculatePercentageValue = function calculatePercentageValue(value, percentage) {
|
|
2767
2769
|
return value * percentage / 100;
|
|
2768
2770
|
};
|
|
@@ -2925,7 +2927,7 @@ var removeImageProperty = function removeImageProperty() {
|
|
|
2925
2927
|
if ('image' in elem) {
|
|
2926
2928
|
// eslint-disable-next-line no-unused-vars
|
|
2927
2929
|
elem.image;
|
|
2928
|
-
var rest = _objectWithoutProperties(elem, _excluded
|
|
2930
|
+
var rest = _objectWithoutProperties(elem, _excluded);
|
|
2929
2931
|
return rest;
|
|
2930
2932
|
}
|
|
2931
2933
|
return elem;
|
|
@@ -6435,7 +6437,6 @@ var isPropValid = /* #__PURE__ */memoize(function (prop) {
|
|
|
6435
6437
|
/* Z+1 */
|
|
6436
6438
|
);
|
|
6437
6439
|
|
|
6438
|
-
var _excluded = ["ref"];
|
|
6439
6440
|
/**
|
|
6440
6441
|
* @typedef {Object} StudioProps
|
|
6441
6442
|
* @property {string} [title]
|
|
@@ -6455,7 +6456,8 @@ var _excluded = ["ref"];
|
|
|
6455
6456
|
* @property {'en'|'ru'|'pl'|'de'|'es'|'fr'|'it'} [locale]
|
|
6456
6457
|
* @property {Function} [onCreateNewTemplate] - called when user creates a new template, passes new canvas elements
|
|
6457
6458
|
* @property {Function} [onTemplateSelect] - called when a template is selected, passes template id
|
|
6458
|
-
* @property {Function} [uploadQRLogoImage]
|
|
6459
|
+
* @property {Function} [uploadQRLogoImage]
|
|
6460
|
+
* - Optional callback to upload the QR logo image. Should return a string or an object with `{ url }`
|
|
6459
6461
|
* @property {number} [zoomLevel] - Optional zoom level (e.g. 100 for 100%)
|
|
6460
6462
|
* @property {boolean} [showBackgroundImagePicker] - Used to set background image on entire canvas
|
|
6461
6463
|
* @property {boolean} [showOpacityPicker] - Related to showBackgroundImagePicker and it's opacity
|
|
@@ -6468,7 +6470,7 @@ var _excluded = ["ref"];
|
|
|
6468
6470
|
* @type {React.ForwardRefExoticComponent<StudioProps & React.RefAttributes<HTMLDivElement>>}
|
|
6469
6471
|
*/
|
|
6470
6472
|
var Studio = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
|
|
6471
|
-
var _elements$elements$fi, _elements$
|
|
6473
|
+
var _elements$elements$fi, _elements$find5, _elements$find6, _elements$find7;
|
|
6472
6474
|
var _ref$title = _ref.title,
|
|
6473
6475
|
title = _ref$title === void 0 ? '' : _ref$title,
|
|
6474
6476
|
_ref$defaultQrLogo = _ref.defaultQrLogo,
|
|
@@ -6506,11 +6508,10 @@ var Studio = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
|
|
|
6506
6508
|
_ref$showQrIdToggle = _ref.showQrIdToggle,
|
|
6507
6509
|
showQrIdToggle = _ref$showQrIdToggle === void 0 ? false : _ref$showQrIdToggle,
|
|
6508
6510
|
_ref$qrId = _ref.qrId,
|
|
6509
|
-
qrId = _ref$qrId === void 0 ? null : _ref$qrId
|
|
6510
|
-
_ref$qrIdText = _ref.qrIdText,
|
|
6511
|
-
qrIdText = _ref$qrIdText === void 0 ? null : _ref$qrIdText;
|
|
6511
|
+
qrId = _ref$qrId === void 0 ? null : _ref$qrId;
|
|
6512
6512
|
var stageRef = React.useRef(null);
|
|
6513
6513
|
var elementCacheRef = React.useRef({});
|
|
6514
|
+
var qrIdActiveRef = React.useRef(false);
|
|
6514
6515
|
var _useState = React.useState(null),
|
|
6515
6516
|
_useState2 = _slicedToArray(_useState, 2),
|
|
6516
6517
|
copiedElement = _useState2[0],
|
|
@@ -6620,7 +6621,59 @@ var Studio = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
|
|
|
6620
6621
|
_useState52 = _slicedToArray(_useState51, 2),
|
|
6621
6622
|
defaultTextProps = _useState52[0],
|
|
6622
6623
|
setDefaultTextProps = _useState52[1];
|
|
6624
|
+
var _useState53 = React.useState(qrId),
|
|
6625
|
+
_useState54 = _slicedToArray(_useState53, 2),
|
|
6626
|
+
currentQrId = _useState54[0],
|
|
6627
|
+
setCurrentQrId = _useState54[1];
|
|
6623
6628
|
var overallLoading = loadingFonts || loadingImages || loadingUploadImage || loading;
|
|
6629
|
+
var getPageDims = React.useCallback(function () {
|
|
6630
|
+
var _base$find;
|
|
6631
|
+
var base = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : elements;
|
|
6632
|
+
var sizeKey = (base === null || base === void 0 || (_base$find = base.find(function (e) {
|
|
6633
|
+
return (e === null || e === void 0 ? void 0 : e.type) === (elementTypes === null || elementTypes === void 0 ? void 0 : elementTypes.pageSize);
|
|
6634
|
+
})) === null || _base$find === void 0 ? void 0 : _base$find.size) || pageSizes.A4;
|
|
6635
|
+
return pageSizesDimensions[sizeKey] || pageSizesDimensions[pageSizes.A4];
|
|
6636
|
+
}, [elements]);
|
|
6637
|
+
var findById = React.useCallback(function (id) {
|
|
6638
|
+
var base = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : elements;
|
|
6639
|
+
return base.find(function (e) {
|
|
6640
|
+
return e.id === id;
|
|
6641
|
+
});
|
|
6642
|
+
}, [elements]);
|
|
6643
|
+
|
|
6644
|
+
/**
|
|
6645
|
+
* Compute the QR-ID frame:
|
|
6646
|
+
* - If LOCATION_ELEMENT_ID exists: center-align above it
|
|
6647
|
+
* - Otherwise: center of page
|
|
6648
|
+
*/
|
|
6649
|
+
var computeQrIdFrame = React.useCallback(function () {
|
|
6650
|
+
var _ref2, _loc$fontSize, _loc$x, _loc$width, _loc$y, _ref3, _loc$color, _loc$fontFamily;
|
|
6651
|
+
var base = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : elements;
|
|
6652
|
+
var _getPageDims = getPageDims(base),
|
|
6653
|
+
Cw = _getPageDims.width,
|
|
6654
|
+
Ch = _getPageDims.height;
|
|
6655
|
+
var loc = findById(LOCATION_ELEMENT_ID, base);
|
|
6656
|
+
var fs = Math.max(14, Math.min(28, (_ref2 = (_loc$fontSize = loc === null || loc === void 0 ? void 0 : loc.fontSize) !== null && _loc$fontSize !== void 0 ? _loc$fontSize : defaultTextProps === null || defaultTextProps === void 0 ? void 0 : defaultTextProps.fontSize) !== null && _ref2 !== void 0 ? _ref2 : 16));
|
|
6657
|
+
var GAP = 8; // vertical gap above location text line
|
|
6658
|
+
var width = Number.isFinite(loc === null || loc === void 0 ? void 0 : loc.width) ? loc.width : 240;
|
|
6659
|
+
|
|
6660
|
+
// center horizontally over location text (or page)
|
|
6661
|
+
var x = loc ? Math.max(0, ((_loc$x = loc.x) !== null && _loc$x !== void 0 ? _loc$x : 0) + (((_loc$width = loc.width) !== null && _loc$width !== void 0 ? _loc$width : width) - width) / 2) : Math.max(0, (Cw - width) / 2);
|
|
6662
|
+
|
|
6663
|
+
// place just above location text line (or vertical center)
|
|
6664
|
+
var y = loc ? Math.max(0, ((_loc$y = loc.y) !== null && _loc$y !== void 0 ? _loc$y : 0) - fs - GAP) : Math.max(0, (Ch - fs) / 2);
|
|
6665
|
+
var color = (_ref3 = (_loc$color = loc === null || loc === void 0 ? void 0 : loc.color) !== null && _loc$color !== void 0 ? _loc$color : defaultTextProps === null || defaultTextProps === void 0 ? void 0 : defaultTextProps.color) !== null && _ref3 !== void 0 ? _ref3 : '#111';
|
|
6666
|
+
var fontFamily = (_loc$fontFamily = loc === null || loc === void 0 ? void 0 : loc.fontFamily) !== null && _loc$fontFamily !== void 0 ? _loc$fontFamily : defaultTextProps === null || defaultTextProps === void 0 ? void 0 : defaultTextProps.fontFamily;
|
|
6667
|
+
return {
|
|
6668
|
+
x: x,
|
|
6669
|
+
y: y,
|
|
6670
|
+
width: width,
|
|
6671
|
+
textAlign: 'center',
|
|
6672
|
+
fontSize: fs,
|
|
6673
|
+
color: color,
|
|
6674
|
+
fontFamily: fontFamily
|
|
6675
|
+
};
|
|
6676
|
+
}, [getPageDims, findById, defaultTextProps]);
|
|
6624
6677
|
var undo = React.useCallback(function () {
|
|
6625
6678
|
if (history.length > 0) {
|
|
6626
6679
|
setSelectedElement(null);
|
|
@@ -6676,9 +6729,41 @@ var Studio = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
|
|
|
6676
6729
|
setLoading: setLoading,
|
|
6677
6730
|
undoCount: history.length,
|
|
6678
6731
|
hasChanges: history.length > 0,
|
|
6679
|
-
redoCount: redoStack.length
|
|
6732
|
+
redoCount: redoStack.length,
|
|
6733
|
+
updateQrId: function updateQrId(newId) {
|
|
6734
|
+
setCurrentQrId(newId);
|
|
6735
|
+
var idx = elements.findIndex(function (e) {
|
|
6736
|
+
return e.id === QRID_ELEMENT_ID;
|
|
6737
|
+
});
|
|
6738
|
+
if (idx > -1) {
|
|
6739
|
+
var frame = computeQrIdFrame(elements);
|
|
6740
|
+
var newElements = _toConsumableArray(elements);
|
|
6741
|
+
newElements[idx] = _objectSpread2(_objectSpread2({}, newElements[idx]), {}, {
|
|
6742
|
+
text: String(newId)
|
|
6743
|
+
}, frame);
|
|
6744
|
+
saveHistory(newElements);
|
|
6745
|
+
if ((selectedElement === null || selectedElement === void 0 ? void 0 : selectedElement.id) === QRID_ELEMENT_ID) setSelectedElement(newElements[idx]);
|
|
6746
|
+
}
|
|
6747
|
+
},
|
|
6748
|
+
reflowQrId: function reflowQrId() {
|
|
6749
|
+
var idx = elements.findIndex(function (e) {
|
|
6750
|
+
return e.id === QRID_ELEMENT_ID;
|
|
6751
|
+
});
|
|
6752
|
+
if (idx === -1) return;
|
|
6753
|
+
var frame = computeQrIdFrame(elements);
|
|
6754
|
+
var copy = _toConsumableArray(elements);
|
|
6755
|
+
copy[idx] = _objectSpread2(_objectSpread2({}, copy[idx]), frame);
|
|
6756
|
+
saveHistory(copy);
|
|
6757
|
+
}
|
|
6680
6758
|
};
|
|
6681
6759
|
});
|
|
6760
|
+
React.useEffect(function () {
|
|
6761
|
+
if (selectedElement && !elements.some(function (e) {
|
|
6762
|
+
return e.id === selectedElement.id;
|
|
6763
|
+
})) {
|
|
6764
|
+
setSelectedElement(null);
|
|
6765
|
+
}
|
|
6766
|
+
}, [elements, selectedElement]);
|
|
6682
6767
|
React.useEffect(function () {
|
|
6683
6768
|
if (typeof zoomLevel === 'number') {
|
|
6684
6769
|
setZoomPercentage(zoomLevel);
|
|
@@ -6767,16 +6852,15 @@ var Studio = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
|
|
|
6767
6852
|
});
|
|
6768
6853
|
if (foundLoc) {
|
|
6769
6854
|
// store a clean copy (no runtime refs)
|
|
6770
|
-
var
|
|
6771
|
-
|
|
6772
|
-
var rest = _objectWithoutProperties(_ref2, _excluded);
|
|
6855
|
+
var _ref4 = foundLoc || {},
|
|
6856
|
+
rest = _extends({}, (_objectDestructuringEmpty(_ref4), _ref4));
|
|
6773
6857
|
elementCacheRef.current[LOCATION_ELEMENT_ID] = _objectSpread2({}, rest);
|
|
6774
6858
|
}
|
|
6775
6859
|
}, _toConsumableArray(elementsList));
|
|
6776
6860
|
var LoadImages = function LoadImages(elems) {
|
|
6777
6861
|
setLoadingImages(true);
|
|
6778
|
-
preloadRelevantImages(elems).then(function (
|
|
6779
|
-
var errors =
|
|
6862
|
+
preloadRelevantImages(elems).then(function (_ref5) {
|
|
6863
|
+
var errors = _ref5.errors;
|
|
6780
6864
|
// console.log('✅ Loaded images:', successes);
|
|
6781
6865
|
if ((errors === null || errors === void 0 ? void 0 : errors.length) > 0) {
|
|
6782
6866
|
console.log('❌ Failed images:', errors);
|
|
@@ -6815,6 +6899,9 @@ var Studio = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
|
|
|
6815
6899
|
return e.type === elementTypes.text && e.id === QRID_ELEMENT_ID;
|
|
6816
6900
|
});
|
|
6817
6901
|
}, [elements]);
|
|
6902
|
+
React.useEffect(function () {
|
|
6903
|
+
qrIdActiveRef.current = hasQrIdText; // keep this in sync
|
|
6904
|
+
}, [hasQrIdText]);
|
|
6818
6905
|
var removeElementById = function removeElementById(id) {
|
|
6819
6906
|
var idx = elements.findIndex(function (e) {
|
|
6820
6907
|
return e.id === id;
|
|
@@ -6823,16 +6910,11 @@ var Studio = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
|
|
|
6823
6910
|
var snapshot = _objectSpread2({}, elements[idx]);
|
|
6824
6911
|
delete snapshot.ref;
|
|
6825
6912
|
// cache latest props before removing
|
|
6826
|
-
|
|
6913
|
+
if (id !== QRID_ELEMENT_ID) {
|
|
6914
|
+
elementCacheRef.current[id] = snapshot; // never cache QR-ID
|
|
6915
|
+
}
|
|
6827
6916
|
var next = elements.slice();
|
|
6828
6917
|
next.splice(idx, 1);
|
|
6829
|
-
if (id === QRID_ELEMENT_ID) {
|
|
6830
|
-
// remove its pill if present
|
|
6831
|
-
var pillId = "".concat(QRID_ELEMENT_ID, "-pill");
|
|
6832
|
-
for (var i = next.length - 1; i >= 0; i--) {
|
|
6833
|
-
if (next[i].id === pillId) next.splice(i, 1);
|
|
6834
|
-
}
|
|
6835
|
-
}
|
|
6836
6918
|
if ((selectedElement === null || selectedElement === void 0 ? void 0 : selectedElement.id) === id) setSelectedElement(null);
|
|
6837
6919
|
saveHistory(next);
|
|
6838
6920
|
}
|
|
@@ -6850,88 +6932,23 @@ var Studio = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
|
|
|
6850
6932
|
setSelectedElement(toAdd);
|
|
6851
6933
|
};
|
|
6852
6934
|
var addQrIdText = function addQrIdText() {
|
|
6853
|
-
var
|
|
6854
|
-
if (!
|
|
6855
|
-
|
|
6856
|
-
|
|
6857
|
-
var
|
|
6858
|
-
if (cached) {
|
|
6859
|
-
var toAdd = _objectSpread2(_objectSpread2({}, cached), {}, {
|
|
6860
|
-
id: QRID_ELEMENT_ID,
|
|
6861
|
-
text: String(qrId)
|
|
6862
|
-
});
|
|
6863
|
-
saveHistory([].concat(_toConsumableArray(elements), [toAdd]));
|
|
6864
|
-
setSelectedElement(toAdd);
|
|
6865
|
-
return;
|
|
6866
|
-
}
|
|
6867
|
-
|
|
6868
|
-
// 2) Otherwise, build from external qrIdText + sensible defaults
|
|
6869
|
-
var sizeKey = (elements === null || elements === void 0 || (_elements$find4 = elements.find(function (e) {
|
|
6870
|
-
return (e === null || e === void 0 ? void 0 : e.type) === (elementTypes === null || elementTypes === void 0 ? void 0 : elementTypes.pageSize);
|
|
6871
|
-
})) === null || _elements$find4 === void 0 ? void 0 : _elements$find4.size) || pageSizes.A4;
|
|
6872
|
-
var _pageSizesDimensions$ = pageSizesDimensions[sizeKey],
|
|
6873
|
-
Cw = _pageSizesDimensions$.width,
|
|
6874
|
-
Ch = _pageSizesDimensions$.height;
|
|
6875
|
-
var fs = (defaultTextProps === null || defaultTextProps === void 0 ? void 0 : defaultTextProps.fontSize) || 16;
|
|
6876
|
-
var lineH = fs * 1.25;
|
|
6877
|
-
|
|
6878
|
-
// --- external layout (REQUIRED x,y for custom placement) ---
|
|
6879
|
-
var hasExternal = qrIdText && typeof qrIdText.x === 'number' && typeof qrIdText.y === 'number';
|
|
6880
|
-
var x = hasExternal ? qrIdText.x : Math.max(0, (Cw - 240) / 2);
|
|
6881
|
-
var y = hasExternal ? qrIdText.y : Math.max(0, (Ch - lineH) / 2);
|
|
6882
|
-
var width = (_qrIdText$width = qrIdText === null || qrIdText === void 0 ? void 0 : qrIdText.width) !== null && _qrIdText$width !== void 0 ? _qrIdText$width : 240;
|
|
6883
|
-
var textAlign = (_qrIdText$textAlign = qrIdText === null || qrIdText === void 0 ? void 0 : qrIdText.textAlign) !== null && _qrIdText$textAlign !== void 0 ? _qrIdText$textAlign : 'center';
|
|
6884
|
-
var color = (_ref5 = (_qrIdText$color = qrIdText === null || qrIdText === void 0 ? void 0 : qrIdText.color) !== null && _qrIdText$color !== void 0 ? _qrIdText$color : defaultTextProps === null || defaultTextProps === void 0 ? void 0 : defaultTextProps.color) !== null && _ref5 !== void 0 ? _ref5 : '#111';
|
|
6885
|
-
|
|
6886
|
-
// optional readability helpers (opt-in)
|
|
6887
|
-
var wantPill = !!(qrIdText !== null && qrIdText !== void 0 && qrIdText.pill);
|
|
6888
|
-
var pillColor = (qrIdText === null || qrIdText === void 0 ? void 0 : qrIdText.pillColor) || (color === '#fff' || color.toLowerCase() === 'white' ? 'rgba(0,0,0,0.35)' : 'rgba(255,255,255,0.85)');
|
|
6889
|
-
var wantOutline = !!(qrIdText !== null && qrIdText !== void 0 && qrIdText.outline);
|
|
6890
|
-
var pillId = "".concat(QRID_ELEMENT_ID, "-pill");
|
|
6891
|
-
var vPad = 8,
|
|
6892
|
-
hPad = 10;
|
|
6893
|
-
var newElements = _toConsumableArray(elements);
|
|
6894
|
-
if (wantPill) {
|
|
6895
|
-
newElements.push({
|
|
6896
|
-
id: pillId,
|
|
6897
|
-
type: elementTypes.square,
|
|
6898
|
-
draggable: true,
|
|
6899
|
-
x: x - hPad,
|
|
6900
|
-
y: y - vPad,
|
|
6901
|
-
width: width + hPad * 2,
|
|
6902
|
-
height: lineH + vPad * 2,
|
|
6903
|
-
cornerRadius: 8,
|
|
6904
|
-
fill: pillColor,
|
|
6905
|
-
opacity: 1,
|
|
6906
|
-
stroke: 'rgba(0,0,0,0.12)',
|
|
6907
|
-
strokeWidth: 1
|
|
6908
|
-
});
|
|
6909
|
-
}
|
|
6935
|
+
var base = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : elements;
|
|
6936
|
+
if (!currentQrId || base.some(function (e) {
|
|
6937
|
+
return e.id === QRID_ELEMENT_ID;
|
|
6938
|
+
})) return;
|
|
6939
|
+
var frame = computeQrIdFrame(base);
|
|
6910
6940
|
var textProps = _objectSpread2({
|
|
6911
6941
|
id: QRID_ELEMENT_ID,
|
|
6912
6942
|
type: elementTypes.text,
|
|
6913
6943
|
draggable: true,
|
|
6914
|
-
|
|
6915
|
-
|
|
6916
|
-
|
|
6917
|
-
textAlign:
|
|
6918
|
-
|
|
6919
|
-
|
|
6920
|
-
|
|
6921
|
-
|
|
6922
|
-
color: color,
|
|
6923
|
-
textDecoration: defaultTextProps === null || defaultTextProps === void 0 ? void 0 : defaultTextProps.textDecoration,
|
|
6924
|
-
fontStyle: defaultTextProps === null || defaultTextProps === void 0 ? void 0 : defaultTextProps.fontStyle,
|
|
6925
|
-
fontWeight: (_ref6 = (_qrIdText$fontWeight = qrIdText === null || qrIdText === void 0 ? void 0 : qrIdText.fontWeight) !== null && _qrIdText$fontWeight !== void 0 ? _qrIdText$fontWeight : defaultTextProps === null || defaultTextProps === void 0 ? void 0 : defaultTextProps.fontWeight) !== null && _ref6 !== void 0 ? _ref6 : '400'
|
|
6926
|
-
}, wantOutline && {
|
|
6927
|
-
stroke: color.toLowerCase() === '#ffffff' || color.toLowerCase() === 'white' ? 'rgba(0,0,0,0.5)' : 'rgba(255,255,255,0.8)',
|
|
6928
|
-
strokeWidth: 1,
|
|
6929
|
-
shadowColor: 'rgba(0,0,0,0.4)',
|
|
6930
|
-
shadowBlur: 3,
|
|
6931
|
-
shadowOpacity: 0.8
|
|
6932
|
-
});
|
|
6933
|
-
newElements.push(textProps);
|
|
6934
|
-
saveHistory(newElements);
|
|
6944
|
+
text: String(currentQrId),
|
|
6945
|
+
fontWeight: '700',
|
|
6946
|
+
// always bold
|
|
6947
|
+
textAlign: 'center',
|
|
6948
|
+
opacity: defaultTextProps === null || defaultTextProps === void 0 ? void 0 : defaultTextProps.opacity
|
|
6949
|
+
}, frame);
|
|
6950
|
+
var next = [].concat(_toConsumableArray(base), [textProps]);
|
|
6951
|
+
saveHistory(next);
|
|
6935
6952
|
setSelectedElement(textProps);
|
|
6936
6953
|
};
|
|
6937
6954
|
var toggleLocationText = function toggleLocationText() {
|
|
@@ -7000,11 +7017,11 @@ var Studio = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
|
|
|
7000
7017
|
saveHistory([].concat(_toConsumableArray(elemClone), [newElement]));
|
|
7001
7018
|
};
|
|
7002
7019
|
var onSetPageSize = function onSetPageSize(newSize) {
|
|
7003
|
-
var _elements$
|
|
7020
|
+
var _elements$find4;
|
|
7004
7021
|
if (!newSize) return;
|
|
7005
|
-
var oldSize = (elements === null || elements === void 0 || (_elements$
|
|
7022
|
+
var oldSize = (elements === null || elements === void 0 || (_elements$find4 = elements.find(function (e) {
|
|
7006
7023
|
return (e === null || e === void 0 ? void 0 : e.type) === (elementTypes === null || elementTypes === void 0 ? void 0 : elementTypes.pageSize);
|
|
7007
|
-
})) === null || _elements$
|
|
7024
|
+
})) === null || _elements$find4 === void 0 ? void 0 : _elements$find4.size) || pageSizes.A4;
|
|
7008
7025
|
var oldDims = pageSizesDimensions[oldSize];
|
|
7009
7026
|
var newDims = pageSizesDimensions[newSize];
|
|
7010
7027
|
var scaleX = newDims.width / oldDims.width;
|
|
@@ -7261,6 +7278,7 @@ var Studio = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
|
|
|
7261
7278
|
saveHistory(_toConsumableArray(copyElements));
|
|
7262
7279
|
};
|
|
7263
7280
|
var createNewTemplate = function createNewTemplate() {
|
|
7281
|
+
var _elementsRef$current;
|
|
7264
7282
|
var elems = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [].concat(_toConsumableArray(defaultElements), [{
|
|
7265
7283
|
type: elementTypes.qr,
|
|
7266
7284
|
id: "element".concat(Date.now() + 1),
|
|
@@ -7277,19 +7295,25 @@ var Studio = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
|
|
|
7277
7295
|
opacity: 1,
|
|
7278
7296
|
logoVisible: false
|
|
7279
7297
|
}]);
|
|
7280
|
-
var
|
|
7281
|
-
|
|
7282
|
-
return element.id === QRID_ELEMENT_ID;
|
|
7298
|
+
var prevHadQrId = (_elementsRef$current = elementsRef.current) === null || _elementsRef$current === void 0 ? void 0 : _elementsRef$current.some(function (e) {
|
|
7299
|
+
return e.id === QRID_ELEMENT_ID;
|
|
7283
7300
|
});
|
|
7284
|
-
var
|
|
7285
|
-
|
|
7286
|
-
|
|
7287
|
-
if (
|
|
7288
|
-
|
|
7289
|
-
|
|
7290
|
-
|
|
7291
|
-
|
|
7292
|
-
|
|
7301
|
+
var next = _toConsumableArray(elems);
|
|
7302
|
+
|
|
7303
|
+
// If toggle was ON before and current template doesn’t include QR-ID, re-add it above Location (or center)
|
|
7304
|
+
if (prevHadQrId && !next.some(function (e) {
|
|
7305
|
+
return e.id === QRID_ELEMENT_ID;
|
|
7306
|
+
}) && showQrIdToggle && currentQrId) {
|
|
7307
|
+
var frame = computeQrIdFrame(next);
|
|
7308
|
+
next.push(_objectSpread2({
|
|
7309
|
+
id: QRID_ELEMENT_ID,
|
|
7310
|
+
type: elementTypes.text,
|
|
7311
|
+
draggable: true,
|
|
7312
|
+
text: String(currentQrId),
|
|
7313
|
+
fontWeight: '700',
|
|
7314
|
+
textAlign: 'center',
|
|
7315
|
+
opacity: defaultTextProps === null || defaultTextProps === void 0 ? void 0 : defaultTextProps.opacity
|
|
7316
|
+
}, frame));
|
|
7293
7317
|
}
|
|
7294
7318
|
setElements(_toConsumableArray(elems));
|
|
7295
7319
|
setHistory([]);
|
|
@@ -7474,7 +7498,7 @@ var Studio = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
|
|
|
7474
7498
|
}
|
|
7475
7499
|
};
|
|
7476
7500
|
var addQrLogo = /*#__PURE__*/function () {
|
|
7477
|
-
var
|
|
7501
|
+
var _ref6 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2() {
|
|
7478
7502
|
var file, result, imageUrl, reader, _t;
|
|
7479
7503
|
return _regenerator().w(function (_context2) {
|
|
7480
7504
|
while (1) switch (_context2.n) {
|
|
@@ -7530,7 +7554,7 @@ var Studio = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
|
|
|
7530
7554
|
}, _callee2, null, [[3, 5, 6, 7]]);
|
|
7531
7555
|
}));
|
|
7532
7556
|
return function addQrLogo() {
|
|
7533
|
-
return
|
|
7557
|
+
return _ref6.apply(this, arguments);
|
|
7534
7558
|
};
|
|
7535
7559
|
}();
|
|
7536
7560
|
var addLogo = function addLogo(url) {
|
|
@@ -7559,7 +7583,7 @@ var Studio = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
|
|
|
7559
7583
|
}
|
|
7560
7584
|
};
|
|
7561
7585
|
var onSaveProgress = /*#__PURE__*/function () {
|
|
7562
|
-
var
|
|
7586
|
+
var _ref7 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3() {
|
|
7563
7587
|
var processedElements, dataURL;
|
|
7564
7588
|
return _regenerator().w(function (_context3) {
|
|
7565
7589
|
while (1) switch (_context3.n) {
|
|
@@ -7593,7 +7617,7 @@ var Studio = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
|
|
|
7593
7617
|
}, _callee3);
|
|
7594
7618
|
}));
|
|
7595
7619
|
return function onSaveProgress() {
|
|
7596
|
-
return
|
|
7620
|
+
return _ref7.apply(this, arguments);
|
|
7597
7621
|
};
|
|
7598
7622
|
}();
|
|
7599
7623
|
return /*#__PURE__*/React.createElement(styled.StyleSheetManager, {
|
|
@@ -7642,12 +7666,12 @@ var Studio = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
|
|
|
7642
7666
|
onToggleQrIdText: toggleQrIdText
|
|
7643
7667
|
}), loadingFonts ? null : /*#__PURE__*/React.createElement(Editor, {
|
|
7644
7668
|
setLoading: setLoading,
|
|
7645
|
-
cuttingGuideStroke: (elements === null || elements === void 0 || (_elements$
|
|
7669
|
+
cuttingGuideStroke: (elements === null || elements === void 0 || (_elements$find5 = elements.find(function (e) {
|
|
7646
7670
|
return (e === null || e === void 0 ? void 0 : e.type) === (elementTypes === null || elementTypes === void 0 ? void 0 : elementTypes.pageSize);
|
|
7647
|
-
})) === null || _elements$
|
|
7648
|
-
cuttingGuideStrokeColor: (elements === null || elements === void 0 || (_elements$
|
|
7671
|
+
})) === null || _elements$find5 === void 0 ? void 0 : _elements$find5.cuttingGuideStroke) || 0,
|
|
7672
|
+
cuttingGuideStrokeColor: (elements === null || elements === void 0 || (_elements$find6 = elements.find(function (e) {
|
|
7649
7673
|
return (e === null || e === void 0 ? void 0 : e.type) === (elementTypes === null || elementTypes === void 0 ? void 0 : elementTypes.pageSize);
|
|
7650
|
-
})) === null || _elements$
|
|
7674
|
+
})) === null || _elements$find6 === void 0 ? void 0 : _elements$find6.cuttingGuideStrokeColor) || (theme === null || theme === void 0 ? void 0 : theme.color.black),
|
|
7651
7675
|
onChangeCuttingGuideProp: function onChangeCuttingGuideProp(type, value) {
|
|
7652
7676
|
_onChangeCuttingGuideProp(type, value);
|
|
7653
7677
|
},
|
|
@@ -7689,9 +7713,9 @@ var Studio = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
|
|
|
7689
7713
|
stageRef: stageRef,
|
|
7690
7714
|
saveHistory: saveHistory,
|
|
7691
7715
|
onChangeBackgroundImageOpacity: onChangeBackgroundImageOpacity,
|
|
7692
|
-
backgroundImageOpacity: (elements === null || elements === void 0 || (_elements$
|
|
7716
|
+
backgroundImageOpacity: (elements === null || elements === void 0 || (_elements$find7 = elements.find(function (e) {
|
|
7693
7717
|
return (e === null || e === void 0 ? void 0 : e.type) === (elementTypes === null || elementTypes === void 0 ? void 0 : elementTypes.backgroundImage);
|
|
7694
|
-
})) === null || _elements$
|
|
7718
|
+
})) === null || _elements$find7 === void 0 ? void 0 : _elements$find7.opacity) || backgroundImageOpacity,
|
|
7695
7719
|
onDeleteSelectedElement: onDeleteSelectedElement,
|
|
7696
7720
|
onCopySelectedElement: onCopySelectedElement,
|
|
7697
7721
|
onToggleLockElement: onToggleLockElement,
|