@dloizides/ui-forms 1.13.3 → 1.14.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.
package/dist/index.js CHANGED
@@ -5,8 +5,8 @@ var reactNative = require('react-native');
5
5
  var uiFeedback = require('@dloizides/ui-feedback');
6
6
  var jsxRuntime = require('react/jsx-runtime');
7
7
  var uiButtons = require('@dloizides/ui-buttons');
8
- var a11y = require('@dloizides/a11y');
9
8
  var reactDom = require('react-dom');
9
+ var a11y = require('@dloizides/a11y');
10
10
 
11
11
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
12
12
 
@@ -465,6 +465,142 @@ var controlStyles = reactNative.StyleSheet.create({
465
465
  error: { fontSize: ERROR_FONT, marginTop: ERROR_GAP }
466
466
  });
467
467
  var IS_WEB3 = reactNative.Platform.OS === "web";
468
+ var MENU_PORTAL_Z_INDEX = 1e3;
469
+ var MENU_TOP_GAP2 = 4;
470
+ function toDomNode(ref) {
471
+ const node = ref.current;
472
+ if (node === null || typeof node.getBoundingClientRect !== "function") return null;
473
+ return node;
474
+ }
475
+ function readAnchorRect(ref) {
476
+ if (!IS_WEB3) return null;
477
+ const node = toDomNode(ref);
478
+ if (node === null) return null;
479
+ const r = node.getBoundingClientRect();
480
+ return { top: r.top, left: r.left, width: r.width, bottom: r.bottom };
481
+ }
482
+ function buildPortalPopoverStyle(rect) {
483
+ return {
484
+ // RN's ViewStyle union omits 'fixed', but react-native-web honours it at runtime.
485
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- web-only position value
486
+ position: "fixed",
487
+ top: rect.bottom + MENU_TOP_GAP2,
488
+ left: rect.left,
489
+ width: rect.width,
490
+ zIndex: MENU_PORTAL_Z_INDEX
491
+ };
492
+ }
493
+ function useAnchorRect(ref, enabled) {
494
+ const [rect, setRect] = React2.useState(null);
495
+ React2.useLayoutEffect(() => {
496
+ if (!IS_WEB3 || !enabled) {
497
+ setRect(null);
498
+ return void 0;
499
+ }
500
+ let frame = null;
501
+ let disposed = false;
502
+ const apply = () => {
503
+ frame = null;
504
+ if (disposed) return;
505
+ setRect(readAnchorRect(ref));
506
+ };
507
+ const schedule = () => {
508
+ if (frame !== null) return;
509
+ frame = window.requestAnimationFrame(apply);
510
+ };
511
+ apply();
512
+ document.addEventListener("scroll", schedule, true);
513
+ window.addEventListener("resize", schedule);
514
+ const node = toDomNode(ref);
515
+ const observer = typeof ResizeObserver === "function" ? new ResizeObserver(schedule) : null;
516
+ if (observer !== null) {
517
+ if (node !== null) observer.observe(node);
518
+ observer.observe(document.body);
519
+ }
520
+ return () => {
521
+ disposed = true;
522
+ if (frame !== null) window.cancelAnimationFrame(frame);
523
+ document.removeEventListener("scroll", schedule, true);
524
+ window.removeEventListener("resize", schedule);
525
+ if (observer !== null) observer.disconnect();
526
+ };
527
+ }, [ref, enabled]);
528
+ return IS_WEB3 && enabled ? rect : null;
529
+ }
530
+ var IS_WEB4 = typeof document !== "undefined";
531
+ var ESCAPE_KEY = "Escape";
532
+ var ACTIVE_WEIGHT = "700";
533
+ var IDLE_WEIGHT = "400";
534
+ function useDismiss(anchorRef, menuRef, onDismiss) {
535
+ React2.useEffect(() => {
536
+ if (!IS_WEB4) return void 0;
537
+ const onMouseDown = (event) => {
538
+ const anchorNode = anchorRef.current;
539
+ const menuNode = menuRef.current;
540
+ const target = event.target instanceof Node ? event.target : null;
541
+ const insideAnchor = anchorNode !== null && target !== null && anchorNode.contains(target);
542
+ const insideMenu = menuNode !== null && target !== null && menuNode.contains(target);
543
+ if (!insideAnchor && !insideMenu) onDismiss();
544
+ };
545
+ const onKeyDown = (event) => {
546
+ if (event.key === ESCAPE_KEY) onDismiss();
547
+ };
548
+ document.addEventListener("mousedown", onMouseDown);
549
+ document.addEventListener("keydown", onKeyDown);
550
+ return () => {
551
+ document.removeEventListener("mousedown", onMouseDown);
552
+ document.removeEventListener("keydown", onKeyDown);
553
+ };
554
+ }, [anchorRef, menuRef, onDismiss]);
555
+ }
556
+ function AnchoredMenu({
557
+ options,
558
+ selectedValue,
559
+ onSelect,
560
+ onDismiss,
561
+ colors,
562
+ optionHint,
563
+ accessibilityLabel,
564
+ testID,
565
+ anchorRef,
566
+ usePortal = true
567
+ }) {
568
+ const menuRef = React2__default.default.useRef(null);
569
+ useDismiss(anchorRef, menuRef, onDismiss);
570
+ const rect = useAnchorRect(anchorRef, usePortal);
571
+ const portalStyle = rect !== null ? buildPortalPopoverStyle(rect) : null;
572
+ const menu = /* @__PURE__ */ jsxRuntime.jsx(
573
+ reactNative.View,
574
+ {
575
+ ref: menuRef,
576
+ accessibilityLabel,
577
+ accessibilityRole: "menu",
578
+ style: [controlStyles.menu, { borderColor: colors.border, backgroundColor: colors.surface }, portalStyle],
579
+ testID: `${testID}-menu`,
580
+ children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.ScrollView, { keyboardShouldPersistTaps: "handled", nestedScrollEnabled: true, children: options.map((opt) => {
581
+ const active = opt.value === selectedValue;
582
+ return /* @__PURE__ */ jsxRuntime.jsx(
583
+ reactNative.Pressable,
584
+ {
585
+ accessibilityRole: "menuitem",
586
+ accessibilityLabel: opt.label,
587
+ accessibilityHint: optionHint,
588
+ accessibilityState: { selected: active },
589
+ "aria-selected": active,
590
+ onPress: () => onSelect(opt.value),
591
+ style: controlStyles.option,
592
+ testID: `${testID}-option-${opt.value}`,
593
+ children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [controlStyles.optionText, { color: active ? colors.brand : colors.text, fontWeight: active ? ACTIVE_WEIGHT : IDLE_WEIGHT }], children: opt.label })
594
+ },
595
+ opt.value
596
+ );
597
+ }) })
598
+ }
599
+ );
600
+ if (usePortal && IS_WEB4) return reactDom.createPortal(menu, document.body);
601
+ return menu;
602
+ }
603
+ var IS_WEB5 = reactNative.Platform.OS === "web";
468
604
  var TRANSITION_PROPERTY = "border-color, background-color, box-shadow";
