@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.
@@ -6,7 +6,7 @@
6
6
  ## Quick Start
7
7
 
8
8
  ```bash
9
- npm install PinitS/ultimate-packaging
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 | Type | Required | Default | Description |
42
- |------|------|----------|---------|-------------|
43
- | `modelId` | `string` | YES | — | One of: `"BECF-1010A"`, `"BECF-1030A"`, `"BECF-1040A"`, `"BECF-11D01"` |
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 |
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({ isShowDimension: true, originalSize: true });
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 { AutoLayoutRef, AutoLayoutConfig, AutoLayoutResult } from "ultimate-packaging";
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: "20x28\"", paperWidth: 508, paperHeight: 711.2 },
80
- { paperId: "2", paperName: "25x36\"", paperWidth: 635, paperHeight: 914.4 },
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: { length: 60, width: 25, height: 100, glueArea: 15, dustFlap: 15, tuckFlap: 15 },
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, // mm gap between pieces (offset contour)
88
- spacing: 5, // mm margin on sides
89
- griper: 10, // mm machine gripper zone
90
- colorbarHeight: 5, // mm colorbar strip height
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 | Type | Required | Description |
100
- |------|------|----------|-------------|
101
- | `config` | `AutoLayoutConfig \| null` | YES | Layout configuration (null = no render) |
102
- | `onResult` | `(result: AutoLayoutResult \| null) => void` | no | Called when layout is calculated |
103
- | `onModifiedPapers` | `(papers: AutoLayoutPaperResult[]) => void` | no | Called when user modifies layout manually |
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); // "BECF-1010A"
142
- console.log(model.nameEN); // "TUCK END BOXES TYPE A"
143
- console.log(model.nameTH); // "กล่องฝาเสียบ ก้นเสียบ A"
144
- console.log(model.dimension); // ["DIE_LINE"]
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; // box length (mm)
156
- width: number; // box width (mm)
157
- height: number; // box height (mm)
158
- glueArea: number; // glue flap width (mm)
159
- dustFlap: number; // dust flap extension (mm)
160
- tuckFlap: number; // tuck flap height (mm)
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 | length | width | height | glueArea | dustFlap | tuckFlap |
165
- |-------|--------|-------|--------|----------|----------|----------|
166
- | BECF-1010A | 60 | 25 | 100 | 15 | 15 | 15 |
167
- | BECF-1030A | 105 | 50 | 155 | 15 | 25 | 14 |
168
- | BECF-1040A | 56 | 56 | 150 | 15 | 30 | 14 |
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; // box length (mm)
175
- width: number; // box width (mm)
176
- height: number; // box height (mm)
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; // glue flap width (mm)
194
+ glueArea: number; // glue flap width (mm)
179
195
  }
180
196
  ```
181
197
 
182
- | Model | length | width | height | flapHeight | glueArea |
183
- |-------|--------|-------|--------|------------|----------|
184
- | BECF-11D01 | 100 | 50 | 150 | 50 | 13 |
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
- } from "ultimate-packaging";
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[]; // paper sizes to try
206
- model: AutoLayoutModel; // { modelId, attributes }
207
- quantity: number; // total pieces needed
208
- layoutDistance: number; // mm between piece cut-lines
209
- spacing: number; // mm margin on paper sides
210
- griper: number; // mm machine gripper zone
211
- colorbarHeight: number; // mm colorbar strip
212
- isShowColorbar: boolean; // show colorbar on layout
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; // mm
219
- paperHeight: number; // mm
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[]; // results per paper size
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; // pieces per sheet
279
+ producedPerSheet: number; // pieces per sheet
241
280
  totalSheets: number;
242
281
  totalProduced: number;
243
- excessCount: number; // overproduction
244
- wastePercent: number; // paper waste %
245
- independentSheets: number; // sheets if using only this paper
246
- independentTotalArea: number; // total paper area (mm²)
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; // "top" | "bottom" | "left" | "right"
287
+ gripperSide: GripperSide; // "top" | "bottom" | "left" | "right"
249
288
  }
250
289
 
251
290
  interface AutoLayoutPlacement {
252
- x: number; // mm from paper left
253
- y: number; // mm from paper top
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; // dieline pattern image
264
- layoutFile: File; // layout arrangement image
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", // cut lines
286
- colorFoldLine: "#00FF00", // crease lines
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, // Recommended: auto-switches by modelId
310
- AUTO_LAYOUT, // Auto-layout packing on paper
311
- MODEL_BECF_1010A, // Direct model components (if needed)
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
- Colorbar, // Sub-components for custom rendering
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, // PackagingModel[] — all models with defaults
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, // Set global theme
357
- calculateAutoLayout, // Compute layout without UI
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 value={modelId} onChange={e => handleModelChange(e.target.value)}>
384
- {modelList.map(m => <option key={m.id} value={m.id}>{m.nameEN}</option>)}
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 { AutoLayoutRef, AutoLayoutConfig, AutoLayoutResult } from "ultimate-packaging";
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: [{ paperId: "1", paperName: "20x28\"", paperWidth: 508, paperHeight: 711.2 }],
404
- model: { modelId: "BECF-1010A", attributes: { length: 60, width: 25, height: 100, glueArea: 15, dustFlap: 15, tuckFlap: 15 } },
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 && <p>Best: {result.recommendedPaperId} — {result.papers[0].producedPerSheet} pcs/sheet</p>}
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: "20x28\"", paperWidth: 508, paperHeight: 711.2 },
438
- { paperId: "B", paperName: "25x36\"", paperWidth: 635, paperHeight: 914.4 },
607
+ { paperId: "A", paperName: '20x28"', paperWidth: 508, paperHeight: 711.2 },
608
+ { paperId: "B", paperName: '25x36"', paperWidth: 635, paperHeight: 914.4 },
439
609
  ],
440
- model: { modelId: "BECF-1030A", attributes: { length: 105, width: 50, height: 155, glueArea: 15, dustFlap: 25, tuckFlap: 14 } },
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(`${p.paperName}: ${p.producedPerSheet} pcs/sheet, ${p.wastePercent}% waste`);
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