web-to-print 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/cjs/app-globals-V2Kpy_OQ.js +5 -0
- package/dist/cjs/canvas-helpers-A6rp5rPD.js +765 -0
- package/dist/cjs/index-IFGFRm-i.js +1649 -0
- package/dist/cjs/index.cjs.js +232 -0
- package/dist/cjs/loader.cjs.js +13 -0
- package/dist/cjs/logo-BUX-b45R.js +18 -0
- package/dist/cjs/web-to-print.cjs.js +25 -0
- package/dist/cjs/wtp-editor_2.cjs.entry.js +12386 -0
- package/dist/cjs/wtp-logo-renderer.cjs.entry.js +353 -0
- package/dist/cjs/wtp-print-area-editor.cjs.entry.js +431 -0
- package/dist/collection/collection-manifest.json +16 -0
- package/dist/collection/components/wtp-editor/wtp-editor.css +124 -0
- package/dist/collection/components/wtp-editor/wtp-editor.js +1114 -0
- package/dist/collection/components/wtp-logo-renderer/wtp-logo-renderer.css +30 -0
- package/dist/collection/components/wtp-logo-renderer/wtp-logo-renderer.js +455 -0
- package/dist/collection/components/wtp-logo-upload/wtp-logo-upload.css +428 -0
- package/dist/collection/components/wtp-logo-upload/wtp-logo-upload.js +573 -0
- package/dist/collection/components/wtp-print-area-editor/wtp-print-area-editor.css +20 -0
- package/dist/collection/components/wtp-print-area-editor/wtp-print-area-editor.js +600 -0
- package/dist/collection/examples/schaeffler--big.svg +1 -0
- package/dist/collection/index.js +8 -0
- package/dist/collection/types/editor.js +1 -0
- package/dist/collection/types/index.js +2 -0
- package/dist/collection/types/labels.js +30 -0
- package/dist/collection/types/logo.js +13 -0
- package/dist/collection/utils/background-removal.js +717 -0
- package/dist/collection/utils/canvas-helpers.js +380 -0
- package/dist/collection/utils/format-detection.js +48 -0
- package/dist/collection/utils/html-render-helpers.js +106 -0
- package/dist/collection/utils/image-preview.js +54 -0
- package/dist/collection/utils/logo-validation.js +141 -0
- package/dist/collection/utils/pdf-export.js +224 -0
- package/dist/components/index.d.ts +35 -0
- package/dist/components/index.js +1 -0
- package/dist/components/p-5qCsRzlt.js +1 -0
- package/dist/components/p-Bn9gR_8e.js +1 -0
- package/dist/components/p-D8pVJRuX.js +1 -0
- package/dist/components/wtp-editor.d.ts +11 -0
- package/dist/components/wtp-editor.js +1 -0
- package/dist/components/wtp-logo-renderer.d.ts +11 -0
- package/dist/components/wtp-logo-renderer.js +1 -0
- package/dist/components/wtp-logo-upload.d.ts +11 -0
- package/dist/components/wtp-logo-upload.js +1 -0
- package/dist/components/wtp-print-area-editor.d.ts +11 -0
- package/dist/components/wtp-print-area-editor.js +1 -0
- package/dist/esm/app-globals-DQuL1Twl.js +3 -0
- package/dist/esm/canvas-helpers-CK8OAq2J.js +748 -0
- package/dist/esm/index-CUetmLbL.js +1641 -0
- package/dist/esm/index.js +228 -0
- package/dist/esm/loader.js +11 -0
- package/dist/esm/logo-D8pVJRuX.js +15 -0
- package/dist/esm/web-to-print.js +21 -0
- package/dist/esm/wtp-editor_2.entry.js +12383 -0
- package/dist/esm/wtp-logo-renderer.entry.js +351 -0
- package/dist/esm/wtp-print-area-editor.entry.js +429 -0
- package/dist/index.cjs.js +1 -0
- package/dist/index.js +1 -0
- package/dist/types/components/wtp-editor/wtp-editor.d.ts +101 -0
- package/dist/types/components/wtp-logo-renderer/wtp-logo-renderer.d.ts +55 -0
- package/dist/types/components/wtp-logo-upload/wtp-logo-upload.d.ts +76 -0
- package/dist/types/components/wtp-print-area-editor/wtp-print-area-editor.d.ts +43 -0
- package/dist/types/components.d.ts +507 -0
- package/dist/types/index.d.ts +11 -0
- package/dist/types/stencil-public-runtime.d.ts +1860 -0
- package/dist/types/types/editor.d.ts +79 -0
- package/dist/types/types/index.d.ts +5 -0
- package/dist/types/types/labels.d.ts +30 -0
- package/dist/types/types/logo.d.ts +47 -0
- package/dist/types/utils/background-removal.d.ts +95 -0
- package/dist/types/utils/canvas-helpers.d.ts +60 -0
- package/dist/types/utils/format-detection.d.ts +4 -0
- package/dist/types/utils/html-render-helpers.d.ts +44 -0
- package/dist/types/utils/image-preview.d.ts +13 -0
- package/dist/types/utils/logo-validation.d.ts +2 -0
- package/dist/types/utils/pdf-export.d.ts +32 -0
- package/dist/web-to-print/index.esm.js +1 -0
- package/dist/web-to-print/p-611ec561.entry.js +1 -0
- package/dist/web-to-print/p-703e4c52.entry.js +1 -0
- package/dist/web-to-print/p-CK8OAq2J.js +1 -0
- package/dist/web-to-print/p-CUetmLbL.js +2 -0
- package/dist/web-to-print/p-D8pVJRuX.js +1 -0
- package/dist/web-to-print/p-DQuL1Twl.js +1 -0
- package/dist/web-to-print/p-b532777b.entry.js +1 -0
- package/dist/web-to-print/web-to-print.esm.js +1 -0
- package/loader/cdn.js +1 -0
- package/loader/index.cjs.js +1 -0
- package/loader/index.d.ts +24 -0
- package/loader/index.es2017.js +1 -0
- package/loader/index.js +2 -0
- package/package.json +68 -0
- package/readme.md +490 -0
package/readme.md
ADDED
|
@@ -0,0 +1,490 @@
|
|
|
1
|
+
# web-to-print
|
|
2
|
+
|
|
3
|
+
A Stencil.js Web Components library for promotional product customization. Upload logos, preview them on products, and edit layouts — all client-side, no server required.
|
|
4
|
+
|
|
5
|
+
## Components
|
|
6
|
+
|
|
7
|
+
| Component | Description | Encapsulation |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `<wtp-logo-upload>` | Logo upload with drag-and-drop, URL fetch, format detection, print validation, and optional background removal | Shadow DOM |
|
|
10
|
+
| `<wtp-logo-renderer>` | Static logo-on-product rendering via Fabric.js StaticCanvas | Scoped |
|
|
11
|
+
| `<wtp-editor>` | Interactive canvas editor with toolbar, text tool, and JSON serialization via Fabric.js | Scoped |
|
|
12
|
+
|
|
13
|
+
Components communicate via CustomEvents and can be used standalone or composed together.
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install web-to-print
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Lazy-loading (recommended)
|
|
22
|
+
|
|
23
|
+
```html
|
|
24
|
+
<script type="module" src="web-to-print/loader/index.js"></script>
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Or with a bundler:
|
|
28
|
+
|
|
29
|
+
```js
|
|
30
|
+
import { defineCustomElements } from 'web-to-print/loader';
|
|
31
|
+
defineCustomElements();
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Standalone custom elements
|
|
35
|
+
|
|
36
|
+
```js
|
|
37
|
+
import 'web-to-print/wtp-logo-upload';
|
|
38
|
+
import 'web-to-print/wtp-editor';
|
|
39
|
+
import 'web-to-print/wtp-logo-renderer';
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Quick Start
|
|
43
|
+
|
|
44
|
+
```html
|
|
45
|
+
<!-- 1. Upload a logo -->
|
|
46
|
+
<wtp-logo-upload id="uploader"></wtp-logo-upload>
|
|
47
|
+
|
|
48
|
+
<!-- 2. Render it on a product -->
|
|
49
|
+
<wtp-logo-renderer id="renderer" width="400" height="300"></wtp-logo-renderer>
|
|
50
|
+
|
|
51
|
+
<!-- 3. Open an interactive editor -->
|
|
52
|
+
<wtp-editor id="editor" width="800" height="600"></wtp-editor>
|
|
53
|
+
|
|
54
|
+
<script>
|
|
55
|
+
const uploader = document.getElementById('uploader');
|
|
56
|
+
const renderer = document.getElementById('renderer');
|
|
57
|
+
const editor = document.getElementById('editor');
|
|
58
|
+
|
|
59
|
+
uploader.addEventListener('wtpLogoValidated', async (e) => {
|
|
60
|
+
const logo = e.detail;
|
|
61
|
+
|
|
62
|
+
// Place logo on the static renderer
|
|
63
|
+
renderer.logos = [{
|
|
64
|
+
id: 'logo-1',
|
|
65
|
+
dataUrl: logo.dataUrl,
|
|
66
|
+
transform: { x: 200, y: 150, scaleX: 0.5, scaleY: 0.5, angle: 0 },
|
|
67
|
+
}];
|
|
68
|
+
|
|
69
|
+
// Or add it to the interactive editor
|
|
70
|
+
await editor.addLogo(logo);
|
|
71
|
+
});
|
|
72
|
+
</script>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Component API
|
|
76
|
+
|
|
77
|
+
### `<wtp-logo-upload>`
|
|
78
|
+
|
|
79
|
+
Validates uploaded files against configurable print-quality rules (format, DPI, dimensions, file size). Supports file picker, drag-and-drop, and URL fetch.
|
|
80
|
+
|
|
81
|
+
#### Properties
|
|
82
|
+
|
|
83
|
+
| Property | Attribute | Type | Default | Description |
|
|
84
|
+
|---|---|---|---|---|
|
|
85
|
+
| `config` | — | `LogoValidationConfig` | See below | Validation rules for uploaded logos |
|
|
86
|
+
| `accept` | `accept` | `string` | `'image/png,image/jpeg,image/svg+xml,image/tiff,image/avif,application/pdf'` | Accepted MIME types for file input |
|
|
87
|
+
| `multiple` | `multiple` | `boolean` | `false` | Allow multiple file uploads |
|
|
88
|
+
| `disabled` | `disabled` | `boolean` | `false` | Disable the upload component |
|
|
89
|
+
| `enableBackgroundRemoval` | `enable-background-removal` | `boolean` | `false` | Enable client-side background removal for raster images |
|
|
90
|
+
| `bgRemovalConfig` | — | `Partial<BgRemovalConfig>` | `{}` | Configuration for the color-based background removal algorithm |
|
|
91
|
+
| `labels` | — | `Partial<LogoUploadLabels>` | `{}` | Override user-facing strings (see [Localizing text](#localizing-text-labels-prop)) |
|
|
92
|
+
|
|
93
|
+
**Default validation config:**
|
|
94
|
+
|
|
95
|
+
```js
|
|
96
|
+
{
|
|
97
|
+
minDpi: 300,
|
|
98
|
+
maxFileSize: 50 * 1024 * 1024, // 50 MB
|
|
99
|
+
minWidth: 100,
|
|
100
|
+
minHeight: 100,
|
|
101
|
+
allowedFormats: ['png', 'jpeg', 'svg', 'pdf', 'tiff', 'avif'],
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
#### Events
|
|
106
|
+
|
|
107
|
+
| Event | Detail | Description |
|
|
108
|
+
|---|---|---|
|
|
109
|
+
| `wtpLogoValidated` | `LogoData` | Fires when a logo passes validation |
|
|
110
|
+
| `wtpLogoRejected` | `{ file: File; issues: LogoValidationIssue[] }` | Fires when a logo fails validation |
|
|
111
|
+
| `wtpLogoProcessing` | `boolean` | Fires when processing state changes (`true` = busy) |
|
|
112
|
+
|
|
113
|
+
#### Background Removal
|
|
114
|
+
|
|
115
|
+
When `enable-background-removal` is set and a raster image (PNG, JPEG, TIFF, AVIF) is uploaded, the user is presented with a choice between the original image and a version with the background removed. SVG and PDF files skip this step entirely.
|
|
116
|
+
|
|
117
|
+
The background removal runs entirely client-side using a color-based flood-fill algorithm with zero external dependencies:
|
|
118
|
+
|
|
119
|
+
1. Samples all pixels along the 4 edges of the image
|
|
120
|
+
2. Finds the dominant edge color (quantized into buckets)
|
|
121
|
+
3. BFS flood-fills from edge pixels within `tolerance` distance of the background color
|
|
122
|
+
4. Sets matched pixels to transparent — interior regions of the same color (e.g. white text) are preserved
|
|
123
|
+
|
|
124
|
+
Configure via `bgRemovalConfig`:
|
|
125
|
+
|
|
126
|
+
| Option | Type | Default | Description |
|
|
127
|
+
|---|---|---|---|
|
|
128
|
+
| `tolerance` | `number` | `40` | Color distance threshold (0-255, Euclidean RGB distance) |
|
|
129
|
+
| `minEdgeRatio` | `number` | `0.3` | Minimum fraction of edge pixels sharing a color to count as background |
|
|
130
|
+
|
|
131
|
+
```html
|
|
132
|
+
<wtp-logo-upload enable-background-removal></wtp-logo-upload>
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
#### URL Input
|
|
136
|
+
|
|
137
|
+
Users can also paste an HTTPS URL to fetch a remote logo. The fetched file goes through the same validation pipeline. Non-HTTPS URLs are rejected, and CORS errors are displayed with a clear message.
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
### `<wtp-logo-renderer>`
|
|
142
|
+
|
|
143
|
+
Non-interactive canvas for rendering logos on product images. Uses Fabric.js `StaticCanvas` for lightweight rendering without user interaction.
|
|
144
|
+
|
|
145
|
+
#### Properties
|
|
146
|
+
|
|
147
|
+
| Property | Attribute | Type | Default | Description |
|
|
148
|
+
|---|---|---|---|---|
|
|
149
|
+
| `productImage` | `product-image` | `string \| undefined` | `undefined` | Product background image URL |
|
|
150
|
+
| `width` | `width` | `number` | `600` | Canvas width in pixels |
|
|
151
|
+
| `height` | `height` | `number` | `400` | Canvas height in pixels |
|
|
152
|
+
| `logos` | — | `PlacedLogo[]` | `[]` | Array of logos to place on the canvas |
|
|
153
|
+
| `backgroundColor` | `background-color` | `string` | `'#ffffff'` | Canvas background color |
|
|
154
|
+
| `printArea` | — | `PrintArea \| undefined` | `undefined` | Auto-fits logos without an explicit `transform` into the area (0–1 relative coords) |
|
|
155
|
+
|
|
156
|
+
#### Events
|
|
157
|
+
|
|
158
|
+
| Event | Detail | Description |
|
|
159
|
+
|---|---|---|
|
|
160
|
+
| `wtpRenderComplete` | `{ dataUrl: string }` | Fires when all logos have been rendered |
|
|
161
|
+
| `wtpRenderError` | `{ message: string }` | Fires on rendering error |
|
|
162
|
+
|
|
163
|
+
#### Methods
|
|
164
|
+
|
|
165
|
+
| Method | Signature | Description |
|
|
166
|
+
|---|---|---|
|
|
167
|
+
| `exportImage` | `(format?: 'png' \| 'jpeg', quality?: number) => Promise<string>` | Export canvas as a data URL |
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
### `<wtp-editor>`
|
|
172
|
+
|
|
173
|
+
Interactive canvas editor with a built-in toolbar for adding text, changing fonts, deleting objects, and exporting. Uses Fabric.js `Canvas` for full interactivity (drag, resize, rotate).
|
|
174
|
+
|
|
175
|
+
#### Properties
|
|
176
|
+
|
|
177
|
+
| Property | Attribute | Type | Default | Description |
|
|
178
|
+
|---|---|---|---|---|
|
|
179
|
+
| `width` | `width` | `number` | `800` | Canvas width in pixels |
|
|
180
|
+
| `height` | `height` | `number` | `600` | Canvas height in pixels |
|
|
181
|
+
| `productImage` | `product-image` | `string \| undefined` | `undefined` | Product background image URL |
|
|
182
|
+
| `initialState` | `initial-state` | `string \| undefined` | `undefined` | JSON-serialized initial editor state |
|
|
183
|
+
| `fonts` | — | `string[]` | `['Arial', 'Helvetica', 'Times New Roman', 'Georgia', 'Verdana']` | Available font families for the text tool |
|
|
184
|
+
| `printArea` | — | `PrintArea \| undefined` | `undefined` | Print area (0–1 relative coords) used to constrain objects to a defined region |
|
|
185
|
+
| `debug` | `debug` | `boolean` | `false` | Show the print-area overlay and clamp bounding box on the canvas |
|
|
186
|
+
| `labels` | — | `Partial<EditorLabels>` | `{}` | Override toolbar strings (see [Localizing text](#localizing-text-labels-prop)) |
|
|
187
|
+
|
|
188
|
+
#### Events
|
|
189
|
+
|
|
190
|
+
| Event | Detail | Description |
|
|
191
|
+
|---|---|---|
|
|
192
|
+
| `wtpEditorReady` | `void` | Fires when the canvas is initialized |
|
|
193
|
+
| `wtpEditorStateChanged` | `EditorState` | Fires on any object change (add/move/remove) |
|
|
194
|
+
| `wtpEditorObjectSelected` | `{ id: string; type: string }` | Fires when an object is selected |
|
|
195
|
+
| `wtpEditorObjectDeselected` | `void` | Fires when the selection is cleared |
|
|
196
|
+
|
|
197
|
+
#### Methods
|
|
198
|
+
|
|
199
|
+
| Method | Signature | Description |
|
|
200
|
+
|---|---|---|
|
|
201
|
+
| `addLogo` | `(logoData: LogoData) => Promise<string>` | Add a logo image, returns its object ID |
|
|
202
|
+
| `addText` | `(text: string, options?: { fontFamily?, fontSize?, fill? }) => Promise<string>` | Add a text object, returns its object ID |
|
|
203
|
+
| `updateText` | `(id: string, text: string) => Promise<void>` | Update the text content of an `i-text` object by ID |
|
|
204
|
+
| `removeObject` | `(id: string) => Promise<void>` | Remove an object by ID |
|
|
205
|
+
| `resetCanvas` | `() => Promise<void>` | Clear all user objects, keep the canvas instance alive |
|
|
206
|
+
| `exportState` | `() => Promise<EditorState>` | Export the full editor state as a serializable object |
|
|
207
|
+
| `loadState` | `(state: EditorState) => Promise<void>` | Restore a previously exported editor state |
|
|
208
|
+
| `exportImage` | `(format?: 'png' \| 'jpeg', quality?: number) => Promise<string>` | Export canvas as a data URL (1× resolution) |
|
|
209
|
+
| `exportImageHighRes` | `(format?, quality?, multiplier?) => Promise<{ dataUrl, width, height }>` | High-resolution export for PDF/print (default 3× multiplier) |
|
|
210
|
+
| `getObjects` | `() => Promise<{ id: string; type: string }[]>` | List all objects on the canvas |
|
|
211
|
+
|
|
212
|
+
## TypeScript Types
|
|
213
|
+
|
|
214
|
+
All types are exported from the package root:
|
|
215
|
+
|
|
216
|
+
```ts
|
|
217
|
+
import type {
|
|
218
|
+
LogoFormat, // 'png' | 'jpeg' | 'svg' | 'pdf' | 'tiff' | 'avif' | 'unknown'
|
|
219
|
+
LogoMetadata, // Format, dimensions, DPI, file size, transparency
|
|
220
|
+
LogoValidationConfig, // Validation rules (minDpi, maxFileSize, minWidth, etc.)
|
|
221
|
+
LogoValidationIssue, // { code, severity, message }
|
|
222
|
+
LogoValidationResult, // { valid, metadata, issues }
|
|
223
|
+
LogoData, // { dataUrl, previewDataUrl?, metadata }
|
|
224
|
+
BgRemovalConfig, // { tolerance, minEdgeRatio }
|
|
225
|
+
CanvasTransform, // { x, y, scaleX, scaleY, angle, skewX?, skewY? }
|
|
226
|
+
PlacedLogo, // { id, dataUrl, previewDataUrl?, transform? }
|
|
227
|
+
PlacedText, // { id, text, fontFamily, fontSize, fill, transform }
|
|
228
|
+
EditorState, // { fabricJson, logos, texts, productImage, width, height }
|
|
229
|
+
PrintArea, // { topLeft, topRight, bottomRight, bottomLeft, bulge? } (0–1 coords)
|
|
230
|
+
RelativePoint, // { x, y } in 0–1 space
|
|
231
|
+
ArticleView, // Single article view + print-method metadata
|
|
232
|
+
Article, // Multi-view article descriptor
|
|
233
|
+
LogoUploadLabels, // Strings used by <wtp-logo-upload>
|
|
234
|
+
EditorLabels, // Strings used by <wtp-editor>
|
|
235
|
+
} from 'web-to-print';
|
|
236
|
+
|
|
237
|
+
import {
|
|
238
|
+
DEFAULT_VALIDATION_CONFIG,
|
|
239
|
+
DEFAULT_BG_REMOVAL_CONFIG,
|
|
240
|
+
DEFAULT_LOGO_UPLOAD_LABELS,
|
|
241
|
+
DEFAULT_EDITOR_LABELS,
|
|
242
|
+
} from 'web-to-print';
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## Theming
|
|
246
|
+
|
|
247
|
+
Components expose colors and the font family as **CSS custom properties** with sensible fallbacks. Override them with a plain CSS rule — no build step or SCSS knowledge required. CSS variables inherit through the Shadow DOM, so the same rule themes `wtp-logo-upload` (shadow-encapsulated) and the scoped components.
|
|
248
|
+
|
|
249
|
+
```css
|
|
250
|
+
/* Theme all components globally */
|
|
251
|
+
:root {
|
|
252
|
+
--wtp-color-primary: #ff6600;
|
|
253
|
+
--wtp-color-primary-hover: #e65500;
|
|
254
|
+
--wtp-color-primary-light: #ffe4d1;
|
|
255
|
+
--wtp-color-primary-fade: rgba(255, 102, 0, 0.2); /* used for focus glow */
|
|
256
|
+
--wtp-font-family: 'Inter', sans-serif;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/* Or scope to a single instance */
|
|
260
|
+
wtp-editor {
|
|
261
|
+
--wtp-color-border: #aaaaaa;
|
|
262
|
+
--wtp-color-bg-muted: #1e1e1e;
|
|
263
|
+
--wtp-color-text: #ffffff;
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### Available CSS custom properties
|
|
268
|
+
|
|
269
|
+
| Variable | Default | Description |
|
|
270
|
+
|---|---|---|
|
|
271
|
+
| `--wtp-color-primary` | `#2563eb` | Primary action color (buttons, focus rings, dashed outlines) |
|
|
272
|
+
| `--wtp-color-primary-hover` | `#1d4ed8` | Primary hover state |
|
|
273
|
+
| `--wtp-color-primary-light` | `#dbeafe` | Primary tint (drop zone hover/drag-over) |
|
|
274
|
+
| `--wtp-color-primary-fade` | `rgba(37, 99, 235, 0.2)` | Translucent primary (selected-preview glow) |
|
|
275
|
+
| `--wtp-color-secondary` | `#64748b` | Secondary accent (upload icon stroke, preview hover) |
|
|
276
|
+
| `--wtp-color-error` | `#dc2626` | Error state color |
|
|
277
|
+
| `--wtp-color-error-light` | `#fee2e2` | Error background tint |
|
|
278
|
+
| `--wtp-color-success` | `#16a34a` | Success state color |
|
|
279
|
+
| `--wtp-color-success-light` | `#dcfce7` | Success background tint |
|
|
280
|
+
| `--wtp-color-warning` | `#d97706` | Warning state color |
|
|
281
|
+
| `--wtp-color-warning-light` | `#fef3c7` | Warning background tint |
|
|
282
|
+
| `--wtp-color-text` | `#1e293b` | Primary text color |
|
|
283
|
+
| `--wtp-color-text-muted` | `#64748b` | Muted/secondary text color |
|
|
284
|
+
| `--wtp-color-border` | `#e2e8f0` | Border color |
|
|
285
|
+
| `--wtp-color-bg` | `#ffffff` | Background color |
|
|
286
|
+
| `--wtp-color-bg-muted` | `#f8fafc` | Muted background (toolbar, drop zone) |
|
|
287
|
+
| `--wtp-font-family` | system stack | UI font family |
|
|
288
|
+
|
|
289
|
+
> Spacing and border-radius remain build-time SCSS tokens (`$wtp-spacing-*`, `$wtp-radius-*`) — they're not exposed as CSS variables. Fork the package if you need to change them.
|
|
290
|
+
|
|
291
|
+
### `::part()` styling (`wtp-logo-upload`)
|
|
292
|
+
|
|
293
|
+
Because `wtp-logo-upload` uses Shadow DOM, internal elements aren't reachable with normal selectors. Use the `::part()` pseudo-element to target specific elements:
|
|
294
|
+
|
|
295
|
+
```css
|
|
296
|
+
wtp-logo-upload::part(url-submit-btn) {
|
|
297
|
+
background: #16a34a;
|
|
298
|
+
border-color: #16a34a;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
wtp-logo-upload::part(upload-zone drag-over) {
|
|
302
|
+
border-color: red;
|
|
303
|
+
background: #ffe5e5;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
wtp-logo-upload::part(preview-item selected) {
|
|
307
|
+
outline: 3px solid gold;
|
|
308
|
+
}
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
| Part name | Element |
|
|
312
|
+
|---|---|
|
|
313
|
+
| `root` | Outer wrapper |
|
|
314
|
+
| `url-input` | URL `<input type="url">` |
|
|
315
|
+
| `url-submit-btn` | "Fetch" button |
|
|
316
|
+
| `url-error` | URL error message paragraph |
|
|
317
|
+
| `divider` | "or" divider line |
|
|
318
|
+
| `upload-zone` | Drag-and-drop zone (also `drag-over` and `disabled` modifier parts) |
|
|
319
|
+
| `prompt-text` / `prompt-hint` | Default prompt text and hint inside the drop zone |
|
|
320
|
+
| `rejections` / `rejection-item` | Validation failure container and items |
|
|
321
|
+
| `pending-choices` / `choice-card` / `choice-option` | Background-removal choice cards |
|
|
322
|
+
| `previews` / `preview-item` | Preview gallery and items (selected items also get `selected`) |
|
|
323
|
+
| `remove-btn` | Per-preview remove button |
|
|
324
|
+
|
|
325
|
+
### Localizing text (`labels` prop)
|
|
326
|
+
|
|
327
|
+
`wtp-logo-upload` and `wtp-editor` accept a `labels` prop with **partial** overrides — supply only the keys you want to change; missing keys fall back to the English defaults.
|
|
328
|
+
|
|
329
|
+
```html
|
|
330
|
+
<wtp-logo-upload id="uploader"></wtp-logo-upload>
|
|
331
|
+
<script>
|
|
332
|
+
document.getElementById('uploader').labels = {
|
|
333
|
+
dropPromptText: 'Logo hierher ziehen oder klicken',
|
|
334
|
+
dropPromptHint: 'PNG, JPEG, SVG, TIFF oder AVIF',
|
|
335
|
+
dividerText: 'oder',
|
|
336
|
+
urlSubmit: 'Laden',
|
|
337
|
+
urlPlaceholder: 'https://beispiel.de/logo.png',
|
|
338
|
+
urlErrorEmpty: 'Bitte eine URL eingeben',
|
|
339
|
+
urlErrorInvalid: 'Ungültiges URL-Format',
|
|
340
|
+
urlErrorProtocol: 'Nur HTTPS-URLs werden unterstützt',
|
|
341
|
+
urlErrorNetwork: 'Bild konnte nicht geladen werden (CORS).',
|
|
342
|
+
bgRemovalUseOriginal: 'Original verwenden',
|
|
343
|
+
bgRemovalUseRemoved: 'Ohne Hintergrund',
|
|
344
|
+
bgRemovalProcessing: 'Hintergrund wird entfernt...',
|
|
345
|
+
bgRemovalFailed: 'Fehlgeschlagen',
|
|
346
|
+
uploadAriaLabel: 'Logo-Datei hochladen',
|
|
347
|
+
removeAriaLabel: (name) => `${name} entfernen`,
|
|
348
|
+
rejectionDpiUnit: 'DPI',
|
|
349
|
+
};
|
|
350
|
+
</script>
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
```js
|
|
354
|
+
document.querySelector('wtp-editor').labels = {
|
|
355
|
+
addTextButton: 'Text hinzufügen',
|
|
356
|
+
addTextTooltip: 'Text hinzufügen',
|
|
357
|
+
fontSelectTooltip: 'Schriftart',
|
|
358
|
+
colorPickerTooltip: 'Textfarbe',
|
|
359
|
+
deleteButtonTooltip: 'Auswahl löschen',
|
|
360
|
+
defaultText: 'Neuer Text',
|
|
361
|
+
};
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
Import the type and the defaults if you want to start from a complete object:
|
|
365
|
+
|
|
366
|
+
```ts
|
|
367
|
+
import {
|
|
368
|
+
LogoUploadLabels,
|
|
369
|
+
EditorLabels,
|
|
370
|
+
DEFAULT_LOGO_UPLOAD_LABELS,
|
|
371
|
+
DEFAULT_EDITOR_LABELS,
|
|
372
|
+
} from 'web-to-print';
|
|
373
|
+
|
|
374
|
+
const myLabels: LogoUploadLabels = {
|
|
375
|
+
...DEFAULT_LOGO_UPLOAD_LABELS,
|
|
376
|
+
dividerText: 'oder',
|
|
377
|
+
};
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
#### `LogoUploadLabels` keys
|
|
381
|
+
|
|
382
|
+
`urlPlaceholder`, `urlSubmit`, `dividerText`, `dropPromptText`, `dropPromptHint`, `uploadAriaLabel`, `removeAriaLabel(fileName)`, `urlErrorEmpty`, `urlErrorInvalid`, `urlErrorProtocol`, `urlErrorHttp(status, statusText)`, `urlErrorNetwork`, `urlErrorFetch`, `bgRemovalProcessing`, `bgRemovalUseOriginal`, `bgRemovalUseRemoved`, `bgRemovalFailed`, `rejectionDpiUnit`.
|
|
383
|
+
|
|
384
|
+
#### `EditorLabels` keys
|
|
385
|
+
|
|
386
|
+
`addTextButton`, `addTextTooltip`, `fontSelectTooltip`, `colorPickerTooltip`, `deleteButtonTooltip`, `defaultText`.
|
|
387
|
+
|
|
388
|
+
## Development
|
|
389
|
+
|
|
390
|
+
```bash
|
|
391
|
+
# Install dependencies
|
|
392
|
+
npm install
|
|
393
|
+
|
|
394
|
+
# Dev server with hot reload
|
|
395
|
+
npm start
|
|
396
|
+
|
|
397
|
+
# Build for production
|
|
398
|
+
npm run build
|
|
399
|
+
|
|
400
|
+
# Run all tests (spec + e2e)
|
|
401
|
+
npm test
|
|
402
|
+
|
|
403
|
+
# Run only unit tests
|
|
404
|
+
npm run test.spec
|
|
405
|
+
|
|
406
|
+
# Run only e2e tests
|
|
407
|
+
npm run test.e2e
|
|
408
|
+
|
|
409
|
+
# Run tests in watch mode
|
|
410
|
+
npm run test.watch
|
|
411
|
+
|
|
412
|
+
# Run a single test file
|
|
413
|
+
npx stencil test --spec -- src/utils/format-detection.spec.ts
|
|
414
|
+
|
|
415
|
+
# Lint
|
|
416
|
+
npm run lint
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
## Release
|
|
420
|
+
|
|
421
|
+
Releases are published to npm via a GitHub Action (`.github/workflows/release.yml`). Two flows are supported:
|
|
422
|
+
|
|
423
|
+
### Option A — local version bump (recommended)
|
|
424
|
+
|
|
425
|
+
```bash
|
|
426
|
+
npm run release:patch # 0.1.0 → 0.1.1
|
|
427
|
+
npm run release:minor # 0.1.0 → 0.2.0
|
|
428
|
+
npm run release:major # 0.1.0 → 1.0.0
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
Each script bumps `package.json`, creates a `v<version>` git tag, and pushes both. The GitHub Action then runs tests, builds, publishes to npm (with [provenance attestation](https://docs.npmjs.com/generating-provenance-statements)), and creates a GitHub Release with auto-generated notes.
|
|
432
|
+
|
|
433
|
+
### Option B — manual via GitHub UI
|
|
434
|
+
|
|
435
|
+
Trigger the **Release** workflow from the Actions tab with a bump (`patch`/`minor`/`major`) or an explicit version like `1.2.3`. The workflow performs the bump, commit, tag, and push, then publishes.
|
|
436
|
+
|
|
437
|
+
### Prerequisites
|
|
438
|
+
|
|
439
|
+
1. **`NPM_TOKEN`** secret on the repo (Settings → Secrets and variables → Actions). Create an [automation token](https://docs.npmjs.com/creating-and-viewing-access-tokens) on npmjs.com that allows publish.
|
|
440
|
+
2. The package name in `package.json` must be available on npm (or use a scoped name like `@your-org/web-to-print`). Provenance requires the workflow to run on a public repo, so make sure the repo is public when publishing.
|
|
441
|
+
3. The workflow skips publish if the same `name@version` already exists on npm — no need to manually guard against accidental re-runs.
|
|
442
|
+
|
|
443
|
+
## Project Structure
|
|
444
|
+
|
|
445
|
+
```
|
|
446
|
+
src/
|
|
447
|
+
components/
|
|
448
|
+
wtp-editor/ Interactive canvas editor
|
|
449
|
+
wtp-logo-renderer/ Static logo-on-product renderer (HTML/img-based)
|
|
450
|
+
wtp-logo-upload/ Logo upload with validation
|
|
451
|
+
wtp-print-area-editor/ Interactive print-area definition tool (4-corner quad + bulge)
|
|
452
|
+
styles/
|
|
453
|
+
_variables.scss Design tokens (colors and font-family exposed as CSS vars)
|
|
454
|
+
_mixins.scss SCSS mixins
|
|
455
|
+
_reset.scss CSS reset
|
|
456
|
+
types/
|
|
457
|
+
logo.ts Logo-related interfaces
|
|
458
|
+
editor.ts Editor/canvas interfaces
|
|
459
|
+
labels.ts User-facing string interfaces and English defaults
|
|
460
|
+
index.ts Re-exports
|
|
461
|
+
utils/
|
|
462
|
+
background-removal.ts Color-based flood-fill background removal
|
|
463
|
+
canvas-helpers.ts Fabric.js canvas utilities + CORS-safe image loader
|
|
464
|
+
format-detection.ts Magic-byte file format detection
|
|
465
|
+
logo-validation.ts DPI, dimension, and format validation
|
|
466
|
+
image-preview.ts Downscaled preview generation
|
|
467
|
+
html-render-helpers.ts <img>-based layout/export helpers for the renderer
|
|
468
|
+
pdf-export.ts Multi-page PDF export with print-area metadata
|
|
469
|
+
index.ts Public API exports
|
|
470
|
+
index.html Dev server demo page
|
|
471
|
+
scripts/
|
|
472
|
+
image-proxy.mjs Local dev-only CORS proxy for cross-origin product images
|
|
473
|
+
stencil.config.ts Stencil build configuration
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
> The dev script (`npm start`) automatically launches `scripts/image-proxy.mjs` on port 3001. The canvas helper tries direct CORS first, then this proxy as a fallback, before loading the image tainted (which would block export).
|
|
477
|
+
|
|
478
|
+
## Key Dependencies
|
|
479
|
+
|
|
480
|
+
| Package | Purpose |
|
|
481
|
+
|---|---|
|
|
482
|
+
| [Fabric.js](https://fabricjs.com/) v7 | Canvas rendering, object manipulation, JSON serialization |
|
|
483
|
+
| [ExifReader](https://github.com/nicolo-ribaudo/exifreader) | DPI and metadata extraction from raster images |
|
|
484
|
+
| — | Background removal uses a built-in color-based flood-fill (zero dependencies) |
|
|
485
|
+
| [@stencil/core](https://stenciljs.com/) v4 | Web component compiler |
|
|
486
|
+
| [@stencil/sass](https://github.com/ionic-team/stencil-sass) | SCSS support |
|
|
487
|
+
|
|
488
|
+
## License
|
|
489
|
+
|
|
490
|
+
MIT
|