469
605
  var TRANSITION_DURATION = "0.14s";
470
606
  var TRANSITION_TIMING = "ease";
@@ -480,7 +616,7 @@ var GREEN_START = 3;
480
616
  var BLUE_START = 5;
481
617
  var CHANNEL_END_OFFSET = 2;
482
618
  function prefersReducedMotion() {
483
- if (!IS_WEB3 || typeof window === "undefined" || typeof window.matchMedia !== "function") return false;
619
+ if (!IS_WEB5 || typeof window === "undefined" || typeof window.matchMedia !== "function") return false;
484
620
  return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
485
621
  }
486
622
  function withAlpha(color, alpha) {
@@ -523,7 +659,7 @@ function useThemedInput(options = {}) {
523
659
  const borderColor = isFocused ? focusBorder : isHovered ? withAlpha(colors.text, HOVER_BORDER_ALPHA) : restBorder;
524
660
  const backgroundColor = isFocused ? colors.surface : colors.surfaceElevated;
525
661
  const base = { color: colors.text, borderColor, backgroundColor };
526
- if (!IS_WEB3) return base;
662
+ if (!IS_WEB5) return base;
527
663
  const ringColor = hasError ? errorColor : primary;
528
664
  const ring = isFocused ? `0 0 0 ${FOCUS_RING_WIDTH}px ${withAlpha(ringColor, FOCUS_RING_ALPHA)}` : "none";
529
665
  const webStyle = {
@@ -548,7 +684,7 @@ function useThemedInput(options = {}) {
548
684
  ]);
549
685
  const focusBind = React2.useMemo(() => ({ onFocus: handleFocus, onBlur: handleBlur }), [handleFocus, handleBlur]);
550
686
  const hoverBind = React2.useMemo(
551
- () => IS_WEB3 ? { onMouseEnter: handleHoverIn, onMouseLeave: handleHoverOut } : {},
687
+ () => IS_WEB5 ? { onMouseEnter: handleHoverIn, onMouseLeave: handleHoverOut } : {},
552
688
  [handleHoverIn, handleHoverOut]
553
689
  );
554
690
  return {
@@ -560,9 +696,9 @@ function useThemedInput(options = {}) {
560
696
  hoverBind
561
697
  };
562
698
  }
563
- var IS_WEB4 = reactNative.Platform.OS === "web";
699
+ var IS_WEB6 = reactNative.Platform.OS === "web";
564
700
  function webFieldA11y({ describedById, hasError = false, required = false }) {
565
- if (!IS_WEB4) {
701
+ if (!IS_WEB6) {
566
702
  return {};
567
703
  }
568
704
  return {
@@ -612,12 +748,187 @@ var ThemedTextInput = React2__default.default.forwardRef(function ThemedTextInpu
612
748
  }
613
749
  );
614
750
  });
751
+
752
+ // src/useRecentValues/recentValuesCore.ts
753
+ var STORAGE_PREFIX = "@dloizides/ui-forms:recent:";
754
+ var DEFAULT_MAX_RECENTS = 10;
755
+ function recentStorageKey(key) {
756
+ return `${STORAGE_PREFIX}${key}`;
757
+ }
758
+ function getStorage() {
759
+ try {
760
+ if (typeof window === "undefined") return null;
761
+ const storage = window.localStorage;
762
+ return storage !== null && storage !== void 0 ? storage : null;
763
+ } catch {
764
+ return null;
765
+ }
766
+ }
767
+ function readRecents(key) {
768
+ const storage = getStorage();
769
+ if (storage === null) return [];
770
+ try {
771
+ const raw = storage.getItem(recentStorageKey(key));
772
+ if (raw === null) return [];
773
+ const parsed = JSON.parse(raw);
774
+ if (!Array.isArray(parsed)) return [];
775
+ return parsed.filter((entry) => typeof entry === "string");
776
+ } catch {
777
+ return [];
778
+ }
779
+ }
780
+ function writeRecents(key, values) {
781
+ const storage = getStorage();
782
+ if (storage === null) return;
783
+ try {
784
+ storage.setItem(recentStorageKey(key), JSON.stringify(values));
785
+ } catch {
786
+ }
787
+ }
788
+ function clearRecents(key) {
789
+ const storage = getStorage();
790
+ if (storage === null) return;
791
+ try {
792
+ storage.removeItem(recentStorageKey(key));
793
+ } catch {
794
+ }
795
+ }
796
+ function computeNextRecents(current, value, max) {
797
+ const trimmed = value.trim();
798
+ if (trimmed === "") return [...current];
799
+ const lower = trimmed.toLowerCase();
800
+ const withoutMatch = current.filter((entry) => entry.toLowerCase() !== lower);
801
+ const promoted = [trimmed, ...withoutMatch];
802
+ const cap = max > 0 ? max : 0;
803
+ return promoted.slice(0, cap);
804
+ }
805
+ function recentsEqual(a, b) {
806
+ if (a.length !== b.length) return false;
807
+ return a.every((entry, index) => entry === b[index]);
808
+ }
809
+
810
+ // src/useRecentValues/useRecentValues.ts
811
+ function useRecentValues(key, max = DEFAULT_MAX_RECENTS) {
812
+ const [recents, setRecents] = React2.useState(() => readRecents(key).slice(0, max));
813
+ React2.useEffect(() => {
814
+ setRecents(readRecents(key).slice(0, max));
815
+ }, [key, max]);
816
+ const remember = React2.useCallback(
817
+ (value) => {
818
+ setRecents((current) => {
819
+ const next = computeNextRecents(current, value, max);
820
+ if (recentsEqual(next, current)) return current;
821
+ writeRecents(key, next);
822
+ return next;
823
+ });
824
+ },
825
+ [key, max]
826
+ );
827
+ const clear = React2.useCallback(() => {
828
+ clearRecents(key);
829
+ setRecents([]);
830
+ }, [key]);
831
+ return { recents, remember, clear };
832
+ }
833
+ var CLOSE_DELAY_MS = 140;
834
+ function RecentInputField({
835
+ recentKey,
836
+ recentMax,
837
+ label,
838
+ value,
839
+ testID,
840
+ onChangeText,
841
+ onSubmitEditing,
842
+ onFocus,
843
+ onBlur,
844
+ ...rest
845
+ }) {
846
+ const { theme } = uiFeedback.useUi();
847
+ const { colors, palette } = theme;
848
+ const { recents, remember } = useRecentValues(recentKey, recentMax);
849
+ const anchorRef = React2.useRef(null);
850
+ const latestText = React2.useRef(typeof value === "string" ? value : "");
851
+ const [isOpen, setIsOpen] = React2.useState(false);
852
+ const handleChange = React2.useCallback(
853
+ (text) => {
854
+ latestText.current = text;
855
+ onChangeText?.(text);
856
+ },
857
+ [onChangeText]
858
+ );
859
+ const handleFocus = React2.useCallback(
860
+ (event) => {
861
+ setIsOpen(true);
862
+ onFocus?.(event);
863
+ },
864
+ [onFocus]
865
+ );
866
+ const handleBlur = React2.useCallback(
867
+ (event) => {
868
+ if (latestText.current.trim() !== "") remember(latestText.current);
869
+ setTimeout(() => setIsOpen(false), CLOSE_DELAY_MS);
870
+ onBlur?.(event);
871
+ },
872
+ [remember, onBlur]
873
+ );
874
+ const handleSubmit = React2.useCallback(
875
+ (event) => {
876
+ remember(latestText.current);
877
+ setIsOpen(false);
878
+ onSubmitEditing?.(event);
879
+ },
880
+ [remember, onSubmitEditing]
881
+ );
882
+ const pick = React2.useCallback(
883
+ (picked) => {
884
+ latestText.current = picked;
885
+ onChangeText?.(picked);
886
+ remember(picked);
887
+ setIsOpen(false);
888
+ },
889
+ [onChangeText, remember]
890
+ );
891
+ const options = recents.map((entry) => ({ label: entry, value: entry }));
892
+ const showMenu = isOpen && options.length > 0;
893
+ const recentTestID = testID !== void 0 ? `${testID}-recent` : "form-field-recent";
894
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { ref: anchorRef, style: controlStyles.anchor, children: [
895
+ /* @__PURE__ */ jsxRuntime.jsx(
896
+ ThemedTextInput,
897
+ {
898
+ ...rest,
899
+ testID,
900
+ value,
901
+ onChangeText: handleChange,
902
+ onFocus: handleFocus,
903
+ onBlur: handleBlur,
904
+ onSubmitEditing: handleSubmit
905
+ }
906
+ ),
907
+ showMenu ? /* @__PURE__ */ jsxRuntime.jsx(
908
+ AnchoredMenu,
909
+ {
910
+ accessibilityLabel: `Recent ${label} values`,
911
+ anchorRef,
912
+ colors: { text: colors.text, border: colors.border, surface: colors.surface, brand: palette.primary["500"] },
913
+ onDismiss: () => setIsOpen(false),
914
+ onSelect: pick,
915
+ optionHint: `Fill ${label} with this recent value`,
916
+ options,
917
+ selectedValue: typeof value === "string" ? value : "",
918
+ testID: recentTestID,
919
+ usePortal: true
920
+ }
921
+ ) : null
922
+ ] });
923
+ }
615
924
  var FormField = ({
616
925
  label,
617
926
  labelHidden = false,
618
927
  required = false,
619
928
  error,
620
929
  containerStyle,
930
+ recentKey,
931
+ recentMax,
621
932
  ...textInputProps
622
933
  }) => /* @__PURE__ */ jsxRuntime.jsx(
623
934
  Field,
@@ -626,9 +937,8 @@ var FormField = ({
626
937
  error,
627
938
  label: labelHidden ? void 0 : label,
628
939
  required,
629
- children: ({ describedById, hasError, controlId }) => /* @__PURE__ */ jsxRuntime.jsx(
630
- ThemedTextInput,
631
- {
940
+ children: ({ describedById, hasError, controlId }) => {
941
+ const inputProps = {
632
942
  accessibilityHint: `Enter ${label}`,
633
943
  accessibilityLabel: label,
634
944
  describedById,
@@ -637,8 +947,9 @@ var FormField = ({
637
947
  requiredField: required,
638
948
  testID: "form-field-input",
639
949
  ...textInputProps
640
- }
641
- )
950
+ };
951
+ return recentKey !== void 0 && recentKey !== "" ? /* @__PURE__ */ jsxRuntime.jsx(RecentInputField, { label, recentKey, recentMax, ...inputProps }) : /* @__PURE__ */ jsxRuntime.jsx(ThemedTextInput, { ...inputProps });
952
+ }
642
953
  }
643
954
  );
644
955
  var TRANSPARENT_COLOR = "transparent";
@@ -1009,140 +1320,6 @@ var FormCheckbox = ({
1009
1320
  }
1010
1321
  );
1011
1322
  };
1012
- var IS_WEB5 = reactNative.Platform.OS === "web";
1013
- var MENU_PORTAL_Z_INDEX = 1e3;
1014
- var MENU_TOP_GAP2 = 4;
1015
- function toDomNode(ref) {
1016
- const node = ref.current;
1017
- if (node === null || typeof node.getBoundingClientRect !== "function") return null;
1018
- return node;
1019
- }
1020
- function readAnchorRect(ref) {
1021
- if (!IS_WEB5) return null;
1022
- const node = toDomNode(ref);
1023
- if (node === null) return null;
1024
- const r = node.getBoundingClientRect();
1025
- return { top: r.top, left: r.left, width: r.width, bottom: r.bottom };
1026
- }
1027
- function buildPortalPopoverStyle(rect) {
1028
- return {
1029
- // RN's ViewStyle union omits 'fixed', but react-native-web honours it at runtime.
1030
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- web-only position value
1031
- position: "fixed",
1032
- top: rect.bottom + MENU_TOP_GAP2,
1033
- left: rect.left,
1034
- width: rect.width,
1035
- zIndex: MENU_PORTAL_Z_INDEX
1036
- };
1037
- }
1038
- function useAnchorRect(ref, enabled) {
1039
- const [rect, setRect] = React2.useState(null);
1040
- React2.useLayoutEffect(() => {
1041
- if (!IS_WEB5 || !enabled) {
1042
- setRect(null);
1043
- return void 0;
1044
- }
1045
- let frame = null;
1046
- let disposed = false;
1047
- const apply = () => {
1048
- frame = null;
1049
- if (disposed) return;
1050
- setRect(readAnchorRect(ref));
1051
- };
1052
- const schedule = () => {
1053
- if (frame !== null) return;
1054
- frame = window.requestAnimationFrame(apply);
1055
- };
1056
- apply();
1057
- document.addEventListener("scroll", schedule, true);
1058
- window.addEventListener("resize", schedule);
1059
- const node = toDomNode(ref);
1060
- const observer = typeof ResizeObserver === "function" ? new ResizeObserver(schedule) : null;
1061
- if (observer !== null) {
1062
- if (node !== null) observer.observe(node);
1063
- observer.observe(document.body);
1064
- }
1065
- return () => {
1066
- disposed = true;
1067
- if (frame !== null) window.cancelAnimationFrame(frame);
1068
- document.removeEventListener("scroll", schedule, true);
1069
- window.removeEventListener("resize", schedule);
1070
- if (observer !== null) observer.disconnect();
1071
- };
1072
- }, [ref, enabled]);
1073
- return IS_WEB5 && enabled ? rect : null;
1074
- }
1075
- var IS_WEB6 = typeof document !== "undefined";
1076
- var ESCAPE_KEY = "Escape";
1077
- var ACTIVE_WEIGHT = "700";
1078
- var IDLE_WEIGHT = "400";
1079
- function useDismiss(anchorRef, menuRef, onDismiss) {
1080
- React2.useEffect(() => {
1081
- if (!IS_WEB6) return void 0;
1082
- const onMouseDown = (event) => {
1083
- const anchorNode = anchorRef.current;
1084
- const menuNode = menuRef.current;
1085
- const target = event.target instanceof Node ? event.target : null;
1086
- const insideAnchor = anchorNode !== null && target !== null && anchorNode.contains(target);
1087
- const insideMenu = menuNode !== null && target !== null && menuNode.contains(target);
1088
- if (!insideAnchor && !insideMenu) onDismiss();
1089
- };
1090
- const onKeyDown = (event) => {
1091
- if (event.key === ESCAPE_KEY) onDismiss();
1092
- };
1093
- document.addEventListener("mousedown", onMouseDown);
1094
- document.addEventListener("keydown", onKeyDown);
1095
- return () => {
1096
- document.removeEventListener("mousedown", onMouseDown);
1097
- document.removeEventListener("keydown", onKeyDown);
1098
- };
1099
- }, [anchorRef, menuRef, onDismiss]);
1100
- }
1101
- function AnchoredMenu({
1102
- options,
1103
- selectedValue,
1104
- onSelect,
1105
- onDismiss,
1106
- colors,
1107
- optionHint,
1108
- testID,
1109
- anchorRef,
1110
- usePortal = false
1111
- }) {
1112
- const menuRef = React2__default.default.useRef(null);
1113
- useDismiss(anchorRef, menuRef, onDismiss);
1114
- const rect = useAnchorRect(anchorRef, usePortal);
1115
- const portalStyle = rect !== null ? buildPortalPopoverStyle(rect) : null;
1116
- const menu = /* @__PURE__ */ jsxRuntime.jsx(
1117
- reactNative.View,
1118
- {
1119
- ref: menuRef,
1120
- accessibilityRole: "menu",
1121
- style: [controlStyles.menu, { borderColor: colors.border, backgroundColor: colors.surface }, portalStyle],
1122
- testID: `${testID}-menu`,
1123
- children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.ScrollView, { keyboardShouldPersistTaps: "handled", nestedScrollEnabled: true, children: options.map((opt) => {
1124
- const active = opt.value === selectedValue;
1125
- return /* @__PURE__ */ jsxRuntime.jsx(
1126
- reactNative.Pressable,
1127
- {
1128
- accessibilityRole: "menuitem",
1129
- accessibilityLabel: opt.label,
1130
- accessibilityHint: optionHint,
1131
- accessibilityState: { selected: active },
1132
- "aria-selected": active,
1133
- onPress: () => onSelect(opt.value),
1134
- style: controlStyles.option,
1135
- testID: `${testID}-option-${opt.value}`,
1136
- children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [controlStyles.optionText, { color: active ? colors.brand : colors.text, fontWeight: active ? ACTIVE_WEIGHT : IDLE_WEIGHT }], children: opt.label })
1137
- },
1138
- opt.value
1139
- );
1140
- }) })
1141
- }
1142
- );
1143
- if (usePortal && IS_WEB6) return reactDom.createPortal(menu, document.body);
1144
- return menu;
1145
- }
1146
1323
  var CHEVRON_DOWN = "\u25BE";
