@aptly-sdk/hq 0.0.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.
Files changed (3) hide show
  1. package/dist/global.css +454 -0
  2. package/dist/index.js +1195 -0
  3. package/package.json +63 -0
package/dist/index.js ADDED
@@ -0,0 +1,1195 @@
1
+ import './global.css';
2
+ import require$$0, { useState, useEffect, createContext, useRef, useContext, useCallback, useMemo, Activity } from 'react';
3
+ import Brook from '@aptly-sdk/brook';
4
+ import { BrookProvider as BrookProvider$1, useStream } from '@aptly-sdk/brook/react';
5
+
6
+ function getProject(apiKey) {
7
+ return new Promise(resolve => {
8
+ fetch(`https://connect.aptly.cloud/hq/conversations/project`, {
9
+ headers: {
10
+ "Content-Type": "application/json",
11
+ "x-api-key": apiKey
12
+ }
13
+ }).then(res => res.json()).then(res => resolve(res)).catch(e => {
14
+ console.log("Error fetching data.", e);
15
+ resolve(null);
16
+ });
17
+ });
18
+ }
19
+
20
+ var project = {};
21
+ var context = null;
22
+ var contextListeners = new Set();
23
+ async function init({
24
+ apiKey
25
+ }) {
26
+ const data = await getProject(apiKey);
27
+ if (data) data.apiKey = apiKey;
28
+ project = data;
29
+ return project;
30
+ }
31
+ var client = {
32
+ init,
33
+ getProject: () => project,
34
+ getContext: () => context,
35
+ setContext: nextContext => {
36
+ context = nextContext;
37
+ contextListeners.forEach(listener => listener(context));
38
+ },
39
+ subscribeToContext: listener => {
40
+ contextListeners.add(listener);
41
+ return () => {
42
+ contextListeners.delete(listener);
43
+ };
44
+ }
45
+ };
46
+
47
+ var jsxRuntime = {exports: {}};
48
+
49
+ var reactJsxRuntime_production = {};
50
+
51
+ /**
52
+ * @license React
53
+ * react-jsx-runtime.production.js
54
+ *
55
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
56
+ *
57
+ * This source code is licensed under the MIT license found in the
58
+ * LICENSE file in the root directory of this source tree.
59
+ */
60
+
61
+ var hasRequiredReactJsxRuntime_production;
62
+
63
+ function requireReactJsxRuntime_production () {
64
+ if (hasRequiredReactJsxRuntime_production) return reactJsxRuntime_production;
65
+ hasRequiredReactJsxRuntime_production = 1;
66
+ var REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"),
67
+ REACT_FRAGMENT_TYPE = Symbol.for("react.fragment");
68
+ function jsxProd(type, config, maybeKey) {
69
+ var key = null;
70
+ void 0 !== maybeKey && (key = "" + maybeKey);
71
+ void 0 !== config.key && (key = "" + config.key);
72
+ if ("key" in config) {
73
+ maybeKey = {};
74
+ for (var propName in config)
75
+ "key" !== propName && (maybeKey[propName] = config[propName]);
76
+ } else maybeKey = config;
77
+ config = maybeKey.ref;
78
+ return {
79
+ $$typeof: REACT_ELEMENT_TYPE,
80
+ type: type,
81
+ key: key,
82
+ ref: void 0 !== config ? config : null,
83
+ props: maybeKey
84
+ };
85
+ }
86
+ reactJsxRuntime_production.Fragment = REACT_FRAGMENT_TYPE;
87
+ reactJsxRuntime_production.jsx = jsxProd;
88
+ reactJsxRuntime_production.jsxs = jsxProd;
89
+ return reactJsxRuntime_production;
90
+ }
91
+
92
+ var reactJsxRuntime_development = {};
93
+
94
+ /**
95
+ * @license React
96
+ * react-jsx-runtime.development.js
97
+ *
98
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
99
+ *
100
+ * This source code is licensed under the MIT license found in the
101
+ * LICENSE file in the root directory of this source tree.
102
+ */
103
+
104
+ var hasRequiredReactJsxRuntime_development;
105
+
106
+ function requireReactJsxRuntime_development () {
107
+ if (hasRequiredReactJsxRuntime_development) return reactJsxRuntime_development;
108
+ hasRequiredReactJsxRuntime_development = 1;
109
+ "production" !== process.env.NODE_ENV &&
110
+ (function () {
111
+ function getComponentNameFromType(type) {
112
+ if (null == type) return null;
113
+ if ("function" === typeof type)
114
+ return type.$$typeof === REACT_CLIENT_REFERENCE
115
+ ? null
116
+ : type.displayName || type.name || null;
117
+ if ("string" === typeof type) return type;
118
+ switch (type) {
119
+ case REACT_FRAGMENT_TYPE:
120
+ return "Fragment";
121
+ case REACT_PROFILER_TYPE:
122
+ return "Profiler";
123
+ case REACT_STRICT_MODE_TYPE:
124
+ return "StrictMode";
125
+ case REACT_SUSPENSE_TYPE:
126
+ return "Suspense";
127
+ case REACT_SUSPENSE_LIST_TYPE:
128
+ return "SuspenseList";
129
+ case REACT_ACTIVITY_TYPE:
130
+ return "Activity";
131
+ }
132
+ if ("object" === typeof type)
133
+ switch (
134
+ ("number" === typeof type.tag &&
135
+ console.error(
136
+ "Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."
137
+ ),
138
+ type.$$typeof)
139
+ ) {
140
+ case REACT_PORTAL_TYPE:
141
+ return "Portal";
142
+ case REACT_CONTEXT_TYPE:
143
+ return type.displayName || "Context";
144
+ case REACT_CONSUMER_TYPE:
145
+ return (type._context.displayName || "Context") + ".Consumer";
146
+ case REACT_FORWARD_REF_TYPE:
147
+ var innerType = type.render;
148
+ type = type.displayName;
149
+ type ||
150
+ ((type = innerType.displayName || innerType.name || ""),
151
+ (type = "" !== type ? "ForwardRef(" + type + ")" : "ForwardRef"));
152
+ return type;
153
+ case REACT_MEMO_TYPE:
154
+ return (
155
+ (innerType = type.displayName || null),
156
+ null !== innerType
157
+ ? innerType
158
+ : getComponentNameFromType(type.type) || "Memo"
159
+ );
160
+ case REACT_LAZY_TYPE:
161
+ innerType = type._payload;
162
+ type = type._init;
163
+ try {
164
+ return getComponentNameFromType(type(innerType));
165
+ } catch (x) {}
166
+ }
167
+ return null;
168
+ }
169
+ function testStringCoercion(value) {
170
+ return "" + value;
171
+ }
172
+ function checkKeyStringCoercion(value) {
173
+ try {
174
+ testStringCoercion(value);
175
+ var JSCompiler_inline_result = !1;
176
+ } catch (e) {
177
+ JSCompiler_inline_result = true;
178
+ }
179
+ if (JSCompiler_inline_result) {
180
+ JSCompiler_inline_result = console;
181
+ var JSCompiler_temp_const = JSCompiler_inline_result.error;
182
+ var JSCompiler_inline_result$jscomp$0 =
183
+ ("function" === typeof Symbol &&
184
+ Symbol.toStringTag &&
185
+ value[Symbol.toStringTag]) ||
186
+ value.constructor.name ||
187
+ "Object";
188
+ JSCompiler_temp_const.call(
189
+ JSCompiler_inline_result,
190
+ "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",
191
+ JSCompiler_inline_result$jscomp$0
192
+ );
193
+ return testStringCoercion(value);
194
+ }
195
+ }
196
+ function getTaskName(type) {
197
+ if (type === REACT_FRAGMENT_TYPE) return "<>";
198
+ if (
199
+ "object" === typeof type &&
200
+ null !== type &&
201
+ type.$$typeof === REACT_LAZY_TYPE
202
+ )
203
+ return "<...>";
204
+ try {
205
+ var name = getComponentNameFromType(type);
206
+ return name ? "<" + name + ">" : "<...>";
207
+ } catch (x) {
208
+ return "<...>";
209
+ }
210
+ }
211
+ function getOwner() {
212
+ var dispatcher = ReactSharedInternals.A;
213
+ return null === dispatcher ? null : dispatcher.getOwner();
214
+ }
215
+ function UnknownOwner() {
216
+ return Error("react-stack-top-frame");
217
+ }
218
+ function hasValidKey(config) {
219
+ if (hasOwnProperty.call(config, "key")) {
220
+ var getter = Object.getOwnPropertyDescriptor(config, "key").get;
221
+ if (getter && getter.isReactWarning) return false;
222
+ }
223
+ return void 0 !== config.key;
224
+ }
225
+ function defineKeyPropWarningGetter(props, displayName) {
226
+ function warnAboutAccessingKey() {
227
+ specialPropKeyWarningShown ||
228
+ ((specialPropKeyWarningShown = true),
229
+ console.error(
230
+ "%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",
231
+ displayName
232
+ ));
233
+ }
234
+ warnAboutAccessingKey.isReactWarning = true;
235
+ Object.defineProperty(props, "key", {
236
+ get: warnAboutAccessingKey,
237
+ configurable: true
238
+ });
239
+ }
240
+ function elementRefGetterWithDeprecationWarning() {
241
+ var componentName = getComponentNameFromType(this.type);
242
+ didWarnAboutElementRef[componentName] ||
243
+ ((didWarnAboutElementRef[componentName] = true),
244
+ console.error(
245
+ "Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release."
246
+ ));
247
+ componentName = this.props.ref;
248
+ return void 0 !== componentName ? componentName : null;
249
+ }
250
+ function ReactElement(type, key, props, owner, debugStack, debugTask) {
251
+ var refProp = props.ref;
252
+ type = {
253
+ $$typeof: REACT_ELEMENT_TYPE,
254
+ type: type,
255
+ key: key,
256
+ props: props,
257
+ _owner: owner
258
+ };
259
+ null !== (void 0 !== refProp ? refProp : null)
260
+ ? Object.defineProperty(type, "ref", {
261
+ enumerable: false,
262
+ get: elementRefGetterWithDeprecationWarning
263
+ })
264
+ : Object.defineProperty(type, "ref", { enumerable: false, value: null });
265
+ type._store = {};
266
+ Object.defineProperty(type._store, "validated", {
267
+ configurable: false,
268
+ enumerable: false,
269
+ writable: true,
270
+ value: 0
271
+ });
272
+ Object.defineProperty(type, "_debugInfo", {
273
+ configurable: false,
274
+ enumerable: false,
275
+ writable: true,
276
+ value: null
277
+ });
278
+ Object.defineProperty(type, "_debugStack", {
279
+ configurable: false,
280
+ enumerable: false,
281
+ writable: true,
282
+ value: debugStack
283
+ });
284
+ Object.defineProperty(type, "_debugTask", {
285
+ configurable: false,
286
+ enumerable: false,
287
+ writable: true,
288
+ value: debugTask
289
+ });
290
+ Object.freeze && (Object.freeze(type.props), Object.freeze(type));
291
+ return type;
292
+ }
293
+ function jsxDEVImpl(
294
+ type,
295
+ config,
296
+ maybeKey,
297
+ isStaticChildren,
298
+ debugStack,
299
+ debugTask
300
+ ) {
301
+ var children = config.children;
302
+ if (void 0 !== children)
303
+ if (isStaticChildren)
304
+ if (isArrayImpl(children)) {
305
+ for (
306
+ isStaticChildren = 0;
307
+ isStaticChildren < children.length;
308
+ isStaticChildren++
309
+ )
310
+ validateChildKeys(children[isStaticChildren]);
311
+ Object.freeze && Object.freeze(children);
312
+ } else
313
+ console.error(
314
+ "React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead."
315
+ );
316
+ else validateChildKeys(children);
317
+ if (hasOwnProperty.call(config, "key")) {
318
+ children = getComponentNameFromType(type);
319
+ var keys = Object.keys(config).filter(function (k) {
320
+ return "key" !== k;
321
+ });
322
+ isStaticChildren =
323
+ 0 < keys.length
324
+ ? "{key: someKey, " + keys.join(": ..., ") + ": ...}"
325
+ : "{key: someKey}";
326
+ didWarnAboutKeySpread[children + isStaticChildren] ||
327
+ ((keys =
328
+ 0 < keys.length ? "{" + keys.join(": ..., ") + ": ...}" : "{}"),
329
+ console.error(
330
+ 'A props object containing a "key" prop is being spread into JSX:\n let props = %s;\n <%s {...props} />\nReact keys must be passed directly to JSX without using spread:\n let props = %s;\n <%s key={someKey} {...props} />',
331
+ isStaticChildren,
332
+ children,
333
+ keys,
334
+ children
335
+ ),
336
+ (didWarnAboutKeySpread[children + isStaticChildren] = true));
337
+ }
338
+ children = null;
339
+ void 0 !== maybeKey &&
340
+ (checkKeyStringCoercion(maybeKey), (children = "" + maybeKey));
341
+ hasValidKey(config) &&
342
+ (checkKeyStringCoercion(config.key), (children = "" + config.key));
343
+ if ("key" in config) {
344
+ maybeKey = {};
345
+ for (var propName in config)
346
+ "key" !== propName && (maybeKey[propName] = config[propName]);
347
+ } else maybeKey = config;
348
+ children &&
349
+ defineKeyPropWarningGetter(
350
+ maybeKey,
351
+ "function" === typeof type
352
+ ? type.displayName || type.name || "Unknown"
353
+ : type
354
+ );
355
+ return ReactElement(
356
+ type,
357
+ children,
358
+ maybeKey,
359
+ getOwner(),
360
+ debugStack,
361
+ debugTask
362
+ );
363
+ }
364
+ function validateChildKeys(node) {
365
+ isValidElement(node)
366
+ ? node._store && (node._store.validated = 1)
367
+ : "object" === typeof node &&
368
+ null !== node &&
369
+ node.$$typeof === REACT_LAZY_TYPE &&
370
+ ("fulfilled" === node._payload.status
371
+ ? isValidElement(node._payload.value) &&
372
+ node._payload.value._store &&
373
+ (node._payload.value._store.validated = 1)
374
+ : node._store && (node._store.validated = 1));
375
+ }
376
+ function isValidElement(object) {
377
+ return (
378
+ "object" === typeof object &&
379
+ null !== object &&
380
+ object.$$typeof === REACT_ELEMENT_TYPE
381
+ );
382
+ }
383
+ var React = require$$0,
384
+ REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"),
385
+ REACT_PORTAL_TYPE = Symbol.for("react.portal"),
386
+ REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"),
387
+ REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"),
388
+ REACT_PROFILER_TYPE = Symbol.for("react.profiler"),
389
+ REACT_CONSUMER_TYPE = Symbol.for("react.consumer"),
390
+ REACT_CONTEXT_TYPE = Symbol.for("react.context"),
391
+ REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"),
392
+ REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"),
393
+ REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"),
394
+ REACT_MEMO_TYPE = Symbol.for("react.memo"),
395
+ REACT_LAZY_TYPE = Symbol.for("react.lazy"),
396
+ REACT_ACTIVITY_TYPE = Symbol.for("react.activity"),
397
+ REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"),
398
+ ReactSharedInternals =
399
+ React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,
400
+ hasOwnProperty = Object.prototype.hasOwnProperty,
401
+ isArrayImpl = Array.isArray,
402
+ createTask = console.createTask
403
+ ? console.createTask
404
+ : function () {
405
+ return null;
406
+ };
407
+ React = {
408
+ react_stack_bottom_frame: function (callStackForError) {
409
+ return callStackForError();
410
+ }
411
+ };
412
+ var specialPropKeyWarningShown;
413
+ var didWarnAboutElementRef = {};
414
+ var unknownOwnerDebugStack = React.react_stack_bottom_frame.bind(
415
+ React,
416
+ UnknownOwner
417
+ )();
418
+ var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));
419
+ var didWarnAboutKeySpread = {};
420
+ reactJsxRuntime_development.Fragment = REACT_FRAGMENT_TYPE;
421
+ reactJsxRuntime_development.jsx = function (type, config, maybeKey) {
422
+ var trackActualOwner =
423
+ 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;
424
+ return jsxDEVImpl(
425
+ type,
426
+ config,
427
+ maybeKey,
428
+ false,
429
+ trackActualOwner
430
+ ? Error("react-stack-top-frame")
431
+ : unknownOwnerDebugStack,
432
+ trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask
433
+ );
434
+ };
435
+ reactJsxRuntime_development.jsxs = function (type, config, maybeKey) {
436
+ var trackActualOwner =
437
+ 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;
438
+ return jsxDEVImpl(
439
+ type,
440
+ config,
441
+ maybeKey,
442
+ true,
443
+ trackActualOwner
444
+ ? Error("react-stack-top-frame")
445
+ : unknownOwnerDebugStack,
446
+ trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask
447
+ );
448
+ };
449
+ })();
450
+ return reactJsxRuntime_development;
451
+ }
452
+
453
+ var hasRequiredJsxRuntime;
454
+
455
+ function requireJsxRuntime () {
456
+ if (hasRequiredJsxRuntime) return jsxRuntime.exports;
457
+ hasRequiredJsxRuntime = 1;
458
+
459
+ if (process.env.NODE_ENV === 'production') {
460
+ jsxRuntime.exports = requireReactJsxRuntime_production();
461
+ } else {
462
+ jsxRuntime.exports = requireReactJsxRuntime_development();
463
+ }
464
+ return jsxRuntime.exports;
465
+ }
466
+
467
+ var jsxRuntimeExports = requireJsxRuntime();
468
+
469
+ const BrookProvider = ({
470
+ children,
471
+ apiKey
472
+ }) => {
473
+ const config = {
474
+ apiKey: apiKey || "apiKey",
475
+ // todo: remove these on prod
476
+ verbose: true,
477
+ host: "ws://localhost:8787"
478
+ };
479
+ const [client, setClient] = useState(new Brook(config));
480
+ useEffect(() => {
481
+ client.cleanup();
482
+ if (apiKey) {
483
+ const brook = new Brook(config);
484
+ setClient(brook);
485
+ return () => {
486
+ brook.cleanup();
487
+ };
488
+ }
489
+ }, [apiKey]);
490
+ return /*#__PURE__*/jsxRuntimeExports.jsx(BrookProvider$1, {
491
+ config: client,
492
+ children: children
493
+ });
494
+ };
495
+
496
+ const HQProviderContext = /*#__PURE__*/createContext({});
497
+ function HQProvider({
498
+ children,
499
+ apiKey
500
+ }) {
501
+ const [project, setProject] = useState(null);
502
+ const [context, setContext] = useState(client.getContext());
503
+ useEffect(() => {
504
+ client.init({
505
+ apiKey
506
+ }).then(p => setProject(p));
507
+ }, [apiKey]);
508
+ useEffect(() => {
509
+ const unsubscribe = client.subscribeToContext(nextContext => {
510
+ setContext(nextContext);
511
+ });
512
+ return unsubscribe;
513
+ }, []);
514
+ return /*#__PURE__*/jsxRuntimeExports.jsx(HQProviderContext.Provider, {
515
+ value: {
516
+ project,
517
+ context
518
+ },
519
+ children: /*#__PURE__*/jsxRuntimeExports.jsx(BrookProvider, {
520
+ apiKey: project?.apiKey,
521
+ children: children
522
+ })
523
+ });
524
+ }
525
+
526
+ function useOnMount(callback) {
527
+ const ref = useRef({
528
+ called: false,
529
+ mounted: false
530
+ });
531
+ if (ref.current.called || ref.current.mounted) return;
532
+ if (ref.current.called === false && ref.current.mounted === false) {
533
+ callback();
534
+ ref.current.called = true;
535
+ }
536
+ if (ref.current.mounted === false) ref.current.mounted = true;
537
+ }
538
+
539
+ function startConversation(apiKey, payload) {
540
+ return new Promise(resolve => {
541
+ fetch(`https://connect.aptly.cloud/hq/conversations`, {
542
+ method: "POST",
543
+ headers: {
544
+ "Content-Type": "application/json",
545
+ "x-api-key": apiKey
546
+ },
547
+ body: payload
548
+ }).then(res => res.json()).then(res => resolve(res)).catch(e => {
549
+ console.log("Error fetching data.", e);
550
+ resolve(null);
551
+ });
552
+ });
553
+ }
554
+
555
+ function useHQ() {
556
+ const ctx = useContext(HQProviderContext);
557
+ return ctx;
558
+ }
559
+
560
+ function useProject() {
561
+ const hq = useHQ();
562
+ return hq.project;
563
+ }
564
+
565
+ const useConversation$1 = () => {
566
+ const project = useProject();
567
+ const [conversation, setConversation] = useState(null);
568
+ useOnMount(() => {
569
+ const cache = localStorage.getItem("conversation");
570
+ if (cache) setConversation(JSON.parse(cache));
571
+ });
572
+ const start = useCallback(async function start(values) {
573
+ const response = await startConversation(project.apiKey, values);
574
+
575
+ // attach initial message to the conversation, to use later when useMessage is ready to send the initial message
576
+ response.initialMessage = values?.message;
577
+ if (response) {
578
+ setConversation(response);
579
+ localStorage.setItem("conversation", JSON.stringify({
580
+ id: response.id,
581
+ context: {
582
+ id: response?.context?.id
583
+ }
584
+ }));
585
+ }
586
+ }, [project]);
587
+ const close = useCallback(() => {
588
+ // todo: update status in BE
589
+ setConversation(null);
590
+ localStorage.removeItem("conversation");
591
+ }, [project]);
592
+ return {
593
+ start,
594
+ data: conversation,
595
+ close
596
+ };
597
+ };
598
+
599
+ function getMessages(apiKey, conversationsId) {
600
+ return new Promise(resolve => {
601
+ fetch(`https://connect.aptly.cloud/hq/conversations/messages?conversationsId=${conversationsId}`, {
602
+ headers: {
603
+ "Content-Type": "application/json",
604
+ "x-api-key": apiKey
605
+ }
606
+ }).then(res => res.json()).then(res => resolve(res || [])).catch(e => {
607
+ console.log("Error fetching data.", e);
608
+ resolve([]);
609
+ });
610
+ });
611
+ }
612
+
613
+ function sendMessage({
614
+ message,
615
+ conversationId,
616
+ senderId,
617
+ senderName
618
+ }) {
619
+ return new Promise(resolve => {
620
+ const project = client.getProject();
621
+ if (!project.apiKey) return null;
622
+ fetch(`https://connect.aptly.cloud/hq/conversations/message`, {
623
+ headers: {
624
+ "Content-Type": "application/json",
625
+ "x-api-key": project.apiKey
626
+ },
627
+ method: "POST",
628
+ body: JSON.stringify({
629
+ message,
630
+ conversationId,
631
+ senderId,
632
+ senderName
633
+ })
634
+ }).then(res => res.json()).then(res => resolve(res)).catch(e => {
635
+ console.log("Error fetching data.", e);
636
+ resolve(null);
637
+ });
638
+ });
639
+ }
640
+
641
+ function generateRandomString(length) {
642
+ const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
643
+ let result = '';
644
+ const randomArray = new Uint8Array(length);
645
+ crypto.getRandomValues(randomArray);
646
+ randomArray.forEach(number => {
647
+ result += chars[number % chars.length];
648
+ });
649
+ return result;
650
+ }
651
+
652
+ function useMessages(conversation) {
653
+ const conversationId = conversation?.id;
654
+ const lookupRef = useRef({});
655
+ const initialMessageLookUpRef = useRef(new Set()); // set of conversation ids that already sent initial message
656
+
657
+ const project = useProject();
658
+ const [messages, setMessages] = useState([]);
659
+ const getAll = useCallback(() => {
660
+ if (!conversationId) return;
661
+ return new Promise(resolve => {
662
+ lookupRef.current[conversationId] = new Set();
663
+ handleGetMessages(project?.apiKey, conversationId) //
664
+ .then(m => {
665
+ setMessages(m);
666
+ lookupRef.current[conversationId].add(m.id);
667
+ resolve(m);
668
+ }).finally(resolve);
669
+ });
670
+ }, [conversationId]);
671
+ useEffect(() => {
672
+ if (conversationId) {
673
+ // get all message
674
+ getAll().then(() => {
675
+ if (!initialMessageLookUpRef.current.has(conversation.id)) {
676
+ if (conversation.initialMessage) {
677
+ handleSend(conversation.initialMessage).then(() => {
678
+ initialMessageLookUpRef.current.add(conversation.id);
679
+ });
680
+ }
681
+ }
682
+ });
683
+ }
684
+ }, [conversationId]);
685
+ useStream(`messages.${conversationId}`, incoming => {
686
+ if (!lookupRef.current[conversationId].has(incoming.id)) {
687
+ if (incoming.sender_id !== conversation.context.id) {
688
+ setMessages(m => [...m, incoming]);
689
+ lookupRef.current[conversationId].add(incoming.id);
690
+ }
691
+ }
692
+ });
693
+ async function handleSend(message) {
694
+ if (!message) return;
695
+ const temporaryId = generateRandomString(12);
696
+ let messageData = {
697
+ _id: temporaryId,
698
+ message,
699
+ conversation_id: conversation?.id,
700
+ sender_id: conversation?.context?.id,
701
+ status: "pending",
702
+ created_at: new Date().toISOString(),
703
+ updated_at: new Date().toISOString(),
704
+ sender_name: conversation?.context?.name
705
+ };
706
+ setMessages(m => [...m, messageData]);
707
+ const response = await sendMessage({
708
+ message,
709
+ conversationId,
710
+ senderId: conversation?.context?.id,
711
+ senderName: conversation?.context?.name
712
+ });
713
+ if (response.id) {
714
+ const newMessage = {
715
+ ...messageData
716
+ };
717
+ newMessage.id = response.id;
718
+ newMessage.status = response.status;
719
+ newMessage.updated_at = response.updated_at;
720
+ newMessage.sender_name = response.sender_name;
721
+ setMessages(prev => [...prev].map(m => {
722
+ if (m._id === temporaryId) {
723
+ return newMessage;
724
+ }
725
+ return m;
726
+ }));
727
+ lookupRef.current[conversationId].add(response.id);
728
+ }
729
+ }
730
+ return {
731
+ data: messages,
732
+ messages,
733
+ send: handleSend
734
+ };
735
+ }
736
+ async function handleGetMessages(apiKey, conversationsId) {
737
+ const messages = await getMessages(apiKey, conversationsId);
738
+ return messages;
739
+ }
740
+
741
+ function Wrapper(props) {
742
+ return /*#__PURE__*/jsxRuntimeExports.jsx(HQProvider, {
743
+ apiKey: props.apiKey,
744
+ children: /*#__PURE__*/jsxRuntimeExports.jsx(HQWidget, {
745
+ ...props
746
+ })
747
+ });
748
+ }
749
+ function HQWidget({
750
+ className,
751
+ position,
752
+ children,
753
+ ClosedIcon,
754
+ OpenedIcon
755
+ }) {
756
+ const project = useProject();
757
+ const valuesRef = useRef({});
758
+ const [values, setValues] = useState({});
759
+ const conversation = useConversation$1();
760
+ const message = useMessages(conversation.data);
761
+ const [isOpened, setIsOpened] = useState(false);
762
+ const [showCloseConfirmation, setShowCloseConfirmation] = useState(false);
763
+ const handleOnChange = useCallback((event, field) => {
764
+ const incomingValue = event.target?.value;
765
+ setValues(prev => ({
766
+ ...prev,
767
+ [field?.name]: incomingValue
768
+ }));
769
+ valuesRef.current[field?.name] = incomingValue;
770
+ }, []);
771
+ const handleStartConversation = useCallback(async event => {
772
+ event?.preventDefault();
773
+ const messageInput = document.getElementById("startMessageInputEl");
774
+ const messageValue = messageInput?.value;
775
+ valuesRef.current.message = messageValue;
776
+ await conversation.start(valuesRef.current);
777
+ setValues({});
778
+ valuesRef.current = {};
779
+ messageInput.value = "";
780
+ }, [project]);
781
+ async function handleSendMessage(messageString) {
782
+ const input = document.getElementById("messageInputEl");
783
+ let messageValue = input.value;
784
+ if (typeof messageString === "string") messageValue = messageString;
785
+ input.disable = true;
786
+ await message.send(messageValue);
787
+ input.disable = false;
788
+ input.value = "";
789
+ }
790
+ function handleClickClose() {
791
+ setShowCloseConfirmation(true);
792
+ }
793
+ const fields = project?.metadata?.fields || [];
794
+ const WidgetIcon = useMemo(() => {
795
+ let icon = () => null;
796
+ if (isOpened) icon = OpenedIcon || DefaultOpenedIcon;else icon = ClosedIcon || DefaultClosedIcon;
797
+ return icon;
798
+ }, [isOpened, ClosedIcon, OpenedIcon]);
799
+ return /*#__PURE__*/jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, {
800
+ children: [children, project && /*#__PURE__*/jsxRuntimeExports.jsxs("div", {
801
+ className: `aptly-hq-widget ${className || ""}`,
802
+ children: [/*#__PURE__*/jsxRuntimeExports.jsx(Activity, {
803
+ mode: isOpened ? "visible" : "hidden",
804
+ children: /*#__PURE__*/jsxRuntimeExports.jsxs("div", {
805
+ className: "shadow widget-container",
806
+ children: [/*#__PURE__*/jsxRuntimeExports.jsxs(Activity, {
807
+ mode: !conversation.data ? "visible" : "hidden",
808
+ children: [/*#__PURE__*/jsxRuntimeExports.jsx(Header, {
809
+ onClose: () => setIsOpened(p => !p)
810
+ }), /*#__PURE__*/jsxRuntimeExports.jsxs("section", {
811
+ className: "widget-form-container",
812
+ children: [/*#__PURE__*/jsxRuntimeExports.jsxs("form", {
813
+ id: "widgetForm",
814
+ className: "widget-form",
815
+ onSubmit: handleStartConversation,
816
+ children: [fields?.map(field => /*#__PURE__*/jsxRuntimeExports.jsxs("div", {
817
+ children: [/*#__PURE__*/jsxRuntimeExports.jsx("label", {
818
+ children: field.label
819
+ }), /*#__PURE__*/jsxRuntimeExports.jsx("input", {
820
+ required: field?.required,
821
+ type: field.type,
822
+ placeholder: field?.placeholder,
823
+ value: values?.[field.name] || "",
824
+ onChange: e => handleOnChange(e, field)
825
+ })]
826
+ }, `field-${field.name}`)), /*#__PURE__*/jsxRuntimeExports.jsxs("div", {
827
+ className: "flex flex-col",
828
+ children: [/*#__PURE__*/jsxRuntimeExports.jsx("label", {
829
+ children: "Message"
830
+ }), /*#__PURE__*/jsxRuntimeExports.jsx("textarea", {
831
+ maxLength: 1000,
832
+ rows: 4,
833
+ id: "startMessageInputEl",
834
+ required: true,
835
+ placeholder: project?.metadata?.settings?.messagePlaceholder
836
+ })]
837
+ })]
838
+ }), /*#__PURE__*/jsxRuntimeExports.jsx("button", {
839
+ form: "widgetForm",
840
+ className: "widget-start-button",
841
+ type: "submit",
842
+ children: project?.metadata?.settings?.startLabel || "Start"
843
+ })]
844
+ })]
845
+ }), /*#__PURE__*/jsxRuntimeExports.jsx(Activity, {
846
+ mode: !!conversation.data ? "visible" : "hidden",
847
+ children: /*#__PURE__*/jsxRuntimeExports.jsxs("section", {
848
+ className: "widget-message-area-container",
849
+ children: [/*#__PURE__*/jsxRuntimeExports.jsx(Header, {
850
+ onClose: () => setIsOpened(p => !p)
851
+ }), /*#__PURE__*/jsxRuntimeExports.jsx("div", {
852
+ className: "widget-message-area",
853
+ children: message.messages?.map(m => {
854
+ const pendingStyle = {
855
+ opacity: m.status === "pending" ? 0.5 : 1
856
+ };
857
+ return /*#__PURE__*/jsxRuntimeExports.jsx(Message, {
858
+ style: pendingStyle,
859
+ isOwnersMessage: m.sender_id === conversation?.data?.context?.id,
860
+ children: m.message
861
+ }, m._id || m.id);
862
+ })
863
+ }), /*#__PURE__*/jsxRuntimeExports.jsxs("div", {
864
+ className: "widget-message-area-action",
865
+ children: [/*#__PURE__*/jsxRuntimeExports.jsx("textarea", {
866
+ id: "messageInputEl",
867
+ className: "field-sizing-content",
868
+ placeholder: project?.metadata?.settings?.messagePlaceholder
869
+ }), /*#__PURE__*/jsxRuntimeExports.jsx("button", {
870
+ onClick: handleSendMessage,
871
+ children: /*#__PURE__*/jsxRuntimeExports.jsx(SendIcon, {})
872
+ })]
873
+ }), /*#__PURE__*/jsxRuntimeExports.jsxs("footer", {
874
+ className: "widget-footer",
875
+ children: [!showCloseConfirmation && /*#__PURE__*/jsxRuntimeExports.jsx("button", {
876
+ onClick: handleClickClose,
877
+ children: project?.metadata?.settings?.closeLabel || "Close"
878
+ }), showCloseConfirmation && /*#__PURE__*/jsxRuntimeExports.jsxs("div", {
879
+ children: ["Are you sure?", " ", /*#__PURE__*/jsxRuntimeExports.jsx("button", {
880
+ onClick: () => {
881
+ conversation.close();
882
+ setShowCloseConfirmation(false);
883
+ },
884
+ children: /*#__PURE__*/jsxRuntimeExports.jsx("code", {
885
+ children: "Yes (Y)"
886
+ })
887
+ }), /*#__PURE__*/jsxRuntimeExports.jsx("span", {
888
+ className: "inline-block px-2",
889
+ children: "|"
890
+ }), /*#__PURE__*/jsxRuntimeExports.jsx("button", {
891
+ onClick: () => setShowCloseConfirmation(false),
892
+ children: /*#__PURE__*/jsxRuntimeExports.jsx("code", {
893
+ children: "No (N)"
894
+ })
895
+ })]
896
+ })]
897
+ })]
898
+ })
899
+ })]
900
+ })
901
+ }), /*#__PURE__*/jsxRuntimeExports.jsx("button", {
902
+ onClick: () => setIsOpened(p => !p),
903
+ children: /*#__PURE__*/jsxRuntimeExports.jsx(WidgetIcon, {})
904
+ })]
905
+ })]
906
+ });
907
+ }
908
+ function Message({
909
+ children,
910
+ style = {},
911
+ isOwnersMessage
912
+ }) {
913
+ return /*#__PURE__*/jsxRuntimeExports.jsx("li", {
914
+ style: style,
915
+ className: `widget-message ${isOwnersMessage ? "widget-owner-message" : "widget-agent-message"}`.trim(),
916
+ children: /*#__PURE__*/jsxRuntimeExports.jsx("span", {
917
+ children: children
918
+ })
919
+ });
920
+ }
921
+ function Header({
922
+ onClose
923
+ }) {
924
+ const project = useProject();
925
+ return /*#__PURE__*/jsxRuntimeExports.jsxs("header", {
926
+ className: "widget-header",
927
+ children: [/*#__PURE__*/jsxRuntimeExports.jsxs("div", {
928
+ children: [/*#__PURE__*/jsxRuntimeExports.jsx("div", {
929
+ children: /*#__PURE__*/jsxRuntimeExports.jsx("strong", {
930
+ children: project.name
931
+ })
932
+ }), /*#__PURE__*/jsxRuntimeExports.jsx("small", {
933
+ children: project.description || "-"
934
+ })]
935
+ }), /*#__PURE__*/jsxRuntimeExports.jsx("button", {
936
+ onClick: onClose,
937
+ children: /*#__PURE__*/jsxRuntimeExports.jsx(CloseIcon, {})
938
+ })]
939
+ });
940
+ }
941
+ function DefaultClosedIcon() {
942
+ return /*#__PURE__*/jsxRuntimeExports.jsxs("span", {
943
+ className: "default-closed-icon",
944
+ children: [/*#__PURE__*/jsxRuntimeExports.jsx("svg", {
945
+ width: "24",
946
+ height: "24",
947
+ viewBox: "0 0 240 240",
948
+ fill: "none",
949
+ xmlns: "http://www.w3.org/2000/svg",
950
+ children: /*#__PURE__*/jsxRuntimeExports.jsx("path", {
951
+ d: "M240.808 240.808H122.123C56.6994 240.808 3.45695 187.562 3.45695 122.122C3.45695 56.7031 56.6994 3.45697 122.124 3.45697C187.566 3.45697 240.808 56.7031 240.808 122.122V240.808Z",
952
+ fill: "#fff"
953
+ })
954
+ }), "Chat with us"]
955
+ });
956
+ }
957
+ function DefaultOpenedIcon() {
958
+ return /*#__PURE__*/jsxRuntimeExports.jsx("span", {
959
+ className: "default-opened-icon",
960
+ children: /*#__PURE__*/jsxRuntimeExports.jsx("svg", {
961
+ xmlns: "http://www.w3.org/2000/svg",
962
+ width: "1.5em",
963
+ height: "1.5em",
964
+ viewBox: "0 0 16 16",
965
+ fill: "currentColor",
966
+ "aria-hidden": "true",
967
+ focusable: "false",
968
+ "aria-label": "close",
969
+ "data-category": "application",
970
+ style: {
971
+ fontSize: "1em",
972
+ color: "#fff"
973
+ },
974
+ children: /*#__PURE__*/jsxRuntimeExports.jsx("path", {
975
+ d: "m2.784 2.089.069.058 5.146 5.147 5.146-5.147a.5.5 0 0 1 .765.638l-.058.069L8.705 8l5.147 5.146a.5.5 0 0 1-.638.765l-.069-.058-5.146-5.147-5.146 5.147a.5.5 0 0 1-.765-.638l.058-.069L7.293 8 2.146 2.854a.5.5 0 0 1 .638-.765"
976
+ })
977
+ })
978
+ });
979
+ }
980
+ function CloseIcon() {
981
+ return /*#__PURE__*/jsxRuntimeExports.jsxs("svg", {
982
+ xmlns: "http://www.w3.org/2000/svg",
983
+ width: "24",
984
+ height: "24",
985
+ viewBox: "0 0 24 24",
986
+ fill: "none",
987
+ stroke: "currentColor",
988
+ strokeWidth: "2",
989
+ strokeLinecap: "round",
990
+ strokeLinejoin: "round",
991
+ children: [/*#__PURE__*/jsxRuntimeExports.jsx("path", {
992
+ d: "M18 6l-12 12"
993
+ }), /*#__PURE__*/jsxRuntimeExports.jsx("path", {
994
+ d: "M6 6l12 12"
995
+ })]
996
+ });
997
+ }
998
+ function SendIcon() {
999
+ return /*#__PURE__*/jsxRuntimeExports.jsxs("svg", {
1000
+ xmlns: "http://www.w3.org/2000/svg",
1001
+ width: "24",
1002
+ height: "24",
1003
+ viewBox: "0 0 24 24",
1004
+ fill: "none",
1005
+ stroke: "currentColor",
1006
+ strokeWidth: "2",
1007
+ strokeLinecap: "round",
1008
+ strokeLinejoin: "round",
1009
+ children: [/*#__PURE__*/jsxRuntimeExports.jsx("path", {
1010
+ d: "M4.698 4.034l16.302 7.966l-16.302 7.966a.503 .503 0 0 1 -.546 -.124a.555 .555 0 0 1 -.12 -.568l2.468 -7.274l-2.468 -7.274a.555 .555 0 0 1 .12 -.568a.503 .503 0 0 1 .546 -.124z"
1011
+ }), /*#__PURE__*/jsxRuntimeExports.jsx("path", {
1012
+ d: "M6.5 12h14.5"
1013
+ })]
1014
+ });
1015
+ }
1016
+
1017
+ function setContext$1(apiKey, payload) {
1018
+ return new Promise(resolve => {
1019
+ fetch(`https://connect.aptly.cloud/hq/conversations/context`, {
1020
+ method: "PUT",
1021
+ headers: {
1022
+ "Content-Type": "application/json",
1023
+ "x-api-key": apiKey
1024
+ },
1025
+ body: JSON.stringify(payload)
1026
+ }).then(res => res.json()).then(res => resolve(res)).catch(e => {
1027
+ console.log("Error fetching data.", e);
1028
+ resolve(null);
1029
+ });
1030
+ });
1031
+ }
1032
+
1033
+ async function setContext(payload) {
1034
+ const project = client.getProject();
1035
+ if (!project?.apiKey) return null;
1036
+ const response = await setContext$1(project.apiKey, payload);
1037
+ if (response) client.setContext(response);
1038
+ return response;
1039
+ }
1040
+
1041
+ function getConversations(apiKey) {
1042
+ return new Promise(resolve => {
1043
+ fetch(`https://connect.aptly.cloud/hq/conversations`, {
1044
+ headers: {
1045
+ "Content-Type": "application/json",
1046
+ "x-api-key": apiKey
1047
+ }
1048
+ }).then(res => res.json()).then(res => resolve(res)).catch(e => {
1049
+ console.log("Error fetching data.", e);
1050
+ resolve(null);
1051
+ });
1052
+ });
1053
+ }
1054
+
1055
+ function useConversations(_filters = {}) {
1056
+ const project = useProject();
1057
+ const {
1058
+ context
1059
+ } = useHQ();
1060
+ const [conversations, setConversations] = useState([]);
1061
+ const refresh = useCallback(() => {
1062
+ if (!project?.apiKey) return null;
1063
+ if (!context) return null;
1064
+ return getConversations(project.apiKey).then(res => {
1065
+ if (Array.isArray(res)) setConversations(res);
1066
+ return res;
1067
+ });
1068
+ }, [project?.apiKey, context]);
1069
+ useEffect(() => {
1070
+ refresh();
1071
+ }, [refresh]);
1072
+ return {
1073
+ conversations,
1074
+ data: conversations,
1075
+ refresh
1076
+ };
1077
+ }
1078
+
1079
+ function getConversation(apiKey, conversationsId) {
1080
+ return new Promise(resolve => {
1081
+ fetch(`https://connect.aptly.cloud/hq/conversations?conversationsId=${conversationsId}`, {
1082
+ headers: {
1083
+ "Content-Type": "application/json",
1084
+ "x-api-key": apiKey
1085
+ }
1086
+ }).then(res => res.json()).then(res => {
1087
+ if (Array.isArray(res)) {
1088
+ resolve(res[0] || null);
1089
+ return;
1090
+ }
1091
+ resolve(res);
1092
+ }).catch(e => {
1093
+ console.log("Error fetching data.", e);
1094
+ resolve(null);
1095
+ });
1096
+ });
1097
+ }
1098
+
1099
+ function updateConversation(apiKey, payload) {
1100
+ return new Promise(resolve => {
1101
+ fetch(`https://connect.aptly.cloud/hq/conversations`, {
1102
+ method: "PATCH",
1103
+ headers: {
1104
+ "Content-Type": "application/json",
1105
+ "x-api-key": apiKey
1106
+ },
1107
+ body: JSON.stringify(payload)
1108
+ }).then(res => res.json()).then(res => resolve(res)).catch(e => {
1109
+ console.log("Error fetching data.", e);
1110
+ resolve(null);
1111
+ });
1112
+ });
1113
+ }
1114
+
1115
+ function useConversation(conversationId) {
1116
+ const project = useProject();
1117
+ const {
1118
+ context
1119
+ } = useHQ();
1120
+ const [messages, setMessages] = useState([]);
1121
+ const [conversation, setConversation] = useState(null);
1122
+ const refresh = useCallback(() => {
1123
+ if (!project?.apiKey) return null;
1124
+ if (!context) return null;
1125
+ if (!conversationId) return null;
1126
+ return Promise.all([getConversation(project.apiKey, conversationId), getMessages(project.apiKey, conversationId)]).then(([conversationRes, messagesRes]) => {
1127
+ if (conversationRes) setConversation(conversationRes);
1128
+ if (Array.isArray(messagesRes)) setMessages(messagesRes);
1129
+ return {
1130
+ conversation: conversationRes,
1131
+ messages: messagesRes
1132
+ };
1133
+ });
1134
+ }, [project?.apiKey, context, conversationId]);
1135
+ const send = useCallback(message => {
1136
+ if (!project?.apiKey) return null;
1137
+ if (!context) return null;
1138
+ if (!conversationId) return null;
1139
+ if (!message) return null;
1140
+ return sendMessage({
1141
+ message,
1142
+ conversationId,
1143
+ senderId: context.id,
1144
+ senderName: context.name
1145
+ }).then(res => {
1146
+ refresh();
1147
+ return res;
1148
+ });
1149
+ }, [project?.apiKey, context, conversationId, refresh]);
1150
+ const updateConversation$1 = useCallback((payload = {}) => {
1151
+ if (!project?.apiKey) return null;
1152
+ if (!context) return null;
1153
+ if (!conversationId) return null;
1154
+ const {
1155
+ status,
1156
+ ...rest
1157
+ } = payload || {};
1158
+ let metadata = undefined;
1159
+ if (Object.keys(rest).length > 0) {
1160
+ metadata = {
1161
+ ...rest
1162
+ };
1163
+ }
1164
+ const body = {
1165
+ conversationId,
1166
+ status,
1167
+ metadata
1168
+ };
1169
+ return updateConversation(project.apiKey, body).then(res => {
1170
+ if (res) setConversation(res);
1171
+ refresh();
1172
+ return res;
1173
+ });
1174
+ }, [project?.apiKey, context, conversationId, refresh]);
1175
+ const closeConversation = useCallback(() => {
1176
+ return updateConversation$1({
1177
+ status: "closed"
1178
+ });
1179
+ }, [updateConversation$1]);
1180
+ useEffect(() => {
1181
+ refresh();
1182
+ }, [refresh]);
1183
+ return {
1184
+ conversation,
1185
+ messages,
1186
+ data: messages,
1187
+ sendMessage: send,
1188
+ send,
1189
+ updateConversation: updateConversation$1,
1190
+ closeConversation,
1191
+ refresh
1192
+ };
1193
+ }
1194
+
1195
+ export { HQProvider, Wrapper as HQWidget, setContext, useConversation, useConversations };