@dloizides/ui-forms 1.22.0 → 1.23.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/CHANGELOG.md +10 -0
- package/dist/index.d.mts +50 -8
- package/dist/index.d.ts +50 -8
- package/dist/index.js +362 -108
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +362 -110
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -550,9 +550,55 @@ var controlStyles = reactNative.StyleSheet.create({
|
|
|
550
550
|
optionText: { fontSize: OPTION_FONT },
|
|
551
551
|
error: { fontSize: ERROR_FONT, marginTop: ERROR_GAP }
|
|
552
552
|
});
|
|
553
|
+
var ACTIVE_WEIGHT = "700";
|
|
554
|
+
var IDLE_WEIGHT = "400";
|
|
555
|
+
var DETAIL_FONT = 12;
|
|
556
|
+
var DETAIL_GAP = 12;
|
|
557
|
+
var STACK_GAP = 2;
|
|
558
|
+
var DETAIL_BESIDE_MIN_MENU_WIDTH = 400;
|
|
559
|
+
var styles7 = reactNative.StyleSheet.create({
|
|
560
|
+
beside: { alignItems: "baseline", flexDirection: "row", gap: DETAIL_GAP, justifyContent: "space-between" },
|
|
561
|
+
stacked: { gap: STACK_GAP },
|
|
562
|
+
shrink: { flexShrink: 1 },
|
|
563
|
+
detail: { flexShrink: 1, fontSize: DETAIL_FONT }
|
|
564
|
+
});
|
|
565
|
+
function optionDomId(testID, value) {
|
|
566
|
+
return `${testID}-option-${value}`.replace(/\s+/g, "_");
|
|
567
|
+
}
|
|
568
|
+
function listboxDomId(testID) {
|
|
569
|
+
return `${testID}-listbox`;
|
|
570
|
+
}
|
|
571
|
+
function isDetailBesideTitle(menuWidth) {
|
|
572
|
+
return menuWidth >= DETAIL_BESIDE_MIN_MENU_WIDTH;
|
|
573
|
+
}
|
|
574
|
+
function OptionRow({ option, isActive, isHighlighted, isListboxRow, menuWidth, hint, colors, testID, onSelect }) {
|
|
575
|
+
const hasDetail = option.detail !== void 0 && option.detail !== "";
|
|
576
|
+
const label = hasDetail ? `${option.label}, ${option.detail}` : option.label;
|
|
577
|
+
const roleProps = isListboxRow ? { role: "option", tabIndex: -1, id: optionDomId(testID, option.value), "aria-selected": isHighlighted } : { accessibilityRole: "menuitem", "aria-selected": isActive };
|
|
578
|
+
const isBold = isActive || isHighlighted;
|
|
579
|
+
const titleColor = isActive ? colors.brand : colors.text;
|
|
580
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
581
|
+
reactNative.Pressable,
|
|
582
|
+
{
|
|
583
|
+
...roleProps,
|
|
584
|
+
accessibilityLabel: label,
|
|
585
|
+
accessibilityHint: hint,
|
|
586
|
+
accessibilityState: { selected: isActive },
|
|
587
|
+
onPress: () => onSelect(option.value),
|
|
588
|
+
style: [controlStyles.option, isHighlighted ? { backgroundColor: colors.border } : null],
|
|
589
|
+
testID: `${testID}-option-${option.value}`,
|
|
590
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: isDetailBesideTitle(menuWidth) ? styles7.beside : styles7.stacked, children: [
|
|
591
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [controlStyles.optionText, styles7.shrink, { color: titleColor, fontWeight: isBold ? ACTIVE_WEIGHT : IDLE_WEIGHT }], children: option.label }),
|
|
592
|
+
hasDetail ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles7.detail, { color: colors.textSecondary ?? colors.text }], children: option.detail }) : null
|
|
593
|
+
] })
|
|
594
|
+
}
|
|
595
|
+
);
|
|
596
|
+
}
|
|
553
597
|
var IS_WEB3 = reactNative.Platform.OS === "web";
|
|
554
598
|
var MENU_PORTAL_Z_INDEX = designTokens.Z_INDEX.popover;
|
|
555
599
|
var MENU_TOP_GAP2 = 4;
|
|
600
|
+
var MENU_MIN_HEIGHT = 96;
|
|
601
|
+
var VIEWPORT_MARGIN = 8;
|
|
556
602
|
function toDomNode(ref) {
|
|
557
603
|
const node = ref.current;
|
|
558
604
|
if (node === null || typeof node.getBoundingClientRect !== "function") return null;
|
|
@@ -565,8 +611,9 @@ function readAnchorRect(ref) {
|
|
|
565
611
|
const r = node.getBoundingClientRect();
|
|
566
612
|
return { top: r.top, left: r.left, width: r.width, bottom: r.bottom };
|
|
567
613
|
}
|
|
568
|
-
function buildPortalPopoverStyle(rect) {
|
|
614
|
+
function buildPortalPopoverStyle(rect, viewportBottom) {
|
|
569
615
|
return {
|
|
616
|
+
...viewportBottom !== void 0 ? { maxHeight: menuMaxHeight(rect.bottom, viewportBottom) } : null,
|
|
570
617
|
// RN's ViewStyle union omits 'fixed', but react-native-web honours it at runtime.
|
|
571
618
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- web-only position value
|
|
572
619
|
position: "fixed",
|
|
@@ -613,10 +660,64 @@ function useAnchorRect(ref, enabled) {
|
|
|
613
660
|
}, [ref, enabled]);
|
|
614
661
|
return IS_WEB3 && enabled ? rect : null;
|
|
615
662
|
}
|
|
663
|
+
function roomUnderAnchor(anchorBottom, viewportBottom) {
|
|
664
|
+
return viewportBottom - anchorBottom - MENU_TOP_GAP2 - VIEWPORT_MARGIN;
|
|
665
|
+
}
|
|
666
|
+
function menuMaxHeight(anchorBottom, viewportBottom) {
|
|
667
|
+
return Math.min(MENU_MAX_HEIGHT, Math.max(MENU_MIN_HEIGHT, roomUnderAnchor(anchorBottom, viewportBottom)));
|
|
668
|
+
}
|
|
669
|
+
function anchorScrollBlock(anchorBottom, viewportBottom) {
|
|
670
|
+
return roomUnderAnchor(anchorBottom, viewportBottom) < MENU_MAX_HEIGHT ? "start" : "nearest";
|
|
671
|
+
}
|
|
672
|
+
function readViewportBottom() {
|
|
673
|
+
const viewport = window.visualViewport ?? null;
|
|
674
|
+
return viewport === null ? window.innerHeight : viewport.offsetTop + viewport.height;
|
|
675
|
+
}
|
|
676
|
+
function useVisualViewportBottom(enabled) {
|
|
677
|
+
const [bottom, setBottom] = React2.useState(null);
|
|
678
|
+
React2.useLayoutEffect(() => {
|
|
679
|
+
if (!IS_WEB3 || !enabled) {
|
|
680
|
+
setBottom(null);
|
|
681
|
+
return void 0;
|
|
682
|
+
}
|
|
683
|
+
const update = () => setBottom(readViewportBottom());
|
|
684
|
+
update();
|
|
685
|
+
const viewport = window.visualViewport ?? null;
|
|
686
|
+
viewport?.addEventListener("resize", update);
|
|
687
|
+
viewport?.addEventListener("scroll", update);
|
|
688
|
+
window.addEventListener("resize", update);
|
|
689
|
+
return () => {
|
|
690
|
+
viewport?.removeEventListener("resize", update);
|
|
691
|
+
viewport?.removeEventListener("scroll", update);
|
|
692
|
+
window.removeEventListener("resize", update);
|
|
693
|
+
};
|
|
694
|
+
}, [enabled]);
|
|
695
|
+
return bottom;
|
|
696
|
+
}
|
|
697
|
+
function scrollNodeIntoView(node, block) {
|
|
698
|
+
if (node !== null && typeof node.scrollIntoView === "function") node.scrollIntoView({ block });
|
|
699
|
+
}
|
|
700
|
+
function scrollAnchorIntoView(ref, marginTop) {
|
|
701
|
+
if (!IS_WEB3) return;
|
|
702
|
+
const node = toDomNode(ref);
|
|
703
|
+
if (node === null) return;
|
|
704
|
+
node.style.scrollMarginTop = `${marginTop}px`;
|
|
705
|
+
scrollNodeIntoView(node, anchorScrollBlock(node.getBoundingClientRect().bottom, readViewportBottom()));
|
|
706
|
+
}
|
|
707
|
+
function useKeepAnchorInRoom(ref, marginTop, enabled) {
|
|
708
|
+
React2.useLayoutEffect(() => {
|
|
709
|
+
if (!IS_WEB3 || !enabled) return void 0;
|
|
710
|
+
const place = () => scrollAnchorIntoView(ref, marginTop);
|
|
711
|
+
place();
|
|
712
|
+
const viewport = window.visualViewport ?? null;
|
|
713
|
+
viewport?.addEventListener("resize", place);
|
|
714
|
+
return () => viewport?.removeEventListener("resize", place);
|
|
715
|
+
}, [ref, marginTop, enabled]);
|
|
716
|
+
}
|
|
616
717
|
var IS_WEB4 = typeof document !== "undefined";
|
|
617
718
|
var ESCAPE_KEY = "Escape";
|
|
618
|
-
var
|
|
619
|
-
var
|
|
719
|
+
var LISTBOX_ROLE = { role: "listbox" };
|
|
720
|
+
var KEEP_FIELD_FOCUS = { onMouseDown: (event) => event.preventDefault() };
|
|
620
721
|
function useDismiss(anchorRef, menuRef, onDismiss) {
|
|
621
722
|
React2.useEffect(() => {
|
|
622
723
|
if (!IS_WEB4) return void 0;
|
|
@@ -639,6 +740,12 @@ function useDismiss(anchorRef, menuRef, onDismiss) {
|
|
|
639
740
|
};
|
|
640
741
|
}, [anchorRef, menuRef, onDismiss]);
|
|
641
742
|
}
|
|
743
|
+
function useKeepHighlightInView(testID, highlightedValue) {
|
|
744
|
+
React2.useEffect(() => {
|
|
745
|
+
if (!IS_WEB4 || highlightedValue === void 0 || highlightedValue === "") return;
|
|
746
|
+
scrollNodeIntoView(document.getElementById(optionDomId(testID, highlightedValue)), "nearest");
|
|
747
|
+
}, [testID, highlightedValue]);
|
|
748
|
+
}
|
|
642
749
|
function AnchoredMenu({
|
|
643
750
|
options,
|
|
644
751
|
selectedValue,
|
|
@@ -649,38 +756,48 @@ function AnchoredMenu({
|
|
|
649
756
|
accessibilityLabel,
|
|
650
757
|
testID,
|
|
651
758
|
anchorRef,
|
|
652
|
-
usePortal = true
|
|
759
|
+
usePortal = true,
|
|
760
|
+
listbox
|
|
653
761
|
}) {
|
|
654
762
|
const menuRef = React2__default.default.useRef(null);
|
|
655
763
|
useDismiss(anchorRef, menuRef, onDismiss);
|
|
764
|
+
useKeepHighlightInView(testID, listbox?.highlightedValue);
|
|
656
765
|
const rect = useAnchorRect(anchorRef, usePortal);
|
|
657
|
-
const
|
|
658
|
-
const
|
|
766
|
+
const viewportBottom = useVisualViewportBottom(usePortal);
|
|
767
|
+
const portalStyle = rect !== null ? buildPortalPopoverStyle(rect, viewportBottom ?? void 0) : null;
|
|
768
|
+
const { width: windowWidth } = reactNative.useWindowDimensions();
|
|
769
|
+
const menuWidth = rect?.width ?? windowWidth;
|
|
770
|
+
const isListbox = listbox !== void 0;
|
|
771
|
+
const statusText = listbox?.statusText;
|
|
772
|
+
const rows = options.map((option) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
773
|
+
OptionRow,
|
|
774
|
+
{
|
|
775
|
+
colors,
|
|
776
|
+
hint: optionHint,
|
|
777
|
+
isActive: option.value === selectedValue,
|
|
778
|
+
isHighlighted: option.value === listbox?.highlightedValue,
|
|
779
|
+
isListboxRow: isListbox,
|
|
780
|
+
menuWidth,
|
|
781
|
+
option,
|
|
782
|
+
testID,
|
|
783
|
+
onSelect
|
|
784
|
+
},
|
|
785
|
+
option.value
|
|
786
|
+
));
|
|
787
|
+
const listboxBody = options.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { accessibilityLabel, id: listboxDomId(testID), ...LISTBOX_ROLE, testID: listboxDomId(testID), children: rows }) : null;
|
|
788
|
+
const menu = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
659
789
|
reactNative.View,
|
|
660
790
|
{
|
|
791
|
+
...isListbox ? KEEP_FIELD_FOCUS : null,
|
|
661
792
|
ref: menuRef,
|
|
662
|
-
accessibilityLabel,
|
|
663
|
-
accessibilityRole: "menu",
|
|
793
|
+
accessibilityLabel: isListbox ? void 0 : accessibilityLabel,
|
|
794
|
+
accessibilityRole: isListbox ? void 0 : "menu",
|
|
664
795
|
style: [controlStyles.menu, { borderColor: colors.border, backgroundColor: colors.surface }, portalStyle],
|
|
665
796
|
testID: `${testID}-menu`,
|
|
666
|
-
children:
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
{
|
|
671
|
-
accessibilityRole: "menuitem",
|
|
672
|
-
accessibilityLabel: opt.label,
|
|
673
|
-
accessibilityHint: optionHint,
|
|
674
|
-
accessibilityState: { selected: active },
|
|
675
|
-
"aria-selected": active,
|
|
676
|
-
onPress: () => onSelect(opt.value),
|
|
677
|
-
style: controlStyles.option,
|
|
678
|
-
testID: `${testID}-option-${opt.value}`,
|
|
679
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [controlStyles.optionText, { color: active ? colors.brand : colors.text, fontWeight: active ? ACTIVE_WEIGHT : IDLE_WEIGHT }], children: opt.label })
|
|
680
|
-
},
|
|
681
|
-
opt.value
|
|
682
|
-
);
|
|
683
|
-
}) })
|
|
797
|
+
children: [
|
|
798
|
+
isListbox ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { role: "status", style: statusText !== void 0 ? [controlStyles.option, controlStyles.optionText, { color: colors.text }] : void 0, children: statusText ?? "" }) : null,
|
|
799
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.ScrollView, { keyboardShouldPersistTaps: "handled", nestedScrollEnabled: true, children: isListbox ? listboxBody : rows })
|
|
800
|
+
]
|
|
684
801
|
}
|
|
685
802
|
);
|
|
686
803
|
if (usePortal && IS_WEB4) return reactDom.createPortal(menu, document.body);
|
|
@@ -1255,7 +1372,7 @@ function chipIdentity(option, selected, config) {
|
|
|
1255
1372
|
ariaChecked: isRadio ? selected : void 0
|
|
1256
1373
|
};
|
|
1257
1374
|
}
|
|
1258
|
-
var
|
|
1375
|
+
var styles8 = reactNative.StyleSheet.create({
|
|
1259
1376
|
chipContainer: {
|
|
1260
1377
|
flexDirection: "row",
|
|
1261
1378
|
flexWrap: "wrap",
|
|
@@ -1341,7 +1458,7 @@ var ChipSelector = ({
|
|
|
1341
1458
|
reactNative.View,
|
|
1342
1459
|
{
|
|
1343
1460
|
accessibilityRole: isRadioGroup ? "radiogroup" : void 0,
|
|
1344
|
-
style:
|
|
1461
|
+
style: styles8.chipContainer,
|
|
1345
1462
|
...webFieldA11y({ describedById, hasError }),
|
|
1346
1463
|
...radio.groupProps,
|
|
1347
1464
|
children: options.map(renderChip)
|
|
@@ -1351,7 +1468,7 @@ var ChipSelector = ({
|
|
|
1351
1468
|
);
|
|
1352
1469
|
};
|
|
1353
1470
|
var DESCRIPTION_FONT_SIZE2 = 12;
|
|
1354
|
-
var
|
|
1471
|
+
var styles9 = reactNative.StyleSheet.create({
|
|
1355
1472
|
container: {
|
|
1356
1473
|
flexDirection: "row",
|
|
1357
1474
|
justifyContent: "space-between",
|
|
@@ -1412,15 +1529,15 @@ var FormSwitch = ({
|
|
|
1412
1529
|
accessible: false,
|
|
1413
1530
|
disabled,
|
|
1414
1531
|
onPress: toggle,
|
|
1415
|
-
style: [
|
|
1532
|
+
style: [styles9.container, containerStyle],
|
|
1416
1533
|
tabIndex: -1,
|
|
1417
1534
|
testID: `${testID}-row`,
|
|
1418
1535
|
children: [
|
|
1419
|
-
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style:
|
|
1420
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [
|
|
1421
|
-
hasDescription ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [
|
|
1536
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles9.textColumn, children: [
|
|
1537
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles9.label, themeStyles.label], children: label }),
|
|
1538
|
+
hasDescription ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles9.description, themeStyles.description], children: description }) : null
|
|
1422
1539
|
] }),
|
|
1423
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { pointerEvents: "none", style:
|
|
1540
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { pointerEvents: "none", style: styles9.switchSlot, testID: `${testID}-hitbox`, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1424
1541
|
reactNative.Switch,
|
|
1425
1542
|
{
|
|
1426
1543
|
accessibilityHint: accessibilityHint ?? label,
|
|
@@ -1449,7 +1566,7 @@ var DISABLED_OPACITY = 0.5;
|
|
|
1449
1566
|
var FOCUS_RING_WIDTH = 2;
|
|
1450
1567
|
var WEB_NO_DEFAULT_OUTLINE = { outlineStyle: "none" };
|
|
1451
1568
|
var FOCUS_RING_INSET = -6;
|
|
1452
|
-
var
|
|
1569
|
+
var styles10 = reactNative.StyleSheet.create({
|
|
1453
1570
|
container: {
|
|
1454
1571
|
flexDirection: "row",
|
|
1455
1572
|
alignItems: "flex-start",
|
|
@@ -1554,8 +1671,8 @@ var FormCheckbox = ({
|
|
|
1554
1671
|
onPress: toggle,
|
|
1555
1672
|
role: "checkbox",
|
|
1556
1673
|
style: [
|
|
1557
|
-
|
|
1558
|
-
hasHint ? null :
|
|
1674
|
+
styles10.container,
|
|
1675
|
+
hasHint ? null : styles10.centered,
|
|
1559
1676
|
containerStyle,
|
|
1560
1677
|
disabled ? { opacity: DISABLED_OPACITY } : null,
|
|
1561
1678
|
reactNative.Platform.OS === "web" ? WEB_NO_DEFAULT_OUTLINE : null
|
|
@@ -1563,13 +1680,13 @@ var FormCheckbox = ({
|
|
|
1563
1680
|
testID,
|
|
1564
1681
|
...keyboardProps,
|
|
1565
1682
|
children: [
|
|
1566
|
-
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [
|
|
1567
|
-
focused ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { pointerEvents: "none", style: [
|
|
1568
|
-
value ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [
|
|
1683
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles10.box, value ? themeStyles.boxOn : themeStyles.boxOff], testID: `${testID}-box`, children: [
|
|
1684
|
+
focused ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { pointerEvents: "none", style: [styles10.focusRing, themeStyles.ring], testID: `${testID}-focus-ring` }) : null,
|
|
1685
|
+
value ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles10.check, { color: colors.surface }], accessibilityElementsHidden: true, children: "\u2713" }) : null
|
|
1569
1686
|
] }),
|
|
1570
|
-
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style:
|
|
1571
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [
|
|
1572
|
-
hasHint ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { nativeID: hintId, style: [
|
|
1687
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles10.textColumn, children: [
|
|
1688
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles10.label, themeStyles.label], children: label }),
|
|
1689
|
+
hasHint ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { nativeID: hintId, style: [styles10.hint, themeStyles.hint], children: hintText }) : null
|
|
1573
1690
|
] })
|
|
1574
1691
|
]
|
|
1575
1692
|
}
|
|
@@ -1676,94 +1793,212 @@ function isUnmatched(options, text) {
|
|
|
1676
1793
|
if (needle === "") return false;
|
|
1677
1794
|
return !options.some((o) => o.value.toLowerCase() === needle || o.label.toLowerCase() === needle);
|
|
1678
1795
|
}
|
|
1679
|
-
var
|
|
1680
|
-
var
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1796
|
+
var DEFAULT_TYPEAHEAD_DEBOUNCE_MS = 250;
|
|
1797
|
+
var IDLE = { results: [], isLoading: false, hasFailed: false, hasSettled: false };
|
|
1798
|
+
function useTypeaheadSearch(load, query, enabled, debounceMs) {
|
|
1799
|
+
const [state, setState] = React2.useState(IDLE);
|
|
1800
|
+
const loadRef = React2.useRef(load);
|
|
1801
|
+
loadRef.current = load;
|
|
1802
|
+
React2.useEffect(() => {
|
|
1803
|
+
if (!enabled) {
|
|
1804
|
+
setState(IDLE);
|
|
1805
|
+
return void 0;
|
|
1806
|
+
}
|
|
1807
|
+
setState((current) => ({ ...current, isLoading: true, hasFailed: false }));
|
|
1808
|
+
const controller = new AbortController();
|
|
1809
|
+
const settle = (next) => {
|
|
1810
|
+
if (!controller.signal.aborted) setState(next);
|
|
1811
|
+
};
|
|
1812
|
+
const timer = setTimeout(() => {
|
|
1813
|
+
Promise.resolve().then(() => loadRef.current?.(query, controller.signal) ?? []).then(
|
|
1814
|
+
(results) => settle({ results, isLoading: false, hasFailed: false, hasSettled: true }),
|
|
1815
|
+
() => settle({ results: [], isLoading: false, hasFailed: true, hasSettled: true })
|
|
1816
|
+
);
|
|
1817
|
+
}, debounceMs);
|
|
1818
|
+
return () => {
|
|
1819
|
+
clearTimeout(timer);
|
|
1820
|
+
controller.abort();
|
|
1821
|
+
};
|
|
1822
|
+
}, [query, enabled, debounceMs]);
|
|
1823
|
+
return state;
|
|
1824
|
+
}
|
|
1825
|
+
|
|
1826
|
+
// src/TypeaheadControl/hooks/useTypeaheadState.ts
|
|
1827
|
+
var NO_HIGHLIGHT = -1;
|
|
1828
|
+
var FORWARD = 1;
|
|
1829
|
+
var BACKWARD = -1;
|
|
1830
|
+
var NO_ROWS = [];
|
|
1831
|
+
function nextHighlight(current, count, delta) {
|
|
1832
|
+
if (count === 0) return NO_HIGHLIGHT;
|
|
1833
|
+
if (current === NO_HIGHLIGHT) return delta > 0 ? 0 : count - 1;
|
|
1834
|
+
return (current + delta + count) % count;
|
|
1835
|
+
}
|
|
1836
|
+
function searchStatusText(found, search) {
|
|
1837
|
+
if (found.hasFailed) return search.errorText;
|
|
1838
|
+
if (found.results.length > 0) return void 0;
|
|
1839
|
+
if (found.isLoading) return search.loadingText;
|
|
1840
|
+
return found.hasSettled ? search.emptyText : void 0;
|
|
1841
|
+
}
|
|
1842
|
+
function useTypeaheadRows(input, isOpen, isPicked) {
|
|
1843
|
+
const { options, search, value, minChars, maxSuggestions } = input;
|
|
1844
|
+
const query = value.trim();
|
|
1845
|
+
const isSearching = search !== void 0 && isOpen && !isPicked && query.length >= minChars;
|
|
1846
|
+
const found = useTypeaheadSearch(search?.load, query, isSearching, search?.debounceMs ?? DEFAULT_TYPEAHEAD_DEBOUNCE_MS);
|
|
1847
|
+
const staticRows = React2.useMemo(() => {
|
|
1848
|
+
if (options === void 0 || options.some((o) => o.label === value)) return NO_ROWS;
|
|
1849
|
+
return suggestOptions(options, value, minChars, maxSuggestions);
|
|
1850
|
+
}, [options, value, minChars, maxSuggestions]);
|
|
1851
|
+
const foundRows = React2.useMemo(() => found.results.slice(0, maxSuggestions), [found.results, maxSuggestions]);
|
|
1852
|
+
if (search === void 0) return { rows: staticRows, statusText: void 0 };
|
|
1853
|
+
return { rows: foundRows, statusText: searchStatusText(found, search) };
|
|
1854
|
+
}
|
|
1855
|
+
function useTypeaheadState(input) {
|
|
1856
|
+
const { search, value, onChange, onSubmit } = input;
|
|
1700
1857
|
const [isOpen, setIsOpen] = React2.useState(false);
|
|
1701
|
-
const
|
|
1702
|
-
const
|
|
1703
|
-
|
|
1704
|
-
|
|
1858
|
+
const [picked, setPicked] = React2.useState(null);
|
|
1859
|
+
const [highlightIndex, setHighlightIndex] = React2.useState(NO_HIGHLIGHT);
|
|
1860
|
+
const { rows, statusText } = useTypeaheadRows(input, isOpen, picked !== null && picked.label === value);
|
|
1861
|
+
const rowKey = rows.map((row) => row.value).join("\n");
|
|
1862
|
+
const highlighted = isOpen ? rows[highlightIndex] : void 0;
|
|
1863
|
+
React2.useEffect(() => setHighlightIndex(NO_HIGHLIGHT), [rowKey]);
|
|
1864
|
+
React2.useEffect(() => setPicked((current) => current !== null && current.label !== value ? null : current), [value]);
|
|
1865
|
+
const open = React2.useCallback(() => setIsOpen(true), []);
|
|
1866
|
+
const close = React2.useCallback(() => {
|
|
1867
|
+
setIsOpen(false);
|
|
1868
|
+
setHighlightIndex(NO_HIGHLIGHT);
|
|
1869
|
+
}, []);
|
|
1870
|
+
const pick = React2.useCallback(
|
|
1871
|
+
(option) => {
|
|
1872
|
+
setPicked(option);
|
|
1873
|
+
onChange(option.label);
|
|
1874
|
+
search?.onPick(option);
|
|
1875
|
+
close();
|
|
1876
|
+
},
|
|
1877
|
+
[onChange, search, close]
|
|
1878
|
+
);
|
|
1879
|
+
const selectValue = React2.useCallback(
|
|
1880
|
+
(optionValue) => {
|
|
1881
|
+
const option = rows.find((row) => row.value === optionValue);
|
|
1882
|
+
if (option !== void 0) pick(option);
|
|
1883
|
+
},
|
|
1884
|
+
[rows, pick]
|
|
1705
1885
|
);
|
|
1706
|
-
const showMenu = isOpen && suggestions.length > 0;
|
|
1707
1886
|
const handleChange = React2.useCallback(
|
|
1708
1887
|
(next) => {
|
|
1888
|
+
if (picked !== null) {
|
|
1889
|
+
setPicked(null);
|
|
1890
|
+
search?.onPick(null);
|
|
1891
|
+
}
|
|
1709
1892
|
onChange(next);
|
|
1710
1893
|
setIsOpen(true);
|
|
1894
|
+
setHighlightIndex(NO_HIGHLIGHT);
|
|
1711
1895
|
},
|
|
1712
|
-
[onChange]
|
|
1896
|
+
[picked, search, onChange]
|
|
1713
1897
|
);
|
|
1714
|
-
const
|
|
1715
|
-
(optionValue) => {
|
|
1716
|
-
const opt = options.find((o) => o.value === optionValue);
|
|
1717
|
-
onChange(opt?.label ?? optionValue);
|
|
1718
|
-
setIsOpen(false);
|
|
1719
|
-
},
|
|
1720
|
-
[options, onChange]
|
|
1721
|
-
);
|
|
1722
|
-
const handleBlur = React2.useCallback(() => {
|
|
1723
|
-
setTimeout(() => setIsOpen(false), CLOSE_DELAY_MS2);
|
|
1724
|
-
}, []);
|
|
1898
|
+
const handleKeyPress = useTypeaheadKeys({ rowCount: rows.length, isOpen, highlighted, setIsOpen, setHighlightIndex, close, pick });
|
|
1725
1899
|
const handleSubmit = React2.useCallback(() => {
|
|
1726
|
-
|
|
1900
|
+
if (highlighted !== void 0) {
|
|
1901
|
+
pick(highlighted);
|
|
1902
|
+
return;
|
|
1903
|
+
}
|
|
1904
|
+
close();
|
|
1727
1905
|
onSubmit?.();
|
|
1728
|
-
}, [onSubmit]);
|
|
1906
|
+
}, [highlighted, pick, close, onSubmit]);
|
|
1907
|
+
return { rows, statusText, isOpen, picked, highlighted, open, close, selectValue, handleChange, handleKeyPress, handleSubmit };
|
|
1908
|
+
}
|
|
1909
|
+
function useTypeaheadKeys(input) {
|
|
1910
|
+
const { rowCount, isOpen, highlighted, setIsOpen, setHighlightIndex, close, pick } = input;
|
|
1911
|
+
return React2.useCallback(
|
|
1912
|
+
(event) => {
|
|
1913
|
+
const { key } = event.nativeEvent;
|
|
1914
|
+
if (key === "ArrowDown" || key === "ArrowUp") {
|
|
1915
|
+
event.preventDefault();
|
|
1916
|
+
setIsOpen(true);
|
|
1917
|
+
setHighlightIndex((current) => nextHighlight(current, rowCount, key === "ArrowDown" ? FORWARD : BACKWARD));
|
|
1918
|
+
} else if (key === "Escape" && isOpen) {
|
|
1919
|
+
event.preventDefault();
|
|
1920
|
+
close();
|
|
1921
|
+
} else if (key === "Enter" && highlighted !== void 0) {
|
|
1922
|
+
event.preventDefault();
|
|
1923
|
+
pick(highlighted);
|
|
1924
|
+
}
|
|
1925
|
+
},
|
|
1926
|
+
[rowCount, isOpen, highlighted, setIsOpen, setHighlightIndex, close, pick]
|
|
1927
|
+
);
|
|
1928
|
+
}
|
|
1929
|
+
var CLOSE_DELAY_MS2 = 140;
|
|
1930
|
+
var DEFAULT_TYPEAHEAD_MIN_CHARS = 1;
|
|
1931
|
+
var DEFAULT_TYPEAHEAD_MAX_SUGGESTIONS = 8;
|
|
1932
|
+
function comboboxAria(testID, isExpanded, highlighted) {
|
|
1933
|
+
return {
|
|
1934
|
+
role: "combobox",
|
|
1935
|
+
"aria-autocomplete": "list",
|
|
1936
|
+
"aria-expanded": isExpanded,
|
|
1937
|
+
"aria-controls": isExpanded ? listboxDomId(testID) : void 0,
|
|
1938
|
+
"aria-activedescendant": highlighted !== void 0 ? optionDomId(testID, highlighted.value) : void 0
|
|
1939
|
+
};
|
|
1940
|
+
}
|
|
1941
|
+
function TypeaheadControlImpl(props, ref) {
|
|
1942
|
+
const { value, onChange, onSubmit, placeholder, accessibilityLabel, accessibilityHint, optionHint = "", error, minChars = DEFAULT_TYPEAHEAD_MIN_CHARS, style, testID } = props;
|
|
1943
|
+
const { id, describedById } = props;
|
|
1944
|
+
const search = "search" in props ? props.search : void 0;
|
|
1945
|
+
const options = "options" in props ? props.options : void 0;
|
|
1946
|
+
const maxSuggestions = ("search" in props ? props.search.maxResults : props.maxSuggestions) ?? DEFAULT_TYPEAHEAD_MAX_SUGGESTIONS;
|
|
1947
|
+
const { theme } = uiFeedback.useUi();
|
|
1948
|
+
const { colors, palette } = theme;
|
|
1949
|
+
const anchorRef = React2.useRef(null);
|
|
1950
|
+
const state = useTypeaheadState({ options, search, value, minChars, maxSuggestions, onChange, onSubmit });
|
|
1951
|
+
const showMenu = state.isOpen && (state.rows.length > 0 || state.statusText !== void 0);
|
|
1952
|
+
const isExpanded = state.isOpen && state.rows.length > 0;
|
|
1729
1953
|
const hasError = error !== void 0 && error !== "";
|
|
1954
|
+
useKeepAnchorInRoom(anchorRef, search?.scrollMarginTop ?? 0, search !== void 0 && state.isOpen);
|
|
1730
1955
|
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { ref: anchorRef, style: [controlStyles.anchor, style], children: [
|
|
1731
1956
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1732
1957
|
reactNative.TextInput,
|
|
1733
1958
|
{
|
|
1959
|
+
ref,
|
|
1960
|
+
id,
|
|
1961
|
+
...comboboxAria(testID, isExpanded, state.highlighted),
|
|
1962
|
+
...webFieldA11y({ describedById }),
|
|
1734
1963
|
accessibilityLabel,
|
|
1735
1964
|
accessibilityHint,
|
|
1736
1965
|
autoCapitalize: "none",
|
|
1966
|
+
autoComplete: "off",
|
|
1737
1967
|
autoCorrect: false,
|
|
1968
|
+
blurOnSubmit: search === void 0,
|
|
1738
1969
|
placeholder,
|
|
1739
1970
|
placeholderTextColor: colors.textSecondary,
|
|
1740
1971
|
spellCheck: false,
|
|
1741
1972
|
value,
|
|
1742
|
-
onChangeText: handleChange,
|
|
1743
|
-
onFocus:
|
|
1744
|
-
onBlur:
|
|
1745
|
-
|
|
1973
|
+
onChangeText: state.handleChange,
|
|
1974
|
+
onFocus: state.open,
|
|
1975
|
+
onBlur: () => setTimeout(state.close, CLOSE_DELAY_MS2),
|
|
1976
|
+
onKeyPress: state.handleKeyPress,
|
|
1977
|
+
onSubmitEditing: state.handleSubmit,
|
|
1746
1978
|
style: [controlStyles.input, { borderColor: hasError ? fieldErrorInk(theme) : colors.border, backgroundColor: colors.surface, color: colors.text }],
|
|
1747
|
-
testID: `${testID}-input`
|
|
1979
|
+
testID: search?.inputTestID ?? `${testID}-input`
|
|
1748
1980
|
}
|
|
1749
1981
|
),
|
|
1750
1982
|
showMenu ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1751
1983
|
AnchoredMenu,
|
|
1752
1984
|
{
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1985
|
+
accessibilityLabel,
|
|
1986
|
+
options: state.rows,
|
|
1987
|
+
selectedValue: search !== void 0 ? state.picked?.value ?? "" : value,
|
|
1988
|
+
onSelect: state.selectValue,
|
|
1989
|
+
onDismiss: state.close,
|
|
1990
|
+
colors: { text: colors.text, textSecondary: colors.textSecondary, border: colors.border, surface: colors.surface, brand: palette.primary["500"] },
|
|
1758
1991
|
optionHint,
|
|
1759
1992
|
testID,
|
|
1760
1993
|
anchorRef,
|
|
1994
|
+
listbox: { highlightedValue: state.highlighted?.value ?? "", statusText: state.statusText },
|
|
1761
1995
|
usePortal: true
|
|
1762
1996
|
}
|
|
1763
1997
|
) : null,
|
|
1764
1998
|
hasError ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { role: "alert", style: [controlStyles.error, { color: fieldErrorInk(theme) }], testID: `${testID}-error`, children: error }) : null
|
|
1765
1999
|
] });
|
|
1766
2000
|
}
|
|
2001
|
+
var TypeaheadControl = React2.forwardRef(TypeaheadControlImpl);
|
|
1767
2002
|
var WEB_DATE_PROPS = typeof document !== "undefined" ? { type: "date" } : {};
|
|
1768
2003
|
function DateInput(p) {
|
|
1769
2004
|
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: controlStyles.dateCol, children: [
|
|
@@ -1864,7 +2099,7 @@ var ROW_GAP = 4;
|
|
|
1864
2099
|
var TAB_PADDING = 4;
|
|
1865
2100
|
var INDICATOR_WIDTH = 2;
|
|
1866
2101
|
var TAB_FONT_SIZE = 12;
|
|
1867
|
-
var
|
|
2102
|
+
var styles11 = reactNative.StyleSheet.create({
|
|
1868
2103
|
row: { flexDirection: "row", flexWrap: "nowrap", gap: ROW_GAP },
|
|
1869
2104
|
tab: {
|
|
1870
2105
|
borderBottomWidth: INDICATOR_WIDTH,
|
|
@@ -1904,13 +2139,13 @@ var StepperTab = ({
|
|
|
1904
2139
|
accessibilityRole: "tab",
|
|
1905
2140
|
accessibilityState: { selected },
|
|
1906
2141
|
"aria-selected": selected,
|
|
1907
|
-
style: [
|
|
2142
|
+
style: [styles11.tab, { borderBottomColor: indicator }, ring.ringStyle],
|
|
1908
2143
|
testID,
|
|
1909
2144
|
onBlur: ring.onBlur,
|
|
1910
2145
|
onFocus: ring.onFocus,
|
|
1911
2146
|
onPress: () => onStep(step.key),
|
|
1912
2147
|
...webKeyProps,
|
|
1913
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [
|
|
2148
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles11.text, { color: theme.colors.text }, selected ? styles11.textSelected : void 0], children: step.label })
|
|
1914
2149
|
}
|
|
1915
2150
|
);
|
|
1916
2151
|
};
|
|
@@ -1920,7 +2155,7 @@ var StepperTabs = ({
|
|
|
1920
2155
|
onStep,
|
|
1921
2156
|
stepHint,
|
|
1922
2157
|
testID
|
|
1923
|
-
}) => /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { accessibilityRole: "tablist", style:
|
|
2158
|
+
}) => /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { accessibilityRole: "tablist", style: styles11.row, testID, children: steps.map((step) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1924
2159
|
StepperTab,
|
|
1925
2160
|
{
|
|
1926
2161
|
hint: stepHint,
|
|
@@ -1939,7 +2174,7 @@ function resolveStepNeighbours(steps, current) {
|
|
|
1939
2174
|
return { previous: steps[index - 1] ?? null, next: steps[index + 1] ?? null };
|
|
1940
2175
|
}
|
|
1941
2176
|
var ROW_GAP2 = 8;
|
|
1942
|
-
var
|
|
2177
|
+
var styles12 = reactNative.StyleSheet.create({
|
|
1943
2178
|
cell: { flex: 1, minWidth: 0 },
|
|
1944
2179
|
row: { flexDirection: "row", gap: ROW_GAP2 }
|
|
1945
2180
|
});
|
|
@@ -1951,8 +2186,8 @@ var StepperNav = ({
|
|
|
1951
2186
|
testID
|
|
1952
2187
|
}) => {
|
|
1953
2188
|
const { previous, next } = resolveStepNeighbours(steps, current);
|
|
1954
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style:
|
|
1955
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style:
|
|
2189
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles12.row, testID, children: [
|
|
2190
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles12.cell, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1956
2191
|
uiButtons.Button,
|
|
1957
2192
|
{
|
|
1958
2193
|
fullWidth: true,
|
|
@@ -1968,7 +2203,7 @@ var StepperNav = ({
|
|
|
1968
2203
|
}
|
|
1969
2204
|
}
|
|
1970
2205
|
) }),
|
|
1971
|
-
next === null ? null : /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style:
|
|
2206
|
+
next === null ? null : /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles12.cell, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1972
2207
|
uiButtons.Button,
|
|
1973
2208
|
{
|
|
1974
2209
|
fullWidth: true,
|
|
@@ -1982,12 +2217,29 @@ var StepperNav = ({
|
|
|
1982
2217
|
) })
|
|
1983
2218
|
] });
|
|
1984
2219
|
};
|
|
2220
|
+
var STATUS_FONT = 16;
|
|
2221
|
+
var styles13 = reactNative.StyleSheet.create({
|
|
2222
|
+
line: { fontSize: STATUS_FONT }
|
|
2223
|
+
});
|
|
2224
|
+
function FormStatusLine({ message, testID, style }) {
|
|
2225
|
+
const { theme } = uiFeedback.useUi();
|
|
2226
|
+
if (message === null || message === void 0 || message === "") return null;
|
|
2227
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { role: "alert", style: [styles13.line, { color: theme.colors.text }, style], testID, children: message });
|
|
2228
|
+
}
|
|
2229
|
+
function useFocusFirstInvalid(refs) {
|
|
2230
|
+
const latest = React2.useRef(refs);
|
|
2231
|
+
latest.current = refs;
|
|
2232
|
+
return React2.useCallback((invalid) => {
|
|
2233
|
+
const first = invalid.map((field) => latest.current[field].current).find((node) => node !== null);
|
|
2234
|
+
first?.focus();
|
|
2235
|
+
}, []);
|
|
2236
|
+
}
|
|
1985
2237
|
var DEFAULT_PREVIEW_PX = 48;
|
|
1986
2238
|
var PREVIEW_RADIUS = 8;
|
|
1987
2239
|
var GAP = 8;
|
|
1988
2240
|
var TITLE_FONT_SIZE = 14;
|
|
1989
2241
|
var HELP_FONT_SIZE = 13;
|
|
1990
|
-
var
|
|
2242
|
+
var styles14 = reactNative.StyleSheet.create({
|
|
1991
2243
|
help: { flex: 1, fontSize: HELP_FONT_SIZE },
|
|
1992
2244
|
root: { gap: GAP },
|
|
1993
2245
|
tile: { alignItems: "center", flexDirection: "row", gap: GAP },
|
|
@@ -2009,11 +2261,11 @@ var UploadWithLinkField = ({
|
|
|
2009
2261
|
const url = value ?? "";
|
|
2010
2262
|
const [pasting, setPasting] = React2.useState(url !== "");
|
|
2011
2263
|
const previewBox = { borderRadius: PREVIEW_RADIUS, height: previewSize, width: previewSize };
|
|
2012
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style:
|
|
2013
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [
|
|
2014
|
-
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style:
|
|
2264
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles14.root, children: [
|
|
2265
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles14.title, { color: theme.colors.text }], children: labels.title }),
|
|
2266
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles14.tile, children: [
|
|
2015
2267
|
url === "" ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [previewBox, { backgroundColor: theme.colors.border }] }) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Image, { accessible: false, source: { uri: url }, style: previewBox, testID: `${testID}-preview` }),
|
|
2016
|
-
labels.help === void 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [
|
|
2268
|
+
labels.help === void 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles14.help, { color: theme.colors.text }], children: labels.help })
|
|
2017
2269
|
] }),
|
|
2018
2270
|
uploadControl,
|
|
2019
2271
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2024,12 +2276,12 @@ var UploadWithLinkField = ({
|
|
|
2024
2276
|
accessibilityRole: "button",
|
|
2025
2277
|
accessibilityState: { expanded: pasting },
|
|
2026
2278
|
"aria-expanded": pasting,
|
|
2027
|
-
style: [
|
|
2279
|
+
style: [styles14.toggle, ring.ringStyle],
|
|
2028
2280
|
testID: `${testID}-paste`,
|
|
2029
2281
|
onBlur: ring.onBlur,
|
|
2030
2282
|
onFocus: ring.onFocus,
|
|
2031
2283
|
onPress: () => setPasting(!pasting),
|
|
2032
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [
|
|
2284
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles14.toggleText, { color: theme.colors.text }], children: labels.pasteToggle })
|
|
2033
2285
|
}
|
|
2034
2286
|
),
|
|
2035
2287
|
pasting ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2062,6 +2314,7 @@ exports.FormCheckbox = FormCheckbox;
|
|
|
2062
2314
|
exports.FormField = FormField;
|
|
2063
2315
|
exports.FormGrid = FormGrid;
|
|
2064
2316
|
exports.FormSection = FormSection;
|
|
2317
|
+
exports.FormStatusLine = FormStatusLine;
|
|
2065
2318
|
exports.FormSwitch = FormSwitch;
|
|
2066
2319
|
exports.INLINE_FIELD_ROW_MIN_WIDTH = INLINE_FIELD_ROW_MIN_WIDTH;
|
|
2067
2320
|
exports.InlineFieldRow = InlineFieldRow;
|
|
@@ -2079,6 +2332,7 @@ exports.resolveGroupSelection = resolveGroupSelection;
|
|
|
2079
2332
|
exports.resolveStepNeighbours = resolveStepNeighbours;
|
|
2080
2333
|
exports.suggestOptions = suggestOptions;
|
|
2081
2334
|
exports.toggleGroupSelection = toggleGroupSelection;
|
|
2335
|
+
exports.useFocusFirstInvalid = useFocusFirstInvalid;
|
|
2082
2336
|
exports.useRecentValues = useRecentValues;
|
|
2083
2337
|
exports.useThemedInput = useThemedInput;
|
|
2084
2338
|
//# sourceMappingURL=index.js.map
|