@inploi/plugin-chatbot 3.12.6 → 3.13.0

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.
@@ -1,4 +1,4 @@
1
- import { _, g as getHeadOrThrow, i as invariant, A as AbortedError, N, a as getFlowSubmissionsPayload, h as hasProp, k as kbToReadableSize, o as o$1, c as clsx, b as _$1, y, F, s as store, d as a$2, p, e as parse, f as picklist, j as h, l as k, m as isSubmissionOfType, C as Cn, n as parseAsync, V as ValiError, q as object, t as transform, r as maxLength, u as minLength, v as record, w as boolean, x as string, z as email, B as url, D as regex, T, E as cva, G as ERROR_MESSAGES } from "./index-9ff98ab5.js";
1
+ import { _, g as getHeadOrThrow, i as invariant, A as AbortedError, N, a as getFlowSubmissionsPayload, k as kbToReadableSize, h, b as _$1, p, F, o as o$1, c as clsx, y, s as store, d as a$2, e as debounce$1, f as k, j as parse, l as picklist, m as isSubmissionOfType, C as Cn, n as parseAsync, V as ValiError, q as object, t as transform, r as maxLength, u as minLength, v as record, w as boolean, x as string, z as email, B as url, D as regex, E as cva, G as ERROR_MESSAGES } from "./index-767d53bf.js";
2
2
  import "@inploi/sdk";
