@netlib/widerrufsbutton 1.1.2 → 2.1.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/README.md +4 -4
- package/dist/fallback.cjs.js +389 -0
- package/dist/fallback.d.ts +21 -4
- package/dist/fallback.es.js +412 -0
- package/dist/index.cjs.js +133 -71
- package/dist/index.d.ts +1 -1
- package/dist/index.es.js +325 -228
- package/dist/styles.d.ts +1 -1
- package/dist/types.d.ts +10 -5
- package/dist/widerruf.html +27 -33
- package/dist/widerrufsbutton.iife.js +17 -9
- package/package.json +8 -3
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
const o = `
|
|
2
|
+
/* Widerrufsbutton widget — prefix: wrb- */
|
|
3
|
+
.wrb-btn {
|
|
4
|
+
display: inline-flex;
|
|
5
|
+
align-items: center;
|
|
6
|
+
gap: 6px;
|
|
7
|
+
padding: 10px 20px;
|
|
8
|
+
background: #c0392b;
|
|
9
|
+
color: #fff;
|
|
10
|
+
border: none;
|
|
11
|
+
border-radius: 6px;
|
|
12
|
+
font-size: 15px;
|
|
13
|
+
font-weight: 600;
|
|
14
|
+
cursor: pointer;
|
|
15
|
+
font-family: inherit;
|
|
16
|
+
transition: background 0.2s;
|
|
17
|
+
text-decoration: none;
|
|
18
|
+
}
|
|
19
|
+
.wrb-btn:hover { background: #a93226; }
|
|
20
|
+
.wrb-btn:focus-visible { outline: 3px solid #e74c3c; outline-offset: 2px; }
|
|
21
|
+
|
|
22
|
+
/* Overlay */
|
|
23
|
+
.wrb-overlay {
|
|
24
|
+
position: fixed;
|
|
25
|
+
inset: 0;
|
|
26
|
+
background: rgba(0,0,0,0.55);
|
|
27
|
+
display: flex;
|
|
28
|
+
align-items: center;
|
|
29
|
+
justify-content: center;
|
|
30
|
+
z-index: 99999;
|
|
31
|
+
padding: 16px;
|
|
32
|
+
animation: wrb-fade-in 0.15s ease;
|
|
33
|
+
}
|
|
34
|
+
@keyframes wrb-fade-in { from { opacity: 0 } to { opacity: 1 } }
|
|
35
|
+
|
|
36
|
+
/* Modal box */
|
|
37
|
+
.wrb-modal {
|
|
38
|
+
background: #fff;
|
|
39
|
+
border-radius: 10px;
|
|
40
|
+
box-shadow: 0 20px 60px rgba(0,0,0,0.3);
|
|
41
|
+
width: 100%;
|
|
42
|
+
max-width: 540px;
|
|
43
|
+
max-height: 90vh;
|
|
44
|
+
overflow-y: auto;
|
|
45
|
+
animation: wrb-slide-up 0.2s ease;
|
|
46
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
47
|
+
font-size: 15px;
|
|
48
|
+
color: #1a1a1a;
|
|
49
|
+
}
|
|
50
|
+
@keyframes wrb-slide-up { from { transform: translateY(20px); opacity: 0 } to { transform: none; opacity: 1 } }
|
|
51
|
+
|
|
52
|
+
.wrb-modal-header {
|
|
53
|
+
display: flex;
|
|
54
|
+
align-items: flex-start;
|
|
55
|
+
justify-content: space-between;
|
|
56
|
+
padding: 20px 24px 16px;
|
|
57
|
+
border-bottom: 1px solid #e5e7eb;
|
|
58
|
+
gap: 12px;
|
|
59
|
+
}
|
|
60
|
+
.wrb-modal-title {
|
|
61
|
+
margin: 0;
|
|
62
|
+
font-size: 18px;
|
|
63
|
+
font-weight: 700;
|
|
64
|
+
color: #111;
|
|
65
|
+
line-height: 1.3;
|
|
66
|
+
}
|
|
67
|
+
.wrb-close-btn {
|
|
68
|
+
background: none;
|
|
69
|
+
border: none;
|
|
70
|
+
cursor: pointer;
|
|
71
|
+
color: #6b7280;
|
|
72
|
+
padding: 4px;
|
|
73
|
+
border-radius: 4px;
|
|
74
|
+
font-size: 20px;
|
|
75
|
+
line-height: 1;
|
|
76
|
+
flex-shrink: 0;
|
|
77
|
+
}
|
|
78
|
+
.wrb-close-btn:hover { color: #111; background: #f3f4f6; }
|
|
79
|
+
|
|
80
|
+
.wrb-modal-body {
|
|
81
|
+
padding: 20px 24px 24px;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.wrb-intro {
|
|
85
|
+
margin: 0 0 20px;
|
|
86
|
+
color: #4b5563;
|
|
87
|
+
line-height: 1.6;
|
|
88
|
+
font-size: 14px;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/* Form */
|
|
92
|
+
.wrb-field {
|
|
93
|
+
margin-bottom: 16px;
|
|
94
|
+
}
|
|
95
|
+
.wrb-label {
|
|
96
|
+
display: block;
|
|
97
|
+
font-size: 13px;
|
|
98
|
+
font-weight: 600;
|
|
99
|
+
color: #374151;
|
|
100
|
+
margin-bottom: 5px;
|
|
101
|
+
}
|
|
102
|
+
.wrb-required {
|
|
103
|
+
color: #c0392b;
|
|
104
|
+
margin-left: 2px;
|
|
105
|
+
}
|
|
106
|
+
.wrb-input,
|
|
107
|
+
.wrb-textarea {
|
|
108
|
+
width: 100%;
|
|
109
|
+
padding: 9px 12px;
|
|
110
|
+
border: 1.5px solid #d1d5db;
|
|
111
|
+
border-radius: 6px;
|
|
112
|
+
font-size: 15px;
|
|
113
|
+
font-family: inherit;
|
|
114
|
+
color: #111;
|
|
115
|
+
background: #fff;
|
|
116
|
+
box-sizing: border-box;
|
|
117
|
+
transition: border-color 0.15s;
|
|
118
|
+
}
|
|
119
|
+
.wrb-input:focus,
|
|
120
|
+
.wrb-textarea:focus {
|
|
121
|
+
outline: none;
|
|
122
|
+
border-color: #c0392b;
|
|
123
|
+
box-shadow: 0 0 0 3px rgba(192,57,43,0.12);
|
|
124
|
+
}
|
|
125
|
+
.wrb-input.wrb-error,
|
|
126
|
+
.wrb-textarea.wrb-error {
|
|
127
|
+
border-color: #c0392b;
|
|
128
|
+
}
|
|
129
|
+
.wrb-field-error {
|
|
130
|
+
color: #c0392b;
|
|
131
|
+
font-size: 12px;
|
|
132
|
+
margin-top: 4px;
|
|
133
|
+
}
|
|
134
|
+
.wrb-textarea { resize: vertical; min-height: 80px; }
|
|
135
|
+
|
|
136
|
+
.wrb-hint {
|
|
137
|
+
font-size: 12px;
|
|
138
|
+
color: #6b7280;
|
|
139
|
+
margin-top: 4px;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.wrb-date-display {
|
|
143
|
+
padding: 9px 12px;
|
|
144
|
+
background: #f9fafb;
|
|
145
|
+
border: 1.5px solid #e5e7eb;
|
|
146
|
+
border-radius: 6px;
|
|
147
|
+
color: #6b7280;
|
|
148
|
+
font-size: 15px;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/* Actions */
|
|
152
|
+
.wrb-actions {
|
|
153
|
+
display: flex;
|
|
154
|
+
gap: 10px;
|
|
155
|
+
justify-content: flex-end;
|
|
156
|
+
margin-top: 24px;
|
|
157
|
+
padding-top: 16px;
|
|
158
|
+
border-top: 1px solid #e5e7eb;
|
|
159
|
+
}
|
|
160
|
+
.wrb-submit-btn {
|
|
161
|
+
display: inline-flex;
|
|
162
|
+
align-items: center;
|
|
163
|
+
justify-content: center;
|
|
164
|
+
text-decoration: none;
|
|
165
|
+
padding: 10px 22px;
|
|
166
|
+
background: #c0392b;
|
|
167
|
+
color: #fff;
|
|
168
|
+
border: none;
|
|
169
|
+
border-radius: 6px;
|
|
170
|
+
font-size: 15px;
|
|
171
|
+
font-weight: 600;
|
|
172
|
+
cursor: pointer;
|
|
173
|
+
font-family: inherit;
|
|
174
|
+
transition: background 0.2s;
|
|
175
|
+
}
|
|
176
|
+
.wrb-submit-btn:hover:not(:disabled) { background: #a93226; }
|
|
177
|
+
.wrb-submit-btn:disabled { opacity: 0.6; cursor: not-allowed; }
|
|
178
|
+
.wrb-cancel-btn {
|
|
179
|
+
display: inline-flex;
|
|
180
|
+
align-items: center;
|
|
181
|
+
justify-content: center;
|
|
182
|
+
text-decoration: none;
|
|
183
|
+
padding: 10px 18px;
|
|
184
|
+
background: transparent;
|
|
185
|
+
color: #374151;
|
|
186
|
+
border: 1.5px solid #d1d5db;
|
|
187
|
+
border-radius: 6px;
|
|
188
|
+
font-size: 15px;
|
|
189
|
+
cursor: pointer;
|
|
190
|
+
font-family: inherit;
|
|
191
|
+
transition: background 0.15s;
|
|
192
|
+
}
|
|
193
|
+
.wrb-cancel-btn:hover { background: #f3f4f6; }
|
|
194
|
+
|
|
195
|
+
/* Success / Error states */
|
|
196
|
+
.wrb-success {
|
|
197
|
+
text-align: center;
|
|
198
|
+
padding: 32px 24px;
|
|
199
|
+
}
|
|
200
|
+
.wrb-success-icon { font-size: 48px; display: block; margin-bottom: 12px; }
|
|
201
|
+
.wrb-success h3 { margin: 0 0 8px; font-size: 20px; color: #111; }
|
|
202
|
+
.wrb-success p { margin: 0; color: #4b5563; line-height: 1.6; }
|
|
203
|
+
|
|
204
|
+
.wrb-alert {
|
|
205
|
+
padding: 12px 16px;
|
|
206
|
+
border-radius: 6px;
|
|
207
|
+
margin-bottom: 16px;
|
|
208
|
+
font-size: 14px;
|
|
209
|
+
}
|
|
210
|
+
.wrb-alert-error { background: #fef2f2; border: 1px solid #fecaca; color: #991b1b; }
|
|
211
|
+
|
|
212
|
+
/* Legal links */
|
|
213
|
+
.wrb-legal-links {
|
|
214
|
+
display: flex;
|
|
215
|
+
flex-wrap: wrap;
|
|
216
|
+
gap: 4px 16px;
|
|
217
|
+
margin-top: 16px;
|
|
218
|
+
padding-top: 12px;
|
|
219
|
+
border-top: 1px solid #e5e7eb;
|
|
220
|
+
}
|
|
221
|
+
.wrb-legal-link {
|
|
222
|
+
font-size: 12px;
|
|
223
|
+
color: #6b7280;
|
|
224
|
+
text-decoration: none;
|
|
225
|
+
}
|
|
226
|
+
.wrb-legal-link:hover {
|
|
227
|
+
color: #374151;
|
|
228
|
+
text-decoration: underline;
|
|
229
|
+
}
|
|
230
|
+
`;
|
|
231
|
+
function r(e) {
|
|
232
|
+
return e.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
233
|
+
}
|
|
234
|
+
function n(e) {
|
|
235
|
+
var a;
|
|
236
|
+
return (a = e.legalLinks) != null && a.length ? `
|
|
237
|
+
<div class="wrb-legal-links">
|
|
238
|
+
${e.legalLinks.map((t) => `<a href="${r(t.href)}" class="wrb-legal-link" rel="noopener noreferrer">${r(t.name)}</a>`).join(`
|
|
239
|
+
`)}
|
|
240
|
+
</div>` : "";
|
|
241
|
+
}
|
|
242
|
+
function s(e, a = "", t = "") {
|
|
243
|
+
const l = r(e.successUrl ?? a), i = r(e.errorUrl ?? t);
|
|
244
|
+
return `
|
|
245
|
+
<div class="wrb-field">
|
|
246
|
+
<label class="wrb-label">
|
|
247
|
+
Vorname <span class="wrb-required" aria-hidden="true">*</span>
|
|
248
|
+
</label>
|
|
249
|
+
<input class="wrb-input" type="text" name="firstName" autocomplete="given-name"
|
|
250
|
+
placeholder="Max" required>
|
|
251
|
+
</div>
|
|
252
|
+
<div class="wrb-field">
|
|
253
|
+
<label class="wrb-label">
|
|
254
|
+
Nachname <span class="wrb-required" aria-hidden="true">*</span>
|
|
255
|
+
</label>
|
|
256
|
+
<input class="wrb-input" type="text" name="lastName" autocomplete="family-name"
|
|
257
|
+
placeholder="Mustermann" required>
|
|
258
|
+
</div>
|
|
259
|
+
<div class="wrb-field">
|
|
260
|
+
<label class="wrb-label">
|
|
261
|
+
E-Mail-Adresse <span class="wrb-required" aria-hidden="true">*</span>
|
|
262
|
+
</label>
|
|
263
|
+
<input class="wrb-input" type="email" name="email" autocomplete="email"
|
|
264
|
+
placeholder="name@beispiel.de" required>
|
|
265
|
+
<p class="wrb-hint">Hierüber erhalten Sie die Eingangsbestätigung.</p>
|
|
266
|
+
</div>
|
|
267
|
+
<div class="wrb-field">
|
|
268
|
+
<label class="wrb-label">
|
|
269
|
+
Bestell- / Auftrags- / Vertragsnummer
|
|
270
|
+
<span class="wrb-required" aria-hidden="true">*</span>
|
|
271
|
+
</label>
|
|
272
|
+
<input class="wrb-input" type="text" name="orderNumber"
|
|
273
|
+
placeholder="z.B. 10045678" required>
|
|
274
|
+
<p class="wrb-hint">Zu finden in Ihrer Bestellbestätigung.</p>
|
|
275
|
+
</div>
|
|
276
|
+
<div class="wrb-field">
|
|
277
|
+
<label class="wrb-label">Widerrufsgrund</label>
|
|
278
|
+
<textarea class="wrb-textarea" name="reason" placeholder="Optional" rows="2"></textarea>
|
|
279
|
+
<p class="wrb-hint">
|
|
280
|
+
Freiwillige Angabe – ein Widerruf ist ohne Angabe von Gründen möglich.
|
|
281
|
+
</p>
|
|
282
|
+
</div>
|
|
283
|
+
<div class="wrb-field">
|
|
284
|
+
<label class="wrb-label">Nachricht</label>
|
|
285
|
+
<textarea class="wrb-textarea" name="userMessage" placeholder="Optional" rows="3"></textarea>
|
|
286
|
+
</div>
|
|
287
|
+
<input type="hidden" name="action" value="${r(e.action)}">
|
|
288
|
+
${l ? `<input type="hidden" name="successUrl" value="${l}">` : ""}
|
|
289
|
+
${i ? `<input type="hidden" name="errorUrl" value="${i}">` : ""}`;
|
|
290
|
+
}
|
|
291
|
+
function b(e) {
|
|
292
|
+
const a = e.companyName ? `Widerruf – ${r(e.companyName)}` : "Widerrufsformular", t = r(e.formAction ?? e.apiUrl ?? "/rest/v1/apiCancellation");
|
|
293
|
+
return `<!DOCTYPE html>
|
|
294
|
+
<html lang="de">
|
|
295
|
+
<head>
|
|
296
|
+
<meta charset="UTF-8">
|
|
297
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
298
|
+
<title>${a}</title>
|
|
299
|
+
<style>
|
|
300
|
+
*, *::before, *::after { box-sizing: border-box; }
|
|
301
|
+
body { margin: 0; background: #f9fafb; }
|
|
302
|
+
.wrb-page {
|
|
303
|
+
min-height: 100vh;
|
|
304
|
+
display: flex;
|
|
305
|
+
align-items: flex-start;
|
|
306
|
+
justify-content: center;
|
|
307
|
+
padding: 40px 16px;
|
|
308
|
+
}
|
|
309
|
+
.wrb-page .wrb-modal { max-height: none; }
|
|
310
|
+
.wrb-page .wrb-modal-title { font-size: 20px; }
|
|
311
|
+
${o}
|
|
312
|
+
</style>
|
|
313
|
+
</head>
|
|
314
|
+
<body>
|
|
315
|
+
<div class="wrb-page">
|
|
316
|
+
<div class="wrb-modal">
|
|
317
|
+
<div class="wrb-modal-header">
|
|
318
|
+
<h1 class="wrb-modal-title">${a}</h1>
|
|
319
|
+
</div>
|
|
320
|
+
<div class="wrb-modal-body">
|
|
321
|
+
${e.introText ? `<p class="wrb-intro">${r(e.introText)}</p>` : ""}
|
|
322
|
+
<form method="POST" action="${t}" novalidate>
|
|
323
|
+
${s(e)}
|
|
324
|
+
<div class="wrb-actions">
|
|
325
|
+
<button type="submit" class="wrb-submit-btn">
|
|
326
|
+
${r(e.submitLabel ?? "Absenden")}
|
|
327
|
+
</button>
|
|
328
|
+
</div>
|
|
329
|
+
</form>
|
|
330
|
+
${n(e)}
|
|
331
|
+
</div>
|
|
332
|
+
</div>
|
|
333
|
+
</div>
|
|
334
|
+
</body>
|
|
335
|
+
</html>`;
|
|
336
|
+
}
|
|
337
|
+
function c(e, { inlineStyles: a = !0 } = {}) {
|
|
338
|
+
const t = e.companyName ? `Widerruf – ${r(e.companyName)}` : "Widerrufsformular", l = r(e.formAction ?? e.apiUrl ?? "/rest/v1/apiCancellation"), i = `
|
|
339
|
+
#wrb-modal, #wrb-success, #wrb-error { display: none; }
|
|
340
|
+
#wrb-modal:target, #wrb-success:target, #wrb-error:target { display: flex; }`;
|
|
341
|
+
return `${a ? `<style>${i}
|
|
342
|
+
${o}</style>` : `<style>${i}</style>`}
|
|
343
|
+
|
|
344
|
+
<!-- Widerruf: Form-Modal -->
|
|
345
|
+
<div id="wrb-modal" class="wrb-overlay" role="dialog" aria-modal="true" aria-labelledby="wrb-modal-title">
|
|
346
|
+
<div class="wrb-modal">
|
|
347
|
+
<div class="wrb-modal-header">
|
|
348
|
+
<h2 class="wrb-modal-title" id="wrb-modal-title">${t}</h2>
|
|
349
|
+
<a href="#" class="wrb-close-btn" aria-label="Schließen">✕</a>
|
|
350
|
+
</div>
|
|
351
|
+
<div class="wrb-modal-body">
|
|
352
|
+
${e.introText ? `<p class="wrb-intro">${r(e.introText)}</p>` : ""}
|
|
353
|
+
<form method="POST" action="${l}" novalidate>
|
|
354
|
+
${s(e, "#wrb-success", "#wrb-error")}
|
|
355
|
+
<div class="wrb-actions">
|
|
356
|
+
<a href="#" class="wrb-cancel-btn">${r(e.cancelLabel ?? "Abbrechen")}</a>
|
|
357
|
+
<button type="submit" class="wrb-submit-btn">
|
|
358
|
+
${r(e.submitLabel ?? "Absenden")}
|
|
359
|
+
</button>
|
|
360
|
+
</div>
|
|
361
|
+
</form>
|
|
362
|
+
${n(e)}
|
|
363
|
+
</div>
|
|
364
|
+
</div>
|
|
365
|
+
</div>
|
|
366
|
+
|
|
367
|
+
<!-- Widerruf: Success-Modal -->
|
|
368
|
+
<div id="wrb-success" class="wrb-overlay" role="dialog" aria-modal="true">
|
|
369
|
+
<div class="wrb-modal">
|
|
370
|
+
<div class="wrb-modal-header">
|
|
371
|
+
<h2 class="wrb-modal-title">Widerruf eingegangen</h2>
|
|
372
|
+
<a href="#" class="wrb-close-btn" aria-label="Schließen">✕</a>
|
|
373
|
+
</div>
|
|
374
|
+
<div class="wrb-modal-body">
|
|
375
|
+
<div class="wrb-success">
|
|
376
|
+
<span class="wrb-success-icon">✓</span>
|
|
377
|
+
<h3>Widerruf eingegangen</h3>
|
|
378
|
+
<p>
|
|
379
|
+
Ihr Widerruf wurde erfolgreich übermittelt. Sie erhalten in Kürze eine
|
|
380
|
+
Bestätigung per E-Mail.
|
|
381
|
+
</p>
|
|
382
|
+
</div>
|
|
383
|
+
${n(e)}
|
|
384
|
+
</div>
|
|
385
|
+
</div>
|
|
386
|
+
</div>
|
|
387
|
+
|
|
388
|
+
<!-- Widerruf: Error-Modal -->
|
|
389
|
+
<div id="wrb-error" class="wrb-overlay" role="alertdialog" aria-modal="true">
|
|
390
|
+
<div class="wrb-modal">
|
|
391
|
+
<div class="wrb-modal-header">
|
|
392
|
+
<h2 class="wrb-modal-title">Fehler beim Senden</h2>
|
|
393
|
+
<a href="#" class="wrb-close-btn" aria-label="Schließen">✕</a>
|
|
394
|
+
</div>
|
|
395
|
+
<div class="wrb-modal-body">
|
|
396
|
+
<div class="wrb-alert wrb-alert-error" role="alert">
|
|
397
|
+
Ihr Widerruf konnte leider nicht übermittelt werden. Bitte versuchen Sie es
|
|
398
|
+
erneut oder kontaktieren Sie uns direkt.
|
|
399
|
+
</div>
|
|
400
|
+
<div class="wrb-actions">
|
|
401
|
+
<a href="#" class="wrb-cancel-btn">Schließen</a>
|
|
402
|
+
<a href="#wrb-modal" class="wrb-submit-btn">Erneut versuchen</a>
|
|
403
|
+
</div>
|
|
404
|
+
${n(e)}
|
|
405
|
+
</div>
|
|
406
|
+
</div>
|
|
407
|
+
</div>`;
|
|
408
|
+
}
|
|
409
|
+
export {
|
|
410
|
+
b as generateFallbackHtml,
|
|
411
|
+
c as generateModalHtml
|
|
412
|
+
};
|