@eka-care/medassist-widget-embed 0.2.6 → 0.2.8
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/iframe.js +51 -18
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +79 -11
- package/dist/src/medassist-widget.css +6 -0
- package/dist/src/medassist-widget.js +9 -6
- package/dist/src/medassist-widget.js.map +1 -1
- package/iframe.ts +58 -21
- package/index.ts +81 -12
- package/package.json +1 -1
- package/src/medassist-widget.css +6 -0
- package/src/medassist-widget.js +9 -6
- package/src/medassist-widget.js.map +1 -1
- package/test.html +0 -1
package/dist/iframe.js
CHANGED
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
}
|
|
43
43
|
/** Fetch agent-config from API with timeout; aborts if pending > 10s */
|
|
44
44
|
async function fetchAgentConfig(baseUrl, agentId) {
|
|
45
|
+
var _a;
|
|
45
46
|
const url = `${baseUrl.replace(/\/$/, "")}/med-assist/agent-config/${agentId}`;
|
|
46
47
|
const controller = new AbortController();
|
|
47
48
|
const timeoutId = setTimeout(() => controller.abort(), API_FETCH_TIMEOUT_MS);
|
|
@@ -55,7 +56,7 @@
|
|
|
55
56
|
if (!res.ok)
|
|
56
57
|
return undefined;
|
|
57
58
|
const json = await res.json();
|
|
58
|
-
if ((json === null || json === void 0 ? void 0 : json.success) && (json === null || json === void 0 ? void 0 : json.data))
|
|
59
|
+
if ((json === null || json === void 0 ? void 0 : json.success) && ((_a = json === null || json === void 0 ? void 0 : json.data) === null || _a === void 0 ? void 0 : _a.theme))
|
|
59
60
|
return json.data;
|
|
60
61
|
return undefined;
|
|
61
62
|
}
|
|
@@ -101,10 +102,49 @@
|
|
|
101
102
|
const WIDGET_CSS_URL = `${widgetAssetBaseUrl}medassist-widget.css`;
|
|
102
103
|
let widgetScriptPromise = null;
|
|
103
104
|
let widgetCssTextPromise = null;
|
|
105
|
+
// --- Start loading as early as possible (don't wait for DOMContentLoaded) ---
|
|
106
|
+
const urlParams = new URLSearchParams(typeof window !== "undefined" ? window.location.search : "");
|
|
107
|
+
const earlyAgentId = urlParams.get("agentId");
|
|
108
|
+
const earlyBaseUrl = urlParams.get("baseUrl") || "https://matrix.eka.care/reloaded";
|
|
109
|
+
if (typeof document !== "undefined" && document.head) {
|
|
110
|
+
try {
|
|
111
|
+
const assetOrigin = new URL(widgetAssetBaseUrl).origin;
|
|
112
|
+
const apiOrigin = new URL(earlyBaseUrl).origin;
|
|
113
|
+
const preconnectAsset = document.createElement("link");
|
|
114
|
+
preconnectAsset.rel = "preconnect";
|
|
115
|
+
preconnectAsset.href = assetOrigin;
|
|
116
|
+
preconnectAsset.crossOrigin = "anonymous";
|
|
117
|
+
document.head.appendChild(preconnectAsset);
|
|
118
|
+
if (assetOrigin !== apiOrigin) {
|
|
119
|
+
const preconnectApi = document.createElement("link");
|
|
120
|
+
preconnectApi.rel = "preconnect";
|
|
121
|
+
preconnectApi.href = apiOrigin;
|
|
122
|
+
preconnectApi.crossOrigin = "anonymous";
|
|
123
|
+
document.head.appendChild(preconnectApi);
|
|
124
|
+
}
|
|
125
|
+
const preloadScript = document.createElement("link");
|
|
126
|
+
preloadScript.rel = "preload";
|
|
127
|
+
preloadScript.as = "script";
|
|
128
|
+
preloadScript.href = WIDGET_JS_URL;
|
|
129
|
+
document.head.appendChild(preloadScript);
|
|
130
|
+
const preloadCss = document.createElement("link");
|
|
131
|
+
preloadCss.rel = "preload";
|
|
132
|
+
preloadCss.as = "style";
|
|
133
|
+
preloadCss.href = WIDGET_CSS_URL;
|
|
134
|
+
document.head.appendChild(preloadCss);
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
// ignore URL/preload errors
|
|
138
|
+
}
|
|
139
|
+
loadWidgetCss();
|
|
140
|
+
loadWidgetScript();
|
|
141
|
+
}
|
|
142
|
+
const agentConfigPromise = earlyAgentId && earlyBaseUrl
|
|
143
|
+
? fetchAgentConfig(earlyBaseUrl, earlyAgentId)
|
|
144
|
+
: Promise.resolve(undefined);
|
|
104
145
|
// Auto-initialize from URL parameters (no shadow DOM needed in iframe)
|
|
105
146
|
const initializeFromUrlParams = async () => {
|
|
106
147
|
var _a, _b, _c, _d, _e;
|
|
107
|
-
const urlParams = new URLSearchParams(window.location.search);
|
|
108
148
|
const agentId = urlParams.get("agentId");
|
|
109
149
|
if (!agentId) {
|
|
110
150
|
console.error("Agent ID is required in URL parameters");
|
|
@@ -127,31 +167,24 @@
|
|
|
127
167
|
: undefined;
|
|
128
168
|
const container = document.getElementById("root") || document.body;
|
|
129
169
|
try {
|
|
130
|
-
await Promise.all([
|
|
170
|
+
const [, , agentConfig] = await Promise.all([
|
|
171
|
+
loadWidgetCss(),
|
|
172
|
+
loadWidgetScript(),
|
|
173
|
+
agentConfigPromise,
|
|
174
|
+
]);
|
|
131
175
|
if (!(window === null || window === void 0 ? void 0 : window.renderMedAssist) ||
|
|
132
176
|
typeof (window === null || window === void 0 ? void 0 : window.renderMedAssist) !== "function") {
|
|
133
177
|
throw new Error("renderMedAssist is not available on window");
|
|
134
178
|
}
|
|
135
|
-
// Fetch agent-config when baseUrl is available; 10s timeout aborts pending request
|
|
136
179
|
let apiTheme;
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
const agentConfig = await fetchAgentConfig(baseUrl, agentId);
|
|
142
|
-
title = (_b = agentConfig === null || agentConfig === void 0 ? void 0 : agentConfig.name) !== null && _b !== void 0 ? _b : title;
|
|
143
|
-
iconUrl = (_d = (_c = agentConfig === null || agentConfig === void 0 ? void 0 : agentConfig.theme) === null || _c === void 0 ? void 0 : _c.icon_img) !== null && _d !== void 0 ? _d : iconUrl;
|
|
144
|
-
apiTheme = mapAgentConfigThemeToWidgetTheme((_e = agentConfig === null || agentConfig === void 0 ? void 0 : agentConfig.theme) !== null && _e !== void 0 ? _e : undefined);
|
|
145
|
-
allowed = agentConfig === null || agentConfig === void 0 ? void 0 : agentConfig.allowed;
|
|
146
|
-
}
|
|
147
|
-
catch {
|
|
148
|
-
// ignore; use URL params only
|
|
149
|
-
}
|
|
180
|
+
if (agentConfig) {
|
|
181
|
+
title = (_b = agentConfig === null || agentConfig === void 0 ? void 0 : agentConfig.name) !== null && _b !== void 0 ? _b : title;
|
|
182
|
+
iconUrl = (_d = (_c = agentConfig === null || agentConfig === void 0 ? void 0 : agentConfig.theme) === null || _c === void 0 ? void 0 : _c.icon_img) !== null && _d !== void 0 ? _d : iconUrl;
|
|
183
|
+
apiTheme = mapAgentConfigThemeToWidgetTheme((_e = agentConfig === null || agentConfig === void 0 ? void 0 : agentConfig.theme) !== null && _e !== void 0 ? _e : undefined);
|
|
150
184
|
}
|
|
151
185
|
const config = {
|
|
152
186
|
title,
|
|
153
187
|
iconUrl,
|
|
154
|
-
allowed,
|
|
155
188
|
environment,
|
|
156
189
|
onClose: () => {
|
|
157
190
|
if (window.parent !== window) {
|
package/dist/index.d.ts
CHANGED
|
@@ -34,6 +34,8 @@ type MedAssistInitConfig = {
|
|
|
34
34
|
};
|
|
35
35
|
/** Map agent-config API theme to widget theme (mode → textColor: dark→black, light→white) */
|
|
36
36
|
declare function mapAgentConfigThemeToWidgetTheme(apiTheme: AgentConfig["theme"] | undefined): MedAssistInitConfig["theme"];
|
|
37
|
+
/** Preload an image by URL so it is cached and loads faster when the widget uses it. */
|
|
38
|
+
declare function preloadImage(url: string): void;
|
|
37
39
|
/** Fetch agent-config from API and return theme from response data */
|
|
38
40
|
declare function fetchAgentConfig(baseUrl: string, agentId: string): Promise<AgentConfig | undefined>;
|
|
39
41
|
interface EkaMedAssistWindow extends Window {
|
|
@@ -51,6 +53,8 @@ declare const WIDGET_JS_URL: string;
|
|
|
51
53
|
declare const WIDGET_CSS_URL: string;
|
|
52
54
|
declare let widgetScriptPromise: Promise<void> | null;
|
|
53
55
|
declare let widgetCssTextPromise: Promise<string> | null;
|
|
56
|
+
/** Start fetching widget CSS (shared promise). Used for preload and by loadWidgetCss. */
|
|
57
|
+
declare function getWidgetCssTextPromise(): Promise<string>;
|
|
54
58
|
declare class MedAssistWidgetLoader extends HTMLElement {
|
|
55
59
|
private defaultIconUrl;
|
|
56
60
|
private widgetLoaded;
|
|
@@ -59,6 +63,10 @@ declare class MedAssistWidgetLoader extends HTMLElement {
|
|
|
59
63
|
static get observedAttributes(): string[];
|
|
60
64
|
connectedCallback(): void;
|
|
61
65
|
attributeChangedCallback(name: string): void;
|
|
66
|
+
/** When in widget mode, start loading JS and CSS on page load so first open is faster. */
|
|
67
|
+
private preloadWidgetAssets;
|
|
68
|
+
/** Preload theme background image from init config, theme attribute, or agent-config API. */
|
|
69
|
+
private preloadBackgroundImage;
|
|
62
70
|
private setupAuthExpirationListener;
|
|
63
71
|
openFromBridge(): void;
|
|
64
72
|
renderButton(): void;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,gBAAgB,QAAO,iBAAiB,GAAG,IAahD,CAAC;AAEF,KAAK,iBAAiB,GAAG,YAAY,GAAG,aAAa,GAAG,SAAS,CAAC;AAElE,QAAA,MAAM,cAAc,GAClB,OAAO,MAAM,GAAG,IAAI,KACnB,iBAAiB,GAAG,SAStB,CAAC;AAEF,QAAA,MAAM,QAAQ,0BAAqB,CAAC;AAGpC,QAAA,MAAM,yBAAyB,QAK3B,CAAC;AAEL,6FAA6F;AAC7F,KAAK,WAAW,GAAG;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC;IACxC,KAAK,CAAC,EAAE;QACN,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;QACxB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;KAClB,CAAA;CACF,CAAC;AAEF,KAAK,mBAAmB,GAAG;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC;IACxC,KAAK,CAAC,EAAE;QACN,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,SAAS,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;KAC/B,CAAC;IACF,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAEF,6FAA6F;AAC7F,iBAAS,gCAAgC,CAAC,QAAQ,EAAE,WAAW,CAAC,OAAO,CAAC,GAAG,SAAS,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAUlH;AAED,sEAAsE;AACtE,iBAAe,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAYlG;AAED,UAAU,kBAAmB,SAAQ,MAAM;IACzC,YAAY,CAAC,EAAE;QACb,IAAI,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,IAAI,CAAC;QAC5C,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;KACtB,CAAC;IACF,sBAAsB,CAAC,EAAE,mBAAmB,CAAC;CAC9C;AAED,QAAA,MAAM,qBAAqB,EAAE,mBAAwB,CAAC;AAEtD,QAAA,MAAM,gBAAgB,QAAO,WAAW,GAAG,IAK1C,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -41,6 +41,23 @@ function mapAgentConfigThemeToWidgetTheme(apiTheme) {
|
|
|
41
41
|
...(apiTheme.title_img && { titleImg: apiTheme.title_img }),
|
|
42
42
|
};
|
|
43
43
|
}
|
|
44
|
+
/** Preload an image by URL so it is cached and loads faster when the widget uses it. */
|
|
45
|
+
function preloadImage(url) {
|
|
46
|
+
if (!url || typeof document === "undefined")
|
|
47
|
+
return;
|
|
48
|
+
try {
|
|
49
|
+
const link = document.createElement("link");
|
|
50
|
+
link.rel = "preload";
|
|
51
|
+
link.as = "image";
|
|
52
|
+
link.href = url;
|
|
53
|
+
document.head.appendChild(link);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// fallback: use Image to prime cache
|
|
57
|
+
const img = new Image();
|
|
58
|
+
img.src = url;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
44
61
|
/** Fetch agent-config from API and return theme from response data */
|
|
45
62
|
async function fetchAgentConfig(baseUrl, agentId) {
|
|
46
63
|
const url = `${baseUrl.replace(/\/$/, "")}/med-assist/agent-config/${agentId}`;
|
|
@@ -68,7 +85,7 @@ if (typeof window !== "undefined") {
|
|
|
68
85
|
w.__ekaMedAssistConfig__ = globalMedAssistConfig;
|
|
69
86
|
w.EkaMedAssist = {
|
|
70
87
|
init(config) {
|
|
71
|
-
var _a, _b;
|
|
88
|
+
var _a, _b, _c;
|
|
72
89
|
Object.assign(globalMedAssistConfig, config);
|
|
73
90
|
const el = getWidgetElement();
|
|
74
91
|
if (!el)
|
|
@@ -89,7 +106,10 @@ if (typeof window !== "undefined") {
|
|
|
89
106
|
console.warn("Failed to stringify context passed to init");
|
|
90
107
|
}
|
|
91
108
|
}
|
|
92
|
-
|
|
109
|
+
if ((_a = config.theme) === null || _a === void 0 ? void 0 : _a.backgroundImage) {
|
|
110
|
+
preloadImage(config.theme.backgroundImage);
|
|
111
|
+
}
|
|
112
|
+
(_c = (_b = el).openFromBridge) === null || _c === void 0 ? void 0 : _c.call(_b);
|
|
93
113
|
},
|
|
94
114
|
};
|
|
95
115
|
}
|
|
@@ -126,6 +146,18 @@ const WIDGET_JS_URL = `${widgetAssetBaseUrl}medassist-widget.js`;
|
|
|
126
146
|
const WIDGET_CSS_URL = `${widgetAssetBaseUrl}medassist-widget.css`;
|
|
127
147
|
let widgetScriptPromise = null;
|
|
128
148
|
let widgetCssTextPromise = null;
|
|
149
|
+
/** Start fetching widget CSS (shared promise). Used for preload and by loadWidgetCss. */
|
|
150
|
+
function getWidgetCssTextPromise() {
|
|
151
|
+
if (!widgetCssTextPromise) {
|
|
152
|
+
widgetCssTextPromise = fetch(WIDGET_CSS_URL).then((response) => {
|
|
153
|
+
if (!response.ok) {
|
|
154
|
+
throw new Error(`Unable to fetch widget styles from ${WIDGET_CSS_URL}`);
|
|
155
|
+
}
|
|
156
|
+
return response.text();
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
return widgetCssTextPromise;
|
|
160
|
+
}
|
|
129
161
|
class MedAssistWidgetLoader extends HTMLElement {
|
|
130
162
|
constructor() {
|
|
131
163
|
super();
|
|
@@ -145,6 +177,7 @@ class MedAssistWidgetLoader extends HTMLElement {
|
|
|
145
177
|
}
|
|
146
178
|
else {
|
|
147
179
|
this.renderButton();
|
|
180
|
+
this.preloadWidgetAssets();
|
|
148
181
|
}
|
|
149
182
|
}
|
|
150
183
|
attributeChangedCallback(name) {
|
|
@@ -166,6 +199,49 @@ class MedAssistWidgetLoader extends HTMLElement {
|
|
|
166
199
|
}
|
|
167
200
|
}
|
|
168
201
|
}
|
|
202
|
+
/** When in widget mode, start loading JS and CSS on page load so first open is faster. */
|
|
203
|
+
preloadWidgetAssets() {
|
|
204
|
+
getWidgetCssTextPromise(); // start CSS fetch (no inject until open)
|
|
205
|
+
void this.loadWidgetScript(); // start JS load
|
|
206
|
+
void this.preloadBackgroundImage();
|
|
207
|
+
}
|
|
208
|
+
/** Preload theme background image from init config, theme attribute, or agent-config API. */
|
|
209
|
+
preloadBackgroundImage() {
|
|
210
|
+
var _a;
|
|
211
|
+
const initConfig = typeof window !== "undefined"
|
|
212
|
+
? window.__ekaMedAssistConfig__
|
|
213
|
+
: undefined;
|
|
214
|
+
const attributeTheme = this.getAttribute("theme")
|
|
215
|
+
? (() => {
|
|
216
|
+
try {
|
|
217
|
+
return JSON.parse(this.getAttribute("theme") || "{}");
|
|
218
|
+
}
|
|
219
|
+
catch {
|
|
220
|
+
return undefined;
|
|
221
|
+
}
|
|
222
|
+
})()
|
|
223
|
+
: undefined;
|
|
224
|
+
const fromInit = (_a = initConfig === null || initConfig === void 0 ? void 0 : initConfig.theme) === null || _a === void 0 ? void 0 : _a.backgroundImage;
|
|
225
|
+
const fromAttr = attributeTheme === null || attributeTheme === void 0 ? void 0 : attributeTheme.backgroundImage;
|
|
226
|
+
if (fromInit)
|
|
227
|
+
preloadImage(fromInit);
|
|
228
|
+
if (fromAttr && fromAttr !== fromInit)
|
|
229
|
+
preloadImage(fromAttr);
|
|
230
|
+
const baseUrl = (initConfig === null || initConfig === void 0 ? void 0 : initConfig.baseUrl) || this.getAttribute("base-url") || "";
|
|
231
|
+
const agentId = (initConfig === null || initConfig === void 0 ? void 0 : initConfig.agentId) || this.getAttribute("agent-id") || "";
|
|
232
|
+
if (baseUrl && agentId) {
|
|
233
|
+
fetchAgentConfig(baseUrl, agentId)
|
|
234
|
+
.then((agentConfig) => {
|
|
235
|
+
var _a;
|
|
236
|
+
const url = (_a = agentConfig === null || agentConfig === void 0 ? void 0 : agentConfig.theme) === null || _a === void 0 ? void 0 : _a.background_img;
|
|
237
|
+
if (url)
|
|
238
|
+
preloadImage(url);
|
|
239
|
+
})
|
|
240
|
+
.catch(() => {
|
|
241
|
+
// ignore; widget will load config when it opens
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
}
|
|
169
245
|
setupAuthExpirationListener() {
|
|
170
246
|
if (typeof window === "undefined")
|
|
171
247
|
return;
|
|
@@ -391,15 +467,7 @@ class MedAssistWidgetLoader extends HTMLElement {
|
|
|
391
467
|
if (shadowRoot.querySelector("[data-medassist-style='true']")) {
|
|
392
468
|
return;
|
|
393
469
|
}
|
|
394
|
-
|
|
395
|
-
widgetCssTextPromise = fetch(WIDGET_CSS_URL).then((response) => {
|
|
396
|
-
if (!response.ok) {
|
|
397
|
-
throw new Error(`Unable to fetch widget styles from ${WIDGET_CSS_URL}`);
|
|
398
|
-
}
|
|
399
|
-
return response.text();
|
|
400
|
-
});
|
|
401
|
-
}
|
|
402
|
-
const cssText = await widgetCssTextPromise;
|
|
470
|
+
const cssText = await getWidgetCssTextPromise();
|
|
403
471
|
const styleTag = document.createElement("style");
|
|
404
472
|
styleTag.setAttribute("data-medassist-style", "true");
|
|
405
473
|
styleTag.textContent = cssText;
|
|
@@ -2727,6 +2727,12 @@ body {
|
|
|
2727
2727
|
opacity: 0.6;
|
|
2728
2728
|
}
|
|
2729
2729
|
|
|
2730
|
+
.disabled\:hover\:scale-100:hover:disabled {
|
|
2731
|
+
--tw-scale-x: 1;
|
|
2732
|
+
--tw-scale-y: 1;
|
|
2733
|
+
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
|
2734
|
+
}
|
|
2735
|
+
|
|
2730
2736
|
.group:hover .group-hover\:bg-purple-200\/70 {
|
|
2731
2737
|
background-color: rgb(233 213 255 / 0.7);
|
|
2732
2738
|
}
|
|
@@ -32017,8 +32017,10 @@ var MedAssistWidget = (function(exports) {
|
|
|
32017
32017
|
}) {
|
|
32018
32018
|
const fileInputRef = reactExports.useRef(null);
|
|
32019
32019
|
const textareaRef = reactExports.useRef(null);
|
|
32020
|
-
const
|
|
32020
|
+
const hasContent = value.trim().length > 0 || hasAttachment;
|
|
32021
32021
|
const showMic = allowed === void 0 || allowed.includes("audio");
|
|
32022
|
+
const showSendButton = hasContent || !showMic;
|
|
32023
|
+
const canSend = hasContent;
|
|
32022
32024
|
const showFileAttachment = allowed === void 0 || allowed.includes("file");
|
|
32023
32025
|
const isMicDisabled = (isDisabled || recordingStatus !== AudioRecordingStatus.IDLE) && !isRecording;
|
|
32024
32026
|
const micButtonClasses = cn(
|
|
@@ -32038,7 +32040,7 @@ var MedAssistWidget = (function(exports) {
|
|
|
32038
32040
|
fileInputRef.current?.click();
|
|
32039
32041
|
};
|
|
32040
32042
|
const handleKeyPress = (e) => {
|
|
32041
|
-
if (e.key === "Enter" && !e.shiftKey &&
|
|
32043
|
+
if (e.key === "Enter" && !e.shiftKey && canSend && !isDisabled) {
|
|
32042
32044
|
e.preventDefault();
|
|
32043
32045
|
onSend();
|
|
32044
32046
|
}
|
|
@@ -32178,15 +32180,16 @@ var MedAssistWidget = (function(exports) {
|
|
|
32178
32180
|
children: /* @__PURE__ */ jsxRuntimeExports.jsx(Mic, { className: "w-5 h-5" })
|
|
32179
32181
|
}
|
|
32180
32182
|
),
|
|
32181
|
-
showSendButton &&
|
|
32183
|
+
showSendButton && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
32182
32184
|
Button,
|
|
32183
32185
|
{
|
|
32184
32186
|
type: "button",
|
|
32185
32187
|
size: "icon",
|
|
32186
32188
|
onClick: onSend,
|
|
32187
|
-
|
|
32188
|
-
|
|
32189
|
-
"
|
|
32189
|
+
disabled: isDisabled || !canSend,
|
|
32190
|
+
className: `absolute right-0.5 top-1/2 -translate-y-1/2 h-10 w-10 ${!showMic ? "" : "bg-primary"} hover:bg-primary/90 rounded-full text-primary-foreground transition-all duration-200 shadow-lg hover:shadow-xl hover:scale-105 active:scale-95 shrink-0 disabled:opacity-50 disabled:pointer-events-none disabled:hover:scale-100`,
|
|
32191
|
+
title: canSend ? "Send message" : "Type a message to send",
|
|
32192
|
+
"aria-label": canSend ? "Send message" : "Type a message to send",
|
|
32190
32193
|
children: /* @__PURE__ */ jsxRuntimeExports.jsx(SendIcon, { className: "w-4 h-4 text-primary-foreground" })
|
|
32191
32194
|
}
|
|
32192
32195
|
)
|