3
3
  const followNodes = ({
4
4
  node,
@@ -452,197 +452,39 @@ async function interpretQuestionBooleanNode({
452
452
  }
453
453
  next(node.nextId);
454
454
  }
455
- const dummyDivBecauseGoogleRequiresIt = document.createElement("div");
456
- const keyToAddressComponnents = {
457
- line1: ["street_number", "floor", "room", "premise"],
458
- line2: ["subpremise", "street_address", "route"],
459
- line3: ["sublocality", "neighborhood"],
460
- city: ["locality", "postal_town"],
461
- state: ["administrative_area_level_1"],
462
- postcode: ["postal_code"],
463
- country: ["country"]
464
- };
465
- const fieldMapKeys = Object.keys(keyToAddressComponnents);
466
455
  async function interpretQuestionAddressNode({
467
456
  chat,
468
457
  next,
469
- node,
470
- logger
458
+ node
471
459
  }) {
472
- if (fieldMapKeys.every((key) => node.data.keys[key] === null))
473
- return next(node.nextId);
474
- const {
475
- google
476
- } = window;
477
460
  await chat.sendMessage({
478
461
  author: "bot",
479
462
  type: "text",
480
463
  text: node.data.question
481
464
  });
482
- const askForAddress = async (defaultValues) => {
483
- const addressFields = [{
484
- label: "Postcode",
485
- key: node.data.keys.postcode,
486
- optional: false,
487
- defaultValue: defaultValues.postcode
488
- }, {
489
- label: "Line 1",
490
- key: node.data.keys.line1,
491
- optional: false,
492
- defaultValue: defaultValues.line1
493
- }, {
494
- label: "Line 2",
495
- key: node.data.keys.line2,
496
- optional: true,
497
- defaultValue: defaultValues.line2
498
- }, {
499
- label: "Line 3",
500
- key: node.data.keys.line3,
501
- optional: true,
502
- defaultValue: defaultValues.line3
503
- }, {
504
- label: "City",
505
- key: node.data.keys.city,
506
- optional: false,
507
- defaultValue: defaultValues.city
508
- }, {
509
- label: "State/County/Province",
510
- key: node.data.keys.state,
511
- optional: true,
512
- defaultValue: defaultValues.state
513
- }, {
514
- label: "Country",
515
- key: node.data.keys.country,
516
- optional: false,
517
- defaultValue: defaultValues.country
518
- }];
519
- for (const field of addressFields) {
520
- if (field.key === null)
521
- continue;
522
- await chat.sendMessage({
523
- author: "bot",
524
- type: "text",
525
- text: field.label
526
- });
527
- const {
528
- value
529
- } = await chat.userInput({
530
- type: "text",
531
- key: field.key,
532
- config: {
533
- format: "text",
534
- optional: field.optional,
535
- defaultValue: field.defaultValue
536
- }
537
- });
538
- if (value === null) {
539
- await chat.sendMessage({
540
- type: "system",
541
- variant: "info",
542
- text: "Skipped"
543
- });
544
- } else {
545
- await chat.sendMessage({
546
- author: "user",
547
- type: "text",
548
- text: value
549
- });
550
- }
551
- }
552
- };
553
- if (!hasProp(window, "google") || !hasProp(window.google, "maps") || !hasProp(window.google.maps, "places")) {
554
- logger.warn("Google maps not available, falling back to manual input.");
555
- logger.info("If you’d like to use the address autocomplete, please insert the google maps API snippet in your website and make sure it has access to the *places* library.");
556
- await askForAddress({});
557
- return next(node.nextId);
558
- }
559
- const autocomplete = new google.maps.places.AutocompleteService();
560
- const places = new google.maps.places.PlacesService(dummyDivBecauseGoogleRequiresIt);
561
- const {
562
- value: search
563
- } = await chat.userInput({
564
- type: "text",
565
- key: "_internal-address-search",
566
- config: {
567
- format: "text",
568
- optional: false,
569
- placeholder: "Search for your address"
570
- }
571
- });
572
- if (search === null)
573
- return next(node.id);
574
- await chat.sendMessage({
575
- author: "user",
576
- type: "text",
577
- text: `Search for “${search}”`
578
- });
579
- const {
580
- predictions
581
- } = await autocomplete.getPlacePredictions({
582
- input: search
583
- });
584
- const {
585
- value: [selected]
586
- } = await chat.userInput({
587
- type: "multiple-choice",
588
- key: void 0,
465
+ const response = await chat.userInput({
466
+ type: "address",
467
+ key: node.data.key,
589
468
  config: {
590
- options: predictions.slice(0, 4).map((p2) => ({
591
- label: p2.description,
592
- value: p2.place_id
593
- })).concat({
594
- label: "None of these",
595
- value: "none"
596
- }),
597
- maxSelected: 1,
598
- minSelected: 1
469
+ optional: node.data.optional,
470
+ keys: node.data.keys,
471
+ placeholder: node.data.placeholder
599
472
  }
600
473
  });
601
- if (!selected || selected === "none") {
602
- return next(node.id);
603
- }
604
- const result = await new Promise((resolve, reject) => places.getDetails({
605
- placeId: selected,
606
- fields: ["address_components"]
607
- }, (result2, status) => {
608
- if (status !== google.maps.places.PlacesServiceStatus["OK"])
609
- return reject(status);
610
- if (result2 === null)
611
- return reject("ZERO_RESULTS");
612
- return resolve({
613
- ok: true,
614
- place: result2
615
- });
616
- })).catch(async (e) => {
617
- logger.error("Failed to get address details", e);
618
- return {
619
- ok: false
620
- };
621
- });
622
- if (result.ok === false) {
474
+ if (response.value === null) {
623
475
  await chat.sendMessage({
624
476
  type: "system",
625
- variant: "error",
626
- text: "Failed to get address details"
477
+ variant: "info",
478
+ text: "Skipped"
479
+ });
480
+ } else {
481
+ const addressMessage = Object.values(response.value).filter((line) => line && line.trim().length > 0).join(", ");
482
+ await chat.sendMessage({
483
+ author: "user",
484
+ type: "text",
485
+ text: addressMessage
627
486
  });
628
- await askForAddress({});
629
- return next(node.id);
630
487
  }
631
- const addressComponents = result.place.address_components;
632
- const autoFilledInputs = addressComponents ? fieldMapKeys.reduce((acc, key) => {
633
- const componentTypes = keyToAddressComponnents[key];
634
- const value = addressComponents.filter((component) => component.types.some((type) => componentTypes.includes(type))).map((component) => component.long_name).join(", ");
635
- if (value) {
636
- acc[key] = value;
637
- }
638
- return acc;
639
- }, {}) : {};
640
- await chat.sendMessage({
641
- author: "bot",
642
- type: "text",
643
- text: "Please confirm or adjust your address:"
644
- });
645
- await askForAddress(autoFilledInputs);
646
488
  return next(node.nextId);
647
489
  }
648
490
  async function interpretQuestionFileNode({
@@ -741,7 +583,14 @@ const isIfBlockConditionMet = (ifBlock, submissions) => {
741
583
  answer: {
742
584
  type: "file"
743
585
  }
744
- }, () => false).exhaustive();
586
+ }, () => false).with({
587
+ answer: {
588
+ type: "address",
589
+ value: _.any
590
+ }
591
+ }, () => {
592
+ return false;
593
+ }).exhaustive();
745
594
  };
746
595
  const interpolateString = (str, context) => {
747
596
  const regex2 = /{{\s*([^}]+?)\s*(?:\|\s*([^}]+?)\s*)?}}/g;
@@ -764,6 +613,203 @@ const interpolateString = (str, context) => {
764
613
  }
765
614
  });
766
615
  };
