@lucablockltd/ultimate-packaging 1.0.2 → 1.1.0
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/AGENTS_README.md +288 -106
- package/dist/index.d.mts +129 -23
- package/dist/index.d.ts +129 -23
- package/dist/index.js +2167 -522
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2164 -523
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -3
package/dist/AGENTS_README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
## Quick Start
|
|
7
7
|
|
|
8
8
|
```bash
|
|
9
|
-
npm install
|
|
9
|
+
npm install @lucablockltd/ultimate-packaging
|
|
10
10
|
```
|
|
11
11
|
|
|
12
12
|
Requires `react >= 18.0.0` and `react-dom >= 18.0.0`.
|
|
@@ -18,13 +18,13 @@ Requires `react >= 18.0.0` and `react-dom >= 18.0.0`.
|
|
|
18
18
|
Use `DIE_LINE_LAYOUT` — one component for ALL models. No switch-case needed.
|
|
19
19
|
|
|
20
20
|
```tsx
|
|
21
|
-
import { DIE_LINE_LAYOUT, modelList } from "ultimate-packaging";
|
|
22
|
-
import type { DieLineLayoutRef } from "ultimate-packaging";
|
|
21
|
+
import { DIE_LINE_LAYOUT, modelList } from "@lucablockltd/ultimate-packaging";
|
|
22
|
+
import type { DieLineLayoutRef } from "@lucablockltd/ultimate-packaging";
|
|
23
23
|
|
|
24
24
|
const ref = useRef<DieLineLayoutRef>(null);
|
|
25
25
|
|
|
26
26
|
// Get default attributes for any model
|
|
27
|
-
const model = modelList.find(m => m.id === "BECF-1010A")!;
|
|
27
|
+
const model = modelList.find((m) => m.id === "BECF-1010A")!;
|
|
28
28
|
|
|
29
29
|
<DIE_LINE_LAYOUT
|
|
30
30
|
ref={ref}
|
|
@@ -33,18 +33,18 @@ const model = modelList.find(m => m.id === "BECF-1010A")!;
|
|
|
33
33
|
unit="mm"
|
|
34
34
|
mode="DIE_LINE"
|
|
35
35
|
isShowDimensions={true}
|
|
36
|
-
|
|
36
|
+
/>;
|
|
37
37
|
```
|
|
38
38
|
|
|
39
39
|
### DIE_LINE_LAYOUT Props
|
|
40
40
|
|
|
41
|
-
| Prop
|
|
42
|
-
|
|
43
|
-
| `modelId`
|
|
44
|
-
| `attributes`
|
|
45
|
-
| `unit`
|
|
46
|
-
| `mode`
|
|
47
|
-
| `isShowDimensions` | `boolean`
|
|
41
|
+
| Prop | Type | Required | Default | Description |
|
|
42
|
+
| ------------------ | ---------------------- | -------- | ------------ | ------------------------------------------------------------------------------------------------------ |
|
|
43
|
+
| `modelId` | `string` | YES | — | One of: `"BECF-1010A"`, `"BECF-1030A"`, `"BECF-1040A"`, `"BECF-11D01"`, `"BECF-12101"`, `"BECF-12109"` |
|
|
44
|
+
| `attributes` | `object` | YES | — | Box dimensions (see Model Attributes below) |
|
|
45
|
+
| `unit` | `"mm" \| "cm" \| "in"` | no | `"mm"` | Display unit for dimension labels |
|
|
46
|
+
| `mode` | `ModelMode` | no | `"DIE_LINE"` | `"DIE_LINE"` = interactive canvas, `"AUTO_LAYOUT"` = raw SVG |
|
|
47
|
+
| `isShowDimensions` | `boolean` | no | `false` | Show dimension annotation lines |
|
|
48
48
|
|
|
49
49
|
### DIE_LINE_LAYOUT Ref Methods
|
|
50
50
|
|
|
@@ -55,7 +55,10 @@ const ref = useRef<DieLineLayoutRef>(null);
|
|
|
55
55
|
ref.current.getAttributes(); // → { length: 60, width: 25, ... }
|
|
56
56
|
|
|
57
57
|
// Export as PNG image
|
|
58
|
-
const blob = await ref.current.exportImage({
|
|
58
|
+
const blob = await ref.current.exportImage({
|
|
59
|
+
isShowDimension: true,
|
|
60
|
+
originalSize: true,
|
|
61
|
+
});
|
|
59
62
|
|
|
60
63
|
// Export dimensions as PDF
|
|
61
64
|
const pdf = await ref.current.exportDimension();
|
|
@@ -68,39 +71,52 @@ const pdf = await ref.current.exportDimension();
|
|
|
68
71
|
Use `AUTO_LAYOUT` to automatically arrange dieline pieces on paper sheets.
|
|
69
72
|
|
|
70
73
|
```tsx
|
|
71
|
-
import { AUTO_LAYOUT, calculateAutoLayout } from "ultimate-packaging";
|
|
72
|
-
import type {
|
|
74
|
+
import { AUTO_LAYOUT, calculateAutoLayout } from "@lucablockltd/ultimate-packaging";
|
|
75
|
+
import type {
|
|
76
|
+
AutoLayoutRef,
|
|
77
|
+
AutoLayoutConfig,
|
|
78
|
+
AutoLayoutResult,
|
|
79
|
+
} from "@lucablockltd/ultimate-packaging";
|
|
73
80
|
|
|
74
81
|
const ref = useRef<AutoLayoutRef>(null);
|
|
75
82
|
const [result, setResult] = useState<AutoLayoutResult | null>(null);
|
|
76
83
|
|
|
77
84
|
const config: AutoLayoutConfig = {
|
|
78
85
|
papers: [
|
|
79
|
-
{ paperId: "1", paperName:
|
|
80
|
-
{ paperId: "2", paperName:
|
|
86
|
+
{ paperId: "1", paperName: '20x28"', paperWidth: 508, paperHeight: 711.2 },
|
|
87
|
+
{ paperId: "2", paperName: '25x36"', paperWidth: 635, paperHeight: 914.4 },
|
|
81
88
|
],
|
|
82
89
|
model: {
|
|
83
90
|
modelId: "BECF-1010A",
|
|
84
|
-
attributes: {
|
|
91
|
+
attributes: {
|
|
92
|
+
length: 60,
|
|
93
|
+
width: 25,
|
|
94
|
+
height: 100,
|
|
95
|
+
glueArea: 15,
|
|
96
|
+
dustFlap: 15,
|
|
97
|
+
tuckFlap: 15,
|
|
98
|
+
},
|
|
85
99
|
},
|
|
86
100
|
quantity: 1000,
|
|
87
|
-
layoutDistance: 3,
|
|
88
|
-
spacing: 5,
|
|
89
|
-
griper: 10,
|
|
90
|
-
colorbarHeight: 5,
|
|
101
|
+
layoutDistance: 3, // mm gap between pieces (offset contour)
|
|
102
|
+
spacing: 5, // mm margin on sides
|
|
103
|
+
griper: 10, // mm machine gripper zone
|
|
104
|
+
colorbarHeight: 5, // mm colorbar strip height
|
|
91
105
|
isShowColorbar: true,
|
|
92
106
|
};
|
|
93
107
|
|
|
94
|
-
<AUTO_LAYOUT ref={ref} config={config} onResult={setResult}
|
|
108
|
+
<AUTO_LAYOUT ref={ref} config={config} onResult={setResult} />;
|
|
95
109
|
```
|
|
96
110
|
|
|
97
111
|
### AUTO_LAYOUT Props
|
|
98
112
|
|
|
99
|
-
| Prop
|
|
100
|
-
|
|
101
|
-
| `config`
|
|
102
|
-
| `onResult`
|
|
103
|
-
| `onModifiedPapers` | `(papers: AutoLayoutPaperResult[]) => void`
|
|
113
|
+
| Prop | Type | Required | Description |
|
|
114
|
+
| ------------------ | -------------------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------- |
|
|
115
|
+
| `config` | `AutoLayoutConfig \| null` | YES | Layout configuration (null = no render) |
|
|
116
|
+
| `onResult` | `(result: AutoLayoutResult \| null) => void` | no | Called when layout is calculated |
|
|
117
|
+
| `onModifiedPapers` | `(papers: AutoLayoutPaperResult[]) => void` | no | Called when user modifies layout manually |
|
|
118
|
+
| `isShowSummary` | `boolean` | no | Show/hide summary panel (default: `true`) |
|
|
119
|
+
| `isShowAction` | `AutoLayoutAction[]` | no | Which action buttons to show. If omitted, all are shown. Values: `"EXPORT_SHEET"`, `"EXPORT_PDF"`, `"MODIFY_LAYOUT"` |
|
|
104
120
|
|
|
105
121
|
### AUTO_LAYOUT Ref Methods
|
|
106
122
|
|
|
@@ -122,7 +138,7 @@ const packed = await ref.current.getPackedResult(0);
|
|
|
122
138
|
### Programmatic Calculation (No UI)
|
|
123
139
|
|
|
124
140
|
```tsx
|
|
125
|
-
import { calculateAutoLayout } from "ultimate-packaging";
|
|
141
|
+
import { calculateAutoLayout } from "@lucablockltd/ultimate-packaging";
|
|
126
142
|
|
|
127
143
|
const result = calculateAutoLayout(config);
|
|
128
144
|
// → AutoLayoutResult { papers, quantity, totalProduced, totalSheets, remainingNeeded, recommendedPaperId }
|
|
@@ -135,13 +151,13 @@ const result = calculateAutoLayout(config);
|
|
|
135
151
|
### Get All Models
|
|
136
152
|
|
|
137
153
|
```tsx
|
|
138
|
-
import { modelList } from "ultimate-packaging";
|
|
154
|
+
import { modelList } from "@lucablockltd/ultimate-packaging";
|
|
139
155
|
|
|
140
|
-
modelList.forEach(model => {
|
|
141
|
-
console.log(model.id);
|
|
142
|
-
console.log(model.nameEN);
|
|
143
|
-
console.log(model.nameTH);
|
|
144
|
-
console.log(model.dimension);
|
|
156
|
+
modelList.forEach((model) => {
|
|
157
|
+
console.log(model.id); // "BECF-1010A"
|
|
158
|
+
console.log(model.nameEN); // "TUCK END BOXES TYPE A"
|
|
159
|
+
console.log(model.nameTH); // "กล่องฝาเสียบ ก้นเสียบ A"
|
|
160
|
+
console.log(model.dimension); // ["DIE_LINE"]
|
|
145
161
|
console.log(model.attributes); // { length: 60, width: 25, ... }
|
|
146
162
|
});
|
|
147
163
|
```
|
|
@@ -152,36 +168,57 @@ modelList.forEach(model => {
|
|
|
152
168
|
|
|
153
169
|
```typescript
|
|
154
170
|
interface TuckEndBoxAttributes {
|
|
155
|
-
length: number;
|
|
156
|
-
width: number;
|
|
157
|
-
height: number;
|
|
158
|
-
glueArea: number;
|
|
159
|
-
dustFlap: number;
|
|
160
|
-
tuckFlap: number;
|
|
171
|
+
length: number; // box length (mm)
|
|
172
|
+
width: number; // box width (mm)
|
|
173
|
+
height: number; // box height (mm)
|
|
174
|
+
glueArea: number; // glue flap width (mm)
|
|
175
|
+
dustFlap: number; // dust flap extension (mm)
|
|
176
|
+
tuckFlap: number; // tuck flap height (mm)
|
|
161
177
|
}
|
|
162
178
|
```
|
|
163
179
|
|
|
164
|
-
| Model
|
|
165
|
-
|
|
166
|
-
| BECF-1010A | 60
|
|
167
|
-
| BECF-1030A | 105
|
|
168
|
-
| BECF-1040A | 56
|
|
180
|
+
| Model | length | width | height | glueArea | dustFlap | tuckFlap |
|
|
181
|
+
| ---------- | ------ | ----- | ------ | -------- | -------- | -------- |
|
|
182
|
+
| BECF-1010A | 60 | 25 | 100 | 15 | 15 | 15 |
|
|
183
|
+
| BECF-1030A | 105 | 50 | 155 | 15 | 25 | 14 |
|
|
184
|
+
| BECF-1040A | 56 | 56 | 150 | 15 | 30 | 14 |
|
|
169
185
|
|
|
170
186
|
#### Standard Box (BECF-11D01)
|
|
171
187
|
|
|
172
188
|
```typescript
|
|
173
189
|
interface StandardBoxAttributes {
|
|
174
|
-
length: number;
|
|
175
|
-
width: number;
|
|
176
|
-
height: number;
|
|
190
|
+
length: number; // box length (mm)
|
|
191
|
+
width: number; // box width (mm)
|
|
192
|
+
height: number; // box height (mm)
|
|
177
193
|
flapHeight: number; // top/bottom flap height (mm)
|
|
178
|
-
glueArea: number;
|
|
194
|
+
glueArea: number; // glue flap width (mm)
|
|
179
195
|
}
|
|
180
196
|
```
|
|
181
197
|
|
|
182
|
-
| Model
|
|
183
|
-
|
|
184
|
-
| BECF-11D01 | 100
|
|
198
|
+
| Model | length | width | height | flapHeight | glueArea |
|
|
199
|
+
| ---------- | ------ | ----- | ------ | ---------- | -------- |
|
|
200
|
+
| BECF-11D01 | 100 | 50 | 150 | 50 | 13 |
|
|
201
|
+
|
|
202
|
+
#### Carton Bags / Shopping Bags (BECF-12101, BECF-12109)
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
interface CartonBagAttributes {
|
|
206
|
+
length: number; // A — bag length / front-back panel width (mm)
|
|
207
|
+
width: number; // B — bag width / side panel gusset (mm)
|
|
208
|
+
height: number; // C — bag body height (mm)
|
|
209
|
+
glueArea: number; // glue flap width (mm)
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Auto-calculated values (not user inputs):
|
|
214
|
+
|
|
215
|
+
- `D` — top flap height = min(C - 2 - B/2, 40)
|
|
216
|
+
- `DIP` — bottom glue tab height (15mm for 12101, 13mm for 12109)
|
|
217
|
+
|
|
218
|
+
| Model | length | width | height | glueArea |
|
|
219
|
+
| ------------------- | ------ | ----- | ------ | -------- |
|
|
220
|
+
| BECF-12101 (Type A) | 100 | 50 | 150 | 13 |
|
|
221
|
+
| BECF-12109 (Type B) | 100 | 50 | 150 | 13 |
|
|
185
222
|
|
|
186
223
|
### Default Attribute Constants
|
|
187
224
|
|
|
@@ -191,7 +228,9 @@ import {
|
|
|
191
228
|
BECF_1030A_DEFAULT_ATTRIBUTES,
|
|
192
229
|
BECF_1040A_DEFAULT_ATTRIBUTES,
|
|
193
230
|
BECF_11D01_DEFAULT_ATTRIBUTES,
|
|
194
|
-
|
|
231
|
+
BECF_12101_DEFAULT_ATTRIBUTES,
|
|
232
|
+
BECF_12109_DEFAULT_ATTRIBUTES,
|
|
233
|
+
} from "@lucablockltd/ultimate-packaging";
|
|
195
234
|
```
|
|
196
235
|
|
|
197
236
|
---
|
|
@@ -202,21 +241,21 @@ import {
|
|
|
202
241
|
|
|
203
242
|
```typescript
|
|
204
243
|
interface AutoLayoutConfig {
|
|
205
|
-
papers: AutoLayoutPaper[];
|
|
206
|
-
model: AutoLayoutModel;
|
|
207
|
-
quantity: number;
|
|
208
|
-
layoutDistance
|
|
209
|
-
spacing
|
|
210
|
-
griper
|
|
211
|
-
colorbarHeight
|
|
212
|
-
isShowColorbar
|
|
244
|
+
papers: AutoLayoutPaper[]; // paper sizes to try
|
|
245
|
+
model: AutoLayoutModel; // { modelId, attributes }
|
|
246
|
+
quantity: number; // total pieces needed
|
|
247
|
+
layoutDistance?: number; // mm between piece cut-lines (default: 3)
|
|
248
|
+
spacing?: number; // mm margin on paper sides (default: 5)
|
|
249
|
+
griper?: number; // mm machine gripper zone (default: 10)
|
|
250
|
+
colorbarHeight?: number; // mm colorbar strip (default: 5)
|
|
251
|
+
isShowColorbar?: boolean; // show colorbar on layout (default: true)
|
|
213
252
|
}
|
|
214
253
|
|
|
215
254
|
interface AutoLayoutPaper {
|
|
216
255
|
paperId: string;
|
|
217
256
|
paperName: string;
|
|
218
|
-
paperWidth: number;
|
|
219
|
-
paperHeight: number;
|
|
257
|
+
paperWidth: number; // mm
|
|
258
|
+
paperHeight: number; // mm
|
|
220
259
|
}
|
|
221
260
|
```
|
|
222
261
|
|
|
@@ -224,7 +263,7 @@ interface AutoLayoutPaper {
|
|
|
224
263
|
|
|
225
264
|
```typescript
|
|
226
265
|
interface AutoLayoutResult {
|
|
227
|
-
papers: AutoLayoutPaperResult[];
|
|
266
|
+
papers: AutoLayoutPaperResult[]; // results per paper size
|
|
228
267
|
quantity: number;
|
|
229
268
|
totalProduced: number;
|
|
230
269
|
totalSheets: number;
|
|
@@ -237,20 +276,20 @@ interface AutoLayoutPaperResult {
|
|
|
237
276
|
paperName: string;
|
|
238
277
|
paperWidth: number;
|
|
239
278
|
paperHeight: number;
|
|
240
|
-
producedPerSheet: number;
|
|
279
|
+
producedPerSheet: number; // pieces per sheet
|
|
241
280
|
totalSheets: number;
|
|
242
281
|
totalProduced: number;
|
|
243
|
-
excessCount: number;
|
|
244
|
-
wastePercent: number;
|
|
245
|
-
independentSheets: number;
|
|
246
|
-
independentTotalArea: number;
|
|
282
|
+
excessCount: number; // overproduction
|
|
283
|
+
wastePercent: number; // paper waste %
|
|
284
|
+
independentSheets: number; // sheets if using only this paper
|
|
285
|
+
independentTotalArea: number; // total paper area (mm²)
|
|
247
286
|
placements: AutoLayoutPlacement[];
|
|
248
|
-
gripperSide: GripperSide;
|
|
287
|
+
gripperSide: GripperSide; // "top" | "bottom" | "left" | "right"
|
|
249
288
|
}
|
|
250
289
|
|
|
251
290
|
interface AutoLayoutPlacement {
|
|
252
|
-
x: number;
|
|
253
|
-
y: number;
|
|
291
|
+
x: number; // mm from paper left
|
|
292
|
+
y: number; // mm from paper top
|
|
254
293
|
rotation: number; // 0 | 90 | 180 | 270
|
|
255
294
|
}
|
|
256
295
|
```
|
|
@@ -260,8 +299,8 @@ interface AutoLayoutPlacement {
|
|
|
260
299
|
```typescript
|
|
261
300
|
interface AutoLayoutPackedResult extends AutoLayoutPaperResult {
|
|
262
301
|
quantity: number;
|
|
263
|
-
dielineFile: File;
|
|
264
|
-
layoutFile: File;
|
|
302
|
+
dielineFile: File; // dieline pattern image
|
|
303
|
+
layoutFile: File; // layout arrangement image
|
|
265
304
|
}
|
|
266
305
|
```
|
|
267
306
|
|
|
@@ -275,15 +314,17 @@ type ModelMode = "DIE_LINE" | "3D" | "AUTO_LAYOUT";
|
|
|
275
314
|
|
|
276
315
|
## 5. Theme Configuration
|
|
277
316
|
|
|
317
|
+
`configurePackaging()` must be called **ONCE before rendering** any packaging components. All fields are optional — only override what you need.
|
|
318
|
+
|
|
278
319
|
```tsx
|
|
279
|
-
import { configurePackaging } from "ultimate-packaging";
|
|
320
|
+
import { configurePackaging } from "@lucablockltd/ultimate-packaging";
|
|
280
321
|
|
|
281
|
-
// Call ONCE at app startup, BEFORE rendering any components
|
|
282
322
|
configurePackaging({
|
|
323
|
+
fontDimensionSize: 4.2, // dimension label font size (default: 4.2)
|
|
283
324
|
modelTheme: {
|
|
284
325
|
colorBackground: "#FAFAFA",
|
|
285
|
-
colorDieLine: "#FF0000",
|
|
286
|
-
colorFoldLine: "#00FF00",
|
|
326
|
+
colorDieLine: "#FF0000", // cut lines
|
|
327
|
+
colorFoldLine: "#00FF00", // crease lines
|
|
287
328
|
},
|
|
288
329
|
autoLayoutTheme: {
|
|
289
330
|
colorBackground: "#F5F5F5",
|
|
@@ -299,6 +340,95 @@ configurePackaging({
|
|
|
299
340
|
});
|
|
300
341
|
```
|
|
301
342
|
|
|
343
|
+
### Where to call `configurePackaging()` per framework
|
|
344
|
+
|
|
345
|
+
#### Vite / CRA (Client-side SPA)
|
|
346
|
+
|
|
347
|
+
Call in `main.tsx` before `createRoot().render()`:
|
|
348
|
+
|
|
349
|
+
```tsx
|
|
350
|
+
// main.tsx
|
|
351
|
+
import { configurePackaging } from "@lucablockltd/ultimate-packaging";
|
|
352
|
+
|
|
353
|
+
configurePackaging({ modelTheme: { colorDieLine: "#FF0000" } });
|
|
354
|
+
|
|
355
|
+
createRoot(document.getElementById("root")!).render(<App />);
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
#### Next.js (App Router)
|
|
359
|
+
|
|
360
|
+
Create a client-side provider component and use it in the root layout:
|
|
361
|
+
|
|
362
|
+
```tsx
|
|
363
|
+
// components/PackagingProvider.tsx
|
|
364
|
+
"use client";
|
|
365
|
+
|
|
366
|
+
import { configurePackaging } from "@lucablockltd/ultimate-packaging";
|
|
367
|
+
|
|
368
|
+
// Runs once on module load (client-side only)
|
|
369
|
+
configurePackaging({
|
|
370
|
+
modelTheme: { colorDieLine: "#FF0000" },
|
|
371
|
+
autoLayoutTheme: { colorDistanceLine: "#0088FF" },
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
export default function PackagingProvider({
|
|
375
|
+
children,
|
|
376
|
+
}: {
|
|
377
|
+
children: React.ReactNode;
|
|
378
|
+
}) {
|
|
379
|
+
return <>{children}</>;
|
|
380
|
+
}
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
```tsx
|
|
384
|
+
// app/layout.tsx
|
|
385
|
+
import PackagingProvider from "@/components/PackagingProvider";
|
|
386
|
+
|
|
387
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
388
|
+
return (
|
|
389
|
+
<html>
|
|
390
|
+
<body>
|
|
391
|
+
<PackagingProvider>{children}</PackagingProvider>
|
|
392
|
+
</body>
|
|
393
|
+
</html>
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
> **Why a `"use client"` provider?** — `configurePackaging()` sets a global variable. In Next.js App Router, server components run on the server where this global has no effect. Using `"use client"` ensures the config runs in the browser before any packaging components render.
|
|
399
|
+
|
|
400
|
+
#### Next.js (Pages Router)
|
|
401
|
+
|
|
402
|
+
Call in `_app.tsx`:
|
|
403
|
+
|
|
404
|
+
```tsx
|
|
405
|
+
// pages/_app.tsx
|
|
406
|
+
import { configurePackaging } from "@lucablockltd/ultimate-packaging";
|
|
407
|
+
import type { AppProps } from "next/app";
|
|
408
|
+
|
|
409
|
+
configurePackaging({
|
|
410
|
+
modelTheme: { colorDieLine: "#FF0000" },
|
|
411
|
+
autoLayoutTheme: { colorDistanceLine: "#0088FF" },
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
export default function App({ Component, pageProps }: AppProps) {
|
|
415
|
+
return <Component {...pageProps} />;
|
|
416
|
+
}
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
#### Remix
|
|
420
|
+
|
|
421
|
+
Call in `root.tsx` or a client-only module:
|
|
422
|
+
|
|
423
|
+
```tsx
|
|
424
|
+
// app/root.tsx
|
|
425
|
+
import { configurePackaging } from "@lucablockltd/ultimate-packaging";
|
|
426
|
+
|
|
427
|
+
configurePackaging({
|
|
428
|
+
modelTheme: { colorDieLine: "#FF0000" },
|
|
429
|
+
});
|
|
430
|
+
```
|
|
431
|
+
|
|
302
432
|
---
|
|
303
433
|
|
|
304
434
|
## 6. Complete Imports Cheat Sheet
|
|
@@ -306,15 +436,17 @@ configurePackaging({
|
|
|
306
436
|
```tsx
|
|
307
437
|
// Components
|
|
308
438
|
import {
|
|
309
|
-
DIE_LINE_LAYOUT,
|
|
310
|
-
AUTO_LAYOUT,
|
|
311
|
-
MODEL_BECF_1010A,
|
|
439
|
+
DIE_LINE_LAYOUT, // Recommended: auto-switches by modelId
|
|
440
|
+
AUTO_LAYOUT, // Auto-layout packing on paper
|
|
441
|
+
MODEL_BECF_1010A, // Direct model components (if needed)
|
|
312
442
|
MODEL_BECF_1030A,
|
|
313
443
|
MODEL_BECF_1040A,
|
|
314
444
|
MODEL_BECF_11D01,
|
|
315
|
-
|
|
445
|
+
MODEL_BECF_12101,
|
|
446
|
+
MODEL_BECF_12109,
|
|
447
|
+
Colorbar, // Sub-components for custom rendering
|
|
316
448
|
Gripper,
|
|
317
|
-
} from "ultimate-packaging";
|
|
449
|
+
} from "@lucablockltd/ultimate-packaging";
|
|
318
450
|
|
|
319
451
|
// Types
|
|
320
452
|
import type {
|
|
@@ -329,8 +461,11 @@ import type {
|
|
|
329
461
|
AutoLayoutPlacement,
|
|
330
462
|
AutoLayoutPaper,
|
|
331
463
|
AutoLayoutModel,
|
|
464
|
+
AutoLayoutAction,
|
|
332
465
|
TuckEndBoxAttributes,
|
|
333
466
|
StandardBoxAttributes,
|
|
467
|
+
CartonBagAttributes,
|
|
468
|
+
CartonBag12109Attributes,
|
|
334
469
|
ModelMode,
|
|
335
470
|
PackagingModel,
|
|
336
471
|
GripperSide,
|
|
@@ -338,24 +473,26 @@ import type {
|
|
|
338
473
|
ModelThemeConfig,
|
|
339
474
|
AutoLayoutThemeConfig,
|
|
340
475
|
UltimatePackagingConfig,
|
|
341
|
-
} from "ultimate-packaging";
|
|
476
|
+
} from "@lucablockltd/ultimate-packaging";
|
|
342
477
|
|
|
343
478
|
// Data & Constants
|
|
344
479
|
import {
|
|
345
|
-
modelList,
|
|
480
|
+
modelList, // PackagingModel[] — all models with defaults
|
|
346
481
|
BECF_1010A_DEFAULT_ATTRIBUTES,
|
|
347
482
|
BECF_1030A_DEFAULT_ATTRIBUTES,
|
|
348
483
|
BECF_1040A_DEFAULT_ATTRIBUTES,
|
|
349
484
|
BECF_11D01_DEFAULT_ATTRIBUTES,
|
|
485
|
+
BECF_12101_DEFAULT_ATTRIBUTES,
|
|
486
|
+
BECF_12109_DEFAULT_ATTRIBUTES,
|
|
350
487
|
MODEL_THEME_CONFIG,
|
|
351
488
|
AUTO_LAYOUT_THEME_CONFIG,
|
|
352
|
-
} from "ultimate-packaging";
|
|
489
|
+
} from "@lucablockltd/ultimate-packaging";
|
|
353
490
|
|
|
354
491
|
// Functions
|
|
355
492
|
import {
|
|
356
|
-
configurePackaging,
|
|
357
|
-
calculateAutoLayout,
|
|
358
|
-
} from "ultimate-packaging";
|
|
493
|
+
configurePackaging, // Set global theme
|
|
494
|
+
calculateAutoLayout, // Compute layout without UI
|
|
495
|
+
} from "@lucablockltd/ultimate-packaging";
|
|
359
496
|
```
|
|
360
497
|
|
|
361
498
|
---
|
|
@@ -365,8 +502,8 @@ import {
|
|
|
365
502
|
### Pattern A: Display a Dieline with Controls
|
|
366
503
|
|
|
367
504
|
```tsx
|
|
368
|
-
import { DIE_LINE_LAYOUT, modelList } from "ultimate-packaging";
|
|
369
|
-
import type { DieLineLayoutRef } from "ultimate-packaging";
|
|
505
|
+
import { DIE_LINE_LAYOUT, modelList } from "@lucablockltd/ultimate-packaging";
|
|
506
|
+
import type { DieLineLayoutRef } from "@lucablockltd/ultimate-packaging";
|
|
370
507
|
|
|
371
508
|
function DielineEditor() {
|
|
372
509
|
const ref = useRef<DieLineLayoutRef>(null);
|
|
@@ -375,13 +512,20 @@ function DielineEditor() {
|
|
|
375
512
|
|
|
376
513
|
const handleModelChange = (id: string) => {
|
|
377
514
|
setModelId(id);
|
|
378
|
-
setAttrs(modelList.find(m => m.id === id)!.attributes);
|
|
515
|
+
setAttrs(modelList.find((m) => m.id === id)!.attributes);
|
|
379
516
|
};
|
|
380
517
|
|
|
381
518
|
return (
|
|
382
519
|
<>
|
|
383
|
-
<select
|
|
384
|
-
|
|
520
|
+
<select
|
|
521
|
+
value={modelId}
|
|
522
|
+
onChange={(e) => handleModelChange(e.target.value)}
|
|
523
|
+
>
|
|
524
|
+
{modelList.map((m) => (
|
|
525
|
+
<option key={m.id} value={m.id}>
|
|
526
|
+
{m.nameEN}
|
|
527
|
+
</option>
|
|
528
|
+
))}
|
|
385
529
|
</select>
|
|
386
530
|
<DIE_LINE_LAYOUT ref={ref} modelId={modelId} attributes={attrs} />
|
|
387
531
|
</>
|
|
@@ -392,16 +536,37 @@ function DielineEditor() {
|
|
|
392
536
|
### Pattern B: Auto-Layout with Export
|
|
393
537
|
|
|
394
538
|
```tsx
|
|
395
|
-
import { AUTO_LAYOUT } from "ultimate-packaging";
|
|
396
|
-
import type {
|
|
539
|
+
import { AUTO_LAYOUT } from "@lucablockltd/ultimate-packaging";
|
|
540
|
+
import type {
|
|
541
|
+
AutoLayoutRef,
|
|
542
|
+
AutoLayoutConfig,
|
|
543
|
+
AutoLayoutResult,
|
|
544
|
+
} from "@lucablockltd/ultimate-packaging";
|
|
397
545
|
|
|
398
546
|
function LayoutPlanner() {
|
|
399
547
|
const ref = useRef<AutoLayoutRef>(null);
|
|
400
548
|
const [result, setResult] = useState<AutoLayoutResult | null>(null);
|
|
401
549
|
|
|
402
550
|
const config: AutoLayoutConfig = {
|
|
403
|
-
papers: [
|
|
404
|
-
|
|
551
|
+
papers: [
|
|
552
|
+
{
|
|
553
|
+
paperId: "1",
|
|
554
|
+
paperName: '20x28"',
|
|
555
|
+
paperWidth: 508,
|
|
556
|
+
paperHeight: 711.2,
|
|
557
|
+
},
|
|
558
|
+
],
|
|
559
|
+
model: {
|
|
560
|
+
modelId: "BECF-1010A",
|
|
561
|
+
attributes: {
|
|
562
|
+
length: 60,
|
|
563
|
+
width: 25,
|
|
564
|
+
height: 100,
|
|
565
|
+
glueArea: 15,
|
|
566
|
+
dustFlap: 15,
|
|
567
|
+
tuckFlap: 15,
|
|
568
|
+
},
|
|
569
|
+
},
|
|
405
570
|
quantity: 500,
|
|
406
571
|
layoutDistance: 3,
|
|
407
572
|
spacing: 5,
|
|
@@ -420,7 +585,12 @@ function LayoutPlanner() {
|
|
|
420
585
|
return (
|
|
421
586
|
<>
|
|
422
587
|
<AUTO_LAYOUT ref={ref} config={config} onResult={setResult} />
|
|
423
|
-
{result &&
|
|
588
|
+
{result && (
|
|
589
|
+
<p>
|
|
590
|
+
Best: {result.recommendedPaperId} —{" "}
|
|
591
|
+
{result.papers[0].producedPerSheet} pcs/sheet
|
|
592
|
+
</p>
|
|
593
|
+
)}
|
|
424
594
|
<button onClick={handleExport}>Export</button>
|
|
425
595
|
</>
|
|
426
596
|
);
|
|
@@ -430,14 +600,24 @@ function LayoutPlanner() {
|
|
|
430
600
|
### Pattern C: Headless Calculation (No React)
|
|
431
601
|
|
|
432
602
|
```tsx
|
|
433
|
-
import { calculateAutoLayout } from "ultimate-packaging";
|
|
603
|
+
import { calculateAutoLayout } from "@lucablockltd/ultimate-packaging";
|
|
434
604
|
|
|
435
605
|
const result = calculateAutoLayout({
|
|
436
606
|
papers: [
|
|
437
|
-
{ paperId: "A", paperName:
|
|
438
|
-
{ paperId: "B", paperName:
|
|
607
|
+
{ paperId: "A", paperName: '20x28"', paperWidth: 508, paperHeight: 711.2 },
|
|
608
|
+
{ paperId: "B", paperName: '25x36"', paperWidth: 635, paperHeight: 914.4 },
|
|
439
609
|
],
|
|
440
|
-
model: {
|
|
610
|
+
model: {
|
|
611
|
+
modelId: "BECF-1030A",
|
|
612
|
+
attributes: {
|
|
613
|
+
length: 105,
|
|
614
|
+
width: 50,
|
|
615
|
+
height: 155,
|
|
616
|
+
glueArea: 15,
|
|
617
|
+
dustFlap: 25,
|
|
618
|
+
tuckFlap: 14,
|
|
619
|
+
},
|
|
620
|
+
},
|
|
441
621
|
quantity: 1000,
|
|
442
622
|
layoutDistance: 3,
|
|
443
623
|
spacing: 5,
|
|
@@ -447,8 +627,10 @@ const result = calculateAutoLayout({
|
|
|
447
627
|
});
|
|
448
628
|
|
|
449
629
|
console.log(result.recommendedPaperId); // "B"
|
|
450
|
-
result.papers.forEach(p => {
|
|
451
|
-
console.log(
|
|
630
|
+
result.papers.forEach((p) => {
|
|
631
|
+
console.log(
|
|
632
|
+
`${p.paperName}: ${p.producedPerSheet} pcs/sheet, ${p.wastePercent}% waste`,
|
|
633
|
+
);
|
|
452
634
|
});
|
|
453
635
|
```
|
|
454
636
|
|