@active-reach/web-sdk 1.21.0 → 1.25.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/dist/aegis-sw.js +1 -1
- package/dist/aegis.min.js +1 -1
- package/dist/aegis.min.js.map +1 -1
- package/dist/{analytics-DblhjFhs.mjs → analytics-0p0p56H0.mjs} +11 -6
- package/dist/analytics-0p0p56H0.mjs.map +1 -0
- package/dist/chat/AegisChat.d.ts +6 -0
- package/dist/chat/AegisChat.d.ts.map +1 -1
- package/dist/core/prefetch-bundle-client.d.ts.map +1 -1
- package/dist/inapp/AegisInAppManager.d.ts +32 -0
- package/dist/inapp/AegisInAppManager.d.ts.map +1 -1
- package/dist/inapp/lucide-svg.d.ts +46 -0
- package/dist/inapp/lucide-svg.d.ts.map +1 -0
- package/dist/inapp/renderers/active-web-chat.d.ts.map +1 -1
- package/dist/inapp/renderers/card-style.d.ts +28 -0
- package/dist/inapp/renderers/card-style.d.ts.map +1 -0
- package/dist/inapp/renderers/card-template.d.ts +127 -0
- package/dist/inapp/renderers/card-template.d.ts.map +1 -0
- package/dist/inapp/renderers/carousel-cards.d.ts.map +1 -1
- package/dist/inapp/renderers/games.d.ts.map +1 -1
- package/dist/inapp/renderers/hero.d.ts.map +1 -1
- package/dist/inapp/renderers/index.d.ts +3 -1
- package/dist/inapp/renderers/index.d.ts.map +1 -1
- package/dist/inapp/renderers/product-recommendation.d.ts +19 -5
- package/dist/inapp/renderers/product-recommendation.d.ts.map +1 -1
- package/dist/inapp/renderers/progress-bar.d.ts.map +1 -1
- package/dist/inapp/renderers/sticky-bar.d.ts.map +1 -1
- package/dist/inapp/renderers/stories.d.ts.map +1 -1
- package/dist/inapp/renderers/types.d.ts +10 -0
- package/dist/inapp/renderers/types.d.ts.map +1 -1
- package/dist/inapp/renderers/video.d.ts.map +1 -1
- package/dist/index.js +1460 -272
- package/dist/index.js.map +1 -1
- package/dist/push/AegisWebPush.d.ts +1 -6
- package/dist/push/AegisWebPush.d.ts.map +1 -1
- package/dist/push/AegisWebPush.js +20 -1
- package/dist/push/AegisWebPush.js.map +1 -1
- package/dist/react.js +1 -1
- package/dist/runtime/AegisMessageRuntime.d.ts +11 -1
- package/dist/runtime/AegisMessageRuntime.d.ts.map +1 -1
- package/dist/triggers/IntentRuleEvaluator.d.ts +21 -0
- package/dist/triggers/IntentRuleEvaluator.d.ts.map +1 -1
- package/dist/utils/consent.d.ts.map +1 -1
- package/dist/widgets/AegisWidgetManager.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/analytics-DblhjFhs.mjs.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as Storage, l as logger, A as Aegis } from "./analytics-
|
|
2
|
-
import { B, E, N, R, U, m } from "./analytics-
|
|
1
|
+
import { S as Storage, l as logger, A as Aegis } from "./analytics-0p0p56H0.mjs";
|
|
2
|
+
import { B, E, N, R, U, m } from "./analytics-0p0p56H0.mjs";
|
|
3
3
|
import { AegisWebPush } from "./push/AegisWebPush.js";
|
|
4
4
|
function debounce(func, wait) {
|
|
5
5
|
let timeoutId = null;
|
|
@@ -25,9 +25,921 @@ function throttle(func, limit) {
|
|
|
25
25
|
}
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
|
+
const ICONS = {
|
|
29
|
+
x: [
|
|
30
|
+
["path", { d: "M18 6 6 18" }],
|
|
31
|
+
["path", { d: "m6 6 12 12" }]
|
|
32
|
+
],
|
|
33
|
+
check: [["path", { d: "M20 6 9 17l-5-5" }]],
|
|
34
|
+
info: [
|
|
35
|
+
["circle", { cx: "12", cy: "12", r: "10" }],
|
|
36
|
+
["path", { d: "M12 16v-4" }],
|
|
37
|
+
["path", { d: "M12 8h.01" }]
|
|
38
|
+
],
|
|
39
|
+
"triangle-alert": [
|
|
40
|
+
["path", { d: "m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" }],
|
|
41
|
+
["path", { d: "M12 9v4" }],
|
|
42
|
+
["path", { d: "M12 17h.01" }]
|
|
43
|
+
],
|
|
44
|
+
"volume-2": [
|
|
45
|
+
[
|
|
46
|
+
"path",
|
|
47
|
+
{
|
|
48
|
+
d: "M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z"
|
|
49
|
+
}
|
|
50
|
+
],
|
|
51
|
+
["path", { d: "M16 9a5 5 0 0 1 0 6" }],
|
|
52
|
+
["path", { d: "M19.364 18.364a9 9 0 0 0 0-12.728" }]
|
|
53
|
+
],
|
|
54
|
+
"volume-x": [
|
|
55
|
+
[
|
|
56
|
+
"path",
|
|
57
|
+
{
|
|
58
|
+
d: "M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z"
|
|
59
|
+
}
|
|
60
|
+
],
|
|
61
|
+
["line", { x1: "22", x2: "16", y1: "9", y2: "15" }],
|
|
62
|
+
["line", { x1: "16", x2: "22", y1: "9", y2: "15" }]
|
|
63
|
+
],
|
|
64
|
+
clock: [
|
|
65
|
+
["circle", { cx: "12", cy: "12", r: "10" }],
|
|
66
|
+
["polyline", { points: "12 6 12 12 16 14" }]
|
|
67
|
+
],
|
|
68
|
+
play: [["polygon", { points: "6 3 20 12 6 21 6 3" }]],
|
|
69
|
+
pause: [
|
|
70
|
+
["rect", { x: "14", y: "4", width: "4", height: "16", rx: "1" }],
|
|
71
|
+
["rect", { x: "6", y: "4", width: "4", height: "16", rx: "1" }]
|
|
72
|
+
],
|
|
73
|
+
square: [["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2" }]],
|
|
74
|
+
"square-check": [
|
|
75
|
+
["path", { d: "M21 10.5V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h12.5" }],
|
|
76
|
+
["path", { d: "m9 11 3 3L22 4" }]
|
|
77
|
+
],
|
|
78
|
+
truck: [
|
|
79
|
+
["path", { d: "M14 18V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v11a1 1 0 0 0 1 1h2" }],
|
|
80
|
+
["path", { d: "M15 18H9" }],
|
|
81
|
+
[
|
|
82
|
+
"path",
|
|
83
|
+
{
|
|
84
|
+
d: "M19 18h2a1 1 0 0 0 1-1v-3.65a1 1 0 0 0-.22-.624l-3.48-4.35A1 1 0 0 0 17.52 8H14"
|
|
85
|
+
}
|
|
86
|
+
],
|
|
87
|
+
["circle", { cx: "17", cy: "18", r: "2" }],
|
|
88
|
+
["circle", { cx: "7", cy: "18", r: "2" }]
|
|
89
|
+
],
|
|
90
|
+
"circle-check": [
|
|
91
|
+
["circle", { cx: "12", cy: "12", r: "10" }],
|
|
92
|
+
["path", { d: "m9 12 2 2 4-4" }]
|
|
93
|
+
],
|
|
94
|
+
// ── Commerce / value-bar set (rich card editor picker) ───────────────────
|
|
95
|
+
"shopping-cart": [
|
|
96
|
+
["circle", { cx: "8", cy: "21", r: "1" }],
|
|
97
|
+
["circle", { cx: "19", cy: "21", r: "1" }],
|
|
98
|
+
["path", { d: "M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12" }]
|
|
99
|
+
],
|
|
100
|
+
"shopping-bag": [
|
|
101
|
+
["path", { d: "M6 2 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4Z" }],
|
|
102
|
+
["path", { d: "M3 6h18" }],
|
|
103
|
+
["path", { d: "M16 10a4 4 0 0 1-8 0" }]
|
|
104
|
+
],
|
|
105
|
+
gift: [
|
|
106
|
+
["rect", { x: "3", y: "8", width: "18", height: "4", rx: "1" }],
|
|
107
|
+
["path", { d: "M12 8v13" }],
|
|
108
|
+
["path", { d: "M19 12v7a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2v-7" }],
|
|
109
|
+
["path", { d: "M7.5 8a2.5 2.5 0 0 1 0-5A4.8 8 0 0 1 12 8a4.8 8 0 0 1 4.5-5 2.5 2.5 0 0 1 0 5" }]
|
|
110
|
+
],
|
|
111
|
+
tag: [
|
|
112
|
+
["path", { d: "M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z" }],
|
|
113
|
+
["circle", { cx: "7.5", cy: "7.5", r: ".5", fill: "currentColor" }]
|
|
114
|
+
],
|
|
115
|
+
percent: [
|
|
116
|
+
["line", { x1: "19", x2: "5", y1: "5", y2: "19" }],
|
|
117
|
+
["circle", { cx: "6.5", cy: "6.5", r: "2.5" }],
|
|
118
|
+
["circle", { cx: "17.5", cy: "17.5", r: "2.5" }]
|
|
119
|
+
],
|
|
120
|
+
star: [
|
|
121
|
+
["path", { d: "M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z" }]
|
|
122
|
+
],
|
|
123
|
+
sparkles: [
|
|
124
|
+
["path", { d: "M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z" }],
|
|
125
|
+
["path", { d: "M20 3v4" }],
|
|
126
|
+
["path", { d: "M22 5h-4" }]
|
|
127
|
+
],
|
|
128
|
+
zap: [
|
|
129
|
+
["path", { d: "M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z" }]
|
|
130
|
+
],
|
|
131
|
+
heart: [
|
|
132
|
+
["path", { d: "M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z" }]
|
|
133
|
+
],
|
|
134
|
+
bell: [
|
|
135
|
+
["path", { d: "M10.268 21a2 2 0 0 0 3.464 0" }],
|
|
136
|
+
["path", { d: "M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326" }]
|
|
137
|
+
],
|
|
138
|
+
lock: [
|
|
139
|
+
["rect", { width: "18", height: "11", x: "3", y: "11", rx: "2", ry: "2" }],
|
|
140
|
+
["path", { d: "M7 11V7a5 5 0 0 1 10 0v4" }]
|
|
141
|
+
],
|
|
142
|
+
"badge-check": [
|
|
143
|
+
["path", { d: "M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z" }],
|
|
144
|
+
["path", { d: "m9 12 2 2 4-4" }]
|
|
145
|
+
],
|
|
146
|
+
package: [
|
|
147
|
+
["path", { d: "M11 21.73a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73z" }],
|
|
148
|
+
["path", { d: "M12 22V12" }],
|
|
149
|
+
["path", { d: "m3.3 7 8.7 5 8.7-5" }],
|
|
150
|
+
["path", { d: "m7.5 4.27 9 5.15" }]
|
|
151
|
+
],
|
|
152
|
+
flame: [
|
|
153
|
+
["path", { d: "M8.5 14.5A2.5 2.5 0 0 0 11 12c0-1.38-.5-2-1-3-1.072-2.143-.224-4.054 2-6 .5 2.5 2 4.9 4 6.5 2 1.6 3 3.5 3 5.5a7 7 0 1 1-14 0c0-1.153.433-2.294 1-3a2.5 2.5 0 0 0 2.5 2.5z" }]
|
|
154
|
+
],
|
|
155
|
+
crown: [
|
|
156
|
+
["path", { d: "M11.562 3.266a.5.5 0 0 1 .876 0L15.39 8.87a1 1 0 0 0 1.516.294L21.183 5.5a.5.5 0 0 1 .798.519l-2.834 10.246a1 1 0 0 1-.956.734H5.81a1 1 0 0 1-.957-.734L2.02 6.02a.5.5 0 0 1 .798-.519l4.276 3.664a1 1 0 0 0 1.516-.294z" }],
|
|
157
|
+
["path", { d: "M5 21h14" }]
|
|
158
|
+
],
|
|
159
|
+
ticket: [
|
|
160
|
+
["path", { d: "M2 9a3 3 0 0 1 0 6v2a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-2a3 3 0 0 1 0-6V7a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2Z" }],
|
|
161
|
+
["path", { d: "M13 5v2" }],
|
|
162
|
+
["path", { d: "M13 17v2" }],
|
|
163
|
+
["path", { d: "M13 11v2" }]
|
|
164
|
+
],
|
|
165
|
+
wallet: [
|
|
166
|
+
["path", { d: "M19 7V4a1 1 0 0 0-1-1H5a2 2 0 0 0 0 4h15a1 1 0 0 1 1 1v4h-3a2 2 0 0 0 0 4h3a1 1 0 0 0 1-1v-2a1 1 0 0 0-1-1" }],
|
|
167
|
+
["path", { d: "M3 5v14a2 2 0 0 0 2 2h15a1 1 0 0 0 1-1v-4" }]
|
|
168
|
+
],
|
|
169
|
+
coins: [
|
|
170
|
+
["circle", { cx: "8", cy: "8", r: "6" }],
|
|
171
|
+
["path", { d: "M18.09 10.37A6 6 0 1 1 10.34 18" }],
|
|
172
|
+
["path", { d: "M7 6h1v4" }],
|
|
173
|
+
["path", { d: "m16.71 13.88.7.71-2.82 2.82" }]
|
|
174
|
+
],
|
|
175
|
+
trophy: [
|
|
176
|
+
["path", { d: "M6 9H4.5a2.5 2.5 0 0 1 0-5H6" }],
|
|
177
|
+
["path", { d: "M18 9h1.5a2.5 2.5 0 0 0 0-5H18" }],
|
|
178
|
+
["path", { d: "M4 22h16" }],
|
|
179
|
+
["path", { d: "M10 14.66V17c0 .55-.47.98-.97 1.21C7.85 18.75 7 20.24 7 22" }],
|
|
180
|
+
["path", { d: "M14 14.66V17c0 .55.47.98.97 1.21C16.15 18.75 17 20.24 17 22" }],
|
|
181
|
+
["path", { d: "M18 2H6v7a6 6 0 0 0 12 0V2Z" }]
|
|
182
|
+
],
|
|
183
|
+
timer: [
|
|
184
|
+
["line", { x1: "10", x2: "14", y1: "2", y2: "2" }],
|
|
185
|
+
["line", { x1: "12", x2: "15", y1: "14", y2: "11" }],
|
|
186
|
+
["circle", { cx: "12", cy: "14", r: "8" }]
|
|
187
|
+
],
|
|
188
|
+
"map-pin": [
|
|
189
|
+
["path", { d: "M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0" }],
|
|
190
|
+
["circle", { cx: "12", cy: "10", r: "3" }]
|
|
191
|
+
],
|
|
192
|
+
user: [
|
|
193
|
+
["path", { d: "M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2" }],
|
|
194
|
+
["circle", { cx: "12", cy: "7", r: "4" }]
|
|
195
|
+
],
|
|
196
|
+
"thumbs-up": [
|
|
197
|
+
["path", { d: "M7 10v12" }],
|
|
198
|
+
["path", { d: "M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2a3.13 3.13 0 0 1 3 3.88Z" }]
|
|
199
|
+
],
|
|
200
|
+
"arrow-right": [
|
|
201
|
+
["path", { d: "M5 12h14" }],
|
|
202
|
+
["path", { d: "m12 5 7 7-7 7" }]
|
|
203
|
+
],
|
|
204
|
+
"chevron-right": [["path", { d: "m9 18 6-6-6-6" }]],
|
|
205
|
+
plus: [
|
|
206
|
+
["path", { d: "M5 12h14" }],
|
|
207
|
+
["path", { d: "M12 5v14" }]
|
|
208
|
+
],
|
|
209
|
+
store: [
|
|
210
|
+
["path", { d: "m2 7 4.41-4.41A2 2 0 0 1 7.83 2h8.34a2 2 0 0 1 1.42.59L22 7" }],
|
|
211
|
+
["path", { d: "M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8" }],
|
|
212
|
+
["path", { d: "M15 22v-4a2 2 0 0 0-2-2h-2a2 2 0 0 0-2 2v4" }],
|
|
213
|
+
["path", { d: "M2 7h20" }],
|
|
214
|
+
["path", { d: "M22 7v3a2 2 0 0 1-2 2a2.7 2.7 0 0 1-1.59-.63.7.7 0 0 0-.82 0A2.7 2.7 0 0 1 16 12a2.7 2.7 0 0 1-1.59-.63.7.7 0 0 0-.82 0A2.7 2.7 0 0 1 12 12a2.7 2.7 0 0 1-1.59-.63.7.7 0 0 0-.82 0A2.7 2.7 0 0 1 8 12a2.7 2.7 0 0 1-1.59-.63.7.7 0 0 0-.82 0A2.7 2.7 0 0 1 4 12a2 2 0 0 1-2-2V7" }]
|
|
215
|
+
],
|
|
216
|
+
rocket: [
|
|
217
|
+
["path", { d: "M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09z" }],
|
|
218
|
+
["path", { d: "m12 15-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z" }],
|
|
219
|
+
["path", { d: "M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0" }],
|
|
220
|
+
["path", { d: "M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5" }]
|
|
221
|
+
]
|
|
222
|
+
};
|
|
223
|
+
function escapeAttr(value) {
|
|
224
|
+
return value.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<");
|
|
225
|
+
}
|
|
226
|
+
const SVG_NS = "http://www.w3.org/2000/svg";
|
|
227
|
+
function lucideSvgEl(name, opts = {}) {
|
|
228
|
+
const node = ICONS[name];
|
|
229
|
+
if (!node || typeof document === "undefined") return null;
|
|
230
|
+
const size = opts.size ?? 24;
|
|
231
|
+
const svg = document.createElementNS(SVG_NS, "svg");
|
|
232
|
+
svg.setAttribute("width", String(size));
|
|
233
|
+
svg.setAttribute("height", String(size));
|
|
234
|
+
svg.setAttribute("viewBox", "0 0 24 24");
|
|
235
|
+
svg.setAttribute("fill", "none");
|
|
236
|
+
svg.setAttribute("stroke", opts.color ?? "currentColor");
|
|
237
|
+
svg.setAttribute("stroke-width", String(opts.strokeWidth ?? 2));
|
|
238
|
+
svg.setAttribute("stroke-linecap", "round");
|
|
239
|
+
svg.setAttribute("stroke-linejoin", "round");
|
|
240
|
+
if (opts.className) svg.setAttribute("class", opts.className);
|
|
241
|
+
if (opts.ariaLabel) {
|
|
242
|
+
svg.setAttribute("role", "img");
|
|
243
|
+
svg.setAttribute("aria-label", opts.ariaLabel);
|
|
244
|
+
} else {
|
|
245
|
+
svg.setAttribute("aria-hidden", "true");
|
|
246
|
+
}
|
|
247
|
+
for (const [tag, attrs] of node) {
|
|
248
|
+
const child = document.createElementNS(SVG_NS, tag);
|
|
249
|
+
for (const [k, v] of Object.entries(attrs)) child.setAttribute(k, String(v));
|
|
250
|
+
svg.appendChild(child);
|
|
251
|
+
}
|
|
252
|
+
return svg;
|
|
253
|
+
}
|
|
254
|
+
function lucideSvg(name, opts = {}) {
|
|
255
|
+
const node = ICONS[name];
|
|
256
|
+
if (!node) return "";
|
|
257
|
+
const size = opts.size ?? 24;
|
|
258
|
+
const color = opts.color ?? "currentColor";
|
|
259
|
+
const strokeWidth = opts.strokeWidth ?? 2;
|
|
260
|
+
const a11y = opts.ariaLabel ? `role="img" aria-label="${escapeAttr(opts.ariaLabel)}"` : 'aria-hidden="true"';
|
|
261
|
+
const cls = opts.className ? ` class="${escapeAttr(opts.className)}"` : "";
|
|
262
|
+
const children = node.map(([tag, attrs]) => {
|
|
263
|
+
const attrStr = Object.entries(attrs).map(([k, v]) => `${k}="${escapeAttr(String(v))}"`).join(" ");
|
|
264
|
+
return `<${tag} ${attrStr}/>`;
|
|
265
|
+
}).join("");
|
|
266
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" viewBox="0 0 24 24" fill="none" stroke="${escapeAttr(color)}" stroke-width="${strokeWidth}" stroke-linecap="round" stroke-linejoin="round"${cls} ${a11y}>${children}</svg>`;
|
|
267
|
+
}
|
|
268
|
+
const WEIGHT = {
|
|
269
|
+
regular: "400",
|
|
270
|
+
medium: "500",
|
|
271
|
+
semibold: "600",
|
|
272
|
+
bold: "700"
|
|
273
|
+
};
|
|
274
|
+
const ICON_PX = { sm: 22, md: 30, lg: 40 };
|
|
275
|
+
const TEXT_PX = { sm: 11.5, md: 13, lg: 15 };
|
|
276
|
+
function interpolateTokens(s, ctx) {
|
|
277
|
+
if (!s || s.indexOf("{") === -1) return s;
|
|
278
|
+
const props = ctx.properties && ctx.properties() || {};
|
|
279
|
+
const cart = ctx.getCartState && ctx.getCartState();
|
|
280
|
+
return s.replace(/\{([a-z0-9_.]+)\}/gi, (_m, key) => {
|
|
281
|
+
let v = props[key];
|
|
282
|
+
if (v == null) {
|
|
283
|
+
if (key === "cart.total") v = cart == null ? void 0 : cart.total;
|
|
284
|
+
else if (key === "cart.count") v = cart == null ? void 0 : cart.itemCount;
|
|
285
|
+
}
|
|
286
|
+
return v == null || v === "" ? "" : String(v);
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
const ASPECT$2 = { "1/1": "1 / 1", "4/3": "4 / 3", "16/9": "16 / 9" };
|
|
290
|
+
const DEFAULT_CARD_TEMPLATE = {
|
|
291
|
+
id: "clean",
|
|
292
|
+
frame: { bg: "#ffffff", border: "#f1f1f3", radius: 14 },
|
|
293
|
+
elements: [
|
|
294
|
+
{ type: "image", aspect: "1/1", radius: 10 },
|
|
295
|
+
{ type: "price", variant: "pill", color: "#059669" },
|
|
296
|
+
{ type: "title", lines: 2 },
|
|
297
|
+
{ type: "rating" },
|
|
298
|
+
// Zepto/Blinkit-style ADD: a single OUTLINED pill (white fill, brand
|
|
299
|
+
// border + brand text) overlaid on the bottom-right of the product image —
|
|
300
|
+
// NOT a solid filled bar. `overlay:true` anchors it onto the image; the
|
|
301
|
+
// outline variant paints the white/border look. The rail's tile-body click
|
|
302
|
+
// still opens the product, so this one CTA owns add-to-cart.
|
|
303
|
+
{ type: "cta", variant: "outline", overlay: true }
|
|
304
|
+
]
|
|
305
|
+
};
|
|
306
|
+
function asLook(v) {
|
|
307
|
+
return v && typeof v === "object" ? v : {};
|
|
308
|
+
}
|
|
309
|
+
function templateFromCardStyle(look) {
|
|
310
|
+
const elements = [{ type: "image", aspect: "1/1", radius: 10 }];
|
|
311
|
+
if (look.badge) elements.push({ type: "badge", text: look.badge, color: look.badge_color });
|
|
312
|
+
if (!look.hide_price) elements.push({ type: "price", variant: "pill", color: "#059669" });
|
|
313
|
+
elements.push({ type: "title", lines: 2 });
|
|
314
|
+
if (!look.hide_rating) elements.push({ type: "rating" });
|
|
315
|
+
if (!look.hide_cta) elements.push({ type: "cta", variant: "fill", text: look.cta_text });
|
|
316
|
+
return {
|
|
317
|
+
id: "legacy",
|
|
318
|
+
frame: {
|
|
319
|
+
bg: look.background,
|
|
320
|
+
border: look.border_color,
|
|
321
|
+
radius: look.radius,
|
|
322
|
+
accent: look.accent ?? null
|
|
323
|
+
},
|
|
324
|
+
elements
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
function resolveGlobalTemplate(ic) {
|
|
328
|
+
const t = ic.card_template;
|
|
329
|
+
if (t && typeof t === "object" && Array.isArray(t.elements)) {
|
|
330
|
+
return t;
|
|
331
|
+
}
|
|
332
|
+
const legacy = ic.card_style;
|
|
333
|
+
if (legacy && typeof legacy === "object") {
|
|
334
|
+
return templateFromCardStyle(asLook(legacy));
|
|
335
|
+
}
|
|
336
|
+
return DEFAULT_CARD_TEMPLATE;
|
|
337
|
+
}
|
|
338
|
+
function applyPerCardOverride(tpl, look) {
|
|
339
|
+
if (!look || Object.keys(look).length === 0) return tpl;
|
|
340
|
+
const frame = { ...tpl.frame || {} };
|
|
341
|
+
if (look.accent) frame.accent = look.accent;
|
|
342
|
+
if (look.radius !== void 0) frame.radius = look.radius;
|
|
343
|
+
let elements = (tpl.elements || []).slice();
|
|
344
|
+
const drop = (type) => elements = elements.filter((e) => e.type !== type);
|
|
345
|
+
if (look.hide_price) drop("price");
|
|
346
|
+
if (look.hide_cta) drop("cta");
|
|
347
|
+
if (look.hide_rating) drop("rating");
|
|
348
|
+
if (look.cta_text) elements = elements.map((e) => e.type === "cta" ? { ...e, text: look.cta_text } : e);
|
|
349
|
+
if (look.badge) {
|
|
350
|
+
const badgeEl = { type: "badge", text: look.badge, color: look.badge_color };
|
|
351
|
+
elements = elements.some((e) => e.type === "badge") ? elements.map((e) => e.type === "badge" ? badgeEl : e) : [elements[0], badgeEl, ...elements.slice(1)].filter(Boolean);
|
|
352
|
+
}
|
|
353
|
+
return { ...tpl, frame, elements };
|
|
354
|
+
}
|
|
355
|
+
function priceText(card) {
|
|
356
|
+
const meta = card.metadata || {};
|
|
357
|
+
const p = meta.price;
|
|
358
|
+
if (p !== void 0 && p !== null) return String(p);
|
|
359
|
+
if (card.body && /\d/.test(card.body)) return card.body;
|
|
360
|
+
return void 0;
|
|
361
|
+
}
|
|
362
|
+
function paintPrice(card, el, accent, ctx) {
|
|
363
|
+
const price = priceText(card);
|
|
364
|
+
if (price === void 0) return null;
|
|
365
|
+
const meta = card.metadata || {};
|
|
366
|
+
const compareAt = meta.compare_at_price ?? meta.compare_at ?? meta.original_price;
|
|
367
|
+
const row = document.createElement("div");
|
|
368
|
+
row.style.cssText = "display:flex;align-items:baseline;gap:6px;flex-wrap:wrap;";
|
|
369
|
+
const p = document.createElement("span");
|
|
370
|
+
p.textContent = price;
|
|
371
|
+
if (el.variant === "plain") {
|
|
372
|
+
p.style.cssText = `color:${accent};font-weight:700;font-size:13px;`;
|
|
373
|
+
} else {
|
|
374
|
+
const pillBg = el.color ? ctx.sanitizeColor(el.color) : "#059669";
|
|
375
|
+
p.style.cssText = `background:${pillBg};color:#fff;font-weight:800;font-size:12px;padding:2px 7px;border-radius:6px;`;
|
|
376
|
+
}
|
|
377
|
+
row.appendChild(p);
|
|
378
|
+
const pNum = parseFloat(price.replace(/[^0-9.]/g, ""));
|
|
379
|
+
const cNum = compareAt !== void 0 ? parseFloat(String(compareAt).replace(/[^0-9.]/g, "")) : NaN;
|
|
380
|
+
if (isFinite(cNum) && isFinite(pNum) && cNum > pNum) {
|
|
381
|
+
const orig = document.createElement("span");
|
|
382
|
+
orig.textContent = String(compareAt);
|
|
383
|
+
orig.style.cssText = "text-decoration:line-through;opacity:0.5;font-size:11px;";
|
|
384
|
+
row.appendChild(orig);
|
|
385
|
+
const off = document.createElement("span");
|
|
386
|
+
off.textContent = `-${Math.round((1 - pNum / cNum) * 100)}%`;
|
|
387
|
+
off.style.cssText = "background:#ef444422;color:#ef4444;font-weight:700;font-size:10px;padding:1px 5px;border-radius:999px;";
|
|
388
|
+
row.appendChild(off);
|
|
389
|
+
}
|
|
390
|
+
return row;
|
|
391
|
+
}
|
|
392
|
+
function paintRating(card) {
|
|
393
|
+
const meta = card.metadata || {};
|
|
394
|
+
const avg = Number(meta.avg_rating ?? 0);
|
|
395
|
+
if (!(avg > 0)) return null;
|
|
396
|
+
const count = Number(meta.review_count ?? 0);
|
|
397
|
+
const rr = document.createElement("div");
|
|
398
|
+
rr.style.cssText = "display:flex;align-items:center;gap:3px;font-size:11px;line-height:1;";
|
|
399
|
+
const star = document.createElement("span");
|
|
400
|
+
star.textContent = "★";
|
|
401
|
+
star.style.cssText = "color:#059669;";
|
|
402
|
+
const val = document.createElement("span");
|
|
403
|
+
val.textContent = avg.toFixed(1);
|
|
404
|
+
val.style.cssText = "color:#059669;font-weight:700;";
|
|
405
|
+
rr.appendChild(star);
|
|
406
|
+
rr.appendChild(val);
|
|
407
|
+
if (count > 0) {
|
|
408
|
+
const c = document.createElement("span");
|
|
409
|
+
c.textContent = `(${count})`;
|
|
410
|
+
c.style.cssText = "color:#94a3b8;";
|
|
411
|
+
rr.appendChild(c);
|
|
412
|
+
}
|
|
413
|
+
return rr;
|
|
414
|
+
}
|
|
415
|
+
function contrastFg(bg) {
|
|
416
|
+
const raw = bg.replace("#", "");
|
|
417
|
+
if (raw.length < 3) return "#1f2937";
|
|
418
|
+
const h = raw.length === 3 ? raw.split("").map((c) => c + c).join("") : raw.slice(0, 6);
|
|
419
|
+
const r = parseInt(h.slice(0, 2), 16);
|
|
420
|
+
const g = parseInt(h.slice(2, 4), 16);
|
|
421
|
+
const b = parseInt(h.slice(4, 6), 16);
|
|
422
|
+
if ([r, g, b].some((n) => Number.isNaN(n))) return "#1f2937";
|
|
423
|
+
const lum = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
|
|
424
|
+
return lum < 0.5 ? "#ffffff" : "#1f2937";
|
|
425
|
+
}
|
|
426
|
+
function buildCountdownElement(el, fg, muted) {
|
|
427
|
+
const targetStr = typeof el.countdown_target === "string" ? el.countdown_target : "";
|
|
428
|
+
const target = targetStr ? Date.parse(targetStr) : NaN;
|
|
429
|
+
if (!targetStr || isNaN(target)) return null;
|
|
430
|
+
const wrap = document.createElement("div");
|
|
431
|
+
wrap.style.cssText = "display:flex;align-items:baseline;gap:8px;font-variant-numeric:tabular-nums;margin:2px 0;";
|
|
432
|
+
const label = document.createElement("span");
|
|
433
|
+
label.textContent = typeof el.countdown_label === "string" && el.countdown_label || "Ends in";
|
|
434
|
+
label.style.cssText = `font-size:12px;color:${muted};`;
|
|
435
|
+
const time = document.createElement("span");
|
|
436
|
+
time.style.cssText = `font-size:15px;font-weight:700;color:${fg};letter-spacing:0.2px;`;
|
|
437
|
+
wrap.appendChild(label);
|
|
438
|
+
wrap.appendChild(time);
|
|
439
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
440
|
+
let started = false;
|
|
441
|
+
let timer = 0;
|
|
442
|
+
const tick = () => {
|
|
443
|
+
if (started && !wrap.isConnected) {
|
|
444
|
+
if (timer) clearInterval(timer);
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
const ms = target - Date.now();
|
|
448
|
+
if (ms <= 0) {
|
|
449
|
+
time.textContent = "00:00:00";
|
|
450
|
+
if (timer) clearInterval(timer);
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
const s = Math.floor(ms / 1e3);
|
|
454
|
+
const d = Math.floor(s / 86400);
|
|
455
|
+
const h = Math.floor(s % 86400 / 3600);
|
|
456
|
+
const m2 = Math.floor(s % 3600 / 60);
|
|
457
|
+
const ss = s % 60;
|
|
458
|
+
time.textContent = d > 0 ? `${d}d ${pad(h)}:${pad(m2)}:${pad(ss)}` : `${pad(h)}:${pad(m2)}:${pad(ss)}`;
|
|
459
|
+
started = true;
|
|
460
|
+
};
|
|
461
|
+
tick();
|
|
462
|
+
timer = setInterval(tick, 1e3);
|
|
463
|
+
return wrap;
|
|
464
|
+
}
|
|
465
|
+
function buildRatingInputElement(el, ctx, fg) {
|
|
466
|
+
const wrap = document.createElement("div");
|
|
467
|
+
wrap.style.cssText = "display:flex;flex-direction:column;gap:6px;margin:2px 0;";
|
|
468
|
+
if (el.content) {
|
|
469
|
+
const q = document.createElement("div");
|
|
470
|
+
q.textContent = el.content;
|
|
471
|
+
q.style.cssText = `font-size:13px;font-weight:600;color:${fg};`;
|
|
472
|
+
wrap.appendChild(q);
|
|
473
|
+
}
|
|
474
|
+
const scale = typeof el.rating_scale === "number" && el.rating_scale >= 2 && el.rating_scale <= 10 ? Math.floor(el.rating_scale) : 5;
|
|
475
|
+
const row = document.createElement("div");
|
|
476
|
+
row.style.cssText = "display:flex;gap:6px;";
|
|
477
|
+
const stars = [];
|
|
478
|
+
let submitted = false;
|
|
479
|
+
const paint = (upto) => {
|
|
480
|
+
stars.forEach((s, idx) => {
|
|
481
|
+
const on = idx < upto;
|
|
482
|
+
s.setAttribute("stroke", on ? "#f59e0b" : "#d1d5db");
|
|
483
|
+
s.setAttribute("fill", on ? "#f59e0b" : "none");
|
|
484
|
+
});
|
|
485
|
+
};
|
|
486
|
+
for (let i = 1; i <= scale; i++) {
|
|
487
|
+
const btn = document.createElement("button");
|
|
488
|
+
btn.type = "button";
|
|
489
|
+
btn.setAttribute("aria-label", `${i} star${i > 1 ? "s" : ""}`);
|
|
490
|
+
btn.style.cssText = "cursor:pointer;border:none;background:none;padding:0;line-height:0;";
|
|
491
|
+
const svg = lucideSvgEl("star", { size: 26, color: "#d1d5db" });
|
|
492
|
+
if (svg) {
|
|
493
|
+
btn.appendChild(svg);
|
|
494
|
+
stars.push(svg);
|
|
495
|
+
}
|
|
496
|
+
btn.addEventListener("mouseenter", () => {
|
|
497
|
+
if (!submitted) paint(i);
|
|
498
|
+
});
|
|
499
|
+
btn.addEventListener("mouseleave", () => {
|
|
500
|
+
if (!submitted) paint(0);
|
|
501
|
+
});
|
|
502
|
+
btn.addEventListener("click", () => {
|
|
503
|
+
var _a, _b;
|
|
504
|
+
if (submitted) return;
|
|
505
|
+
submitted = true;
|
|
506
|
+
paint(i);
|
|
507
|
+
ctx.trackEvent(ctx.campaign.id, "clicked", { meta: { element: "rating_input", stars: i } });
|
|
508
|
+
void ((_a = ctx.submitResponse) == null ? void 0 : _a.call(ctx, "rating", { stars: i }));
|
|
509
|
+
(_b = ctx.playReaction) == null ? void 0 : _b.call(ctx, wrap, i >= Math.ceil(scale * 0.6) ? "affirm" : "acknowledge");
|
|
510
|
+
appendThanks(wrap, el, fg, "Thanks for rating us!");
|
|
511
|
+
});
|
|
512
|
+
row.appendChild(btn);
|
|
513
|
+
}
|
|
514
|
+
wrap.appendChild(row);
|
|
515
|
+
return wrap;
|
|
516
|
+
}
|
|
517
|
+
function appendThanks(wrap, el, fg, fallback) {
|
|
518
|
+
const msg = typeof el.thanks_text === "string" && el.thanks_text.trim() ? el.thanks_text : fallback;
|
|
519
|
+
if (!msg) return;
|
|
520
|
+
const note = document.createElement("div");
|
|
521
|
+
note.textContent = msg;
|
|
522
|
+
note.setAttribute("role", "status");
|
|
523
|
+
note.style.cssText = `font-size:12px;font-weight:600;color:${fg};opacity:0.85;margin-top:4px;`;
|
|
524
|
+
wrap.appendChild(note);
|
|
525
|
+
}
|
|
526
|
+
function buildPollElement(el, ctx, fg, accent) {
|
|
527
|
+
const opts = Array.isArray(el.poll_options) ? el.poll_options.filter((o) => typeof o === "string" && o.trim().length > 0) : [];
|
|
528
|
+
if (opts.length < 2) return null;
|
|
529
|
+
const wrap = document.createElement("div");
|
|
530
|
+
wrap.style.cssText = "display:flex;flex-direction:column;gap:6px;margin:2px 0;";
|
|
531
|
+
if (el.content) {
|
|
532
|
+
const q = document.createElement("div");
|
|
533
|
+
q.textContent = el.content;
|
|
534
|
+
q.style.cssText = `font-size:13px;font-weight:600;color:${fg};`;
|
|
535
|
+
wrap.appendChild(q);
|
|
536
|
+
}
|
|
537
|
+
let submitted = false;
|
|
538
|
+
opts.forEach((label, idx) => {
|
|
539
|
+
const btn = document.createElement("button");
|
|
540
|
+
btn.type = "button";
|
|
541
|
+
btn.textContent = label;
|
|
542
|
+
btn.style.cssText = `text-align:left;cursor:pointer;border:1px solid color-mix(in srgb, ${accent} 35%, transparent);background:transparent;color:${fg};border-radius:10px;padding:9px 12px;font-size:13px;font-weight:600;transition:background .12s,border-color .12s;`;
|
|
543
|
+
btn.addEventListener("mouseenter", () => {
|
|
544
|
+
if (!submitted) btn.style.background = `color-mix(in srgb, ${accent} 8%, transparent)`;
|
|
545
|
+
});
|
|
546
|
+
btn.addEventListener("mouseleave", () => {
|
|
547
|
+
if (!submitted) btn.style.background = "transparent";
|
|
548
|
+
});
|
|
549
|
+
btn.addEventListener("click", () => {
|
|
550
|
+
var _a, _b;
|
|
551
|
+
if (submitted) return;
|
|
552
|
+
submitted = true;
|
|
553
|
+
Array.from(wrap.querySelectorAll("button")).forEach((b) => {
|
|
554
|
+
b.disabled = true;
|
|
555
|
+
b.style.opacity = "0.6";
|
|
556
|
+
});
|
|
557
|
+
btn.style.background = accent;
|
|
558
|
+
btn.style.color = "#fff";
|
|
559
|
+
btn.style.opacity = "1";
|
|
560
|
+
ctx.trackEvent(ctx.campaign.id, "clicked", { meta: { element: "poll", option_index: idx, option_label: label } });
|
|
561
|
+
void ((_a = ctx.submitResponse) == null ? void 0 : _a.call(ctx, "poll", { option_index: idx, option_label: label }));
|
|
562
|
+
(_b = ctx.playReaction) == null ? void 0 : _b.call(ctx, wrap, "affirm");
|
|
563
|
+
appendThanks(wrap, el, fg, "Thanks for your answer!");
|
|
564
|
+
});
|
|
565
|
+
wrap.appendChild(btn);
|
|
566
|
+
});
|
|
567
|
+
return wrap;
|
|
568
|
+
}
|
|
569
|
+
function buildNpsElement(el, ctx, fg, accent, muted) {
|
|
570
|
+
const wrap = document.createElement("div");
|
|
571
|
+
wrap.style.cssText = "display:flex;flex-direction:column;gap:6px;margin:2px 0;";
|
|
572
|
+
if (el.content) {
|
|
573
|
+
const q = document.createElement("div");
|
|
574
|
+
q.textContent = el.content;
|
|
575
|
+
q.style.cssText = `font-size:13px;font-weight:600;color:${fg};`;
|
|
576
|
+
wrap.appendChild(q);
|
|
577
|
+
}
|
|
578
|
+
const row = document.createElement("div");
|
|
579
|
+
row.style.cssText = "display:flex;flex-wrap:wrap;gap:4px;";
|
|
580
|
+
let submitted = false;
|
|
581
|
+
for (let n = 0; n <= 10; n++) {
|
|
582
|
+
const btn = document.createElement("button");
|
|
583
|
+
btn.type = "button";
|
|
584
|
+
btn.textContent = String(n);
|
|
585
|
+
btn.setAttribute("aria-label", `Score ${n}`);
|
|
586
|
+
btn.style.cssText = `cursor:pointer;min-width:26px;height:30px;border:1px solid color-mix(in srgb, ${accent} 30%, transparent);background:transparent;color:${fg};border-radius:7px;font-size:12px;font-weight:700;transition:background .12s;`;
|
|
587
|
+
btn.addEventListener("mouseenter", () => {
|
|
588
|
+
if (!submitted) btn.style.background = `color-mix(in srgb, ${accent} 10%, transparent)`;
|
|
589
|
+
});
|
|
590
|
+
btn.addEventListener("mouseleave", () => {
|
|
591
|
+
if (!submitted) btn.style.background = "transparent";
|
|
592
|
+
});
|
|
593
|
+
btn.addEventListener("click", () => {
|
|
594
|
+
var _a, _b;
|
|
595
|
+
if (submitted) return;
|
|
596
|
+
submitted = true;
|
|
597
|
+
Array.from(row.children).forEach((b) => {
|
|
598
|
+
b.disabled = true;
|
|
599
|
+
b.style.opacity = "0.55";
|
|
600
|
+
});
|
|
601
|
+
btn.style.background = accent;
|
|
602
|
+
btn.style.color = "#fff";
|
|
603
|
+
btn.style.opacity = "1";
|
|
604
|
+
ctx.trackEvent(ctx.campaign.id, "clicked", { meta: { element: "nps", score: n } });
|
|
605
|
+
void ((_a = ctx.submitResponse) == null ? void 0 : _a.call(ctx, "nps", { score: n }));
|
|
606
|
+
(_b = ctx.playReaction) == null ? void 0 : _b.call(ctx, wrap, n >= 9 ? "affirm" : n >= 7 ? "acknowledge" : "empathize");
|
|
607
|
+
appendThanks(wrap, el, fg, "Thanks for your feedback!");
|
|
608
|
+
});
|
|
609
|
+
row.appendChild(btn);
|
|
610
|
+
}
|
|
611
|
+
wrap.appendChild(row);
|
|
612
|
+
const scale = document.createElement("div");
|
|
613
|
+
scale.style.cssText = `display:flex;justify-content:space-between;font-size:10px;color:${muted};`;
|
|
614
|
+
const lo = document.createElement("span");
|
|
615
|
+
lo.textContent = "Not likely";
|
|
616
|
+
const hi = document.createElement("span");
|
|
617
|
+
hi.textContent = "Very likely";
|
|
618
|
+
scale.appendChild(lo);
|
|
619
|
+
scale.appendChild(hi);
|
|
620
|
+
wrap.appendChild(scale);
|
|
621
|
+
return wrap;
|
|
622
|
+
}
|
|
623
|
+
function buildProgressElement(el, ctx, accent, muted) {
|
|
624
|
+
const { trackEvent, campaign, sanitizeColor } = ctx;
|
|
625
|
+
const goal = el.goal_type || "cart_total";
|
|
626
|
+
const moneyGoal = goal === "cart_total";
|
|
627
|
+
const fill = el.fill ? sanitizeColor(el.fill) : accent;
|
|
628
|
+
const props = () => ctx.properties && ctx.properties() || {};
|
|
629
|
+
const sym = () => {
|
|
630
|
+
var _a;
|
|
631
|
+
if (el.currency_symbol) return el.currency_symbol;
|
|
632
|
+
const code = ctx.getCartState && ((_a = ctx.getCartState()) == null ? void 0 : _a.currency);
|
|
633
|
+
const M = { INR: "₹", USD: "$", EUR: "€", GBP: "£" };
|
|
634
|
+
return code && M[code] || "";
|
|
635
|
+
};
|
|
636
|
+
const threshold = () => {
|
|
637
|
+
if (typeof el.threshold === "number" && el.threshold > 0) return el.threshold;
|
|
638
|
+
if (el.threshold_source === "free_delivery_setting") {
|
|
639
|
+
const v = Number(props()["cart.free_delivery_above"]);
|
|
640
|
+
if (v > 0) return v;
|
|
641
|
+
}
|
|
642
|
+
return 0;
|
|
643
|
+
};
|
|
644
|
+
const readCur = () => {
|
|
645
|
+
const cart = ctx.getCartState && ctx.getCartState();
|
|
646
|
+
if (goal === "items_in_cart") return Number(cart == null ? void 0 : cart.itemCount) || 0;
|
|
647
|
+
if (goal === "cart_total") return Number(cart == null ? void 0 : cart.total) || 0;
|
|
648
|
+
const p = props();
|
|
649
|
+
if (goal === "loyalty_points") return Number(p["loyalty.points"]) || 0;
|
|
650
|
+
if (goal === "referrals") return Number(p["referrals.count"]) || 0;
|
|
651
|
+
return 0;
|
|
652
|
+
};
|
|
653
|
+
const wrap = document.createElement("div");
|
|
654
|
+
wrap.style.cssText = "display:flex;flex-direction:column;gap:3px;min-width:0;width:100%;";
|
|
655
|
+
const sub = document.createElement("div");
|
|
656
|
+
sub.style.cssText = `font-size:11.5px;line-height:1.2;color:${muted};white-space:nowrap;overflow:hidden;text-overflow:ellipsis;`;
|
|
657
|
+
const shell = document.createElement("div");
|
|
658
|
+
shell.style.cssText = `height:3px;border-radius:999px;background:color-mix(in srgb, ${fill} 16%, transparent);overflow:hidden;`;
|
|
659
|
+
const bar = document.createElement("div");
|
|
660
|
+
bar.style.cssText = `height:100%;border-radius:999px;background:${fill};width:0%;transition:width .4s cubic-bezier(.4,0,.2,1);`;
|
|
661
|
+
shell.appendChild(bar);
|
|
662
|
+
wrap.appendChild(sub);
|
|
663
|
+
wrap.appendChild(shell);
|
|
664
|
+
let firedUnlock = false;
|
|
665
|
+
const update = () => {
|
|
666
|
+
var _a;
|
|
667
|
+
const th = threshold();
|
|
668
|
+
const cur = readCur();
|
|
669
|
+
const pct = th > 0 ? Math.max(0, Math.min(100, cur / th * 100)) : 0;
|
|
670
|
+
bar.style.width = `${pct}%`;
|
|
671
|
+
if (th > 0 && pct >= 100) {
|
|
672
|
+
sub.textContent = el.reward_text || "Unlocked!";
|
|
673
|
+
sub.style.color = "#10b981";
|
|
674
|
+
sub.style.fontWeight = "700";
|
|
675
|
+
if (!firedUnlock) {
|
|
676
|
+
firedUnlock = true;
|
|
677
|
+
trackEvent(campaign.id, "clicked", { stepId: el.id || "unlocked" });
|
|
678
|
+
if (el.celebrate_on_complete !== false) (_a = ctx.playReaction) == null ? void 0 : _a.call(ctx, wrap, "celebrate");
|
|
679
|
+
}
|
|
680
|
+
} else {
|
|
681
|
+
sub.style.color = muted;
|
|
682
|
+
sub.style.fontWeight = "";
|
|
683
|
+
firedUnlock = false;
|
|
684
|
+
const remaining = Math.max(0, th - cur);
|
|
685
|
+
const pre = moneyGoal ? sym() : "";
|
|
686
|
+
const pctStr = el.show_pct && th > 0 ? ` · ${Math.round(pct)}%` : "";
|
|
687
|
+
sub.textContent = th > 0 ? `Shop for ${pre}${remaining.toFixed(0)} more${pctStr}` : el.reward_text || "";
|
|
688
|
+
}
|
|
689
|
+
};
|
|
690
|
+
update();
|
|
691
|
+
const timer = setInterval(update, 1e3);
|
|
692
|
+
if (typeof window !== "undefined") {
|
|
693
|
+
window.addEventListener("beforeunload", () => clearInterval(timer), { once: true });
|
|
694
|
+
}
|
|
695
|
+
return wrap;
|
|
696
|
+
}
|
|
697
|
+
function renderCardFromTemplate(card, opts) {
|
|
698
|
+
const { ctx, action, layout, layoutAccent } = opts;
|
|
699
|
+
const inline = action === "cart";
|
|
700
|
+
const { campaign, trackEvent, sanitizeUrl, sanitizeColor } = ctx;
|
|
701
|
+
const tpl = applyPerCardOverride(opts.template, asLook(card.style));
|
|
702
|
+
const frame = tpl.frame || {};
|
|
703
|
+
const meta = card.metadata || {};
|
|
704
|
+
const accent = typeof frame.accent === "string" && frame.accent ? sanitizeColor(frame.accent) : layoutAccent;
|
|
705
|
+
const brand = `var(--aegis-brand-accent, ${accent})`;
|
|
706
|
+
const fg = contrastFg(frame.bg ? sanitizeColor(frame.bg) : "#ffffff");
|
|
707
|
+
const muted = fg === "#ffffff" ? "rgba(255,255,255,0.72)" : "#6b7280";
|
|
708
|
+
const tile = document.createElement("div");
|
|
709
|
+
const radius = frame.radius !== void 0 ? `${parseInt(String(frame.radius), 10) || 12}px` : "12px";
|
|
710
|
+
const fLayout = frame.layout;
|
|
711
|
+
const dir = fLayout === "row" ? "row" : "column";
|
|
712
|
+
const tileGap = frame.gap != null ? frame.gap : 6;
|
|
713
|
+
const sizing = fLayout ? frame.width != null ? `width:${typeof frame.width === "number" ? `${frame.width}px` : frame.width};` : "flex:1 1 auto; width:100%;" : layout === "grid" ? "" : "flex:0 0 150px; scroll-snap-align:start;";
|
|
714
|
+
tile.style.cssText = `
|
|
715
|
+
box-sizing:border-box; display:flex; flex-direction:${dir}; ${fLayout === "row" ? "align-items:center;" : ""} gap:${tileGap}px; position:relative;
|
|
716
|
+
color:${fg};
|
|
717
|
+
background:${frame.bg ? sanitizeColor(frame.bg) : "#ffffff"};
|
|
718
|
+
border:1px solid ${frame.border ? sanitizeColor(frame.border) : "transparent"};
|
|
719
|
+
border-radius:${radius}; padding:8px;
|
|
720
|
+
${frame.max_width ? `max-width:${frame.max_width}px;` : ""}${frame.min_width ? `min-width:${frame.min_width}px;` : ""}
|
|
721
|
+
${frame.height ? `height:${frame.height}px;` : ""}${frame.min_height ? `min-height:${frame.min_height}px;` : ""}
|
|
722
|
+
${sizing}
|
|
723
|
+
cursor:${card.cta_url || inline ? "pointer" : "default"}; transition:transform 0.15s ease;
|
|
724
|
+
`;
|
|
725
|
+
const elements = tpl.elements && tpl.elements.length ? tpl.elements : DEFAULT_CARD_TEMPLATE.elements;
|
|
726
|
+
let imageWrap = null;
|
|
727
|
+
const paintInto = (container, els) => {
|
|
728
|
+
for (const el of els) {
|
|
729
|
+
switch (el.type) {
|
|
730
|
+
case "image": {
|
|
731
|
+
const wrap = document.createElement("div");
|
|
732
|
+
wrap.style.cssText = `position:relative;width:100%;aspect-ratio:${ASPECT$2[el.aspect || "1/1"] || "1 / 1"};border-radius:${el.radius ?? 10}px;overflow:hidden;background:#f7f8fa;`;
|
|
733
|
+
const safeVideo = card.video_url ? sanitizeUrl(card.video_url) : "";
|
|
734
|
+
if (safeVideo) {
|
|
735
|
+
const v = document.createElement("video");
|
|
736
|
+
v.src = safeVideo;
|
|
737
|
+
v.muted = true;
|
|
738
|
+
v.loop = true;
|
|
739
|
+
v.autoplay = true;
|
|
740
|
+
v.playsInline = true;
|
|
741
|
+
v.setAttribute("playsinline", "");
|
|
742
|
+
v.style.cssText = "width:100%;height:100%;object-fit:cover;display:block;";
|
|
743
|
+
wrap.appendChild(v);
|
|
744
|
+
} else if (card.image_url) {
|
|
745
|
+
const safe = sanitizeUrl(card.image_url);
|
|
746
|
+
if (safe) {
|
|
747
|
+
const img = document.createElement("img");
|
|
748
|
+
img.src = safe;
|
|
749
|
+
img.alt = "";
|
|
750
|
+
img.loading = "lazy";
|
|
751
|
+
img.style.cssText = "width:100%;height:100%;object-fit:cover;display:block;";
|
|
752
|
+
wrap.appendChild(img);
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
imageWrap = wrap;
|
|
756
|
+
container.appendChild(wrap);
|
|
757
|
+
break;
|
|
758
|
+
}
|
|
759
|
+
case "badge": {
|
|
760
|
+
const text = el.text;
|
|
761
|
+
if (!text) break;
|
|
762
|
+
const badge = document.createElement("span");
|
|
763
|
+
badge.textContent = text;
|
|
764
|
+
const bg = el.color ? sanitizeColor(el.color) : brand;
|
|
765
|
+
badge.style.cssText = `position:absolute;top:6px;left:6px;z-index:1;background:${bg};color:#fff;font-size:9px;font-weight:800;text-transform:uppercase;letter-spacing:0.03em;padding:3px 6px;border-radius:5px;`;
|
|
766
|
+
(imageWrap || container).appendChild(badge);
|
|
767
|
+
break;
|
|
768
|
+
}
|
|
769
|
+
case "price": {
|
|
770
|
+
const node = paintPrice(card, el, accent, ctx);
|
|
771
|
+
if (node) container.appendChild(node);
|
|
772
|
+
break;
|
|
773
|
+
}
|
|
774
|
+
case "title": {
|
|
775
|
+
if (!card.title) break;
|
|
776
|
+
const t = document.createElement("div");
|
|
777
|
+
t.textContent = card.title;
|
|
778
|
+
const lines = el.lines && el.lines > 0 ? el.lines : 2;
|
|
779
|
+
t.style.cssText = `font-size:12.5px;font-weight:600;line-height:1.3;text-align:${el.align ?? "left"};color:${el.color ? sanitizeColor(el.color) : fg};display:-webkit-box;-webkit-line-clamp:${lines};-webkit-box-orient:vertical;overflow:hidden;`;
|
|
780
|
+
container.appendChild(t);
|
|
781
|
+
break;
|
|
782
|
+
}
|
|
783
|
+
case "subtitle": {
|
|
784
|
+
if (!card.body) break;
|
|
785
|
+
const s = document.createElement("div");
|
|
786
|
+
s.textContent = card.body;
|
|
787
|
+
const lines = el.lines && el.lines > 0 ? el.lines : 2;
|
|
788
|
+
s.style.cssText = `font-size:11px;color:${el.color ? sanitizeColor(el.color) : muted};line-height:1.3;text-align:${el.align ?? "left"};display:-webkit-box;-webkit-line-clamp:${lines};-webkit-box-orient:vertical;overflow:hidden;`;
|
|
789
|
+
container.appendChild(s);
|
|
790
|
+
break;
|
|
791
|
+
}
|
|
792
|
+
case "rating": {
|
|
793
|
+
const node = paintRating(card);
|
|
794
|
+
if (node) container.appendChild(node);
|
|
795
|
+
break;
|
|
796
|
+
}
|
|
797
|
+
case "category": {
|
|
798
|
+
const cat = meta.category;
|
|
799
|
+
if (typeof cat !== "string" || !cat) break;
|
|
800
|
+
const chip = document.createElement("span");
|
|
801
|
+
chip.textContent = cat;
|
|
802
|
+
chip.style.cssText = "align-self:flex-start;background:#f3f4f6;color:#6b7280;font-size:10px;font-weight:500;padding:2px 7px;border-radius:6px;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;";
|
|
803
|
+
container.appendChild(chip);
|
|
804
|
+
break;
|
|
805
|
+
}
|
|
806
|
+
// ── rich-card-editor elements (P0) ──────────────────────────────────
|
|
807
|
+
case "icon": {
|
|
808
|
+
const px = ICON_PX[el.size || "md"] || 30;
|
|
809
|
+
const node = document.createElement("div");
|
|
810
|
+
const iconColor = el.color ? sanitizeColor(el.color) : fg;
|
|
811
|
+
if (el.bubble) {
|
|
812
|
+
const bubbleTint = el.color ? sanitizeColor(el.color) : brand;
|
|
813
|
+
node.style.cssText = `flex:0 0 auto;width:${px}px;height:${px}px;border-radius:999px;display:flex;align-items:center;justify-content:center;background:color-mix(in srgb, ${bubbleTint} 16%, transparent);`;
|
|
814
|
+
} else {
|
|
815
|
+
node.style.cssText = "flex:0 0 auto;display:flex;align-items:center;";
|
|
816
|
+
}
|
|
817
|
+
const svg = lucideSvgEl(el.icon_name || "circle-check", {
|
|
818
|
+
size: el.bubble ? Math.round(px * 0.55) : Math.round(px * 0.7),
|
|
819
|
+
color: iconColor,
|
|
820
|
+
strokeWidth: 2
|
|
821
|
+
});
|
|
822
|
+
if (svg) node.appendChild(svg);
|
|
823
|
+
container.appendChild(node);
|
|
824
|
+
break;
|
|
825
|
+
}
|
|
826
|
+
case "text": {
|
|
827
|
+
const t = document.createElement("div");
|
|
828
|
+
const fs = TEXT_PX[el.size || "md"] || 13;
|
|
829
|
+
t.style.cssText = `font-size:${fs}px;font-weight:${WEIGHT[el.weight ?? "medium"]};text-align:${el.align ?? "left"};color:${el.color ? sanitizeColor(el.color) : fg};line-height:1.25;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0;`;
|
|
830
|
+
t.textContent = interpolateTokens(el.content ?? "", ctx);
|
|
831
|
+
container.appendChild(t);
|
|
832
|
+
break;
|
|
833
|
+
}
|
|
834
|
+
case "spacer": {
|
|
835
|
+
const sp = document.createElement("div");
|
|
836
|
+
sp.style.height = `${el.height ?? 8}px`;
|
|
837
|
+
container.appendChild(sp);
|
|
838
|
+
break;
|
|
839
|
+
}
|
|
840
|
+
case "progress": {
|
|
841
|
+
container.appendChild(buildProgressElement(el, ctx, brand, muted));
|
|
842
|
+
break;
|
|
843
|
+
}
|
|
844
|
+
case "countdown": {
|
|
845
|
+
const cd = buildCountdownElement(el, fg, muted);
|
|
846
|
+
if (cd) container.appendChild(cd);
|
|
847
|
+
break;
|
|
848
|
+
}
|
|
849
|
+
case "rating_input": {
|
|
850
|
+
container.appendChild(buildRatingInputElement(el, ctx, fg));
|
|
851
|
+
break;
|
|
852
|
+
}
|
|
853
|
+
case "poll": {
|
|
854
|
+
const p = buildPollElement(el, ctx, fg, brand);
|
|
855
|
+
if (p) container.appendChild(p);
|
|
856
|
+
break;
|
|
857
|
+
}
|
|
858
|
+
case "nps": {
|
|
859
|
+
container.appendChild(buildNpsElement(el, ctx, fg, brand, muted));
|
|
860
|
+
break;
|
|
861
|
+
}
|
|
862
|
+
case "group": {
|
|
863
|
+
const g = document.createElement("div");
|
|
864
|
+
const gdir = el.layout === "row" ? "row" : "column";
|
|
865
|
+
g.style.cssText = `display:flex;flex-direction:${gdir};${el.layout === "row" ? "align-items:center;" : ""}gap:${el.gap ?? 4}px;min-width:0;${el.layout === "row" ? "" : "flex:1 1 auto;"}`;
|
|
866
|
+
paintInto(g, el.elements || []);
|
|
867
|
+
container.appendChild(g);
|
|
868
|
+
break;
|
|
869
|
+
}
|
|
870
|
+
case "cta": {
|
|
871
|
+
const label = el.text || card.cta_text || (inline ? "Add" : "Shop");
|
|
872
|
+
const cta = document.createElement("button");
|
|
873
|
+
cta.className = "aegis-cta";
|
|
874
|
+
cta.textContent = label;
|
|
875
|
+
const overlayOnImage = !!el.overlay && !!imageWrap;
|
|
876
|
+
if (overlayOnImage) {
|
|
877
|
+
cta.style.cssText = el.variant === "outline" ? `position:absolute;right:6px;bottom:6px;background:#fff;color:${brand};border:1px solid ${brand};border-radius:9px;padding:5px 18px;font-size:12px;font-weight:800;text-transform:uppercase;letter-spacing:0.04em;cursor:pointer;box-shadow:0 2px 6px rgba(0,0,0,0.14);` : `position:absolute;right:6px;bottom:6px;background:${brand};color:#fff;border:none;border-radius:9px;padding:5px 18px;font-size:12px;font-weight:800;text-transform:uppercase;letter-spacing:0.04em;cursor:pointer;box-shadow:0 2px 6px rgba(0,0,0,0.14);`;
|
|
878
|
+
} else {
|
|
879
|
+
cta.style.cssText = el.variant === "outline" ? `margin-top:${fLayout === "row" ? "0" : "auto"};background:transparent;color:${brand};border:1px solid ${brand};border-radius:999px;padding:6px 10px;font-size:12px;font-weight:700;cursor:pointer;white-space:nowrap;` : `margin-top:${fLayout === "row" ? "0" : "auto"};background:${brand};color:#fff;border:none;border-radius:999px;padding:7px 10px;font-size:12px;font-weight:700;cursor:pointer;white-space:nowrap;`;
|
|
880
|
+
}
|
|
881
|
+
cta.addEventListener("click", (e) => {
|
|
882
|
+
e.stopPropagation();
|
|
883
|
+
trackEvent(campaign.id, "clicked", { stepId: el.id || "add" });
|
|
884
|
+
if (inline) {
|
|
885
|
+
if (typeof window !== "undefined") {
|
|
886
|
+
window.dispatchEvent(
|
|
887
|
+
new CustomEvent("aegis:add-to-cart", {
|
|
888
|
+
detail: {
|
|
889
|
+
campaign_id: campaign.id,
|
|
890
|
+
product_id: meta.product_id,
|
|
891
|
+
sku: meta.sku,
|
|
892
|
+
title: card.title,
|
|
893
|
+
price: meta.price ?? card.body,
|
|
894
|
+
image_url: card.image_url,
|
|
895
|
+
cta_url: card.cta_url
|
|
896
|
+
}
|
|
897
|
+
})
|
|
898
|
+
);
|
|
899
|
+
}
|
|
900
|
+
return;
|
|
901
|
+
}
|
|
902
|
+
if (card.cta_url) {
|
|
903
|
+
const safe = sanitizeUrl(card.cta_url);
|
|
904
|
+
if (safe) ctx.navigate ? ctx.navigate(safe) : window.location.href = safe;
|
|
905
|
+
}
|
|
906
|
+
});
|
|
907
|
+
(overlayOnImage ? imageWrap : container).appendChild(cta);
|
|
908
|
+
break;
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
};
|
|
913
|
+
paintInto(tile, elements);
|
|
914
|
+
const open = (e) => {
|
|
915
|
+
e.stopPropagation();
|
|
916
|
+
trackEvent(campaign.id, "clicked");
|
|
917
|
+
if (inline) {
|
|
918
|
+
if (typeof window !== "undefined") {
|
|
919
|
+
window.dispatchEvent(
|
|
920
|
+
new CustomEvent("aegis:open-product", {
|
|
921
|
+
detail: {
|
|
922
|
+
campaign_id: campaign.id,
|
|
923
|
+
product_id: meta.product_id,
|
|
924
|
+
sku: meta.sku,
|
|
925
|
+
cta_url: card.cta_url
|
|
926
|
+
}
|
|
927
|
+
})
|
|
928
|
+
);
|
|
929
|
+
}
|
|
930
|
+
return;
|
|
931
|
+
}
|
|
932
|
+
if (card.cta_url) {
|
|
933
|
+
const safe = sanitizeUrl(card.cta_url);
|
|
934
|
+
if (safe) ctx.navigate ? ctx.navigate(safe) : window.location.href = safe;
|
|
935
|
+
}
|
|
936
|
+
};
|
|
937
|
+
if (inline || card.cta_url) tile.addEventListener("click", open);
|
|
938
|
+
return tile;
|
|
939
|
+
}
|
|
28
940
|
const MAX_CARDS_RENDERED = 10;
|
|
29
941
|
function renderCarouselCards(ctx) {
|
|
30
|
-
const { campaign, trackEvent,
|
|
942
|
+
const { campaign, trackEvent, sanitizeColor, log, addAnimationStyles } = ctx;
|
|
31
943
|
const ic = campaign.interactive_config || {};
|
|
32
944
|
const rawCards = Array.isArray(ic.cards) ? ic.cards : [];
|
|
33
945
|
const cards = rawCards.slice(0, MAX_CARDS_RENDERED);
|
|
@@ -70,7 +982,7 @@ function renderCarouselCards(ctx) {
|
|
|
70
982
|
headerText.appendChild(body);
|
|
71
983
|
header.appendChild(headerText);
|
|
72
984
|
const closeBtn = document.createElement("button");
|
|
73
|
-
closeBtn.
|
|
985
|
+
closeBtn.innerHTML = lucideSvg("x", { size: 16 });
|
|
74
986
|
closeBtn.setAttribute("aria-label", "Close");
|
|
75
987
|
closeBtn.style.cssText = `
|
|
76
988
|
background: transparent; border: none; color: inherit;
|
|
@@ -89,68 +1001,16 @@ function renderCarouselCards(ctx) {
|
|
|
89
1001
|
padding-bottom: 4px; -webkit-overflow-scrolling: touch;
|
|
90
1002
|
`;
|
|
91
1003
|
track.style.msOverflowStyle = "none";
|
|
1004
|
+
const template = resolveGlobalTemplate(ic);
|
|
92
1005
|
cards.forEach((c, i) => {
|
|
93
|
-
const tile =
|
|
1006
|
+
const tile = renderCardFromTemplate(c, {
|
|
1007
|
+
template,
|
|
1008
|
+
ctx,
|
|
1009
|
+
action: "navigate",
|
|
1010
|
+
layout: "row",
|
|
1011
|
+
layoutAccent: accent
|
|
1012
|
+
});
|
|
94
1013
|
tile.setAttribute("data-card-index", String(i));
|
|
95
|
-
tile.style.cssText = `
|
|
96
|
-
flex: 0 0 auto; width: 140px; scroll-snap-align: start;
|
|
97
|
-
background: ${fg}0a; border-radius: 12px; padding: 10px;
|
|
98
|
-
display: flex; flex-direction: column; gap: 6px;
|
|
99
|
-
cursor: ${c.cta_url ? "pointer" : "default"};
|
|
100
|
-
`;
|
|
101
|
-
const safeVideo = c.video_url ? sanitizeUrl(c.video_url) : "";
|
|
102
|
-
if (safeVideo) {
|
|
103
|
-
const vid = document.createElement("video");
|
|
104
|
-
vid.src = safeVideo;
|
|
105
|
-
vid.muted = true;
|
|
106
|
-
vid.loop = true;
|
|
107
|
-
vid.autoplay = true;
|
|
108
|
-
vid.playsInline = true;
|
|
109
|
-
vid.setAttribute("playsinline", "");
|
|
110
|
-
vid.style.cssText = "width: 100%; height: 96px; border-radius: 8px; object-fit: cover;";
|
|
111
|
-
tile.appendChild(vid);
|
|
112
|
-
} else if (c.image_url) {
|
|
113
|
-
const img = document.createElement("img");
|
|
114
|
-
const safe = sanitizeUrl(c.image_url);
|
|
115
|
-
if (safe) {
|
|
116
|
-
img.src = safe;
|
|
117
|
-
img.alt = "";
|
|
118
|
-
img.loading = "lazy";
|
|
119
|
-
img.style.cssText = "width: 100%; height: 96px; border-radius: 8px; object-fit: cover;";
|
|
120
|
-
tile.appendChild(img);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
if (c.title) {
|
|
124
|
-
const t = document.createElement("div");
|
|
125
|
-
t.textContent = c.title;
|
|
126
|
-
t.style.cssText = "font-weight: 600; font-size: 13px; line-height: 1.3;";
|
|
127
|
-
tile.appendChild(t);
|
|
128
|
-
}
|
|
129
|
-
if (c.body) {
|
|
130
|
-
const b = document.createElement("div");
|
|
131
|
-
b.textContent = c.body;
|
|
132
|
-
b.style.cssText = "font-size: 11.5px; opacity: 0.72; line-height: 1.3;";
|
|
133
|
-
tile.appendChild(b);
|
|
134
|
-
}
|
|
135
|
-
if (c.cta_text && c.cta_url) {
|
|
136
|
-
const cta = document.createElement("button");
|
|
137
|
-
cta.className = "aegis-cta";
|
|
138
|
-
cta.textContent = c.cta_text;
|
|
139
|
-
cta.style.cssText = `
|
|
140
|
-
margin-top: auto; background: ${accent}; color: #fff;
|
|
141
|
-
border: none; padding: 6px 10px; border-radius: 999px;
|
|
142
|
-
font-size: 12px; font-weight: 600; cursor: pointer;
|
|
143
|
-
`;
|
|
144
|
-
const goto2 = (e) => {
|
|
145
|
-
e.stopPropagation();
|
|
146
|
-
trackEvent(campaign.id, "clicked", { stepId: `card_${i}` });
|
|
147
|
-
const safe = sanitizeUrl(c.cta_url);
|
|
148
|
-
if (safe) window.location.href = safe;
|
|
149
|
-
};
|
|
150
|
-
cta.addEventListener("click", goto2);
|
|
151
|
-
tile.appendChild(cta);
|
|
152
|
-
tile.addEventListener("click", goto2);
|
|
153
|
-
}
|
|
154
1014
|
track.appendChild(tile);
|
|
155
1015
|
});
|
|
156
1016
|
card.appendChild(track);
|
|
@@ -314,7 +1174,7 @@ function renderStickyBar(ctx) {
|
|
|
314
1174
|
};
|
|
315
1175
|
if (dismissible) {
|
|
316
1176
|
const close = document.createElement("button");
|
|
317
|
-
close.
|
|
1177
|
+
close.innerHTML = lucideSvg("x", { size: 16 });
|
|
318
1178
|
close.setAttribute("aria-label", "Dismiss");
|
|
319
1179
|
close.style.cssText = `
|
|
320
1180
|
background: transparent; border: none; color: inherit;
|
|
@@ -344,13 +1204,12 @@ function buildProgressBar(ctx, inline) {
|
|
|
344
1204
|
const source = ic.progress_source === "sse" ? "sse" : "client";
|
|
345
1205
|
addAnimationStyles();
|
|
346
1206
|
const brand = sanitizeColor(campaign.background_color || "#4169e1");
|
|
1207
|
+
const accentVar = `var(--aegis-brand-accent, ${brand})`;
|
|
347
1208
|
const branded = ic.surface_style === "branded";
|
|
348
|
-
const bg = branded ?
|
|
1209
|
+
const bg = branded ? accentVar : "#ffffff";
|
|
349
1210
|
const fg = sanitizeColor(campaign.text_color || (branded ? "#ffffff" : "#0f172a"));
|
|
350
|
-
const fill = sanitizeColor(
|
|
351
|
-
|
|
352
|
-
);
|
|
353
|
-
const track = branded ? "rgba(255,255,255,0.25)" : `${fill}22`;
|
|
1211
|
+
const fill = ic.progress_fill_color ? sanitizeColor(ic.progress_fill_color) : branded ? "#ffffff" : accentVar;
|
|
1212
|
+
const track = branded ? "rgba(255,255,255,0.25)" : `color-mix(in srgb, ${fill} 14%, transparent)`;
|
|
354
1213
|
const bar = document.createElement("div");
|
|
355
1214
|
bar.className = "aegis-in-app-progress-bar";
|
|
356
1215
|
bar.setAttribute("data-campaign-id", campaign.id);
|
|
@@ -730,7 +1589,7 @@ function renderCoachmarkTour(ctx) {
|
|
|
730
1589
|
}
|
|
731
1590
|
const MAX_PRODUCTS = 24;
|
|
732
1591
|
function renderProductRecommendation(ctx) {
|
|
733
|
-
const { campaign, trackEvent,
|
|
1592
|
+
const { campaign, trackEvent, sanitizeColor, log, addAnimationStyles } = ctx;
|
|
734
1593
|
const ic = campaign.interactive_config || {};
|
|
735
1594
|
const rawCards = Array.isArray(ic.cards) ? ic.cards : [];
|
|
736
1595
|
const cards = rawCards.slice(0, MAX_PRODUCTS);
|
|
@@ -739,7 +1598,7 @@ function renderProductRecommendation(ctx) {
|
|
|
739
1598
|
return;
|
|
740
1599
|
}
|
|
741
1600
|
const layout = ic.rec_layout || "grid";
|
|
742
|
-
const
|
|
1601
|
+
const template = resolveGlobalTemplate(ic);
|
|
743
1602
|
addAnimationStyles();
|
|
744
1603
|
const bg = "#ffffff";
|
|
745
1604
|
const fg = "#0f172a";
|
|
@@ -782,7 +1641,7 @@ function renderProductRecommendation(ctx) {
|
|
|
782
1641
|
headerText.appendChild(body);
|
|
783
1642
|
header.appendChild(headerText);
|
|
784
1643
|
const close = document.createElement("button");
|
|
785
|
-
close.
|
|
1644
|
+
close.innerHTML = lucideSvg("x", { size: 18 });
|
|
786
1645
|
close.setAttribute("aria-label", "Close");
|
|
787
1646
|
close.style.cssText = `
|
|
788
1647
|
background: transparent; border: none; color: inherit;
|
|
@@ -807,82 +1666,9 @@ function renderProductRecommendation(ctx) {
|
|
|
807
1666
|
`;
|
|
808
1667
|
}
|
|
809
1668
|
cards.forEach((c) => {
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
background: ${fg}08; border-radius: 12px;
|
|
814
|
-
padding: 10px; display: flex; flex-direction: column; gap: 6px;
|
|
815
|
-
cursor: ${c.cta_url ? "pointer" : "default"};
|
|
816
|
-
${isRow ? "flex: 0 0 150px; scroll-snap-align: start;" : ""}
|
|
817
|
-
transition: transform 0.15s ease;
|
|
818
|
-
`;
|
|
819
|
-
if (c.image_url) {
|
|
820
|
-
const img = document.createElement("img");
|
|
821
|
-
const safe = sanitizeUrl(c.image_url);
|
|
822
|
-
if (safe) {
|
|
823
|
-
img.src = safe;
|
|
824
|
-
img.alt = "";
|
|
825
|
-
img.loading = "lazy";
|
|
826
|
-
img.style.cssText = "width: 100%; aspect-ratio: 1 / 1; border-radius: 8px; object-fit: cover;";
|
|
827
|
-
tile.appendChild(img);
|
|
828
|
-
}
|
|
829
|
-
}
|
|
830
|
-
if (c.title) {
|
|
831
|
-
const t = document.createElement("div");
|
|
832
|
-
t.textContent = c.title;
|
|
833
|
-
t.style.cssText = "font-weight: 600; font-size: 13px; line-height: 1.3;";
|
|
834
|
-
tile.appendChild(t);
|
|
835
|
-
}
|
|
836
|
-
const meta = c.metadata && typeof c.metadata === "object" ? c.metadata : {};
|
|
837
|
-
const price = meta.price;
|
|
838
|
-
const compareAt = meta.compare_at_price ?? meta.compare_at ?? meta.original_price;
|
|
839
|
-
if (price !== void 0) {
|
|
840
|
-
const priceRow = document.createElement("div");
|
|
841
|
-
priceRow.style.cssText = "display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap;";
|
|
842
|
-
const p = document.createElement("span");
|
|
843
|
-
p.textContent = String(price);
|
|
844
|
-
p.style.cssText = `color: ${accent}; font-weight: 700; font-size: 13px;`;
|
|
845
|
-
priceRow.appendChild(p);
|
|
846
|
-
const pNum = parseFloat(String(price).replace(/[^0-9.]/g, ""));
|
|
847
|
-
const cNum = compareAt !== void 0 ? parseFloat(String(compareAt).replace(/[^0-9.]/g, "")) : NaN;
|
|
848
|
-
if (isFinite(cNum) && isFinite(pNum) && cNum > pNum) {
|
|
849
|
-
const orig = document.createElement("span");
|
|
850
|
-
orig.textContent = String(compareAt);
|
|
851
|
-
orig.style.cssText = "text-decoration: line-through; opacity: 0.5; font-size: 11px;";
|
|
852
|
-
priceRow.appendChild(orig);
|
|
853
|
-
const off = document.createElement("span");
|
|
854
|
-
off.textContent = `-${Math.round((1 - pNum / cNum) * 100)}%`;
|
|
855
|
-
off.style.cssText = "background: #ef444422; color: #ef4444; font-weight: 700; font-size: 10px; padding: 1px 5px; border-radius: 999px;";
|
|
856
|
-
priceRow.appendChild(off);
|
|
857
|
-
}
|
|
858
|
-
tile.appendChild(priceRow);
|
|
859
|
-
} else if (c.body) {
|
|
860
|
-
const b = document.createElement("div");
|
|
861
|
-
b.textContent = c.body;
|
|
862
|
-
b.style.cssText = "font-size: 11.5px; opacity: 0.72; line-height: 1.3;";
|
|
863
|
-
tile.appendChild(b);
|
|
864
|
-
}
|
|
865
|
-
const cta = document.createElement("button");
|
|
866
|
-
cta.className = "aegis-cta";
|
|
867
|
-
cta.textContent = c.cta_text || ctaDefault;
|
|
868
|
-
cta.style.cssText = `
|
|
869
|
-
margin-top: auto;
|
|
870
|
-
background: ${accent}; color: #fff;
|
|
871
|
-
border: none; padding: 7px 10px; border-radius: 999px;
|
|
872
|
-
font-size: 12px; font-weight: 600; cursor: pointer;
|
|
873
|
-
`;
|
|
874
|
-
const go = (e) => {
|
|
875
|
-
e.stopPropagation();
|
|
876
|
-
trackEvent(campaign.id, "clicked");
|
|
877
|
-
if (c.cta_url) {
|
|
878
|
-
const safe = sanitizeUrl(c.cta_url);
|
|
879
|
-
if (safe) window.location.href = safe;
|
|
880
|
-
}
|
|
881
|
-
};
|
|
882
|
-
cta.addEventListener("click", go);
|
|
883
|
-
tile.appendChild(cta);
|
|
884
|
-
if (c.cta_url) tile.addEventListener("click", go);
|
|
885
|
-
grid.appendChild(tile);
|
|
1669
|
+
grid.appendChild(
|
|
1670
|
+
renderCardFromTemplate(c, { template, ctx, action: "navigate", layout, layoutAccent: accent })
|
|
1671
|
+
);
|
|
886
1672
|
});
|
|
887
1673
|
sheet.appendChild(grid);
|
|
888
1674
|
overlay.appendChild(sheet);
|
|
@@ -894,6 +1680,88 @@ function renderProductRecommendation(ctx) {
|
|
|
894
1680
|
});
|
|
895
1681
|
document.body.appendChild(overlay);
|
|
896
1682
|
}
|
|
1683
|
+
function renderProductRecommendationInline(ctx, target) {
|
|
1684
|
+
const { campaign, sanitizeColor, addAnimationStyles, log } = ctx;
|
|
1685
|
+
const ic = campaign.interactive_config || {};
|
|
1686
|
+
const rawCards = Array.isArray(ic.cards) ? ic.cards : [];
|
|
1687
|
+
const cards = rawCards.slice(0, MAX_PRODUCTS);
|
|
1688
|
+
if (cards.length === 0) {
|
|
1689
|
+
log("product_recommendation (inline) rendered with zero products — skipping", "warn");
|
|
1690
|
+
return false;
|
|
1691
|
+
}
|
|
1692
|
+
const layout = ic.rec_layout || "row";
|
|
1693
|
+
const template = resolveGlobalTemplate(ic);
|
|
1694
|
+
const fg = "#0f172a";
|
|
1695
|
+
const accent = sanitizeColor(campaign.background_color || "#4169e1");
|
|
1696
|
+
addAnimationStyles();
|
|
1697
|
+
const section = document.createElement("section");
|
|
1698
|
+
section.className = "aegis-in-app-product-rec-inline";
|
|
1699
|
+
section.setAttribute("data-campaign-id", campaign.id);
|
|
1700
|
+
section.style.cssText = `
|
|
1701
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
1702
|
+
color: ${fg};
|
|
1703
|
+
`;
|
|
1704
|
+
if (campaign.title) {
|
|
1705
|
+
const title = document.createElement("h2");
|
|
1706
|
+
title.textContent = campaign.title;
|
|
1707
|
+
title.style.cssText = "font-weight: 700; font-size: 16px; margin: 0 0 2px;";
|
|
1708
|
+
section.appendChild(title);
|
|
1709
|
+
}
|
|
1710
|
+
if (campaign.body) {
|
|
1711
|
+
const body = document.createElement("div");
|
|
1712
|
+
body.textContent = campaign.body;
|
|
1713
|
+
body.style.cssText = "font-size: 13px; opacity: 0.65; line-height: 1.4; margin-bottom: 10px;";
|
|
1714
|
+
section.appendChild(body);
|
|
1715
|
+
}
|
|
1716
|
+
const grid = document.createElement("div");
|
|
1717
|
+
const isRow = layout !== "grid";
|
|
1718
|
+
if (layout === "grid") {
|
|
1719
|
+
grid.style.cssText = "display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px;";
|
|
1720
|
+
} else {
|
|
1721
|
+
grid.style.cssText = `
|
|
1722
|
+
display: flex; gap: 10px; overflow-x: auto;
|
|
1723
|
+
scroll-snap-type: x proximity; padding: 0 0 6px;
|
|
1724
|
+
-webkit-overflow-scrolling: touch; scrollbar-width: none;
|
|
1725
|
+
`;
|
|
1726
|
+
grid.style.msOverflowStyle = "none";
|
|
1727
|
+
}
|
|
1728
|
+
cards.forEach((c) => {
|
|
1729
|
+
grid.appendChild(
|
|
1730
|
+
renderCardFromTemplate(c, { template, ctx, action: "cart", layout, layoutAccent: accent })
|
|
1731
|
+
);
|
|
1732
|
+
});
|
|
1733
|
+
if (isRow && cards.length > 2) {
|
|
1734
|
+
const wrap = document.createElement("div");
|
|
1735
|
+
wrap.style.cssText = "position: relative;";
|
|
1736
|
+
wrap.appendChild(grid);
|
|
1737
|
+
const arrow = document.createElement("button");
|
|
1738
|
+
arrow.setAttribute("aria-label", "Scroll for more");
|
|
1739
|
+
arrow.innerHTML = "›";
|
|
1740
|
+
arrow.style.cssText = `
|
|
1741
|
+
position: absolute; top: 50%; right: 0; transform: translateY(-50%);
|
|
1742
|
+
width: 30px; height: 30px; border-radius: 999px; border: 1px solid ${fg}1a;
|
|
1743
|
+
background: #fff; color: ${fg}; font-size: 18px; line-height: 1; cursor: pointer;
|
|
1744
|
+
box-shadow: 0 2px 8px rgba(0,0,0,0.12); display: flex; align-items: center;
|
|
1745
|
+
justify-content: center; z-index: 2;
|
|
1746
|
+
`;
|
|
1747
|
+
arrow.addEventListener("click", (e) => {
|
|
1748
|
+
e.stopPropagation();
|
|
1749
|
+
grid.scrollBy({ left: Math.round(grid.clientWidth * 0.8), behavior: "smooth" });
|
|
1750
|
+
});
|
|
1751
|
+
const syncArrow = () => {
|
|
1752
|
+
const atEnd = grid.scrollLeft + grid.clientWidth >= grid.scrollWidth - 8;
|
|
1753
|
+
arrow.style.display = atEnd ? "none" : "flex";
|
|
1754
|
+
};
|
|
1755
|
+
grid.addEventListener("scroll", syncArrow, { passive: true });
|
|
1756
|
+
setTimeout(syncArrow, 0);
|
|
1757
|
+
wrap.appendChild(arrow);
|
|
1758
|
+
section.appendChild(wrap);
|
|
1759
|
+
} else {
|
|
1760
|
+
section.appendChild(grid);
|
|
1761
|
+
}
|
|
1762
|
+
target.appendChild(section);
|
|
1763
|
+
return true;
|
|
1764
|
+
}
|
|
897
1765
|
const MAX_GROUPS = 12;
|
|
898
1766
|
const MAX_FRAMES = 20;
|
|
899
1767
|
const DEFAULT_DURATION_MS = 5e3;
|
|
@@ -997,7 +1865,7 @@ function renderLauncherBar(ctx, cfg, target) {
|
|
|
997
1865
|
if (floating) {
|
|
998
1866
|
const dismiss = document.createElement("button");
|
|
999
1867
|
dismiss.type = "button";
|
|
1000
|
-
dismiss.
|
|
1868
|
+
dismiss.innerHTML = lucideSvg("x", { size: 14 });
|
|
1001
1869
|
dismiss.setAttribute("aria-label", "Dismiss stories");
|
|
1002
1870
|
dismiss.style.cssText = `
|
|
1003
1871
|
flex: 0 0 auto; align-self: center; margin-left: auto;
|
|
@@ -1141,7 +2009,7 @@ function openViewer(ctx, cfg, startGroupIndex, startFrameIndex = 0) {
|
|
|
1141
2009
|
};
|
|
1142
2010
|
const close = document.createElement("button");
|
|
1143
2011
|
close.type = "button";
|
|
1144
|
-
close.
|
|
2012
|
+
close.innerHTML = lucideSvg("x", { size: 18 });
|
|
1145
2013
|
close.setAttribute("aria-label", "Close");
|
|
1146
2014
|
close.style.cssText = "position: absolute; top: 12px; right: 10px; z-index: 5; width: 34px; height: 34px; border: none; border-radius: 999px; background: rgba(0,0,0,0.32); color: #fff; font-size: 18px; cursor: pointer; display: flex; align-items: center; justify-content: center; line-height: 1;";
|
|
1147
2015
|
stage.appendChild(close);
|
|
@@ -1418,7 +2286,7 @@ function openGameModal(ctx, className, maxWidth = 360) {
|
|
|
1418
2286
|
};
|
|
1419
2287
|
const close = document.createElement("button");
|
|
1420
2288
|
close.type = "button";
|
|
1421
|
-
close.
|
|
2289
|
+
close.innerHTML = lucideSvg("x", { size: 15 });
|
|
1422
2290
|
close.setAttribute("aria-label", "Close");
|
|
1423
2291
|
close.style.cssText = `position:absolute;top:10px;right:10px;width:30px;height:30px;border:none;border-radius:999px;background:${branded ? "rgba(255,255,255,0.18)" : "rgba(0,0,0,0.05)"};color:${branded ? "#fff" : "#475569"};font-size:15px;cursor:pointer;z-index:1;`;
|
|
1424
2292
|
close.addEventListener("click", () => dismiss(true));
|
|
@@ -2136,14 +3004,15 @@ function buildVideo(ctx, aspect, autoplay, loop) {
|
|
|
2136
3004
|
});
|
|
2137
3005
|
const pill = document.createElement("button");
|
|
2138
3006
|
pill.type = "button";
|
|
2139
|
-
pill.
|
|
3007
|
+
pill.innerHTML = lucideSvg("volume-x", { size: 14 });
|
|
2140
3008
|
pill.setAttribute("aria-label", "Unmute");
|
|
2141
3009
|
pill.style.cssText = "position:absolute;bottom:10px;right:10px;z-index:2;width:34px;height:34px;border:none;border-radius:999px;background:rgba(0,0,0,0.45);color:#fff;font-size:14px;cursor:pointer;";
|
|
2142
3010
|
pill.addEventListener("click", (e) => {
|
|
2143
3011
|
var _a2;
|
|
2144
3012
|
e.stopPropagation();
|
|
2145
3013
|
vid.muted = !vid.muted;
|
|
2146
|
-
pill.
|
|
3014
|
+
pill.innerHTML = lucideSvg(vid.muted ? "volume-x" : "volume-2", { size: 14 });
|
|
3015
|
+
pill.setAttribute("aria-label", vid.muted ? "Unmute" : "Mute");
|
|
2147
3016
|
if (!vid.muted) void ((_a2 = vid.play) == null ? void 0 : _a2.call(vid).catch(() => {
|
|
2148
3017
|
}));
|
|
2149
3018
|
});
|
|
@@ -2231,7 +3100,7 @@ function renderVideo(ctx) {
|
|
|
2231
3100
|
}
|
|
2232
3101
|
const close = document.createElement("button");
|
|
2233
3102
|
close.type = "button";
|
|
2234
|
-
close.
|
|
3103
|
+
close.innerHTML = lucideSvg("x", { size: 15 });
|
|
2235
3104
|
close.setAttribute("aria-label", "Close");
|
|
2236
3105
|
close.style.cssText = "position:absolute;top:10px;left:10px;z-index:3;width:32px;height:32px;border:none;border-radius:999px;background:rgba(0,0,0,0.4);color:#fff;font-size:15px;cursor:pointer;";
|
|
2237
3106
|
close.addEventListener("click", () => {
|
|
@@ -2276,8 +3145,15 @@ const HEX = /^#[0-9a-fA-F]{3,8}$/;
|
|
|
2276
3145
|
function safeColor(c, fallback) {
|
|
2277
3146
|
return c && HEX.test(c) ? c : fallback;
|
|
2278
3147
|
}
|
|
2279
|
-
const RADIUS = { none: "0", lg: "12px", xl: "16px", "2xl": "20px" };
|
|
2280
3148
|
const ASPECT = { "16:9": "16 / 9", "4:3": "4 / 3", "21:9": "21 / 9" };
|
|
3149
|
+
function _injectHeroResponsiveCss() {
|
|
3150
|
+
if (typeof document === "undefined") return;
|
|
3151
|
+
if (document.getElementById("aegis-hero-style")) return;
|
|
3152
|
+
const style = document.createElement("style");
|
|
3153
|
+
style.id = "aegis-hero-style";
|
|
3154
|
+
style.textContent = ".aegis-hero-root{border-radius:16px;}@media (min-width:768px){.aegis-hero-root{border-radius:0;min-height:45vh;max-height:70vh;}}";
|
|
3155
|
+
document.head.appendChild(style);
|
|
3156
|
+
}
|
|
2281
3157
|
function cardHeadline(c) {
|
|
2282
3158
|
return c.headline ?? c.title ?? "";
|
|
2283
3159
|
}
|
|
@@ -2303,7 +3179,6 @@ function renderHeroInline(ctx, target) {
|
|
|
2303
3179
|
chrome.accent && chrome.accent !== "brand" ? chrome.accent : campaign.background_color,
|
|
2304
3180
|
"#4169e1"
|
|
2305
3181
|
);
|
|
2306
|
-
const radius = RADIUS[chrome.radius ?? "2xl"] ?? RADIUS["2xl"];
|
|
2307
3182
|
const variant = chrome.variant ?? "hero_fullbleed";
|
|
2308
3183
|
if (variant === "announcement_bar") {
|
|
2309
3184
|
const c = cards[0];
|
|
@@ -2326,8 +3201,10 @@ function renderHeroInline(ctx, target) {
|
|
|
2326
3201
|
trackEvent(campaign.id, "impression");
|
|
2327
3202
|
return true;
|
|
2328
3203
|
}
|
|
3204
|
+
_injectHeroResponsiveCss();
|
|
2329
3205
|
const root = document.createElement("div");
|
|
2330
|
-
root.
|
|
3206
|
+
root.className = "aegis-hero-root";
|
|
3207
|
+
root.style.cssText = `position:relative;width:100%;overflow:hidden;box-shadow:0 1px 2px rgba(16,24,40,0.06);${chrome.aspect_ratio && ASPECT[chrome.aspect_ratio] ? `aspect-ratio:${ASPECT[chrome.aspect_ratio]};` : "min-height:300px;"}`;
|
|
2331
3208
|
root.setAttribute("data-campaign-id", campaign.id);
|
|
2332
3209
|
const track = document.createElement("div");
|
|
2333
3210
|
track.style.cssText = "display:flex;height:100%;width:100%;transition:transform 0.5s ease;";
|
|
@@ -2459,6 +3336,7 @@ class AegisChat {
|
|
|
2459
3336
|
this.title = config.title ?? "Shopping Assistant";
|
|
2460
3337
|
this.greeting = config.greeting ?? "Hi! 👋 How can I help you today?";
|
|
2461
3338
|
this.accent = config.accentColor ?? "#4169e1";
|
|
3339
|
+
this.surfaceStyle = config.surfaceStyle === "tinted" ? "tinted" : "solid";
|
|
2462
3340
|
this.icon = config.icon ?? "sparkle";
|
|
2463
3341
|
this.logoUrl = config.logoUrl;
|
|
2464
3342
|
this.position = config.position ?? "bottom-right";
|
|
@@ -2729,6 +3607,10 @@ class AegisChat {
|
|
|
2729
3607
|
const root = document.createElement("div");
|
|
2730
3608
|
root.className = `aegis-chat-root aegis-chat-root--${this.position}`;
|
|
2731
3609
|
root.style.setProperty("--aegis-chat-accent", this.accent);
|
|
3610
|
+
if (this.surfaceStyle === "tinted") {
|
|
3611
|
+
root.style.setProperty("--aegis-chat-fill", "color-mix(in srgb, var(--aegis-chat-accent,#4169e1) 16%, #ffffff)");
|
|
3612
|
+
root.style.setProperty("--aegis-chat-fill-fg", "#0f172a");
|
|
3613
|
+
}
|
|
2732
3614
|
const bubble = document.createElement("button");
|
|
2733
3615
|
bubble.className = "aegis-chat-bubble";
|
|
2734
3616
|
bubble.setAttribute("aria-label", `Open ${this.title}`);
|
|
@@ -2750,7 +3632,7 @@ class AegisChat {
|
|
|
2750
3632
|
const closeBtn = document.createElement("button");
|
|
2751
3633
|
closeBtn.className = "aegis-chat-close";
|
|
2752
3634
|
closeBtn.setAttribute("aria-label", "Close chat");
|
|
2753
|
-
closeBtn.
|
|
3635
|
+
closeBtn.innerHTML = lucideSvg("x", { size: 16 });
|
|
2754
3636
|
closeBtn.addEventListener("click", () => this.closePanel());
|
|
2755
3637
|
header.appendChild(titleEl);
|
|
2756
3638
|
header.appendChild(closeBtn);
|
|
@@ -2806,7 +3688,7 @@ class AegisChat {
|
|
|
2806
3688
|
const tipClose = document.createElement("button");
|
|
2807
3689
|
tipClose.className = "aegis-chat-tip-close";
|
|
2808
3690
|
tipClose.setAttribute("aria-label", "Dismiss");
|
|
2809
|
-
tipClose.
|
|
3691
|
+
tipClose.innerHTML = lucideSvg("x", { size: 14 });
|
|
2810
3692
|
tipClose.addEventListener("click", (e) => {
|
|
2811
3693
|
e.stopPropagation();
|
|
2812
3694
|
this.dismissAttention();
|
|
@@ -3084,16 +3966,18 @@ const CHAT_CSS = `
|
|
|
3084
3966
|
.aegis-chat-badge{position:absolute;top:-2px;right:-2px;min-width:20px;height:20px;padding:0 5px;border-radius:9999px;background:#ef4444;color:#fff;font-size:12px;font-weight:600;display:flex;align-items:center;justify-content:center}
|
|
3085
3967
|
.aegis-chat-panel{position:absolute;bottom:0;right:0;width:380px;max-width:calc(100vw - 32px);height:560px;max-height:calc(100vh - 48px);background:#fff;border-radius:16px;box-shadow:0 16px 48px rgba(0,0,0,.24);display:none;flex-direction:column;overflow:hidden}
|
|
3086
3968
|
.aegis-chat-panel--open{display:flex}
|
|
3087
|
-
|
|
3969
|
+
/* Header + customer bubbles use the "fill" surface — accent solid by default, or
|
|
3970
|
+
a soft tint when surfaceStyle:'tinted' sets --aegis-chat-fill/-fg on the root. */
|
|
3971
|
+
.aegis-chat-header{display:flex;align-items:center;justify-content:space-between;padding:14px 16px;background:var(--aegis-chat-fill,var(--aegis-chat-accent,#4169e1));color:var(--aegis-chat-fill-fg,#fff)}
|
|
3088
3972
|
.aegis-chat-title{font-weight:600;font-size:15px}
|
|
3089
|
-
.aegis-chat-close{background:transparent;border:none;color
|
|
3973
|
+
.aegis-chat-close{background:transparent;border:none;color:var(--aegis-chat-fill-fg,#fff);font-size:16px;cursor:pointer;opacity:.85}
|
|
3090
3974
|
.aegis-chat-close:hover{opacity:1}
|
|
3091
3975
|
.aegis-chat-thread{flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:10px;background:#f8fafc}
|
|
3092
3976
|
.aegis-chat-msg{display:flex;flex-direction:column;max-width:85%}
|
|
3093
3977
|
.aegis-chat-msg--customer{align-self:flex-end;align-items:flex-end}
|
|
3094
3978
|
.aegis-chat-msg--assistant,.aegis-chat-msg--system{align-self:flex-start;align-items:flex-start}
|
|
3095
3979
|
.aegis-chat-bubbletext{padding:9px 13px;border-radius:14px;font-size:14px;line-height:1.45;white-space:pre-wrap;word-break:break-word}
|
|
3096
|
-
.aegis-chat-msg--customer .aegis-chat-bubbletext{background:var(--aegis-chat-accent,#4169e1);color
|
|
3980
|
+
.aegis-chat-msg--customer .aegis-chat-bubbletext{background:var(--aegis-chat-fill,var(--aegis-chat-accent,#4169e1));color:var(--aegis-chat-fill-fg,#fff);border-bottom-right-radius:4px}
|
|
3097
3981
|
.aegis-chat-msg--assistant .aegis-chat-bubbletext{background:#fff;color:#0f172a;border:1px solid #e2e8f0;border-bottom-left-radius:4px}
|
|
3098
3982
|
.aegis-chat-quickreplies{display:flex;flex-wrap:wrap;gap:6px;padding:2px 4px 6px;justify-content:flex-start}
|
|
3099
3983
|
.aegis-chat-chip{appearance:none;cursor:pointer;border:1px solid var(--aegis-chat-accent,#4169e1);background:#fff;color:var(--aegis-chat-accent,#4169e1);border-radius:9999px;padding:6px 12px;font-size:13px;line-height:1;font-family:inherit;transition:background .15s,color .15s}
|
|
@@ -3699,6 +4583,7 @@ function renderActiveWebChat(ctx, creds) {
|
|
|
3699
4583
|
icon: icon === "sparkle" || icon === "chat" || icon === "logo" ? icon : void 0,
|
|
3700
4584
|
logoUrl: logo ? ctx.sanitizeUrl(logo) ?? void 0 : void 0,
|
|
3701
4585
|
position: ic.chat_position === "bottom-left" ? "bottom-left" : void 0,
|
|
4586
|
+
surfaceStyle: ic.chat_theme === "tinted" ? "tinted" : void 0,
|
|
3702
4587
|
// 'nav' = headless (no bubble); the host opens it via aegis.chat.open() or a
|
|
3703
4588
|
// client_trigger. Defaults to 'bubble'. Per-device override via device_type
|
|
3704
4589
|
// targeting on the campaign (e.g. a mobile campaign with chat_display_mode='nav').
|
|
@@ -3772,10 +4657,15 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
3772
4657
|
this.ready = new Promise((resolve) => {
|
|
3773
4658
|
this.readyResolve = resolve;
|
|
3774
4659
|
});
|
|
4660
|
+
this.pendingPreInitRefresh = false;
|
|
3775
4661
|
this.currentSurface = null;
|
|
3776
4662
|
this.currentScreen = null;
|
|
3777
4663
|
this.currentLocationId = null;
|
|
3778
4664
|
this.filledSlots = /* @__PURE__ */ new WeakSet();
|
|
4665
|
+
this.slotSignatures = /* @__PURE__ */ new WeakMap();
|
|
4666
|
+
this.slotTimers = /* @__PURE__ */ new WeakMap();
|
|
4667
|
+
this.slotObserver = null;
|
|
4668
|
+
this.slotRenderScheduled = false;
|
|
3779
4669
|
this.writeKey = config.writeKey;
|
|
3780
4670
|
this.apiHost = config.apiHost || "https://api.aegis.ai";
|
|
3781
4671
|
this.userId = config.userId ?? readAnonIdFromStorage$1();
|
|
@@ -3887,6 +4777,11 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
3887
4777
|
this.connectSSE();
|
|
3888
4778
|
}
|
|
3889
4779
|
this.isInitialized = true;
|
|
4780
|
+
if (this.pendingPreInitRefresh) {
|
|
4781
|
+
this.pendingPreInitRefresh = false;
|
|
4782
|
+
this.log("Re-fetching campaigns for surface/screen declared during init");
|
|
4783
|
+
void this.refreshCampaigns();
|
|
4784
|
+
}
|
|
3890
4785
|
this.log("AegisInApp initialized successfully");
|
|
3891
4786
|
}
|
|
3892
4787
|
updateUserId(userId) {
|
|
@@ -3935,16 +4830,17 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
3935
4830
|
* change `currentSurface`, so arbitrary events never poison the surface gate.
|
|
3936
4831
|
*/
|
|
3937
4832
|
refreshOnEvent(eventName, isScreenDeclaration = false) {
|
|
3938
|
-
if (!this.isInitialized) {
|
|
3939
|
-
this.log(`refreshOnEvent(${eventName}) before initialize — ignored`);
|
|
3940
|
-
return;
|
|
3941
|
-
}
|
|
3942
4833
|
if (eventName && _AegisInAppManager.KNOWN_SURFACES.has(eventName)) {
|
|
3943
4834
|
this.currentSurface = eventName;
|
|
3944
4835
|
}
|
|
3945
4836
|
if (isScreenDeclaration && eventName && eventName !== "page_view") {
|
|
3946
4837
|
this.currentScreen = eventName;
|
|
3947
4838
|
}
|
|
4839
|
+
if (!this.isInitialized) {
|
|
4840
|
+
this.pendingPreInitRefresh = true;
|
|
4841
|
+
this.log(`refreshOnEvent(${eventName}) before initialize — surface captured, refetch deferred to initialize()`);
|
|
4842
|
+
return;
|
|
4843
|
+
}
|
|
3948
4844
|
if (this.refreshDebounceTimer) {
|
|
3949
4845
|
clearTimeout(this.refreshDebounceTimer);
|
|
3950
4846
|
}
|
|
@@ -4162,7 +5058,7 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
4162
5058
|
try {
|
|
4163
5059
|
const context = new URLSearchParams({
|
|
4164
5060
|
device_type: this.detectDeviceType(),
|
|
4165
|
-
page_url: typeof window !== "undefined" ? window.location.pathname : "/"
|
|
5061
|
+
page_url: typeof window !== "undefined" ? window.location.pathname + window.location.search : "/"
|
|
4166
5062
|
});
|
|
4167
5063
|
context.set("is_new_user", this.isNewUser() ? "true" : "false");
|
|
4168
5064
|
if (this.currentSurface) {
|
|
@@ -4320,28 +5216,75 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
4320
5216
|
if (!c.surface || c.surface.length === 0) return screenOk;
|
|
4321
5217
|
return screenOk || this.matchesCurrentSurface(c);
|
|
4322
5218
|
}
|
|
5219
|
+
// Re-fill slots that mount after a poll (SPA route changes). Observes the DOM
|
|
5220
|
+
// once; when a new [data-aegis-slot] appears it re-runs renderIntoSlots from
|
|
5221
|
+
// the cached campaigns (idempotent — already-filled slots are skipped). Does
|
|
5222
|
+
// NOT loop on the SDK's own injections (those add content INTO a slot, not a
|
|
5223
|
+
// new slot element).
|
|
5224
|
+
ensureSlotObserver() {
|
|
5225
|
+
if (this.slotObserver || typeof MutationObserver === "undefined" || typeof document === "undefined") {
|
|
5226
|
+
return;
|
|
5227
|
+
}
|
|
5228
|
+
this.slotObserver = new MutationObserver((mutations) => {
|
|
5229
|
+
let sawSlot = false;
|
|
5230
|
+
for (const m2 of mutations) {
|
|
5231
|
+
m2.addedNodes.forEach((n) => {
|
|
5232
|
+
var _a, _b;
|
|
5233
|
+
if (sawSlot || n.nodeType !== 1) return;
|
|
5234
|
+
const el = n;
|
|
5235
|
+
if (((_a = el.matches) == null ? void 0 : _a.call(el, "[data-aegis-slot]")) || ((_b = el.querySelector) == null ? void 0 : _b.call(el, "[data-aegis-slot]"))) {
|
|
5236
|
+
sawSlot = true;
|
|
5237
|
+
}
|
|
5238
|
+
});
|
|
5239
|
+
if (sawSlot) break;
|
|
5240
|
+
}
|
|
5241
|
+
if (!sawSlot || this.slotRenderScheduled) return;
|
|
5242
|
+
this.slotRenderScheduled = true;
|
|
5243
|
+
const run = () => {
|
|
5244
|
+
this.slotRenderScheduled = false;
|
|
5245
|
+
this.renderIntoSlots();
|
|
5246
|
+
};
|
|
5247
|
+
if (typeof requestAnimationFrame === "function") requestAnimationFrame(run);
|
|
5248
|
+
else setTimeout(run, 0);
|
|
5249
|
+
});
|
|
5250
|
+
this.slotObserver.observe(document.body, { childList: true, subtree: true });
|
|
5251
|
+
}
|
|
4323
5252
|
renderIntoSlots() {
|
|
4324
5253
|
if (typeof document === "undefined") return;
|
|
5254
|
+
this.ensureSlotObserver();
|
|
4325
5255
|
const slots = document.querySelectorAll("[data-aegis-slot]");
|
|
4326
5256
|
if (slots.length === 0) return;
|
|
4327
5257
|
const eligibleByCategory = /* @__PURE__ */ new Map();
|
|
5258
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
4328
5259
|
for (const c of this.campaigns) {
|
|
4329
5260
|
if (!this.matchesCurrentScreenOrSurface(c)) continue;
|
|
4330
5261
|
const modes = c.delivery_modes;
|
|
4331
5262
|
const category = c.widget_category;
|
|
4332
5263
|
if (!modes || !modes.includes("embedded_card")) continue;
|
|
4333
5264
|
if (!category) continue;
|
|
5265
|
+
if (seenIds.has(c.id)) continue;
|
|
5266
|
+
seenIds.add(c.id);
|
|
4334
5267
|
const arr2 = eligibleByCategory.get(category);
|
|
4335
5268
|
if (arr2) arr2.push(c);
|
|
4336
5269
|
else eligibleByCategory.set(category, [c]);
|
|
4337
5270
|
}
|
|
4338
5271
|
if (eligibleByCategory.size === 0) return;
|
|
4339
5272
|
slots.forEach((slot) => {
|
|
4340
|
-
if (this.filledSlots.has(slot)) return;
|
|
4341
5273
|
const key = slot.getAttribute("data-aegis-slot");
|
|
4342
5274
|
if (!key) return;
|
|
4343
5275
|
const list = eligibleByCategory.get(key);
|
|
4344
5276
|
if (!list || list.length === 0) return;
|
|
5277
|
+
const sig = list.map((c) => `${c.id}:${c.assigned_variant_id ?? ""}`).join(",");
|
|
5278
|
+
if (this.filledSlots.has(slot) && this.slotSignatures.get(slot) === sig) return;
|
|
5279
|
+
const oldTimer = this.slotTimers.get(slot);
|
|
5280
|
+
if (oldTimer) {
|
|
5281
|
+
clearInterval(oldTimer);
|
|
5282
|
+
this.slotTimers.delete(slot);
|
|
5283
|
+
}
|
|
5284
|
+
slot.querySelectorAll(
|
|
5285
|
+
":scope > [data-aegis-rotate-pane], :scope > [data-aegis-slot-rendered], :scope > [data-aegis-rotate-dots]"
|
|
5286
|
+
).forEach((n) => n.remove());
|
|
5287
|
+
this.slotSignatures.set(slot, sig);
|
|
4345
5288
|
slot.querySelectorAll(":scope > [data-aegis-slot-default]").forEach((d) => d.remove());
|
|
4346
5289
|
const attrMs = parseInt(slot.getAttribute("data-aegis-slot-rotate") || "0", 10);
|
|
4347
5290
|
const declaredMs = list.reduce((m2, c) => {
|
|
@@ -4350,10 +5293,15 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
4350
5293
|
return Number.isFinite(v) && v > m2 ? v : m2;
|
|
4351
5294
|
}, 0);
|
|
4352
5295
|
const rotateMs = attrMs > 0 ? attrMs : declaredMs;
|
|
5296
|
+
const flush = slot.hasAttribute("data-aegis-slot-flush");
|
|
4353
5297
|
if (rotateMs > 0 && list.length > 1) {
|
|
4354
|
-
this.renderRotatingSlot(slot, list, rotateMs);
|
|
5298
|
+
this.renderRotatingSlot(slot, list, rotateMs, flush);
|
|
4355
5299
|
} else {
|
|
4356
|
-
|
|
5300
|
+
const host = document.createElement("div");
|
|
5301
|
+
host.setAttribute("data-aegis-slot-rendered", list[0].id);
|
|
5302
|
+
slot.appendChild(host);
|
|
5303
|
+
this.renderCampaignIntoSlot(list[0], host);
|
|
5304
|
+
if (flush) this._flattenSlotCard(host);
|
|
4357
5305
|
}
|
|
4358
5306
|
this.filledSlots.add(slot);
|
|
4359
5307
|
});
|
|
@@ -4366,7 +5314,7 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
4366
5314
|
* is deferred at render and fired per campaign on FIRST visibility, so hidden
|
|
4367
5315
|
* panes never over-count. One rendered pane → no rotation (just shows it).
|
|
4368
5316
|
*/
|
|
4369
|
-
renderRotatingSlot(slot, campaigns, rotateMs) {
|
|
5317
|
+
renderRotatingSlot(slot, campaigns, rotateMs, flush = false) {
|
|
4370
5318
|
const panes = [];
|
|
4371
5319
|
for (const c of campaigns) {
|
|
4372
5320
|
const pane = document.createElement("div");
|
|
@@ -4374,8 +5322,10 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
4374
5322
|
pane.style.display = "none";
|
|
4375
5323
|
slot.appendChild(pane);
|
|
4376
5324
|
this.renderCampaignIntoSlot(c, pane, { deferImpression: true });
|
|
4377
|
-
if (pane.childElementCount > 0)
|
|
4378
|
-
|
|
5325
|
+
if (pane.childElementCount > 0) {
|
|
5326
|
+
if (flush) this._flattenSlotCard(pane);
|
|
5327
|
+
panes.push({ el: pane, campaign: c });
|
|
5328
|
+
} else pane.remove();
|
|
4379
5329
|
}
|
|
4380
5330
|
if (panes.length === 0) return;
|
|
4381
5331
|
const impressed = /* @__PURE__ */ new Set();
|
|
@@ -4386,17 +5336,75 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
4386
5336
|
this.emit("campaign-shown", c);
|
|
4387
5337
|
};
|
|
4388
5338
|
let idx = 0;
|
|
4389
|
-
|
|
4390
|
-
|
|
4391
|
-
|
|
4392
|
-
|
|
5339
|
+
const isDarkSurface = (c) => {
|
|
5340
|
+
var _a, _b;
|
|
5341
|
+
const ic = c.interactive_config || {};
|
|
5342
|
+
if (ic.surface_style === "dark") return true;
|
|
5343
|
+
const tplBg = (_b = (_a = ic.card_template) == null ? void 0 : _a.frame) == null ? void 0 : _b.bg;
|
|
5344
|
+
const bg = (typeof tplBg === "string" ? tplBg : "") || c.background_color || "";
|
|
5345
|
+
if (bg.startsWith("#")) {
|
|
5346
|
+
const h = bg.length === 4 ? bg.slice(1).split("").map((x) => x + x).join("") : bg.slice(1, 7);
|
|
5347
|
+
const r = parseInt(h.slice(0, 2), 16), g = parseInt(h.slice(2, 4), 16), b = parseInt(h.slice(4, 6), 16);
|
|
5348
|
+
if (![r, g, b].some(Number.isNaN)) return (0.299 * r + 0.587 * g + 0.114 * b) / 255 < 0.5;
|
|
5349
|
+
}
|
|
5350
|
+
return false;
|
|
5351
|
+
};
|
|
5352
|
+
const darkDots = panes.length > 0 && panes.every((p) => isDarkSurface(p.campaign));
|
|
5353
|
+
const dotInactive = darkDots ? "rgba(255,255,255,0.4)" : "rgba(15,23,42,0.2)";
|
|
5354
|
+
const dotActive = darkDots ? "#ffffff" : "var(--aegis-brand-accent, #4169e1)";
|
|
5355
|
+
const dots = [];
|
|
5356
|
+
if (panes.length > 1) {
|
|
5357
|
+
const bar = document.createElement("div");
|
|
5358
|
+
bar.setAttribute("data-aegis-rotate-dots", "");
|
|
5359
|
+
bar.setAttribute("role", "tablist");
|
|
5360
|
+
bar.setAttribute("aria-label", "Offers");
|
|
5361
|
+
bar.style.cssText = "display:flex;align-items:center;justify-content:center;gap:5px;padding:2px 0 8px;";
|
|
5362
|
+
panes.forEach((_, i) => {
|
|
5363
|
+
const dot = document.createElement("button");
|
|
5364
|
+
dot.type = "button";
|
|
5365
|
+
dot.setAttribute("role", "tab");
|
|
5366
|
+
dot.setAttribute("aria-label", `Offer ${i + 1} of ${panes.length}`);
|
|
5367
|
+
dot.style.cssText = `border:none;padding:0;cursor:pointer;height:6px;width:6px;border-radius:999px;background:${dotInactive};transition:width .25s ease,background .25s ease;`;
|
|
5368
|
+
dot.addEventListener("click", (e) => {
|
|
5369
|
+
e.stopPropagation();
|
|
5370
|
+
show(i, true);
|
|
5371
|
+
});
|
|
5372
|
+
dots.push(dot);
|
|
5373
|
+
bar.appendChild(dot);
|
|
5374
|
+
});
|
|
5375
|
+
slot.appendChild(bar);
|
|
5376
|
+
}
|
|
5377
|
+
const paintDots = () => {
|
|
5378
|
+
dots.forEach((d, i) => {
|
|
5379
|
+
const active = i === idx;
|
|
5380
|
+
d.style.width = active ? "16px" : "6px";
|
|
5381
|
+
d.style.background = active ? dotActive : dotInactive;
|
|
5382
|
+
d.setAttribute("aria-selected", active ? "true" : "false");
|
|
5383
|
+
});
|
|
5384
|
+
};
|
|
5385
|
+
let timer = null;
|
|
5386
|
+
const start = () => setInterval(() => {
|
|
5387
|
+
show(idx + 1);
|
|
5388
|
+
}, rotateMs);
|
|
5389
|
+
function show(i, fromClick = false) {
|
|
4393
5390
|
panes[idx].el.style.display = "none";
|
|
4394
|
-
idx = (
|
|
5391
|
+
idx = (i % panes.length + panes.length) % panes.length;
|
|
4395
5392
|
panes[idx].el.style.display = "";
|
|
4396
5393
|
markVisible(panes[idx].campaign);
|
|
4397
|
-
|
|
5394
|
+
paintDots();
|
|
5395
|
+
if (fromClick && timer) {
|
|
5396
|
+
clearInterval(timer);
|
|
5397
|
+
timer = start();
|
|
5398
|
+
}
|
|
5399
|
+
}
|
|
5400
|
+
panes[0].el.style.display = "";
|
|
5401
|
+
markVisible(panes[0].campaign);
|
|
5402
|
+
paintDots();
|
|
5403
|
+
if (panes.length === 1) return;
|
|
5404
|
+
timer = start();
|
|
5405
|
+
this.slotTimers.set(slot, timer);
|
|
4398
5406
|
if (typeof window !== "undefined") {
|
|
4399
|
-
window.addEventListener("beforeunload", () => clearInterval(timer), { once: true });
|
|
5407
|
+
window.addEventListener("beforeunload", () => timer && clearInterval(timer), { once: true });
|
|
4400
5408
|
}
|
|
4401
5409
|
}
|
|
4402
5410
|
/**
|
|
@@ -4450,6 +5458,14 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
4450
5458
|
target.querySelectorAll(":scope > [data-aegis-slot-default]").forEach((d) => d.remove());
|
|
4451
5459
|
}
|
|
4452
5460
|
}
|
|
5461
|
+
const spacing = Number(anchor == null ? void 0 : anchor.element_spacing);
|
|
5462
|
+
if (spacing > 0) {
|
|
5463
|
+
if (position === "before" || position === "after") {
|
|
5464
|
+
target.style.margin = `${spacing}px`;
|
|
5465
|
+
} else {
|
|
5466
|
+
target.style.padding = `${spacing}px`;
|
|
5467
|
+
}
|
|
5468
|
+
}
|
|
4453
5469
|
if (this.filledSlots.has(target)) continue;
|
|
4454
5470
|
this.renderCampaignIntoSlot(c, target);
|
|
4455
5471
|
this.filledSlots.add(target);
|
|
@@ -4555,7 +5571,12 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
4555
5571
|
}
|
|
4556
5572
|
return;
|
|
4557
5573
|
}
|
|
4558
|
-
|
|
5574
|
+
const _tpl = ic.card_template;
|
|
5575
|
+
const _hasComposedTemplate = !!_tpl && typeof _tpl === "object" && Array.isArray(_tpl.elements);
|
|
5576
|
+
const _isMultiCard = campaign.sub_type === "product_recommendation" || campaign.sub_type === "carousel_cards";
|
|
5577
|
+
if (_hasComposedTemplate && !_isMultiCard) {
|
|
5578
|
+
rendered = this.renderComposedCardSlot(campaign, ic, target);
|
|
5579
|
+
} else if (campaign.widget_category === "hero") {
|
|
4559
5580
|
rendered = renderHeroInline(this.buildRenderContext(campaign), target);
|
|
4560
5581
|
} else
|
|
4561
5582
|
switch (campaign.sub_type) {
|
|
@@ -4608,6 +5629,9 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
4608
5629
|
case "progress_bar":
|
|
4609
5630
|
rendered = renderProgressBarInline(this.buildRenderContext(campaign), target);
|
|
4610
5631
|
break;
|
|
5632
|
+
case "product_recommendation":
|
|
5633
|
+
rendered = renderProductRecommendationInline(this.buildRenderContext(campaign), target);
|
|
5634
|
+
break;
|
|
4611
5635
|
case "quiz":
|
|
4612
5636
|
rendered = this.renderQuizSlot(campaign, ic, bg, text, target);
|
|
4613
5637
|
if (!rendered) {
|
|
@@ -4670,6 +5694,85 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
4670
5694
|
* The catch-all for banner + nudge sub_types (birthday, referral, app-install,
|
|
4671
5695
|
* win-back, etc.) so EVERY gallery nudge renders on the bill (previously only
|
|
4672
5696
|
* star_rating / nps_survey / form were handled → nudges never appeared). */
|
|
5697
|
+
/**
|
|
5698
|
+
* Composed single card — renders a campaign's top-level `card_template`
|
|
5699
|
+
* (frame + elements: icon/text/progress/image/cta/group/…) through the generic
|
|
5700
|
+
* `renderCardFromTemplate` engine. The canonical path for the rich card editor:
|
|
5701
|
+
* the storefront value bar, loyalty nudges, and any operator-composed card all
|
|
5702
|
+
* render here from declarative JSON, on ACS / custom / third-party sites.
|
|
5703
|
+
*/
|
|
5704
|
+
renderComposedCardSlot(campaign, ic, target) {
|
|
5705
|
+
const c = campaign;
|
|
5706
|
+
const card = {
|
|
5707
|
+
image_url: typeof c.image_url === "string" ? c.image_url : void 0,
|
|
5708
|
+
title: campaign.title,
|
|
5709
|
+
body: campaign.body,
|
|
5710
|
+
cta_text: typeof c.button_text === "string" ? c.button_text : void 0,
|
|
5711
|
+
cta_url: typeof c.action_url === "string" ? c.action_url : void 0,
|
|
5712
|
+
metadata: ic.card_meta || {}
|
|
5713
|
+
};
|
|
5714
|
+
const template = resolveGlobalTemplate(ic);
|
|
5715
|
+
const { accent } = this._surfacePalette(campaign);
|
|
5716
|
+
const tile = renderCardFromTemplate(card, {
|
|
5717
|
+
template,
|
|
5718
|
+
ctx: this.buildRenderContext(campaign),
|
|
5719
|
+
action: "navigate",
|
|
5720
|
+
layoutAccent: this.sanitizeColor(campaign.background_color || accent)
|
|
5721
|
+
});
|
|
5722
|
+
target.appendChild(tile);
|
|
5723
|
+
return true;
|
|
5724
|
+
}
|
|
5725
|
+
/**
|
|
5726
|
+
* C2 — composed card body in an OVERLAY (modal / banner / full_screen /
|
|
5727
|
+
* half_interstitial). The overlay counterpart to `renderComposedCardSlot`: it
|
|
5728
|
+
* builds the same `TemplateCard` from the campaign's canonical fields and paints
|
|
5729
|
+
* it with the generic `renderCardFromTemplate` engine, then wraps it in the
|
|
5730
|
+
* standard overlay chrome (close button + size scaling) so a composed card looks
|
|
5731
|
+
* identical whether overlaid or slotted. Only invoked when a `card_template` is
|
|
5732
|
+
* present (see displayCampaign) — flat campaigns never reach here.
|
|
5733
|
+
* See IN_APP_FORMAT_LOCK_AND_COMPOSABLE_CARDS_TRACKER.md (Part B / C2).
|
|
5734
|
+
*/
|
|
5735
|
+
renderComposedCardOverlay(campaign, ic) {
|
|
5736
|
+
const { accent } = this._surfacePalette(campaign);
|
|
5737
|
+
const bg = this.sanitizeColor(campaign.background_color || "#ffffff");
|
|
5738
|
+
const text = this.sanitizeColor(campaign.text_color || "#111827");
|
|
5739
|
+
const fullScreen = campaign.type === "full_screen";
|
|
5740
|
+
const overlay = this.createOverlay("aegis-in-app-composed-card-overlay");
|
|
5741
|
+
const modal = document.createElement("div");
|
|
5742
|
+
modal.style.cssText = fullScreen ? `position: relative; width: 100%; height: 100%; max-width: 100%; overflow: auto;
|
|
5743
|
+
background: ${bg}; color: ${text}; animation: aegisScaleIn 0.3s ease;` : `position: relative; max-width: 380px; width: 92%; border-radius: 18px; overflow: hidden;
|
|
5744
|
+
background: ${bg}; color: ${text}; box-shadow: 0 16px 48px rgba(0,0,0,0.22);
|
|
5745
|
+
animation: aegisScaleIn 0.3s ease;`;
|
|
5746
|
+
const c = campaign;
|
|
5747
|
+
const card = {
|
|
5748
|
+
image_url: typeof c.image_url === "string" ? c.image_url : void 0,
|
|
5749
|
+
title: campaign.title,
|
|
5750
|
+
body: campaign.body,
|
|
5751
|
+
cta_text: typeof c.button_text === "string" ? c.button_text : void 0,
|
|
5752
|
+
cta_url: typeof c.action_url === "string" ? c.action_url : void 0,
|
|
5753
|
+
metadata: ic.card_meta || {}
|
|
5754
|
+
};
|
|
5755
|
+
const template = resolveGlobalTemplate(ic);
|
|
5756
|
+
const tile = renderCardFromTemplate(card, {
|
|
5757
|
+
template,
|
|
5758
|
+
ctx: this.buildRenderContext(campaign),
|
|
5759
|
+
action: "navigate",
|
|
5760
|
+
layoutAccent: this.sanitizeColor(campaign.background_color || accent)
|
|
5761
|
+
});
|
|
5762
|
+
modal.appendChild(tile);
|
|
5763
|
+
this._addCornerClose(modal, overlay, campaign.id, text);
|
|
5764
|
+
if (fullScreen) {
|
|
5765
|
+
overlay.appendChild(modal);
|
|
5766
|
+
} else {
|
|
5767
|
+
const mul = this._sizeMul(ic);
|
|
5768
|
+
const sizer = document.createElement("div");
|
|
5769
|
+
sizer.style.cssText = `display: flex; justify-content: center; align-items: center; width: 100%; transform: scale(${mul}); transform-origin: center;`;
|
|
5770
|
+
sizer.appendChild(modal);
|
|
5771
|
+
overlay.appendChild(sizer);
|
|
5772
|
+
}
|
|
5773
|
+
this.addAnimationStyles();
|
|
5774
|
+
document.body.appendChild(overlay);
|
|
5775
|
+
}
|
|
4673
5776
|
renderGenericCardSlot(campaign, ic, bg, text, target) {
|
|
4674
5777
|
const st = this._slotStyle(campaign);
|
|
4675
5778
|
const card = this._wrapInSlotCard("aegis-in-app-generic-card", campaign.id, bg, text, st.radius);
|
|
@@ -4685,6 +5788,45 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
4685
5788
|
im.style.cssText = "width: 100%; height: 96px; object-fit: cover; display: block;";
|
|
4686
5789
|
card.appendChild(im);
|
|
4687
5790
|
}
|
|
5791
|
+
const widgetCat = typeof c.widget_category === "string" ? c.widget_category : "";
|
|
5792
|
+
if (widgetCat === "promo" && !img) {
|
|
5793
|
+
const row = document.createElement("div");
|
|
5794
|
+
row.style.cssText = `display:flex; align-items:center; gap:12px; min-height:46px; padding:${st.padY ?? 10}px ${st.padX ?? 14}px;`;
|
|
5795
|
+
const colL = document.createElement("div");
|
|
5796
|
+
colL.style.cssText = "flex:1 1 auto; min-width:0; display:flex; flex-direction:column; gap:2px;";
|
|
5797
|
+
if (campaign.title) {
|
|
5798
|
+
const t = document.createElement("div");
|
|
5799
|
+
t.style.cssText = `font-size:13px; font-weight:${st.weight ?? "700"}; line-height:1.25; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;`;
|
|
5800
|
+
t.textContent = campaign.title;
|
|
5801
|
+
colL.appendChild(t);
|
|
5802
|
+
}
|
|
5803
|
+
if (campaign.body) {
|
|
5804
|
+
const b = document.createElement("div");
|
|
5805
|
+
b.style.cssText = "font-size:11.5px; opacity:0.7; line-height:1.3; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;";
|
|
5806
|
+
b.textContent = campaign.body;
|
|
5807
|
+
colL.appendChild(b);
|
|
5808
|
+
}
|
|
5809
|
+
row.appendChild(colL);
|
|
5810
|
+
if (buttonText) {
|
|
5811
|
+
const btn = document.createElement("button");
|
|
5812
|
+
btn.type = "button";
|
|
5813
|
+
btn.textContent = buttonText;
|
|
5814
|
+
const accentTok = `var(--aegis-brand-accent, ${text})`;
|
|
5815
|
+
btn.style.cssText = `flex:0 0 auto; align-self:center; cursor:pointer; white-space:nowrap;background:color-mix(in srgb, ${accentTok} 12%, #fff); color:${accentTok}; border:none;border-radius:999px; padding:7px 16px; font-size:12.5px; font-weight:700;`;
|
|
5816
|
+
btn.addEventListener("click", () => {
|
|
5817
|
+
void this.trackEvent(campaign.id, "clicked");
|
|
5818
|
+
if (actionUrl) {
|
|
5819
|
+
window.open(actionUrl, "_blank", "noopener");
|
|
5820
|
+
} else if (typeof window !== "undefined") {
|
|
5821
|
+
window.dispatchEvent(new CustomEvent("aegis:open-login", { detail: { campaign_id: campaign.id } }));
|
|
5822
|
+
}
|
|
5823
|
+
});
|
|
5824
|
+
row.appendChild(btn);
|
|
5825
|
+
}
|
|
5826
|
+
card.appendChild(row);
|
|
5827
|
+
target.appendChild(card);
|
|
5828
|
+
return true;
|
|
5829
|
+
}
|
|
4688
5830
|
const cbody = document.createElement("div");
|
|
4689
5831
|
cbody.style.cssText = `padding: ${st.padY ?? 12}px ${st.padX ?? 12}px; display: flex; flex-direction: column; gap: 6px;`;
|
|
4690
5832
|
if (campaign.title) {
|
|
@@ -4828,8 +5970,14 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
4828
5970
|
body.style.alignItems = "center";
|
|
4829
5971
|
body.style.justifyContent = "center";
|
|
4830
5972
|
const done = document.createElement("div");
|
|
4831
|
-
done.style.cssText = "padding: 8px 0; font-size: 13px; font-weight: 600; text-align: center;";
|
|
4832
|
-
|
|
5973
|
+
done.style.cssText = "padding: 8px 0; font-size: 13px; font-weight: 600; text-align: center; display: inline-flex; align-items: center; justify-content: center; gap: 6px;";
|
|
5974
|
+
const customThanks = typeof ((_a = campaign.interactive_config) == null ? void 0 : _a.thank_you_message) === "string" ? campaign.interactive_config.thank_you_message : null;
|
|
5975
|
+
if (customThanks) {
|
|
5976
|
+
done.textContent = customThanks;
|
|
5977
|
+
} else {
|
|
5978
|
+
done.innerHTML = lucideSvg("check", { size: 14 });
|
|
5979
|
+
done.appendChild(document.createTextNode("Thanks — your details are saved."));
|
|
5980
|
+
}
|
|
4833
5981
|
body.appendChild(done);
|
|
4834
5982
|
this._playReaction(body, "affirm", "check.json", campaign.interactive_config);
|
|
4835
5983
|
});
|
|
@@ -5169,11 +6317,11 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
5169
6317
|
const soundBtn = document.createElement("button");
|
|
5170
6318
|
soundBtn.type = "button";
|
|
5171
6319
|
soundBtn.setAttribute("aria-label", "Toggle sound");
|
|
5172
|
-
soundBtn.
|
|
6320
|
+
soundBtn.innerHTML = lucideSvg(soundOn ? "volume-2" : "volume-x", { size: 15 });
|
|
5173
6321
|
soundBtn.style.cssText = "position: absolute; top: 10px; left: 12px; background: transparent; border: none; font-size: 15px; cursor: pointer; opacity: 0.65; z-index: 6; line-height: 1;";
|
|
5174
6322
|
soundBtn.addEventListener("click", () => {
|
|
5175
6323
|
soundOn = !soundOn;
|
|
5176
|
-
soundBtn.
|
|
6324
|
+
soundBtn.innerHTML = lucideSvg(soundOn ? "volume-2" : "volume-x", { size: 15 });
|
|
5177
6325
|
});
|
|
5178
6326
|
card.appendChild(soundBtn);
|
|
5179
6327
|
}
|
|
@@ -5288,7 +6436,7 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
5288
6436
|
var _a;
|
|
5289
6437
|
try {
|
|
5290
6438
|
void ((_a = navigator.clipboard) == null ? void 0 : _a.writeText(r.code));
|
|
5291
|
-
chip.textContent = "Copied
|
|
6439
|
+
chip.textContent = "Copied";
|
|
5292
6440
|
} catch {
|
|
5293
6441
|
}
|
|
5294
6442
|
});
|
|
@@ -5334,7 +6482,7 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
5334
6482
|
var _a;
|
|
5335
6483
|
try {
|
|
5336
6484
|
void ((_a = navigator.clipboard) == null ? void 0 : _a.writeText(r.code));
|
|
5337
|
-
chip.textContent = "Copied
|
|
6485
|
+
chip.textContent = "Copied";
|
|
5338
6486
|
} catch {
|
|
5339
6487
|
}
|
|
5340
6488
|
});
|
|
@@ -5575,7 +6723,7 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
5575
6723
|
pctLabel.textContent = `${pct}%`;
|
|
5576
6724
|
pctLabel.style.opacity = "0.8";
|
|
5577
6725
|
} else if (pctLabel && i === selected) {
|
|
5578
|
-
pctLabel.
|
|
6726
|
+
pctLabel.innerHTML = lucideSvg("check", { size: 14 });
|
|
5579
6727
|
pctLabel.style.opacity = "0.8";
|
|
5580
6728
|
}
|
|
5581
6729
|
});
|
|
@@ -5598,59 +6746,18 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
5598
6746
|
}
|
|
5599
6747
|
const strip = document.createElement("div");
|
|
5600
6748
|
strip.style.cssText = `display: flex; gap: 8px; overflow-x: auto; scroll-snap-type: x mandatory; padding: ${st.padY ?? 12}px ${st.padX ?? 12}px;`;
|
|
6749
|
+
const template = resolveGlobalTemplate(ic);
|
|
6750
|
+
const ctx = this.buildRenderContext(campaign);
|
|
6751
|
+
const accent = this.sanitizeColor(campaign.background_color || text);
|
|
5601
6752
|
cards.forEach((c, i) => {
|
|
5602
|
-
const tile =
|
|
5603
|
-
|
|
5604
|
-
|
|
5605
|
-
|
|
5606
|
-
|
|
5607
|
-
|
|
5608
|
-
|
|
5609
|
-
|
|
5610
|
-
v.muted = true;
|
|
5611
|
-
v.loop = true;
|
|
5612
|
-
v.autoplay = true;
|
|
5613
|
-
v.playsInline = true;
|
|
5614
|
-
v.setAttribute("playsinline", "");
|
|
5615
|
-
v.style.cssText = "width: 100%; height: 90px; object-fit: cover; display: block;";
|
|
5616
|
-
tile.appendChild(v);
|
|
5617
|
-
} else if (imageUrl) {
|
|
5618
|
-
const im = document.createElement("img");
|
|
5619
|
-
im.src = imageUrl;
|
|
5620
|
-
im.alt = "";
|
|
5621
|
-
im.loading = "lazy";
|
|
5622
|
-
im.style.cssText = "width: 100%; height: 90px; object-fit: cover; display: block;";
|
|
5623
|
-
tile.appendChild(im);
|
|
5624
|
-
}
|
|
5625
|
-
const tb = document.createElement("div");
|
|
5626
|
-
tb.style.cssText = "padding: 0 8px 8px; display: flex; flex-direction: column; gap: 4px;";
|
|
5627
|
-
if (typeof c.title === "string" && c.title) {
|
|
5628
|
-
const tt = document.createElement("div");
|
|
5629
|
-
tt.style.cssText = "font-size: 12px; font-weight: 600; line-height: 1.3;";
|
|
5630
|
-
tt.textContent = c.title;
|
|
5631
|
-
tb.appendChild(tt);
|
|
5632
|
-
}
|
|
5633
|
-
if (typeof c.body === "string" && c.body) {
|
|
5634
|
-
const tbd = document.createElement("div");
|
|
5635
|
-
tbd.style.cssText = "font-size: 10.5px; opacity: 0.72; line-height: 1.3;";
|
|
5636
|
-
tbd.textContent = c.body;
|
|
5637
|
-
tb.appendChild(tbd);
|
|
5638
|
-
}
|
|
5639
|
-
const ctaText = typeof c.cta_text === "string" ? c.cta_text : "";
|
|
5640
|
-
if (ctaText && ctaUrl) {
|
|
5641
|
-
const cta = document.createElement("button");
|
|
5642
|
-
cta.textContent = ctaText;
|
|
5643
|
-
cta.style.cssText = `margin-top: auto; align-self: flex-start; background: ${text}; color: ${bg}; border: none; padding: 5px 10px; border-radius: ${st.btnRadius ?? 999}px; font-size: 11px; font-weight: 600; cursor: pointer;`;
|
|
5644
|
-
const goto = (e) => {
|
|
5645
|
-
e.stopPropagation();
|
|
5646
|
-
void this.trackEvent(campaign.id, "clicked", { stepId: `card_${i}` });
|
|
5647
|
-
window.open(ctaUrl, "_blank", "noopener");
|
|
5648
|
-
};
|
|
5649
|
-
cta.addEventListener("click", goto);
|
|
5650
|
-
tile.addEventListener("click", goto);
|
|
5651
|
-
tb.appendChild(cta);
|
|
5652
|
-
}
|
|
5653
|
-
tile.appendChild(tb);
|
|
6753
|
+
const tile = renderCardFromTemplate(c, {
|
|
6754
|
+
template,
|
|
6755
|
+
ctx,
|
|
6756
|
+
action: "navigate",
|
|
6757
|
+
layout: "row",
|
|
6758
|
+
layoutAccent: accent
|
|
6759
|
+
});
|
|
6760
|
+
tile.setAttribute("data-card-index", String(i));
|
|
5654
6761
|
strip.appendChild(tile);
|
|
5655
6762
|
});
|
|
5656
6763
|
card.appendChild(strip);
|
|
@@ -5902,11 +7009,11 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
5902
7009
|
const sb = document.createElement("button");
|
|
5903
7010
|
sb.type = "button";
|
|
5904
7011
|
sb.setAttribute("aria-label", "Toggle sound");
|
|
5905
|
-
sb.
|
|
7012
|
+
sb.innerHTML = lucideSvg(soundOn ? "volume-2" : "volume-x", { size: 15 });
|
|
5906
7013
|
sb.style.cssText = "position: absolute; top: 10px; left: 12px; background: transparent; border: none; font-size: 15px; cursor: pointer; opacity: 0.65; z-index: 6; line-height: 1;";
|
|
5907
7014
|
sb.addEventListener("click", () => {
|
|
5908
7015
|
soundOn = !soundOn;
|
|
5909
|
-
sb.
|
|
7016
|
+
sb.innerHTML = lucideSvg(soundOn ? "volume-2" : "volume-x", { size: 15 });
|
|
5910
7017
|
});
|
|
5911
7018
|
card.appendChild(sb);
|
|
5912
7019
|
}
|
|
@@ -6075,7 +7182,7 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
6075
7182
|
var _a;
|
|
6076
7183
|
try {
|
|
6077
7184
|
void ((_a = navigator.clipboard) == null ? void 0 : _a.writeText(code));
|
|
6078
|
-
chip.textContent = "Copied
|
|
7185
|
+
chip.textContent = "Copied";
|
|
6079
7186
|
} catch {
|
|
6080
7187
|
}
|
|
6081
7188
|
});
|
|
@@ -6263,6 +7370,19 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
6263
7370
|
`;
|
|
6264
7371
|
return card;
|
|
6265
7372
|
}
|
|
7373
|
+
/**
|
|
7374
|
+
* Flush a rendered slot card into its host card — drop the per-campaign radius
|
|
7375
|
+
* + shadow so it reads as one unit with the host wrapper (used for the
|
|
7376
|
+
* storefront value bar via `data-aegis-slot-flush`). Targets every
|
|
7377
|
+
* `[data-campaign-id]` card inside `container` (or the container itself).
|
|
7378
|
+
*/
|
|
7379
|
+
_flattenSlotCard(container) {
|
|
7380
|
+
const cards = container.matches("[data-campaign-id]") ? [container] : Array.from(container.querySelectorAll("[data-campaign-id]"));
|
|
7381
|
+
for (const el of cards) {
|
|
7382
|
+
el.style.borderRadius = "0";
|
|
7383
|
+
el.style.boxShadow = "none";
|
|
7384
|
+
}
|
|
7385
|
+
}
|
|
6266
7386
|
// Optional header/brand image atop a survey-style widget (star / nps).
|
|
6267
7387
|
_appendHeaderImage(body, ic) {
|
|
6268
7388
|
const url = ic.header_image_url;
|
|
@@ -6704,6 +7824,9 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
6704
7824
|
}
|
|
6705
7825
|
}
|
|
6706
7826
|
displayCampaign(campaign) {
|
|
7827
|
+
if (Array.isArray(campaign.delivery_modes) && campaign.delivery_modes.length > 0 && !campaign.delivery_modes.includes("in_app_overlay")) {
|
|
7828
|
+
return;
|
|
7829
|
+
}
|
|
6707
7830
|
const proceed = this.emit("campaign-will-show", campaign);
|
|
6708
7831
|
if (!proceed) {
|
|
6709
7832
|
this.log(`campaign ${campaign.id} suppressed by campaign-will-show handler`);
|
|
@@ -6734,6 +7857,19 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
6734
7857
|
this.emit("campaign-shown", campaign);
|
|
6735
7858
|
return;
|
|
6736
7859
|
}
|
|
7860
|
+
{
|
|
7861
|
+
const ic2 = campaign.interactive_config || {};
|
|
7862
|
+
const tpl2 = ic2.card_template;
|
|
7863
|
+
const hasTpl2 = !!tpl2 && typeof tpl2 === "object" && Array.isArray(tpl2.elements) && tpl2.elements.length > 0;
|
|
7864
|
+
const multiCard2 = campaign.sub_type === "product_recommendation" || campaign.sub_type === "carousel_cards";
|
|
7865
|
+
const overlayCardType = campaign.type === "modal" || campaign.type === "banner" || campaign.type === "full_screen" || campaign.type === "half_interstitial";
|
|
7866
|
+
if (hasTpl2 && !multiCard2 && overlayCardType) {
|
|
7867
|
+
this.renderComposedCardOverlay(campaign, ic2);
|
|
7868
|
+
this.trackEvent(campaign.id, "impression");
|
|
7869
|
+
this.emit("campaign-shown", campaign);
|
|
7870
|
+
return;
|
|
7871
|
+
}
|
|
7872
|
+
}
|
|
6737
7873
|
switch (campaign.type) {
|
|
6738
7874
|
case "custom_html":
|
|
6739
7875
|
this.renderCustomHtml(campaign);
|
|
@@ -6833,6 +7969,16 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
6833
7969
|
return {
|
|
6834
7970
|
campaign,
|
|
6835
7971
|
getCartState: this.getCartState,
|
|
7972
|
+
properties: () => {
|
|
7973
|
+
var _a, _b;
|
|
7974
|
+
const cart = (_a = this.getCartState) == null ? void 0 : _a.call(this);
|
|
7975
|
+
const ctxObj = ((_b = campaign.interactive_config) == null ? void 0 : _b.card_context) || {};
|
|
7976
|
+
return {
|
|
7977
|
+
"cart.total": cart == null ? void 0 : cart.total,
|
|
7978
|
+
"cart.count": cart == null ? void 0 : cart.itemCount,
|
|
7979
|
+
...ctxObj
|
|
7980
|
+
};
|
|
7981
|
+
},
|
|
6836
7982
|
trackEvent: (id, evt, extra) => {
|
|
6837
7983
|
void this.trackEvent(id, evt, extra);
|
|
6838
7984
|
},
|
|
@@ -6943,7 +8089,7 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
6943
8089
|
'<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>'
|
|
6944
8090
|
);
|
|
6945
8091
|
if (closeIcon) x.appendChild(closeIcon);
|
|
6946
|
-
else x.
|
|
8092
|
+
else x.innerHTML = lucideSvg("x", { size: 14 });
|
|
6947
8093
|
x.style.cssText = `
|
|
6948
8094
|
position: absolute; top: 12px; right: 12px; z-index: 4; width: 28px; height: 28px;
|
|
6949
8095
|
display: flex; align-items: center; justify-content: center; border: none;
|
|
@@ -7781,12 +8927,17 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
7781
8927
|
_surfacePalette(campaign) {
|
|
7782
8928
|
const ic = campaign.interactive_config || {};
|
|
7783
8929
|
const brand = this.sanitizeColor(campaign.background_color || "#4169e1");
|
|
7784
|
-
const
|
|
7785
|
-
if (branded) {
|
|
8930
|
+
const surface = ic.surface_style;
|
|
8931
|
+
if (surface === "branded") {
|
|
7786
8932
|
const bg = brand;
|
|
7787
8933
|
const text = campaign.text_color ? this.sanitizeColor(campaign.text_color) : "#ffffff";
|
|
7788
8934
|
return { bg, text, btnBg: text, btnText: bg, accent: text, branded: true };
|
|
7789
8935
|
}
|
|
8936
|
+
if (surface === "dark") {
|
|
8937
|
+
const bg = this.sanitizeColor(campaign.background_color || "#0f172a");
|
|
8938
|
+
const text = campaign.text_color ? this.sanitizeColor(campaign.text_color) : "#ffffff";
|
|
8939
|
+
return { bg, text, btnBg: "#ffffff", btnText: bg, accent: text, branded: false };
|
|
8940
|
+
}
|
|
7790
8941
|
return { bg: "#ffffff", text: "#0f172a", btnBg: brand, btnText: this._contrastText(brand), accent: brand, branded: false };
|
|
7791
8942
|
}
|
|
7792
8943
|
inAppStyle(campaign) {
|
|
@@ -7890,7 +9041,7 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
7890
9041
|
actionsContainer.appendChild(ctaButton);
|
|
7891
9042
|
}
|
|
7892
9043
|
const closeButton = document.createElement("button");
|
|
7893
|
-
closeButton.
|
|
9044
|
+
closeButton.innerHTML = lucideSvg("x", { size: 18 });
|
|
7894
9045
|
closeButton.setAttribute("aria-label", "Close");
|
|
7895
9046
|
closeButton.style.cssText = `
|
|
7896
9047
|
background: transparent;
|
|
@@ -8088,7 +9239,7 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
8088
9239
|
pill.replaceChildren();
|
|
8089
9240
|
const ic = document.createElement("span");
|
|
8090
9241
|
ic.style.fontSize = "13px";
|
|
8091
|
-
ic.
|
|
9242
|
+
ic.innerHTML = lucideSvg(v.muted ? "volume-x" : "volume-2", { size: 13 });
|
|
8092
9243
|
pill.appendChild(ic);
|
|
8093
9244
|
if (v.muted) {
|
|
8094
9245
|
const t = document.createElement("span");
|
|
@@ -8218,7 +9369,7 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
8218
9369
|
}
|
|
8219
9370
|
overlay.appendChild(contentContainer);
|
|
8220
9371
|
const closeButton = document.createElement("button");
|
|
8221
|
-
closeButton.
|
|
9372
|
+
closeButton.innerHTML = lucideSvg("x", { size: isBg ? 18 : 28 });
|
|
8222
9373
|
closeButton.setAttribute("aria-label", "Close");
|
|
8223
9374
|
closeButton.style.cssText = `
|
|
8224
9375
|
position: absolute; top: 20px; right: 20px; z-index: 3; background: ${isBg ? "rgba(0,0,0,0.45)" : "transparent"};
|
|
@@ -8346,7 +9497,7 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
8346
9497
|
}
|
|
8347
9498
|
modal.appendChild(content);
|
|
8348
9499
|
const closeButton = document.createElement("button");
|
|
8349
|
-
closeButton.
|
|
9500
|
+
closeButton.innerHTML = lucideSvg("x", { size: 22 });
|
|
8350
9501
|
closeButton.setAttribute("aria-label", "Close");
|
|
8351
9502
|
closeButton.style.cssText = `
|
|
8352
9503
|
position: absolute;
|
|
@@ -8419,16 +9570,16 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
8419
9570
|
const ic = campaign.interactive_config || {};
|
|
8420
9571
|
const variant = ic.alert_variant || "";
|
|
8421
9572
|
const VARIANTS = {
|
|
8422
|
-
info: {
|
|
8423
|
-
success: {
|
|
8424
|
-
warning: {
|
|
8425
|
-
error: {
|
|
9573
|
+
info: { icon: "info", color: "#3b82f6" },
|
|
9574
|
+
success: { icon: "check", color: "#10b981" },
|
|
9575
|
+
warning: { icon: "triangle-alert", color: "#f59e0b" },
|
|
9576
|
+
error: { icon: "x", color: "#ef4444" }
|
|
8426
9577
|
};
|
|
8427
9578
|
const vspec = VARIANTS[variant];
|
|
8428
9579
|
if (vspec) {
|
|
8429
9580
|
const badge = document.createElement("div");
|
|
8430
9581
|
badge.style.cssText = `width: 48px; height: 48px; border-radius: 50%; margin: 0 auto 12px; display: flex; align-items: center; justify-content: center; font-size: 24px; font-weight: 800; background: ${vspec.color}22; color: ${vspec.color};`;
|
|
8431
|
-
badge.
|
|
9582
|
+
badge.innerHTML = lucideSvg(vspec.icon, { size: 24 });
|
|
8432
9583
|
content.appendChild(badge);
|
|
8433
9584
|
}
|
|
8434
9585
|
const title = document.createElement("h3");
|
|
@@ -8570,7 +9721,7 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
8570
9721
|
if (!hasMedia) {
|
|
8571
9722
|
const placeholder = document.createElement("div");
|
|
8572
9723
|
placeholder.style.cssText = "width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; background: linear-gradient(135deg, #1f2937, #0f172a); color: rgba(255,255,255,0.35); font-size: 34px;";
|
|
8573
|
-
placeholder.
|
|
9724
|
+
placeholder.innerHTML = lucideSvg("play", { size: 34 });
|
|
8574
9725
|
mediaWrap.appendChild(placeholder);
|
|
8575
9726
|
}
|
|
8576
9727
|
pip.appendChild(mediaWrap);
|
|
@@ -8581,7 +9732,7 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
8581
9732
|
playGlyph.setAttribute("aria-label", "Play or pause");
|
|
8582
9733
|
playGlyph.style.cssText = "position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 52px; height: 52px; border-radius: 50%; border: none; background: rgba(0,0,0,0.45); color: #fff; font-size: 22px; cursor: pointer; display: flex; align-items: center; justify-content: center; opacity: 0; transition: opacity 0.25s ease; backdrop-filter: blur(2px);";
|
|
8583
9734
|
const syncGlyph = () => {
|
|
8584
|
-
playGlyph.
|
|
9735
|
+
playGlyph.innerHTML = lucideSvg(v.paused ? "play" : "pause", { size: 22 });
|
|
8585
9736
|
playGlyph.style.opacity = v.paused ? "1" : "0";
|
|
8586
9737
|
};
|
|
8587
9738
|
const togglePlay = () => {
|
|
@@ -8608,7 +9759,7 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
8608
9759
|
mutePill.replaceChildren();
|
|
8609
9760
|
const ic2 = document.createElement("span");
|
|
8610
9761
|
ic2.style.fontSize = "13px";
|
|
8611
|
-
ic2.
|
|
9762
|
+
ic2.innerHTML = lucideSvg(v.muted ? "volume-x" : "volume-2", { size: 13 });
|
|
8612
9763
|
mutePill.appendChild(ic2);
|
|
8613
9764
|
if (v.muted) {
|
|
8614
9765
|
const t = document.createElement("span");
|
|
@@ -8703,7 +9854,7 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
8703
9854
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
8704
9855
|
`;
|
|
8705
9856
|
if (expandBtn) {
|
|
8706
|
-
expandBtn.
|
|
9857
|
+
expandBtn.innerHTML = lucideSvg("x", { size: 16 });
|
|
8707
9858
|
expandBtn.setAttribute("aria-label", "Minimize");
|
|
8708
9859
|
}
|
|
8709
9860
|
if (video && video.muted) {
|
|
@@ -8726,7 +9877,7 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
8726
9877
|
}
|
|
8727
9878
|
const closeButton = document.createElement("button");
|
|
8728
9879
|
closeButton.type = "button";
|
|
8729
|
-
closeButton.
|
|
9880
|
+
closeButton.innerHTML = lucideSvg("x", { size: 16 });
|
|
8730
9881
|
closeButton.setAttribute("aria-label", "Close");
|
|
8731
9882
|
closeButton.style.cssText = ctrlBtnCss;
|
|
8732
9883
|
closeButton.addEventListener("click", (e) => {
|
|
@@ -9746,13 +10897,29 @@ function evaluateRule(rule, snapshot, namespaces) {
|
|
|
9746
10897
|
const result = evaluateExpr(rule.when, snapshot, namespaces);
|
|
9747
10898
|
return result === true;
|
|
9748
10899
|
}
|
|
9749
|
-
class
|
|
10900
|
+
const _IntentRuleEvaluator = class _IntentRuleEvaluator {
|
|
9750
10901
|
constructor() {
|
|
9751
10902
|
this.armed = [];
|
|
9752
10903
|
this.snapshot = {};
|
|
9753
10904
|
this.namespaces = {};
|
|
9754
10905
|
this.firedThisSession = /* @__PURE__ */ new Set();
|
|
9755
10906
|
this.silencedThisSession = /* @__PURE__ */ new Set();
|
|
10907
|
+
this.oneInterruptionPerSession = false;
|
|
10908
|
+
this.interruptiveBudgetSpent = false;
|
|
10909
|
+
this.ttfiMs = 0;
|
|
10910
|
+
this.sessionStartMs = Date.now();
|
|
10911
|
+
this.nowFn = () => Date.now();
|
|
10912
|
+
}
|
|
10913
|
+
/** Tune governance. `now` also (re)bases the TTFI session clock. */
|
|
10914
|
+
setGovernance(opts) {
|
|
10915
|
+
if (opts.oneInterruptionPerSession !== void 0) {
|
|
10916
|
+
this.oneInterruptionPerSession = opts.oneInterruptionPerSession;
|
|
10917
|
+
}
|
|
10918
|
+
if (opts.ttfiMs !== void 0) this.ttfiMs = opts.ttfiMs;
|
|
10919
|
+
if (opts.now) {
|
|
10920
|
+
this.nowFn = opts.now;
|
|
10921
|
+
this.sessionStartMs = opts.now();
|
|
10922
|
+
}
|
|
9756
10923
|
}
|
|
9757
10924
|
// ─── snapshot management ───
|
|
9758
10925
|
updateSignal(signal, value) {
|
|
@@ -9788,12 +10955,15 @@ class IntentRuleEvaluator {
|
|
|
9788
10955
|
}
|
|
9789
10956
|
markFired(campaignId) {
|
|
9790
10957
|
this.firedThisSession.add(campaignId);
|
|
10958
|
+
this.interruptiveBudgetSpent = true;
|
|
9791
10959
|
}
|
|
9792
10960
|
/** Clear all per-session state. Caller invokes on logout or explicit
|
|
9793
10961
|
* session reset. */
|
|
9794
10962
|
reset() {
|
|
9795
10963
|
this.firedThisSession.clear();
|
|
9796
10964
|
this.silencedThisSession.clear();
|
|
10965
|
+
this.interruptiveBudgetSpent = false;
|
|
10966
|
+
this.sessionStartMs = this.nowFn();
|
|
9797
10967
|
}
|
|
9798
10968
|
// ─── the main dispatch ───
|
|
9799
10969
|
/**
|
|
@@ -9816,6 +10986,11 @@ class IntentRuleEvaluator {
|
|
|
9816
10986
|
* 5. If nothing matches, return 'none'.
|
|
9817
10987
|
*/
|
|
9818
10988
|
onSignalChanged(signal) {
|
|
10989
|
+
if (this.oneInterruptionPerSession && this.interruptiveBudgetSpent) {
|
|
10990
|
+
return { kind: "none" };
|
|
10991
|
+
}
|
|
10992
|
+
const sessionElapsedMs = this.nowFn() - this.sessionStartMs;
|
|
10993
|
+
const exemptFromTtfi = _IntentRuleEvaluator.EXIT_SIGNALS.includes(signal);
|
|
9819
10994
|
const candidates = this.armed.filter((c) => c.rule.fire_on.includes(signal)).filter((c) => !this.firedThisSession.has(c.id)).filter((c) => !this.silencedThisSession.has(c.id)).sort((a, b) => {
|
|
9820
10995
|
if (b.rule.priority !== a.rule.priority) {
|
|
9821
10996
|
return b.rule.priority - a.rule.priority;
|
|
@@ -9825,6 +11000,9 @@ class IntentRuleEvaluator {
|
|
|
9825
11000
|
for (let i = 0; i < candidates.length; i++) {
|
|
9826
11001
|
const c = candidates[i];
|
|
9827
11002
|
if (!evaluateRule(c.rule, this.snapshot, this.namespaces)) continue;
|
|
11003
|
+
if (this.ttfiMs > 0 && sessionElapsedMs < this.ttfiMs && !exemptFromTtfi) {
|
|
11004
|
+
continue;
|
|
11005
|
+
}
|
|
9828
11006
|
if (c.rule.suppress_competing) {
|
|
9829
11007
|
const suppressIds = this.armed.filter((other) => other.id !== c.id).map((other) => other.id);
|
|
9830
11008
|
suppressIds.forEach((id) => this.silencedThisSession.add(id));
|
|
@@ -9838,7 +11016,12 @@ class IntentRuleEvaluator {
|
|
|
9838
11016
|
}
|
|
9839
11017
|
return { kind: "none" };
|
|
9840
11018
|
}
|
|
9841
|
-
}
|
|
11019
|
+
};
|
|
11020
|
+
_IntentRuleEvaluator.EXIT_SIGNALS = [
|
|
11021
|
+
"exit_intent",
|
|
11022
|
+
"back_button"
|
|
11023
|
+
];
|
|
11024
|
+
let IntentRuleEvaluator = _IntentRuleEvaluator;
|
|
9842
11025
|
class ContactScoresFetcher {
|
|
9843
11026
|
constructor(cfg) {
|
|
9844
11027
|
this.lastFetchedAt = 0;
|
|
@@ -10192,7 +11375,7 @@ class PrefetchBundleClient {
|
|
|
10192
11375
|
}
|
|
10193
11376
|
let response;
|
|
10194
11377
|
try {
|
|
10195
|
-
response = await fetch(url, { method: "GET", headers });
|
|
11378
|
+
response = await fetch(url, { method: "GET", headers, cache: "no-cache" });
|
|
10196
11379
|
} catch (err) {
|
|
10197
11380
|
logger.warn("prefetch-bundle fetch network error:", err);
|
|
10198
11381
|
return this.currentBundle;
|
|
@@ -11217,8 +12400,8 @@ class AegisWidgetManager {
|
|
|
11217
12400
|
{ label: "Prize 3", color: "#48dbfb" },
|
|
11218
12401
|
{ label: "Prize 4", color: "#ff6348" }
|
|
11219
12402
|
];
|
|
11220
|
-
const
|
|
11221
|
-
const wheel = document.createElementNS(
|
|
12403
|
+
const SVG_NS2 = "http://www.w3.org/2000/svg";
|
|
12404
|
+
const wheel = document.createElementNS(SVG_NS2, "svg");
|
|
11222
12405
|
wheel.setAttribute("viewBox", "-160 -160 320 320");
|
|
11223
12406
|
wheel.setAttribute("width", "300");
|
|
11224
12407
|
wheel.setAttribute("height", "300");
|
|
@@ -11234,7 +12417,7 @@ class AegisWidgetManager {
|
|
|
11234
12417
|
const x2 = Math.cos(end) * radius;
|
|
11235
12418
|
const y2 = Math.sin(end) * radius;
|
|
11236
12419
|
const largeArc = anglePer > Math.PI ? 1 : 0;
|
|
11237
|
-
const path = document.createElementNS(
|
|
12420
|
+
const path = document.createElementNS(SVG_NS2, "path");
|
|
11238
12421
|
path.setAttribute(
|
|
11239
12422
|
"d",
|
|
11240
12423
|
`M 0 0 L ${x1.toFixed(2)} ${y1.toFixed(2)} A ${radius} ${radius} 0 ${largeArc} 1 ${x2.toFixed(2)} ${y2.toFixed(2)} Z`
|
|
@@ -11246,7 +12429,7 @@ class AegisWidgetManager {
|
|
|
11246
12429
|
const labelAngle = start + anglePer / 2;
|
|
11247
12430
|
const lx = Math.cos(labelAngle) * radius * 0.65;
|
|
11248
12431
|
const ly = Math.sin(labelAngle) * radius * 0.65;
|
|
11249
|
-
const text = document.createElementNS(
|
|
12432
|
+
const text = document.createElementNS(SVG_NS2, "text");
|
|
11250
12433
|
text.setAttribute("x", lx.toFixed(2));
|
|
11251
12434
|
text.setAttribute("y", ly.toFixed(2));
|
|
11252
12435
|
text.setAttribute("fill", "#ffffff");
|
|
@@ -11358,7 +12541,8 @@ class AegisWidgetManager {
|
|
|
11358
12541
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
11359
12542
|
`;
|
|
11360
12543
|
const closeBtn = document.createElement("button");
|
|
11361
|
-
closeBtn.innerHTML = "
|
|
12544
|
+
closeBtn.innerHTML = lucideSvg("x", { size: 16 });
|
|
12545
|
+
closeBtn.setAttribute("aria-label", "Close");
|
|
11362
12546
|
closeBtn.className = "aegis-spin-wheel-close";
|
|
11363
12547
|
closeBtn.style.cssText = `
|
|
11364
12548
|
position: absolute;
|
|
@@ -12338,8 +13522,9 @@ class AegisWidgetManager {
|
|
|
12338
13522
|
}
|
|
12339
13523
|
if (config.show_timer && config.timer_minutes) {
|
|
12340
13524
|
const timer = document.createElement("div");
|
|
12341
|
-
timer.style.cssText = "margin: 0 0 24px 0;
|
|
12342
|
-
timer.
|
|
13525
|
+
timer.style.cssText = "margin: 0 0 24px 0; display: flex; align-items: center; justify-content: center; gap: 6px; font-size: 14px; color: #999;";
|
|
13526
|
+
timer.innerHTML = lucideSvg("clock", { size: 14 });
|
|
13527
|
+
timer.appendChild(document.createTextNode(`Offer expires in ${config.timer_minutes} minutes`));
|
|
12343
13528
|
modal.appendChild(timer);
|
|
12344
13529
|
}
|
|
12345
13530
|
const ctaButton = document.createElement("button");
|
|
@@ -12470,7 +13655,7 @@ class AegisWidgetManager {
|
|
|
12470
13655
|
});
|
|
12471
13656
|
modal.innerHTML = `
|
|
12472
13657
|
<div style="text-align: center; padding: 20px;">
|
|
12473
|
-
<div style="
|
|
13658
|
+
<div style="margin-bottom: 16px; color: #10b981;">${lucideSvg("check", { size: 48 })}</div>
|
|
12474
13659
|
<h3 style="margin: 0 0 12px 0; color: #1a73e8;">Thank You!</h3>
|
|
12475
13660
|
<p style="margin: 0; color: #666;">Check your email for your discount code!</p>
|
|
12476
13661
|
</div>
|
|
@@ -12716,6 +13901,9 @@ class AegisMessageRuntime {
|
|
|
12716
13901
|
getCartState: () => this.deriveCartState()
|
|
12717
13902
|
});
|
|
12718
13903
|
this.intentRuleEvaluator = new IntentRuleEvaluator();
|
|
13904
|
+
if (config.governance) {
|
|
13905
|
+
this.intentRuleEvaluator.setGovernance(config.governance);
|
|
13906
|
+
}
|
|
12719
13907
|
this.contactScores = new ContactScoresFetcher({
|
|
12720
13908
|
// Falls back to same-origin when no apiHost configured (storefront
|
|
12721
13909
|
// typical case) — matches WidgetManager/InAppManager handling
|