616
+ function getDefaultExportFromCjs(x) {
617
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
618
+ }
619
+ function debounce(func, wait, immediate) {
620
+ var timeout, args, context, timestamp, result;
621
+ if (null == wait)
622
+ wait = 100;
623
+ function later() {
624
+ var last = Date.now() - timestamp;
625
+ if (last < wait && last >= 0) {
626
+ timeout = setTimeout(later, wait - last);
627
+ } else {
628
+ timeout = null;
629
+ if (!immediate) {
630
+ result = func.apply(context, args);
631
+ context = args = null;
632
+ }
633
+ }
634
+ }
635
+ var debounced = function() {
636
+ context = this;
637
+ args = arguments;
638
+ timestamp = Date.now();
639
+ var callNow = immediate && !timeout;
640
+ if (!timeout)
641
+ timeout = setTimeout(later, wait);
642
+ if (callNow) {
643
+ result = func.apply(context, args);
644
+ context = args = null;
645
+ }
646
+ return result;
647
+ };
648
+ debounced.clear = function() {
649
+ if (timeout) {
650
+ clearTimeout(timeout);
651
+ timeout = null;
652
+ }
653
+ };
654
+ debounced.flush = function() {
655
+ if (timeout) {
656
+ result = func.apply(context, args);
657
+ context = args = null;
658
+ clearTimeout(timeout);
659
+ timeout = null;
660
+ }
661
+ };
662
+ return debounced;
663
+ }
664
+ debounce.debounce = debounce;
665
+ var debounce_1 = debounce;
666
+ const createDebounce = /* @__PURE__ */ getDefaultExportFromCjs(debounce_1);
667
+ function useMeasure(_temp) {
668
+ let {
669
+ debounce: debounce2,
670
+ scroll,
671
+ polyfill,
672
+ offsetSize
673
+ } = _temp === void 0 ? {
674
+ debounce: 0,
675
+ scroll: false,
676
+ offsetSize: false
677
+ } : _temp;
678
+ const ResizeObserver = polyfill || (typeof window === "undefined" ? class ResizeObserver {
679
+ } : window.ResizeObserver);
680
+ if (!ResizeObserver) {
681
+ throw new Error("This browser does not support ResizeObserver out of the box. See: https://github.com/react-spring/react-use-measure/#resize-observer-polyfills");
682
+ }
683
+ const [bounds, set2] = h({
684
+ left: 0,
685
+ top: 0,
686
+ width: 0,
687
+ height: 0,
688
+ bottom: 0,
689
+ right: 0,
690
+ x: 0,
691
+ y: 0
692
+ });
693
+ const state = _$1({
694
+ element: null,
695
+ scrollContainers: null,
696
+ resizeObserver: null,
697
+ lastBounds: bounds
698
+ });
699
+ const scrollDebounce = debounce2 ? typeof debounce2 === "number" ? debounce2 : debounce2.scroll : null;
700
+ const resizeDebounce = debounce2 ? typeof debounce2 === "number" ? debounce2 : debounce2.resize : null;
701
+ const mounted = _$1(false);
702
+ p(() => {
703
+ mounted.current = true;
704
+ return () => void (mounted.current = false);
705
+ });
706
+ const [forceRefresh, resizeChange, scrollChange] = F(() => {
707
+ const callback = () => {
708
+ if (!state.current.element)
709
+ return;
710
+ const {
711
+ left,
712
+ top,
713
+ width,
714
+ height,
715
+ bottom,
716
+ right,
717
+ x,
718
+ y: y2
719
+ } = state.current.element.getBoundingClientRect();
720
+ const size = {
721
+ left,
722
+ top,
723
+ width,
724
+ height,
725
+ bottom,
726
+ right,
727
+ x,
728
+ y: y2
729
+ };
730
+ if (state.current.element instanceof HTMLElement && offsetSize) {
731
+ size.height = state.current.element.offsetHeight;
732
+ size.width = state.current.element.offsetWidth;
733
+ }
734
+ Object.freeze(size);
735
+ if (mounted.current && !areBoundsEqual(state.current.lastBounds, size))
736
+ set2(state.current.lastBounds = size);
737
+ };
738
+ return [callback, resizeDebounce ? createDebounce(callback, resizeDebounce) : callback, scrollDebounce ? createDebounce(callback, scrollDebounce) : callback];
739
+ }, [set2, offsetSize, scrollDebounce, resizeDebounce]);
740
+ function removeListeners() {
741
+ if (state.current.scrollContainers) {
742
+ state.current.scrollContainers.forEach((element) => element.removeEventListener("scroll", scrollChange, true));
743
+ state.current.scrollContainers = null;
744
+ }
745
+ if (state.current.resizeObserver) {
746
+ state.current.resizeObserver.disconnect();
747
+ state.current.resizeObserver = null;
748
+ }
749
+ }
750
+ function addListeners() {
751
+ if (!state.current.element)
752
+ return;
753
+ state.current.resizeObserver = new ResizeObserver(scrollChange);
754
+ state.current.resizeObserver.observe(state.current.element);
755
+ if (scroll && state.current.scrollContainers) {
756
+ state.current.scrollContainers.forEach((scrollContainer) => scrollContainer.addEventListener("scroll", scrollChange, {
757
+ capture: true,
758
+ passive: true
759
+ }));
760
+ }
761
+ }
762
+ const ref = (node) => {
763
+ if (!node || node === state.current.element)
764
+ return;
765
+ removeListeners();
766
+ state.current.element = node;
767
+ state.current.scrollContainers = findScrollContainers(node);
768
+ addListeners();
769
+ };
770
+ useOnWindowScroll(scrollChange, Boolean(scroll));
771
+ useOnWindowResize(resizeChange);
772
+ p(() => {
773
+ removeListeners();
774
+ addListeners();
775
+ }, [scroll, scrollChange, resizeChange]);
776
+ p(() => removeListeners, []);
777
+ return [ref, bounds, forceRefresh];
778
+ }
779
+ function useOnWindowResize(onWindowResize) {
780
+ p(() => {
781
+ const cb = onWindowResize;
782
+ window.addEventListener("resize", cb);
783
+ return () => void window.removeEventListener("resize", cb);
784
+ }, [onWindowResize]);
785
+ }
786
+ function useOnWindowScroll(onScroll, enabled) {
787
+ p(() => {
788
+ if (enabled) {
789
+ const cb = onScroll;
790
+ window.addEventListener("scroll", cb, {
791
+ capture: true,
792
+ passive: true
793
+ });
794
+ return () => void window.removeEventListener("scroll", cb, true);
795
+ }
796
+ }, [onScroll, enabled]);
797
+ }
798
+ function findScrollContainers(element) {
799
+ const result = [];
800
+ if (!element || element === document.body)
801
+ return result;
802
+ const {
803
+ overflow,
804
+ overflowX,
805
+ overflowY
806
+ } = window.getComputedStyle(element);
807
+ if ([overflow, overflowX, overflowY].some((prop) => prop === "auto" || prop === "scroll"))
808
+ result.push(element);
809
+ return [...result, ...findScrollContainers(element.parentElement)];
810
+ }
811
+ const keys = ["x", "y", "top", "bottom", "left", "right", "width", "height"];
812
+ const areBoundsEqual = (a2, b) => keys.every((key) => a2[key] === b[key]);
767
813
  const SendButton = ({
768
814
  class: className,
769
815
  ...props
@@ -904,6 +950,341 @@ const SkipButton = ({
904
950
  })]
905
951
  }), "Skip"]
