@nice2dev/ui-printing 1.1.6 → 1.1.9

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.
Files changed (32) hide show
  1. package/dist/index.cjs +2 -2
  2. package/dist/index.d.ts +5 -5
  3. package/dist/index.mjs +1894 -1728
  4. package/dist/ui-printing.css +1 -1
  5. package/package.json +3 -2
  6. package/src/index.ts +5 -24
  7. package/src/print-button/NicePrintButton.tsx +44 -18
  8. package/src/print-button/PrintButton.module.css +147 -43
  9. package/src/print-preview/NicePrintPreview.tsx +19 -17
  10. package/src/print-preview/PrintPreview.module.css +60 -18
  11. package/src/print-queue/NicePrintQueue.tsx +76 -42
  12. package/src/print-queue/PrintQueue.module.css +207 -57
  13. package/src/template-browser/NiceTemplateBrowser.tsx +44 -19
  14. package/src/template-browser/TemplateBrowser.module.css +70 -25
  15. package/src/template-editor/NiceTemplateEditor.tsx +307 -182
  16. package/src/template-editor/TemplateEditor.module.css +184 -128
  17. package/src/types/printingTypes.ts +1 -1
  18. package/dist/index.d.ts.map +0 -1
  19. package/dist/print-button/NicePrintButton.d.ts.map +0 -1
  20. package/dist/print-button/index.d.ts.map +0 -1
  21. package/dist/print-preview/NicePrintPreview.d.ts.map +0 -1
  22. package/dist/print-preview/index.d.ts.map +0 -1
  23. package/dist/print-queue/NicePrintQueue.d.ts.map +0 -1
  24. package/dist/print-queue/index.d.ts.map +0 -1
  25. package/dist/style.css +0 -1
  26. package/dist/template-browser/NiceTemplateBrowser.d.ts.map +0 -1
  27. package/dist/template-browser/index.d.ts.map +0 -1
  28. package/dist/template-editor/NiceTemplateEditor.d.ts.map +0 -1
  29. package/dist/template-editor/index.d.ts.map +0 -1
  30. package/dist/types/printingTypes.d.ts.map +0 -1
  31. package/src/template-editor/NiceTemplateEditor.tsx.first +0 -1011
  32. package/src/template-editor/NiceTemplateEditor.tsx.tmp +0 -392
@@ -1,11 +1,24 @@
1
1
  /* eslint-disable jsx-a11y/click-events-have-key-events -- modal overlay backdrops (Esc-on-parent provides keyboard close), selection rows in .map() accompanied by visible cursor:pointer styling and sibling buttons; full keyboard migration via useAccessibleClick + extracted subcomponents tracked in TODO_1.0.10 A2.3 */
2
+ import { NiceIcon, useNiceTranslation } from '@nice2dev/ui';
2
3
  import React, { useState } from 'react';
3
4
 
4
- import type { PrintTemplate, TemplateId as _TemplateId, NiceTemplateBrowserProps } from '../types/printingTypes';
5
+ import type {
6
+ PrintTemplate,
7
+ TemplateId as _TemplateId,
8
+ NiceTemplateBrowserProps,
9
+ } from '../types/printingTypes';
5
10
 
6
11
  import styles from './TemplateBrowser.module.css';
7
12
 
8
- const CATEGORIES = ['Faktury', 'Raporty', 'Etykiety', 'Listy', 'Umowy', 'Inne'];
13
+ /** Built-in category chips; `key` is what a template's `category` field holds. */
14
+ const CATEGORIES: { key: string; fallback: string }[] = [
15
+ { key: 'printing.category.invoices', fallback: 'Invoices' },
16
+ { key: 'printing.category.reports', fallback: 'Reports' },
17
+ { key: 'printing.category.labels', fallback: 'Labels' },
18
+ { key: 'printing.category.letters', fallback: 'Letters' },
19
+ { key: 'printing.category.contracts', fallback: 'Contracts' },
20
+ { key: 'printing.category.other', fallback: 'Other' },
21
+ ];
9
22
 
