@active-reach/web-sdk 1.21.0 → 1.22.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.map +1 -1
- package/dist/core/prefetch-bundle-client.d.ts.map +1 -1
- package/dist/inapp/AegisInAppManager.d.ts +21 -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/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 +107 -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 +1148 -269
- 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 +10 -0
- 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,700 @@ 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 buildProgressElement(el, ctx, accent, muted) {
|
|
427
|
+
const { trackEvent, campaign, sanitizeColor } = ctx;
|
|
428
|
+
const goal = el.goal_type || "cart_total";
|
|
429
|
+
const moneyGoal = goal === "cart_total";
|
|
430
|
+
const fill = el.fill ? sanitizeColor(el.fill) : accent;
|
|
431
|
+
const props = () => ctx.properties && ctx.properties() || {};
|
|
432
|
+
const sym = () => {
|
|
433
|
+
var _a;
|
|
434
|
+
if (el.currency_symbol) return el.currency_symbol;
|
|
435
|
+
const code = ctx.getCartState && ((_a = ctx.getCartState()) == null ? void 0 : _a.currency);
|
|
436
|
+
const M = { INR: "₹", USD: "$", EUR: "€", GBP: "£" };
|
|
437
|
+
return code && M[code] || "";
|
|
438
|
+
};
|
|
439
|
+
const threshold = () => {
|
|
440
|
+
if (typeof el.threshold === "number" && el.threshold > 0) return el.threshold;
|
|
441
|
+
if (el.threshold_source === "free_delivery_setting") {
|
|
442
|
+
const v = Number(props()["cart.free_delivery_above"]);
|
|
443
|
+
if (v > 0) return v;
|
|
444
|
+
}
|
|
445
|
+
return 0;
|
|
446
|
+
};
|
|
447
|
+
const readCur = () => {
|
|
448
|
+
const cart = ctx.getCartState && ctx.getCartState();
|
|
449
|
+
if (goal === "items_in_cart") return Number(cart == null ? void 0 : cart.itemCount) || 0;
|
|
450
|
+
if (goal === "cart_total") return Number(cart == null ? void 0 : cart.total) || 0;
|
|
451
|
+
const p = props();
|
|
452
|
+
if (goal === "loyalty_points") return Number(p["loyalty.points"]) || 0;
|
|
453
|
+
if (goal === "referrals") return Number(p["referrals.count"]) || 0;
|
|
454
|
+
return 0;
|
|
455
|
+
};
|
|
456
|
+
const wrap = document.createElement("div");
|
|
457
|
+
wrap.style.cssText = "display:flex;flex-direction:column;gap:3px;min-width:0;width:100%;";
|
|
458
|
+
const sub = document.createElement("div");
|
|
459
|
+
sub.style.cssText = `font-size:11.5px;line-height:1.2;color:${muted};white-space:nowrap;overflow:hidden;text-overflow:ellipsis;`;
|
|
460
|
+
const shell = document.createElement("div");
|
|
461
|
+
shell.style.cssText = `height:3px;border-radius:999px;background:color-mix(in srgb, ${fill} 16%, transparent);overflow:hidden;`;
|
|
462
|
+
const bar = document.createElement("div");
|
|
463
|
+
bar.style.cssText = `height:100%;border-radius:999px;background:${fill};width:0%;transition:width .4s cubic-bezier(.4,0,.2,1);`;
|
|
464
|
+
shell.appendChild(bar);
|
|
465
|
+
wrap.appendChild(sub);
|
|
466
|
+
wrap.appendChild(shell);
|
|
467
|
+
let firedUnlock = false;
|
|
468
|
+
const update = () => {
|
|
469
|
+
const th = threshold();
|
|
470
|
+
const cur = readCur();
|
|
471
|
+
const pct = th > 0 ? Math.max(0, Math.min(100, cur / th * 100)) : 0;
|
|
472
|
+
bar.style.width = `${pct}%`;
|
|
473
|
+
if (th > 0 && pct >= 100) {
|
|
474
|
+
sub.textContent = el.reward_text || "Unlocked!";
|
|
475
|
+
sub.style.color = "#34d399";
|
|
476
|
+
if (!firedUnlock) {
|
|
477
|
+
firedUnlock = true;
|
|
478
|
+
trackEvent(campaign.id, "clicked", { stepId: el.id || "unlocked" });
|
|
479
|
+
}
|
|
480
|
+
} else {
|
|
481
|
+
sub.style.color = muted;
|
|
482
|
+
const remaining = Math.max(0, th - cur);
|
|
483
|
+
const pre = moneyGoal ? sym() : "";
|
|
484
|
+
const pctStr = el.show_pct && th > 0 ? ` · ${Math.round(pct)}%` : "";
|
|
485
|
+
sub.textContent = th > 0 ? `Shop for ${pre}${remaining.toFixed(0)} more${pctStr}` : el.reward_text || "";
|
|
486
|
+
}
|
|
487
|
+
};
|
|
488
|
+
update();
|
|
489
|
+
const timer = setInterval(update, 1e3);
|
|
490
|
+
if (typeof window !== "undefined") {
|
|
491
|
+
window.addEventListener("beforeunload", () => clearInterval(timer), { once: true });
|
|
492
|
+
}
|
|
493
|
+
return wrap;
|
|
494
|
+
}
|
|
495
|
+
function renderCardFromTemplate(card, opts) {
|
|
496
|
+
const { ctx, action, layout, layoutAccent } = opts;
|
|
497
|
+
const inline = action === "cart";
|
|
498
|
+
const { campaign, trackEvent, sanitizeUrl, sanitizeColor } = ctx;
|
|
499
|
+
const tpl = applyPerCardOverride(opts.template, asLook(card.style));
|
|
500
|
+
const frame = tpl.frame || {};
|
|
501
|
+
const meta = card.metadata || {};
|
|
502
|
+
const accent = typeof frame.accent === "string" && frame.accent ? sanitizeColor(frame.accent) : layoutAccent;
|
|
503
|
+
const brand = `var(--aegis-brand-accent, ${accent})`;
|
|
504
|
+
const fg = contrastFg(frame.bg ? sanitizeColor(frame.bg) : "#ffffff");
|
|
505
|
+
const muted = fg === "#ffffff" ? "rgba(255,255,255,0.72)" : "#6b7280";
|
|
506
|
+
const tile = document.createElement("div");
|
|
507
|
+
const radius = frame.radius !== void 0 ? `${parseInt(String(frame.radius), 10) || 12}px` : "12px";
|
|
508
|
+
const fLayout = frame.layout;
|
|
509
|
+
const dir = fLayout === "row" ? "row" : "column";
|
|
510
|
+
const tileGap = frame.gap != null ? frame.gap : 6;
|
|
511
|
+
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;";
|
|
512
|
+
tile.style.cssText = `
|
|
513
|
+
box-sizing:border-box; display:flex; flex-direction:${dir}; ${fLayout === "row" ? "align-items:center;" : ""} gap:${tileGap}px; position:relative;
|
|
514
|
+
color:${fg};
|
|
515
|
+
background:${frame.bg ? sanitizeColor(frame.bg) : "#ffffff"};
|
|
516
|
+
border:1px solid ${frame.border ? sanitizeColor(frame.border) : "transparent"};
|
|
517
|
+
border-radius:${radius}; padding:8px;
|
|
518
|
+
${frame.max_width ? `max-width:${frame.max_width}px;` : ""}${frame.min_width ? `min-width:${frame.min_width}px;` : ""}
|
|
519
|
+
${sizing}
|
|
520
|
+
cursor:${card.cta_url || inline ? "pointer" : "default"}; transition:transform 0.15s ease;
|
|
521
|
+
`;
|
|
522
|
+
const elements = tpl.elements && tpl.elements.length ? tpl.elements : DEFAULT_CARD_TEMPLATE.elements;
|
|
523
|
+
let imageWrap = null;
|
|
524
|
+
const paintInto = (container, els) => {
|
|
525
|
+
for (const el of els) {
|
|
526
|
+
switch (el.type) {
|
|
527
|
+
case "image": {
|
|
528
|
+
const wrap = document.createElement("div");
|
|
529
|
+
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;`;
|
|
530
|
+
const safeVideo = card.video_url ? sanitizeUrl(card.video_url) : "";
|
|
531
|
+
if (safeVideo) {
|
|
532
|
+
const v = document.createElement("video");
|
|
533
|
+
v.src = safeVideo;
|
|
534
|
+
v.muted = true;
|
|
535
|
+
v.loop = true;
|
|
536
|
+
v.autoplay = true;
|
|
537
|
+
v.playsInline = true;
|
|
538
|
+
v.setAttribute("playsinline", "");
|
|
539
|
+
v.style.cssText = "width:100%;height:100%;object-fit:cover;display:block;";
|
|
540
|
+
wrap.appendChild(v);
|
|
541
|
+
} else if (card.image_url) {
|
|
542
|
+
const safe = sanitizeUrl(card.image_url);
|
|
543
|
+
if (safe) {
|
|
544
|
+
const img = document.createElement("img");
|
|
545
|
+
img.src = safe;
|
|
546
|
+
img.alt = "";
|
|
547
|
+
img.loading = "lazy";
|
|
548
|
+
img.style.cssText = "width:100%;height:100%;object-fit:cover;display:block;";
|
|
549
|
+
wrap.appendChild(img);
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
imageWrap = wrap;
|
|
553
|
+
container.appendChild(wrap);
|
|
554
|
+
break;
|
|
555
|
+
}
|
|
556
|
+
case "badge": {
|
|
557
|
+
const text = el.text;
|
|
558
|
+
if (!text) break;
|
|
559
|
+
const badge = document.createElement("span");
|
|
560
|
+
badge.textContent = text;
|
|
561
|
+
const bg = el.color ? sanitizeColor(el.color) : brand;
|
|
562
|
+
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;`;
|
|
563
|
+
(imageWrap || container).appendChild(badge);
|
|
564
|
+
break;
|
|
565
|
+
}
|
|
566
|
+
case "price": {
|
|
567
|
+
const node = paintPrice(card, el, accent, ctx);
|
|
568
|
+
if (node) container.appendChild(node);
|
|
569
|
+
break;
|
|
570
|
+
}
|
|
571
|
+
case "title": {
|
|
572
|
+
if (!card.title) break;
|
|
573
|
+
const t = document.createElement("div");
|
|
574
|
+
t.textContent = card.title;
|
|
575
|
+
const lines = el.lines && el.lines > 0 ? el.lines : 2;
|
|
576
|
+
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;`;
|
|
577
|
+
container.appendChild(t);
|
|
578
|
+
break;
|
|
579
|
+
}
|
|
580
|
+
case "subtitle": {
|
|
581
|
+
if (!card.body) break;
|
|
582
|
+
const s = document.createElement("div");
|
|
583
|
+
s.textContent = card.body;
|
|
584
|
+
const lines = el.lines && el.lines > 0 ? el.lines : 2;
|
|
585
|
+
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;`;
|
|
586
|
+
container.appendChild(s);
|
|
587
|
+
break;
|
|
588
|
+
}
|
|
589
|
+
case "rating": {
|
|
590
|
+
const node = paintRating(card);
|
|
591
|
+
if (node) container.appendChild(node);
|
|
592
|
+
break;
|
|
593
|
+
}
|
|
594
|
+
case "category": {
|
|
595
|
+
const cat = meta.category;
|
|
596
|
+
if (typeof cat !== "string" || !cat) break;
|
|
597
|
+
const chip = document.createElement("span");
|
|
598
|
+
chip.textContent = cat;
|
|
599
|
+
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;";
|
|
600
|
+
container.appendChild(chip);
|
|
601
|
+
break;
|
|
602
|
+
}
|
|
603
|
+
// ── rich-card-editor elements (P0) ──────────────────────────────────
|
|
604
|
+
case "icon": {
|
|
605
|
+
const px = ICON_PX[el.size || "md"] || 30;
|
|
606
|
+
const node = document.createElement("div");
|
|
607
|
+
const iconColor = el.color ? sanitizeColor(el.color) : fg;
|
|
608
|
+
if (el.bubble) {
|
|
609
|
+
const bubbleTint = el.color ? sanitizeColor(el.color) : brand;
|
|
610
|
+
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);`;
|
|
611
|
+
} else {
|
|
612
|
+
node.style.cssText = "flex:0 0 auto;display:flex;align-items:center;";
|
|
613
|
+
}
|
|
614
|
+
const svg = lucideSvgEl(el.icon_name || "circle-check", {
|
|
615
|
+
size: el.bubble ? Math.round(px * 0.55) : Math.round(px * 0.7),
|
|
616
|
+
color: iconColor,
|
|
617
|
+
strokeWidth: 2
|
|
618
|
+
});
|
|
619
|
+
if (svg) node.appendChild(svg);
|
|
620
|
+
container.appendChild(node);
|
|
621
|
+
break;
|
|
622
|
+
}
|
|
623
|
+
case "text": {
|
|
624
|
+
const t = document.createElement("div");
|
|
625
|
+
const fs = TEXT_PX[el.size || "md"] || 13;
|
|
626
|
+
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;`;
|
|
627
|
+
t.textContent = interpolateTokens(el.content ?? "", ctx);
|
|
628
|
+
container.appendChild(t);
|
|
629
|
+
break;
|
|
630
|
+
}
|
|
631
|
+
case "spacer": {
|
|
632
|
+
const sp = document.createElement("div");
|
|
633
|
+
sp.style.height = `${el.height ?? 8}px`;
|
|
634
|
+
container.appendChild(sp);
|
|
635
|
+
break;
|
|
636
|
+
}
|
|
637
|
+
case "progress": {
|
|
638
|
+
container.appendChild(buildProgressElement(el, ctx, brand, muted));
|
|
639
|
+
break;
|
|
640
|
+
}
|
|
641
|
+
case "group": {
|
|
642
|
+
const g = document.createElement("div");
|
|
643
|
+
const gdir = el.layout === "row" ? "row" : "column";
|
|
644
|
+
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;"}`;
|
|
645
|
+
paintInto(g, el.elements || []);
|
|
646
|
+
container.appendChild(g);
|
|
647
|
+
break;
|
|
648
|
+
}
|
|
649
|
+
case "cta": {
|
|
650
|
+
const label = el.text || card.cta_text || (inline ? "Add" : "Shop");
|
|
651
|
+
const cta = document.createElement("button");
|
|
652
|
+
cta.className = "aegis-cta";
|
|
653
|
+
cta.textContent = label;
|
|
654
|
+
const overlayOnImage = !!el.overlay && !!imageWrap;
|
|
655
|
+
if (overlayOnImage) {
|
|
656
|
+
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);`;
|
|
657
|
+
} else {
|
|
658
|
+
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;`;
|
|
659
|
+
}
|
|
660
|
+
cta.addEventListener("click", (e) => {
|
|
661
|
+
e.stopPropagation();
|
|
662
|
+
trackEvent(campaign.id, "clicked", { stepId: el.id || "add" });
|
|
663
|
+
if (inline) {
|
|
664
|
+
if (typeof window !== "undefined") {
|
|
665
|
+
window.dispatchEvent(
|
|
666
|
+
new CustomEvent("aegis:add-to-cart", {
|
|
667
|
+
detail: {
|
|
668
|
+
campaign_id: campaign.id,
|
|
669
|
+
product_id: meta.product_id,
|
|
670
|
+
sku: meta.sku,
|
|
671
|
+
title: card.title,
|
|
672
|
+
price: meta.price ?? card.body,
|
|
673
|
+
image_url: card.image_url,
|
|
674
|
+
cta_url: card.cta_url
|
|
675
|
+
}
|
|
676
|
+
})
|
|
677
|
+
);
|
|
678
|
+
}
|
|
679
|
+
return;
|
|
680
|
+
}
|
|
681
|
+
if (card.cta_url) {
|
|
682
|
+
const safe = sanitizeUrl(card.cta_url);
|
|
683
|
+
if (safe) ctx.navigate ? ctx.navigate(safe) : window.location.href = safe;
|
|
684
|
+
}
|
|
685
|
+
});
|
|
686
|
+
(overlayOnImage ? imageWrap : container).appendChild(cta);
|
|
687
|
+
break;
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
};
|
|
692
|
+
paintInto(tile, elements);
|
|
693
|
+
const open = (e) => {
|
|
694
|
+
e.stopPropagation();
|
|
695
|
+
trackEvent(campaign.id, "clicked");
|
|
696
|
+
if (inline) {
|
|
697
|
+
if (typeof window !== "undefined") {
|
|
698
|
+
window.dispatchEvent(
|
|
699
|
+
new CustomEvent("aegis:open-product", {
|
|
700
|
+
detail: {
|
|
701
|
+
campaign_id: campaign.id,
|
|
702
|
+
product_id: meta.product_id,
|
|
703
|
+
sku: meta.sku,
|
|
704
|
+
cta_url: card.cta_url
|
|
705
|
+
}
|
|
706
|
+
})
|
|
707
|
+
);
|
|
708
|
+
}
|
|
709
|
+
return;
|
|
710
|
+
}
|
|
711
|
+
if (card.cta_url) {
|
|
712
|
+
const safe = sanitizeUrl(card.cta_url);
|
|
713
|
+
if (safe) ctx.navigate ? ctx.navigate(safe) : window.location.href = safe;
|
|
714
|
+
}
|
|
715
|
+
};
|
|
716
|
+
if (inline || card.cta_url) tile.addEventListener("click", open);
|
|
717
|
+
return tile;
|
|
718
|
+
}
|
|
28
719
|
const MAX_CARDS_RENDERED = 10;
|
|
29
720
|
function renderCarouselCards(ctx) {
|
|
30
|
-
const { campaign, trackEvent,
|
|
721
|
+
const { campaign, trackEvent, sanitizeColor, log, addAnimationStyles } = ctx;
|
|
31
722
|
const ic = campaign.interactive_config || {};
|
|
32
723
|
const rawCards = Array.isArray(ic.cards) ? ic.cards : [];
|
|
33
724
|
const cards = rawCards.slice(0, MAX_CARDS_RENDERED);
|
|
@@ -70,7 +761,7 @@ function renderCarouselCards(ctx) {
|
|
|
70
761
|
headerText.appendChild(body);
|
|
71
762
|
header.appendChild(headerText);
|
|
72
763
|
const closeBtn = document.createElement("button");
|
|
73
|
-
closeBtn.
|
|
764
|
+
closeBtn.innerHTML = lucideSvg("x", { size: 16 });
|
|
74
765
|
closeBtn.setAttribute("aria-label", "Close");
|
|
75
766
|
closeBtn.style.cssText = `
|
|
76
767
|
background: transparent; border: none; color: inherit;
|
|
@@ -89,68 +780,16 @@ function renderCarouselCards(ctx) {
|
|
|
89
780
|
padding-bottom: 4px; -webkit-overflow-scrolling: touch;
|
|
90
781
|
`;
|
|
91
782
|
track.style.msOverflowStyle = "none";
|
|
783
|
+
const template = resolveGlobalTemplate(ic);
|
|
92
784
|
cards.forEach((c, i) => {
|
|
93
|
-
const tile =
|
|
785
|
+
const tile = renderCardFromTemplate(c, {
|
|
786
|
+
template,
|
|
787
|
+
ctx,
|
|
788
|
+
action: "navigate",
|
|
789
|
+
layout: "row",
|
|
790
|
+
layoutAccent: accent
|
|
791
|
+
});
|
|
94
792
|
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
793
|
track.appendChild(tile);
|
|
155
794
|
});
|
|
156
795
|
card.appendChild(track);
|
|
@@ -314,7 +953,7 @@ function renderStickyBar(ctx) {
|
|
|
314
953
|
};
|
|
315
954
|
if (dismissible) {
|
|
316
955
|
const close = document.createElement("button");
|
|
317
|
-
close.
|
|
956
|
+
close.innerHTML = lucideSvg("x", { size: 16 });
|
|
318
957
|
close.setAttribute("aria-label", "Dismiss");
|
|
319
958
|
close.style.cssText = `
|
|
320
959
|
background: transparent; border: none; color: inherit;
|
|
@@ -344,13 +983,12 @@ function buildProgressBar(ctx, inline) {
|
|
|
344
983
|
const source = ic.progress_source === "sse" ? "sse" : "client";
|
|
345
984
|
addAnimationStyles();
|
|
346
985
|
const brand = sanitizeColor(campaign.background_color || "#4169e1");
|
|
986
|
+
const accentVar = `var(--aegis-brand-accent, ${brand})`;
|
|
347
987
|
const branded = ic.surface_style === "branded";
|
|
348
|
-
const bg = branded ?
|
|
988
|
+
const bg = branded ? accentVar : "#ffffff";
|
|
349
989
|
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`;
|
|
990
|
+
const fill = ic.progress_fill_color ? sanitizeColor(ic.progress_fill_color) : branded ? "#ffffff" : accentVar;
|
|
991
|
+
const track = branded ? "rgba(255,255,255,0.25)" : `color-mix(in srgb, ${fill} 14%, transparent)`;
|
|
354
992
|
const bar = document.createElement("div");
|
|
355
993
|
bar.className = "aegis-in-app-progress-bar";
|
|
356
994
|
bar.setAttribute("data-campaign-id", campaign.id);
|
|
@@ -730,7 +1368,7 @@ function renderCoachmarkTour(ctx) {
|
|
|
730
1368
|
}
|
|
731
1369
|
const MAX_PRODUCTS = 24;
|
|
732
1370
|
function renderProductRecommendation(ctx) {
|
|
733
|
-
const { campaign, trackEvent,
|
|
1371
|
+
const { campaign, trackEvent, sanitizeColor, log, addAnimationStyles } = ctx;
|
|
734
1372
|
const ic = campaign.interactive_config || {};
|
|
735
1373
|
const rawCards = Array.isArray(ic.cards) ? ic.cards : [];
|
|
736
1374
|
const cards = rawCards.slice(0, MAX_PRODUCTS);
|
|
@@ -739,7 +1377,7 @@ function renderProductRecommendation(ctx) {
|
|
|
739
1377
|
return;
|
|
740
1378
|
}
|
|
741
1379
|
const layout = ic.rec_layout || "grid";
|
|
742
|
-
const
|
|
1380
|
+
const template = resolveGlobalTemplate(ic);
|
|
743
1381
|
addAnimationStyles();
|
|
744
1382
|
const bg = "#ffffff";
|
|
745
1383
|
const fg = "#0f172a";
|
|
@@ -782,7 +1420,7 @@ function renderProductRecommendation(ctx) {
|
|
|
782
1420
|
headerText.appendChild(body);
|
|
783
1421
|
header.appendChild(headerText);
|
|
784
1422
|
const close = document.createElement("button");
|
|
785
|
-
close.
|
|
1423
|
+
close.innerHTML = lucideSvg("x", { size: 18 });
|
|
786
1424
|
close.setAttribute("aria-label", "Close");
|
|
787
1425
|
close.style.cssText = `
|
|
788
1426
|
background: transparent; border: none; color: inherit;
|
|
@@ -807,82 +1445,9 @@ function renderProductRecommendation(ctx) {
|
|
|
807
1445
|
`;
|
|
808
1446
|
}
|
|
809
1447
|
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);
|
|
1448
|
+
grid.appendChild(
|
|
1449
|
+
renderCardFromTemplate(c, { template, ctx, action: "navigate", layout, layoutAccent: accent })
|
|
1450
|
+
);
|
|
886
1451
|
});
|
|
887
1452
|
sheet.appendChild(grid);
|
|
888
1453
|
overlay.appendChild(sheet);
|
|
@@ -894,6 +1459,88 @@ function renderProductRecommendation(ctx) {
|
|
|
894
1459
|
});
|
|
895
1460
|
document.body.appendChild(overlay);
|
|
896
1461
|
}
|
|
1462
|
+
function renderProductRecommendationInline(ctx, target) {
|
|
1463
|
+
const { campaign, sanitizeColor, addAnimationStyles, log } = ctx;
|
|
1464
|
+
const ic = campaign.interactive_config || {};
|
|
1465
|
+
const rawCards = Array.isArray(ic.cards) ? ic.cards : [];
|
|
1466
|
+
const cards = rawCards.slice(0, MAX_PRODUCTS);
|
|
1467
|
+
if (cards.length === 0) {
|
|
1468
|
+
log("product_recommendation (inline) rendered with zero products — skipping", "warn");
|
|
1469
|
+
return false;
|
|
1470
|
+
}
|
|
1471
|
+
const layout = ic.rec_layout || "row";
|
|
1472
|
+
const template = resolveGlobalTemplate(ic);
|
|
1473
|
+
const fg = "#0f172a";
|
|
1474
|
+
const accent = sanitizeColor(campaign.background_color || "#4169e1");
|
|
1475
|
+
addAnimationStyles();
|
|
1476
|
+
const section = document.createElement("section");
|
|
1477
|
+
section.className = "aegis-in-app-product-rec-inline";
|
|
1478
|
+
section.setAttribute("data-campaign-id", campaign.id);
|
|
1479
|
+
section.style.cssText = `
|
|
1480
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
1481
|
+
color: ${fg};
|
|
1482
|
+
`;
|
|
1483
|
+
if (campaign.title) {
|
|
1484
|
+
const title = document.createElement("h2");
|
|
1485
|
+
title.textContent = campaign.title;
|
|
1486
|
+
title.style.cssText = "font-weight: 700; font-size: 16px; margin: 0 0 2px;";
|
|
1487
|
+
section.appendChild(title);
|
|
1488
|
+
}
|
|
1489
|
+
if (campaign.body) {
|
|
1490
|
+
const body = document.createElement("div");
|
|
1491
|
+
body.textContent = campaign.body;
|
|
1492
|
+
body.style.cssText = "font-size: 13px; opacity: 0.65; line-height: 1.4; margin-bottom: 10px;";
|
|
1493
|
+
section.appendChild(body);
|
|
1494
|
+
}
|
|
1495
|
+
const grid = document.createElement("div");
|
|
1496
|
+
const isRow = layout !== "grid";
|
|
1497
|
+
if (layout === "grid") {
|
|
1498
|
+
grid.style.cssText = "display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px;";
|
|
1499
|
+
} else {
|
|
1500
|
+
grid.style.cssText = `
|
|
1501
|
+
display: flex; gap: 10px; overflow-x: auto;
|
|
1502
|
+
scroll-snap-type: x proximity; padding: 0 0 6px;
|
|
1503
|
+
-webkit-overflow-scrolling: touch; scrollbar-width: none;
|
|
1504
|
+
`;
|
|
1505
|
+
grid.style.msOverflowStyle = "none";
|
|
1506
|
+
}
|
|
1507
|
+
cards.forEach((c) => {
|
|
1508
|
+
grid.appendChild(
|
|
1509
|
+
renderCardFromTemplate(c, { template, ctx, action: "cart", layout, layoutAccent: accent })
|
|
1510
|
+
);
|
|
1511
|
+
});
|
|
1512
|
+
if (isRow && cards.length > 2) {
|
|
1513
|
+
const wrap = document.createElement("div");
|
|
1514
|
+
wrap.style.cssText = "position: relative;";
|
|
1515
|
+
wrap.appendChild(grid);
|
|
1516
|
+
const arrow = document.createElement("button");
|
|
1517
|
+
arrow.setAttribute("aria-label", "Scroll for more");
|
|
1518
|
+
arrow.innerHTML = "›";
|
|
1519
|
+
arrow.style.cssText = `
|
|
1520
|
+
position: absolute; top: 50%; right: 0; transform: translateY(-50%);
|
|
1521
|
+
width: 30px; height: 30px; border-radius: 999px; border: 1px solid ${fg}1a;
|
|
1522
|
+
background: #fff; color: ${fg}; font-size: 18px; line-height: 1; cursor: pointer;
|
|
1523
|
+
box-shadow: 0 2px 8px rgba(0,0,0,0.12); display: flex; align-items: center;
|
|
1524
|
+
justify-content: center; z-index: 2;
|
|
1525
|
+
`;
|
|
1526
|
+
arrow.addEventListener("click", (e) => {
|
|
1527
|
+
e.stopPropagation();
|
|
1528
|
+
grid.scrollBy({ left: Math.round(grid.clientWidth * 0.8), behavior: "smooth" });
|
|
1529
|
+
});
|
|
1530
|
+
const syncArrow = () => {
|
|
1531
|
+
const atEnd = grid.scrollLeft + grid.clientWidth >= grid.scrollWidth - 8;
|
|
1532
|
+
arrow.style.display = atEnd ? "none" : "flex";
|
|
1533
|
+
};
|
|
1534
|
+
grid.addEventListener("scroll", syncArrow, { passive: true });
|
|
1535
|
+
setTimeout(syncArrow, 0);
|
|
1536
|
+
wrap.appendChild(arrow);
|
|
1537
|
+
section.appendChild(wrap);
|
|
1538
|
+
} else {
|
|
1539
|
+
section.appendChild(grid);
|
|
1540
|
+
}
|
|
1541
|
+
target.appendChild(section);
|
|
1542
|
+
return true;
|
|
1543
|
+
}
|
|
897
1544
|
const MAX_GROUPS = 12;
|
|
898
1545
|
const MAX_FRAMES = 20;
|
|
899
1546
|
const DEFAULT_DURATION_MS = 5e3;
|
|
@@ -997,7 +1644,7 @@ function renderLauncherBar(ctx, cfg, target) {
|
|
|
997
1644
|
if (floating) {
|
|
998
1645
|
const dismiss = document.createElement("button");
|
|
999
1646
|
dismiss.type = "button";
|
|
1000
|
-
dismiss.
|
|
1647
|
+
dismiss.innerHTML = lucideSvg("x", { size: 14 });
|
|
1001
1648
|
dismiss.setAttribute("aria-label", "Dismiss stories");
|
|
1002
1649
|
dismiss.style.cssText = `
|
|
1003
1650
|
flex: 0 0 auto; align-self: center; margin-left: auto;
|
|
@@ -1141,7 +1788,7 @@ function openViewer(ctx, cfg, startGroupIndex, startFrameIndex = 0) {
|
|
|
1141
1788
|
};
|
|
1142
1789
|
const close = document.createElement("button");
|
|
1143
1790
|
close.type = "button";
|
|
1144
|
-
close.
|
|
1791
|
+
close.innerHTML = lucideSvg("x", { size: 18 });
|
|
1145
1792
|
close.setAttribute("aria-label", "Close");
|
|
1146
1793
|
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
1794
|
stage.appendChild(close);
|
|
@@ -1418,7 +2065,7 @@ function openGameModal(ctx, className, maxWidth = 360) {
|
|
|
1418
2065
|
};
|
|
1419
2066
|
const close = document.createElement("button");
|
|
1420
2067
|
close.type = "button";
|
|
1421
|
-
close.
|
|
2068
|
+
close.innerHTML = lucideSvg("x", { size: 15 });
|
|
1422
2069
|
close.setAttribute("aria-label", "Close");
|
|
1423
2070
|
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
2071
|
close.addEventListener("click", () => dismiss(true));
|
|
@@ -2136,14 +2783,15 @@ function buildVideo(ctx, aspect, autoplay, loop) {
|
|
|
2136
2783
|
});
|
|
2137
2784
|
const pill = document.createElement("button");
|
|
2138
2785
|
pill.type = "button";
|
|
2139
|
-
pill.
|
|
2786
|
+
pill.innerHTML = lucideSvg("volume-x", { size: 14 });
|
|
2140
2787
|
pill.setAttribute("aria-label", "Unmute");
|
|
2141
2788
|
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
2789
|
pill.addEventListener("click", (e) => {
|
|
2143
2790
|
var _a2;
|
|
2144
2791
|
e.stopPropagation();
|
|
2145
2792
|
vid.muted = !vid.muted;
|
|
2146
|
-
pill.
|
|
2793
|
+
pill.innerHTML = lucideSvg(vid.muted ? "volume-x" : "volume-2", { size: 14 });
|
|
2794
|
+
pill.setAttribute("aria-label", vid.muted ? "Unmute" : "Mute");
|
|
2147
2795
|
if (!vid.muted) void ((_a2 = vid.play) == null ? void 0 : _a2.call(vid).catch(() => {
|
|
2148
2796
|
}));
|
|
2149
2797
|
});
|
|
@@ -2231,7 +2879,7 @@ function renderVideo(ctx) {
|
|
|
2231
2879
|
}
|
|
2232
2880
|
const close = document.createElement("button");
|
|
2233
2881
|
close.type = "button";
|
|
2234
|
-
close.
|
|
2882
|
+
close.innerHTML = lucideSvg("x", { size: 15 });
|
|
2235
2883
|
close.setAttribute("aria-label", "Close");
|
|
2236
2884
|
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
2885
|
close.addEventListener("click", () => {
|
|
@@ -2276,8 +2924,15 @@ const HEX = /^#[0-9a-fA-F]{3,8}$/;
|
|
|
2276
2924
|
function safeColor(c, fallback) {
|
|
2277
2925
|
return c && HEX.test(c) ? c : fallback;
|
|
2278
2926
|
}
|
|
2279
|
-
const RADIUS = { none: "0", lg: "12px", xl: "16px", "2xl": "20px" };
|
|
2280
2927
|
const ASPECT = { "16:9": "16 / 9", "4:3": "4 / 3", "21:9": "21 / 9" };
|
|
2928
|
+
function _injectHeroResponsiveCss() {
|
|
2929
|
+
if (typeof document === "undefined") return;
|
|
2930
|
+
if (document.getElementById("aegis-hero-style")) return;
|
|
2931
|
+
const style = document.createElement("style");
|
|
2932
|
+
style.id = "aegis-hero-style";
|
|
2933
|
+
style.textContent = ".aegis-hero-root{border-radius:16px;}@media (min-width:768px){.aegis-hero-root{border-radius:0;min-height:45vh;max-height:70vh;}}";
|
|
2934
|
+
document.head.appendChild(style);
|
|
2935
|
+
}
|
|
2281
2936
|
function cardHeadline(c) {
|
|
2282
2937
|
return c.headline ?? c.title ?? "";
|
|
2283
2938
|
}
|
|
@@ -2303,7 +2958,6 @@ function renderHeroInline(ctx, target) {
|
|
|
2303
2958
|
chrome.accent && chrome.accent !== "brand" ? chrome.accent : campaign.background_color,
|
|
2304
2959
|
"#4169e1"
|
|
2305
2960
|
);
|
|
2306
|
-
const radius = RADIUS[chrome.radius ?? "2xl"] ?? RADIUS["2xl"];
|
|
2307
2961
|
const variant = chrome.variant ?? "hero_fullbleed";
|
|
2308
2962
|
if (variant === "announcement_bar") {
|
|
2309
2963
|
const c = cards[0];
|
|
@@ -2326,8 +2980,10 @@ function renderHeroInline(ctx, target) {
|
|
|
2326
2980
|
trackEvent(campaign.id, "impression");
|
|
2327
2981
|
return true;
|
|
2328
2982
|
}
|
|
2983
|
+
_injectHeroResponsiveCss();
|
|
2329
2984
|
const root = document.createElement("div");
|
|
2330
|
-
root.
|
|
2985
|
+
root.className = "aegis-hero-root";
|
|
2986
|
+
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
2987
|
root.setAttribute("data-campaign-id", campaign.id);
|
|
2332
2988
|
const track = document.createElement("div");
|
|
2333
2989
|
track.style.cssText = "display:flex;height:100%;width:100%;transition:transform 0.5s ease;";
|
|
@@ -2750,7 +3406,7 @@ class AegisChat {
|
|
|
2750
3406
|
const closeBtn = document.createElement("button");
|
|
2751
3407
|
closeBtn.className = "aegis-chat-close";
|
|
2752
3408
|
closeBtn.setAttribute("aria-label", "Close chat");
|
|
2753
|
-
closeBtn.
|
|
3409
|
+
closeBtn.innerHTML = lucideSvg("x", { size: 16 });
|
|
2754
3410
|
closeBtn.addEventListener("click", () => this.closePanel());
|
|
2755
3411
|
header.appendChild(titleEl);
|
|
2756
3412
|
header.appendChild(closeBtn);
|
|
@@ -2806,7 +3462,7 @@ class AegisChat {
|
|
|
2806
3462
|
const tipClose = document.createElement("button");
|
|
2807
3463
|
tipClose.className = "aegis-chat-tip-close";
|
|
2808
3464
|
tipClose.setAttribute("aria-label", "Dismiss");
|
|
2809
|
-
tipClose.
|
|
3465
|
+
tipClose.innerHTML = lucideSvg("x", { size: 14 });
|
|
2810
3466
|
tipClose.addEventListener("click", (e) => {
|
|
2811
3467
|
e.stopPropagation();
|
|
2812
3468
|
this.dismissAttention();
|
|
@@ -3772,10 +4428,15 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
3772
4428
|
this.ready = new Promise((resolve) => {
|
|
3773
4429
|
this.readyResolve = resolve;
|
|
3774
4430
|
});
|
|
4431
|
+
this.pendingPreInitRefresh = false;
|
|
3775
4432
|
this.currentSurface = null;
|
|
3776
4433
|
this.currentScreen = null;
|
|
3777
4434
|
this.currentLocationId = null;
|
|
3778
4435
|
this.filledSlots = /* @__PURE__ */ new WeakSet();
|
|
4436
|
+
this.slotSignatures = /* @__PURE__ */ new WeakMap();
|
|
4437
|
+
this.slotTimers = /* @__PURE__ */ new WeakMap();
|
|
4438
|
+
this.slotObserver = null;
|
|
4439
|
+
this.slotRenderScheduled = false;
|
|
3779
4440
|
this.writeKey = config.writeKey;
|
|
3780
4441
|
this.apiHost = config.apiHost || "https://api.aegis.ai";
|
|
3781
4442
|
this.userId = config.userId ?? readAnonIdFromStorage$1();
|
|
@@ -3887,6 +4548,11 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
3887
4548
|
this.connectSSE();
|
|
3888
4549
|
}
|
|
3889
4550
|
this.isInitialized = true;
|
|
4551
|
+
if (this.pendingPreInitRefresh) {
|
|
4552
|
+
this.pendingPreInitRefresh = false;
|
|
4553
|
+
this.log("Re-fetching campaigns for surface/screen declared during init");
|
|
4554
|
+
void this.refreshCampaigns();
|
|
4555
|
+
}
|
|
3890
4556
|
this.log("AegisInApp initialized successfully");
|
|
3891
4557
|
}
|
|
3892
4558
|
updateUserId(userId) {
|
|
@@ -3935,16 +4601,17 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
3935
4601
|
* change `currentSurface`, so arbitrary events never poison the surface gate.
|
|
3936
4602
|
*/
|
|
3937
4603
|
refreshOnEvent(eventName, isScreenDeclaration = false) {
|
|
3938
|
-
if (!this.isInitialized) {
|
|
3939
|
-
this.log(`refreshOnEvent(${eventName}) before initialize — ignored`);
|
|
3940
|
-
return;
|
|
3941
|
-
}
|
|
3942
4604
|
if (eventName && _AegisInAppManager.KNOWN_SURFACES.has(eventName)) {
|
|
3943
4605
|
this.currentSurface = eventName;
|
|
3944
4606
|
}
|
|
3945
4607
|
if (isScreenDeclaration && eventName && eventName !== "page_view") {
|
|
3946
4608
|
this.currentScreen = eventName;
|
|
3947
4609
|
}
|
|
4610
|
+
if (!this.isInitialized) {
|
|
4611
|
+
this.pendingPreInitRefresh = true;
|
|
4612
|
+
this.log(`refreshOnEvent(${eventName}) before initialize — surface captured, refetch deferred to initialize()`);
|
|
4613
|
+
return;
|
|
4614
|
+
}
|
|
3948
4615
|
if (this.refreshDebounceTimer) {
|
|
3949
4616
|
clearTimeout(this.refreshDebounceTimer);
|
|
3950
4617
|
}
|
|
@@ -4162,7 +4829,7 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
4162
4829
|
try {
|
|
4163
4830
|
const context = new URLSearchParams({
|
|
4164
4831
|
device_type: this.detectDeviceType(),
|
|
4165
|
-
page_url: typeof window !== "undefined" ? window.location.pathname : "/"
|
|
4832
|
+
page_url: typeof window !== "undefined" ? window.location.pathname + window.location.search : "/"
|
|
4166
4833
|
});
|
|
4167
4834
|
context.set("is_new_user", this.isNewUser() ? "true" : "false");
|
|
4168
4835
|
if (this.currentSurface) {
|
|
@@ -4320,28 +4987,75 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
4320
4987
|
if (!c.surface || c.surface.length === 0) return screenOk;
|
|
4321
4988
|
return screenOk || this.matchesCurrentSurface(c);
|
|
4322
4989
|
}
|
|
4990
|
+
// Re-fill slots that mount after a poll (SPA route changes). Observes the DOM
|
|
4991
|
+
// once; when a new [data-aegis-slot] appears it re-runs renderIntoSlots from
|
|
4992
|
+
// the cached campaigns (idempotent — already-filled slots are skipped). Does
|
|
4993
|
+
// NOT loop on the SDK's own injections (those add content INTO a slot, not a
|
|
4994
|
+
// new slot element).
|
|
4995
|
+
ensureSlotObserver() {
|
|
4996
|
+
if (this.slotObserver || typeof MutationObserver === "undefined" || typeof document === "undefined") {
|
|
4997
|
+
return;
|
|
4998
|
+
}
|
|
4999
|
+
this.slotObserver = new MutationObserver((mutations) => {
|
|
5000
|
+
let sawSlot = false;
|
|
5001
|
+
for (const m2 of mutations) {
|
|
5002
|
+
m2.addedNodes.forEach((n) => {
|
|
5003
|
+
var _a, _b;
|
|
5004
|
+
if (sawSlot || n.nodeType !== 1) return;
|
|
5005
|
+
const el = n;
|
|
5006
|
+
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]"))) {
|
|
5007
|
+
sawSlot = true;
|
|
5008
|
+
}
|
|
5009
|
+
});
|
|
5010
|
+
if (sawSlot) break;
|
|
5011
|
+
}
|
|
5012
|
+
if (!sawSlot || this.slotRenderScheduled) return;
|
|
5013
|
+
this.slotRenderScheduled = true;
|
|
5014
|
+
const run = () => {
|
|
5015
|
+
this.slotRenderScheduled = false;
|
|
5016
|
+
this.renderIntoSlots();
|
|
5017
|
+
};
|
|
5018
|
+
if (typeof requestAnimationFrame === "function") requestAnimationFrame(run);
|
|
5019
|
+
else setTimeout(run, 0);
|
|
5020
|
+
});
|
|
5021
|
+
this.slotObserver.observe(document.body, { childList: true, subtree: true });
|
|
5022
|
+
}
|
|
4323
5023
|
renderIntoSlots() {
|
|
4324
5024
|
if (typeof document === "undefined") return;
|
|
5025
|
+
this.ensureSlotObserver();
|
|
4325
5026
|
const slots = document.querySelectorAll("[data-aegis-slot]");
|
|
4326
5027
|
if (slots.length === 0) return;
|
|
4327
5028
|
const eligibleByCategory = /* @__PURE__ */ new Map();
|
|
5029
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
4328
5030
|
for (const c of this.campaigns) {
|
|
4329
5031
|
if (!this.matchesCurrentScreenOrSurface(c)) continue;
|
|
4330
5032
|
const modes = c.delivery_modes;
|
|
4331
5033
|
const category = c.widget_category;
|
|
4332
5034
|
if (!modes || !modes.includes("embedded_card")) continue;
|
|
4333
5035
|
if (!category) continue;
|
|
5036
|
+
if (seenIds.has(c.id)) continue;
|
|
5037
|
+
seenIds.add(c.id);
|
|
4334
5038
|
const arr2 = eligibleByCategory.get(category);
|
|
4335
5039
|
if (arr2) arr2.push(c);
|
|
4336
5040
|
else eligibleByCategory.set(category, [c]);
|
|
4337
5041
|
}
|
|
4338
5042
|
if (eligibleByCategory.size === 0) return;
|
|
4339
5043
|
slots.forEach((slot) => {
|
|
4340
|
-
if (this.filledSlots.has(slot)) return;
|
|
4341
5044
|
const key = slot.getAttribute("data-aegis-slot");
|
|
4342
5045
|
if (!key) return;
|
|
4343
5046
|
const list = eligibleByCategory.get(key);
|
|
4344
5047
|
if (!list || list.length === 0) return;
|
|
5048
|
+
const sig = list.map((c) => `${c.id}:${c.assigned_variant_id ?? ""}`).join(",");
|
|
5049
|
+
if (this.filledSlots.has(slot) && this.slotSignatures.get(slot) === sig) return;
|
|
5050
|
+
const oldTimer = this.slotTimers.get(slot);
|
|
5051
|
+
if (oldTimer) {
|
|
5052
|
+
clearInterval(oldTimer);
|
|
5053
|
+
this.slotTimers.delete(slot);
|
|
5054
|
+
}
|
|
5055
|
+
slot.querySelectorAll(
|
|
5056
|
+
":scope > [data-aegis-rotate-pane], :scope > [data-aegis-slot-rendered], :scope > [data-aegis-rotate-dots]"
|
|
5057
|
+
).forEach((n) => n.remove());
|
|
5058
|
+
this.slotSignatures.set(slot, sig);
|
|
4345
5059
|
slot.querySelectorAll(":scope > [data-aegis-slot-default]").forEach((d) => d.remove());
|
|
4346
5060
|
const attrMs = parseInt(slot.getAttribute("data-aegis-slot-rotate") || "0", 10);
|
|
4347
5061
|
const declaredMs = list.reduce((m2, c) => {
|
|
@@ -4350,10 +5064,15 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
4350
5064
|
return Number.isFinite(v) && v > m2 ? v : m2;
|
|
4351
5065
|
}, 0);
|
|
4352
5066
|
const rotateMs = attrMs > 0 ? attrMs : declaredMs;
|
|
5067
|
+
const flush = slot.hasAttribute("data-aegis-slot-flush");
|
|
4353
5068
|
if (rotateMs > 0 && list.length > 1) {
|
|
4354
|
-
this.renderRotatingSlot(slot, list, rotateMs);
|
|
5069
|
+
this.renderRotatingSlot(slot, list, rotateMs, flush);
|
|
4355
5070
|
} else {
|
|
4356
|
-
|
|
5071
|
+
const host = document.createElement("div");
|
|
5072
|
+
host.setAttribute("data-aegis-slot-rendered", list[0].id);
|
|
5073
|
+
slot.appendChild(host);
|
|
5074
|
+
this.renderCampaignIntoSlot(list[0], host);
|
|
5075
|
+
if (flush) this._flattenSlotCard(host);
|
|
4357
5076
|
}
|
|
4358
5077
|
this.filledSlots.add(slot);
|
|
4359
5078
|
});
|
|
@@ -4366,7 +5085,7 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
4366
5085
|
* is deferred at render and fired per campaign on FIRST visibility, so hidden
|
|
4367
5086
|
* panes never over-count. One rendered pane → no rotation (just shows it).
|
|
4368
5087
|
*/
|
|
4369
|
-
renderRotatingSlot(slot, campaigns, rotateMs) {
|
|
5088
|
+
renderRotatingSlot(slot, campaigns, rotateMs, flush = false) {
|
|
4370
5089
|
const panes = [];
|
|
4371
5090
|
for (const c of campaigns) {
|
|
4372
5091
|
const pane = document.createElement("div");
|
|
@@ -4374,8 +5093,10 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
4374
5093
|
pane.style.display = "none";
|
|
4375
5094
|
slot.appendChild(pane);
|
|
4376
5095
|
this.renderCampaignIntoSlot(c, pane, { deferImpression: true });
|
|
4377
|
-
if (pane.childElementCount > 0)
|
|
4378
|
-
|
|
5096
|
+
if (pane.childElementCount > 0) {
|
|
5097
|
+
if (flush) this._flattenSlotCard(pane);
|
|
5098
|
+
panes.push({ el: pane, campaign: c });
|
|
5099
|
+
} else pane.remove();
|
|
4379
5100
|
}
|
|
4380
5101
|
if (panes.length === 0) return;
|
|
4381
5102
|
const impressed = /* @__PURE__ */ new Set();
|
|
@@ -4386,17 +5107,59 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
4386
5107
|
this.emit("campaign-shown", c);
|
|
4387
5108
|
};
|
|
4388
5109
|
let idx = 0;
|
|
4389
|
-
|
|
4390
|
-
|
|
4391
|
-
|
|
4392
|
-
|
|
5110
|
+
const dots = [];
|
|
5111
|
+
if (panes.length > 1) {
|
|
5112
|
+
const bar = document.createElement("div");
|
|
5113
|
+
bar.setAttribute("data-aegis-rotate-dots", "");
|
|
5114
|
+
bar.setAttribute("role", "tablist");
|
|
5115
|
+
bar.setAttribute("aria-label", "Offers");
|
|
5116
|
+
bar.style.cssText = "display:flex;align-items:center;justify-content:center;gap:5px;padding:2px 0 8px;";
|
|
5117
|
+
panes.forEach((_, i) => {
|
|
5118
|
+
const dot = document.createElement("button");
|
|
5119
|
+
dot.type = "button";
|
|
5120
|
+
dot.setAttribute("role", "tab");
|
|
5121
|
+
dot.setAttribute("aria-label", `Offer ${i + 1} of ${panes.length}`);
|
|
5122
|
+
dot.style.cssText = "border:none;padding:0;cursor:pointer;height:6px;width:6px;border-radius:999px;background:rgba(15,23,42,0.2);transition:width .25s ease,background .25s ease;";
|
|
5123
|
+
dot.addEventListener("click", (e) => {
|
|
5124
|
+
e.stopPropagation();
|
|
5125
|
+
show(i, true);
|
|
5126
|
+
});
|
|
5127
|
+
dots.push(dot);
|
|
5128
|
+
bar.appendChild(dot);
|
|
5129
|
+
});
|
|
5130
|
+
slot.appendChild(bar);
|
|
5131
|
+
}
|
|
5132
|
+
const paintDots = () => {
|
|
5133
|
+
dots.forEach((d, i) => {
|
|
5134
|
+
const active = i === idx;
|
|
5135
|
+
d.style.width = active ? "16px" : "6px";
|
|
5136
|
+
d.style.background = active ? "var(--aegis-brand-accent, #4169e1)" : "rgba(15,23,42,0.2)";
|
|
5137
|
+
d.setAttribute("aria-selected", active ? "true" : "false");
|
|
5138
|
+
});
|
|
5139
|
+
};
|
|
5140
|
+
let timer = null;
|
|
5141
|
+
const start = () => setInterval(() => {
|
|
5142
|
+
show(idx + 1);
|
|
5143
|
+
}, rotateMs);
|
|
5144
|
+
function show(i, fromClick = false) {
|
|
4393
5145
|
panes[idx].el.style.display = "none";
|
|
4394
|
-
idx = (
|
|
5146
|
+
idx = (i % panes.length + panes.length) % panes.length;
|
|
4395
5147
|
panes[idx].el.style.display = "";
|
|
4396
5148
|
markVisible(panes[idx].campaign);
|
|
4397
|
-
|
|
5149
|
+
paintDots();
|
|
5150
|
+
if (fromClick && timer) {
|
|
5151
|
+
clearInterval(timer);
|
|
5152
|
+
timer = start();
|
|
5153
|
+
}
|
|
5154
|
+
}
|
|
5155
|
+
panes[0].el.style.display = "";
|
|
5156
|
+
markVisible(panes[0].campaign);
|
|
5157
|
+
paintDots();
|
|
5158
|
+
if (panes.length === 1) return;
|
|
5159
|
+
timer = start();
|
|
5160
|
+
this.slotTimers.set(slot, timer);
|
|
4398
5161
|
if (typeof window !== "undefined") {
|
|
4399
|
-
window.addEventListener("beforeunload", () => clearInterval(timer), { once: true });
|
|
5162
|
+
window.addEventListener("beforeunload", () => timer && clearInterval(timer), { once: true });
|
|
4400
5163
|
}
|
|
4401
5164
|
}
|
|
4402
5165
|
/**
|
|
@@ -4450,6 +5213,14 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
4450
5213
|
target.querySelectorAll(":scope > [data-aegis-slot-default]").forEach((d) => d.remove());
|
|
4451
5214
|
}
|
|
4452
5215
|
}
|
|
5216
|
+
const spacing = Number(anchor == null ? void 0 : anchor.element_spacing);
|
|
5217
|
+
if (spacing > 0) {
|
|
5218
|
+
if (position === "before" || position === "after") {
|
|
5219
|
+
target.style.margin = `${spacing}px`;
|
|
5220
|
+
} else {
|
|
5221
|
+
target.style.padding = `${spacing}px`;
|
|
5222
|
+
}
|
|
5223
|
+
}
|
|
4453
5224
|
if (this.filledSlots.has(target)) continue;
|
|
4454
5225
|
this.renderCampaignIntoSlot(c, target);
|
|
4455
5226
|
this.filledSlots.add(target);
|
|
@@ -4555,7 +5326,12 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
4555
5326
|
}
|
|
4556
5327
|
return;
|
|
4557
5328
|
}
|
|
4558
|
-
|
|
5329
|
+
const _tpl = ic.card_template;
|
|
5330
|
+
const _hasComposedTemplate = !!_tpl && typeof _tpl === "object" && Array.isArray(_tpl.elements);
|
|
5331
|
+
const _isMultiCard = campaign.sub_type === "product_recommendation" || campaign.sub_type === "carousel_cards";
|
|
5332
|
+
if (_hasComposedTemplate && !_isMultiCard) {
|
|
5333
|
+
rendered = this.renderComposedCardSlot(campaign, ic, target);
|
|
5334
|
+
} else if (campaign.widget_category === "hero") {
|
|
4559
5335
|
rendered = renderHeroInline(this.buildRenderContext(campaign), target);
|
|
4560
5336
|
} else
|
|
4561
5337
|
switch (campaign.sub_type) {
|
|
@@ -4608,6 +5384,9 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
4608
5384
|
case "progress_bar":
|
|
4609
5385
|
rendered = renderProgressBarInline(this.buildRenderContext(campaign), target);
|
|
4610
5386
|
break;
|
|
5387
|
+
case "product_recommendation":
|
|
5388
|
+
rendered = renderProductRecommendationInline(this.buildRenderContext(campaign), target);
|
|
5389
|
+
break;
|
|
4611
5390
|
case "quiz":
|
|
4612
5391
|
rendered = this.renderQuizSlot(campaign, ic, bg, text, target);
|
|
4613
5392
|
if (!rendered) {
|
|
@@ -4670,6 +5449,34 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
4670
5449
|
* The catch-all for banner + nudge sub_types (birthday, referral, app-install,
|
|
4671
5450
|
* win-back, etc.) so EVERY gallery nudge renders on the bill (previously only
|
|
4672
5451
|
* star_rating / nps_survey / form were handled → nudges never appeared). */
|
|
5452
|
+
/**
|
|
5453
|
+
* Composed single card — renders a campaign's top-level `card_template`
|
|
5454
|
+
* (frame + elements: icon/text/progress/image/cta/group/…) through the generic
|
|
5455
|
+
* `renderCardFromTemplate` engine. The canonical path for the rich card editor:
|
|
5456
|
+
* the storefront value bar, loyalty nudges, and any operator-composed card all
|
|
5457
|
+
* render here from declarative JSON, on ACS / custom / third-party sites.
|
|
5458
|
+
*/
|
|
5459
|
+
renderComposedCardSlot(campaign, ic, target) {
|
|
5460
|
+
const c = campaign;
|
|
5461
|
+
const card = {
|
|
5462
|
+
image_url: typeof c.image_url === "string" ? c.image_url : void 0,
|
|
5463
|
+
title: campaign.title,
|
|
5464
|
+
body: campaign.body,
|
|
5465
|
+
cta_text: typeof c.button_text === "string" ? c.button_text : void 0,
|
|
5466
|
+
cta_url: typeof c.action_url === "string" ? c.action_url : void 0,
|
|
5467
|
+
metadata: ic.card_meta || {}
|
|
5468
|
+
};
|
|
5469
|
+
const template = resolveGlobalTemplate(ic);
|
|
5470
|
+
const { accent } = this._surfacePalette(campaign);
|
|
5471
|
+
const tile = renderCardFromTemplate(card, {
|
|
5472
|
+
template,
|
|
5473
|
+
ctx: this.buildRenderContext(campaign),
|
|
5474
|
+
action: "navigate",
|
|
5475
|
+
layoutAccent: this.sanitizeColor(campaign.background_color || accent)
|
|
5476
|
+
});
|
|
5477
|
+
target.appendChild(tile);
|
|
5478
|
+
return true;
|
|
5479
|
+
}
|
|
4673
5480
|
renderGenericCardSlot(campaign, ic, bg, text, target) {
|
|
4674
5481
|
const st = this._slotStyle(campaign);
|
|
4675
5482
|
const card = this._wrapInSlotCard("aegis-in-app-generic-card", campaign.id, bg, text, st.radius);
|
|
@@ -4685,6 +5492,45 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
4685
5492
|
im.style.cssText = "width: 100%; height: 96px; object-fit: cover; display: block;";
|
|
4686
5493
|
card.appendChild(im);
|
|
4687
5494
|
}
|
|
5495
|
+
const widgetCat = typeof c.widget_category === "string" ? c.widget_category : "";
|
|
5496
|
+
if (widgetCat === "promo" && !img) {
|
|
5497
|
+
const row = document.createElement("div");
|
|
5498
|
+
row.style.cssText = `display:flex; align-items:center; gap:12px; min-height:46px; padding:${st.padY ?? 10}px ${st.padX ?? 14}px;`;
|
|
5499
|
+
const colL = document.createElement("div");
|
|
5500
|
+
colL.style.cssText = "flex:1 1 auto; min-width:0; display:flex; flex-direction:column; gap:2px;";
|
|
5501
|
+
if (campaign.title) {
|
|
5502
|
+
const t = document.createElement("div");
|
|
5503
|
+
t.style.cssText = `font-size:13px; font-weight:${st.weight ?? "700"}; line-height:1.25; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;`;
|
|
5504
|
+
t.textContent = campaign.title;
|
|
5505
|
+
colL.appendChild(t);
|
|
5506
|
+
}
|
|
5507
|
+
if (campaign.body) {
|
|
5508
|
+
const b = document.createElement("div");
|
|
5509
|
+
b.style.cssText = "font-size:11.5px; opacity:0.7; line-height:1.3; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;";
|
|
5510
|
+
b.textContent = campaign.body;
|
|
5511
|
+
colL.appendChild(b);
|
|
5512
|
+
}
|
|
5513
|
+
row.appendChild(colL);
|
|
5514
|
+
if (buttonText) {
|
|
5515
|
+
const btn = document.createElement("button");
|
|
5516
|
+
btn.type = "button";
|
|
5517
|
+
btn.textContent = buttonText;
|
|
5518
|
+
const accentTok = `var(--aegis-brand-accent, ${text})`;
|
|
5519
|
+
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;`;
|
|
5520
|
+
btn.addEventListener("click", () => {
|
|
5521
|
+
void this.trackEvent(campaign.id, "clicked");
|
|
5522
|
+
if (actionUrl) {
|
|
5523
|
+
window.open(actionUrl, "_blank", "noopener");
|
|
5524
|
+
} else if (typeof window !== "undefined") {
|
|
5525
|
+
window.dispatchEvent(new CustomEvent("aegis:open-login", { detail: { campaign_id: campaign.id } }));
|
|
5526
|
+
}
|
|
5527
|
+
});
|
|
5528
|
+
row.appendChild(btn);
|
|
5529
|
+
}
|
|
5530
|
+
card.appendChild(row);
|
|
5531
|
+
target.appendChild(card);
|
|
5532
|
+
return true;
|
|
5533
|
+
}
|
|
4688
5534
|
const cbody = document.createElement("div");
|
|
4689
5535
|
cbody.style.cssText = `padding: ${st.padY ?? 12}px ${st.padX ?? 12}px; display: flex; flex-direction: column; gap: 6px;`;
|
|
4690
5536
|
if (campaign.title) {
|
|
@@ -4828,8 +5674,14 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
4828
5674
|
body.style.alignItems = "center";
|
|
4829
5675
|
body.style.justifyContent = "center";
|
|
4830
5676
|
const done = document.createElement("div");
|
|
4831
|
-
done.style.cssText = "padding: 8px 0; font-size: 13px; font-weight: 600; text-align: center;";
|
|
4832
|
-
|
|
5677
|
+
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;";
|
|
5678
|
+
const customThanks = typeof ((_a = campaign.interactive_config) == null ? void 0 : _a.thank_you_message) === "string" ? campaign.interactive_config.thank_you_message : null;
|
|
5679
|
+
if (customThanks) {
|
|
5680
|
+
done.textContent = customThanks;
|
|
5681
|
+
} else {
|
|
5682
|
+
done.innerHTML = lucideSvg("check", { size: 14 });
|
|
5683
|
+
done.appendChild(document.createTextNode("Thanks — your details are saved."));
|
|
5684
|
+
}
|
|
4833
5685
|
body.appendChild(done);
|
|
4834
5686
|
this._playReaction(body, "affirm", "check.json", campaign.interactive_config);
|
|
4835
5687
|
});
|
|
@@ -5169,11 +6021,11 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
5169
6021
|
const soundBtn = document.createElement("button");
|
|
5170
6022
|
soundBtn.type = "button";
|
|
5171
6023
|
soundBtn.setAttribute("aria-label", "Toggle sound");
|
|
5172
|
-
soundBtn.
|
|
6024
|
+
soundBtn.innerHTML = lucideSvg(soundOn ? "volume-2" : "volume-x", { size: 15 });
|
|
5173
6025
|
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
6026
|
soundBtn.addEventListener("click", () => {
|
|
5175
6027
|
soundOn = !soundOn;
|
|
5176
|
-
soundBtn.
|
|
6028
|
+
soundBtn.innerHTML = lucideSvg(soundOn ? "volume-2" : "volume-x", { size: 15 });
|
|
5177
6029
|
});
|
|
5178
6030
|
card.appendChild(soundBtn);
|
|
5179
6031
|
}
|
|
@@ -5288,7 +6140,7 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
5288
6140
|
var _a;
|
|
5289
6141
|
try {
|
|
5290
6142
|
void ((_a = navigator.clipboard) == null ? void 0 : _a.writeText(r.code));
|
|
5291
|
-
chip.textContent = "Copied
|
|
6143
|
+
chip.textContent = "Copied";
|
|
5292
6144
|
} catch {
|
|
5293
6145
|
}
|
|
5294
6146
|
});
|
|
@@ -5334,7 +6186,7 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
5334
6186
|
var _a;
|
|
5335
6187
|
try {
|
|
5336
6188
|
void ((_a = navigator.clipboard) == null ? void 0 : _a.writeText(r.code));
|
|
5337
|
-
chip.textContent = "Copied
|
|
6189
|
+
chip.textContent = "Copied";
|
|
5338
6190
|
} catch {
|
|
5339
6191
|
}
|
|
5340
6192
|
});
|
|
@@ -5575,7 +6427,7 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
5575
6427
|
pctLabel.textContent = `${pct}%`;
|
|
5576
6428
|
pctLabel.style.opacity = "0.8";
|
|
5577
6429
|
} else if (pctLabel && i === selected) {
|
|
5578
|
-
pctLabel.
|
|
6430
|
+
pctLabel.innerHTML = lucideSvg("check", { size: 14 });
|
|
5579
6431
|
pctLabel.style.opacity = "0.8";
|
|
5580
6432
|
}
|
|
5581
6433
|
});
|
|
@@ -5598,59 +6450,18 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
5598
6450
|
}
|
|
5599
6451
|
const strip = document.createElement("div");
|
|
5600
6452
|
strip.style.cssText = `display: flex; gap: 8px; overflow-x: auto; scroll-snap-type: x mandatory; padding: ${st.padY ?? 12}px ${st.padX ?? 12}px;`;
|
|
6453
|
+
const template = resolveGlobalTemplate(ic);
|
|
6454
|
+
const ctx = this.buildRenderContext(campaign);
|
|
6455
|
+
const accent = this.sanitizeColor(campaign.background_color || text);
|
|
5601
6456
|
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);
|
|
6457
|
+
const tile = renderCardFromTemplate(c, {
|
|
6458
|
+
template,
|
|
6459
|
+
ctx,
|
|
6460
|
+
action: "navigate",
|
|
6461
|
+
layout: "row",
|
|
6462
|
+
layoutAccent: accent
|
|
6463
|
+
});
|
|
6464
|
+
tile.setAttribute("data-card-index", String(i));
|
|
5654
6465
|
strip.appendChild(tile);
|
|
5655
6466
|
});
|
|
5656
6467
|
card.appendChild(strip);
|
|
@@ -5902,11 +6713,11 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
5902
6713
|
const sb = document.createElement("button");
|
|
5903
6714
|
sb.type = "button";
|
|
5904
6715
|
sb.setAttribute("aria-label", "Toggle sound");
|
|
5905
|
-
sb.
|
|
6716
|
+
sb.innerHTML = lucideSvg(soundOn ? "volume-2" : "volume-x", { size: 15 });
|
|
5906
6717
|
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
6718
|
sb.addEventListener("click", () => {
|
|
5908
6719
|
soundOn = !soundOn;
|
|
5909
|
-
sb.
|
|
6720
|
+
sb.innerHTML = lucideSvg(soundOn ? "volume-2" : "volume-x", { size: 15 });
|
|
5910
6721
|
});
|
|
5911
6722
|
card.appendChild(sb);
|
|
5912
6723
|
}
|
|
@@ -6075,7 +6886,7 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
6075
6886
|
var _a;
|
|
6076
6887
|
try {
|
|
6077
6888
|
void ((_a = navigator.clipboard) == null ? void 0 : _a.writeText(code));
|
|
6078
|
-
chip.textContent = "Copied
|
|
6889
|
+
chip.textContent = "Copied";
|
|
6079
6890
|
} catch {
|
|
6080
6891
|
}
|
|
6081
6892
|
});
|
|
@@ -6263,6 +7074,19 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
6263
7074
|
`;
|
|
6264
7075
|
return card;
|
|
6265
7076
|
}
|
|
7077
|
+
/**
|
|
7078
|
+
* Flush a rendered slot card into its host card — drop the per-campaign radius
|
|
7079
|
+
* + shadow so it reads as one unit with the host wrapper (used for the
|
|
7080
|
+
* storefront value bar via `data-aegis-slot-flush`). Targets every
|
|
7081
|
+
* `[data-campaign-id]` card inside `container` (or the container itself).
|
|
7082
|
+
*/
|
|
7083
|
+
_flattenSlotCard(container) {
|
|
7084
|
+
const cards = container.matches("[data-campaign-id]") ? [container] : Array.from(container.querySelectorAll("[data-campaign-id]"));
|
|
7085
|
+
for (const el of cards) {
|
|
7086
|
+
el.style.borderRadius = "0";
|
|
7087
|
+
el.style.boxShadow = "none";
|
|
7088
|
+
}
|
|
7089
|
+
}
|
|
6266
7090
|
// Optional header/brand image atop a survey-style widget (star / nps).
|
|
6267
7091
|
_appendHeaderImage(body, ic) {
|
|
6268
7092
|
const url = ic.header_image_url;
|
|
@@ -6704,6 +7528,9 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
6704
7528
|
}
|
|
6705
7529
|
}
|
|
6706
7530
|
displayCampaign(campaign) {
|
|
7531
|
+
if (Array.isArray(campaign.delivery_modes) && campaign.delivery_modes.length > 0 && !campaign.delivery_modes.includes("in_app_overlay")) {
|
|
7532
|
+
return;
|
|
7533
|
+
}
|
|
6707
7534
|
const proceed = this.emit("campaign-will-show", campaign);
|
|
6708
7535
|
if (!proceed) {
|
|
6709
7536
|
this.log(`campaign ${campaign.id} suppressed by campaign-will-show handler`);
|
|
@@ -6833,6 +7660,16 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
6833
7660
|
return {
|
|
6834
7661
|
campaign,
|
|
6835
7662
|
getCartState: this.getCartState,
|
|
7663
|
+
properties: () => {
|
|
7664
|
+
var _a, _b;
|
|
7665
|
+
const cart = (_a = this.getCartState) == null ? void 0 : _a.call(this);
|
|
7666
|
+
const ctxObj = ((_b = campaign.interactive_config) == null ? void 0 : _b.card_context) || {};
|
|
7667
|
+
return {
|
|
7668
|
+
"cart.total": cart == null ? void 0 : cart.total,
|
|
7669
|
+
"cart.count": cart == null ? void 0 : cart.itemCount,
|
|
7670
|
+
...ctxObj
|
|
7671
|
+
};
|
|
7672
|
+
},
|
|
6836
7673
|
trackEvent: (id, evt, extra) => {
|
|
6837
7674
|
void this.trackEvent(id, evt, extra);
|
|
6838
7675
|
},
|
|
@@ -6943,7 +7780,7 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
6943
7780
|
'<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
7781
|
);
|
|
6945
7782
|
if (closeIcon) x.appendChild(closeIcon);
|
|
6946
|
-
else x.
|
|
7783
|
+
else x.innerHTML = lucideSvg("x", { size: 14 });
|
|
6947
7784
|
x.style.cssText = `
|
|
6948
7785
|
position: absolute; top: 12px; right: 12px; z-index: 4; width: 28px; height: 28px;
|
|
6949
7786
|
display: flex; align-items: center; justify-content: center; border: none;
|
|
@@ -7781,12 +8618,17 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
7781
8618
|
_surfacePalette(campaign) {
|
|
7782
8619
|
const ic = campaign.interactive_config || {};
|
|
7783
8620
|
const brand = this.sanitizeColor(campaign.background_color || "#4169e1");
|
|
7784
|
-
const
|
|
7785
|
-
if (branded) {
|
|
8621
|
+
const surface = ic.surface_style;
|
|
8622
|
+
if (surface === "branded") {
|
|
7786
8623
|
const bg = brand;
|
|
7787
8624
|
const text = campaign.text_color ? this.sanitizeColor(campaign.text_color) : "#ffffff";
|
|
7788
8625
|
return { bg, text, btnBg: text, btnText: bg, accent: text, branded: true };
|
|
7789
8626
|
}
|
|
8627
|
+
if (surface === "dark") {
|
|
8628
|
+
const bg = this.sanitizeColor(campaign.background_color || "#0f172a");
|
|
8629
|
+
const text = campaign.text_color ? this.sanitizeColor(campaign.text_color) : "#ffffff";
|
|
8630
|
+
return { bg, text, btnBg: "#ffffff", btnText: bg, accent: text, branded: false };
|
|
8631
|
+
}
|
|
7790
8632
|
return { bg: "#ffffff", text: "#0f172a", btnBg: brand, btnText: this._contrastText(brand), accent: brand, branded: false };
|
|
7791
8633
|
}
|
|
7792
8634
|
inAppStyle(campaign) {
|
|
@@ -7890,7 +8732,7 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
7890
8732
|
actionsContainer.appendChild(ctaButton);
|
|
7891
8733
|
}
|
|
7892
8734
|
const closeButton = document.createElement("button");
|
|
7893
|
-
closeButton.
|
|
8735
|
+
closeButton.innerHTML = lucideSvg("x", { size: 18 });
|
|
7894
8736
|
closeButton.setAttribute("aria-label", "Close");
|
|
7895
8737
|
closeButton.style.cssText = `
|
|
7896
8738
|
background: transparent;
|
|
@@ -8088,7 +8930,7 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
8088
8930
|
pill.replaceChildren();
|
|
8089
8931
|
const ic = document.createElement("span");
|
|
8090
8932
|
ic.style.fontSize = "13px";
|
|
8091
|
-
ic.
|
|
8933
|
+
ic.innerHTML = lucideSvg(v.muted ? "volume-x" : "volume-2", { size: 13 });
|
|
8092
8934
|
pill.appendChild(ic);
|
|
8093
8935
|
if (v.muted) {
|
|
8094
8936
|
const t = document.createElement("span");
|
|
@@ -8218,7 +9060,7 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
8218
9060
|
}
|
|
8219
9061
|
overlay.appendChild(contentContainer);
|
|
8220
9062
|
const closeButton = document.createElement("button");
|
|
8221
|
-
closeButton.
|
|
9063
|
+
closeButton.innerHTML = lucideSvg("x", { size: isBg ? 18 : 28 });
|
|
8222
9064
|
closeButton.setAttribute("aria-label", "Close");
|
|
8223
9065
|
closeButton.style.cssText = `
|
|
8224
9066
|
position: absolute; top: 20px; right: 20px; z-index: 3; background: ${isBg ? "rgba(0,0,0,0.45)" : "transparent"};
|
|
@@ -8346,7 +9188,7 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
8346
9188
|
}
|
|
8347
9189
|
modal.appendChild(content);
|
|
8348
9190
|
const closeButton = document.createElement("button");
|
|
8349
|
-
closeButton.
|
|
9191
|
+
closeButton.innerHTML = lucideSvg("x", { size: 22 });
|
|
8350
9192
|
closeButton.setAttribute("aria-label", "Close");
|
|
8351
9193
|
closeButton.style.cssText = `
|
|
8352
9194
|
position: absolute;
|
|
@@ -8419,16 +9261,16 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
8419
9261
|
const ic = campaign.interactive_config || {};
|
|
8420
9262
|
const variant = ic.alert_variant || "";
|
|
8421
9263
|
const VARIANTS = {
|
|
8422
|
-
info: {
|
|
8423
|
-
success: {
|
|
8424
|
-
warning: {
|
|
8425
|
-
error: {
|
|
9264
|
+
info: { icon: "info", color: "#3b82f6" },
|
|
9265
|
+
success: { icon: "check", color: "#10b981" },
|
|
9266
|
+
warning: { icon: "triangle-alert", color: "#f59e0b" },
|
|
9267
|
+
error: { icon: "x", color: "#ef4444" }
|
|
8426
9268
|
};
|
|
8427
9269
|
const vspec = VARIANTS[variant];
|
|
8428
9270
|
if (vspec) {
|
|
8429
9271
|
const badge = document.createElement("div");
|
|
8430
9272
|
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.
|
|
9273
|
+
badge.innerHTML = lucideSvg(vspec.icon, { size: 24 });
|
|
8432
9274
|
content.appendChild(badge);
|
|
8433
9275
|
}
|
|
8434
9276
|
const title = document.createElement("h3");
|
|
@@ -8570,7 +9412,7 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
8570
9412
|
if (!hasMedia) {
|
|
8571
9413
|
const placeholder = document.createElement("div");
|
|
8572
9414
|
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.
|
|
9415
|
+
placeholder.innerHTML = lucideSvg("play", { size: 34 });
|
|
8574
9416
|
mediaWrap.appendChild(placeholder);
|
|
8575
9417
|
}
|
|
8576
9418
|
pip.appendChild(mediaWrap);
|
|
@@ -8581,7 +9423,7 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
8581
9423
|
playGlyph.setAttribute("aria-label", "Play or pause");
|
|
8582
9424
|
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
9425
|
const syncGlyph = () => {
|
|
8584
|
-
playGlyph.
|
|
9426
|
+
playGlyph.innerHTML = lucideSvg(v.paused ? "play" : "pause", { size: 22 });
|
|
8585
9427
|
playGlyph.style.opacity = v.paused ? "1" : "0";
|
|
8586
9428
|
};
|
|
8587
9429
|
const togglePlay = () => {
|
|
@@ -8608,7 +9450,7 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
8608
9450
|
mutePill.replaceChildren();
|
|
8609
9451
|
const ic2 = document.createElement("span");
|
|
8610
9452
|
ic2.style.fontSize = "13px";
|
|
8611
|
-
ic2.
|
|
9453
|
+
ic2.innerHTML = lucideSvg(v.muted ? "volume-x" : "volume-2", { size: 13 });
|
|
8612
9454
|
mutePill.appendChild(ic2);
|
|
8613
9455
|
if (v.muted) {
|
|
8614
9456
|
const t = document.createElement("span");
|
|
@@ -8703,7 +9545,7 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
8703
9545
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
8704
9546
|
`;
|
|
8705
9547
|
if (expandBtn) {
|
|
8706
|
-
expandBtn.
|
|
9548
|
+
expandBtn.innerHTML = lucideSvg("x", { size: 16 });
|
|
8707
9549
|
expandBtn.setAttribute("aria-label", "Minimize");
|
|
8708
9550
|
}
|
|
8709
9551
|
if (video && video.muted) {
|
|
@@ -8726,7 +9568,7 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
8726
9568
|
}
|
|
8727
9569
|
const closeButton = document.createElement("button");
|
|
8728
9570
|
closeButton.type = "button";
|
|
8729
|
-
closeButton.
|
|
9571
|
+
closeButton.innerHTML = lucideSvg("x", { size: 16 });
|
|
8730
9572
|
closeButton.setAttribute("aria-label", "Close");
|
|
8731
9573
|
closeButton.style.cssText = ctrlBtnCss;
|
|
8732
9574
|
closeButton.addEventListener("click", (e) => {
|
|
@@ -9746,13 +10588,29 @@ function evaluateRule(rule, snapshot, namespaces) {
|
|
|
9746
10588
|
const result = evaluateExpr(rule.when, snapshot, namespaces);
|
|
9747
10589
|
return result === true;
|
|
9748
10590
|
}
|
|
9749
|
-
class
|
|
10591
|
+
const _IntentRuleEvaluator = class _IntentRuleEvaluator {
|
|
9750
10592
|
constructor() {
|
|
9751
10593
|
this.armed = [];
|
|
9752
10594
|
this.snapshot = {};
|
|
9753
10595
|
this.namespaces = {};
|
|
9754
10596
|
this.firedThisSession = /* @__PURE__ */ new Set();
|
|
9755
10597
|
this.silencedThisSession = /* @__PURE__ */ new Set();
|
|
10598
|
+
this.oneInterruptionPerSession = false;
|
|
10599
|
+
this.interruptiveBudgetSpent = false;
|
|
10600
|
+
this.ttfiMs = 0;
|
|
10601
|
+
this.sessionStartMs = Date.now();
|
|
10602
|
+
this.nowFn = () => Date.now();
|
|
10603
|
+
}
|
|
10604
|
+
/** Tune governance. `now` also (re)bases the TTFI session clock. */
|
|
10605
|
+
setGovernance(opts) {
|
|
10606
|
+
if (opts.oneInterruptionPerSession !== void 0) {
|
|
10607
|
+
this.oneInterruptionPerSession = opts.oneInterruptionPerSession;
|
|
10608
|
+
}
|
|
10609
|
+
if (opts.ttfiMs !== void 0) this.ttfiMs = opts.ttfiMs;
|
|
10610
|
+
if (opts.now) {
|
|
10611
|
+
this.nowFn = opts.now;
|
|
10612
|
+
this.sessionStartMs = opts.now();
|
|
10613
|
+
}
|
|
9756
10614
|
}
|
|
9757
10615
|
// ─── snapshot management ───
|
|
9758
10616
|
updateSignal(signal, value) {
|
|
@@ -9788,12 +10646,15 @@ class IntentRuleEvaluator {
|
|
|
9788
10646
|
}
|
|
9789
10647
|
markFired(campaignId) {
|
|
9790
10648
|
this.firedThisSession.add(campaignId);
|
|
10649
|
+
this.interruptiveBudgetSpent = true;
|
|
9791
10650
|
}
|
|
9792
10651
|
/** Clear all per-session state. Caller invokes on logout or explicit
|
|
9793
10652
|
* session reset. */
|
|
9794
10653
|
reset() {
|
|
9795
10654
|
this.firedThisSession.clear();
|
|
9796
10655
|
this.silencedThisSession.clear();
|
|
10656
|
+
this.interruptiveBudgetSpent = false;
|
|
10657
|
+
this.sessionStartMs = this.nowFn();
|
|
9797
10658
|
}
|
|
9798
10659
|
// ─── the main dispatch ───
|
|
9799
10660
|
/**
|
|
@@ -9816,6 +10677,11 @@ class IntentRuleEvaluator {
|
|
|
9816
10677
|
* 5. If nothing matches, return 'none'.
|
|
9817
10678
|
*/
|
|
9818
10679
|
onSignalChanged(signal) {
|
|
10680
|
+
if (this.oneInterruptionPerSession && this.interruptiveBudgetSpent) {
|
|
10681
|
+
return { kind: "none" };
|
|
10682
|
+
}
|
|
10683
|
+
const sessionElapsedMs = this.nowFn() - this.sessionStartMs;
|
|
10684
|
+
const exemptFromTtfi = _IntentRuleEvaluator.EXIT_SIGNALS.includes(signal);
|
|
9819
10685
|
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
10686
|
if (b.rule.priority !== a.rule.priority) {
|
|
9821
10687
|
return b.rule.priority - a.rule.priority;
|
|
@@ -9825,6 +10691,9 @@ class IntentRuleEvaluator {
|
|
|
9825
10691
|
for (let i = 0; i < candidates.length; i++) {
|
|
9826
10692
|
const c = candidates[i];
|
|
9827
10693
|
if (!evaluateRule(c.rule, this.snapshot, this.namespaces)) continue;
|
|
10694
|
+
if (this.ttfiMs > 0 && sessionElapsedMs < this.ttfiMs && !exemptFromTtfi) {
|
|
10695
|
+
continue;
|
|
10696
|
+
}
|
|
9828
10697
|
if (c.rule.suppress_competing) {
|
|
9829
10698
|
const suppressIds = this.armed.filter((other) => other.id !== c.id).map((other) => other.id);
|
|
9830
10699
|
suppressIds.forEach((id) => this.silencedThisSession.add(id));
|
|
@@ -9838,7 +10707,12 @@ class IntentRuleEvaluator {
|
|
|
9838
10707
|
}
|
|
9839
10708
|
return { kind: "none" };
|
|
9840
10709
|
}
|
|
9841
|
-
}
|
|
10710
|
+
};
|
|
10711
|
+
_IntentRuleEvaluator.EXIT_SIGNALS = [
|
|
10712
|
+
"exit_intent",
|
|
10713
|
+
"back_button"
|
|
10714
|
+
];
|
|
10715
|
+
let IntentRuleEvaluator = _IntentRuleEvaluator;
|
|
9842
10716
|
class ContactScoresFetcher {
|
|
9843
10717
|
constructor(cfg) {
|
|
9844
10718
|
this.lastFetchedAt = 0;
|
|
@@ -10192,7 +11066,7 @@ class PrefetchBundleClient {
|
|
|
10192
11066
|
}
|
|
10193
11067
|
let response;
|
|
10194
11068
|
try {
|
|
10195
|
-
response = await fetch(url, { method: "GET", headers });
|
|
11069
|
+
response = await fetch(url, { method: "GET", headers, cache: "no-cache" });
|
|
10196
11070
|
} catch (err) {
|
|
10197
11071
|
logger.warn("prefetch-bundle fetch network error:", err);
|
|
10198
11072
|
return this.currentBundle;
|
|
@@ -11217,8 +12091,8 @@ class AegisWidgetManager {
|
|
|
11217
12091
|
{ label: "Prize 3", color: "#48dbfb" },
|
|
11218
12092
|
{ label: "Prize 4", color: "#ff6348" }
|
|
11219
12093
|
];
|
|
11220
|
-
const
|
|
11221
|
-
const wheel = document.createElementNS(
|
|
12094
|
+
const SVG_NS2 = "http://www.w3.org/2000/svg";
|
|
12095
|
+
const wheel = document.createElementNS(SVG_NS2, "svg");
|
|
11222
12096
|
wheel.setAttribute("viewBox", "-160 -160 320 320");
|
|
11223
12097
|
wheel.setAttribute("width", "300");
|
|
11224
12098
|
wheel.setAttribute("height", "300");
|
|
@@ -11234,7 +12108,7 @@ class AegisWidgetManager {
|
|
|
11234
12108
|
const x2 = Math.cos(end) * radius;
|
|
11235
12109
|
const y2 = Math.sin(end) * radius;
|
|
11236
12110
|
const largeArc = anglePer > Math.PI ? 1 : 0;
|
|
11237
|
-
const path = document.createElementNS(
|
|
12111
|
+
const path = document.createElementNS(SVG_NS2, "path");
|
|
11238
12112
|
path.setAttribute(
|
|
11239
12113
|
"d",
|
|
11240
12114
|
`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 +12120,7 @@ class AegisWidgetManager {
|
|
|
11246
12120
|
const labelAngle = start + anglePer / 2;
|
|
11247
12121
|
const lx = Math.cos(labelAngle) * radius * 0.65;
|
|
11248
12122
|
const ly = Math.sin(labelAngle) * radius * 0.65;
|
|
11249
|
-
const text = document.createElementNS(
|
|
12123
|
+
const text = document.createElementNS(SVG_NS2, "text");
|
|
11250
12124
|
text.setAttribute("x", lx.toFixed(2));
|
|
11251
12125
|
text.setAttribute("y", ly.toFixed(2));
|
|
11252
12126
|
text.setAttribute("fill", "#ffffff");
|
|
@@ -11358,7 +12232,8 @@ class AegisWidgetManager {
|
|
|
11358
12232
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
11359
12233
|
`;
|
|
11360
12234
|
const closeBtn = document.createElement("button");
|
|
11361
|
-
closeBtn.innerHTML = "
|
|
12235
|
+
closeBtn.innerHTML = lucideSvg("x", { size: 16 });
|
|
12236
|
+
closeBtn.setAttribute("aria-label", "Close");
|
|
11362
12237
|
closeBtn.className = "aegis-spin-wheel-close";
|
|
11363
12238
|
closeBtn.style.cssText = `
|
|
11364
12239
|
position: absolute;
|
|
@@ -12338,8 +13213,9 @@ class AegisWidgetManager {
|
|
|
12338
13213
|
}
|
|
12339
13214
|
if (config.show_timer && config.timer_minutes) {
|
|
12340
13215
|
const timer = document.createElement("div");
|
|
12341
|
-
timer.style.cssText = "margin: 0 0 24px 0;
|
|
12342
|
-
timer.
|
|
13216
|
+
timer.style.cssText = "margin: 0 0 24px 0; display: flex; align-items: center; justify-content: center; gap: 6px; font-size: 14px; color: #999;";
|
|
13217
|
+
timer.innerHTML = lucideSvg("clock", { size: 14 });
|
|
13218
|
+
timer.appendChild(document.createTextNode(`Offer expires in ${config.timer_minutes} minutes`));
|
|
12343
13219
|
modal.appendChild(timer);
|
|
12344
13220
|
}
|
|
12345
13221
|
const ctaButton = document.createElement("button");
|
|
@@ -12470,7 +13346,7 @@ class AegisWidgetManager {
|
|
|
12470
13346
|
});
|
|
12471
13347
|
modal.innerHTML = `
|
|
12472
13348
|
<div style="text-align: center; padding: 20px;">
|
|
12473
|
-
<div style="
|
|
13349
|
+
<div style="margin-bottom: 16px; color: #10b981;">${lucideSvg("check", { size: 48 })}</div>
|
|
12474
13350
|
<h3 style="margin: 0 0 12px 0; color: #1a73e8;">Thank You!</h3>
|
|
12475
13351
|
<p style="margin: 0; color: #666;">Check your email for your discount code!</p>
|
|
12476
13352
|
</div>
|
|
@@ -12716,6 +13592,9 @@ class AegisMessageRuntime {
|
|
|
12716
13592
|
getCartState: () => this.deriveCartState()
|
|
12717
13593
|
});
|
|
12718
13594
|
this.intentRuleEvaluator = new IntentRuleEvaluator();
|
|
13595
|
+
if (config.governance) {
|
|
13596
|
+
this.intentRuleEvaluator.setGovernance(config.governance);
|
|
13597
|
+
}
|
|
12719
13598
|
this.contactScores = new ContactScoresFetcher({
|
|
12720
13599
|
// Falls back to same-origin when no apiHost configured (storefront
|
|
12721
13600
|
// typical case) — matches WidgetManager/InAppManager handling
|