906
952
  });
953
+ const keyToAddressComponents = {
954
+ line1: ["street_number", "floor", "room", "premise"],
955
+ line2: ["subpremise", "street_address", "route"],
956
+ line3: ["sublocality", "neighborhood"],
957
+ city: ["locality", "postal_town"],
958
+ state: ["administrative_area_level_1"],
959
+ postcode: ["postal_code"],
960
+ country: ["country"]
961
+ };
962
+ const fieldMapKeys = Object.keys(keyToAddressComponents);
963
+ const addressComponentsToFields = (addressComponents) => {
964
+ return fieldMapKeys.reduce((acc, key) => {
965
+ const componentTypes = keyToAddressComponents[key];
966
+ const value = addressComponents.filter((component) => component.types.some((type) => componentTypes.includes(type))).map((component) => component.long_name).join(", ");
967
+ if (value) {
968
+ acc[key] = value;
969
+ }
970
+ return acc;
971
+ }, {});
972
+ };
973
+ const dummyDivBecauseGoogleRequiresIt = document.createElement("div");
974
+ const useGooglePlaces = () => {
975
+ return F(() => {
976
+ const {
977
+ google
978
+ } = window;
979
+ if ("google" in window === false || "maps" in google === false || "places" in google.maps === false) {
980
+ return {
981
+ enabled: false
982
+ };
983
+ }
984
+ const autocomplete = new google.maps.places.AutocompleteService();
985
+ const places = new google.maps.places.PlacesService(dummyDivBecauseGoogleRequiresIt);
986
+ return {
987
+ enabled: true,
988
+ getPredictions: async (input) => {
989
+ const {
990
+ predictions
991
+ } = await autocomplete.getPlacePredictions({
992
+ input
993
+ });
994
+ return predictions.map((p2) => ({
995
+ label: p2.description,
996
+ value: p2.place_id
997
+ }));
998
+ },
999
+ getPlaceDetails: async (placeId) => {
1000
+ const result = await new Promise((resolve, reject) => places.getDetails({
1001
+ placeId,
1002
+ fields: ["address_components"]
1003
+ }, (result2, status) => {
1004
+ if (status !== google.maps.places.PlacesServiceStatus["OK"])
1005
+ return reject(status);
1006
+ if (result2 === null)
1007
+ return reject("ZERO_RESULTS");
1008
+ return resolve({
1009
+ ok: true,
1010
+ place: result2
1011
+ });
1012
+ })).catch(async (e) => {
1013
+ console.error("Failed to get address details", e);
1014
+ return {
1015
+ ok: false
1016
+ };
1017
+ });
1018
+ return result;
1019
+ }
1020
+ };
1021
+ }, []);
1022
+ };
1023
+ const BackButton = (props) => {
1024
+ return o$1("button", {
1025
+ type: "button",
1026
+ class: "text-neutral-10 hover:bg-neutral-4 hover:text-neutral-12 hover:border-neutral-5 flex items-center gap-1 rounded-[18px] border border-solid border-transparent px-3 py-1 pl-1.5 text-sm transition-colors",
1027
+ ...props,
1028
+ children: [o$1("svg", {
1029
+ width: "16",
1030
+ height: "16",
1031
+ viewBox: "0 0 16 16",
1032
+ stroke: "currentColor",
1033
+ "stroke-width": "1.5",
1034
+ fill: "none",
1035
+ xmlns: "http://www.w3.org/2000/svg",
1036
+ children: o$1("path", {
1037
+ d: "M10 3L5 8L10 13"
1038
+ })
1039
+ }), o$1("span", {
1040
+ children: "Back"
1041
+ })]
1042
+ });
1043
+ };
1044
+ const optionManual = {
1045
+ label: "Fill in manually",
1046
+ value: ""
1047
+ };
1048
+ const ChatInputAddress = ({
1049
+ input,
1050
+ onSubmitSuccess
1051
+ }) => {
1052
+ const [query, setQuery] = h("");
1053
+ const [addressFields, setAddressFields] = h();
1054
+ const [suggestions, setSuggestions] = h([]);
1055
+ const [placeId, setPlaceId] = h();
1056
+ const {
1057
+ enabled,
1058
+ getPredictions,
1059
+ getPlaceDetails
1060
+ } = useGooglePlaces();
1061
+ const [state, setState] = h(enabled ? "query" : "manual");
1062
+ const debouncedQuery = F(() => debounce$1((query2) => {
1063
+ invariant(enabled, "Query state should not be enabled if Google Places isn't available");
1064
+ setQuery(query2);
1065
+ if (query2 === "") {
1066
+ setSuggestions([]);
1067
+ return;
1068
+ }
1069
+ getPredictions(query2).then((predictions) => {
1070
+ setSuggestions(predictions);
1071
+ });
1072
+ }, 500), [enabled, getPredictions]);
1073
+ p(() => {
1074
+ if (!enabled)
1075
+ return;
1076
+ if (placeId === void 0 || placeId === "")
1077
+ return;
1078
+ getPlaceDetails(placeId).then((result) => {
1079
+ if (!result.ok || !result.place.address_components) {
1080
+ setAddressFields({});
1081
+ return;
1082
+ }
1083
+ const fields = addressComponentsToFields(result.place.address_components);
1084
+ setAddressFields(fields);
1085
+ setState("details");
1086
+ });
1087
+ return () => {
1088
+ setAddressFields(void 0);
1089
+ };
1090
+ }, [placeId, getPlaceDetails, enabled]);
1091
+ switch (state) {
1092
+ case "query": {
1093
+ invariant(enabled, "Query state should not be enabled if Google Places isn't available");
1094
+ return o$1(ChatInputAddressQuery, {
1095
+ input,
1096
+ onSkip: () => onSubmitSuccess(null),
1097
+ onAddressSelect: (e) => {
1098
+ setPlaceId(e);
1099
+ setState("loading");
1100
+ },
1101
+ onInputChange: debouncedQuery,
1102
+ suggestions,
1103
+ query
1104
+ });
1105
+ }
1106
+ case "loading":
1107
+ return o$1(ChatInputAddressDetails, {
1108
+ input,
1109
+ onSubmitSuccess,
1110
+ addressFields: {},
1111
+ actions: o$1(BackButton, {
1112
+ onClick: () => {
1113
+ setPlaceId(void 0);
1114
+ setState("query");
1115
+ }
1116
+ })
1117
+ });
1118
+ case "details":
1119
+ invariant(addressFields !== void 0);
1120
+ return o$1(ChatInputAddressDetails, {
1121
+ input,
1122
+ onSubmitSuccess,
1123
+ addressFields,
1124
+ actions: o$1(BackButton, {
1125
+ onClick: () => {
1126
+ setPlaceId(void 0);
1127
+ setState("query");
1128
+ }
1129
+ })
1130
+ });
1131
+ case "manual":
1132
+ return o$1(ChatInputAddressDetails, {
1133
+ input,
1134
+ onSubmitSuccess,
1135
+ addressFields: {},
1136
+ actions: enabled ? o$1(BackButton, {
1137
+ onClick: () => {
1138
+ setPlaceId(void 0);
1139
+ setState("query");
1140
+ }
1141
+ }) : void 0
1142
+ });
1143
+ }
1144
+ };
1145
+ const ChatInputAddressQuery = ({
1146
+ input,
1147
+ onSkip,
1148
+ suggestions,
1149
+ onAddressSelect,
1150
+ query,
1151
+ onInputChange
1152
+ }) => {
1153
+ const ref = _$1(null);
1154
+ y(() => {
1155
+ if (ref.current) {
1156
+ ref.current.focus();
1157
+ ref.current.select();
1158
+ }
1159
+ }, []);
1160
+ return o$1(k, {
1161
+ children: [o$1("form", {
1162
+ noValidate: true,
1163
+ onSubmit: (e) => {
1164
+ e.preventDefault;
1165
+ },
1166
+ class: "flex flex-col justify-end gap-1 p-2.5",
1167
+ children: [o$1("input", {
1168
+ onChange: (e) => {
1169
+ onInputChange(e.currentTarget.value);
1170
+ },
1171
+ ref,
1172
+ name: "address",
1173
+ id: "chat-address",
1174
+ autocomplete: "on",
1175
+ autoFocus: true,
1176
+ class: "outline-divider ease-expo-out placeholder:text-neutral-10 text-neutral-12 focus-visible:outline-accent-7 caret-accent-9 bg-lowest w-full rounded-full px-3 py-1 text-base outline outline-2 transition-all",
1177
+ placeholder: input.config.placeholder || "Search an address",
1178
+ defaultValue: query
1179
+ }), !input.config.optional && o$1(SkipButton, {
1180
+ class: "absolute right-3",
1181
+ onClick: onSkip
1182
+ })]
1183
+ }), o$1("ul", {
1184
+ children: [suggestions.map((suggestion) => o$1("li", {
1185
+ children: o$1("button", {
1186
+ class: "text-neutral-11 fr hover:bg-neutral-3 hover:text-neutral-12 border-b-neutral-3 flex w-full items-center border border-b border-solid border-transparent px-4 py-3 text-sm transition-colors duration-100",
1187
+ onClick: () => {
1188
+ onAddressSelect(suggestion.value);
1189
+ },
1190
+ children: [o$1("span", {
1191
+ class: "flex-grow",
1192
+ children: suggestion.label
1193
+ }), o$1("svg", {
1194
+ class: "flex-none",
1195
+ width: "16",
1196
+ height: "16",
1197
+ viewBox: "0 0 16 16",
1198
+ stroke: "currentColor",
1199
+ "stroke-width": "1.5",
1200
+ fill: "none",
1201
+ xmlns: "http://www.w3.org/2000/svg",
1202
+ children: o$1("path", {
1203
+ d: "M6 3L11 8L6 13"
1204
+ })
1205
+ })]
1206
+ })
1207
+ }, suggestion.label)), o$1("li", {
1208
+ children: o$1("button", {
1209
+ class: "text-neutral-11 fr hover:bg-neutral-3 hover:text-neutral-12 border-b-neutral-3 flex w-full items-center border border-b border-solid border-transparent px-4 py-3 text-sm transition-colors duration-100",
1210
+ onClick: () => {
1211
+ onAddressSelect(optionManual.value);
1212
+ },
1213
+ children: o$1("span", {
1214
+ class: "flex-grow",
1215
+ children: optionManual.label
1216
+ })
1217
+ })
1218
+ }, optionManual.label)]
1219
+ })]
1220
+ });
1221
+ };
1222
+ const addressKeyToLabel = {
1223
+ line1: "Line 1",
1224
+ line2: "Line 2",
1225
+ line3: "Line 3",
1226
+ city: "City",
1227
+ state: "State",
1228
+ postcode: "Postcode",
1229
+ country: "Country"
1230
+ };
1231
+ const ChatInputAddressDetails = ({
1232
+ addressFields,
1233
+ onSubmitSuccess,
1234
+ actions
1235
+ }) => {
1236
+ const ref = _$1(null);
1237
+ y(() => {
1238
+ if (ref.current) {
1239
+ ref.current.focus();
1240
+ ref.current.select();
1241
+ }
1242
+ }, []);
1243
+ return o$1("form", {
1244
+ class: "bg-neutral-1/90 flex flex-col justify-end gap-2 p-2",
1245
+ onSubmit: (e) => {
1246
+ const formData = new FormData(e.currentTarget);
1247
+ const fields = Object.fromEntries(formData.entries());
1248
+ onSubmitSuccess(fields);
1249
+ },
1250
+ children: [o$1("div", {
1251
+ class: "bg-neutral-3 border-neutral-5 grid items-center gap-1.5 rounded-2xl border pb-2 pl-4 pr-3 pt-3 [grid-template-columns:min-content_1fr]",
1252
+ ref,
1253
+ children: fieldMapKeys.map((key, i2) => {
1254
+ const labelId = `isdk_${key}`;
1255
+ return o$1(k, {
1256
+ children: [o$1("label", {
1257
+ for: labelId,
1258
+ class: "text-neutral-9 [&:has(+*>input:focus)]:text-neutral-11 w-24 pb-2 text-xs uppercase leading-3 tracking-widest transition-colors",
1259
+ children: addressKeyToLabel[key]
1260
+ }), o$1("div", {
1261
+ class: "flex flex-col items-stretch gap-1.5",
1262
+ children: [o$1("input", {
1263
+ autoFocus: i2 === 0 ? true : void 0,
1264
+ class: "text-neutral-12 hover:bg-neutral-4 placeholder:text-neutral-8 focus:bg-neutral-5 flex-1 rounded-lg border-solid bg-transparent px-3 py-1.5 text-base transition-colors focus:outline-none",
1265
+ name: key,
1266
+ id: labelId,
1267
+ defaultValue: addressFields[key],
1268
+ required: true
1269
+ }), i2 !== fieldMapKeys.length - 1 && o$1("hr", {
1270
+ class: "border-b-neutral-5 m-0 w-full border-b border-solid"
1271
+ }), i2 === fieldMapKeys.length - 1 && o$1("hr", {
1272
+ class: "m-0 w-full border-b border-b-transparent"
1273
+ })]
1274
+ })]
1275
+ });
1276
+ })
1277
+ }), o$1("div", {
1278
+ class: "flex w-full flex-1 ",
1279
+ children: [o$1("div", {
1280
+ class: "flex-grow",
1281
+ children: actions
1282
+ }), o$1(SendButton, {
1283
+ class: "flex items-center justify-center"
1284
+ })]
1285
+ })]
1286
+ });
1287
+ };
907
1288
  const useFocusOnMount = () => {
908
1289
  const focusRef = _$1(null);
909
1290
  p(() => {
@@ -917,11 +1298,9 @@ const AnswerSchema = picklist(options);
917
1298
  const FIELD_NAME = "answer";
918
1299
  const ChatInputBoolean = ({
919
1300
  input,
920
- onSubmitSuccess,
921
- onHeightChange
1301
+ onSubmitSuccess
922
1302
  }) => {
923
1303
  const focusRef = useFocusOnMount();
924
- onHeightChange();
925
1304
  return o$1("form", {
926
1305
  noValidate: true,
927
1306
  class: "",
@@ -965,14 +1344,8 @@ const ChatInputBoolean = ({
965
1344
  });
966
1345
  };
967
1346
  const InputError = ({
968
- error,
969
- onAnimationComplete
1347
+ error
970
1348
  }) => {
971
- y(() => {
972
- if (error) {
973
- onAnimationComplete();
974
- }
975
- }, [error, onAnimationComplete]);
976
1349
  if (!error)
977
1350
  return null;
978
1351
  return o$1("div", {
@@ -1074,8 +1447,7 @@ const trimFileName = (fileName, maxLength2) => {
1074
1447
  };
1075
1448
  const ChatInputFile = ({
1076
1449
  input,
1077
- onSubmitSuccess,
1078
- onHeightChange
1450
+ onSubmitSuccess
1079
1451
  }) => {
1080
1452
  var _a;
1081
1453
  const submission = (_a = store.current$.value.flow) == null ? void 0 : _a.data.submissions[input.key];
@@ -1221,7 +1593,6 @@ const ChatInputFile = ({
1221
1593
  })]
1222
1594
  })]
1223
1595
  }), error && o$1(InputError, {
1224
- onAnimationComplete: onHeightChange,
1225
1596
  error
1226
1597
  })]
1227
1598
  });
