@nice2dev/ui-printing 1.2.0 → 1.2.1
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/index.cjs +2 -2
- package/dist/index.mjs +1312 -1295
- package/dist/types/printingTypes.d.ts +2 -2
- package/dist/ui-printing.css +1 -1
- package/package.json +3 -3
- package/src/__tests__/renders-empty.test.tsx +46 -0
- package/src/print-preview/NicePrintPreview.tsx +5 -1
- package/src/print-preview/PrintPreview.module.css +1 -1
- package/src/print-queue/NicePrintQueue.tsx +5 -1
- package/src/print-queue/PrintQueue.module.css +1 -1
- package/src/template-browser/NiceTemplateBrowser.tsx +5 -1
- package/src/template-editor/NiceTemplateEditor.tsx +52 -25
- package/src/template-editor/TemplateEditor.module.css +3 -3
- package/src/types/printingTypes.ts +2 -2
|
@@ -149,6 +149,7 @@ function historyReducer(state: HistoryState, action: HistoryAction): HistoryStat
|
|
|
149
149
|
*/
|
|
150
150
|
const INK = '#000000';
|
|
151
151
|
/** Same, for the faint grey a watermark is drawn in. */
|
|
152
|
+
// audit-allow: literal-color — ink on the white page - a print colour
|
|
152
153
|
const INK_FAINT = '#94a3b8';
|
|
153
154
|
|
|
154
155
|
function uid() {
|
|
@@ -395,6 +396,7 @@ const SectionCanvas: React.FC<SectionCanvasProps> = ({
|
|
|
395
396
|
const [draggingOver, setDraggingOver] = useState(false);
|
|
396
397
|
|
|
397
398
|
const sectionTypeColors: Record<string, string> = {
|
|
399
|
+
// audit-allow: literal-color +3 — band tints on the white page - print colours
|
|
398
400
|
header: 'rgba(219,234,254,0.35)',
|
|
399
401
|
footer: 'rgba(220,252,231,0.35)',
|
|
400
402
|
background: 'rgba(254,249,195,0.35)',
|
|
@@ -556,6 +558,7 @@ const Toolbar: React.FC<ToolbarProps> = ({
|
|
|
556
558
|
onSendBackward,
|
|
557
559
|
onSave,
|
|
558
560
|
}) => {
|
|
561
|
+
const { t } = useNiceTranslation();
|
|
559
562
|
const { t: tr } = useNiceTranslation();
|
|
560
563
|
const [insertOpen, setInsertOpen] = useState(false);
|
|
561
564
|
const ZOOM_PRESETS = [0.5, 0.75, 1, 1.25, 1.5, 2];
|
|
@@ -578,14 +581,14 @@ const Toolbar: React.FC<ToolbarProps> = ({
|
|
|
578
581
|
<button
|
|
579
582
|
className={`${styles.toolbarBtn} ${tpl.orientation === 'portrait' ? styles.toolbarBtnActive : ''}`}
|
|
580
583
|
onClick={() => onPaperChange(tpl.paperSize, 'portrait')}
|
|
581
|
-
title=
|
|
584
|
+
title={t('templateEditor.portrait', 'Portrait')}
|
|
582
585
|
>
|
|
583
586
|
<NiceIcon name="file" size={14} />
|
|
584
587
|
</button>
|
|
585
588
|
<button
|
|
586
589
|
className={`${styles.toolbarBtn} ${tpl.orientation === 'landscape' ? styles.toolbarBtnActive : ''}`}
|
|
587
590
|
onClick={() => onPaperChange(tpl.paperSize, 'landscape')}
|
|
588
|
-
title=
|
|
591
|
+
title={t('templateEditor.landscape', 'Landscape')}
|
|
589
592
|
>
|
|
590
593
|
<NiceIcon name="file" size={14} style={{ transform: 'rotate(90deg)' }} />
|
|
591
594
|
</button>
|
|
@@ -641,7 +644,9 @@ const Toolbar: React.FC<ToolbarProps> = ({
|
|
|
641
644
|
{fieldTypeLabel(tr, t)}
|
|
642
645
|
</button>
|
|
643
646
|
))}
|
|
644
|
-
<div className={styles.insertCategory}>
|
|
647
|
+
<div className={styles.insertCategory}>
|
|
648
|
+
{t('templateEditor.staticElements', 'Static elements')}
|
|
649
|
+
</div>
|
|
645
650
|
{[
|
|
646
651
|
'static_text',
|
|
647
652
|
'static_image',
|
|
@@ -663,7 +668,7 @@ const Toolbar: React.FC<ToolbarProps> = ({
|
|
|
663
668
|
{fieldTypeLabel(tr, t)}
|
|
664
669
|
</button>
|
|
665
670
|
))}
|
|
666
|
-
<div className={styles.insertCategory}>
|
|
671
|
+
<div className={styles.insertCategory}>{t('templateEditor.special', 'Special')}</div>
|
|
667
672
|
<button
|
|
668
673
|
className={styles.insertItem}
|
|
669
674
|
onClick={() => {
|
|
@@ -754,7 +759,11 @@ const Toolbar: React.FC<ToolbarProps> = ({
|
|
|
754
759
|
⊥
|
|
755
760
|
</button>
|
|
756
761
|
<span className={styles.toolbarSep} />
|
|
757
|
-
<button
|
|
762
|
+
<button
|
|
763
|
+
className={styles.toolbarBtn}
|
|
764
|
+
onClick={onBringForward}
|
|
765
|
+
title={t('templateEditor.bringForward', 'Bring forward')}
|
|
766
|
+
>
|
|
758
767
|
<NiceIcon name="arrow-up" size={14} />
|
|
759
768
|
</button>
|
|
760
769
|
<button
|
|
@@ -844,6 +853,7 @@ const LeftPanel: React.FC<LeftPanelProps> = ({
|
|
|
844
853
|
onUpdateTpl,
|
|
845
854
|
onReorderField,
|
|
846
855
|
}) => {
|
|
856
|
+
const { t } = useNiceTranslation();
|
|
847
857
|
const { t: tr } = useNiceTranslation();
|
|
848
858
|
const [search, setSearch] = useState('');
|
|
849
859
|
const filteredFields = schema?.fields.filter(
|
|
@@ -982,7 +992,7 @@ const LeftPanel: React.FC<LeftPanelProps> = ({
|
|
|
982
992
|
{/* ── Watermarks tab ── */}
|
|
983
993
|
{activeTab === 'watermarks' && (
|
|
984
994
|
<>
|
|
985
|
-
<div className={styles.panelHeader}>
|
|
995
|
+
<div className={styles.panelHeader}>{t('templateEditor.watermarks', 'Watermarks')}</div>
|
|
986
996
|
<div className={styles.wmList}>
|
|
987
997
|
{(tpl.watermarks ?? []).map((wm) => (
|
|
988
998
|
<div key={wm.id} className={styles.wmItem}>
|
|
@@ -1022,7 +1032,7 @@ const LeftPanel: React.FC<LeftPanelProps> = ({
|
|
|
1022
1032
|
</div>
|
|
1023
1033
|
)}
|
|
1024
1034
|
<div className={styles.wmRow}>
|
|
1025
|
-
<span className={styles.wmLabel}>
|
|
1035
|
+
<span className={styles.wmLabel}>{t('templateEditor.opacity', 'Opacity')}</span>
|
|
1026
1036
|
<input
|
|
1027
1037
|
type="range"
|
|
1028
1038
|
min={0.02}
|
|
@@ -1131,12 +1141,12 @@ const LeftPanel: React.FC<LeftPanelProps> = ({
|
|
|
1131
1141
|
{/* ── Signatures tab ── */}
|
|
1132
1142
|
{activeTab === 'signatures' && (
|
|
1133
1143
|
<>
|
|
1134
|
-
<div className={styles.panelHeader}>
|
|
1144
|
+
<div className={styles.panelHeader}>{t('templateEditor.signatures', 'Signatures')}</div>
|
|
1135
1145
|
<div className={styles.wmList}>
|
|
1136
1146
|
{(tpl.signatures ?? []).map((sig) => (
|
|
1137
1147
|
<div key={sig.id} className={styles.wmItem}>
|
|
1138
1148
|
<div className={styles.wmRow}>
|
|
1139
|
-
<span className={styles.wmLabel}>
|
|
1149
|
+
<span className={styles.wmLabel}>{t('templateEditor.label', 'Label')}</span>
|
|
1140
1150
|
<input
|
|
1141
1151
|
className={styles.wmInput}
|
|
1142
1152
|
value={sig.label}
|
|
@@ -1150,7 +1160,7 @@ const LeftPanel: React.FC<LeftPanelProps> = ({
|
|
|
1150
1160
|
/>
|
|
1151
1161
|
</div>
|
|
1152
1162
|
<div className={styles.wmRow}>
|
|
1153
|
-
<span className={styles.wmLabel}>
|
|
1163
|
+
<span className={styles.wmLabel}>{t('templateEditor.signerName', 'Name')}</span>
|
|
1154
1164
|
<input
|
|
1155
1165
|
className={styles.wmInput}
|
|
1156
1166
|
value={sig.signerName ?? ''}
|
|
@@ -1254,7 +1264,9 @@ const LeftPanel: React.FC<LeftPanelProps> = ({
|
|
|
1254
1264
|
/>
|
|
1255
1265
|
</div>
|
|
1256
1266
|
<div className={styles.settingsRow}>
|
|
1257
|
-
<label className={styles.settingsLabel}>
|
|
1267
|
+
<label className={styles.settingsLabel}>
|
|
1268
|
+
{t('templateEditor.category', 'Category')}
|
|
1269
|
+
</label>
|
|
1258
1270
|
<input
|
|
1259
1271
|
className={styles.settingsInput}
|
|
1260
1272
|
value={tpl.category ?? ''}
|
|
@@ -1315,6 +1327,7 @@ const PropertiesPanel: React.FC<PropertiesPanelProps> = ({
|
|
|
1315
1327
|
paperWidthMm,
|
|
1316
1328
|
paperHeightMm: _paperHeightMm,
|
|
1317
1329
|
}) => {
|
|
1330
|
+
const { t } = useNiceTranslation();
|
|
1318
1331
|
const { t: tr } = useNiceTranslation();
|
|
1319
1332
|
const p = useCallback(
|
|
1320
1333
|
(patch: Partial<FieldPosition>) =>
|
|
@@ -1425,7 +1438,7 @@ const PropertiesPanel: React.FC<PropertiesPanelProps> = ({
|
|
|
1425
1438
|
<span className={styles.posUnit}>°</span>
|
|
1426
1439
|
</div>
|
|
1427
1440
|
<div className={styles.posCell}>
|
|
1428
|
-
<label className={styles.posLabel}>Z-idx</label>
|
|
1441
|
+
<label className={styles.posLabel}>{t('templateEditor.zIdx', 'Z-idx')}</label>
|
|
1429
1442
|
<input
|
|
1430
1443
|
type="number"
|
|
1431
1444
|
step={1}
|
|
@@ -1473,9 +1486,11 @@ const PropertiesPanel: React.FC<PropertiesPanelProps> = ({
|
|
|
1473
1486
|
<>
|
|
1474
1487
|
{hasText && (
|
|
1475
1488
|
<div className={styles.styleGroup}>
|
|
1476
|
-
<div className={styles.styleGroupTitle}>
|
|
1489
|
+
<div className={styles.styleGroupTitle}>{t('templateEditor.font', 'Font')}</div>
|
|
1477
1490
|
<div className={styles.styleRow}>
|
|
1478
|
-
<label className={styles.styleLabel}>
|
|
1491
|
+
<label className={styles.styleLabel}>
|
|
1492
|
+
{t('templateEditor.fontFamily', 'Family')}
|
|
1493
|
+
</label>
|
|
1479
1494
|
<select
|
|
1480
1495
|
className={styles.styleSelectFull}
|
|
1481
1496
|
value={field.style.fontFamily ?? 'sans-serif'}
|
|
@@ -1574,7 +1589,9 @@ const PropertiesPanel: React.FC<PropertiesPanelProps> = ({
|
|
|
1574
1589
|
</div>
|
|
1575
1590
|
</div>
|
|
1576
1591
|
<div className={styles.styleRow}>
|
|
1577
|
-
<label className={styles.styleLabel}>
|
|
1592
|
+
<label className={styles.styleLabel}>
|
|
1593
|
+
{t('templateEditor.lineHeight', 'Line h.')}
|
|
1594
|
+
</label>
|
|
1578
1595
|
<input
|
|
1579
1596
|
type="number"
|
|
1580
1597
|
step={0.1}
|
|
@@ -1624,7 +1641,7 @@ const PropertiesPanel: React.FC<PropertiesPanelProps> = ({
|
|
|
1624
1641
|
</button>
|
|
1625
1642
|
</div>
|
|
1626
1643
|
<div className={styles.styleRow}>
|
|
1627
|
-
<label className={styles.styleLabel}>
|
|
1644
|
+
<label className={styles.styleLabel}>{t('templateEditor.border', 'Border')}</label>
|
|
1628
1645
|
<input
|
|
1629
1646
|
type="number"
|
|
1630
1647
|
step={0.5}
|
|
@@ -1651,7 +1668,7 @@ const PropertiesPanel: React.FC<PropertiesPanelProps> = ({
|
|
|
1651
1668
|
</select>
|
|
1652
1669
|
</div>
|
|
1653
1670
|
<div className={styles.styleRow}>
|
|
1654
|
-
<label className={styles.styleLabel}>
|
|
1671
|
+
<label className={styles.styleLabel}>{t('templateEditor.radius', 'Radius')}</label>
|
|
1655
1672
|
<input
|
|
1656
1673
|
type="number"
|
|
1657
1674
|
step={1}
|
|
@@ -1664,7 +1681,9 @@ const PropertiesPanel: React.FC<PropertiesPanelProps> = ({
|
|
|
1664
1681
|
<span className={styles.styleUnit}>px</span>
|
|
1665
1682
|
</div>
|
|
1666
1683
|
<div className={styles.styleRow}>
|
|
1667
|
-
<label className={styles.styleLabel}>
|
|
1684
|
+
<label className={styles.styleLabel}>
|
|
1685
|
+
{t('templateEditor.padding', 'Padding')}
|
|
1686
|
+
</label>
|
|
1668
1687
|
<input
|
|
1669
1688
|
type="number"
|
|
1670
1689
|
step={0.5}
|
|
@@ -1677,7 +1696,9 @@ const PropertiesPanel: React.FC<PropertiesPanelProps> = ({
|
|
|
1677
1696
|
<span className={styles.styleUnit}>mm</span>
|
|
1678
1697
|
</div>
|
|
1679
1698
|
<div className={styles.styleRow}>
|
|
1680
|
-
<label className={styles.styleLabel}>
|
|
1699
|
+
<label className={styles.styleLabel}>
|
|
1700
|
+
{t('templateEditor.opacity', 'Opacity')}
|
|
1701
|
+
</label>
|
|
1681
1702
|
<input
|
|
1682
1703
|
type="range"
|
|
1683
1704
|
min={0.1}
|
|
@@ -1707,7 +1728,7 @@ const PropertiesPanel: React.FC<PropertiesPanelProps> = ({
|
|
|
1707
1728
|
className={styles.styleInputFull}
|
|
1708
1729
|
value={field.dataPath}
|
|
1709
1730
|
onChange={(e) => onChange({ dataPath: e.target.value })}
|
|
1710
|
-
placeholder=
|
|
1731
|
+
placeholder={t('templateEditor.egInvoiceNumber', 'e.g. invoice.number')}
|
|
1711
1732
|
/>
|
|
1712
1733
|
</div>
|
|
1713
1734
|
<div className={styles.styleRow}>
|
|
@@ -1716,7 +1737,7 @@ const PropertiesPanel: React.FC<PropertiesPanelProps> = ({
|
|
|
1716
1737
|
className={styles.styleInputFull}
|
|
1717
1738
|
value={field.format ?? ''}
|
|
1718
1739
|
onChange={(e) => onChange({ format: e.target.value })}
|
|
1719
|
-
placeholder=
|
|
1740
|
+
placeholder={t('templateEditor.ddMmYyyy000', 'DD.MM.YYYY / #,##0.00')}
|
|
1720
1741
|
/>
|
|
1721
1742
|
</div>
|
|
1722
1743
|
<div className={styles.styleRow}>
|
|
@@ -1793,11 +1814,13 @@ const PropertiesPanel: React.FC<PropertiesPanelProps> = ({
|
|
|
1793
1814
|
},
|
|
1794
1815
|
})
|
|
1795
1816
|
}
|
|
1796
|
-
placeholder=
|
|
1817
|
+
placeholder={t('templateEditor.egInvoiceIsPaid', 'e.g. invoice.isPaid')}
|
|
1797
1818
|
/>
|
|
1798
1819
|
</div>
|
|
1799
1820
|
<div className={styles.styleRow}>
|
|
1800
|
-
<label className={styles.styleLabel}>
|
|
1821
|
+
<label className={styles.styleLabel}>
|
|
1822
|
+
{t('templateEditor.operator', 'Operator')}
|
|
1823
|
+
</label>
|
|
1801
1824
|
<select
|
|
1802
1825
|
className={styles.styleSelectFull}
|
|
1803
1826
|
value={field.conditional?.operator ?? 'eq'}
|
|
@@ -1834,7 +1857,7 @@ const PropertiesPanel: React.FC<PropertiesPanelProps> = ({
|
|
|
1834
1857
|
},
|
|
1835
1858
|
})
|
|
1836
1859
|
}
|
|
1837
|
-
placeholder='
|
|
1860
|
+
placeholder={t('templateEditor.egTruePaid', 'e.g. true / "PAID"')}
|
|
1838
1861
|
/>
|
|
1839
1862
|
</div>
|
|
1840
1863
|
{field.conditional?.field && (
|
|
@@ -2031,7 +2054,11 @@ export const NiceTemplateEditor: React.FC<NiceTemplateEditorProps> = ({
|
|
|
2031
2054
|
if (e.ctrlKey || e.metaKey) {
|
|
2032
2055
|
setSelectedIds((prev) => {
|
|
2033
2056
|
const n = new Set(prev);
|
|
2034
|
-
n.has(id)
|
|
2057
|
+
if (n.has(id)) {
|
|
2058
|
+
n.delete(id);
|
|
2059
|
+
} else {
|
|
2060
|
+
n.add(id);
|
|
2061
|
+
}
|
|
2035
2062
|
return n;
|
|
2036
2063
|
});
|
|
2037
2064
|
} else if (e.shiftKey) {
|
|
@@ -752,7 +752,7 @@
|
|
|
752
752
|
}
|
|
753
753
|
|
|
754
754
|
.dark .testDataBar {
|
|
755
|
-
background: #1c1709;
|
|
755
|
+
background: var(--nice-warning-bg, #1c1709);
|
|
756
756
|
border-bottom-color: var(--nice-warning-dark, #78350f);
|
|
757
757
|
}
|
|
758
758
|
|
|
@@ -902,7 +902,7 @@
|
|
|
902
902
|
.marginGuide {
|
|
903
903
|
position: absolute;
|
|
904
904
|
pointer-events: none;
|
|
905
|
-
border: 1px dashed
|
|
905
|
+
border: 1px dashed color-mix(in srgb, var(--nice-color-primary, #3b82f6) 35%, transparent);
|
|
906
906
|
z-index: 0;
|
|
907
907
|
}
|
|
908
908
|
|
|
@@ -941,7 +941,7 @@
|
|
|
941
941
|
letter-spacing: 0.06em;
|
|
942
942
|
padding: var(--nice-space-px, 1px) var(--nice-space-1-25, 5px);
|
|
943
943
|
border-radius: var(--nice-radius-sm, 3px);
|
|
944
|
-
background:
|
|
944
|
+
background: color-mix(in srgb, var(--nice-text-muted, #94a3b8) 25%, transparent);
|
|
945
945
|
color: var(--nice-text-secondary, #64748b);
|
|
946
946
|
pointer-events: none;
|
|
947
947
|
z-index: 50;
|
|
@@ -238,7 +238,7 @@ export interface NiceTemplateEditorProps {
|
|
|
238
238
|
}
|
|
239
239
|
|
|
240
240
|
export interface NiceTemplateBrowserProps {
|
|
241
|
-
templates
|
|
241
|
+
templates?: PrintTemplate[];
|
|
242
242
|
selectedId?: TemplateId;
|
|
243
243
|
onSelect?: (template: PrintTemplate) => void;
|
|
244
244
|
onImport?: (template: PrintTemplate) => void;
|
|
@@ -271,7 +271,7 @@ export interface NicePrintPreviewProps {
|
|
|
271
271
|
}
|
|
272
272
|
|
|
273
273
|
export interface NicePrintQueueProps {
|
|
274
|
-
jobs
|
|
274
|
+
jobs?: PrintJob[];
|
|
275
275
|
printers?: PrinterInfo[];
|
|
276
276
|
onJobUpdate: (id: PrintJobId, patch: Partial<PrintJob>) => void;
|
|
277
277
|
onJobRemove: (id: PrintJobId) => void;
|