@wix/ditto-codegen-public 1.0.171 → 1.0.173
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/examples-apps/custom-element/src/widgets/custom-elements/countdown-timer/widget.tsx
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { items } from '@wix/data';
|
|
2
|
+
import { window as wixWindow } from '@wix/site-window';
|
|
3
|
+
|
|
4
|
+
interface CountdownConfig {
|
|
5
|
+
_id: string;
|
|
6
|
+
targetDate: Date;
|
|
7
|
+
title?: string;
|
|
5
8
|
isActive: boolean;
|
|
6
|
-
description?: string;
|
|
7
9
|
}
|
|
8
10
|
|
|
9
11
|
interface TimeRemaining {
|
|
@@ -15,41 +17,65 @@ interface TimeRemaining {
|
|
|
15
17
|
|
|
16
18
|
export default class extends HTMLElement {
|
|
17
19
|
private intervalId: number | null = null;
|
|
18
|
-
private
|
|
20
|
+
private config: CountdownConfig | null = null;
|
|
21
|
+
private isEditorMode = false;
|
|
19
22
|
|
|
20
|
-
public connectedCallback(): void {
|
|
21
|
-
this.
|
|
23
|
+
public async connectedCallback(): Promise<void> {
|
|
24
|
+
await this.checkEnvironment();
|
|
25
|
+
if (this.isEditorMode) {
|
|
26
|
+
this.renderEditorPlaceholder();
|
|
27
|
+
} else {
|
|
28
|
+
await this.loadConfig();
|
|
29
|
+
}
|
|
22
30
|
}
|
|
23
31
|
|
|
24
32
|
public disconnectedCallback(): void {
|
|
25
33
|
if (this.intervalId !== null) {
|
|
26
34
|
clearInterval(this.intervalId);
|
|
35
|
+
this.intervalId = null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private async checkEnvironment(): Promise<void> {
|
|
40
|
+
try {
|
|
41
|
+
const currentViewMode = await wixWindow.viewMode();
|
|
42
|
+
this.isEditorMode = currentViewMode === 'Editor';
|
|
43
|
+
} catch (error) {
|
|
44
|
+
console.error('Failed to check view mode:', error);
|
|
45
|
+
this.isEditorMode = false;
|
|
27
46
|
}
|
|
28
47
|
}
|
|
29
48
|
|
|
30
|
-
private async
|
|
49
|
+
private async loadConfig(): Promise<void> {
|
|
31
50
|
try {
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
51
|
+
const result = await items.query('countdown-config')
|
|
52
|
+
.eq('isActive', true)
|
|
53
|
+
.limit(1)
|
|
54
|
+
.find();
|
|
55
|
+
|
|
56
|
+
if (result.items.length > 0) {
|
|
57
|
+
const item = result.items[0];
|
|
58
|
+
this.config = {
|
|
59
|
+
_id: item._id as string,
|
|
60
|
+
targetDate: new Date(item.targetDate as string),
|
|
61
|
+
title: item.title as string | undefined,
|
|
62
|
+
isActive: item.isActive as boolean
|
|
63
|
+
};
|
|
64
|
+
this.render();
|
|
65
|
+
this.startCountdown();
|
|
66
|
+
} else {
|
|
67
|
+
this.renderNoConfig();
|
|
68
|
+
}
|
|
43
69
|
} catch (error) {
|
|
44
|
-
console.error('Failed to load
|
|
70
|
+
console.error('Failed to load countdown config:', error);
|
|
45
71
|
this.renderError();
|
|
46
72
|
}
|
|
47
73
|
}
|
|
48
74
|
|
|
49
|
-
private calculateTimeRemaining(
|
|
75
|
+
private calculateTimeRemaining(targetDate: Date): TimeRemaining | null {
|
|
50
76
|
const now = new Date().getTime();
|
|
51
|
-
const
|
|
52
|
-
const difference =
|
|
77
|
+
const target = targetDate.getTime();
|
|
78
|
+
const difference = target - now;
|
|
53
79
|
|
|
54
80
|
if (difference <= 0) {
|
|
55
81
|
return null;
|
|
@@ -64,7 +90,7 @@ export default class extends HTMLElement {
|
|
|
64
90
|
}
|
|
65
91
|
|
|
66
92
|
private startCountdown(): void {
|
|
67
|
-
if (!this.
|
|
93
|
+
if (!this.config || !this.config.isActive) {
|
|
68
94
|
return;
|
|
69
95
|
}
|
|
70
96
|
|
|
@@ -74,12 +100,12 @@ export default class extends HTMLElement {
|
|
|
74
100
|
}
|
|
75
101
|
|
|
76
102
|
private updateCountdown(): void {
|
|
77
|
-
if (!this.
|
|
103
|
+
if (!this.config) {
|
|
78
104
|
return;
|
|
79
105
|
}
|
|
80
106
|
|
|
81
|
-
const timeRemaining = this.calculateTimeRemaining(this.
|
|
82
|
-
|
|
107
|
+
const timeRemaining = this.calculateTimeRemaining(this.config.targetDate);
|
|
108
|
+
|
|
83
109
|
if (timeRemaining === null) {
|
|
84
110
|
this.renderExpired();
|
|
85
111
|
if (this.intervalId !== null) {
|
|
@@ -93,12 +119,12 @@ export default class extends HTMLElement {
|
|
|
93
119
|
}
|
|
94
120
|
|
|
95
121
|
private render(): void {
|
|
96
|
-
if (!this.
|
|
122
|
+
if (!this.config) {
|
|
97
123
|
return;
|
|
98
124
|
}
|
|
99
125
|
|
|
100
|
-
const timeRemaining = this.calculateTimeRemaining(this.
|
|
101
|
-
|
|
126
|
+
const timeRemaining = this.calculateTimeRemaining(this.config.targetDate);
|
|
127
|
+
|
|
102
128
|
if (timeRemaining === null) {
|
|
103
129
|
this.renderExpired();
|
|
104
130
|
} else {
|
|
@@ -106,220 +132,355 @@ export default class extends HTMLElement {
|
|
|
106
132
|
}
|
|
107
133
|
}
|
|
108
134
|
|
|
109
|
-
private
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
135
|
+
private getStyles(): string {
|
|
136
|
+
return `
|
|
137
|
+
<style>
|
|
138
|
+
/* Editor Placeholder Styles */
|
|
139
|
+
.editor-container {
|
|
140
|
+
font-family: 'Courier New', monospace;
|
|
141
|
+
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
|
|
142
|
+
color: #00ff88;
|
|
143
|
+
padding: 48px 24px;
|
|
144
|
+
border-radius: 16px;
|
|
145
|
+
text-align: center;
|
|
146
|
+
box-shadow: 0 8px 32px rgba(0, 255, 136, 0.2);
|
|
147
|
+
max-width: 600px;
|
|
148
|
+
margin: 0 auto;
|
|
149
|
+
border: 2px solid #00ff88;
|
|
150
|
+
}
|
|
125
151
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
`;
|
|
152
|
+
.editor-icon {
|
|
153
|
+
font-size: 64px;
|
|
154
|
+
margin-bottom: 16px;
|
|
155
|
+
animation: pulse 2s ease-in-out infinite;
|
|
156
|
+
}
|
|
132
157
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
158
|
+
.editor-title {
|
|
159
|
+
font-size: 28px;
|
|
160
|
+
font-weight: 700;
|
|
161
|
+
margin: 0 0 12px 0;
|
|
162
|
+
text-shadow: 0 0 10px rgba(0, 255, 136, 0.5);
|
|
163
|
+
letter-spacing: 2px;
|
|
164
|
+
}
|
|
139
165
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
166
|
+
.editor-message {
|
|
167
|
+
font-size: 16px;
|
|
168
|
+
opacity: 0.85;
|
|
169
|
+
margin: 0;
|
|
170
|
+
line-height: 1.6;
|
|
171
|
+
}
|
|
146
172
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
173
|
+
/* Countdown Timer Styles */
|
|
174
|
+
.timer-container {
|
|
175
|
+
font-family: 'Orbitron', 'Rajdhani', 'Exo 2', monospace, sans-serif;
|
|
176
|
+
background: linear-gradient(135deg, #0f2027 0%, #203a43 50%, #2c5364 100%);
|
|
177
|
+
color: #00d9ff;
|
|
178
|
+
padding: 40px 24px;
|
|
179
|
+
border-radius: 20px;
|
|
180
|
+
text-align: center;
|
|
181
|
+
box-shadow: 0 20px 60px rgba(0, 217, 255, 0.3), inset 0 0 40px rgba(0, 217, 255, 0.1);
|
|
182
|
+
max-width: 700px;
|
|
183
|
+
margin: 0 auto;
|
|
184
|
+
position: relative;
|
|
185
|
+
overflow: hidden;
|
|
186
|
+
}
|
|
153
187
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
188
|
+
.timer-glow {
|
|
189
|
+
content: '';
|
|
190
|
+
position: absolute;
|
|
191
|
+
top: -50%;
|
|
192
|
+
left: -50%;
|
|
193
|
+
width: 200%;
|
|
194
|
+
height: 200%;
|
|
195
|
+
background: radial-gradient(circle, rgba(0, 217, 255, 0.1) 0%, transparent 70%);
|
|
196
|
+
animation: rotate 10s linear infinite;
|
|
197
|
+
}
|
|
160
198
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
199
|
+
.timer-title {
|
|
200
|
+
font-size: 32px;
|
|
201
|
+
font-weight: 900;
|
|
202
|
+
margin: 0 0 12px 0;
|
|
203
|
+
text-shadow: 0 0 20px rgba(0, 217, 255, 0.8), 0 0 40px rgba(0, 217, 255, 0.4);
|
|
204
|
+
letter-spacing: 3px;
|
|
205
|
+
text-transform: uppercase;
|
|
206
|
+
position: relative;
|
|
207
|
+
z-index: 1;
|
|
208
|
+
}
|
|
168
209
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
cursor: pointer;
|
|
178
|
-
transition: all 0.3s ease;
|
|
179
|
-
text-decoration: none;
|
|
180
|
-
display: inline-block;
|
|
181
|
-
margin-top: 16px;
|
|
182
|
-
backdrop-filter: blur(10px);
|
|
183
|
-
`;
|
|
210
|
+
.timer-grid {
|
|
211
|
+
display: grid;
|
|
212
|
+
grid-template-columns: repeat(4, 1fr);
|
|
213
|
+
gap: 20px;
|
|
214
|
+
margin: 32px 0;
|
|
215
|
+
position: relative;
|
|
216
|
+
z-index: 1;
|
|
217
|
+
}
|
|
184
218
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
219
|
+
.time-unit {
|
|
220
|
+
background: rgba(0, 217, 255, 0.15);
|
|
221
|
+
border-radius: 12px;
|
|
222
|
+
padding: 24px 12px;
|
|
223
|
+
backdrop-filter: blur(10px);
|
|
224
|
+
border: 2px solid rgba(0, 217, 255, 0.3);
|
|
225
|
+
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3), inset 0 0 20px rgba(0, 217, 255, 0.1);
|
|
226
|
+
transition: all 0.3s ease;
|
|
227
|
+
}
|
|
190
228
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
gap: 12px;
|
|
229
|
+
.time-unit:hover {
|
|
230
|
+
transform: translateY(-4px);
|
|
231
|
+
border-color: rgba(0, 217, 255, 0.6);
|
|
232
|
+
box-shadow: 0 12px 40px rgba(0, 217, 255, 0.4), inset 0 0 30px rgba(0, 217, 255, 0.2);
|
|
196
233
|
}
|
|
234
|
+
|
|
197
235
|
.time-number {
|
|
236
|
+
font-size: 48px;
|
|
237
|
+
font-weight: 900;
|
|
238
|
+
margin: 0;
|
|
239
|
+
text-shadow: 0 0 15px rgba(0, 217, 255, 0.8), 0 0 30px rgba(0, 217, 255, 0.4);
|
|
240
|
+
font-family: 'Orbitron', monospace;
|
|
241
|
+
letter-spacing: 2px;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.time-label {
|
|
245
|
+
font-size: 13px;
|
|
246
|
+
text-transform: uppercase;
|
|
247
|
+
letter-spacing: 2px;
|
|
248
|
+
margin: 8px 0 0 0;
|
|
249
|
+
opacity: 0.9;
|
|
250
|
+
font-weight: 700;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/* Expired State Styles */
|
|
254
|
+
.expired-container {
|
|
255
|
+
font-family: 'Bebas Neue', 'Anton', 'Oswald', sans-serif;
|
|
256
|
+
background: linear-gradient(135deg, #2d1b00 0%, #5c3a1f 50%, #8b4513 100%);
|
|
257
|
+
color: #ffa500;
|
|
258
|
+
padding: 48px 24px;
|
|
259
|
+
border-radius: 20px;
|
|
260
|
+
text-align: center;
|
|
261
|
+
box-shadow: 0 20px 60px rgba(255, 165, 0, 0.4), inset 0 0 40px rgba(255, 165, 0, 0.1);
|
|
262
|
+
max-width: 600px;
|
|
263
|
+
margin: 0 auto;
|
|
264
|
+
border: 3px solid #ffa500;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
.expired-icon {
|
|
268
|
+
font-size: 80px;
|
|
269
|
+
margin-bottom: 16px;
|
|
270
|
+
animation: bounce 1s ease-in-out infinite;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
.expired-title {
|
|
274
|
+
font-size: 48px;
|
|
275
|
+
font-weight: 900;
|
|
276
|
+
margin: 0 0 16px 0;
|
|
277
|
+
text-shadow: 0 0 20px rgba(255, 165, 0, 0.8), 0 4px 8px rgba(0, 0, 0, 0.5);
|
|
278
|
+
letter-spacing: 4px;
|
|
279
|
+
text-transform: uppercase;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
.expired-message {
|
|
283
|
+
font-size: 20px;
|
|
284
|
+
margin: 0;
|
|
285
|
+
opacity: 0.95;
|
|
286
|
+
font-weight: 600;
|
|
287
|
+
letter-spacing: 1px;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/* No Config State Styles */
|
|
291
|
+
.no-config-container {
|
|
292
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
293
|
+
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
|
|
294
|
+
color: #2c3e50;
|
|
295
|
+
padding: 40px 24px;
|
|
296
|
+
border-radius: 16px;
|
|
297
|
+
text-align: center;
|
|
298
|
+
border: 2px dashed #95a5a6;
|
|
299
|
+
max-width: 500px;
|
|
300
|
+
margin: 0 auto;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
.no-config-icon {
|
|
304
|
+
font-size: 64px;
|
|
305
|
+
margin-bottom: 16px;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
.no-config-title {
|
|
198
309
|
font-size: 24px;
|
|
310
|
+
font-weight: 700;
|
|
311
|
+
margin: 0 0 12px 0;
|
|
312
|
+
color: #34495e;
|
|
199
313
|
}
|
|
200
|
-
|
|
201
|
-
|
|
314
|
+
|
|
315
|
+
.no-config-message {
|
|
316
|
+
font-size: 16px;
|
|
317
|
+
margin: 0;
|
|
318
|
+
line-height: 1.6;
|
|
319
|
+
color: #7f8c8d;
|
|
202
320
|
}
|
|
203
|
-
}
|
|
204
|
-
`;
|
|
205
321
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
322
|
+
/* Error State Styles */
|
|
323
|
+
.error-container {
|
|
324
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
325
|
+
background: #fff5f5;
|
|
326
|
+
color: #c53030;
|
|
327
|
+
padding: 32px 24px;
|
|
328
|
+
border-radius: 12px;
|
|
329
|
+
text-align: center;
|
|
330
|
+
border: 2px solid #fc8181;
|
|
331
|
+
max-width: 500px;
|
|
332
|
+
margin: 0 auto;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
.error-icon {
|
|
336
|
+
font-size: 48px;
|
|
337
|
+
margin-bottom: 12px;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
.error-message {
|
|
341
|
+
margin: 0;
|
|
342
|
+
font-size: 16px;
|
|
343
|
+
font-weight: 600;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/* Animations */
|
|
347
|
+
@keyframes pulse {
|
|
348
|
+
0%, 100% {
|
|
349
|
+
opacity: 1;
|
|
350
|
+
transform: scale(1);
|
|
351
|
+
}
|
|
352
|
+
50% {
|
|
353
|
+
opacity: 0.6;
|
|
354
|
+
transform: scale(1.1);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
@keyframes rotate {
|
|
359
|
+
from {
|
|
360
|
+
transform: rotate(0deg);
|
|
361
|
+
}
|
|
362
|
+
to {
|
|
363
|
+
transform: rotate(360deg);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
@keyframes bounce {
|
|
368
|
+
0%, 100% {
|
|
369
|
+
transform: translateY(0);
|
|
370
|
+
}
|
|
371
|
+
50% {
|
|
372
|
+
transform: translateY(-20px);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/* Responsive Styles */
|
|
377
|
+
@media (max-width: 600px) {
|
|
378
|
+
.timer-grid {
|
|
379
|
+
grid-template-columns: repeat(2, 1fr);
|
|
380
|
+
gap: 16px;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
.time-number {
|
|
384
|
+
font-size: 36px;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
.timer-container {
|
|
388
|
+
padding: 24px 16px;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
.timer-title {
|
|
392
|
+
font-size: 24px;
|
|
393
|
+
}
|
|
211
394
|
}
|
|
212
395
|
</style>
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
<div style="${timeUnitStyle}">
|
|
227
|
-
<div class="time-number" style="${numberStyle}">${timeRemaining.minutes.toString().padStart(2, '0')}</div>
|
|
228
|
-
<div style="${labelStyle}">Minutes</div>
|
|
229
|
-
</div>
|
|
230
|
-
<div style="${timeUnitStyle}">
|
|
231
|
-
<div class="time-number" style="${numberStyle}">${timeRemaining.seconds.toString().padStart(2, '0')}</div>
|
|
232
|
-
<div style="${labelStyle}">Seconds</div>
|
|
233
|
-
</div>
|
|
234
|
-
</div>
|
|
235
|
-
|
|
236
|
-
${this.timerData.targetUrl ? `
|
|
237
|
-
<a href="${this.escapeHtml(this.timerData.targetUrl)}"
|
|
238
|
-
class="timer-button"
|
|
239
|
-
style="${buttonStyle}"
|
|
240
|
-
role="button"
|
|
241
|
-
aria-label="Take action before timer expires">
|
|
242
|
-
Don't Miss Out!
|
|
243
|
-
</a>
|
|
244
|
-
` : ''}
|
|
396
|
+
`;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
private renderEditorPlaceholder(): void {
|
|
400
|
+
this.innerHTML = `
|
|
401
|
+
${this.getStyles()}
|
|
402
|
+
<div class="editor-container" data-testid="countdown-timer-editor">
|
|
403
|
+
<div class="editor-icon">⏱️</div>
|
|
404
|
+
<h2 class="editor-title">COUNTDOWN TIMER</h2>
|
|
405
|
+
<p class="editor-message">
|
|
406
|
+
This widget will display a live countdown on your published site.<br>
|
|
407
|
+
Configure the target date in your dashboard to get started.
|
|
408
|
+
</p>
|
|
245
409
|
</div>
|
|
246
410
|
`;
|
|
247
411
|
}
|
|
248
412
|
|
|
249
|
-
private
|
|
250
|
-
if (!this.
|
|
413
|
+
private renderCountdown(timeRemaining: TimeRemaining): void {
|
|
414
|
+
if (!this.config) {
|
|
251
415
|
return;
|
|
252
416
|
}
|
|
253
417
|
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
418
|
+
const timeUnits = [
|
|
419
|
+
{ value: timeRemaining.days, label: 'Days' },
|
|
420
|
+
{ value: timeRemaining.hours, label: 'Hours' },
|
|
421
|
+
{ value: timeRemaining.minutes, label: 'Minutes' },
|
|
422
|
+
{ value: timeRemaining.seconds, label: 'Seconds' }
|
|
423
|
+
];
|
|
424
|
+
|
|
425
|
+
const timeUnitsHtml = timeUnits
|
|
426
|
+
.map(unit => `
|
|
427
|
+
<div class="time-unit">
|
|
428
|
+
<div class="time-number">${unit.value.toString().padStart(2, '0')}</div>
|
|
429
|
+
<div class="time-label">${unit.label}</div>
|
|
430
|
+
</div>
|
|
431
|
+
`)
|
|
432
|
+
.join('');
|
|
265
433
|
|
|
266
|
-
const
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
margin: 0 0 16px 0;
|
|
270
|
-
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
|
271
|
-
`;
|
|
434
|
+
const titleHtml = this.config.title
|
|
435
|
+
? `<h2 class="timer-title">${this.escapeHtml(this.config.title)}</h2>`
|
|
436
|
+
: '';
|
|
272
437
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
438
|
+
this.innerHTML = `
|
|
439
|
+
${this.getStyles()}
|
|
440
|
+
<div class="timer-container" data-testid="countdown-timer">
|
|
441
|
+
<div class="timer-glow"></div>
|
|
442
|
+
${titleHtml}
|
|
443
|
+
<div class="timer-grid">
|
|
444
|
+
${timeUnitsHtml}
|
|
445
|
+
</div>
|
|
446
|
+
</div>
|
|
277
447
|
`;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
private renderExpired(): void {
|
|
451
|
+
const message = this.config && this.config.title
|
|
452
|
+
? `${this.escapeHtml(this.config.title)} has ended.`
|
|
453
|
+
: 'The countdown has ended.';
|
|
278
454
|
|
|
279
455
|
this.innerHTML = `
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
<
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
style="
|
|
286
|
-
background: rgba(255, 255, 255, 0.2);
|
|
287
|
-
color: white;
|
|
288
|
-
border: 2px solid rgba(255, 255, 255, 0.3);
|
|
289
|
-
padding: 12px 24px;
|
|
290
|
-
border-radius: 6px;
|
|
291
|
-
font-size: 16px;
|
|
292
|
-
font-weight: 600;
|
|
293
|
-
cursor: pointer;
|
|
294
|
-
text-decoration: none;
|
|
295
|
-
display: inline-block;
|
|
296
|
-
margin-top: 16px;
|
|
297
|
-
backdrop-filter: blur(10px);
|
|
298
|
-
"
|
|
299
|
-
role="button">
|
|
300
|
-
Learn More
|
|
301
|
-
</a>
|
|
302
|
-
` : ''}
|
|
456
|
+
${this.getStyles()}
|
|
457
|
+
<div class="expired-container" data-testid="countdown-timer-expired">
|
|
458
|
+
<div class="expired-icon">🎉</div>
|
|
459
|
+
<h2 class="expired-title">Time's Up!</h2>
|
|
460
|
+
<p class="expired-message">${message}</p>
|
|
303
461
|
</div>
|
|
304
462
|
`;
|
|
305
463
|
}
|
|
306
464
|
|
|
307
|
-
private
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
margin: 0 auto;
|
|
465
|
+
private renderNoConfig(): void {
|
|
466
|
+
this.innerHTML = `
|
|
467
|
+
${this.getStyles()}
|
|
468
|
+
<div class="no-config-container" data-testid="countdown-timer-no-config">
|
|
469
|
+
<div class="no-config-icon">⚙️</div>
|
|
470
|
+
<h2 class="no-config-title">No Active Countdown</h2>
|
|
471
|
+
<p class="no-config-message">
|
|
472
|
+
Please configure a countdown timer in your dashboard to display it here.
|
|
473
|
+
</p>
|
|
474
|
+
</div>
|
|
318
475
|
`;
|
|
476
|
+
}
|
|
319
477
|
|
|
478
|
+
private renderError(): void {
|
|
320
479
|
this.innerHTML = `
|
|
321
|
-
|
|
322
|
-
|
|
480
|
+
${this.getStyles()}
|
|
481
|
+
<div class="error-container" data-testid="countdown-timer-error">
|
|
482
|
+
<div class="error-icon">⚠️</div>
|
|
483
|
+
<p class="error-message">Unable to load countdown timer</p>
|
|
323
484
|
</div>
|
|
324
485
|
`;
|
|
325
486
|
}
|
package/dist/out.js
CHANGED
|
@@ -39504,6 +39504,23 @@ Expected plan (abbreviated):
|
|
|
39504
39504
|
}
|
|
39505
39505
|
});
|
|
39506
39506
|
|
|
39507
|
+
// dist/system-prompts/system-prompt-builders/utils/typescript-quality-guidelines.js
|
|
39508
|
+
var require_typescript_quality_guidelines = __commonJS({
|
|
39509
|
+
"dist/system-prompts/system-prompt-builders/utils/typescript-quality-guidelines.js"(exports2) {
|
|
39510
|
+
"use strict";
|
|
39511
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
39512
|
+
exports2.typescriptQualityGuidelines = void 0;
|
|
39513
|
+
exports2.typescriptQualityGuidelines = `<typescript_quality_guidelines>
|
|
39514
|
+
- Generated code MUST compile with zero TypeScript errors under strict settings:
|
|
39515
|
+
strict, noImplicitAny, strictNullChecks, exactOptionalPropertyTypes, noUncheckedIndexedAccess
|
|
39516
|
+
- Prefer type-narrowing and exhaustive logic over assertions; avoid non-null assertions (!) and unsafe casts (as any)
|
|
39517
|
+
- Treat optional values, refs, and array indexing results as possibly undefined and handle them explicitly
|
|
39518
|
+
- Use exhaustive checks for unions (e.g., switch with a never check) and return total values (no implicit undefined)
|
|
39519
|
+
- Do NOT use // @ts-ignore or // @ts-expect-error; fix the types or add guards instead
|
|
39520
|
+
</typescript_quality_guidelines>`;
|
|
39521
|
+
}
|
|
39522
|
+
});
|
|
39523
|
+
|
|
39507
39524
|
// dist/system-prompts/dashboardPage/dashboardPackage.js
|
|
39508
39525
|
var require_dashboardPackage = __commonJS({
|
|
39509
39526
|
"dist/system-prompts/dashboardPage/dashboardPackage.js"(exports2) {
|
|
@@ -64348,7 +64365,7 @@ ${componentDescription}
|
|
|
64348
64365
|
</description>${featuresBlock}
|
|
64349
64366
|
</component>`;
|
|
64350
64367
|
}
|
|
64351
|
-
|
|
64368
|
+
function buildWdsSystemPrompt(allowedComponents) {
|
|
64352
64369
|
const parsedData = wdsJson;
|
|
64353
64370
|
const relevantComponents = (parsedData.items || []).filter((component) => allowedComponents.has(component.storyName));
|
|
64354
64371
|
if (!relevantComponents.length) {
|
|
@@ -64369,6 +64386,7 @@ var require_dashboard_page_instructions = __commonJS({
|
|
|
64369
64386
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
64370
64387
|
exports2.dashboardPageInstructions = void 0;
|
|
64371
64388
|
var apiSpec_1 = require_apiSpec();
|
|
64389
|
+
var typescript_quality_guidelines_1 = require_typescript_quality_guidelines();
|
|
64372
64390
|
var dashboardPackage_1 = require_dashboardPackage();
|
|
64373
64391
|
var data_1 = require_data();
|
|
64374
64392
|
var dynamicParameters_1 = require_dynamicParameters();
|
|
@@ -64468,34 +64486,18 @@ export default function () {
|
|
|
64468
64486
|
- Do NOT use components from @wix/wix-ui-icons-common unless you know the correct import path and it's explicitly needed for icons
|
|
64469
64487
|
- Always verify component availability before using it in your generated code
|
|
64470
64488
|
- If you need a component not in the list, use a basic HTML element or create a simple custom component instead`;
|
|
64471
|
-
var dashboardPageWdsReference = async () => {
|
|
64472
|
-
const wdsPrompt = await (0, wdsPackage_1.buildWdsSystemPrompt)(supportedWDSComponents);
|
|
64473
|
-
return wdsPrompt;
|
|
64474
|
-
};
|
|
64475
|
-
var dashboardApiReferences = `${dashboardPackage_1.dashboardPackage}
|
|
64476
|
-
${ecomPackage_1.ecomPackage}`;
|
|
64477
|
-
var dashboardPageTypescriptQualityGuidelines = `<typescript_quality_guidelines>
|
|
64478
|
-
- Generated code MUST compile with zero TypeScript errors under strict settings:
|
|
64479
|
-
strict, noImplicitAny, strictNullChecks, exactOptionalPropertyTypes, noUncheckedIndexedAccess
|
|
64480
|
-
- Prefer type-narrowing and exhaustive logic over assertions; avoid non-null assertions (!) and unsafe casts (as any)
|
|
64481
|
-
- Treat optional values, refs, and array indexing results as possibly undefined and handle them explicitly
|
|
64482
|
-
- Use exhaustive checks for unions (e.g., switch with a never check) and return total values (no implicit undefined)
|
|
64483
|
-
- Do NOT use // @ts-ignore or // @ts-expect-error; fix the types or add guards instead
|
|
64484
|
-
</typescript_quality_guidelines>`;
|
|
64485
|
-
var dashboardPageDataPrompt = data_1.dataPrompt;
|
|
64486
|
-
var dashboardPageApiSpecPrompt = (0, apiSpec_1.apiSpecPrompt)();
|
|
64487
|
-
var dashboardPageDynamicParametersManagementPrompt = (0, dynamicParameters_1.dynamicParametersManagementPrompt)();
|
|
64488
64489
|
exports2.dashboardPageInstructions = {
|
|
64489
64490
|
role: dashboardPageRole,
|
|
64490
64491
|
filesAndCode: dashboardPageFilesAndCode,
|
|
64491
64492
|
wdsProviderUsage: dashboardPageWdsProviderUsage,
|
|
64492
64493
|
hardConstraints: dashboardPageHardConstraints,
|
|
64493
|
-
wdsReference: () =>
|
|
64494
|
-
apiReferences:
|
|
64495
|
-
|
|
64496
|
-
|
|
64497
|
-
|
|
64498
|
-
|
|
64494
|
+
wdsReference: () => (0, wdsPackage_1.buildWdsSystemPrompt)(supportedWDSComponents),
|
|
64495
|
+
apiReferences: `${dashboardPackage_1.dashboardPackage}
|
|
64496
|
+
${ecomPackage_1.ecomPackage}`,
|
|
64497
|
+
typescriptQualityGuidelines: typescript_quality_guidelines_1.typescriptQualityGuidelines,
|
|
64498
|
+
dataPrompt: data_1.dataPrompt,
|
|
64499
|
+
apiSpecPrompt: (0, apiSpec_1.apiSpecPrompt)(),
|
|
64500
|
+
dynamicParametersManagementPrompt: (0, dynamicParameters_1.dynamicParametersManagementPrompt)()
|
|
64499
64501
|
};
|
|
64500
64502
|
}
|
|
64501
64503
|
});
|
|
@@ -65342,13 +65344,12 @@ var require_dashboard_page_prompt = __commonJS({
|
|
|
65342
65344
|
var dashboard_page_instructions_1 = require_dashboard_page_instructions();
|
|
65343
65345
|
var CodeGenerationSystemPromptBuilder_1 = require_CodeGenerationSystemPromptBuilder();
|
|
65344
65346
|
var dashboardPagePrompt = async ({ useData, useApiSpec, useDynamicParameters, apiNames, useIteration }) => {
|
|
65345
|
-
const wdsReference = await dashboard_page_instructions_1.dashboardPageInstructions.wdsReference();
|
|
65346
65347
|
const systemPrompt = (0, CodeGenerationSystemPromptBuilder_1.codeGenerationSystemPromptBuilder)({
|
|
65347
65348
|
agentType: types_impl_1.ExtensionType.DASHBOARD_PAGE,
|
|
65348
65349
|
apiNames,
|
|
65349
65350
|
useData,
|
|
65350
65351
|
useIteration
|
|
65351
|
-
}).withRole(dashboard_page_instructions_1.dashboardPageInstructions.role).withSection("dashboard_page_extension_files_and_code", dashboard_page_instructions_1.dashboardPageInstructions.filesAndCode).withSection("wds_provider_usage", dashboard_page_instructions_1.dashboardPageInstructions.wdsProviderUsage).withSection("hard_constraints", dashboard_page_instructions_1.dashboardPageInstructions.hardConstraints).withSection("api_references", dashboard_page_instructions_1.dashboardPageInstructions.apiReferences).withSection("wds_reference", wdsReference).withContextExplanation().withApiDocs().withCorePrinciples().withImplementationGuidelines(dashboard_page_instructions_1.dashboardPageInstructions.typescriptQualityGuidelines).withExamples();
|
|
65352
|
+
}).withRole(dashboard_page_instructions_1.dashboardPageInstructions.role).withSection("dashboard_page_extension_files_and_code", dashboard_page_instructions_1.dashboardPageInstructions.filesAndCode).withSection("wds_provider_usage", dashboard_page_instructions_1.dashboardPageInstructions.wdsProviderUsage).withSection("hard_constraints", dashboard_page_instructions_1.dashboardPageInstructions.hardConstraints).withSection("api_references", dashboard_page_instructions_1.dashboardPageInstructions.apiReferences).withSection("wds_reference", dashboard_page_instructions_1.dashboardPageInstructions.wdsReference()).withContextExplanation().withApiDocs().withCorePrinciples().withImplementationGuidelines(dashboard_page_instructions_1.dashboardPageInstructions.typescriptQualityGuidelines).withExamples();
|
|
65352
65353
|
if (useData) {
|
|
65353
65354
|
systemPrompt.withSection("data_prompt", dashboard_page_instructions_1.dashboardPageInstructions.dataPrompt);
|
|
65354
65355
|
}
|
|
@@ -65700,6 +65701,7 @@ var require_site_component_instructions = __commonJS({
|
|
|
65700
65701
|
"use strict";
|
|
65701
65702
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
65702
65703
|
exports2.siteComponentInstructions = void 0;
|
|
65704
|
+
var typescript_quality_guidelines_1 = require_typescript_quality_guidelines();
|
|
65703
65705
|
var siteComponentRole = "You are a senior Wix CLI App Developer and React expert. Your job is to produce a beautiful, production\u2011quality site component quickly and correctly.";
|
|
65704
65706
|
var siteComponentImplementationGuidelines = `<rules>
|
|
65705
65707
|
- Return ONLY a JSON object matching the schema { path, content, type } (no prose, no markdown)
|
|
@@ -65722,14 +65724,7 @@ var require_site_component_instructions = __commonJS({
|
|
|
65722
65724
|
- Name things clearly; avoid magic numbers; extract tiny helpers if it improves clarity
|
|
65723
65725
|
</engineering_guidelines>
|
|
65724
65726
|
|
|
65725
|
-
|
|
65726
|
-
- Generated code MUST compile with zero TypeScript errors under strict settings:
|
|
65727
|
-
strict, noImplicitAny, strictNullChecks, exactOptionalPropertyTypes, noUncheckedIndexedAccess
|
|
65728
|
-
- Prefer type-narrowing and exhaustive logic over assertions; avoid non-null assertions (!) and unsafe casts (as any)
|
|
65729
|
-
- Treat optional values, refs, and array indexing results as possibly undefined and handle them explicitly
|
|
65730
|
-
- Use exhaustive checks for unions (e.g., switch with a never check) and return total values (no implicit undefined)
|
|
65731
|
-
- Do NOT use // @ts-ignore or // @ts-expect-error; fix the types or add guards instead
|
|
65732
|
-
</typescript_quality_guidelines>
|
|
65727
|
+
${typescript_quality_guidelines_1.typescriptQualityGuidelines}
|
|
65733
65728
|
`;
|
|
65734
65729
|
exports2.siteComponentInstructions = {
|
|
65735
65730
|
role: siteComponentRole,
|
|
@@ -65813,6 +65808,7 @@ var require_custom_element_instructions = __commonJS({
|
|
|
65813
65808
|
"use strict";
|
|
65814
65809
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
65815
65810
|
exports2.customElementInstructions = void 0;
|
|
65811
|
+
var typescript_quality_guidelines_1 = require_typescript_quality_guidelines();
|
|
65816
65812
|
var customElementRole = `You are a senior Wix CLI App Developer. Your job is to produce a beautiful, production\u2011quality site component quickly and correctly.`;
|
|
65817
65813
|
var customElementImplementationGuidelines = `<rules>
|
|
65818
65814
|
- Return ONLY a JSON object matching the schema { path, content, type } (no prose, no markdown)
|
|
@@ -65827,14 +65823,7 @@ var require_custom_element_instructions = __commonJS({
|
|
|
65827
65823
|
- Name things clearly; avoid magic numbers; extract tiny helpers if it improves clarity
|
|
65828
65824
|
</engineering_guidelines>
|
|
65829
65825
|
|
|
65830
|
-
|
|
65831
|
-
- Generated code MUST compile with zero TypeScript errors under strict settings:
|
|
65832
|
-
strict, noImplicitAny, strictNullChecks, exactOptionalPropertyTypes, noUncheckedIndexedAccess
|
|
65833
|
-
- Prefer type-narrowing and exhaustive logic over assertions; avoid non-null assertions (!) and unsafe casts (as any)
|
|
65834
|
-
- Treat optional values, refs, and array indexing results as possibly undefined and handle them explicitly
|
|
65835
|
-
- Use exhaustive checks for unions (e.g., switch with a never check) and return total values (no implicit undefined)
|
|
65836
|
-
- Do NOT use // @ts-ignore or // @ts-expect-error; fix the types or add guards instead
|
|
65837
|
-
</typescript_quality_guidelines>
|
|
65826
|
+
${typescript_quality_guidelines_1.typescriptQualityGuidelines}
|
|
65838
65827
|
|
|
65839
65828
|
<frontend_aesthetics>
|
|
65840
65829
|
You tend to converge toward generic, "on distribution" outputs. In frontend design, this creates what users call the "AI slop" aesthetic. Avoid this: make creative, distinctive frontends that surprise and delight.
|
|
@@ -66304,13 +66293,13 @@ var require_backend_api_instructions = __commonJS({
|
|
|
66304
66293
|
var backendApiRole = `You are a specialized code-generation agent for creating Astro Server Endpoints (API Routes) for fullstack applications.`;
|
|
66305
66294
|
var backendApiImplementationGuidelines = `Generate clean, well-structured Astro Server Endpoints based on the API Spec that follow these patterns and best practices.
|
|
66306
66295
|
Focus on creating maintainable, secure, and efficient API routes that integrate well with frontend applications.`;
|
|
66307
|
-
var backendApiCoreKnowledge =
|
|
66296
|
+
var backendApiCoreKnowledge = `<astro_server_endpoints_overview>
|
|
66308
66297
|
- Astro Server Endpoints are API routes that run on the server side
|
|
66309
66298
|
- They are located in the \`src/pages/api/\` directory
|
|
66310
66299
|
- Each file exports named functions for HTTP methods (GET, POST, PUT, DELETE, etc.)
|
|
66311
66300
|
- Files use the \`.ts\` extension and are automatically converted to API endpoints
|
|
66312
|
-
|
|
66313
|
-
|
|
66301
|
+
</astro_server_endpoints_overview>
|
|
66302
|
+
<file_structure_and_naming>
|
|
66314
66303
|
- API routes are created in \`src/pages/api/\` directory
|
|
66315
66304
|
- File names become the endpoint path (e.g., \`users.ts\` \u2192 \`/api/users\`)
|
|
66316
66305
|
- For dynamic routes with parameters, use square brackets in the filename (e.g., \`/api/users/[id]\`)
|
|
@@ -66339,39 +66328,40 @@ export async function GET({ params }) {
|
|
|
66339
66328
|
});
|
|
66340
66329
|
}
|
|
66341
66330
|
\`\`\`
|
|
66342
|
-
|
|
66343
|
-
|
|
66331
|
+
</file_structure_and_naming>
|
|
66332
|
+
<typescript_patterns>
|
|
66344
66333
|
- Import \`APIRoute\` type from 'astro'
|
|
66345
66334
|
- Export named functions for HTTP methods: \`GET\`, \`POST\`, \`PUT\`, \`DELETE\`, \`PATCH\`
|
|
66346
66335
|
- Use async/await for handling asynchronous operations
|
|
66347
66336
|
- Always return a \`Response\` object
|
|
66348
|
-
|
|
66349
|
-
|
|
66337
|
+
</typescript_patterns>
|
|
66338
|
+
<request_handling>
|
|
66350
66339
|
- Access request data through the \`request\` parameter
|
|
66351
66340
|
- Use \`request.json()\` for POST/PUT request bodies
|
|
66352
66341
|
- Use \`request.url\` for the full URL
|
|
66353
66342
|
- Use \`new URL(request.url).searchParams\` for query parameters
|
|
66354
66343
|
- Access headers via \`request.headers\`
|
|
66355
|
-
|
|
66356
|
-
|
|
66344
|
+
</request_handling>
|
|
66345
|
+
<response_patterns>
|
|
66357
66346
|
- Always return a \`Response\` object
|
|
66358
66347
|
- Use \`JSON.stringify()\` for JSON responses
|
|
66359
66348
|
- Set appropriate status codes (200, 201, 400, 404, 500, etc.)
|
|
66360
66349
|
- Include proper headers, especially \`Content-Type: application/json\`
|
|
66361
|
-
|
|
66362
|
-
|
|
66350
|
+
</response_patterns>
|
|
66351
|
+
<common_patterns>
|
|
66363
66352
|
- GET endpoints for data retrieval
|
|
66364
66353
|
- POST endpoints for data creation
|
|
66365
66354
|
- PUT/PATCH endpoints for data updates
|
|
66366
66355
|
- DELETE endpoints for data removal
|
|
66367
66356
|
- Use proper HTTP status codes
|
|
66368
|
-
|
|
66369
|
-
|
|
66357
|
+
</common_patterns>
|
|
66358
|
+
<best_practices>
|
|
66370
66359
|
- Use proper TypeScript types
|
|
66371
66360
|
- Return appropriate HTTP status codes
|
|
66372
66361
|
- Include proper headers
|
|
66373
66362
|
- Use async/await for asynchronous operations
|
|
66374
|
-
- Keep endpoints focused and single-purpose
|
|
66363
|
+
- Keep endpoints focused and single-purpose
|
|
66364
|
+
</best_practices>`;
|
|
66375
66365
|
exports2.backendApiInstructions = {
|
|
66376
66366
|
role: backendApiRole,
|
|
66377
66367
|
implementationGuidelines: backendApiImplementationGuidelines,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/ditto-codegen-public",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.173",
|
|
4
4
|
"description": "AI-powered Wix CLI app generator - standalone executable",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "node build.mjs",
|
|
@@ -24,5 +24,5 @@
|
|
|
24
24
|
"@wix/ditto-codegen": "1.0.0",
|
|
25
25
|
"esbuild": "^0.25.9"
|
|
26
26
|
},
|
|
27
|
-
"falconPackageHash": "
|
|
27
|
+
"falconPackageHash": "143c2dbe2321cf37cf808acd5d4052c36631cc0a6f612540411cf062"
|
|
28
28
|
}
|