@syntrologie/adapt-chatbot 2.8.0-canary.31 → 2.8.0-canary.310
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/AdaptiveChatBar.d.ts +85 -0
- package/dist/AdaptiveChatBar.d.ts.map +1 -0
- package/dist/AdaptiveChatBar.js +10 -0
- package/dist/AdaptiveChatBar.js.map +7 -0
- package/dist/AdaptiveChatBarMountable.d.ts +35 -0
- package/dist/AdaptiveChatBarMountable.d.ts.map +1 -0
- package/dist/AdaptiveChatTrail.d.ts +85 -0
- package/dist/AdaptiveChatTrail.d.ts.map +1 -0
- package/dist/AdaptiveChatTrail.js +9 -0
- package/dist/AdaptiveChatTrail.js.map +7 -0
- package/dist/AdaptiveChipsStrip.d.ts +1150 -0
- package/dist/AdaptiveChipsStrip.d.ts.map +1 -0
- package/dist/AdaptiveChipsStrip.js +11 -0
- package/dist/AdaptiveChipsStrip.js.map +7 -0
- package/dist/AdaptiveChipsStripMountable.d.ts +24 -0
- package/dist/AdaptiveChipsStripMountable.d.ts.map +1 -0
- package/dist/ChatAssistantLit.d.ts +60 -0
- package/dist/ChatAssistantLit.d.ts.map +1 -0
- package/dist/ChatAssistantLit.js +12 -0
- package/dist/ChatAssistantLit.js.map +7 -0
- package/dist/ChatSession.d.ts +178 -0
- package/dist/ChatSession.d.ts.map +1 -0
- package/dist/ChatTransport.d.ts +283 -0
- package/dist/ChatTransport.d.ts.map +1 -0
- package/dist/NavLinkMountable.d.ts +25 -0
- package/dist/NavLinkMountable.d.ts.map +1 -0
- package/dist/NavLinkMountable.test.d.ts +2 -0
- package/dist/NavLinkMountable.test.d.ts.map +1 -0
- package/dist/TextAnswerMountable.d.ts +17 -0
- package/dist/TextAnswerMountable.d.ts.map +1 -0
- package/dist/Turnstile.d.ts +83 -0
- package/dist/Turnstile.d.ts.map +1 -0
- package/dist/cdn.d.ts +2 -6
- package/dist/cdn.d.ts.map +1 -1
- package/dist/chunk-2ZUJ7DZI.js +8770 -0
- package/dist/chunk-2ZUJ7DZI.js.map +7 -0
- package/dist/chunk-BNN5YLN3.js +417 -0
- package/dist/chunk-BNN5YLN3.js.map +7 -0
- package/dist/chunk-FVNSOP7B.js +634 -0
- package/dist/chunk-FVNSOP7B.js.map +7 -0
- package/dist/chunk-ONGGPQER.js +3722 -0
- package/dist/chunk-ONGGPQER.js.map +7 -0
- package/dist/chunk-SCVTTLFJ.js +334 -0
- package/dist/chunk-SCVTTLFJ.js.map +7 -0
- package/dist/chunk-UVKRO5ER.js +13 -0
- package/dist/chunk-UVKRO5ER.js.map +7 -0
- package/dist/chunk-VLJ3WOEX.js +231 -0
- package/dist/chunk-VLJ3WOEX.js.map +7 -0
- package/dist/editor-lit.d.ts +37 -0
- package/dist/editor-lit.d.ts.map +1 -0
- package/dist/editor-lit.js +134 -0
- package/dist/editor-lit.js.map +7 -0
- package/dist/elements/ActionHandler.d.ts +34 -0
- package/dist/elements/ActionHandler.d.ts.map +1 -0
- package/dist/elements/ElementInstanceStore.d.ts +155 -0
- package/dist/elements/ElementInstanceStore.d.ts.map +1 -0
- package/dist/elements/ElementInstanceStore.test.d.ts +2 -0
- package/dist/elements/ElementInstanceStore.test.d.ts.map +1 -0
- package/dist/elements/ElementTypeHandler.d.ts +77 -0
- package/dist/elements/ElementTypeHandler.d.ts.map +1 -0
- package/dist/elements/ItemHandler.d.ts +60 -0
- package/dist/elements/ItemHandler.d.ts.map +1 -0
- package/dist/elements/ItemHandler.test.d.ts +2 -0
- package/dist/elements/ItemHandler.test.d.ts.map +1 -0
- package/dist/elements/TileHandler.d.ts +52 -0
- package/dist/elements/TileHandler.d.ts.map +1 -0
- package/dist/elements/blockRenderer.d.ts +46 -0
- package/dist/elements/blockRenderer.d.ts.map +1 -0
- package/dist/elements/blockRenderer.test.d.ts +13 -0
- package/dist/elements/blockRenderer.test.d.ts.map +1 -0
- package/dist/elements/blocks.d.ts +58 -0
- package/dist/elements/blocks.d.ts.map +1 -0
- package/dist/elements/envelope.d.ts +24 -0
- package/dist/elements/envelope.d.ts.map +1 -0
- package/dist/elements/fetcher.d.ts +40 -0
- package/dist/elements/fetcher.d.ts.map +1 -0
- package/dist/elements/index.d.ts +32 -0
- package/dist/elements/index.d.ts.map +1 -0
- package/dist/elements/types.d.ts +106 -0
- package/dist/elements/types.d.ts.map +1 -0
- package/dist/observer/__tests__/allowlist.test.d.ts +9 -0
- package/dist/observer/__tests__/allowlist.test.d.ts.map +1 -0
- package/dist/observer/__tests__/observer-isolation.test.d.ts +13 -0
- package/dist/observer/__tests__/observer-isolation.test.d.ts.map +1 -0
- package/dist/observer/__tests__/queue.test.d.ts +2 -0
- package/dist/observer/__tests__/queue.test.d.ts.map +1 -0
- package/dist/observer/__tests__/transport.test.d.ts +2 -0
- package/dist/observer/__tests__/transport.test.d.ts.map +1 -0
- package/dist/observer/allowlist.d.ts +32 -0
- package/dist/observer/allowlist.d.ts.map +1 -0
- package/dist/observer/index.d.ts +35 -0
- package/dist/observer/index.d.ts.map +1 -0
- package/dist/observer/queue.d.ts +57 -0
- package/dist/observer/queue.d.ts.map +1 -0
- package/dist/observer/transport.d.ts +26 -0
- package/dist/observer/transport.d.ts.map +1 -0
- package/dist/runtime-lit.d.ts +8 -0
- package/dist/runtime-lit.d.ts.map +1 -0
- package/dist/runtime.d.ts +8 -3
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +1649 -29
- package/dist/runtime.js.map +7 -0
- package/dist/schema.d.ts +3298 -11
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +126 -31
- package/dist/schema.js.map +7 -0
- package/dist/types.d.ts +47 -31
- package/dist/types.d.ts.map +1 -1
- package/package.json +50 -19
- package/dist/ChatAssistant.d.ts +0 -18
- package/dist/ChatAssistant.d.ts.map +0 -1
- package/dist/ChatAssistant.js +0 -178
- package/dist/actionParser.d.ts +0 -15
- package/dist/actionParser.d.ts.map +0 -1
- package/dist/actionParser.js +0 -52
- package/dist/apiClient.d.ts +0 -23
- package/dist/apiClient.d.ts.map +0 -1
- package/dist/apiClient.js +0 -51
- package/dist/cdn.js +0 -37
- package/dist/editor.d.ts +0 -17
- package/dist/editor.d.ts.map +0 -1
- package/dist/editor.js +0 -36
- package/dist/types.js +0 -6
- package/dist/useChat.d.ts +0 -25
- package/dist/useChat.d.ts.map +0 -1
- package/dist/useChat.js +0 -106
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
// src/AdaptiveChatBar.ts
|
|
2
|
+
import { html, LitElement, nothing } from "lit";
|
|
3
|
+
import { styleMap } from "lit/directives/style-map.js";
|
|
4
|
+
var DEFAULT_PLACEHOLDER = "Ask, find, or navigate\u2026";
|
|
5
|
+
var AdaptiveChatBar = class extends LitElement {
|
|
6
|
+
constructor() {
|
|
7
|
+
super(...arguments);
|
|
8
|
+
this.messages = [];
|
|
9
|
+
/** Pass-through to {@link AdaptiveChatTrail}'s ``forceExpanded`` prop.
|
|
10
|
+
* Hosts that mount the chat-bar in a full-screen surface (mobile
|
|
11
|
+
* panel, agent app, etc.) set this to skip the collapse affordance
|
|
12
|
+
* — there is no smaller state to fall back to. */
|
|
13
|
+
this.forceExpanded = false;
|
|
14
|
+
this.placeholder = DEFAULT_PLACEHOLDER;
|
|
15
|
+
/**
|
|
16
|
+
* Initial assistant message shown before any real conversation
|
|
17
|
+
* starts. Renders inside the trail as a phantom assistant chip
|
|
18
|
+
* when messages.length === 0; auto-disappears as soon as the
|
|
19
|
+
* first user message lands. Mirrors ChatAssistantLit's greeting.
|
|
20
|
+
*/
|
|
21
|
+
this.greeting = void 0;
|
|
22
|
+
/**
|
|
23
|
+
* Whether a chat round-trip is in flight (request sent, awaiting
|
|
24
|
+
* reply). The single send/stop button morphs accordingly: ↑ when
|
|
25
|
+
* ready, ⏹ when in-flight. Parent owns this state — set true after
|
|
26
|
+
* `chat-message-sent` fires, false when the reply lands or the
|
|
27
|
+
* request is aborted. Enter is inert while in-flight.
|
|
28
|
+
*/
|
|
29
|
+
this.inFlight = false;
|
|
30
|
+
this._input = "";
|
|
31
|
+
// Host-level styling (display, width, height, flex, etc.) is owned
|
|
32
|
+
// by the container — SDK shadow root provides default rules, panel
|
|
33
|
+
// overrides via design tokens (--sc-chat-bar-host-*). This adaptive
|
|
34
|
+
// never sets inline styles on itself. See SmartCanvasElementLit's
|
|
35
|
+
// static styles for the rule.
|
|
36
|
+
this._onInput = (e) => {
|
|
37
|
+
this._input = e.target.value;
|
|
38
|
+
};
|
|
39
|
+
this._onKeyDown = (e) => {
|
|
40
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
41
|
+
e.preventDefault();
|
|
42
|
+
if (this.inFlight) return;
|
|
43
|
+
this._send();
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
// Single button. Click delegates to send-or-interrupt based on
|
|
47
|
+
// current state. Same DOM node, different behavior — discoverability
|
|
48
|
+
// wins from the user not having to scan for which control is active.
|
|
49
|
+
this._onSendOrInterrupt = () => {
|
|
50
|
+
if (this.inFlight) {
|
|
51
|
+
this.dispatchEvent(new CustomEvent("chat-interrupt", { bubbles: true, composed: true }));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
this._send();
|
|
55
|
+
};
|
|
56
|
+
this._onClose = () => {
|
|
57
|
+
this.dispatchEvent(new CustomEvent("canvas-close", { bubbles: true, composed: true }));
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
createRenderRoot() {
|
|
61
|
+
return this;
|
|
62
|
+
}
|
|
63
|
+
_send() {
|
|
64
|
+
const text = this._input.trim();
|
|
65
|
+
if (!text) return;
|
|
66
|
+
this.dispatchEvent(
|
|
67
|
+
new CustomEvent("chat-message-sent", {
|
|
68
|
+
detail: { text },
|
|
69
|
+
bubbles: true,
|
|
70
|
+
composed: true
|
|
71
|
+
})
|
|
72
|
+
);
|
|
73
|
+
this._input = "";
|
|
74
|
+
const input = this.querySelector("input[data-chat-input]");
|
|
75
|
+
if (input) input.value = "";
|
|
76
|
+
}
|
|
77
|
+
render() {
|
|
78
|
+
return html`
|
|
79
|
+
<div style=${styleMap(rootStyles(this.forceExpanded))}>
|
|
80
|
+
${this.forceExpanded ? renderHeader() : nothing}
|
|
81
|
+
<adaptive-chat-trail
|
|
82
|
+
.messages=${this.messages}
|
|
83
|
+
.greeting=${this.greeting}
|
|
84
|
+
.forceExpanded=${this.forceExpanded}
|
|
85
|
+
></adaptive-chat-trail>
|
|
86
|
+
<div style=${styleMap(rowStyles(this.forceExpanded))} data-chat-row>
|
|
87
|
+
<span style=${styleMap(avatarStyles())} aria-hidden="true">✦</span>
|
|
88
|
+
<input
|
|
89
|
+
data-chat-input
|
|
90
|
+
type="text"
|
|
91
|
+
placeholder=${this.placeholder}
|
|
92
|
+
.value=${this._input}
|
|
93
|
+
@input=${this._onInput}
|
|
94
|
+
@keydown=${this._onKeyDown}
|
|
95
|
+
style=${styleMap(inputStyles())}
|
|
96
|
+
aria-label="Chat input"
|
|
97
|
+
/>
|
|
98
|
+
<button
|
|
99
|
+
type="button"
|
|
100
|
+
data-chat-send
|
|
101
|
+
data-state=${this.inFlight ? "in-flight" : "ready"}
|
|
102
|
+
@click=${this._onSendOrInterrupt}
|
|
103
|
+
aria-label=${this.inFlight ? "Stop" : "Send message"}
|
|
104
|
+
title=${this.inFlight ? "Interrupt" : "Send"}
|
|
105
|
+
style=${styleMap(sendStyles(this.inFlight))}
|
|
106
|
+
>${this.inFlight ? "\u25A0" : "\u2191"}</button>
|
|
107
|
+
<button
|
|
108
|
+
type="button"
|
|
109
|
+
data-chat-close
|
|
110
|
+
@click=${this._onClose}
|
|
111
|
+
aria-label="Hide chat"
|
|
112
|
+
style=${styleMap(closeStyles())}
|
|
113
|
+
>✕</button>
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
`;
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
AdaptiveChatBar.properties = {
|
|
120
|
+
messages: { attribute: false },
|
|
121
|
+
placeholder: { type: String },
|
|
122
|
+
greeting: { type: String },
|
|
123
|
+
inFlight: { type: Boolean, reflect: true },
|
|
124
|
+
forceExpanded: { type: Boolean, reflect: true },
|
|
125
|
+
_input: { state: true }
|
|
126
|
+
};
|
|
127
|
+
function rootStyles(forceExpanded) {
|
|
128
|
+
if (!forceExpanded) {
|
|
129
|
+
return {
|
|
130
|
+
display: "flex",
|
|
131
|
+
flexDirection: "column",
|
|
132
|
+
gap: "6px",
|
|
133
|
+
width: "100%",
|
|
134
|
+
pointerEvents: "auto"
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
position: "relative",
|
|
139
|
+
display: "flex",
|
|
140
|
+
flexDirection: "column",
|
|
141
|
+
gap: "8px",
|
|
142
|
+
width: "100%",
|
|
143
|
+
height: "100%",
|
|
144
|
+
boxSizing: "border-box",
|
|
145
|
+
flex: "1 1 auto",
|
|
146
|
+
minHeight: "0",
|
|
147
|
+
overflow: "hidden",
|
|
148
|
+
pointerEvents: "auto",
|
|
149
|
+
background: "var(--sc-tile-background, rgba(255, 255, 255, 0.92))",
|
|
150
|
+
border: "var(--sc-tile-border, 1px solid rgba(0, 0, 0, 0.06))",
|
|
151
|
+
borderRadius: "var(--sc-tile-border-radius, 14px)",
|
|
152
|
+
boxShadow: "var(--sc-tile-shadow, 0 12px 32px -16px rgba(0, 0, 0, 0.18))",
|
|
153
|
+
// Reserves room for the absolute-positioned input pill (36px high
|
|
154
|
+
// + 12px from bottom) plus a 16px visual gap above the input.
|
|
155
|
+
padding: "0.75rem 0.75rem calc(36px + 1.75rem)",
|
|
156
|
+
color: "var(--sc-tile-title-color, inherit)",
|
|
157
|
+
fontFamily: "var(--sc-font-family, inherit)",
|
|
158
|
+
// Override the trail's host-layout tokens so the trail (a flex item
|
|
159
|
+
// of this column) shrinks to 0 first when space is tight — letting
|
|
160
|
+
// the header and absolute-positioned input pill stay pinned. The
|
|
161
|
+
// SDK-level rule in SmartCanvasElementLit consumes these tokens on
|
|
162
|
+
// adaptive-chat-trail's host element. Containers OWN host styling
|
|
163
|
+
// via tokens; the adaptive never sets inline styles on its host.
|
|
164
|
+
["--sc-chat-trail-host-display"]: "flex",
|
|
165
|
+
["--sc-chat-trail-host-flex-direction"]: "column",
|
|
166
|
+
["--sc-chat-trail-host-flex"]: "1 1 0",
|
|
167
|
+
["--sc-chat-trail-host-min-height"]: "0",
|
|
168
|
+
["--sc-chat-trail-host-overflow"]: "hidden"
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
function rowStyles(forceExpanded) {
|
|
172
|
+
if (forceExpanded) {
|
|
173
|
+
return {
|
|
174
|
+
position: "absolute",
|
|
175
|
+
left: "0.75rem",
|
|
176
|
+
right: "0.75rem",
|
|
177
|
+
bottom: "0.75rem",
|
|
178
|
+
display: "flex",
|
|
179
|
+
alignItems: "center",
|
|
180
|
+
gap: "8px",
|
|
181
|
+
padding: "6px 14px",
|
|
182
|
+
borderRadius: "9999px",
|
|
183
|
+
background: "rgba(0, 0, 0, 0.04)",
|
|
184
|
+
border: "1px solid rgba(0, 0, 0, 0.10)",
|
|
185
|
+
color: "var(--sc-content-text-color, inherit)",
|
|
186
|
+
fontFamily: "var(--sc-font-family, inherit)",
|
|
187
|
+
minHeight: "36px"
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
return {
|
|
191
|
+
display: "flex",
|
|
192
|
+
alignItems: "center",
|
|
193
|
+
gap: "8px",
|
|
194
|
+
padding: "10px 12px",
|
|
195
|
+
borderRadius: "var(--sc-tile-border-radius, 14px)",
|
|
196
|
+
background: "var(--sc-tile-background, rgba(15, 19, 24, 0.6))",
|
|
197
|
+
backdropFilter: "var(--sc-chat-bar-blur, blur(24px) saturate(140%))",
|
|
198
|
+
WebkitBackdropFilter: "var(--sc-chat-bar-blur, blur(24px) saturate(140%))",
|
|
199
|
+
border: "var(--sc-tile-border, 1px solid rgba(255, 255, 255, 0.08))",
|
|
200
|
+
boxShadow: "var(--sc-tile-shadow, 0 2px 12px rgba(0, 0, 0, 0.3))",
|
|
201
|
+
color: "var(--sc-tile-title-color, #fafafa)",
|
|
202
|
+
fontFamily: "var(--sc-font-family, inherit)"
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
function avatarStyles() {
|
|
206
|
+
return {
|
|
207
|
+
display: "inline-flex",
|
|
208
|
+
alignItems: "center",
|
|
209
|
+
justifyContent: "center",
|
|
210
|
+
width: "24px",
|
|
211
|
+
height: "24px",
|
|
212
|
+
borderRadius: "9999px",
|
|
213
|
+
background: "hsl(var(--sc-accent-color) / 0.15)",
|
|
214
|
+
border: "1px solid hsl(var(--sc-accent-color) / 0.30)",
|
|
215
|
+
color: "hsl(var(--sc-accent-color) / 0.95)",
|
|
216
|
+
flexShrink: "0",
|
|
217
|
+
fontSize: "11px"
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
function inputStyles() {
|
|
221
|
+
return {
|
|
222
|
+
flex: "1",
|
|
223
|
+
minWidth: "0",
|
|
224
|
+
background: "transparent",
|
|
225
|
+
border: "none",
|
|
226
|
+
outline: "none",
|
|
227
|
+
color: "inherit",
|
|
228
|
+
fontSize: "13px"
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
function sendStyles(inFlight) {
|
|
232
|
+
return {
|
|
233
|
+
width: "28px",
|
|
234
|
+
height: "28px",
|
|
235
|
+
display: "inline-flex",
|
|
236
|
+
alignItems: "center",
|
|
237
|
+
justifyContent: "center",
|
|
238
|
+
borderRadius: "9999px",
|
|
239
|
+
// Ready: filled accent (send is the affordance). In-flight: hollow
|
|
240
|
+
// ring + accent ring (stop is a one-of-a-kind disruptive action,
|
|
241
|
+
// styled differently so the user reads "this isn't just send").
|
|
242
|
+
background: inFlight ? "transparent" : "hsl(var(--sc-accent-color) / 0.85)",
|
|
243
|
+
color: inFlight ? "hsl(var(--sc-accent-color) / 0.95)" : "var(--sc-accent-foreground, #fff)",
|
|
244
|
+
border: inFlight ? "1px solid hsl(var(--sc-accent-color) / 0.55)" : "none",
|
|
245
|
+
cursor: "pointer",
|
|
246
|
+
flexShrink: "0",
|
|
247
|
+
transition: "background 150ms ease, color 150ms ease, border-color 150ms ease"
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
function closeStyles() {
|
|
251
|
+
return {
|
|
252
|
+
width: "28px",
|
|
253
|
+
height: "28px",
|
|
254
|
+
display: "inline-flex",
|
|
255
|
+
alignItems: "center",
|
|
256
|
+
justifyContent: "center",
|
|
257
|
+
borderRadius: "9999px",
|
|
258
|
+
background: "transparent",
|
|
259
|
+
color: "inherit",
|
|
260
|
+
border: "var(--sc-content-bubble-border, 1px solid rgba(255, 255, 255, 0.18))",
|
|
261
|
+
cursor: "pointer",
|
|
262
|
+
flexShrink: "0",
|
|
263
|
+
opacity: "0.7"
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
function renderHeader() {
|
|
267
|
+
const headerStyles = {
|
|
268
|
+
display: "flex",
|
|
269
|
+
alignItems: "center",
|
|
270
|
+
gap: "8px",
|
|
271
|
+
padding: "4px 4px 12px",
|
|
272
|
+
borderBottom: "1px solid var(--sc-content-divider-color, rgba(0, 0, 0, 0.08))",
|
|
273
|
+
flex: "0 0 auto"
|
|
274
|
+
};
|
|
275
|
+
const avatar = {
|
|
276
|
+
display: "inline-flex",
|
|
277
|
+
alignItems: "center",
|
|
278
|
+
justifyContent: "center",
|
|
279
|
+
width: "28px",
|
|
280
|
+
height: "28px",
|
|
281
|
+
borderRadius: "9999px",
|
|
282
|
+
background: "var(--sc-tile-icon-background, linear-gradient(135deg, #5faf7d 0%, #3d8a5e 100%))",
|
|
283
|
+
color: "#fff",
|
|
284
|
+
flexShrink: "0",
|
|
285
|
+
fontSize: "14px"
|
|
286
|
+
};
|
|
287
|
+
const nameWrap = {
|
|
288
|
+
display: "flex",
|
|
289
|
+
flexDirection: "column",
|
|
290
|
+
minWidth: "0",
|
|
291
|
+
flex: "1 1 auto"
|
|
292
|
+
};
|
|
293
|
+
const name = {
|
|
294
|
+
fontSize: "0.85rem",
|
|
295
|
+
fontWeight: "600",
|
|
296
|
+
color: "var(--sc-content-text-color, inherit)",
|
|
297
|
+
lineHeight: "1.2"
|
|
298
|
+
};
|
|
299
|
+
const status = {
|
|
300
|
+
fontSize: "0.7rem",
|
|
301
|
+
color: "var(--sc-tile-title-color, #3d8275)",
|
|
302
|
+
display: "flex",
|
|
303
|
+
alignItems: "center",
|
|
304
|
+
gap: "4px",
|
|
305
|
+
lineHeight: "1.2"
|
|
306
|
+
};
|
|
307
|
+
const statusDot = {
|
|
308
|
+
width: "6px",
|
|
309
|
+
height: "6px",
|
|
310
|
+
borderRadius: "9999px",
|
|
311
|
+
background: "var(--sc-tile-title-color, #3d8275)",
|
|
312
|
+
display: "inline-block"
|
|
313
|
+
};
|
|
314
|
+
return html`
|
|
315
|
+
<div style=${styleMap(headerStyles)} data-chat-header>
|
|
316
|
+
<span style=${styleMap(avatar)} aria-hidden="true">✦</span>
|
|
317
|
+
<div style=${styleMap(nameWrap)}>
|
|
318
|
+
<span style=${styleMap(name)}>Assistant</span>
|
|
319
|
+
<span style=${styleMap(status)}>
|
|
320
|
+
<span style=${styleMap(statusDot)}></span>
|
|
321
|
+
Online · understands your session
|
|
322
|
+
</span>
|
|
323
|
+
</div>
|
|
324
|
+
</div>
|
|
325
|
+
`;
|
|
326
|
+
}
|
|
327
|
+
if (!customElements.get("adaptive-chat-bar")) {
|
|
328
|
+
customElements.define("adaptive-chat-bar", AdaptiveChatBar);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
export {
|
|
332
|
+
AdaptiveChatBar
|
|
333
|
+
};
|
|
334
|
+
//# sourceMappingURL=chunk-SCVTTLFJ.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/AdaptiveChatBar.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * AdaptiveChatBar \u2014 the canvas lid composition for the chat-canvas\n * experience. Renders the bubble-up trail on top and an always-visible\n * input row below.\n *\n * Wiring contract (events out):\n * - `chat-message-sent` ({ text }): the user submitted text via Enter\n * or the send button. The owning code is responsible for pushing\n * this into the conversation history and producing a reply.\n * - `canvas-close`: the user clicked the close \u2715 button. Propagated\n * to the canvas overlay so the underlying drawer is dismissed.\n *\n * Wiring contract (props in):\n * - `messages`: the conversation trail, passed straight through to\n * `<adaptive-chat-trail>`.\n * - `placeholder`: input placeholder copy. Defaults to a generic\n * \"Ask, find, or navigate\u2026\" \u2014 the host (typically the slot's lid\n * widget mount) can override to a context-specific string.\n *\n * Light DOM. Glassmorphism is applied at the input-row level so the\n * trail above floats over the host page without chrome. See PRD \u00A74.4.\n */\n\nimport { html, LitElement, nothing } from 'lit';\nimport { styleMap } from 'lit/directives/style-map.js';\n\nimport './AdaptiveChatTrail.js';\nimport type { TrailMessage } from './AdaptiveChatTrail.js';\n\nconst DEFAULT_PLACEHOLDER = 'Ask, find, or navigate\u2026';\n\nexport class AdaptiveChatBar extends LitElement {\n static override properties = {\n messages: { attribute: false },\n placeholder: { type: String },\n greeting: { type: String },\n inFlight: { type: Boolean, reflect: true },\n forceExpanded: { type: Boolean, reflect: true },\n _input: { state: true },\n };\n\n messages: TrailMessage[] = [];\n\n /** Pass-through to {@link AdaptiveChatTrail}'s ``forceExpanded`` prop.\n * Hosts that mount the chat-bar in a full-screen surface (mobile\n * panel, agent app, etc.) set this to skip the collapse affordance\n * \u2014 there is no smaller state to fall back to. */\n forceExpanded = false;\n placeholder = DEFAULT_PLACEHOLDER;\n /**\n * Initial assistant message shown before any real conversation\n * starts. Renders inside the trail as a phantom assistant chip\n * when messages.length === 0; auto-disappears as soon as the\n * first user message lands. Mirrors ChatAssistantLit's greeting.\n */\n greeting: string | undefined = undefined;\n /**\n * Whether a chat round-trip is in flight (request sent, awaiting\n * reply). The single send/stop button morphs accordingly: \u2191 when\n * ready, \u23F9 when in-flight. Parent owns this state \u2014 set true after\n * `chat-message-sent` fires, false when the reply lands or the\n * request is aborted. Enter is inert while in-flight.\n */\n inFlight = false;\n _input = '';\n\n override createRenderRoot(): HTMLElement {\n return this;\n }\n\n // Host-level styling (display, width, height, flex, etc.) is owned\n // by the container \u2014 SDK shadow root provides default rules, panel\n // overrides via design tokens (--sc-chat-bar-host-*). This adaptive\n // never sets inline styles on itself. See SmartCanvasElementLit's\n // static styles for the rule.\n\n private _onInput = (e: Event): void => {\n this._input = (e.target as HTMLInputElement).value;\n };\n\n private _onKeyDown = (e: KeyboardEvent): void => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n // Enter is the send affordance \u2014 while in-flight there's nothing\n // to send, so it's a no-op. Interrupt requires the explicit\n // \u23F9 click to avoid surprise-aborting on a stray keystroke.\n if (this.inFlight) return;\n this._send();\n }\n };\n\n // Single button. Click delegates to send-or-interrupt based on\n // current state. Same DOM node, different behavior \u2014 discoverability\n // wins from the user not having to scan for which control is active.\n private _onSendOrInterrupt = (): void => {\n if (this.inFlight) {\n this.dispatchEvent(new CustomEvent('chat-interrupt', { bubbles: true, composed: true }));\n return;\n }\n this._send();\n };\n\n private _onClose = (): void => {\n this.dispatchEvent(new CustomEvent('canvas-close', { bubbles: true, composed: true }));\n };\n\n private _send(): void {\n const text = this._input.trim();\n if (!text) return;\n this.dispatchEvent(\n new CustomEvent<{ text: string }>('chat-message-sent', {\n detail: { text },\n bubbles: true,\n composed: true,\n })\n );\n this._input = '';\n // Drop the input value too \u2014 the input's bound value is `this._input`\n // via the render, but jsdom's two-way binding via property only takes\n // effect after the next render, so set it imperatively for the test\n // and for browser symmetry (most browsers do the right thing here\n // anyway because Lit re-renders on the state change).\n const input = this.querySelector<HTMLInputElement>('input[data-chat-input]');\n if (input) input.value = '';\n }\n\n override render() {\n return html`\n <div style=${styleMap(rootStyles(this.forceExpanded))}>\n ${this.forceExpanded ? renderHeader() : nothing}\n <adaptive-chat-trail\n .messages=${this.messages}\n .greeting=${this.greeting}\n .forceExpanded=${this.forceExpanded}\n ></adaptive-chat-trail>\n <div style=${styleMap(rowStyles(this.forceExpanded))} data-chat-row>\n <span style=${styleMap(avatarStyles())} aria-hidden=\"true\">\u2726</span>\n <input\n data-chat-input\n type=\"text\"\n placeholder=${this.placeholder}\n .value=${this._input}\n @input=${this._onInput}\n @keydown=${this._onKeyDown}\n style=${styleMap(inputStyles())}\n aria-label=\"Chat input\"\n />\n <button\n type=\"button\"\n data-chat-send\n data-state=${this.inFlight ? 'in-flight' : 'ready'}\n @click=${this._onSendOrInterrupt}\n aria-label=${this.inFlight ? 'Stop' : 'Send message'}\n title=${this.inFlight ? 'Interrupt' : 'Send'}\n style=${styleMap(sendStyles(this.inFlight))}\n >${this.inFlight ? '\u25A0' : '\u2191'}</button>\n <button\n type=\"button\"\n data-chat-close\n @click=${this._onClose}\n aria-label=\"Hide chat\"\n style=${styleMap(closeStyles())}\n >\u2715</button>\n </div>\n </div>\n `;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Styles \u2014 kept inline (Lit styleMap) so they participate in light-DOM\n// rendering and pick up host CSS variables (e.g. --sc-tile-background).\n// ---------------------------------------------------------------------------\n\nfunction rootStyles(forceExpanded: boolean): Record<string, string> {\n // When the host expects the chat to fill its container (full-screen\n // panel, agent app), we grow vertically AND wrap the whole widget in\n // its own chrome card \u2014 trail + input read as one cohesive surface\n // instead of a naked trail above a chrome'd input. Floating mounts\n // (bottom-right pinned, etc.) stay chrome-less here because their\n // chrome is owned by the host's positioned wrapper.\n if (!forceExpanded) {\n return {\n display: 'flex',\n flexDirection: 'column',\n gap: '6px',\n width: '100%',\n pointerEvents: 'auto',\n };\n }\n // Input is ABSOLUTELY positioned at the bottom of this chrome card\n // (see rowStyles forceExpanded mode). That guarantees the input is\n // always visible \u2014 even when the lid region is tighter than the\n // chat-bar would naturally want. The flex column above holds\n // header + trail; padding-bottom reserves the input's footprint so\n // trail content can never overlap.\n //\n // Priority of \"what disappears when space is tight\":\n // Trail (shrinks to 0 first via flex: 1 1 0)\n // Header (can shrink via default flex: 0 1 auto)\n // Input (NEVER \u2014 it's positioned absolute, always at the bottom)\n return {\n position: 'relative',\n display: 'flex',\n flexDirection: 'column',\n gap: '8px',\n width: '100%',\n height: '100%',\n boxSizing: 'border-box',\n flex: '1 1 auto',\n minHeight: '0',\n overflow: 'hidden',\n pointerEvents: 'auto',\n background: 'var(--sc-tile-background, rgba(255, 255, 255, 0.92))',\n border: 'var(--sc-tile-border, 1px solid rgba(0, 0, 0, 0.06))',\n borderRadius: 'var(--sc-tile-border-radius, 14px)',\n boxShadow: 'var(--sc-tile-shadow, 0 12px 32px -16px rgba(0, 0, 0, 0.18))',\n // Reserves room for the absolute-positioned input pill (36px high\n // + 12px from bottom) plus a 16px visual gap above the input.\n padding: '0.75rem 0.75rem calc(36px + 1.75rem)',\n color: 'var(--sc-tile-title-color, inherit)',\n fontFamily: 'var(--sc-font-family, inherit)',\n // Override the trail's host-layout tokens so the trail (a flex item\n // of this column) shrinks to 0 first when space is tight \u2014 letting\n // the header and absolute-positioned input pill stay pinned. The\n // SDK-level rule in SmartCanvasElementLit consumes these tokens on\n // adaptive-chat-trail's host element. Containers OWN host styling\n // via tokens; the adaptive never sets inline styles on its host.\n ['--sc-chat-trail-host-display']: 'flex',\n ['--sc-chat-trail-host-flex-direction']: 'column',\n ['--sc-chat-trail-host-flex']: '1 1 0',\n ['--sc-chat-trail-host-min-height']: '0',\n ['--sc-chat-trail-host-overflow']: 'hidden',\n };\n}\n\nfunction rowStyles(forceExpanded: boolean): Record<string, string> {\n // forceExpanded \u2014 root container already carries the chrome; row\n // becomes a flat input-pill inside that chrome (subtle border + soft\n // background, no shadow/blur).\n if (forceExpanded) {\n // Absolute-pinned to the chrome card's bottom edge so it never\n // disappears under any container size. The chrome reserves\n // padding-bottom equal to this row's footprint so flex content\n // above (header + trail) can't overlap.\n return {\n position: 'absolute',\n left: '0.75rem',\n right: '0.75rem',\n bottom: '0.75rem',\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n padding: '6px 14px',\n borderRadius: '9999px',\n background: 'rgba(0, 0, 0, 0.04)',\n border: '1px solid rgba(0, 0, 0, 0.10)',\n color: 'var(--sc-content-text-color, inherit)',\n fontFamily: 'var(--sc-font-family, inherit)',\n minHeight: '36px',\n };\n }\n // Floating mount \u2014 keeps the original tile-chrome look.\n return {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n padding: '10px 12px',\n borderRadius: 'var(--sc-tile-border-radius, 14px)',\n background: 'var(--sc-tile-background, rgba(15, 19, 24, 0.6))',\n backdropFilter: 'var(--sc-chat-bar-blur, blur(24px) saturate(140%))',\n WebkitBackdropFilter: 'var(--sc-chat-bar-blur, blur(24px) saturate(140%))',\n border: 'var(--sc-tile-border, 1px solid rgba(255, 255, 255, 0.08))',\n boxShadow: 'var(--sc-tile-shadow, 0 2px 12px rgba(0, 0, 0, 0.3))',\n color: 'var(--sc-tile-title-color, #fafafa)',\n fontFamily: 'var(--sc-font-family, inherit)',\n };\n}\n\nfunction avatarStyles(): Record<string, string> {\n return {\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '24px',\n height: '24px',\n borderRadius: '9999px',\n background: 'hsl(var(--sc-accent-color) / 0.15)',\n border: '1px solid hsl(var(--sc-accent-color) / 0.30)',\n color: 'hsl(var(--sc-accent-color) / 0.95)',\n flexShrink: '0',\n fontSize: '11px',\n };\n}\n\nfunction inputStyles(): Record<string, string> {\n return {\n flex: '1',\n minWidth: '0',\n background: 'transparent',\n border: 'none',\n outline: 'none',\n color: 'inherit',\n fontSize: '13px',\n };\n}\n\nfunction sendStyles(inFlight: boolean): Record<string, string> {\n return {\n width: '28px',\n height: '28px',\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: '9999px',\n // Ready: filled accent (send is the affordance). In-flight: hollow\n // ring + accent ring (stop is a one-of-a-kind disruptive action,\n // styled differently so the user reads \"this isn't just send\").\n background: inFlight ? 'transparent' : 'hsl(var(--sc-accent-color) / 0.85)',\n color: inFlight ? 'hsl(var(--sc-accent-color) / 0.95)' : 'var(--sc-accent-foreground, #fff)',\n border: inFlight ? '1px solid hsl(var(--sc-accent-color) / 0.55)' : 'none',\n cursor: 'pointer',\n flexShrink: '0',\n transition: 'background 150ms ease, color 150ms ease, border-color 150ms ease',\n };\n}\n\nfunction closeStyles(): Record<string, string> {\n return {\n width: '28px',\n height: '28px',\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: '9999px',\n background: 'transparent',\n color: 'inherit',\n border: 'var(--sc-content-bubble-border, 1px solid rgba(255, 255, 255, 0.18))',\n cursor: 'pointer',\n flexShrink: '0',\n opacity: '0.7',\n };\n}\n\nfunction renderHeader() {\n const headerStyles: Record<string, string> = {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n padding: '4px 4px 12px',\n borderBottom: '1px solid var(--sc-content-divider-color, rgba(0, 0, 0, 0.08))',\n flex: '0 0 auto',\n };\n const avatar: Record<string, string> = {\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '28px',\n height: '28px',\n borderRadius: '9999px',\n background: 'var(--sc-tile-icon-background, linear-gradient(135deg, #5faf7d 0%, #3d8a5e 100%))',\n color: '#fff',\n flexShrink: '0',\n fontSize: '14px',\n };\n const nameWrap: Record<string, string> = {\n display: 'flex',\n flexDirection: 'column',\n minWidth: '0',\n flex: '1 1 auto',\n };\n const name: Record<string, string> = {\n fontSize: '0.85rem',\n fontWeight: '600',\n color: 'var(--sc-content-text-color, inherit)',\n lineHeight: '1.2',\n };\n const status: Record<string, string> = {\n fontSize: '0.7rem',\n color: 'var(--sc-tile-title-color, #3d8275)',\n display: 'flex',\n alignItems: 'center',\n gap: '4px',\n lineHeight: '1.2',\n };\n const statusDot: Record<string, string> = {\n width: '6px',\n height: '6px',\n borderRadius: '9999px',\n background: 'var(--sc-tile-title-color, #3d8275)',\n display: 'inline-block',\n };\n return html`\n <div style=${styleMap(headerStyles)} data-chat-header>\n <span style=${styleMap(avatar)} aria-hidden=\"true\">\u2726</span>\n <div style=${styleMap(nameWrap)}>\n <span style=${styleMap(name)}>Assistant</span>\n <span style=${styleMap(status)}>\n <span style=${styleMap(statusDot)}></span>\n Online \u00B7 understands your session\n </span>\n </div>\n </div>\n `;\n}\n\nif (!customElements.get('adaptive-chat-bar')) {\n customElements.define('adaptive-chat-bar', AdaptiveChatBar);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'adaptive-chat-bar': AdaptiveChatBar;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __export = (target, all) => {
|
|
4
|
+
for (var name in all)
|
|
5
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
6
|
+
};
|
|
7
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
8
|
+
|
|
9
|
+
export {
|
|
10
|
+
__export,
|
|
11
|
+
__publicField
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=chunk-UVKRO5ER.js.map
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
// ../../sdk-contracts/dist/mount-plumbing.js
|
|
2
|
+
var MOUNT_PLUMBING_KEYS = ["instanceId", "runtime", "tileId"];
|
|
3
|
+
function stripMountPlumbing(config) {
|
|
4
|
+
if (!config || typeof config !== "object") {
|
|
5
|
+
return {};
|
|
6
|
+
}
|
|
7
|
+
const out = { ...config };
|
|
8
|
+
for (const key of MOUNT_PLUMBING_KEYS) {
|
|
9
|
+
delete out[key];
|
|
10
|
+
}
|
|
11
|
+
return out;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// ../../sdk-contracts/dist/schemas.js
|
|
15
|
+
import { z } from "zod";
|
|
16
|
+
var AnchorIdZ = z.object({
|
|
17
|
+
selector: z.string(),
|
|
18
|
+
route: z.union([z.string(), z.array(z.string())])
|
|
19
|
+
}).strict();
|
|
20
|
+
var AuthoringFieldsZ = {
|
|
21
|
+
id: z.string().optional().describe('Stable action identifier (e.g. "act_3db6a14d2ab0").'),
|
|
22
|
+
title: z.string().max(200).optional().describe("Authoring-only: short label shown on the action plan dashboard. Stripped before serving to the runtime SDK."),
|
|
23
|
+
description: z.string().max(1e3).optional().describe("Authoring-only: one-sentence explanation of what this action does and why. Stripped before serving to the runtime SDK."),
|
|
24
|
+
validation: z.array(z.string().max(500)).max(10).optional().describe("Authoring-only: ordered steps a reviewer can follow to trigger this action and visually confirm it works. Each entry is one step. Stripped before serving to the runtime SDK.")
|
|
25
|
+
};
|
|
26
|
+
var COUNTABLE_EVENTS = [
|
|
27
|
+
// User interactions (from PostHog autocapture normalization)
|
|
28
|
+
"ui.click",
|
|
29
|
+
"ui.scroll",
|
|
30
|
+
"ui.input",
|
|
31
|
+
"ui.change",
|
|
32
|
+
"ui.submit",
|
|
33
|
+
// Behavioral detectors (from event-processor)
|
|
34
|
+
"ui.hover",
|
|
35
|
+
"ui.idle",
|
|
36
|
+
"ui.scroll_thrash",
|
|
37
|
+
"ui.focus_bounce",
|
|
38
|
+
"ui.hesitate",
|
|
39
|
+
"ui.rage_click",
|
|
40
|
+
// Navigation
|
|
41
|
+
"nav.page_view",
|
|
42
|
+
"nav.page_leave"
|
|
43
|
+
];
|
|
44
|
+
var CountableEventZ = z.enum(COUNTABLE_EVENTS).describe("Event name to count. ui.* = user interactions and behavioral detectors (hesitate, rage_click, scroll_thrash, focus_bounce, idle, hover); nav.* = page navigation.");
|
|
45
|
+
var SESSION_METRIC_KEYS = ["time_on_page", "page_views", "scroll_depth"];
|
|
46
|
+
var SessionMetricKeyZ = z.enum(SESSION_METRIC_KEYS).describe("Session metric key. time_on_page = seconds on current page, page_views = pages visited this session, scroll_depth = 0-100 percentage.");
|
|
47
|
+
var PageUrlConditionZ = z.object({
|
|
48
|
+
type: z.literal("page_url"),
|
|
49
|
+
url: z.string().describe('URL path to match (e.g. "/pricing", "/dashboard")')
|
|
50
|
+
}).describe('Fires when the current page URL matches. Use for page-specific actions. Example: {"type": "page_url", "url": "/pricing"}');
|
|
51
|
+
var RouteConditionZ = z.object({
|
|
52
|
+
type: z.literal("route"),
|
|
53
|
+
routeId: z.string().describe("Named route ID from the route filter")
|
|
54
|
+
}).describe("Fires when the current route matches a named route ID.");
|
|
55
|
+
var AnchorVisibleConditionZ = z.object({
|
|
56
|
+
type: z.literal("anchor_visible"),
|
|
57
|
+
anchorId: z.string().describe("CSS selector of the anchor element"),
|
|
58
|
+
state: z.enum(["visible", "present", "absent"]).describe('"visible" = in viewport, "present" = in DOM, "absent" = not in DOM')
|
|
59
|
+
}).describe(`Fires based on a DOM element's visibility state. Example: {"type": "anchor_visible", "anchorId": "#cta-button", "state": "visible"}`);
|
|
60
|
+
var EventOccurredConditionZ = z.object({
|
|
61
|
+
type: z.literal("event_occurred"),
|
|
62
|
+
eventName: z.string().describe('Event name (e.g. "ui.click", "$pageview")'),
|
|
63
|
+
withinMs: z.number().optional().describe("Time window in ms. Omit = any time this session.")
|
|
64
|
+
}).describe('Fires when a specific event has occurred during this session. Example: {"type": "event_occurred", "eventName": "ui.click", "withinMs": 5000}');
|
|
65
|
+
var StateEqualsConditionZ = z.object({
|
|
66
|
+
type: z.literal("state_equals"),
|
|
67
|
+
key: z.string().describe("Key in the SDK persistent state store (localStorage). Only valid for keys the host app explicitly sets via syntro.state.set()."),
|
|
68
|
+
value: z.unknown().describe("Expected value to match against")
|
|
69
|
+
}).describe("Checks the SDK persistent state store (localStorage). ONLY for host-app state set via syntro.state.set() \u2014 NOT for user attributes like region, device, or UTM params (those are handled by segment targeting). Do NOT use this for targeting. If you do not know the valid state keys, do not use this condition type.");
|
|
70
|
+
var ViewportConditionZ = z.object({
|
|
71
|
+
type: z.literal("viewport"),
|
|
72
|
+
minWidth: z.number().optional().describe("Minimum viewport width in pixels"),
|
|
73
|
+
maxWidth: z.number().optional().describe("Maximum viewport width in pixels"),
|
|
74
|
+
minHeight: z.number().optional().describe("Minimum viewport height in pixels"),
|
|
75
|
+
maxHeight: z.number().optional().describe("Maximum viewport height in pixels")
|
|
76
|
+
}).describe('Fires based on viewport (screen) size. Use for responsive behavior. Example: {"type": "viewport", "minWidth": 768} \u2014 fires on tablet and larger.');
|
|
77
|
+
var SessionMetricConditionZ = z.object({
|
|
78
|
+
type: z.literal("session_metric"),
|
|
79
|
+
key: SessionMetricKeyZ,
|
|
80
|
+
operator: z.enum(["gte", "lte", "eq", "gt", "lt"]),
|
|
81
|
+
threshold: z.number().describe("Numeric threshold to compare against")
|
|
82
|
+
}).describe('Fires when a session metric crosses a threshold. Valid keys: "time_on_page" (seconds), "page_views" (count), "scroll_depth" (0-100). Example: {"type": "session_metric", "key": "time_on_page", "operator": "gte", "threshold": 30}');
|
|
83
|
+
var DismissedConditionZ = z.object({
|
|
84
|
+
type: z.literal("dismissed"),
|
|
85
|
+
key: z.string().describe("Dismissal key (usually a tile or action ID)"),
|
|
86
|
+
inverted: z.boolean().optional().describe("When true, fires if NOT dismissed (default behavior)")
|
|
87
|
+
}).describe("Checks if an item has been dismissed by the user. Use with inverted: true to show only if not dismissed.");
|
|
88
|
+
var CooldownActiveConditionZ = z.object({
|
|
89
|
+
type: z.literal("cooldown_active"),
|
|
90
|
+
key: z.string().describe("Cooldown key"),
|
|
91
|
+
inverted: z.boolean().optional().describe("When true, fires if cooldown is NOT active")
|
|
92
|
+
}).describe("Checks if a cooldown timer is currently active. Use to prevent showing the same intervention too frequently.");
|
|
93
|
+
var FrequencyLimitConditionZ = z.object({
|
|
94
|
+
type: z.literal("frequency_limit"),
|
|
95
|
+
key: z.string().describe("Frequency counter key"),
|
|
96
|
+
limit: z.number().describe("Maximum allowed count"),
|
|
97
|
+
inverted: z.boolean().optional().describe("When true, fires if limit NOT reached")
|
|
98
|
+
}).describe("Checks if a frequency limit has been reached. Use to cap how many times an action fires per session.");
|
|
99
|
+
var MatchOpZ = z.object({
|
|
100
|
+
equals: z.union([z.string(), z.number(), z.boolean()]).optional(),
|
|
101
|
+
contains: z.string().optional()
|
|
102
|
+
}).describe("Match operator for counter filters. Exactly one of equals or contains must be specified.");
|
|
103
|
+
var CounterDefZ = z.object({
|
|
104
|
+
events: z.array(CountableEventZ).min(1).describe("Event names to count. Use values from the countable events enum."),
|
|
105
|
+
match: z.record(z.string(), MatchOpZ).optional().describe("Property filters. Keys are event prop names or element-chain fields (tag_name, $el_text, attr__*). All entries AND together.")
|
|
106
|
+
}).describe("Defines what events to count. Registered as an accumulator predicate at config-load time.");
|
|
107
|
+
var EventCountConditionZ = z.object({
|
|
108
|
+
type: z.literal("event_count"),
|
|
109
|
+
key: z.string().describe("Unique key for this counter (used for accumulator registration)"),
|
|
110
|
+
operator: z.enum(["gte", "lte", "eq", "gt", "lt"]),
|
|
111
|
+
count: z.number().int().min(0).describe("Target count threshold"),
|
|
112
|
+
withinMs: z.number().positive().optional().describe("Time window in ms. Omit = count across entire session."),
|
|
113
|
+
counter: CounterDefZ.optional().describe("Inline counter definition. Defines what events to count.")
|
|
114
|
+
}).describe('Fires when accumulated event count crosses a threshold. Most powerful trigger type. Example: {"type": "event_count", "key": "pricing-clicks", "operator": "gte", "count": 3, "counter": {"events": ["ui.click"], "match": {"attr__data-cta": {"contains": "pricing"}}}}');
|
|
115
|
+
var ConditionZ = z.discriminatedUnion("type", [
|
|
116
|
+
PageUrlConditionZ,
|
|
117
|
+
RouteConditionZ,
|
|
118
|
+
AnchorVisibleConditionZ,
|
|
119
|
+
EventOccurredConditionZ,
|
|
120
|
+
StateEqualsConditionZ,
|
|
121
|
+
ViewportConditionZ,
|
|
122
|
+
SessionMetricConditionZ,
|
|
123
|
+
DismissedConditionZ,
|
|
124
|
+
CooldownActiveConditionZ,
|
|
125
|
+
FrequencyLimitConditionZ,
|
|
126
|
+
EventCountConditionZ
|
|
127
|
+
]);
|
|
128
|
+
var RuleZ = z.object({
|
|
129
|
+
conditions: z.array(ConditionZ).describe("Array of conditions \u2014 ALL must match (AND logic) for this rule to fire."),
|
|
130
|
+
value: z.unknown().describe("Value returned when all conditions match. For triggerWhen: true = fire the action.")
|
|
131
|
+
}).describe("A single rule. ALL conditions must match (AND logic). Rules in a strategy are evaluated top-to-bottom \u2014 first rule where all conditions match wins and returns its value.");
|
|
132
|
+
var RuleStrategyZ = z.object({
|
|
133
|
+
type: z.literal("rules"),
|
|
134
|
+
rules: z.array(RuleZ).describe("Ordered list of rules. Evaluated top-to-bottom \u2014 first match wins."),
|
|
135
|
+
default: z.unknown().describe("Fallback value when no rule matches. For triggerWhen: false = do not fire by default.")
|
|
136
|
+
}).describe("Rule-based strategy. Evaluates rules top-to-bottom. First rule where ALL conditions match returns its value. If no rule matches, returns default. For triggerWhen: set value=true on matching rules, default=false.");
|
|
137
|
+
var ScoreStrategyZ = z.object({
|
|
138
|
+
type: z.literal("score"),
|
|
139
|
+
field: z.string(),
|
|
140
|
+
threshold: z.number(),
|
|
141
|
+
above: z.unknown(),
|
|
142
|
+
below: z.unknown()
|
|
143
|
+
}).describe("Score-based strategy. Compares a field value against a threshold.");
|
|
144
|
+
var ModelStrategyZ = z.object({
|
|
145
|
+
type: z.literal("model"),
|
|
146
|
+
modelId: z.string(),
|
|
147
|
+
inputs: z.array(z.string()),
|
|
148
|
+
outputMapping: z.record(z.string(), z.unknown()),
|
|
149
|
+
default: z.unknown()
|
|
150
|
+
}).describe("ML model strategy. Sends inputs to a model and maps outputs.");
|
|
151
|
+
var ExternalStrategyZ = z.object({
|
|
152
|
+
type: z.literal("external"),
|
|
153
|
+
endpoint: z.string(),
|
|
154
|
+
method: z.enum(["GET", "POST"]).optional(),
|
|
155
|
+
default: z.unknown(),
|
|
156
|
+
timeoutMs: z.number().optional()
|
|
157
|
+
}).describe("External API strategy. Calls an endpoint to determine the value.");
|
|
158
|
+
var DecisionStrategyZ = z.discriminatedUnion("type", [
|
|
159
|
+
RuleStrategyZ,
|
|
160
|
+
ScoreStrategyZ,
|
|
161
|
+
ModelStrategyZ,
|
|
162
|
+
ExternalStrategyZ
|
|
163
|
+
]);
|
|
164
|
+
var TriggerWhenZ = DecisionStrategyZ.nullable().optional();
|
|
165
|
+
var EventScopeZ = z.object({
|
|
166
|
+
events: z.array(z.string()),
|
|
167
|
+
urlContains: z.string().optional(),
|
|
168
|
+
props: z.record(z.union([z.string(), z.number(), z.boolean()])).optional()
|
|
169
|
+
});
|
|
170
|
+
var NotifyZ = z.object({
|
|
171
|
+
title: z.string().optional(),
|
|
172
|
+
body: z.string().optional(),
|
|
173
|
+
icon: z.string().optional()
|
|
174
|
+
}).nullable().optional();
|
|
175
|
+
|
|
176
|
+
// ../../../node_modules/@lit/context/lib/create-context.js
|
|
177
|
+
function n(n2) {
|
|
178
|
+
return n2;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// ../../sdk-contracts/dist/canvas-context.js
|
|
182
|
+
var canvasRuntimeContext = n("syntrologie:canvas-runtime");
|
|
183
|
+
|
|
184
|
+
// ../../sdk-contracts/dist/routes.js
|
|
185
|
+
var utf8Decoder = new TextDecoder("utf-8", { fatal: false });
|
|
186
|
+
|
|
187
|
+
// ../../sdk-contracts/dist/tile-lifecycle.js
|
|
188
|
+
var TILE_MOUNTED_EVENT = "element.tile_mounted";
|
|
189
|
+
var TILE_PATCHED_EVENT = "element.tile_patched";
|
|
190
|
+
var TILE_UNMOUNTED_EVENT = "element.tile_unmounted";
|
|
191
|
+
var TILE_REPLAY_REQUEST_EVENT = "element.tile_replay_request";
|
|
192
|
+
|
|
193
|
+
export {
|
|
194
|
+
stripMountPlumbing,
|
|
195
|
+
AuthoringFieldsZ,
|
|
196
|
+
TriggerWhenZ,
|
|
197
|
+
NotifyZ,
|
|
198
|
+
TILE_MOUNTED_EVENT,
|
|
199
|
+
TILE_PATCHED_EVENT,
|
|
200
|
+
TILE_UNMOUNTED_EVENT,
|
|
201
|
+
TILE_REPLAY_REQUEST_EVENT
|
|
202
|
+
};
|
|
203
|
+
/*! Bundled license information:
|
|
204
|
+
|
|
205
|
+
@lit/context/lib/context-request-event.js:
|
|
206
|
+
@lit/context/lib/create-context.js:
|
|
207
|
+
@lit/context/lib/controllers/context-consumer.js:
|
|
208
|
+
@lit/context/lib/value-notifier.js:
|
|
209
|
+
@lit/context/lib/controllers/context-provider.js:
|
|
210
|
+
@lit/context/lib/context-root.js:
|
|
211
|
+
(**
|
|
212
|
+
* @license
|
|
213
|
+
* Copyright 2021 Google LLC
|
|
214
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
215
|
+
*)
|
|
216
|
+
|
|
217
|
+
@lit/context/lib/decorators/provide.js:
|
|
218
|
+
(**
|
|
219
|
+
* @license
|
|
220
|
+
* Copyright 2017 Google LLC
|
|
221
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
222
|
+
*)
|
|
223
|
+
|
|
224
|
+
@lit/context/lib/decorators/consume.js:
|
|
225
|
+
(**
|
|
226
|
+
* @license
|
|
227
|
+
* Copyright 2022 Google LLC
|
|
228
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
229
|
+
*)
|
|
230
|
+
*/
|
|
231
|
+
//# sourceMappingURL=chunk-VLJ3WOEX.js.map
|