@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.
|
|
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": "
|
|
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.
|
|
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(
|
|
219
|
+
const targets = document.querySelectorAll(
|
|
220
|
+
this.sidebarStateTargetSelector
|
|
221
|
+
);
|
|
138
222
|
targets.forEach((target) => {
|
|
139
223
|
target.setAttribute(
|
|
140
224
|
AgentMiawUi.SIDEBAR_OPEN_ATTR,
|