@ringg/core 0.0.1-alpha.10

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/index.cjs ADDED
@@ -0,0 +1,757 @@
1
+ 'use strict';
2
+
3
+ // src/types/config.ts
4
+ var DEFAULT_CONFIG = {
5
+ mode: "prod",
6
+ title: "Ringg AI Support",
7
+ description: "Ringg AI offers 24/7 voice support to handle your business calls efficiently and professionally",
8
+ defaultTab: "audio",
9
+ hideTabSelector: false,
10
+ notificationTuneUrl: "https://assets.ringg.ai/audios/misc/widget_notification.mp3"
11
+ };
12
+
13
+ // src/adapters/event-bus.ts
14
+ var DomEventBus = class {
15
+ constructor() {
16
+ this.listeners = /* @__PURE__ */ new Map();
17
+ }
18
+ emit(event, payload) {
19
+ if (typeof window !== "undefined") {
20
+ window.dispatchEvent(new CustomEvent(event, { detail: payload }));
21
+ }
22
+ }
23
+ on(event, handler) {
24
+ if (typeof window === "undefined") return () => {
25
+ };
26
+ const wrappedHandler = ((e) => handler(e.detail));
27
+ if (!this.listeners.has(event)) {
28
+ this.listeners.set(event, /* @__PURE__ */ new Set());
29
+ }
30
+ this.listeners.get(event).add(wrappedHandler);
31
+ window.addEventListener(event, wrappedHandler);
32
+ return () => {
33
+ window.removeEventListener(event, wrappedHandler);
34
+ this.listeners.get(event)?.delete(wrappedHandler);
35
+ };
36
+ }
37
+ off(event) {
38
+ if (event) {
39
+ this.listeners.get(event)?.forEach((handler) => {
40
+ window.removeEventListener(event, handler);
41
+ });
42
+ this.listeners.delete(event);
43
+ } else {
44
+ this.listeners.forEach((handlers, eventName) => {
45
+ handlers.forEach((handler) => {
46
+ window.removeEventListener(eventName, handler);
47
+ });
48
+ });
49
+ this.listeners.clear();
50
+ }
51
+ }
52
+ };
53
+ var CallbackEventBus = class {
54
+ constructor() {
55
+ this.listeners = /* @__PURE__ */ new Map();
56
+ }
57
+ emit(event, payload) {
58
+ const handlers = this.listeners.get(event);
59
+ if (handlers) {
60
+ handlers.forEach((handler) => handler(payload));
61
+ }
62
+ }
63
+ on(event, handler) {
64
+ if (!this.listeners.has(event)) {
65
+ this.listeners.set(event, /* @__PURE__ */ new Set());
66
+ }
67
+ const typedHandler = handler;
68
+ this.listeners.get(event).add(typedHandler);
69
+ return () => {
70
+ this.listeners.get(event)?.delete(typedHandler);
71
+ };
72
+ }
73
+ off(event) {
74
+ if (event) {
75
+ this.listeners.delete(event);
76
+ } else {
77
+ this.listeners.clear();
78
+ }
79
+ }
80
+ };
81
+
82
+ // src/api/client.ts
83
+ var StaticUrlResolver = class {
84
+ constructor(urls) {
85
+ this.urls = urls;
86
+ }
87
+ resolve(mode) {
88
+ return this.urls[mode];
89
+ }
90
+ };
91
+ var RinggApiClient = class {
92
+ constructor(config) {
93
+ const { backendUrl } = config.urlResolver.resolve(config.mode);
94
+ this.backendUrl = backendUrl;
95
+ this.xApiKey = config.xApiKey;
96
+ }
97
+ /** Common headers for all API requests. Includes Origin for CORS. */
98
+ get headers() {
99
+ return {
100
+ "Content-Type": "application/json",
101
+ "X-API-KEY": this.xApiKey,
102
+ Origin: "http://localhost:3000"
103
+ };
104
+ }
105
+ /**
106
+ * Initiate a webcall — returns the LiveKit token and call ID.
107
+ */
108
+ async startWebcall(params) {
109
+ const response = await fetch(`${this.backendUrl}/calling/webcall`, {
110
+ method: "POST",
111
+ body: JSON.stringify({
112
+ agent_id: params.agentId,
113
+ custom_args_values: params.variables,
114
+ media_type: params.mediaType
115
+ }),
116
+ headers: this.headers
117
+ });
118
+ const responseText = await response.text();
119
+ let data;
120
+ try {
121
+ data = JSON.parse(responseText);
122
+ } catch {
123
+ throw new Error(responseText.slice(0, 200) || `Request failed with status ${response.status}`);
124
+ }
125
+ if (!response.ok) {
126
+ throw new Error(data?.message || "Failed to make call");
127
+ }
128
+ return {
129
+ call_id: data.call_id,
130
+ user_token: data.user_token,
131
+ enabled_slash_commands: data.enabled_slash_commands
132
+ };
133
+ }
134
+ /**
135
+ * Submit post-call feedback.
136
+ */
137
+ async submitFeedback(callId, feedback) {
138
+ await fetch(`${this.backendUrl}/calling/${callId}/feedback`, {
139
+ method: "POST",
140
+ body: JSON.stringify(feedback),
141
+ headers: this.headers
142
+ });
143
+ }
144
+ /**
145
+ * Call a component API endpoint (for interactive flows).
146
+ */
147
+ async callComponentApi(method, endpoint, payload) {
148
+ const url = endpoint.startsWith("http") ? endpoint : `${this.backendUrl}${endpoint}`;
149
+ const response = await fetch(url, {
150
+ method,
151
+ body: JSON.stringify(payload),
152
+ headers: this.headers
153
+ });
154
+ return response.json();
155
+ }
156
+ };
157
+
158
+ // src/state/widget-state.ts
159
+ var WidgetStateController = class {
160
+ constructor(eventBus, initialCallMode = "audio") {
161
+ this.eventBus = eventBus;
162
+ this.viewState = "closed";
163
+ this.currentCallId = null;
164
+ this.listeners = /* @__PURE__ */ new Set();
165
+ this.conversationEndDispatched = false;
166
+ this.callMode = initialCallMode;
167
+ }
168
+ // ─── Getters ─────────────────────────────────────────────────────────────
169
+ getSnapshot() {
170
+ return {
171
+ viewState: this.viewState,
172
+ currentCallId: this.currentCallId,
173
+ callMode: this.callMode
174
+ };
175
+ }
176
+ get isOpen() {
177
+ return this.viewState === "open" || this.viewState === "feedback";
178
+ }
179
+ get isShowingFeedback() {
180
+ return this.viewState === "feedback";
181
+ }
182
+ // ─── Mutations ───────────────────────────────────────────────────────────
183
+ open() {
184
+ if (this.viewState === "open") return;
185
+ this.viewState = "open";
186
+ this.eventBus.emit("ringg:widget_status", { status: "maximised", mode: this.callMode });
187
+ this.notify();
188
+ }
189
+ minimize() {
190
+ if (this.viewState === "closed") return;
191
+ this.viewState = "closed";
192
+ this.eventBus.emit("ringg:widget_status", { status: "minimised", mode: this.callMode });
193
+ this.notify();
194
+ }
195
+ close() {
196
+ this.viewState = "closed";
197
+ this.currentCallId = null;
198
+ this.eventBus.emit("ringg:widget_status", { status: "minimised", mode: this.callMode });
199
+ this.notify();
200
+ }
201
+ toggle() {
202
+ if (this.isOpen) {
203
+ this.minimize();
204
+ } else {
205
+ this.open();
206
+ }
207
+ }
208
+ showFeedback() {
209
+ this.viewState = "feedback";
210
+ this.notify();
211
+ }
212
+ setCallMode(mode) {
213
+ this.callMode = mode;
214
+ this.notify();
215
+ }
216
+ setCurrentCallId(callId) {
217
+ this.currentCallId = callId;
218
+ this.notify();
219
+ }
220
+ // ─── Conversation lifecycle helpers ──────────────────────────────────────
221
+ dispatchConversationStart(mode, callId) {
222
+ this.conversationEndDispatched = false;
223
+ this.eventBus.emit("ringg:conversation_status", { status: "started", mode, callId });
224
+ }
225
+ dispatchConversationEnd(mode, callId) {
226
+ if (!this.conversationEndDispatched) {
227
+ this.conversationEndDispatched = true;
228
+ this.eventBus.emit("ringg:conversation_status", { status: "ended", mode, callId });
229
+ }
230
+ }
231
+ // ─── Subscription ────────────────────────────────────────────────────────
232
+ subscribe(listener) {
233
+ this.listeners.add(listener);
234
+ return () => {
235
+ this.listeners.delete(listener);
236
+ };
237
+ }
238
+ notify() {
239
+ const snapshot = this.getSnapshot();
240
+ this.listeners.forEach((listener) => listener(snapshot));
241
+ }
242
+ // ─── Cleanup ─────────────────────────────────────────────────────────────
243
+ dispose() {
244
+ this.listeners.clear();
245
+ }
246
+ };
247
+
248
+ // src/theme/gradient-utils.ts
249
+ var GRADIENT_REGEX = /^(linear-gradient|radial-gradient|conic-gradient|repeating-linear-gradient|repeating-radial-gradient|repeating-conic-gradient)\s*\(/i;
250
+ var HEX_COLOR_REGEX = /#([0-9a-fA-F]{3,8})\b/g;
251
+ var RGB_COLOR_REGEX = /rgba?\(\s*[\d.]+[\s,]+[\d.]+[\s,]+[\d.]+(?:[\s,/]+[\d.%]+)?\s*\)/g;
252
+ function isGradient(color) {
253
+ return GRADIENT_REGEX.test(color.trim());
254
+ }
255
+ function extractColorsFromGradient(gradient) {
256
+ const colors = [];
257
+ const hexMatches = gradient.match(HEX_COLOR_REGEX);
258
+ if (hexMatches) colors.push(...hexMatches);
259
+ const rgbMatches = gradient.match(RGB_COLOR_REGEX);
260
+ if (rgbMatches) colors.push(...rgbMatches);
261
+ return colors;
262
+ }
263
+ function getDominantColor(color) {
264
+ if (!isGradient(color)) return color;
265
+ const colors = extractColorsFromGradient(color);
266
+ return colors.length > 0 ? colors[0] : color;
267
+ }
268
+ function colorToBackground(color) {
269
+ if (isGradient(color)) {
270
+ return { background: color };
271
+ }
272
+ return { backgroundColor: color };
273
+ }
274
+ function colorToSolid(color) {
275
+ return getDominantColor(color);
276
+ }
277
+ function colorToBorder(color) {
278
+ if (isGradient(color)) {
279
+ return {
280
+ borderImage: `${color} 1`,
281
+ borderStyle: "solid"
282
+ };
283
+ }
284
+ return { borderColor: color };
285
+ }
286
+
287
+ // src/theme/theme-engine.ts
288
+ var DEFAULT_WIDGET_THEME = {
289
+ primaryColor: "#313335",
290
+ primaryTextColor: "#ffffff",
291
+ backgroundColor: "#fafafa",
292
+ surfaceColor: "#F3F3F5",
293
+ textColor: "#212121",
294
+ mutedTextColor: "#11111180",
295
+ borderColor: "#e5e5e5",
296
+ errorColor: "#ef4444",
297
+ successColor: "#10b981",
298
+ buttonStyle: "rounded",
299
+ borderRadius: "20px",
300
+ fontFamily: "inherit"
301
+ };
302
+ function mergeWidgetTheme(theme) {
303
+ return { ...DEFAULT_WIDGET_THEME, ...theme };
304
+ }
305
+ function mergeComponentTheme(componentTheme, widgetTheme) {
306
+ const base = widgetTheme ?? DEFAULT_WIDGET_THEME;
307
+ return {
308
+ primaryColor: base.primaryColor,
309
+ primaryTextColor: base.primaryTextColor,
310
+ backgroundColor: base.backgroundColor,
311
+ surfaceColor: base.surfaceColor,
312
+ textColor: base.textColor,
313
+ mutedTextColor: base.mutedTextColor,
314
+ borderColor: base.borderColor,
315
+ errorColor: base.errorColor,
316
+ successColor: base.successColor,
317
+ fontFamily: base.fontFamily,
318
+ borderRadius: base.borderRadius,
319
+ buttonStyle: base.buttonStyle,
320
+ ...componentTheme
321
+ };
322
+ }
323
+ function getButtonRadius(style) {
324
+ switch (style) {
325
+ case "pill":
326
+ return "9999px";
327
+ case "square":
328
+ return "6px";
329
+ case "rounded":
330
+ default:
331
+ return "12px";
332
+ }
333
+ }
334
+ function getLuminance(hexColor) {
335
+ const solid = getDominantColor(hexColor);
336
+ const hex = solid.replace("#", "");
337
+ const r = parseInt(hex.substr(0, 2), 16) / 255;
338
+ const g = parseInt(hex.substr(2, 2), 16) / 255;
339
+ const b = parseInt(hex.substr(4, 2), 16) / 255;
340
+ const toLinear = (c) => c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
341
+ return 0.2126 * toLinear(r) + 0.7152 * toLinear(g) + 0.0722 * toLinear(b);
342
+ }
343
+ function isLightColor(hexColor) {
344
+ try {
345
+ return getLuminance(hexColor) > 0.5;
346
+ } catch {
347
+ return true;
348
+ }
349
+ }
350
+ function getContrastingTextColor(bgColor) {
351
+ return isLightColor(bgColor) ? "#212121" : "#ffffff";
352
+ }
353
+ var WIDGET_PRESET_THEMES = {
354
+ light: {
355
+ primaryColor: "#18181b",
356
+ primaryTextColor: "#ffffff",
357
+ backgroundColor: "#ffffff",
358
+ surfaceColor: "#f4f4f5",
359
+ textColor: "#18181b",
360
+ mutedTextColor: "#71717a",
361
+ borderColor: "#e4e4e7"
362
+ },
363
+ warm: {
364
+ primaryColor: "#57534e",
365
+ primaryTextColor: "#ffffff",
366
+ backgroundColor: "#fefefe",
367
+ surfaceColor: "#fafaf9",
368
+ textColor: "#1c1917",
369
+ mutedTextColor: "#78716c",
370
+ borderColor: "#e7e5e4"
371
+ },
372
+ blue: {
373
+ primaryColor: "#2563eb",
374
+ primaryTextColor: "#ffffff",
375
+ backgroundColor: "#fafcff",
376
+ surfaceColor: "#f0f7ff",
377
+ textColor: "#1e3a8a",
378
+ mutedTextColor: "#64748b",
379
+ borderColor: "#dbeafe"
380
+ },
381
+ indigo: {
382
+ primaryColor: "#6366f1",
383
+ primaryTextColor: "#ffffff",
384
+ backgroundColor: "#fbfbff",
385
+ surfaceColor: "#f5f5ff",
386
+ textColor: "#312e81",
387
+ mutedTextColor: "#6b7280",
388
+ borderColor: "#e0e7ff"
389
+ },
390
+ green: {
391
+ primaryColor: "#16a34a",
392
+ primaryTextColor: "#ffffff",
393
+ backgroundColor: "#fbfefb",
394
+ surfaceColor: "#f0fdf4",
395
+ textColor: "#14532d",
396
+ mutedTextColor: "#6b7280",
397
+ borderColor: "#dcfce7"
398
+ },
399
+ orange: {
400
+ primaryColor: "#ea580c",
401
+ primaryTextColor: "#ffffff",
402
+ backgroundColor: "#fffdfb",
403
+ surfaceColor: "#fff7ed",
404
+ textColor: "#7c2d12",
405
+ mutedTextColor: "#78716c",
406
+ borderColor: "#ffedd5"
407
+ },
408
+ dark: {
409
+ primaryColor: "#fafafa",
410
+ primaryTextColor: "#18181b",
411
+ backgroundColor: "#18181b",
412
+ surfaceColor: "#27272a",
413
+ textColor: "#fafafa",
414
+ mutedTextColor: "#a1a1aa",
415
+ borderColor: "#3f3f46"
416
+ },
417
+ sunset: {
418
+ primaryColor: "linear-gradient(135deg, #f97316, #ef4444)",
419
+ primaryTextColor: "#ffffff",
420
+ backgroundColor: "#fffbf7",
421
+ surfaceColor: "#fff3e8",
422
+ textColor: "#7c2d12",
423
+ mutedTextColor: "#9a3412",
424
+ borderColor: "#fed7aa"
425
+ },
426
+ ocean: {
427
+ primaryColor: "linear-gradient(135deg, #667eea, #764ba2)",
428
+ primaryTextColor: "#ffffff",
429
+ backgroundColor: "#faf9ff",
430
+ surfaceColor: "#f0edff",
431
+ textColor: "#312e81",
432
+ mutedTextColor: "#6366f1",
433
+ borderColor: "#ddd6fe"
434
+ },
435
+ emerald: {
436
+ primaryColor: "linear-gradient(135deg, #10b981, #0ea5e9)",
437
+ primaryTextColor: "#ffffff",
438
+ backgroundColor: "#f7fdfb",
439
+ surfaceColor: "#ecfdf5",
440
+ textColor: "#064e3b",
441
+ mutedTextColor: "#047857",
442
+ borderColor: "#a7f3d0"
443
+ },
444
+ midnight: {
445
+ primaryColor: "linear-gradient(135deg, #6366f1, #8b5cf6)",
446
+ primaryTextColor: "#ffffff",
447
+ backgroundColor: "#18181b",
448
+ surfaceColor: "#27272a",
449
+ textColor: "#fafafa",
450
+ mutedTextColor: "#a1a1aa",
451
+ borderColor: "#3f3f46"
452
+ }
453
+ };
454
+
455
+ // src/helpers/component-helpers.ts
456
+ function groupSlotsByDate(slots) {
457
+ const grouped = /* @__PURE__ */ new Map();
458
+ slots.forEach((slot) => {
459
+ const date = new Date(slot.datetime);
460
+ const dateKey = date.toISOString().split("T")[0];
461
+ if (!grouped.has(dateKey)) {
462
+ grouped.set(dateKey, []);
463
+ }
464
+ grouped.get(dateKey).push(slot);
465
+ });
466
+ return Array.from(grouped.entries()).sort(([a], [b]) => a.localeCompare(b)).map(([dateKey, dateSlots]) => {
467
+ const date = new Date(dateKey);
468
+ return {
469
+ date: dateKey,
470
+ dateLabel: date.toLocaleDateString("en-US", {
471
+ weekday: "short",
472
+ month: "short",
473
+ day: "numeric"
474
+ }),
475
+ slots: dateSlots.sort((a, b) => new Date(a.datetime).getTime() - new Date(b.datetime).getTime())
476
+ };
477
+ });
478
+ }
479
+ function formatSlotTime(datetime, timezone) {
480
+ const date = new Date(datetime);
481
+ return date.toLocaleTimeString("en-US", {
482
+ hour: "numeric",
483
+ minute: "2-digit",
484
+ hour12: true,
485
+ timeZone: timezone
486
+ });
487
+ }
488
+ function formatSlotDate(datetime, timezone) {
489
+ const date = new Date(datetime);
490
+ return date.toLocaleDateString("en-US", {
491
+ weekday: "short",
492
+ month: "short",
493
+ day: "numeric",
494
+ timeZone: timezone
495
+ });
496
+ }
497
+ function buildPayload(template, values) {
498
+ const result = {};
499
+ for (const [key, value] of Object.entries(template)) {
500
+ if (typeof value === "string" && value.startsWith("{") && value.endsWith("}")) {
501
+ const placeholder = value.slice(1, -1);
502
+ result[key] = values[placeholder] ?? value;
503
+ } else {
504
+ result[key] = value;
505
+ }
506
+ }
507
+ return result;
508
+ }
509
+ function isCalendarBooking(payload) {
510
+ return payload.component_type === "calendar_booking";
511
+ }
512
+ function isForm(payload) {
513
+ return payload.component_type === "form";
514
+ }
515
+ function isButtons(payload) {
516
+ return payload.component_type === "buttons";
517
+ }
518
+ function isConfirmation(payload) {
519
+ return payload.component_type === "confirmation";
520
+ }
521
+ function isInteractiveFlow(payload) {
522
+ return payload.component_type === "interactive_flow";
523
+ }
524
+ function filterSlashCommands(commands, query) {
525
+ if (!query.startsWith("/")) return [];
526
+ const search = query.slice(1).toLowerCase();
527
+ if (!search) return commands;
528
+ return commands.filter((cmd) => cmd.command.slice(1).toLowerCase().includes(search) || cmd.display_name.toLowerCase().includes(search));
529
+ }
530
+ function hasSubQuestions(disease) {
531
+ return disease.sub_questions.length > 0;
532
+ }
533
+ function getDiseasesWithSubQuestions(selected) {
534
+ return selected.filter(hasSubQuestions);
535
+ }
536
+ function formatTimestamp(dateString, mode = "fromnow") {
537
+ const date = new Date(dateString);
538
+ const now = /* @__PURE__ */ new Date();
539
+ if (mode === "fromnow") {
540
+ const diffSeconds = Math.floor((now.getTime() - date.getTime()) / 1e3);
541
+ if (diffSeconds < 60) return "Just now";
542
+ if (diffSeconds < 3600) {
543
+ const minutes = Math.floor(diffSeconds / 60);
544
+ return `${minutes} min ago`;
545
+ }
546
+ if (diffSeconds < 86400) {
547
+ const hours = Math.floor(diffSeconds / 3600);
548
+ return `${hours} hour${hours !== 1 ? "s" : ""} ago`;
549
+ }
550
+ const days = Math.floor(diffSeconds / 86400);
551
+ return `${days} day${days !== 1 ? "s" : ""} ago`;
552
+ }
553
+ return date.toLocaleTimeString([], {
554
+ hour: "2-digit",
555
+ minute: "2-digit",
556
+ hour12: true
557
+ });
558
+ }
559
+ function isAgentIdentity(identity) {
560
+ return identity.includes("agent") || identity.includes("Agent");
561
+ }
562
+
563
+ // src/rpc/rpc-formatter.ts
564
+ function transformRpcToComponent(componentName, rpcPayload) {
565
+ const componentId = `${componentName}_${Date.now()}`;
566
+ const config = rpcPayload.component_config;
567
+ if (componentName === "calendar") {
568
+ return transformCalendar(componentId, config, rpcPayload);
569
+ }
570
+ if (componentName === "form") {
571
+ return transformForm(componentId, config);
572
+ }
573
+ if (componentName === "buttons") {
574
+ return transformButtons(componentId, config, rpcPayload);
575
+ }
576
+ if (componentName === "confirmation") {
577
+ return transformConfirmation(componentId, rpcPayload);
578
+ }
579
+ if (rpcPayload.component_type && rpcPayload.component_id) {
580
+ return rpcPayload;
581
+ }
582
+ return null;
583
+ }
584
+ function transformCalendar(componentId, config, rpcPayload) {
585
+ const configObj = config;
586
+ const slots = configObj?.slots || [];
587
+ const timezone = configObj?.timezone || "UTC";
588
+ return {
589
+ component_type: "calendar_booking",
590
+ component_id: componentId,
591
+ data: {
592
+ available_slots: slots.map((slot) => ({ id: slot.id, datetime: slot.datetime })),
593
+ timezone,
594
+ title: rpcPayload.title || "Select a time slot"
595
+ }
596
+ };
597
+ }
598
+ function transformForm(componentId, config) {
599
+ const configObj = config;
600
+ const transformedFields = (configObj?.fields || []).map((field) => ({
601
+ name: field.key || field.name || "",
602
+ type: mapFieldType(field.type),
603
+ label: field.description || field.label || field.key || field.name || "",
604
+ required: field.required,
605
+ placeholder: field.placeholder,
606
+ options: field.options
607
+ }));
608
+ return {
609
+ component_type: "form",
610
+ component_id: componentId,
611
+ data: {
612
+ title: configObj?.title || "Form",
613
+ description: configObj?.description,
614
+ fields: transformedFields,
615
+ submit_label: configObj?.cta || configObj?.submit_label || "Submit"
616
+ }
617
+ };
618
+ }
619
+ function transformButtons(componentId, config, rpcPayload) {
620
+ return {
621
+ component_type: "buttons",
622
+ component_id: componentId,
623
+ data: {
624
+ title: rpcPayload.title,
625
+ buttons: Array.isArray(config) ? config : []
626
+ }
627
+ };
628
+ }
629
+ function transformConfirmation(componentId, rpcPayload) {
630
+ return {
631
+ component_type: "confirmation",
632
+ component_id: componentId,
633
+ data: {
634
+ title: rpcPayload.title || "Confirmed",
635
+ message: rpcPayload.message || "",
636
+ icon: rpcPayload.icon || "success",
637
+ details: rpcPayload.details
638
+ }
639
+ };
640
+ }
641
+ function mapFieldType(backendType) {
642
+ const typeMap = {
643
+ text: "text",
644
+ string: "text",
645
+ number: "number",
646
+ email: "email",
647
+ phone_number: "tel",
648
+ single_select: "select",
649
+ multiselect: "multiselect",
650
+ checkbox: "boolean",
651
+ date: "date",
652
+ textarea: "textarea"
653
+ };
654
+ return typeMap[backendType] || "text";
655
+ }
656
+ function formatComponentResponse(componentName, componentId, responseData, originalConfig) {
657
+ const rpcMethod = "receive_dynamic_data";
658
+ let componentData;
659
+ if (componentName === "calendar") {
660
+ const slotId = responseData.step_data && responseData.step_data.slot_id;
661
+ const configObj = originalConfig;
662
+ const slots = configObj?.slots || [];
663
+ const timezone = configObj?.timezone || "UTC";
664
+ const selectedSlot = slots.find((slot) => slot.id === slotId);
665
+ componentData = {
666
+ id: selectedSlot?.id || slotId,
667
+ datetime: selectedSlot?.datetime || responseData.step_data?.slot_datetime,
668
+ timezone
669
+ };
670
+ } else if (componentName === "form") {
671
+ componentData = responseData.step_data || responseData.all_data;
672
+ } else if (componentName === "buttons") {
673
+ const buttonId = responseData.step_data && responseData.step_data.selected_button;
674
+ const buttons = Array.isArray(originalConfig) ? originalConfig : [];
675
+ const selectedButton = buttons.find((btn) => btn.id === buttonId);
676
+ componentData = selectedButton || { id: buttonId };
677
+ } else {
678
+ componentData = responseData;
679
+ }
680
+ const toolId = originalConfig?.tool_id;
681
+ const payload = JSON.stringify({
682
+ component_type: `receive_component_${componentName}`,
683
+ component_id: componentId,
684
+ component_data: componentData,
685
+ ...toolId && { tool_id: toolId }
686
+ });
687
+ return { method: rpcMethod, payload };
688
+ }
689
+ function formatDiseaseSubmission(componentId, selections) {
690
+ return {
691
+ method: "receive_dynamic_data",
692
+ payload: JSON.stringify({
693
+ component_type: "receive_component_disease_plans",
694
+ component_id: componentId,
695
+ selections
696
+ })
697
+ };
698
+ }
699
+ function formatDiseaseSearch(query) {
700
+ return {
701
+ method: "receive_dynamic_data",
702
+ payload: JSON.stringify({
703
+ component_type: "receive_component_disease_search",
704
+ query
705
+ })
706
+ };
707
+ }
708
+ function formatSlashCommand(command) {
709
+ return {
710
+ method: "receive_dynamic_data",
711
+ payload: JSON.stringify({
712
+ component_type: "receive_component_slash_command",
713
+ command: command.replace(/^\//, "")
714
+ })
715
+ };
716
+ }
717
+
718
+ exports.CallbackEventBus = CallbackEventBus;
719
+ exports.DEFAULT_CONFIG = DEFAULT_CONFIG;
720
+ exports.DEFAULT_WIDGET_THEME = DEFAULT_WIDGET_THEME;
721
+ exports.DomEventBus = DomEventBus;
722
+ exports.RinggApiClient = RinggApiClient;
723
+ exports.StaticUrlResolver = StaticUrlResolver;
724
+ exports.WIDGET_PRESET_THEMES = WIDGET_PRESET_THEMES;
725
+ exports.WidgetStateController = WidgetStateController;
726
+ exports.buildPayload = buildPayload;
727
+ exports.colorToBackground = colorToBackground;
728
+ exports.colorToBorder = colorToBorder;
729
+ exports.colorToSolid = colorToSolid;
730
+ exports.extractColorsFromGradient = extractColorsFromGradient;
731
+ exports.filterSlashCommands = filterSlashCommands;
732
+ exports.formatComponentResponse = formatComponentResponse;
733
+ exports.formatDiseaseSearch = formatDiseaseSearch;
734
+ exports.formatDiseaseSubmission = formatDiseaseSubmission;
735
+ exports.formatSlashCommand = formatSlashCommand;
736
+ exports.formatSlotDate = formatSlotDate;
737
+ exports.formatSlotTime = formatSlotTime;
738
+ exports.formatTimestamp = formatTimestamp;
739
+ exports.getButtonRadius = getButtonRadius;
740
+ exports.getContrastingTextColor = getContrastingTextColor;
741
+ exports.getDiseasesWithSubQuestions = getDiseasesWithSubQuestions;
742
+ exports.getDominantColor = getDominantColor;
743
+ exports.groupSlotsByDate = groupSlotsByDate;
744
+ exports.hasSubQuestions = hasSubQuestions;
745
+ exports.isAgentIdentity = isAgentIdentity;
746
+ exports.isButtons = isButtons;
747
+ exports.isCalendarBooking = isCalendarBooking;
748
+ exports.isConfirmation = isConfirmation;
749
+ exports.isForm = isForm;
750
+ exports.isGradient = isGradient;
751
+ exports.isInteractiveFlow = isInteractiveFlow;
752
+ exports.isLightColor = isLightColor;
753
+ exports.mergeComponentTheme = mergeComponentTheme;
754
+ exports.mergeWidgetTheme = mergeWidgetTheme;
755
+ exports.transformRpcToComponent = transformRpcToComponent;
756
+ //# sourceMappingURL=index.cjs.map
757
+ //# sourceMappingURL=index.cjs.map