@@ -1860,7 +2231,7 @@ function createFormControl(props = {}, flushRootRender) {
1860
2231
  const validationModeBeforeSubmit = getValidationModes(_options.mode);
1861
2232
  const validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
1862
2233
  const shouldDisplayAllAssociatedErrors = _options.criteriaMode === VALIDATION_MODE.all;
1863
- const debounce = (callback) => (wait) => {
2234
+ const debounce2 = (callback) => (wait) => {
1864
2235
  clearTimeout(timer);
1865
2236
  timer = setTimeout(callback, wait);
1866
2237
  };
@@ -1954,7 +2325,7 @@ function createFormControl(props = {}, flushRootRender) {
1954
2325
  const previousFieldError = get(_formState.errors, name);
1955
2326
  const shouldUpdateValid = _proxyFormState.isValid && isBoolean(isValid) && _formState.isValid !== isValid;
1956
2327
  if (props.delayError && error) {
1957
- delayErrorCallback = debounce(() => updateErrors(name, error));
2328
+ delayErrorCallback = debounce2(() => updateErrors(name, error));
1958
2329
  delayErrorCallback(props.delayError);
1959
2330
  } else {
1960
2331
  clearTimeout(timer);
@@ -2711,8 +3082,7 @@ const getResolver$1 = (config) => {
2711
3082
  };
2712
3083
  const ChatInputMultipleChoice = ({
2713
3084
  input,
2714
- onSubmitSuccess,
2715
- onHeightChange
3085
+ onSubmitSuccess
2716
3086
  }) => {
2717
3087
  var _a, _b;
2718
3088
  const submission = input.key ? (_a = store.current$.value.flow) == null ? void 0 : _a.data.submissions[input.key] : void 0;
@@ -2788,7 +3158,6 @@ const ChatInputMultipleChoice = ({
2788
3158
  }), o$1("div", {
2789
3159
  class: "px-1",
2790
3160
  children: o$1(InputError, {
2791
- onAnimationComplete: onHeightChange,
2792
3161
  error: (_b = errors2.checked) == null ? void 0 : _b.root
2793
3162
  })
2794
3163
  })]
@@ -2870,8 +3239,7 @@ const getResolver = (config) => {
2870
3239
  };
2871
3240
  const ChatInputText = ({
2872
3241
  input,
2873
- onSubmitSuccess,
2874
- onHeightChange
3242
+ onSubmitSuccess
2875
3243
  }) => {
2876
3244
  var _a;
2877
3245
  const submission = input.key ? (_a = store.current$.value.flow) == null ? void 0 : _a.data.submissions[input.key] : void 0;
@@ -2934,7 +3302,6 @@ const ChatInputText = ({
2934
3302
  })]
2935
3303
  }), o$1(SendButton, {})]
2936
3304
  }), o$1(InputError, {
2937
- onAnimationComplete: onHeightChange,
2938
3305
  error: errors2.text
2939
3306
  })]