10
23
  function importTemplateFromJson(file: File): Promise<PrintTemplate> {
11
24
  return new Promise((resolve, reject) => {
@@ -43,6 +56,7 @@ export const NiceTemplateBrowser: React.FC<NiceTemplateBrowserProps> = ({
43
56
  style,
44
57
  theme = 'light',
45
58
  }) => {
59
+ const { t } = useNiceTranslation();
46
60
  const [search, setSearch] = useState('');
47
61
  const [categoryFilter, setCategoryFilter] = useState<string | null>(null);
48
62
  const [hoveredId, setHoveredId] = useState<string | null>(null);
@@ -82,19 +96,23 @@ export const NiceTemplateBrowser: React.FC<NiceTemplateBrowserProps> = ({
82
96
  <input
83
97
  type="search"
84
98
  className={styles.searchInput}
85
- placeholder="Szukaj szablonów…"
99
+ placeholder={t('printing.searchTemplates', 'Search templates…')}
86
100
  value={search}
87
101
  onChange={(e) => setSearch(e.target.value)}
88
102
  />
89
- <button className={styles.actionBtn} onClick={onNew} title="Nowy szablon">
90
- + Nowy
103
+ <button
104
+ className={styles.actionBtn}
105
+ onClick={onNew}
106
+ title={t('printing.newTemplate', 'New template')}
107
+ >
108
+ <NiceIcon name="plus" size={14} /> {t('printing.new', 'New')}
91
109
  </button>
92
110
  <button
93
111
  className={styles.actionBtn}
94
112
  onClick={() => fileInputRef.current?.click()}
95
- title="Importuj JSON"
113
+ title={t('printing.importJson', 'Import JSON')}
96
114
  >
97
- ⬆ Import
115
+ <NiceIcon name="upload" size={14} /> {t('printing.import', 'Import')}
98
116
  </button>
99
117
  <input ref={fileInputRef} type="file" accept=".json" hidden onChange={handleFileImport} />
100
118
  </div>
@@ -105,15 +123,15 @@ export const NiceTemplateBrowser: React.FC<NiceTemplateBrowserProps> = ({
105
123
  className={`${styles.catChip} ${!categoryFilter ? styles.catChipActive : ''}`}
106
124
  onClick={() => setCategoryFilter(null)}
107
125
  >
108
- Wszystkie
126
+ {t('printing.filter.all', 'All')}
109
127
  </button>
110
128
  {CATEGORIES.map((cat) => (
111
129
  <button
112
- key={cat}
113
- className={`${styles.catChip} ${categoryFilter === cat ? styles.catChipActive : ''}`}
114
- onClick={() => setCategoryFilter((c) => (c === cat ? null : cat))}
130
+ key={cat.key}
131
+ className={`${styles.catChip} ${categoryFilter === cat.fallback ? styles.catChipActive : ''}`}
132
+ onClick={() => setCategoryFilter((c) => (c === cat.fallback ? null : cat.fallback))}
115
133
  >
116
- {cat}
134
+ {t(cat.key, cat.fallback)}
117
135
  </button>
118
136
  ))}
119
137
  </div>
@@ -164,9 +182,9 @@ export const NiceTemplateBrowser: React.FC<NiceTemplateBrowserProps> = ({
164
182
  onExport?.(tpl);
165
183
  exportTemplate(tpl);
166
184
  }}
167
- title="Eksportuj"
185
+ title={t('printing.export', 'Export')}
168
186
  >
169
- ⬇
187
+ <NiceIcon name="download" size={14} />
170
188
  </button>
171
189
  {onDelete && (
172
190
  <button
@@ -175,9 +193,9 @@ export const NiceTemplateBrowser: React.FC<NiceTemplateBrowserProps> = ({
175
193
  e.stopPropagation();
176
194
  onDelete(tpl.id);
177
195
  }}
178
- title="Usuń"
196
+ title={t('printing.action.remove', 'Remove')}
179
197
  >
180
- ✕
198
+ <NiceIcon name="trash" size={14} />
181
199
  </button>
182
200
  )}
183
201
  </div>
@@ -190,7 +208,10 @@ export const NiceTemplateBrowser: React.FC<NiceTemplateBrowserProps> = ({
190
208
  {tpl.description && <div className={styles.cardDesc}>{tpl.description}</div>}
191
209
  <div className={styles.cardMeta}>
192
210
  <span className={styles.cardSize}>
193
- {tpl.paperSize} {tpl.orientation === 'landscape' ? '↔' : '↕'}
211
+ {tpl.paperSize}{' '}
212
+ {tpl.orientation === 'landscape'
213
+ ? t('printing.orientation.landscape', 'landscape')
214
+ : t('printing.orientation.portrait', 'portrait')}
194
215
  </span>
195
216
  {tpl.category && <span className={styles.cardCat}>{tpl.category}</span>}
196
217
  </div>
@@ -209,9 +230,13 @@ export const NiceTemplateBrowser: React.FC<NiceTemplateBrowserProps> = ({
209
230
 
210
231
  {filtered.length === 0 && (
211
232
  <div className={styles.emptyState}>
212
- <span className={styles.emptyIcon}>📄</span>
233
+ <span className={styles.emptyIcon}>
234
+ <NiceIcon name="file" size={32} />
235
+ </span>
213
236
  <span>
214
- {search ? `Brak wyników dla "${search}"` : 'Brak szablonów. Utwórz pierwszy!'}
237
+ {search
238
+ ? `${t('printing.noMatches', 'No matches for')} "${search}"`
239
+ : t('printing.noTemplates', 'No templates yet.')}
215
240
  </span>
216
241
  </div>
217
242
  )}
@@ -10,7 +10,11 @@
10
10
  overflow: hidden;
11
11
  }
12
12
 
13
- .dark { background: var(--nice-text, #0f172a); color: var(--nice-border, #e2e8f0); border-color: var(--nice-text, #1e293b); }
13
+ .dark {
14
+ background: var(--nice-bg-primary, #0f172a);
15
+ color: var(--nice-text-secondary, #e2e8f0);
16
+ border-color: var(--nice-border-color, #1e293b);
17
+ }
14
18
 
15
19
  /* ── Top bar ── */
16
20
  .topBar {
@@ -18,12 +22,15 @@
18
22
  align-items: center;
19
23
  gap: var(--nice-space-2, 8px);
20
24
  padding: var(--nice-space-2-5, 10px) var(--nice-space-3, 12px);
21
- background: var(--nice-bg, #FFF);
25
+ background: var(--nice-bg, #fff);
22
26
  border-bottom: 1px solid var(--nice-border, #e2e8f0);
23
27
  flex-shrink: 0;
24
28
  }
25
29
 
26
- .dark .topBar { background: var(--nice-text, #1e293b); border-bottom-color: var(--nice-text, #334155); }
30
+ .dark .topBar {
31
+ background: var(--nice-bg-secondary, #1e293b);
32
+ border-bottom-color: var(--nice-border-color, #334155);
33
+ }
27
34
 
28
35
  .searchInput {
29
36
  flex: 1;
@@ -36,14 +43,21 @@
36
43
  outline: none;
37
44
  }
38
45
 
39
- .searchInput:focus { border-color: var(--nice-primary-light, #93c5fd); background: var(--nice-bg, #FFF); }
40
- .dark .searchInput { background: var(--nice-text, #334155); border-color: var(--nice-text-secondary, #475569); color: var(--nice-border, #e2e8f0); }
46
+ .searchInput:focus {
47
+ border-color: var(--nice-primary-light, #93c5fd);
48
+ background: var(--nice-bg, #fff);
49
+ }
50
+ .dark .searchInput {
51
+ background: var(--nice-bg-tertiary, #334155);
52
+ border-color: var(--nice-border-color, #475569);
53
+ color: var(--nice-text-secondary, #e2e8f0);
54
+ }
41
55
 
42
56
  .actionBtn {
43
57
  padding: var(--nice-space-1-5, 6px) var(--nice-space-3, 12px);
44
58
  border: 1px solid var(--nice-border, #e2e8f0);
45
59
  border-radius: var(--nice-radius-md, 6px);
46
- background: var(--nice-bg, #FFF);
60
+ background: var(--nice-bg, #fff);
47
61
  cursor: pointer;
48
62
  font-size: 12px;
49
63
  font-weight: 500;
@@ -52,8 +66,14 @@
52
66
  transition: all 0.1s;
53
67
  }
54
68
 
55
- .actionBtn:hover { background: var(--nice-bg-secondary, #f1f5f9); }
56
- .dark .actionBtn { background: var(--nice-text, #334155); border-color: var(--nice-text-secondary, #475569); color: var(--nice-border, #e2e8f0); }
69
+ .actionBtn:hover {
70
+ background: var(--nice-bg-secondary, #f1f5f9);
71
+ }
72
+ .dark .actionBtn {
73
+ background: var(--nice-bg-tertiary, #334155);
74
+ border-color: var(--nice-border-color, #475569);
75
+ color: var(--nice-text-secondary, #e2e8f0);
76
+ }
57
77
 
58
78
  /* ── Categories ── */
59
79
  .categoryRow {
@@ -63,28 +83,33 @@
63
83
  border-bottom: 1px solid var(--nice-bg-secondary, #f1f5f9);
64
84
  flex-wrap: wrap;
65
85
  flex-shrink: 0;
66
- background: var(--nice-bg, #FFF);
86
+ background: var(--nice-bg, #fff);
67
87
  }
68
88
 
69
- .dark .categoryRow { background: var(--nice-text, #1e293b); border-bottom-color: var(--nice-text, #334155); }
89
+ .dark .categoryRow {
90
+ background: var(--nice-bg-secondary, #1e293b);
91
+ border-bottom-color: var(--nice-border-color, #334155);
92
+ }
70
93
 
71
94
  .catChip {
72
95
  padding: var(--nice-space-0-75, 3px) var(--nice-space-2-5, 10px);
73
96
  border: 1px solid var(--nice-border, #e2e8f0);
74
97
  border-radius: var(--nice-radius-xl, 14px);
75
- background: var(--nice-bg, #FFF);
98
+ background: var(--nice-bg, #fff);
76
99
  cursor: pointer;
77
100
  font-size: 12px;
78
101
  color: var(--nice-text-secondary, #64748b);
79
102
  transition: all 0.1s;
80
103
  }
81
104
 
82
- .catChip:hover { background: var(--nice-bg-secondary, #f1f5f9); }
105
+ .catChip:hover {
106
+ background: var(--nice-bg-secondary, #f1f5f9);
107
+ }
83
108
 
84
109
  .catChipActive {
85
110
  background: var(--nice-primary-hover, #2563eb);
86
111
  border-color: var(--nice-primary-hover, #2563eb);
87
- color: var(--nice-bg, #FFF);
112
+ color: var(--nice-text-on-primary, #fff);
88
113
  }
89
114
 
90
115
  /* ── Template grid ── */
@@ -102,7 +127,7 @@
102
127
  .card {
103
128
  flex: 0 0 auto;
104
129
  width: 180px;
105
- background: var(--nice-bg, #FFF);
130
+ background: var(--nice-bg, #fff);
106
131
  border: 2px solid var(--nice-border, #e2e8f0);
107
132
  border-radius: var(--nice-radius-lg, 8px);
108
133
  overflow: hidden;
@@ -120,7 +145,10 @@
120
145
  box-shadow: 0 0 0 3px var(--nice-primary-tint-15, rgba(37, 99, 235, 0.15));
121
146
  }
122
147
 
123
- .dark .card { background: var(--nice-text, #1e293b); border-color: var(--nice-text, #334155); }
148
+ .dark .card {
149
+ background: var(--nice-bg-secondary, #1e293b);
150
+ border-color: var(--nice-border-color, #334155);
151
+ }
124
152
 
125
153
  /* Thumbnail */
126
154
  .thumbnail {
@@ -145,7 +173,7 @@
145
173
 
146
174
  .paperMini {
147
175
  width: 70px;
148
- background: var(--nice-bg, #FFF);
176
+ background: var(--nice-bg, #fff);
149
177
  border: 1px solid var(--nice-border, #e2e8f0);
150
178
  border-radius: var(--nice-radius-sm, 2px);
151
179
  padding: var(--nice-space-2, 8px) var(--nice-space-1-5, 6px);
@@ -175,7 +203,7 @@
175
203
  .overlayBtn {
176
204
  width: 32px;
177
205
  height: 32px;
178
- background: var(--nice-bg, #FFF);
206
+ background: var(--nice-bg, #fff);
179
207
  border: none;
180
208
  border-radius: var(--nice-radius-full, 50%);
181
209
  cursor: pointer;
@@ -186,11 +214,16 @@
186
214
  transition: all 0.1s;
187
215
  }
188
216
 
189
- .overlayBtn:hover { background: var(--nice-primary-bg, #e0f2fe); }
217
+ .overlayBtn:hover {
218
+ background: var(--nice-primary-bg, #e0f2fe);
219
+ }
190
220
 
191
221
  .overlayBtnDanger {
192
- width: 28px; height: 28px;
193
- display: flex; align-items: center; justify-content: center;
222
+ width: 28px;
223
+ height: 28px;
224
+ display: flex;
225
+ align-items: center;
226
+ justify-content: center;
194
227
  background: var(--nice-overlay-light-90, rgba(255, 255, 255, 0.9));
195
228
  border: 1px solid var(--nice-border, #e2e8f0);
196
229
  border-radius: var(--nice-radius-md, 6px);
@@ -200,10 +233,14 @@
200
233
  transition: all 0.1s;
201
234
  }
202
235
 
203
- .overlayBtnDanger:hover { background: var(--nice-danger-bg, #fee2e2) !important; }
236
+ .overlayBtnDanger:hover {
237
+ background: var(--nice-danger-bg, #fee2e2) !important;
238
+ }
204
239
 
205
240
  /* Card body */
206
- .cardBody { padding: var(--nice-space-2, 8px) var(--nice-space-2-5, 10px); }
241
+ .cardBody {
242
+ padding: var(--nice-space-2, 8px) var(--nice-space-2-5, 10px);
243
+ }
207
244
 
208
245
  .cardName {
209
246
  font-weight: 600;
@@ -215,7 +252,9 @@
215
252
  margin-bottom: var(--nice-space-0-5, 2px);
216
253
  }
217
254
 
218
- .dark .cardName { color: var(--nice-bg-secondary, #f1f5f9); }
255
+ .dark .cardName {
256
+ color: var(--nice-text-primary, #f1f5f9);
257
+ }
219
258
 
220
259
  .cardDesc {
221
260
  font-size: 11px;
@@ -251,7 +290,11 @@
251
290
  border-radius: var(--nice-radius-sm, 4px);
252
291
  }
253
292
 
254
- .cardTags { display: flex; gap: var(--nice-space-0-75, 3px); flex-wrap: wrap; }
293
+ .cardTags {
294
+ display: flex;
295
+ gap: var(--nice-space-0-75, 3px);
296
+ flex-wrap: wrap;
297
+ }
255
298
 
256
299
  .cardTag {
257
300
  font-size: 9px;
@@ -274,4 +317,6 @@
274
317
  font-size: 14px;
275
318
  }
276
319
 
277
- .emptyIcon { font-size: 40px; }
320
+ .emptyIcon {
321
+ font-size: 40px;
322
+ }