1147
1324
  var CHEVRON_UP = "\u25B4";
1148
1325
  function SelectControl({
@@ -1244,7 +1421,7 @@ function isUnmatched(options, text) {
1244
1421
  if (needle === "") return false;
1245
1422
  return !options.some((o) => o.value.toLowerCase() === needle || o.label.toLowerCase() === needle);
1246
1423
  }
1247
- var CLOSE_DELAY_MS = 140;
1424
+ var CLOSE_DELAY_MS2 = 140;
1248
1425
  var DEFAULT_TYPEAHEAD_MIN_CHARS = 1;
1249
1426
  var DEFAULT_TYPEAHEAD_MAX_SUGGESTIONS = 8;
1250
1427
  function TypeaheadControl({
@@ -1288,7 +1465,7 @@ function TypeaheadControl({
1288
1465
  [options, onChange]
1289
1466
  );
1290
1467
  const handleBlur = React2.useCallback(() => {
1291
- setTimeout(() => setIsOpen(false), CLOSE_DELAY_MS);
1468
+ setTimeout(() => setIsOpen(false), CLOSE_DELAY_MS2);
1292
1469
  }, []);
1293
1470
  const handleSubmit = React2.useCallback(() => {
1294
1471
  setIsOpen(false);
@@ -1407,6 +1584,7 @@ function DateRangeControl({
1407
1584
 
1408
1585
  exports.AnchoredMenu = AnchoredMenu;
1409
1586
  exports.ChipSelector = ChipSelector;
1587
+ exports.DEFAULT_MAX_RECENTS = DEFAULT_MAX_RECENTS;
1410
1588
  exports.DEFAULT_OPTIONAL_LABEL = DEFAULT_OPTIONAL_LABEL;
1411
1589
  exports.DEFAULT_TYPEAHEAD_MAX_SUGGESTIONS = DEFAULT_TYPEAHEAD_MAX_SUGGESTIONS;
1412
1590
  exports.DEFAULT_TYPEAHEAD_MIN_CHARS = DEFAULT_TYPEAHEAD_MIN_CHARS;
@@ -1425,6 +1603,7 @@ exports.TypeaheadControl = TypeaheadControl;
1425
1603
  exports.controlStyles = controlStyles;
1426
1604
  exports.isUnmatched = isUnmatched;
1427
1605
  exports.suggestOptions = suggestOptions;
1606
+ exports.useRecentValues = useRecentValues;
1428
1607
  exports.useThemedInput = useThemedInput;
1429
1608
  //# sourceMappingURL=index.js.map
1430
1609
  //# sourceMappingURL=index.js.map