2940
3307
  })
@@ -2943,16 +3310,9 @@ const ChatInputText = ({
2943
3310
  const ChatInput = () => {
2944
3311
  var _a;
2945
3312
  const input = (_a = store.current$.value.flow) == null ? void 0 : _a.data.currentInput;
3313
+ const [inputContentRef, bounds] = useMeasure();
2946
3314
  const inputWrapperRef = _$1(null);
2947
- const inputContentRef = _$1(null);
2948
- const updateHeight = T(() => {
2949
- if (inputContentRef.current) {
2950
- store.inputHeight$.value = inputContentRef.current.getBoundingClientRect().height;
2951
- }
2952
- }, []);
2953
- p(() => {
2954
- updateHeight();
2955
- }, [input == null ? void 0 : input.type, updateHeight]);
3315
+ store.inputHeight$.value = bounds.height;
2956
3316
  p(() => {
2957
3317
  const wrapper = inputWrapperRef.current;
2958
3318
  if (!wrapper)
@@ -2972,16 +3332,15 @@ const ChatInput = () => {
2972
3332
  });
2973
3333
  return o$1("div", {
2974
3334
  ref: inputWrapperRef,
3335
+ class: "ease-expo-out absolute bottom-0 w-full overflow-hidden rounded-b-3xl backdrop-blur-xl transition-all duration-700 will-change-[height]",
2975
3336
  style: {
2976
- height: store.inputHeight$.value
3337
+ height: bounds.height
2977
3338
  },
2978
- class: "bg-statusbar ease-expo-out absolute bottom-0 w-full overflow-hidden rounded-b-3xl backdrop-blur-md backdrop-saturate-150 transition-all duration-700",
2979
3339
  children: o$1("div", {
2980
3340
  ref: inputContentRef,
2981
- class: "border-divider border-t",
3341
+ class: "border-divider flex flex-col justify-end border-t",
2982
3342
  children: N({
2983
- input,
2984
- onHeightChange: updateHeight
3343
+ input
2985
3344
  }).with({
2986
3345
  input: _.nullish
2987
3346
  }, () => o$1("div", {
@@ -3031,6 +3390,13 @@ const ChatInput = () => {
3031
3390
  }, (props) => o$1(ChatInputSubmit, {
3032
3391
  onSubmitSuccess: handleSubmitSuccess(props.input.type),
3033
3392
  ...props
3393
+ })).with({
3394
+ input: {
3395
+ type: "address"
3396
+ }
3397
+ }, (props) => o$1(ChatInputAddress, {
3398
+ onSubmitSuccess: handleSubmitSuccess(props.input.type),
3399
+ ...props
3034
3400
  })).exhaustive()
3035
3401
  })
3036
3402
  });