@worm-vue3-print/core 1.3.9 → 1.3.10

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.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * @worm-vue3-print/core v1.3.9
2
+ * @worm-vue3-print/core v1.3.10
3
3
  * Copyright (c) 2026 worm <liu_long_qqcom@qq.com>
4
4
  * SPDX-FileCopyrightText: 2026 worm <liu_long_qqcom@qq.com>
5
5
  * SPDX-License-Identifier: MIT
@@ -28,9 +28,15 @@ var designer_exports = {};
28
28
  __export(designer_exports, {
29
29
  BARCODE_BAR_HEIGHT_MODULES: () => BARCODE_BAR_HEIGHT_MODULES,
30
30
  BARCODE_MARGIN_BOTTOM_MODULES: () => BARCODE_MARGIN_BOTTOM_MODULES,
31
+ BARCODE_MIN_MODULE_WIDTH_MM: () => BARCODE_MIN_MODULE_WIDTH_MM,
31
32
  BARCODE_MODULE_WIDTH_MM: () => BARCODE_MODULE_WIDTH_MM,
32
33
  BARCODE_QUIET_ZONE_MODULES: () => BARCODE_QUIET_ZONE_MODULES,
33
34
  BARCODE_TEXT_FONT_SIZE_MODULES: () => BARCODE_TEXT_FONT_SIZE_MODULES,
35
+ BORDER_EDGE_SIDES: () => BORDER_EDGE_SIDES,
36
+ BORDER_LINE_STYLES: () => BORDER_LINE_STYLES,
37
+ CELL_BORDER_APPLY_HINT: () => CELL_BORDER_APPLY_HINT,
38
+ CELL_BORDER_APPLY_HINT_MIXED: () => CELL_BORDER_APPLY_HINT_MIXED,
39
+ CELL_BORDER_APPLY_HINT_MULTI: () => CELL_BORDER_APPLY_HINT_MULTI,
34
40
  CROP_AXIS_OPTIONS: () => CROP_AXIS_OPTIONS,
35
41
  CROP_GRID_OPTIONS: () => CROP_GRID_OPTIONS,
36
42
  CROP_SAMPLE_IMAGE: () => CROP_SAMPLE_IMAGE,
@@ -38,12 +44,21 @@ __export(designer_exports, {
38
44
  CROP_SCALE_LABEL: () => CROP_SCALE_LABEL,
39
45
  CROP_SCALE_MAX: () => CROP_SCALE_MAX,
40
46
  CROP_SCALE_MIN: () => CROP_SCALE_MIN,
47
+ DEFAULT_BORDER: () => DEFAULT_BORDER,
41
48
  DEFAULT_DEMO_DATA: () => DEFAULT_DEMO_DATA,
42
49
  DEFAULT_SHRINK_MIN_FONT_SIZE_PT: () => DEFAULT_SHRINK_MIN_FONT_SIZE_PT,
43
50
  ELEMENT_BINDING_REGISTRY: () => ELEMENT_BINDING_REGISTRY,
51
+ ELEMENT_BORDER_APPLY_HINT: () => ELEMENT_BORDER_APPLY_HINT,
52
+ ELEMENT_BORDER_FALLBACK_WIDTH: () => ELEMENT_BORDER_FALLBACK_WIDTH,
44
53
  ELEMENT_BORDER_SIDES: () => ELEMENT_BORDER_SIDES,
45
54
  EXTENDED_FUNCTIONS: () => EXTENDED_FUNCTIONS,
46
55
  FIT_SCALE_MIN_PERCENT: () => FIT_SCALE_MIN_PERCENT,
56
+ FLOW_MAX_COLUMNS: () => FLOW_MAX_COLUMNS,
57
+ FLOW_MAX_GAP_X_MM: () => FLOW_MAX_GAP_X_MM,
58
+ FLOW_MAX_ROW_HEIGHT_MM: () => FLOW_MAX_ROW_HEIGHT_MM,
59
+ FLOW_MIN_COLUMNS: () => FLOW_MIN_COLUMNS,
60
+ FLOW_MIN_GAP_X_MM: () => FLOW_MIN_GAP_X_MM,
61
+ FLOW_MIN_ROW_HEIGHT_MM: () => FLOW_MIN_ROW_HEIGHT_MM,
47
62
  GHOST_BORDER_CSS: () => GHOST_BORDER_CSS,
48
63
  IMAGE_FIT_OPTIONS: () => IMAGE_FIT_OPTIONS,
49
64
  LABEL_PAPER_GROUP: () => LABEL_PAPER_GROUP,
@@ -51,17 +66,28 @@ __export(designer_exports, {
51
66
  MIN_SCALE_PERCENT: () => MIN_SCALE_PERCENT,
52
67
  MIN_SHRINK_FONT_SIZE_PT: () => MIN_SHRINK_FONT_SIZE_PT,
53
68
  MM_PER_INCH: () => MM_PER_INCH,
69
+ MM_TO_PX: () => MM_TO_PX,
54
70
  PAPER_PRESETS: () => PAPER_PRESETS,
55
71
  PRESET_COLORS: () => PRESET_COLORS,
72
+ PREVIEW_ZOOM_GUARD_ID: () => PREVIEW_ZOOM_GUARD_ID,
56
73
  PROPERTY_REGISTRY: () => PROPERTY_REGISTRY,
74
+ QR_DEFAULT_QUIET_MODULES: () => QR_DEFAULT_QUIET_MODULES,
57
75
  RESIZE_POINTS: () => RESIZE_POINTS,
58
76
  RULER_THICKNESS: () => RULER_THICKNESS,
59
77
  ZONE_ALLOWED_TYPES: () => ZONE_ALLOWED_TYPES,
78
+ ZOOM_MAX: () => ZOOM_MAX,
79
+ ZOOM_MIN: () => ZOOM_MIN,
60
80
  acceptsElementBorder: () => acceptsElementBorder,
61
81
  applyBorderPreset: () => applyBorderPreset,
82
+ applyElementBorderPreset: () => applyElementBorderPreset,
83
+ applyPreviewViewZoom: () => applyPreviewViewZoom,
62
84
  barcodeAvailableBoxMm: () => barcodeAvailableBoxMm,
85
+ barcodeBarHeightModules: () => barcodeBarHeightModules,
86
+ barcodeBarWidthRecommendText: () => barcodeBarWidthRecommendText,
63
87
  barcodePreferredModuleWidthMm: () => barcodePreferredModuleWidthMm,
88
+ barcodeQuietZoneModules: () => barcodeQuietZoneModules,
64
89
  barcodeUnitsPerModule: () => barcodeUnitsPerModule,
90
+ barcodeWidthBoundModuleWidthMm: () => barcodeWidthBoundModuleWidthMm,
65
91
  buildCropAnchor: () => buildCropAnchor,
66
92
  buildRulerTicks: () => buildRulerTicks,
67
93
  calcResizeRect: () => calcResizeRect,
@@ -74,6 +100,7 @@ __export(designer_exports, {
74
100
  clampResizedColumnWidth: () => clampResizedColumnWidth,
75
101
  clampScalePercent: () => clampScalePercent,
76
102
  clampToZone: () => clampToZone,
103
+ collectWritableCells: () => collectWritableCells,
77
104
  computeAdsorb: () => computeAdsorb,
78
105
  computeFitScale: () => computeFitScale,
79
106
  createCell: () => createCell,
@@ -88,14 +115,24 @@ __export(designer_exports, {
88
115
  cropScalePct: () => cropScalePct,
89
116
  cropStyleDeclarations: () => cropStyleDeclarations,
90
117
  cropWindow: () => cropWindow,
118
+ defaultZoomKey: () => defaultZoomKey,
91
119
  deleteCol: () => deleteCol,
92
120
  deleteRow: () => deleteRow,
121
+ detectFlowListKey: () => detectFlowListKey,
122
+ effectiveElementBorderSpec: () => effectiveElementBorderSpec,
123
+ elementBorderEdgeVisible: () => elementBorderEdgeVisible,
124
+ elementVisibleBorders: () => elementVisibleBorders,
93
125
  engine: () => engine2,
126
+ estimateTextWidthMm: () => estimateTextWidthMm,
94
127
  evaluateTemplate: () => evaluateTemplate2,
95
128
  filterGroups: () => filterGroups,
96
129
  finalizeElementZone: () => finalizeElementZone,
97
130
  findMainCell: () => findMainCell,
131
+ fitZoom: () => fitZoom,
98
132
  floorFontSize: () => floorFontSize,
133
+ flowColumnWidthMm: () => flowColumnWidthMm,
134
+ flowGridStyle: () => flowGridStyle,
135
+ flowSpanWidthMm: () => flowSpanWidthMm,
99
136
  generateGroupId: () => generateGroupId,
100
137
  generateId: () => generateId,
101
138
  getDemoData: () => getDemoData,
@@ -111,6 +148,8 @@ __export(designer_exports, {
111
148
  isContinuousPaperSize: () => isContinuousPaperSize,
112
149
  isLabelPaperSize: () => isLabelPaperSize,
113
150
  labelPaperDefaults: () => labelPaperDefaults,
151
+ layoutBarcodeSize: () => layoutBarcodeSize,
152
+ layoutFlowList: () => layoutFlowList,
114
153
  matchKeywords: () => matchKeywords,
115
154
  mergeCells: () => mergeCells,
116
155
  minorStepMM: () => minorStepMM,
@@ -118,38 +157,61 @@ __export(designer_exports, {
118
157
  nextWheelScale: () => nextWheelScale,
119
158
  normalizeSelection: () => normalizeSelection,
120
159
  normalizeTemplateUnits: () => normalizeTemplateUnits,
160
+ paperWidthPx: () => paperWidthPx,
121
161
  parseCellFitKey: () => parseCellFitKey,
122
162
  parseCropAnchor: () => parseCropAnchor,
163
+ propertyDefault: () => propertyDefault,
123
164
  propertyTip: () => propertyTip,
124
165
  ptToMm: () => ptToMm,
125
166
  pxToMm: () => pxToMm,
167
+ recommendBarcodeBarWidth: () => recommendBarcodeBarWidth,
126
168
  resolveBarcodeDesignValue: () => resolveBarcodeDesignValue,
127
169
  resolveBarcodeSize: () => resolveBarcodeSize,
170
+ resolveBorderEdgeStates: () => resolveBorderEdgeStates,
128
171
  resolveCellBorderCss: () => resolveCellBorderCss,
172
+ resolveCellBorderDisplay: () => resolveCellBorderDisplay,
173
+ resolveCellGroupMode: () => resolveCellGroupMode,
129
174
  resolveCellTextFit: () => resolveCellTextFit,
130
175
  resolveCropPreview: () => resolveCropPreview,
131
176
  resolveCropTravel: () => resolveCropTravel,
132
177
  resolveDesignImageSrc: () => resolveDesignImageSrc,
133
178
  resolveElementBorder: () => resolveElementBorder,
179
+ resolveElementBorderDisplay: () => resolveElementBorderDisplay,
180
+ resolveElementBorderSpec: () => resolveElementBorderSpec,
134
181
  resolveElementTextFit: () => resolveElementTextFit,
182
+ resolveFlowColumns: () => resolveFlowColumns,
183
+ resolveFlowGapX: () => resolveFlowGapX,
184
+ resolveFlowMaxSpan: () => resolveFlowMaxSpan,
185
+ resolveFlowRowHeight: () => resolveFlowRowHeight,
135
186
  resolveOverlayPlacement: () => resolveOverlayPlacement,
187
+ resolvePrinterDpi: () => resolvePrinterDpi,
188
+ resolveSharedCellType: () => resolveSharedCellType,
136
189
  resolveShrinkMinFontSize: () => resolveShrinkMinFontSize,
137
190
  resolveTextBinding: () => resolveTextBinding,
138
191
  resolveToolbarOverflow: () => resolveToolbarOverflow,
192
+ resolveZoomKey: () => resolveZoomKey,
139
193
  roundFontSize: () => roundFontSize,
140
194
  safeEval: () => safeEval2,
141
195
  sanitizeObjectPosition: () => sanitizeObjectPosition,
142
196
  searchProperties: () => searchProperties,
197
+ setCellBorderEdge: () => setCellBorderEdge,
198
+ setElementBorderEdge: () => setElementBorderEdge,
199
+ setElementBorderEdgeVisible: () => setElementBorderEdgeVisible,
200
+ setElementBorderField: () => setElementBorderField,
143
201
  setHeaderRepeat: () => setHeaderRepeat,
144
202
  setRowType: () => setRowType,
203
+ spanForText: () => spanForText,
145
204
  splitCells: () => splitCells,
205
+ suggestFlowColumns: () => suggestFlowColumns,
146
206
  syncTableElementSize: () => syncTableElementSize,
147
207
  useAlign: () => useAlign,
148
208
  useBindingDisplay: () => useBindingDisplay,
149
209
  useGroup: () => useGroup,
150
210
  useKeyboard: () => useKeyboard,
151
211
  useResize: () => useResize,
152
- zoneFromPaperPoint: () => zoneFromPaperPoint
212
+ zoneFromPaperPoint: () => zoneFromPaperPoint,
213
+ zoomPresets: () => zoomPresets,
214
+ zoomValueOf: () => zoomValueOf
153
215
  });
154
216
  module.exports = __toCommonJS(designer_exports);
155
217
 
@@ -173,7 +235,9 @@ function normalizeFit(value) {
173
235
  }
174
236
  var ELEMENT_DEFAULT_FIT = {
175
237
  text: "clip",
176
- longText: "autoHeight"
238
+ longText: "autoHeight",
239
+ // 流式列表一框一页:超出元素框高的单元按截断处理,不自动撑破纸面(specs 第八节第 8 项)
240
+ flowList: "clip"
177
241
  };
178
242
  function resolveElementTextFit(type, opts) {
179
243
  return normalizeFit(opts?.textFit) ?? ELEMENT_DEFAULT_FIT[type] ?? "clip";
@@ -229,13 +293,165 @@ function cellFitCapMm(rows, rowIndex, cell, defaultPadding = 1) {
229
293
  return Math.max(height - padding * 2 - borderMm, 0.5);
230
294
  }
231
295
 
296
+ // src/render/flow-list.ts
297
+ var FLOW_MIN_COLUMNS = 1;
298
+ var FLOW_MAX_COLUMNS = 12;
299
+ var FLOW_MIN_ROW_HEIGHT_MM = 3;
300
+ var FLOW_MAX_ROW_HEIGHT_MM = 100;
301
+ var FLOW_MIN_GAP_X_MM = 0;
302
+ var FLOW_MAX_GAP_X_MM = 50;
303
+ var PT_TO_MM = 25.4 / 72;
304
+ function clampInt(value, min2, max2, fallback) {
305
+ if (typeof value !== "number" || !Number.isFinite(value)) return fallback;
306
+ return Math.min(max2, Math.max(min2, Math.round(value)));
307
+ }
308
+ function resolveFlowColumns(value) {
309
+ return clampInt(value, FLOW_MIN_COLUMNS, FLOW_MAX_COLUMNS, 4);
310
+ }
311
+ function resolveFlowGapX(value) {
312
+ if (typeof value !== "number" || !Number.isFinite(value)) return 4;
313
+ return Math.min(FLOW_MAX_GAP_X_MM, Math.max(FLOW_MIN_GAP_X_MM, value));
314
+ }
315
+ function resolveFlowRowHeight(value) {
316
+ if (typeof value !== "number" || !Number.isFinite(value)) return 8;
317
+ return Math.min(FLOW_MAX_ROW_HEIGHT_MM, Math.max(FLOW_MIN_ROW_HEIGHT_MM, value));
318
+ }
319
+ function resolveFlowMaxSpan(value, columns) {
320
+ const cols = resolveFlowColumns(columns);
321
+ const fallback = Math.min(2, cols);
322
+ if (typeof value !== "number" || !Number.isFinite(value)) return fallback;
323
+ return Math.min(cols, Math.max(1, Math.round(value)));
324
+ }
325
+ function flowColumnWidthMm(width, columns, gapX) {
326
+ const cols = resolveFlowColumns(columns);
327
+ const gap = resolveFlowGapX(gapX);
328
+ const avail = width - gap * (cols - 1);
329
+ if (avail <= 0) return 0;
330
+ return avail / cols;
331
+ }
332
+ function flowSpanWidthMm(colUnitMm, gapX, span) {
333
+ const k = Math.max(1, Math.floor(span));
334
+ return colUnitMm * k + gapX * (k - 1);
335
+ }
336
+ function estimateTextWidthMm(text, fontSizePt) {
337
+ if (!text) return 0;
338
+ const em = typeof fontSizePt === "number" && Number.isFinite(fontSizePt) && fontSizePt > 0 ? fontSizePt * PT_TO_MM : 12 * PT_TO_MM;
339
+ let units = 0;
340
+ for (const ch of text) {
341
+ if (ch === " ") {
342
+ units += 0.28;
343
+ continue;
344
+ }
345
+ const c = ch.codePointAt(0) ?? 0;
346
+ if (c >= 12288 && c <= 12351 || c >= 13312 && c <= 19903 || c >= 19968 && c <= 40959 || c >= 63744 && c <= 64255 || c >= 65280 && c <= 65376 || c >= 65504 && c <= 65510 || c >= 131072) units += 1;
347
+ else if (/^[0-9A-Z]$/.test(ch)) units += 0.6;
348
+ else if (/^[a-z]$/.test(ch)) units += 0.5;
349
+ else if (/^[\u0020-\u007f]$/.test(ch)) units += 0.4;
350
+ else units += 0.75;
351
+ }
352
+ return units * em;
353
+ }
354
+ function spanForText(text, cfg) {
355
+ if (!cfg.autoSpan) return 1;
356
+ const ceiling = resolveFlowMaxSpan(cfg.maxSpan, cfg.columns);
357
+ if (ceiling <= 1 || cfg.colUnitMm <= 0) return 1;
358
+ const need = estimateTextWidthMm(text, cfg.fontSizePt);
359
+ for (let k = 1; k <= ceiling; k++) {
360
+ if (need <= flowSpanWidthMm(cfg.colUnitMm, cfg.gapX, k)) return k;
361
+ }
362
+ return ceiling;
363
+ }
364
+ function layoutFlowList(items, cfg) {
365
+ const columns = resolveFlowColumns(cfg.columns);
366
+ const gapX = resolveFlowGapX(cfg.gapX);
367
+ const colUnitMm = flowColumnWidthMm(cfg.width, columns, gapX);
368
+ const maxSpan = resolveFlowMaxSpan(cfg.maxSpan, columns);
369
+ const rows = [];
370
+ let current = [];
371
+ let used = 0;
372
+ for (const raw of items) {
373
+ const text = String(raw ?? "");
374
+ const span = spanForText(text, { ...cfg, columns, gapX, maxSpan, colUnitMm });
375
+ if (current.length > 0 && used + span > columns) {
376
+ rows.push({ cells: current });
377
+ current = [];
378
+ used = 0;
379
+ }
380
+ current.push({ text, span });
381
+ used += span;
382
+ }
383
+ if (current.length > 0) rows.push({ cells: current });
384
+ return rows;
385
+ }
386
+ function detectFlowListKey(expr, data) {
387
+ if (typeof expr !== "string" || !expr.includes("{") || !data) return void 0;
388
+ const roots = /* @__PURE__ */ new Set();
389
+ for (const token of expr.matchAll(/\{([^{}]*)\}/g)) {
390
+ for (const piece of (token[1] ?? "").split(/[^A-Za-z0-9_\u4e00-\u9fa5.]/)) {
391
+ const root = piece.split(".")[0];
392
+ if (root && !/^\d/.test(root)) roots.add(root);
393
+ }
394
+ }
395
+ for (const root of roots) {
396
+ if (Array.isArray(data[root])) return root;
397
+ }
398
+ return void 0;
399
+ }
400
+ function suggestFlowColumns(width, gapX, fontSizePt) {
401
+ const gap = resolveFlowGapX(gapX);
402
+ const minCol = estimateTextWidthMm("\u4E00", fontSizePt);
403
+ if (minCol <= 0 || width <= 0) return FLOW_MIN_COLUMNS;
404
+ const fit = Math.floor((width + gap) / (minCol + gap));
405
+ return Math.min(FLOW_MAX_COLUMNS, Math.max(FLOW_MIN_COLUMNS, fit));
406
+ }
407
+ var mmNum = (v) => `${Math.round(v * 1e3) / 1e3}mm`;
408
+ function flowGridStyle(cfg) {
409
+ const columns = resolveFlowColumns(cfg.columns);
410
+ const gapX = resolveFlowGapX(cfg.gapX);
411
+ const rowHeight = resolveFlowRowHeight(cfg.rowHeight);
412
+ return [
413
+ `display:grid`,
414
+ `grid-template-columns:repeat(${columns},minmax(0,1fr))`,
415
+ `column-gap:${mmNum(gapX)}`,
416
+ `grid-auto-rows:minmax(${mmNum(rowHeight)},auto)`
417
+ ].join(";");
418
+ }
419
+
232
420
  // src/render/barcode-dot.ts
233
421
  var MM_PER_INCH = 25.4;
234
422
  var BARCODE_QUIET_ZONE_MODULES = 10;
423
+ function barcodeQuietZoneModules(value) {
424
+ return typeof value === "number" && Number.isFinite(value) ? Math.max(0, Math.floor(value)) : BARCODE_QUIET_ZONE_MODULES;
425
+ }
235
426
  var BARCODE_BAR_HEIGHT_MODULES = 30;
236
427
  var BARCODE_TEXT_FONT_SIZE_MODULES = 10;
237
428
  var BARCODE_MARGIN_BOTTOM_MODULES = 2;
429
+ var QR_DEFAULT_QUIET_MODULES = 0;
238
430
  var BARCODE_MODULE_WIDTH_MM = 0.25;
431
+ var BARCODE_MIN_MODULE_WIDTH_MM = 0.254;
432
+ function recommendBarcodeBarWidth(dpi) {
433
+ if (typeof dpi !== "number" || !Number.isFinite(dpi) || dpi <= 0) return null;
434
+ const dotsPerMm = dpi / MM_PER_INCH;
435
+ for (let bw = 2; bw <= 8; bw += 0.5) {
436
+ const dotsPerModule = Math.max(1, Math.round(barcodePreferredModuleWidthMm(bw) * dotsPerMm));
437
+ const moduleWidthMm = dotsPerModule / dotsPerMm;
438
+ if (moduleWidthMm >= BARCODE_MIN_MODULE_WIDTH_MM - 1e-9) {
439
+ return { barWidth: bw, dotsPerModule, moduleWidthMm };
440
+ }
441
+ }
442
+ return null;
443
+ }
444
+ function barcodeBarWidthRecommendText(dpi, currentBarWidth) {
445
+ const rec = recommendBarcodeBarWidth(dpi);
446
+ if (!rec) return "";
447
+ const mm2 = (v) => String(Number(v.toFixed(3)));
448
+ const head = `\u6309 ${dpi}dpi \u63A8\u8350\u6761\u5BBD\u500D\u7387 ${rec.barWidth}\uFF08\u6BCF\u6A21\u5757 ${rec.dotsPerModule} \u4E2A\u6253\u5370\u70B9 = ${mm2(rec.moduleWidthMm)}mm\uFF0C\u53D6\u8FBE\u5230 ${mm2(BARCODE_MIN_MODULE_WIDTH_MM)}mm \u4E0B\u9650\u7684\u6700\u5C0F\u6863\uFF09`;
449
+ const cur = barcodePreferredModuleWidthMm(currentBarWidth ?? 2);
450
+ const curDots = Math.max(1, Math.round(cur * dpi / MM_PER_INCH));
451
+ const curMm = curDots / (dpi / MM_PER_INCH);
452
+ const tail = curMm >= BARCODE_MIN_MODULE_WIDTH_MM - 1e-9 ? `\u5F53\u524D\u500D\u7387 ${currentBarWidth ?? 2} \u6298\u7B97\u4E3A ${curDots} \u70B9 / ${mm2(curMm)}mm\uFF0C\u5DF2\u8FBE\u6807` : `\u5F53\u524D\u500D\u7387 ${currentBarWidth ?? 2} \u53EA\u6709 ${curDots} \u70B9 / ${mm2(curMm)}mm\uFF0C\u4F4E\u4E8E\u4E0B\u9650`;
453
+ return `${head}\uFF1B${tail}\u3002\u8FD9\u91CC\u53EA\u63D0\u793A\uFF0C\u4E0D\u4F1A\u66FF\u4F60\u6539\u503C`;
454
+ }
239
455
  function barcodeUnitsPerModule(barWidth) {
240
456
  const raw = typeof barWidth === "number" && Number.isFinite(barWidth) ? barWidth : 2;
241
457
  return Math.max(1, raw / 2);
@@ -243,6 +459,36 @@ function barcodeUnitsPerModule(barWidth) {
243
459
  function barcodePreferredModuleWidthMm(barWidth) {
244
460
  return barcodeUnitsPerModule(barWidth) * BARCODE_MODULE_WIDTH_MM;
245
461
  }
462
+ function barcodeBarHeightModules(input) {
463
+ const { barHeightMm, moduleWidthMm, boxHeightMm, textModules } = input;
464
+ const hasHeight = typeof barHeightMm === "number" && Number.isFinite(barHeightMm) && barHeightMm > 0;
465
+ const hasGranularity = typeof moduleWidthMm === "number" && Number.isFinite(moduleWidthMm) && moduleWidthMm > 0;
466
+ if (!hasHeight || !hasGranularity) return BARCODE_BAR_HEIGHT_MODULES;
467
+ const wanted = Math.max(1, Math.round(barHeightMm / moduleWidthMm));
468
+ const hasBox = typeof boxHeightMm === "number" && Number.isFinite(boxHeightMm) && boxHeightMm > 0;
469
+ if (!hasBox) return wanted;
470
+ const text = typeof textModules === "number" && Number.isFinite(textModules) && textModules > 0 ? textModules : 0;
471
+ const cap = Math.floor((boxHeightMm - text * moduleWidthMm) / moduleWidthMm);
472
+ return Math.max(1, Math.min(wanted, cap));
473
+ }
474
+ function dotAlignedModuleWidth(preferredMm, maxModuleMm, dotsPerMm) {
475
+ const preferredDots = Math.max(1, Math.round(preferredMm * dotsPerMm));
476
+ const maxDots = Math.floor(maxModuleMm * dotsPerMm);
477
+ if (maxDots < 1) return null;
478
+ const dotsPerModule = Math.min(preferredDots, maxDots);
479
+ return { dotsPerModule, preferredDots, moduleWidthMm: dotsPerModule / dotsPerMm };
480
+ }
481
+ function barcodeWidthBoundModuleWidthMm(input) {
482
+ const preferredMm = barcodePreferredModuleWidthMm(input.barWidth);
483
+ const unitWidth = Math.max(1, Math.ceil(input.unitWidth));
484
+ const maxModuleMm = input.boxWidthMm > 0 ? input.boxWidthMm / unitWidth : Number.POSITIVE_INFINITY;
485
+ const dpi = input.dpi;
486
+ if (typeof dpi === "number" && Number.isFinite(dpi) && dpi > 0) {
487
+ const aligned = dotAlignedModuleWidth(preferredMm, maxModuleMm, dpi / MM_PER_INCH);
488
+ if (aligned) return aligned.moduleWidthMm;
489
+ }
490
+ return Math.min(preferredMm, maxModuleMm);
491
+ }
246
492
  function barcodeAvailableBoxMm(boxMm, maxMm) {
247
493
  const box = typeof boxMm === "number" && boxMm > 0 ? boxMm : Number.POSITIVE_INFINITY;
248
494
  const limit = typeof maxMm === "number" && maxMm > 0 ? Math.min(box, maxMm) : box;
@@ -258,18 +504,14 @@ function resolveBarcodeSize(input) {
258
504
  );
259
505
  const dpi = input.dpi;
260
506
  if (typeof dpi === "number" && Number.isFinite(dpi) && dpi > 0) {
261
- const dotsPerMm = dpi / MM_PER_INCH;
262
- const preferredDots = Math.max(1, Math.round(preferredModuleMm * dotsPerMm));
263
- const maxDots = Math.floor(maxModuleMm * dotsPerMm);
264
- if (maxDots >= 1) {
265
- const dotsPerModule = Math.min(preferredDots, maxDots);
266
- const moduleWidthMm2 = dotsPerModule / dotsPerMm;
507
+ const aligned = dotAlignedModuleWidth(preferredModuleMm, maxModuleMm, dpi / MM_PER_INCH);
508
+ if (aligned) {
267
509
  return {
268
- moduleWidthMm: moduleWidthMm2,
269
- widthMm: unitWidth * moduleWidthMm2,
270
- heightMm: unitHeight * moduleWidthMm2,
271
- dotsPerModule,
272
- scaledDown: dotsPerModule < preferredDots
510
+ moduleWidthMm: aligned.moduleWidthMm,
511
+ widthMm: unitWidth * aligned.moduleWidthMm,
512
+ heightMm: unitHeight * aligned.moduleWidthMm,
513
+ dotsPerModule: aligned.dotsPerModule,
514
+ scaledDown: aligned.dotsPerModule < aligned.preferredDots
273
515
  };
274
516
  }
275
517
  }
@@ -282,6 +524,39 @@ function resolveBarcodeSize(input) {
282
524
  scaledDown: moduleWidthMm < preferredModuleMm
283
525
  };
284
526
  }
527
+ function layoutBarcodeSize(input) {
528
+ const upm = barcodeUnitsPerModule(input.barWidth);
529
+ const settle = (units) => resolveBarcodeSize({
530
+ unitWidth: units.widthUnits / upm,
531
+ unitHeight: units.heightUnits / upm,
532
+ boxWidthMm: input.boxWidthMm,
533
+ boxHeightMm: input.boxHeightMm,
534
+ dpi: input.dpi,
535
+ barWidth: input.barWidth
536
+ });
537
+ const first = input.measure(BARCODE_BAR_HEIGHT_MODULES);
538
+ if (!first) return { barHeightModules: BARCODE_BAR_HEIGHT_MODULES, size: null };
539
+ const hasHeight = typeof input.barHeightMm === "number" && Number.isFinite(input.barHeightMm) && input.barHeightMm > 0;
540
+ if (!hasHeight) return { barHeightModules: BARCODE_BAR_HEIGHT_MODULES, size: settle(first) };
541
+ const textModules = Math.max(0, first.heightUnits / upm - BARCODE_BAR_HEIGHT_MODULES);
542
+ const barHeightModules = barcodeBarHeightModules({
543
+ barHeightMm: input.barHeightMm,
544
+ moduleWidthMm: barcodeWidthBoundModuleWidthMm({
545
+ unitWidth: first.widthUnits / upm,
546
+ boxWidthMm: input.boxWidthMm,
547
+ dpi: input.dpi,
548
+ barWidth: input.barWidth
549
+ }),
550
+ boxHeightMm: input.boxHeightMm,
551
+ textModules
552
+ });
553
+ if (barHeightModules === BARCODE_BAR_HEIGHT_MODULES) {
554
+ return { barHeightModules, size: settle(first) };
555
+ }
556
+ const second = input.measure(barHeightModules);
557
+ if (!second) return { barHeightModules: BARCODE_BAR_HEIGHT_MODULES, size: null };
558
+ return { barHeightModules, size: settle(second) };
559
+ }
285
560
 
286
561
  // src/render/element-border.ts
287
562
  var ELEMENT_BORDER_SIDES = ["top", "right", "bottom", "left"];
@@ -292,6 +567,7 @@ function acceptsElementBorder(type) {
292
567
  var VALID_STYLES = /* @__PURE__ */ new Set(["solid", "dashed", "dotted", "double"]);
293
568
  function parseBorder(width, style, color) {
294
569
  if (typeof width !== "number" || !Number.isFinite(width) || width <= 0) return null;
570
+ if (style === "none") return null;
295
571
  return {
296
572
  borderWidth: `${width}pt`,
297
573
  borderStyle: typeof style === "string" && VALID_STYLES.has(style) ? style : "solid",
@@ -860,6 +1136,54 @@ function applyBorderPreset(rows, rect, preset, border) {
860
1136
  }
861
1137
  }
862
1138
  }
1139
+ var CELL_BORDER_APPLY_HINT = "\u7EBF\u578B / \u5BBD\u5EA6 / \u989C\u8272\u662F\u5F85\u5E94\u7528\u89C4\u683C\uFF1A\u9009\u4E2D\u683C\u5DF2\u6709\u7684\u8FB9\u6846\u89C4\u683C\u4E00\u81F4\u65F6\u4F1A\u586B\u8FDB\u8FD9\u4E09\u884C\uFF1B\u56DB\u8FB9\u4E0D\u4E00\u81F4\u7684\u9879\u663E\u793A\u300C\u6DF7\u5408\u300D\uFF0C\u4E00\u6761\u8FB9\u90FD\u6CA1\u6709\u65F6\u663E\u793A\u300C\u65E0 / 0\u300D\u3002\u6539\u5B8C\u70B9\u300C\u5168\u90E8 / \u5916\u4FA7 / \u5185\u90E8\u300D\u6216\u52FE\u9009\u4E0A\u3001\u4E0B\u3001\u5DE6\u3001\u53F3\u67D0\u6761\u8FB9\u624D\u4F1A\u5199\u5165\u9009\u4E2D\u7684\u5355\u5143\u683C\uFF1B\u300C\u65E0\u300D\u662F\u6E05\u9664\u8FB9\u6846";
1140
+ var CELL_BORDER_APPLY_HINT_MULTI = "\u591A\u9009\u65F6\u4E0D\u56DE\u663E\u5355\u683C\u8FB9\u6846\uFF1A\u7EBF\u578B / \u5BBD\u5EA6 / \u989C\u8272\u6309\u5F53\u524D\u8BBE\u7F6E\u4F5C\u4E3A\u6279\u5199\u89C4\u683C\uFF0C\u70B9\u300C\u5168\u90E8 / \u5916\u4FA7 / \u5185\u90E8\u300D\u6216\u52FE\u9009\u67D0\u6761\u8FB9\u540E\u5199\u5165\u6240\u6709\u9009\u4E2D\u683C\uFF1B\u300C\u65E0\u300D\u662F\u6E05\u9664\u8FB9\u6846";
1141
+ var CELL_BORDER_APPLY_HINT_MIXED = "\u5F53\u524D\u5355\u5143\u683C\u56DB\u8FB9\u8FB9\u6846\u89C4\u683C\u4E0D\u4E00\u81F4\uFF1A\u5E26\u300C\u6DF7\u5408\u300D\u7684\u9879\u4E0D\u8C0E\u62A5\uFF0C\u672A\u6539\u9879\u5728\u70B9\u300C\u5168\u90E8 / \u5916\u4FA7 / \u5185\u90E8\u300D\u6216\u52FE\u9009\u5355\u8FB9\u65F6\u6309\u7F3A\u7701\u6863\uFF08\u5B9E\u7EBF 0.75pt\uFF09\u5199\u5165\uFF0C\u6539\u4EFB\u4E00\u9879\u5373\u6309\u8BE5\u503C\u6279\u5199";
1142
+ function setCellBorderEdge(cell, side, border) {
1143
+ const nb = { ...cell.borders ?? {} };
1144
+ if (border) nb[side] = { ...border };
1145
+ else delete nb[side];
1146
+ cell.borders = nb.top || nb.right || nb.bottom || nb.left ? nb : void 0;
1147
+ }
1148
+ function collectWritableCells(rows, rect) {
1149
+ const out = [];
1150
+ for (let r = rect.r1; r <= rect.r2; r++) {
1151
+ for (let c = rect.c1; c <= rect.c2; c++) {
1152
+ const cell = rows[r]?.cells[c];
1153
+ if (cell && !cell.merged) out.push(cell);
1154
+ }
1155
+ }
1156
+ return out;
1157
+ }
1158
+ function resolveCellGroupMode(rows, rect) {
1159
+ const count2 = collectWritableCells(rows, rect).length;
1160
+ return { mode: count2 > 1 ? "multi" : "single", count: count2 };
1161
+ }
1162
+ function resolveSharedCellType(rows, rect) {
1163
+ const cells = collectWritableCells(rows, rect);
1164
+ if (!cells.length) return null;
1165
+ const first = cells[0].cellType ?? "text";
1166
+ return cells.every((c) => (c.cellType ?? "text") === first) ? first : null;
1167
+ }
1168
+ function resolveCellBorderDisplay(rows, rect) {
1169
+ const edges = [];
1170
+ for (const cell of collectWritableCells(rows, rect)) {
1171
+ for (const side of ["top", "right", "bottom", "left"]) {
1172
+ const b = cell.borders?.[side];
1173
+ if (b) edges.push(b);
1174
+ }
1175
+ }
1176
+ const pick = (get) => {
1177
+ if (!edges.length) return void 0;
1178
+ const first = get(edges[0]);
1179
+ return edges.every((b) => get(b) === first) ? first : "mixed";
1180
+ };
1181
+ return {
1182
+ width: pick((b) => b.width),
1183
+ style: pick((b) => b.style),
1184
+ color: pick((b) => b.color)
1185
+ };
1186
+ }
863
1187
  var GHOST_BORDER_CSS = "1px dashed rgba(0,0,0,0.18)";
864
1188
  function resolveCellBorderCss(b, opts = {}) {
865
1189
  if (b && b.style !== "none") return `${b.width}pt ${b.style} ${b.color}`;
@@ -880,12 +1204,245 @@ function clampResizedColumnWidth(colWidths, index, targetMm, maxTableWidth) {
880
1204
  return Math.min(Math.max(rounded, MIN_COL_WIDTH_MM), cap);
881
1205
  }
882
1206
 
1207
+ // src/designer/utils/element-border-edit.ts
1208
+ var ELEMENT_BORDER_FALLBACK_WIDTH = 0.75;
1209
+ var ELEMENT_BORDER_APPLY_HINT = "\u7EBF\u578B / \u5BBD\u5EA6 / \u989C\u8272\u5373\u65F6\u751F\u6548\uFF0C\u8FD9\u4E09\u884C\u663E\u793A\u7684\u5C31\u662F\u5F53\u524D\u751F\u6548\u89C4\u683C\uFF1A\u5DF2\u6709\u8FB9\u6846\u65F6\u4EFB\u6539\u4E00\u884C\u90FD\u4F1A\u6309\u65B0\u89C4\u683C\u94FA\u6EE1\u56DB\u8FB9\u5E76\u6E05\u6389\u5355\u8FB9\u8986\u76D6\uFF1B\u4E0A\u3001\u4E0B\u3001\u5DE6\u3001\u53F3\u53EA\u7ED9\u9009\u4E2D\u7684\u8FB9\u52A0\u6846\uFF0C\u64A4\u6389\u4E00\u8FB9\u4F1A\u628A\u5B83\u5176\u4F59\u4E09\u8FB9\u843D\u6210\u5355\u8FB9\uFF1B\u300C\u65E0\u300D\u6E05\u9664\u8FB9\u6846\uFF0C\u300C\u5185\u90E8\u300D\u4EC5\u8868\u683C\u5355\u5143\u683C\u53EF\u7528";
1210
+ var BORDER_EDGE_SIDES = ["top", "right", "bottom", "left"];
1211
+ function resolveBorderEdgeStates(borders) {
1212
+ const out = {};
1213
+ for (const side of BORDER_EDGE_SIDES) {
1214
+ const flags = borders.map((b) => !!b?.[side]);
1215
+ out[side] = flags.length > 0 && flags.every(Boolean) ? "on" : flags.some(Boolean) ? "mixed" : "off";
1216
+ }
1217
+ return out;
1218
+ }
1219
+ var BORDER_LINE_STYLES = [
1220
+ { value: "none", label: "\u65E0" },
1221
+ { value: "solid", label: "\u5B9E\u7EBF" },
1222
+ { value: "dashed", label: "\u865A\u7EBF" },
1223
+ { value: "dotted", label: "\u70B9\u7EBF" },
1224
+ { value: "double", label: "\u53CC\u7EBF" }
1225
+ ];
1226
+ var VALID_BORDER_STYLES = /* @__PURE__ */ new Set(["solid", "dashed", "dotted", "double"]);
1227
+ var NO_STYLE = "none";
1228
+ function elementBorderEdgeVisible(opts, side) {
1229
+ const edge = opts.borders?.[side];
1230
+ if (edge && edge.style !== NO_STYLE && typeof edge.width === "number" && Number.isFinite(edge.width) && edge.width > 0) return true;
1231
+ const w = opts.borderWidth;
1232
+ return opts.borderStyle !== NO_STYLE && typeof w === "number" && Number.isFinite(w) && w > 0;
1233
+ }
1234
+ function elementVisibleBorders(opts) {
1235
+ const out = {};
1236
+ for (const side of BORDER_EDGE_SIDES) {
1237
+ if (elementBorderEdgeVisible(opts, side)) out[side] = opts.borders?.[side] ?? { width: opts.borderWidth };
1238
+ }
1239
+ return out;
1240
+ }
1241
+ function resolveElementBorderSpec(opts) {
1242
+ const w = opts.borderWidth;
1243
+ const width = typeof w === "number" && Number.isFinite(w) && w > 0 ? w : ELEMENT_BORDER_FALLBACK_WIDTH;
1244
+ return { width, style: opts.borderStyle || "solid", color: opts.borderColor || "#333333" };
1245
+ }
1246
+ function applyElementBorderPreset(opts, preset, spec) {
1247
+ if (preset === "inner") return;
1248
+ opts.borders = void 0;
1249
+ if (preset === "none") {
1250
+ opts.borderWidth = 0;
1251
+ return;
1252
+ }
1253
+ opts.borderWidth = spec.width;
1254
+ opts.borderStyle = spec.style;
1255
+ opts.borderColor = spec.color;
1256
+ }
1257
+ function hasVisibleElementBorder(opts) {
1258
+ return BORDER_EDGE_SIDES.some((s) => elementBorderEdgeVisible(opts, s));
1259
+ }
1260
+ function pickField(edges, key) {
1261
+ if (!edges.length) return void 0;
1262
+ const first = edges[0]?.[key];
1263
+ return edges.every((e) => e[key] === first) ? first : "mixed";
1264
+ }
1265
+ function normalizeEdge(edge) {
1266
+ if (!edge) return void 0;
1267
+ const style = typeof edge.style === "string" && VALID_BORDER_STYLES.has(edge.style) ? edge.style : "solid";
1268
+ return { width: edge.width, style: edge.style === void 0 ? void 0 : style, color: edge.color };
1269
+ }
1270
+ function displayOfVisibleEdges(opts) {
1271
+ const visible = BORDER_EDGE_SIDES.map((s) => opts.borders?.[s]).filter((e) => typeof e?.width === "number" && Number.isFinite(e.width) && e.width > 0).map((e) => normalizeEdge(e));
1272
+ if (!visible.length) return void 0;
1273
+ const style = pickField(visible, "style");
1274
+ return {
1275
+ width: pickField(visible, "width"),
1276
+ style: style === void 0 ? "solid" : style,
1277
+ color: pickField(visible, "color")
1278
+ };
1279
+ }
1280
+ function resolveElementBorderDisplay(opts) {
1281
+ const w = opts.borderWidth;
1282
+ const declared = typeof w === "number" && Number.isFinite(w);
1283
+ const fromEdges = displayOfVisibleEdges(opts);
1284
+ const allVisible = declared && w > 0;
1285
+ if (fromEdges && !allVisible) return fromEdges;
1286
+ const style = allVisible ? opts.borderStyle || "solid" : NO_STYLE;
1287
+ if (declared) return { width: w, style, color: opts.borderColor };
1288
+ return { width: void 0, style, color: void 0 };
1289
+ }
1290
+ function effectiveElementBorderSpec(opts) {
1291
+ const d = resolveElementBorderDisplay(opts);
1292
+ return {
1293
+ width: typeof d.width === "number" && d.width > 0 ? d.width : ELEMENT_BORDER_FALLBACK_WIDTH,
1294
+ // 「无」不是可复制的线型:勾一条边要出线,落到实线
1295
+ style: typeof d.style === "string" && d.style !== NO_STYLE ? d.style : "solid",
1296
+ color: typeof d.color === "string" ? d.color : "#333333"
1297
+ };
1298
+ }
1299
+ function applyElementBorderAll(opts, spec) {
1300
+ opts.borderWidth = spec.width;
1301
+ opts.borderStyle = spec.style;
1302
+ opts.borderColor = spec.color;
1303
+ opts.borders = void 0;
1304
+ }
1305
+ function setElementBorderField(opts, key, value) {
1306
+ if (key === "borderStyle" && value === NO_STYLE) {
1307
+ const hadBorder = hasVisibleElementBorder(opts);
1308
+ opts.borderStyle = NO_STYLE;
1309
+ if (hadBorder) {
1310
+ opts.borderWidth = 0;
1311
+ opts.borders = void 0;
1312
+ }
1313
+ return;
1314
+ }
1315
+ if (!hasVisibleElementBorder(opts)) {
1316
+ if (key === "borderStyle") {
1317
+ opts.borderStyle = value;
1318
+ opts.borderWidth = ELEMENT_BORDER_FALLBACK_WIDTH;
1319
+ return;
1320
+ }
1321
+ Object.assign(opts, { [key]: value });
1322
+ return;
1323
+ }
1324
+ if (key === "borderWidth" && (typeof value !== "number" || !(value > 0))) {
1325
+ opts.borderWidth = typeof value === "number" && value < 0 ? 0 : value;
1326
+ opts.borders = void 0;
1327
+ return;
1328
+ }
1329
+ applyElementBorderAll(opts, resolveElementBorderSpec({ ...opts, [key]: value }));
1330
+ }
1331
+ function setElementBorderEdgeVisible(opts, side, visible, spec) {
1332
+ if (visible === elementBorderEdgeVisible(opts, side)) return;
1333
+ if (!visible) {
1334
+ const allWidth = opts.borderWidth;
1335
+ if (typeof allWidth !== "number" || !(allWidth > 0)) {
1336
+ setElementBorderEdge(opts, side, null);
1337
+ return;
1338
+ }
1339
+ const next = {};
1340
+ for (const s of BORDER_EDGE_SIDES) {
1341
+ if (s === side) continue;
1342
+ const own = opts.borders?.[s];
1343
+ next[s] = {
1344
+ width: own?.width ?? allWidth,
1345
+ ...own?.style !== void 0 ? { style: own.style } : opts.borderStyle !== void 0 ? { style: opts.borderStyle } : {},
1346
+ ...own?.color !== void 0 ? { color: own.color } : opts.borderColor !== void 0 ? { color: opts.borderColor } : {}
1347
+ };
1348
+ }
1349
+ opts.borders = next;
1350
+ opts.borderWidth = 0;
1351
+ return;
1352
+ }
1353
+ setElementBorderEdge(opts, side, spec ?? effectiveElementBorderSpec(opts));
1354
+ }
1355
+ function setElementBorderEdge(opts, side, spec) {
1356
+ const nb = { ...opts.borders ?? {} };
1357
+ if (spec) nb[side] = { width: spec.width, style: spec.style, color: spec.color };
1358
+ else delete nb[side];
1359
+ opts.borders = nb;
1360
+ }
1361
+
1362
+ // src/designer/utils/preview-zoom.ts
1363
+ var MM_TO_PX = 96 / 25.4;
1364
+ var ZOOM_MIN = 1;
1365
+ var ZOOM_MAX = 8;
1366
+ var FALLBACK_PAPER_WIDTH_MM = 210;
1367
+ function collectDpi(node, out) {
1368
+ if (!node || typeof node !== "object") return;
1369
+ if (Array.isArray(node)) {
1370
+ for (const item of node) collectDpi(item, out);
1371
+ return;
1372
+ }
1373
+ const record = node;
1374
+ if (typeof record.printerDpi === "number" && record.printerDpi > 0) out.add(record.printerDpi);
1375
+ for (const key of Object.keys(record)) {
1376
+ if (key === "printerDpi") continue;
1377
+ const value = record[key];
1378
+ if (value && typeof value === "object") collectDpi(value, out);
1379
+ }
1380
+ }
1381
+ function resolvePrinterDpi(templateJson) {
1382
+ if (!templateJson) return null;
1383
+ const found = /* @__PURE__ */ new Set();
1384
+ collectDpi(templateJson, found);
1385
+ return found.size ? Math.max(...found) : null;
1386
+ }
1387
+ function paperWidthPx(templateJson) {
1388
+ const page = templateJson?.pages?.[0] ?? templateJson;
1389
+ if (!page) return FALLBACK_PAPER_WIDTH_MM * MM_TO_PX;
1390
+ return getPaperDimensions(page).width * MM_TO_PX;
1391
+ }
1392
+ function fitZoom(containerPx, paperPx) {
1393
+ if (containerPx <= 0 || paperPx <= 0) return ZOOM_MIN;
1394
+ return Math.min(ZOOM_MAX, Math.max(ZOOM_MIN, Math.floor(containerPx / paperPx)));
1395
+ }
1396
+ function zoomPresets(dpi, containerPx, paperPx) {
1397
+ const list = [];
1398
+ if (dpi) {
1399
+ list.push({
1400
+ key: "dots",
1401
+ value: dpi / 96,
1402
+ label: `\u70B9\u9635 ${dpi}dpi`,
1403
+ tip: `1 \u5C4F\u5E55\u50CF\u7D20 = 1 \u4E2A\u6253\u5370\u70B9\uFF08${dpi}dpi \xF7 96dpi\uFF09\u3002\u6761\u4E0E\u95F4\u9699\u6309\u7EB8\u9762\u9010\u70B9\u663E\u793A\uFF0C\u4E0D\u4F1A\u5728\u5C4F\u5E55\u4E0A\u7CCA\u6210\u4E00\u7247`
1404
+ });
1405
+ }
1406
+ list.push(
1407
+ { key: "fit", value: fitZoom(containerPx, paperPx), label: "\u9002\u914D", tip: "\u6309\u5BB9\u5668\u5BBD\u653E\u5927\u5230\u653E\u5F97\u4E0B\u6574\u9875\u7684\u6700\u5927\u6574\u6570\u500D" },
1408
+ { key: "100", value: 1, label: "100%", tip: "\u6309 CSS \u771F\u5B9E\u5C3A\u5BF8\u663E\u793A\uFF081mm = 3.78 \u5C4F\u5E55\u50CF\u7D20\uFF09\uFF0C\u70ED\u654F\u70B9\u8DDD\u5728\u6B64\u6863\u4E0D\u53EF\u5206\u8FA8" },
1409
+ { key: "200", value: 2, label: "200%", tip: "\u6574\u6570\u500D\u653E\u5927\uFF0C\u907F\u514D\u975E\u6574\u6570\u7F29\u653E\u5E26\u6765\u7684\u534A\u50CF\u7D20\u8FB9" },
1410
+ { key: "400", value: 4, label: "400%", tip: "\u6574\u6570\u500D\u653E\u5927\uFF0C\u907F\u514D\u975E\u6574\u6570\u7F29\u653E\u5E26\u6765\u7684\u534A\u50CF\u7D20\u8FB9" }
1411
+ );
1412
+ return list;
1413
+ }
1414
+ function defaultZoomKey(dpi) {
1415
+ return dpi ? "dots" : "fit";
1416
+ }
1417
+ var PREVIEW_ZOOM_GUARD_ID = "print-preview-zoom-guard";
1418
+ function applyPreviewViewZoom(doc, zoom) {
1419
+ if (!doc?.documentElement) return;
1420
+ let guard = doc.getElementById(PREVIEW_ZOOM_GUARD_ID);
1421
+ if (!guard) {
1422
+ guard = doc.createElement("style");
1423
+ guard.id = PREVIEW_ZOOM_GUARD_ID;
1424
+ (doc.head ?? doc.documentElement).appendChild(guard);
1425
+ }
1426
+ guard.textContent = `html{zoom:${zoom}}@media print{html{zoom:1 !important}}`;
1427
+ }
1428
+ function resolveZoomKey(presets, currentKey, dpi) {
1429
+ return presets.some((p) => p.key === currentKey) ? currentKey : defaultZoomKey(dpi);
1430
+ }
1431
+ function zoomValueOf(presets, key) {
1432
+ return presets.find((p) => p.key === key)?.value ?? 1;
1433
+ }
1434
+
883
1435
  // src/designer/utils/element-factory.ts
884
1436
  function generateId() {
885
1437
  return `el-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
886
1438
  }
887
1439
  function createDefaultOptions(type) {
888
- const base = { left: 7, top: 17.6, width: 42.3, height: 7.1 };
1440
+ const base = {
1441
+ left: 7,
1442
+ top: 17.6,
1443
+ width: 42.3,
1444
+ height: 7.1
1445
+ };
889
1446
  switch (type) {
890
1447
  case "text":
891
1448
  return { ...base, formatter: "\u6587\u672C", fontSize: 12, textAlign: "left", height: 5.3 };
@@ -912,6 +1469,19 @@ function createDefaultOptions(type) {
912
1469
  tablePagination: { enabled: true }
913
1470
  };
914
1471
  }
1472
+ case "flowList":
1473
+ return {
1474
+ ...base,
1475
+ width: 141.1,
1476
+ height: 21.2,
1477
+ fontSize: 12,
1478
+ formatter: "{name} {spec}",
1479
+ flowColumns: 4,
1480
+ flowRowHeight: 8,
1481
+ flowGapX: 4,
1482
+ flowAutoSpan: false,
1483
+ flowMaxSpan: 2
1484
+ };
915
1485
  case "hline":
916
1486
  return { ...base, width: 70.6, height: 1.8, borderWidth: 0.75 };
917
1487
  case "vline":
@@ -936,6 +1506,7 @@ function createRuntimeElement(type, options) {
936
1506
  image: { title: "\u56FE\u7247" },
937
1507
  longText: { title: "\u957F\u6587" },
938
1508
  table: { title: "\u8868\u683C" },
1509
+ flowList: { title: "\u6D41\u5F0F\u5217\u8868" },
939
1510
  hline: { title: "\u6A2A\u7EBF" },
940
1511
  vline: { title: "\u7AD6\u7EBF" },
941
1512
  rect: { title: "\u77E9\u5F62" },
@@ -1096,7 +1667,7 @@ var PROPERTY_REGISTRY = [
1096
1667
  { key: "ap-line-height", keywords: ["\u884C\u9AD8", "lineheight"] },
1097
1668
  { key: "ap-letter-spacing", keywords: ["\u5B57\u95F4\u8DDD", "letterspacing"] },
1098
1669
  { key: "ap-text-fit", keywords: ["\u6EA2\u51FA", "\u6EA2\u51FA\u663E\u793A", "\u622A\u65AD", "\u81EA\u52A8\u7F29\u5C0F", "\u81EA\u9002\u5E94\u884C\u9AD8", "textfit", "overflow"] },
1099
- { key: "ap-shrink-min", keywords: ["\u6700\u5C0F\u5B57\u53F7", "\u7F29\u653E\u4E0B\u9650", "shrinkminfontsize"] },
1670
+ { key: "ap-shrink-min", keywords: ["\u6700\u5C0F\u5B57\u53F7", "\u7F29\u653E\u4E0B\u9650", "shrinkminfontsize"], default: DEFAULT_SHRINK_MIN_FONT_SIZE_PT, defaultUnit: "pt" },
1100
1671
  { key: "ap-word-wrap", keywords: ["\u81EA\u52A8\u6362\u884C", "\u4E0D\u6362\u884C", "wordwrap"] },
1101
1672
  {
1102
1673
  key: "ap-long-text-indent",
@@ -1116,10 +1687,43 @@ var PROPERTY_REGISTRY = [
1116
1687
  {
1117
1688
  key: "ap-img-fit-scale",
1118
1689
  keywords: ["\u653E\u5927\u6BD4\u4F8B", "\u526A\u88C1\u653E\u5927", "\u653E\u5927\u500D\u6570", "\u53D6\u666F", "\u88C1\u5207\u8303\u56F4", "fitscale", "zoom"],
1690
+ default: CROP_SCALE_MIN,
1691
+ defaultUnit: "%",
1119
1692
  tip: "\u526A\u88C1\u653E\u5927\uFF1A\u7B49\u6BD4\u94FA\u6EE1\u4E4B\u540E\u628A\u753B\u9762\u518D\u63A8\u5927\u8FD9\u4E48\u591A\uFF0C\u4E24\u8F74\u624D\u771F\u7684\u5404\u591A\u51FA\u4E00\u6761\u8FB9\u53EF\u88C1\u2014\u2014\u56FE\u4E0E\u6846\u540C\u6BD4\u4F8B\u65F6\u4E0D\u653E\u5927\u5C31\u4EC0\u4E48\u90FD\u88C1\u4E0D\u6389\u3002100\uFF1D\u4E0D\u653E\u5927\uFF08\u7F3A\u7701\uFF09\uFF0C\u4E0A\u9650 400\uFF1B\u8D85\u51FA\u6846\u7684\u90E8\u5206\u7531\u5143\u7D20\u6846\u88C1\u6389\u3002\u951A\u70B9\u9009\u4E2D\u7684\u90A3\u4E00\u70B9\u65E2\u662F\u53D6\u4F4D\u7684\u9489\u4F4F\u70B9\u3001\u4E5F\u662F\u653E\u5927\u7684\u4E2D\u5FC3\uFF0C\u4E24\u8005\u5171\u7528\u540C\u4E00\u4E2A\u503C\u3002\u4EC5\u300C\u526A\u88C1\u300D\u6863\u751F\u6548\uFF0C\u5176\u4F59\u7F29\u653E\u6A21\u5F0F\u4E0D\u51FA\u672C\u884C"
1120
1693
  }
1121
1694
  ]
1122
1695
  },
1696
+ {
1697
+ group: "flow-list",
1698
+ groupLabel: "\u6D41\u5F0F\u5217\u8868",
1699
+ items: [
1700
+ {
1701
+ key: "fl-columns",
1702
+ keywords: ["\u6BCF\u884C\u5217\u6570", "\u5217\u6570", "\u680F\u6570", "\u51E0\u5217", "flowcolumns"],
1703
+ tip: "\u4E00\u884C\u6392\u51E0\u4E2A\u5355\u5143\uFF0C\u5FC5\u987B\u7531\u4F60\u6307\u5B9A\u2014\u2014\u4E0D\u968F\u5185\u5BB9\u81EA\u52A8\u7B97\u5217\u6570\u3002\u586B\u7684\u5217\u6570\u4E58\u5355\u5143\u5BBD\u653E\u4E0D\u4E0B\u5143\u7D20\u6846\u65F6\u53EA\u7ED9\u63D0\u793A\u3001\u4E0D\u6539\u4F60\u7684\u6570\uFF0C\u51FA\u7EB8\u6309\u4F60\u586B\u7684\u6392"
1704
+ },
1705
+ {
1706
+ key: "fl-row-height",
1707
+ keywords: ["\u884C\u9AD8", "\u6BCF\u884C\u9AD8\u5EA6", "\u5355\u5143\u9AD8\u5EA6", "flowrowheight"],
1708
+ tip: "\u6BCF\u4E2A\u5355\u5143\u884C\u7684\u6700\u4F4E\u9AD8\u5EA6\uFF08\u6BEB\u7C73\uFF09\uFF0C\u4E0E\u8868\u683C\u884C\u9AD8\u540C\u4E00\u53E3\u5F84\uFF1A\u5185\u5BB9\u6BD4\u5B83\u9AD8\u65F6\u8FD9\u4E00\u884C\u4F1A\u6491\u9AD8\uFF0C\u4E0D\u4F1A\u88C1\u5B57"
1709
+ },
1710
+ {
1711
+ key: "fl-gap-x",
1712
+ keywords: ["\u5355\u5143\u95F4\u8DDD", "\u6A2A\u5411\u95F4\u8DDD", "\u683C\u95F4\u8DDD", "\u5217\u95F4\u8DDD", "flowgapx"],
1713
+ tip: "\u76F8\u90BB\u5355\u5143\u4E4B\u95F4\u7684\u6A2A\u5411\u7559\u767D\uFF08\u6BEB\u7C73\uFF09\uFF1B\u7EB5\u5411\u4E0D\u7559\u7F1D\uFF0C\u884C\u4E0E\u884C\u7684\u8DDD\u79BB\u7531\u884C\u9AD8\u627F\u62C5"
1714
+ },
1715
+ {
1716
+ key: "fl-auto-span",
1717
+ keywords: ["\u81EA\u9002\u5E94", "\u8DE8\u5217", "\u5185\u5BB9\u8FC7\u957F", "\u5360\u4E24\u5217", "\u81EA\u52A8\u6362\u884C", "flowsautspan", "flowautospan"],
1718
+ tip: "\u5355\u5143\u5185\u5BB9\u6BD4\u4E00\u5217\u8FD8\u5BBD\u65F6\uFF0C\u8BA9\u5B83\u5360\u6389\u4E24\u4E2A\u6216\u66F4\u591A\u5217\u4F4D\uFF1B\u5F53\u524D\u884C\u5269\u4E0D\u591F\u653E\u5C31\u628A\u6574\u4E2A\u5355\u5143\u632A\u5230\u4E0B\u4E00\u884C\u884C\u9996\uFF08\u7EDD\u4E0D\u628A\u8BCD\u5207\u4E24\u534A\uFF09\u3002\u9ED8\u8BA4\u5173\u2014\u2014\u5F00\u7740\u65F6\u51FA\u7EB8\u680F\u6570\u7531\u5B57\u53F7\u4E0E\u6846\u5BBD\u51B3\u5B9A"
1719
+ },
1720
+ {
1721
+ key: "fl-max-span",
1722
+ keywords: ["\u6700\u591A\u8DE8\u51E0\u5217", "\u8DE8\u5217\u4E0A\u9650", "flowmaxspan"],
1723
+ tip: "\u8DE8\u5217\u7684\u5217\u6570\u4E0A\u9650\uFF0C\u6700\u5927\u53EA\u80FD\u7B49\u4E8E\u300C\u6BCF\u884C\u5217\u6570\u300D\uFF1A\u628A\u6BCF\u884C\u5217\u6570\u6539\u5C0F\u65F6\uFF0C\u8FD9\u91CC\u4F1A\u88AB\u4E00\u5E76\u9876\u56DE\u53BB"
1724
+ }
1725
+ ]
1726
+ },
1123
1727
  {
1124
1728
  group: "code",
1125
1729
  groupLabel: "\u6761\u7801\u8BBE\u7F6E",
@@ -1127,12 +1731,28 @@ var PROPERTY_REGISTRY = [
1127
1731
  { key: "cd-type", keywords: ["\u7801\u5236", "\u6761\u7801\u7C7B\u578B", "\u6761\u5F62\u7801\u7C7B\u578B", "barcodetype", "code128", "ean13", "code39", "itf14"] },
1128
1732
  { key: "cd-dpi", keywords: ["\u6253\u5370\u673A\u5206\u8FA8\u7387", "dpi", "\u6253\u5370\u70B9", "\u70B9\u9635\u5BF9\u9F50", "203", "300"] },
1129
1733
  { key: "cd-bar-width", keywords: ["\u6761\u5BBD", "\u6761\u7C97\u7EC6", "barwidth", "\u6A21\u5757\u5BBD"] },
1734
+ {
1735
+ key: "cd-bar-quiet-zone",
1736
+ keywords: ["\u6761\u7801\u9759\u533A", "\u6761\u7801\u767D\u8FB9", "\u6761\u5F62\u7801\u7559\u767D", "\u6761\u7801\u7A7A\u767D\u8FB9", "barquietzone"],
1737
+ default: BARCODE_QUIET_ZONE_MODULES,
1738
+ defaultUnit: "\u6A21\u5757",
1739
+ tip: "\u6761\u5F62\u7801\u5DE6\u53F3\u4E24\u7AEF\u7684\u7A7A\u767D\u683C\u6570\uFF081 \u683C = 1 \u6761\u5BBD\uFF09\uFF1A\u7F3A\u7701 10\uFF0C\u6B63\u662F\u4E00\u7EF4\u7801\u7801\u5236\u8981\u6C42\u7684\u4E0B\u9650\uFF1B\u6570\u503C\u8D8A\u5C0F\u767D\u8FB9\u8D8A\u7A84\u3001\u540C\u6837\u7684\u6846\u5185\u6761\u8D8A\u7C97\uFF08\u53EF\u653E\u5927\uFF09\u3002\u586B 0 \u5373\u4E0D\u7559\u767D\u8FB9\uFF0C\u4F46\u9759\u533A\u53C2\u4E0E\u300C\u6761\u2192\u7A7A\u2192\u6761\u300D\u8DF3\u53D8\uFF0C\u7D27\u90BB\u6587\u5B57\u6216\u8868\u683C\u7EBF\u65F6\u53EF\u80FD\u626B\u4E0D\u51FA\uFF0C\u9700\u5B9E\u6253\u9A8C\u8BC1"
1740
+ },
1741
+ {
1742
+ key: "cd-bar-height",
1743
+ keywords: ["\u6761\u9AD8", "\u6761\u7801\u9AD8\u5EA6", "\u6761\u533A\u9AD8\u5EA6", "\u6761\u7801\u591A\u9AD8", "barheight"],
1744
+ default: BARCODE_BAR_HEIGHT_MODULES,
1745
+ defaultUnit: "\u6A21\u5757",
1746
+ tip: "\u9ED1\u767D\u6761\u672C\u4F53\u7684\u76EE\u6807\u9AD8\u5EA6\uFF08mm\uFF0C\u4E0D\u542B\u4E0B\u65B9\u6587\u5B57\uFF09\uFF1A\u6298\u7B97\u7C92\u5EA6\u5C31\u662F\u6BCF\u6A21\u5757\u7269\u7406\u5BBD\uFF0C\u6240\u4EE5\u53EA\u80FD\u7CBE\u786E\u5230\u5B83\u7684\u6574\u6570\u500D\u3002\u6761\u5BBD\u4F18\u5148\u2014\u2014\u53EF\u7528\u6846\u9AD8\u88C5\u4E0D\u4E0B\u65F6\u671F\u671B\u6761\u9AD8\u8BA9\u4F4D\uFF0C\u7EDD\u4E0D\u628A\u6761\u5BBD\u6324\u7A84\uFF08\u70ED\u654F\u51FA\u7EB8\u6E05\u6670\u5EA6\u9760\u6761\u5BBD\uFF09\u3002\u4E0E\u300C\u6700\u5927\u9AD8\u5EA6\u300D\u5206\u5DE5\u4E0D\u540C\uFF1A\u90A3\u6761\u9650\u7684\u662F\u6574\u56FE\uFF08\u542B\u6587\u5B57\uFF09\u7684\u4E0A\u9650"
1747
+ },
1130
1748
  { key: "cd-show-text", keywords: ["\u663E\u793A\u6587\u672C", "\u6761\u7801\u6587\u672C", "\u663E\u793A\u6570\u5B57"] },
1131
- { key: "cd-font-size", keywords: ["\u6761\u7801\u5B57\u53F7", "\u6587\u672C\u5B57\u53F7"] },
1749
+ { key: "cd-font-size", keywords: ["\u6761\u7801\u5B57\u53F7", "\u6587\u672C\u5B57\u53F7"], default: BARCODE_TEXT_FONT_SIZE_MODULES, defaultUnit: "\u6A21\u5757" },
1132
1750
  { key: "cd-ec-level", keywords: ["\u7EA0\u9519\u7EA7\u522B", "\u5BB9\u9519", "qrcodelevel"] },
1133
1751
  {
1134
1752
  key: "cd-quiet-zone",
1135
1753
  keywords: ["\u9759\u533A", "\u9759\u533A\u5BBD\u5EA6", "\u767D\u8FB9", "\u7A7A\u767D\u8FB9", "\u7559\u767D", "\u94FA\u6EE1", "quietzone"],
1754
+ default: QR_DEFAULT_QUIET_MODULES,
1755
+ defaultUnit: "\u6A21\u5757",
1136
1756
  tip: "\u4E8C\u7EF4\u7801\u56DB\u5468\u7559\u51FA\u7684\u7A7A\u767D\u683C\u6570\uFF1A0 \u5373\u4E0D\u7559\u767D\u8FB9\u3001\u7801\u9762\u7B49\u6BD4\u94FA\u6EE1\u5143\u7D20\u6846\uFF08\u6B64\u65F6\u9760\u6846\u5916\u7684\u767D\u7EB8\u5145\u5F53\u9759\u533A\uFF09\uFF1B\u6570\u503C\u8D8A\u5927\u767D\u8FB9\u8D8A\u5BBD\u3001\u7801\u9762\u5728\u6846\u5185\u8D8A\u5C0F\uFF08\u7F3A\u7701 0\uFF0C\u9700 ISO/IEC 18004 \u63A8\u8350\u9759\u533A\u65F6\u586B 4\uFF09"
1137
1757
  },
1138
1758
  { key: "cd-fit", keywords: ["\u7F29\u653E\u6A21\u5F0F", "\u62C9\u4F38", "\u7B49\u6BD4", "fit", "contain", "cover"] },
@@ -1156,6 +1776,7 @@ var PROPERTY_REGISTRY = [
1156
1776
  group: "border-bg",
1157
1777
  groupLabel: "\u8FB9\u6846\u4E0E\u80CC\u666F",
1158
1778
  items: [
1779
+ { key: "bb-border-style", keywords: ["\u7EBF\u578B", "\u8FB9\u6846\u7EBF\u578B", "\u5B9E\u7EBF", "\u865A\u7EBF", "\u70B9\u7EBF", "\u53CC\u7EBF", "borderstyle"] },
1159
1780
  { key: "bb-border-width", keywords: ["\u8FB9\u6846\u5BBD\u5EA6", "border"] },
1160
1781
  { key: "bb-border-color", keywords: ["\u8FB9\u6846\u989C\u8272"] },
1161
1782
  { key: "bb-bg-color", keywords: ["\u80CC\u666F\u8272", "background"] }
@@ -1217,6 +1838,14 @@ function searchProperties(search) {
1217
1838
  }
1218
1839
  return { groups, itemKeys };
1219
1840
  }
1841
+ function propertyDefault(key) {
1842
+ for (const g of PROPERTY_REGISTRY) {
1843
+ for (const item of g.items) {
1844
+ if (item.key === key && item.default !== void 0) return { value: item.default, unit: item.defaultUnit };
1845
+ }
1846
+ }
1847
+ return void 0;
1848
+ }
1220
1849
 
1221
1850
  // src/lexer.ts
1222
1851
  var DANGEROUS_PROPS = /* @__PURE__ */ new Set([
@@ -2478,7 +3107,16 @@ var ELEMENT_BINDING_REGISTRY = {
2478
3107
  image: [
2479
3108
  { targetPath: "options.src", label: "\u5185\u5BB9", dataSource: "main", placeholder: "\u8F93\u5165\u56FE\u7247\u8DEF\u5F84\uFF0C\u652F\u6301 /docfiles/... \u76F8\u5BF9\u8DEF\u5F84\u3001\u7EDD\u5BF9 URL \u6216 {\u5B57\u6BB5} \u8868\u8FBE\u5F0F" }
2480
3109
  ],
2481
- table: []
3110
+ table: [],
3111
+ // 流式列表的单元模板是一条完整表达式:列表路径写在里面({drugs.name}),不再单独配数据源
3112
+ flowList: [
3113
+ {
3114
+ targetPath: "options.formatter",
3115
+ label: "\u5355\u5143\u6A21\u677F",
3116
+ dataSource: "main",
3117
+ placeholder: "{drugs.name} {drugs.spec}"
3118
+ }
3119
+ ]
2482
3120
  };
2483
3121
  function getTableCellBindings(rowType, rowIndex, cellIndex, listField) {
2484
3122
  if (rowType === "data") {
@@ -3055,9 +3693,15 @@ function useBindingDisplay() {
3055
3693
  0 && (module.exports = {
3056
3694
  BARCODE_BAR_HEIGHT_MODULES,
3057
3695
  BARCODE_MARGIN_BOTTOM_MODULES,
3696
+ BARCODE_MIN_MODULE_WIDTH_MM,
3058
3697
  BARCODE_MODULE_WIDTH_MM,
3059
3698
  BARCODE_QUIET_ZONE_MODULES,
3060
3699
  BARCODE_TEXT_FONT_SIZE_MODULES,
3700
+ BORDER_EDGE_SIDES,
3701
+ BORDER_LINE_STYLES,
3702
+ CELL_BORDER_APPLY_HINT,
3703
+ CELL_BORDER_APPLY_HINT_MIXED,
3704
+ CELL_BORDER_APPLY_HINT_MULTI,
3061
3705
  CROP_AXIS_OPTIONS,
3062
3706
  CROP_GRID_OPTIONS,
3063
3707
  CROP_SAMPLE_IMAGE,
@@ -3065,12 +3709,21 @@ function useBindingDisplay() {
3065
3709
  CROP_SCALE_LABEL,
3066
3710
  CROP_SCALE_MAX,
3067
3711
  CROP_SCALE_MIN,
3712
+ DEFAULT_BORDER,
3068
3713
  DEFAULT_DEMO_DATA,
3069
3714
  DEFAULT_SHRINK_MIN_FONT_SIZE_PT,
3070
3715
  ELEMENT_BINDING_REGISTRY,
3716
+ ELEMENT_BORDER_APPLY_HINT,
3717
+ ELEMENT_BORDER_FALLBACK_WIDTH,
3071
3718
  ELEMENT_BORDER_SIDES,
3072
3719
  EXTENDED_FUNCTIONS,
3073
3720
  FIT_SCALE_MIN_PERCENT,
3721
+ FLOW_MAX_COLUMNS,
3722
+ FLOW_MAX_GAP_X_MM,
3723
+ FLOW_MAX_ROW_HEIGHT_MM,
3724
+ FLOW_MIN_COLUMNS,
3725
+ FLOW_MIN_GAP_X_MM,
3726
+ FLOW_MIN_ROW_HEIGHT_MM,
3074
3727
  GHOST_BORDER_CSS,
3075
3728
  IMAGE_FIT_OPTIONS,
3076
3729
  LABEL_PAPER_GROUP,
@@ -3078,17 +3731,28 @@ function useBindingDisplay() {
3078
3731
  MIN_SCALE_PERCENT,
3079
3732
  MIN_SHRINK_FONT_SIZE_PT,
3080
3733
  MM_PER_INCH,
3734
+ MM_TO_PX,
3081
3735
  PAPER_PRESETS,
3082
3736
  PRESET_COLORS,
3737
+ PREVIEW_ZOOM_GUARD_ID,
3083
3738
  PROPERTY_REGISTRY,
3739
+ QR_DEFAULT_QUIET_MODULES,
3084
3740
  RESIZE_POINTS,
3085
3741
  RULER_THICKNESS,
3086
3742
  ZONE_ALLOWED_TYPES,
3743
+ ZOOM_MAX,
3744
+ ZOOM_MIN,
3087
3745
  acceptsElementBorder,
3088
3746
  applyBorderPreset,
3747
+ applyElementBorderPreset,
3748
+ applyPreviewViewZoom,
3089
3749
  barcodeAvailableBoxMm,
3750
+ barcodeBarHeightModules,
3751
+ barcodeBarWidthRecommendText,
3090
3752
  barcodePreferredModuleWidthMm,
3753
+ barcodeQuietZoneModules,
3091
3754
  barcodeUnitsPerModule,
3755
+ barcodeWidthBoundModuleWidthMm,
3092
3756
  buildCropAnchor,
3093
3757
  buildRulerTicks,
3094
3758
  calcResizeRect,
@@ -3101,6 +3765,7 @@ function useBindingDisplay() {
3101
3765
  clampResizedColumnWidth,
3102
3766
  clampScalePercent,
3103
3767
  clampToZone,
3768
+ collectWritableCells,
3104
3769
  computeAdsorb,
3105
3770
  computeFitScale,
3106
3771
  createCell,
@@ -3115,14 +3780,24 @@ function useBindingDisplay() {
3115
3780
  cropScalePct,
3116
3781
  cropStyleDeclarations,
3117
3782
  cropWindow,
3783
+ defaultZoomKey,
3118
3784
  deleteCol,
3119
3785
  deleteRow,
3786
+ detectFlowListKey,
3787
+ effectiveElementBorderSpec,
3788
+ elementBorderEdgeVisible,
3789
+ elementVisibleBorders,
3120
3790
  engine,
3791
+ estimateTextWidthMm,
3121
3792
  evaluateTemplate,
3122
3793
  filterGroups,
3123
3794
  finalizeElementZone,
3124
3795
  findMainCell,
3796
+ fitZoom,
3125
3797
  floorFontSize,
3798
+ flowColumnWidthMm,
3799
+ flowGridStyle,
3800
+ flowSpanWidthMm,
3126
3801
  generateGroupId,
3127
3802
  generateId,
3128
3803
  getDemoData,
@@ -3138,6 +3813,8 @@ function useBindingDisplay() {
3138
3813
  isContinuousPaperSize,
3139
3814
  isLabelPaperSize,
3140
3815
  labelPaperDefaults,
3816
+ layoutBarcodeSize,
3817
+ layoutFlowList,
3141
3818
  matchKeywords,
3142
3819
  mergeCells,
3143
3820
  minorStepMM,
@@ -3145,36 +3822,59 @@ function useBindingDisplay() {
3145
3822
  nextWheelScale,
3146
3823
  normalizeSelection,
3147
3824
  normalizeTemplateUnits,
3825
+ paperWidthPx,
3148
3826
  parseCellFitKey,
3149
3827
  parseCropAnchor,
3828
+ propertyDefault,
3150
3829
  propertyTip,
3151
3830
  ptToMm,
3152
3831
  pxToMm,
3832
+ recommendBarcodeBarWidth,
3153
3833
  resolveBarcodeDesignValue,
3154
3834
  resolveBarcodeSize,
3835
+ resolveBorderEdgeStates,
3155
3836
  resolveCellBorderCss,
3837
+ resolveCellBorderDisplay,
3838
+ resolveCellGroupMode,
3156
3839
  resolveCellTextFit,
3157
3840
  resolveCropPreview,
3158
3841
  resolveCropTravel,
3159
3842
  resolveDesignImageSrc,
3160
3843
  resolveElementBorder,
3844
+ resolveElementBorderDisplay,
3845
+ resolveElementBorderSpec,
3161
3846
  resolveElementTextFit,
3847
+ resolveFlowColumns,
3848
+ resolveFlowGapX,
3849
+ resolveFlowMaxSpan,
3850
+ resolveFlowRowHeight,
3162
3851
  resolveOverlayPlacement,
3852
+ resolvePrinterDpi,
3853
+ resolveSharedCellType,
3163
3854
  resolveShrinkMinFontSize,
3164
3855
  resolveTextBinding,
3165
3856
  resolveToolbarOverflow,
3857
+ resolveZoomKey,
3166
3858
  roundFontSize,
3167
3859
  safeEval,
3168
3860
  sanitizeObjectPosition,
3169
3861
  searchProperties,
3862
+ setCellBorderEdge,
3863
+ setElementBorderEdge,
3864
+ setElementBorderEdgeVisible,
3865
+ setElementBorderField,
3170
3866
  setHeaderRepeat,
3171
3867
  setRowType,
3868
+ spanForText,
3172
3869
  splitCells,
3870
+ suggestFlowColumns,
3173
3871
  syncTableElementSize,
3174
3872
  useAlign,
3175
3873
  useBindingDisplay,
3176
3874
  useGroup,
3177
3875
  useKeyboard,
3178
3876
  useResize,
3179
- zoneFromPaperPoint
3877
+ zoneFromPaperPoint,
3878
+ zoomPresets,
3879
+ zoomValueOf
3180
3880
  });