@salesforcedevs/dx-components 1.34.0 → 1.35.1

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": "@salesforcedevs/dx-components",
3
- "version": "1.34.0",
3
+ "version": "1.35.1",
4
4
  "description": "DX Lightning web components",
5
5
  "license": "MIT",
6
6
  "engines": {
@@ -44,5 +44,5 @@
44
44
  "luxon": "3.4.4",
45
45
  "msw": "^2.12.4"
46
46
  },
47
- "gitHead": "5d072e2fa81d7eccadcbfb4134ee007ce2b0c7c4"
47
+ "gitHead": "0112829c264018cab7536554f5984faa2fc5c4f5"
48
48
  }
@@ -57,6 +57,24 @@ function loadMiawUiScript(): Promise<void> {
57
57
  return scriptLoaded;
58
58
  }
59
59
 
60
+ function dropCookie(cookieDomain: string) {
61
+ const { hostname, protocol } = window.location;
62
+ const onCookieDomain =
63
+ !!cookieDomain &&
64
+ (hostname === cookieDomain || hostname.endsWith(`.${cookieDomain}`));
65
+
66
+ document.cookie = [
67
+ "show_agent=true",
68
+ "Path=/",
69
+ "Max-Age=2592000",
70
+ "SameSite=Lax",
71
+ protocol === "https:" ? "Secure" : null,
72
+ onCookieDomain ? `Domain=${cookieDomain}` : null
73
+ ]
74
+ .filter(Boolean)
75
+ .join("; ");
76
+ }
77
+
60
78
  export default class AgentMiawUi extends LightningElement {
61
79
  private static readonly SIDEBAR_OPEN_ATTR = "data-xsf-agent-sidebar-open";
62
80
  private static readonly AGENT_ROOT_SELECTOR = '[data-testid="agent-root"]';
@@ -78,6 +96,38 @@ export default class AgentMiawUi extends LightningElement {
78
96
  /** When set, forwarded to the embed as `welcome-text` (greeting / headline copy). */
79
97
  @api welcomeText?: string;
80
98
  @api agentforceEnv?: string;
99
+ private _hideAgentConditionally = false;
100
+
101
+ /**
102
+ * When set, mounting of the agent is gated behind the `showAgent=true` query param
103
+ * or `show_agent=true` cookie opt-in; otherwise (and by default), gating is off.
104
+ *
105
+ * COERCION: this component is consumed as raw, server-rendered HTML on an LWR page —
106
+ * not inside another LWC's template — so LWC's presence→boolean attribute convention
107
+ * does NOT apply automatically. Native attribute reflection runs instead, and LWC's
108
+ * attributeChangedCallback assigns the raw attribute STRING to this property
109
+ * (`this[prop] = newValue`), so a bare `hide-agent-conditionally` arrives as `""`, not
110
+ * boolean `true`. This setter restores HTML boolean-attribute semantics by source:
111
+ * - boolean (LWC property API / tests): honored as-is, so `false` turns gating off.
112
+ * - string (native attribute reflection): PRESENCE means true regardless of value —
113
+ * `""`, `"true"`, and even `"false"` all enable gating, exactly like `disabled="false"`
114
+ * is still disabled. Only absence (null/undefined, i.e. the attribute removed) is false.
115
+ */
116
+ @api
117
+ get hideAgentConditionally(): boolean {
118
+ return this._hideAgentConditionally;
119
+ }
120
+ set hideAgentConditionally(value: boolean | string | null | undefined) {
121
+ this._hideAgentConditionally =
122
+ typeof value === "boolean"
123
+ ? value
124
+ : value !== null && value !== undefined;
125
+ }
126
+ /**
127
+ * Apex domain that the opt-in cookie targets (covers subdomains); applied only when the
128
+ * current host matches it, so local dev / preview hosts fall back to a host-only cookie.
129
+ */
130
+ @api cookieDomain?: string;
81
131
 
82
132
  /** After first mount attempt is scheduled, we do not run it again for this instance. */
83
133
  private hasRendered = false;
@@ -87,7 +137,9 @@ export default class AgentMiawUi extends LightningElement {
87
137
  renderedCallback(): void {
88
138
  if (!this.hasRendered) {
89
139
  this.hasRendered = true;
90
- this.mountMiawHost();
140
+ if (this.shouldMount()) {
141
+ this.mountMiawHost();
142
+ }
91
143
  }
92
144
  }
93
145
 
@@ -96,6 +148,39 @@ export default class AgentMiawUi extends LightningElement {
96
148
  this.sidebarStateObserver = null;
97
149
  }
98
150
 
151
+ /**
152
+ * Decide whether the agent should mount. If conditional gating is off, always mount.
153
+ * If conditional gating of the agent is on, return `true` only when the user has opted in
154
+ * via the `showAgent=true` query param or the `show_agent=true` cookie. (When only the
155
+ * param is present, persists a sticky opt-in cookie (~30 days) as a side effect so the
156
+ * choice carries across pages and subdomains.)
157
+ *
158
+ * CROSS-SITE CONTRACT: the param key/value, cookie token, Max-Age, SameSite, Secure and
159
+ * Domain-scoping logic are MIRRORED in architect-sf, since both serve pages for Architect.
160
+ * Changing these values requires a coordinated change in all repos.
161
+ */
162
+ private shouldMount(): boolean {
163
+ if (!this.hideAgentConditionally) {
164
+ return true;
165
+ }
166
+
167
+ // When the agent should be conditionally hidden, we check for special query param or
168
+ // cookie required for actually mounting/rendering it.
169
+ const hasParam =
170
+ new URLSearchParams(window.location.search).get("showAgent") ===
171
+ "true";
172
+ const hasCookie = /(?:^|;\s*)show_agent=true(?:;|$)/.test(
173
+ document.cookie
174
+ );
175
+
176
+ // If the user doesn't have the cookie yet but does have the param, set the cookie
177
+ if (hasParam && !hasCookie) {
178
+ dropCookie(this.cookieDomain || "");
179
+ }
180
+
181
+ return hasParam || hasCookie;
182
+ }
183
+
99
184
  private async mountMiawHost(): Promise<void> {
100
185
  try {
101
186
  await loadMiawUiScript();
@@ -114,10 +199,7 @@ export default class AgentMiawUi extends LightningElement {
114
199
  this.richComponentVersion
115
200
  );
116
201
  if (this.routingAttributes) {
117
- el.setAttribute(
118
- "routing-attributes",
119
- this.routingAttributes
120
- );
202
+ el.setAttribute("routing-attributes", this.routingAttributes);
121
203
  }
122
204
  if (this.prompts) {
123
205
  el.setAttribute("prompts", this.prompts);
@@ -134,7 +216,9 @@ export default class AgentMiawUi extends LightningElement {
134
216
  }
135
217
 
136
218
  private setSidebarOpenState(isOpen: boolean): void {
137
- const targets = document.querySelectorAll(this.sidebarStateTargetSelector);
219
+ const targets = document.querySelectorAll(
220
+ this.sidebarStateTargetSelector
221
+ );
138
222
  targets.forEach((target) => {
139
223
  target.setAttribute(
140
224
  AgentMiawUi.SIDEBAR_OPEN_ATTR,