@usereq/widget 0.2.2 → 0.2.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usereq/widget",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "type": "module",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -74,6 +74,7 @@ export class AgentWidgetElement extends HTMLElement {
74
74
  private bootstrapPhase: "idle" | "booting" | "ready" | "blocked" = "idle";
75
75
  private analyticsTrackerKey = "";
76
76
  private analyticsTracker: WidgetAnalyticsTracker | null = null;
77
+ private autoStartTriggered = false;
77
78
 
78
79
  constructor() {
79
80
  super();
@@ -246,14 +247,31 @@ export class AgentWidgetElement extends HTMLElement {
246
247
  const placement = this.getResolvedPlacement();
247
248
  const variant = this.getResolvedVariant();
248
249
  const preset = this.getResolvedPreset();
249
- const emptyAction =
250
+ const autoStartEnabled =
251
+ this.sessionConfig?.widgetConfig.widgetBehavior?.autoStart === true;
252
+ const awaitingConversation =
250
253
  this.status === "booting" ||
251
- (this.sessionState != null && !this.sessionState.conversationId)
254
+ (this.sessionState != null && !this.sessionState.conversationId);
255
+ // When auto-start is on we never render the manual CTA — except as a
256
+ // fallback if the auto-start attempt errored, so the visitor isn't
257
+ // stranded on a blank panel.
258
+ const showFallbackCta = autoStartEnabled && this.status === "error";
259
+ const emptyAction =
260
+ !autoStartEnabled && awaitingConversation
252
261
  ? {
253
262
  label: DEFAULT_START_CONVERSATION_LABEL,
254
263
  onClick: () => void this.handleStartConversation(),
255
264
  disabled: this.status !== "ready",
256
265
  }
266
+ : showFallbackCta
267
+ ? {
268
+ label: DEFAULT_START_CONVERSATION_LABEL,
269
+ onClick: () => {
270
+ this.autoStartTriggered = false;
271
+ void this.handleStartConversation();
272
+ },
273
+ disabled: false,
274
+ }
257
275
  : undefined;
258
276
 
259
277
  this.root.render(
@@ -453,6 +471,27 @@ export class AgentWidgetElement extends HTMLElement {
453
471
  if (this.open && (this.status === "idle" || !this.sessionState)) {
454
472
  await this.ensureBootstrap();
455
473
  }
474
+
475
+ this.maybeAutoStartConversation();
476
+ }
477
+
478
+ /**
479
+ * Auto-start opt-in: when the agent has `widgetBehavior.autoStart`
480
+ * enabled, the first time the visitor opens the launcher we transparently
481
+ * call /conversations/public/start so they skip the empty state. Fires
482
+ * once per element lifetime; subsequent opens reuse the existing
483
+ * conversation via the standard sessionStorage rehydrate.
484
+ */
485
+ private maybeAutoStartConversation() {
486
+ if (this.autoStartTriggered) return;
487
+ if (!this.open) return;
488
+ if (this.status !== "ready") return;
489
+ if (!this.sessionConfig) return;
490
+ if (!this.sessionConfig.widgetConfig.widgetBehavior?.autoStart) return;
491
+ if (this.sessionState?.conversationId) return;
492
+
493
+ this.autoStartTriggered = true;
494
+ void this.handleStartConversation();
456
495
  }
457
496
 
458
497
  private async handleStartConversation() {
@@ -29,6 +29,22 @@ export type WidgetTriggerRule =
29
29
  | { triggerRuleType: "element_clicked"; elementClicked: string }
30
30
  | { triggerRuleType: "element_displayed"; elementDisplayed: string };
31
31
 
32
+ export type WidgetBehavior = {
33
+ autoStart: boolean;
34
+ };
35
+
36
+ export const DEFAULT_WIDGET_BEHAVIOR: WidgetBehavior = {
37
+ autoStart: false,
38
+ };
39
+
40
+ export function normalizeWidgetBehavior(
41
+ behavior: Partial<WidgetBehavior> | null | undefined,
42
+ ): WidgetBehavior {
43
+ return {
44
+ autoStart: Boolean(behavior?.autoStart),
45
+ };
46
+ }
47
+
32
48
  export function widgetTriggerRuleKey(
33
49
  rule: WidgetTriggerRule | null | undefined,
34
50
  ): string {
package/src/types.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type {
2
2
  WidgetAppearance,
3
+ WidgetBehavior,
3
4
  WidgetPlacement,
4
5
  WidgetPreset,
5
6
  WidgetVariant,
@@ -8,12 +9,15 @@ import type {
8
9
 
9
10
  export {
10
11
  DEFAULT_WIDGET_APPEARANCE,
12
+ DEFAULT_WIDGET_BEHAVIOR,
11
13
  DEFAULT_WIDGET_PRESET,
12
14
  type WidgetAppearance,
15
+ type WidgetBehavior,
13
16
  type WidgetPlacement,
14
17
  type WidgetPreset,
15
18
  type WidgetVariant,
16
19
  normalizeWidgetAppearance,
20
+ normalizeWidgetBehavior,
17
21
  normalizeWidgetPlacement,
18
22
  normalizeWidgetPreset,
19
23
  normalizeWidgetVariant,
@@ -40,6 +44,7 @@ export type WidgetSessionConfig = {
40
44
  welcomeMessage: string | null;
41
45
  spotlightMessages: string[];
42
46
  widgetAppearance: WidgetAppearance;
47
+ widgetBehavior: WidgetBehavior;
43
48
  widgetVariant: WidgetVariant;
44
49
  widgetPreset: WidgetPreset;
45
50
  widgetPlacement: WidgetPlacement;