@dloizides/ui-forms 1.22.0 → 1.23.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.
- package/CHANGELOG.md +10 -0
- package/dist/index.d.mts +50 -8
- package/dist/index.d.ts +50 -8
- package/dist/index.js +383 -107
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +383 -109
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -550,9 +550,59 @@ 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 rowInk(colors, isActive, isHighlighted) {
|
|
575
|
+
if (isHighlighted) return { title: colors.surface, detail: colors.surface };
|
|
576
|
+
return { title: isActive ? colors.brand : colors.text, detail: colors.textSecondary ?? colors.text };
|
|
577
|
+
}
|
|
578
|
+
function OptionRow({ option, isActive, isHighlighted, isListboxRow, menuWidth, hint, colors, testID, onSelect }) {
|
|
579
|
+
const hasDetail = option.detail !== void 0 && option.detail !== "";
|
|
580
|
+
const label = hasDetail ? `${option.label}, ${option.detail}` : option.label;
|
|
581
|
+
const roleProps = isListboxRow ? { role: "option", tabIndex: -1, id: optionDomId(testID, option.value), "aria-selected": isHighlighted } : { accessibilityRole: "menuitem", "aria-selected": isActive };
|
|
582
|
+
const isBold = isActive || isHighlighted;
|
|
583
|
+
const ink = rowInk(colors, isActive, isHighlighted);
|
|
584
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
585
|
+
reactNative.Pressable,
|
|
586
|
+
{
|
|
587
|
+
...roleProps,
|
|
588
|
+
accessibilityLabel: label,
|
|
589
|
+
accessibilityHint: hint,
|
|
590
|
+
accessibilityState: { selected: isActive },
|
|
591
|
+
onPress: () => onSelect(option.value),
|
|
592
|
+
style: [controlStyles.option, isHighlighted ? { backgroundColor: colors.text } : null],
|
|
593
|
+
testID: `${testID}-option-${option.value}`,
|
|
594
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: isDetailBesideTitle(menuWidth) ? styles7.beside : styles7.stacked, children: [
|
|
595
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [controlStyles.optionText, styles7.shrink, { color: ink.title, fontWeight: isBold ? ACTIVE_WEIGHT : IDLE_WEIGHT }], children: option.label }),
|
|
596
|
+
hasDetail ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles7.detail, { color: ink.detail }], children: option.detail }) : null
|
|
597
|
+
] })
|
|
598
|
+
}
|
|
599
|
+
);
|
|
600
|
+
}
|
|
553
601
|
var IS_WEB3 = reactNative.Platform.OS === "web";
|
|
554
602
|
var MENU_PORTAL_Z_INDEX = designTokens.Z_INDEX.popover;
|
|
555
603
|
var MENU_TOP_GAP2 = 4;
|
|
604
|
+
var MENU_MIN_HEIGHT = 96;
|
|
605
|
+
var VIEWPORT_MARGIN = 8;
|
|
556
606
|
function toDomNode(ref) {
|
|
557
607
|
const node = ref.current;
|
|
558
608
|
if (node === null || typeof node.getBoundingClientRect !== "function") return null;
|
|
@@ -565,8 +615,9 @@ function readAnchorRect(ref) {
|
|
|
565
615
|
const r = node.getBoundingClientRect();
|
|
566
616
|
return { top: r.top, left: r.left, width: r.width, bottom: r.bottom };
|
|
567
617
|
}
|
|
568
|
-
function buildPortalPopoverStyle(rect) {
|
|
618
|
+
function buildPortalPopoverStyle(rect, viewportBottom) {
|
|
569
619
|
return {
|
|
620
|
+
...viewportBottom !== void 0 ? { maxHeight: menuMaxHeight(rect.bottom, viewportBottom) } : null,
|
|
570
621
|
// RN's ViewStyle union omits 'fixed', but react-native-web honours it at runtime.
|
|
571
622
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- web-only position value
|
|
572
623
|
position: "fixed",
|
|
@@ -613,10 +664,64 @@ function useAnchorRect(ref, enabled) {
|
|
|
613
664
|
}, [ref, enabled]);
|
|
614
665
|
return IS_WEB3 && enabled ? rect : null;
|
|
615
666
|
}
|
|
667
|
+
function roomUnderAnchor(anchorBottom, viewportBottom) {
|
|
668
|
+
return viewportBottom - anchorBottom - MENU_TOP_GAP2 - VIEWPORT_MARGIN;
|
|
669
|
+
}
|
|
670
|
+
function menuMaxHeight(anchorBottom, viewportBottom) {
|
|
671
|
+
return Math.min(MENU_MAX_HEIGHT, Math.max(MENU_MIN_HEIGHT, roomUnderAnchor(anchorBottom, viewportBottom)));
|
|
672
|
+
}
|
|
673
|
+
function anchorScrollBlock(anchorBottom, viewportBottom) {
|
|
674
|
+
return roomUnderAnchor(anchorBottom, viewportBottom) < MENU_MAX_HEIGHT ? "start" : "nearest";
|
|
675
|
+
}
|
|
676
|
+
function readViewportBottom() {
|
|
677
|
+
const viewport = window.visualViewport ?? null;
|
|
678
|
+
return viewport === null ? window.innerHeight : viewport.offsetTop + viewport.height;
|
|
679
|
+
}
|
|
680
|
+
function useVisualViewportBottom(enabled) {
|
|
681
|
+
const [bottom, setBottom] = React2.useState(null);
|
|
682
|
+
React2.useLayoutEffect(() => {
|
|
683
|
+
if (!IS_WEB3 || !enabled) {
|
|
684
|
+
setBottom(null);
|
|
685
|
+
return void 0;
|
|
686
|
+
}
|
|
687
|
+
const update = () => setBottom(readViewportBottom());
|
|
688
|
+
update();
|
|
689
|
+
const viewport = window.visualViewport ?? null;
|
|
690
|
+
viewport?.addEventListener("resize", update);
|
|
691
|
+
viewport?.addEventListener("scroll", update);
|
|
692
|
+
window.addEventListener("resize", update);
|
|
693
|
+
return () => {
|
|
694
|
+
viewport?.removeEventListener("resize", update);
|
|
695
|
+
viewport?.removeEventListener("scroll", update);
|
|
696
|
+
window.removeEventListener("resize", update);
|
|
697
|
+
};
|
|
698
|
+
}, [enabled]);
|
|
699
|
+
return bottom;
|
|
700
|
+
}
|
|
701
|
+
function scrollNodeIntoView(node, block) {
|
|
702
|
+
if (node !== null && typeof node.scrollIntoView === "function") node.scrollIntoView({ block });
|
|
703
|
+
}
|
|
704
|
+
function scrollAnchorIntoView(ref, marginTop) {
|
|
705
|
+
if (!IS_WEB3) return;
|
|
706
|
+
const node = toDomNode(ref);
|
|
707
|
+
if (node === null) return;
|
|
708
|
+
node.style.scrollMarginTop = `${marginTop}px`;
|
|
709
|
+
scrollNodeIntoView(node, anchorScrollBlock(node.getBoundingClientRect().bottom, readViewportBottom()));
|
|
710
|
+
}
|
|
711
|
+
function useKeepAnchorInRoom(ref, marginTop, enabled) {
|
|
712
|
+
React2.useLayoutEffect(() => {
|
|
713
|
+
if (!IS_WEB3 || !enabled) return void 0;
|
|
714
|
+
const place = () => scrollAnchorIntoView(ref, marginTop);
|
|
715
|
+
place();
|
|
716
|
+
const viewport = window.visualViewport ?? null;
|
|
717
|
+
viewport?.addEventListener("resize", place);
|
|
718
|
+
return () => viewport?.removeEventListener("resize", place);
|
|
719
|
+
}, [ref, marginTop, enabled]);
|
|
720
|
+
}
|
|
616
721
|
var IS_WEB4 = typeof document !== "undefined";
|
|
617
722
|
var ESCAPE_KEY = "Escape";
|
|
618
|
-
var
|
|
619
|
-
var
|
|
723
|
+
var LISTBOX_ROLE = { role: "listbox" };
|
|
724
|
+
var KEEP_FIELD_FOCUS = { onMouseDown: (event) => event.preventDefault() };
|
|
620
725
|
function useDismiss(anchorRef, menuRef, onDismiss) {
|
|
621
726
|
React2.useEffect(() => {
|
|
622
727
|
if (!IS_WEB4) return void 0;
|
|
@@ -639,6 +744,12 @@ function useDismiss(anchorRef, menuRef, onDismiss) {
|
|
|
639
744
|
};
|
|
640
745
|
}, [anchorRef, menuRef, onDismiss]);
|
|
641
746
|
}
|
|
747
|
+
function useKeepHighlightInView(testID, highlightedValue) {
|
|
748
|
+
React2.useEffect(() => {
|
|
749
|
+
if (!IS_WEB4 || highlightedValue === void 0 || highlightedValue === "") return;
|
|
750
|
+
scrollNodeIntoView(document.getElementById(optionDomId(testID, highlightedValue)), "nearest");
|
|
751
|
+
}, [testID, highlightedValue]);
|
|
752
|
+
}
|
|
642
753
|
function AnchoredMenu({
|
|
643
754
|
options,
|
|
644
755
|
selectedValue,
|
|
@@ -649,38 +760,48 @@ function AnchoredMenu({
|
|
|
649
760
|
accessibilityLabel,
|
|
650
761
|
testID,
|
|
651
762
|
anchorRef,
|
|
652
|
-
usePortal = true
|
|
763
|
+
usePortal = true,
|
|
764
|
+
listbox
|
|
653
765
|
}) {
|
|
654
766
|
const menuRef = React2__default.default.useRef(null);
|
|
655
767
|
useDismiss(anchorRef, menuRef, onDismiss);
|
|
768
|
+
useKeepHighlightInView(testID, listbox?.highlightedValue);
|
|
656
769
|
const rect = useAnchorRect(anchorRef, usePortal);
|
|
657
|
-
const
|
|
658
|
-
const
|
|
770
|
+
const viewportBottom = useVisualViewportBottom(usePortal);
|
|
771
|
+
const portalStyle = rect !== null ? buildPortalPopoverStyle(rect, viewportBottom ?? void 0) : null;
|
|
772
|
+
const { width: windowWidth } = reactNative.useWindowDimensions();
|
|
773
|
+
const menuWidth = rect?.width ?? windowWidth;
|
|
774
|
+
const isListbox = listbox !== void 0;
|
|
775
|
+
const statusText = listbox?.statusText;
|
|
776
|
+
const rows = options.map((option) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
777
|
+
OptionRow,
|
|
778
|
+
{
|
|
779
|
+
colors,
|
|
780
|
+
hint: optionHint,
|
|
781
|
+
isActive: option.value === selectedValue,
|
|
782
|
+
isHighlighted: option.value === listbox?.highlightedValue,
|
|
783
|
+
isListboxRow: isListbox,
|
|
784
|
+
menuWidth,
|
|
785
|
+
option,
|
|
786
|
+
testID,
|
|
787
|
+
onSelect
|
|
788
|
+
},
|
|
789
|
+
option.value
|
|
790
|
+
));
|
|
791
|
+
const listboxBody = options.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { accessibilityLabel, id: listboxDomId(testID), ...LISTBOX_ROLE, testID: listboxDomId(testID), children: rows }) : null;
|
|
792
|
+
const menu = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
659
793
|
reactNative.View,
|
|
660
794
|
{
|
|
795
|
+
...isListbox ? KEEP_FIELD_FOCUS : null,
|
|
661
796
|
ref: menuRef,
|
|
662
|
-
accessibilityLabel,
|
|
663
|
-
accessibilityRole: "menu",
|
|
797
|
+
accessibilityLabel: isListbox ? void 0 : accessibilityLabel,
|
|
798
|
+
accessibilityRole: isListbox ? void 0 : "menu",
|
|
664
799
|
style: [controlStyles.menu, { borderColor: colors.border, backgroundColor: colors.surface }, portalStyle],
|
|
665
800
|
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
|
-
}) })
|
|
801
|
+
children: [
|
|
802
|
+
isListbox ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { role: "status", style: statusText !== void 0 ? [controlStyles.option, controlStyles.optionText, { color: colors.text }] : void 0, children: statusText ?? "" }) : null,
|
|
803
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.ScrollView, { keyboardShouldPersistTaps: "handled", nestedScrollEnabled: true, children: isListbox ? listboxBody : rows })
|
|
804
|
+
]
|
|
684
805
|
}
|
|
685
806
|
);
|
|
686
807
|
if (usePortal && IS_WEB4) return reactDom.createPortal(menu, document.body);
|
|
@@ -1255,7 +1376,7 @@ function chipIdentity(option, selected, config) {
|
|
|
1255
1376
|
ariaChecked: isRadio ? selected : void 0
|
|
1256
1377
|
};
|
|
1257
1378
|
}
|
|
1258
|
-
var
|
|
1379
|
+
var styles8 = reactNative.StyleSheet.create({
|
|
1259
1380
|
chipContainer: {
|
|
1260
1381
|
flexDirection: "row",
|
|
1261
1382
|
flexWrap: "wrap",
|
|
@@ -1341,7 +1462,7 @@ var ChipSelector = ({
|
|
|
1341
1462
|
reactNative.View,
|
|
1342
1463
|
{
|
|
1343
1464
|
accessibilityRole: isRadioGroup ? "radiogroup" : void 0,
|
|
1344
|
-
style:
|
|
1465
|
+
style: styles8.chipContainer,
|
|
1345
1466
|
...webFieldA11y({ describedById, hasError }),
|
|
1346
1467
|
...radio.groupProps,
|
|
1347
1468
|
children: options.map(renderChip)
|
|
@@ -1351,7 +1472,7 @@ var ChipSelector = ({
|
|
|
1351
1472
|
);
|
|
1352
1473
|
};
|
|
1353
1474
|
var DESCRIPTION_FONT_SIZE2 = 12;
|
|
1354
|
-
var
|
|
1475
|
+
var styles9 = reactNative.StyleSheet.create({
|
|
1355
1476
|
container: {
|
|
1356
1477
|
flexDirection: "row",
|
|
1357
1478
|
justifyContent: "space-between",
|
|
@@ -1412,15 +1533,15 @@ var FormSwitch = ({
|
|
|
1412
1533
|
accessible: false,
|
|
1413
1534
|
disabled,
|
|
1414
1535
|
onPress: toggle,
|
|
1415
|
-
style: [
|
|
1536
|
+
style: [styles9.container, containerStyle],
|
|
1416
1537
|
tabIndex: -1,
|
|
1417
1538
|
testID: `${testID}-row`,
|
|
1418
1539
|
children: [
|
|
1419
|
-
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style:
|
|
1420
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [
|
|
1421
|
-
hasDescription ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [
|
|
1540
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles9.textColumn, children: [
|
|
1541
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles9.label, themeStyles.label], children: label }),
|
|
1542
|
+
hasDescription ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles9.description, themeStyles.description], children: description }) : null
|
|
1422
1543
|
] }),
|
|
1423
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { pointerEvents: "none", style:
|
|
1544
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { pointerEvents: "none", style: styles9.switchSlot, testID: `${testID}-hitbox`, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1424
1545
|
reactNative.Switch,
|
|
1425
1546
|
{
|
|
1426
1547
|
accessibilityHint: accessibilityHint ?? label,
|
|
@@ -1449,7 +1570,7 @@ var DISABLED_OPACITY = 0.5;
|
|
|
1449
1570
|
var FOCUS_RING_WIDTH = 2;
|
|
1450
1571
|
var WEB_NO_DEFAULT_OUTLINE = { outlineStyle: "none" };
|
|
1451
1572
|
var FOCUS_RING_INSET = -6;
|
|
1452
|
-
var
|
|
1573
|
+
var styles10 = reactNative.StyleSheet.create({
|
|
1453
1574
|
container: {
|
|
1454
1575
|
flexDirection: "row",
|
|
1455
1576
|
alignItems: "flex-start",
|
|
@@ -1554,8 +1675,8 @@ var FormCheckbox = ({
|
|
|
1554
1675
|
onPress: toggle,
|
|
1555
1676
|
role: "checkbox",
|
|
1556
1677
|
style: [
|
|
1557
|
-
|
|
1558
|
-
hasHint ? null :
|
|
1678
|
+
styles10.container,
|
|
1679
|
+
hasHint ? null : styles10.centered,
|
|
1559
1680
|
containerStyle,
|
|
1560
1681
|
disabled ? { opacity: DISABLED_OPACITY } : null,
|
|
1561
1682
|
reactNative.Platform.OS === "web" ? WEB_NO_DEFAULT_OUTLINE : null
|
|
@@ -1563,13 +1684,13 @@ var FormCheckbox = ({
|
|
|
1563
1684
|
testID,
|
|
1564
1685
|
...keyboardProps,
|
|
1565
1686
|
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: [
|
|
1687
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles10.box, value ? themeStyles.boxOn : themeStyles.boxOff], testID: `${testID}-box`, children: [
|
|
1688
|
+
focused ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { pointerEvents: "none", style: [styles10.focusRing, themeStyles.ring], testID: `${testID}-focus-ring` }) : null,
|
|
1689
|
+
value ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles10.check, { color: colors.surface }], accessibilityElementsHidden: true, children: "\u2713" }) : null
|
|
1569
1690
|
] }),
|
|
1570
|
-
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style:
|
|
1571
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [
|
|
1572
|
-
hasHint ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { nativeID: hintId, style: [
|
|
1691
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles10.textColumn, children: [
|
|
1692
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles10.label, themeStyles.label], children: label }),
|
|
1693
|
+
hasHint ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { nativeID: hintId, style: [styles10.hint, themeStyles.hint], children: hintText }) : null
|
|
1573
1694
|
] })
|
|
1574
1695
|
]
|
|
1575
1696
|
}
|
|
@@ -1644,6 +1765,24 @@ function SelectControl({
|
|
|
1644
1765
|
) : null
|
|
1645
1766
|
] });
|
|
1646
1767
|
}
|
|
1768
|
+
var CLOSE_DELAY_MS2 = 140;
|
|
1769
|
+
function useDelayedBlurClose(open, close) {
|
|
1770
|
+
const timerRef = React2.useRef(null);
|
|
1771
|
+
const cancelClose = React2.useCallback(() => {
|
|
1772
|
+
if (timerRef.current !== null) clearTimeout(timerRef.current);
|
|
1773
|
+
timerRef.current = null;
|
|
1774
|
+
}, []);
|
|
1775
|
+
React2.useEffect(() => cancelClose, [cancelClose]);
|
|
1776
|
+
const handleFocus = React2.useCallback(() => {
|
|
1777
|
+
cancelClose();
|
|
1778
|
+
open();
|
|
1779
|
+
}, [cancelClose, open]);
|
|
1780
|
+
const handleBlur = React2.useCallback(() => {
|
|
1781
|
+
cancelClose();
|
|
1782
|
+
timerRef.current = setTimeout(close, CLOSE_DELAY_MS2);
|
|
1783
|
+
}, [cancelClose, close]);
|
|
1784
|
+
return { handleFocus, handleBlur };
|
|
1785
|
+
}
|
|
1647
1786
|
|
|
1648
1787
|
// src/controls/suggestOptions.ts
|
|
1649
1788
|
var RANK_VALUE_EXACT = 0;
|
|
@@ -1676,94 +1815,212 @@ function isUnmatched(options, text) {
|
|
|
1676
1815
|
if (needle === "") return false;
|
|
1677
1816
|
return !options.some((o) => o.value.toLowerCase() === needle || o.label.toLowerCase() === needle);
|
|
1678
1817
|
}
|
|
1679
|
-
var
|
|
1680
|
-
var
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1818
|
+
var DEFAULT_TYPEAHEAD_DEBOUNCE_MS = 250;
|
|
1819
|
+
var IDLE = { results: [], isLoading: false, hasFailed: false, hasSettled: false };
|
|
1820
|
+
function useTypeaheadSearch(load, query, enabled, debounceMs) {
|
|
1821
|
+
const [state, setState] = React2.useState(IDLE);
|
|
1822
|
+
const loadRef = React2.useRef(load);
|
|
1823
|
+
loadRef.current = load;
|
|
1824
|
+
React2.useEffect(() => {
|
|
1825
|
+
if (!enabled) {
|
|
1826
|
+
setState(IDLE);
|
|
1827
|
+
return void 0;
|
|
1828
|
+
}
|
|
1829
|
+
setState((current) => ({ ...current, isLoading: true, hasFailed: false }));
|
|
1830
|
+
const controller = new AbortController();
|
|
1831
|
+
const settle = (next) => {
|
|
1832
|
+
if (!controller.signal.aborted) setState(next);
|
|
1833
|
+
};
|
|
1834
|
+
const timer = setTimeout(() => {
|
|
1835
|
+
Promise.resolve().then(() => loadRef.current?.(query, controller.signal) ?? []).then(
|
|
1836
|
+
(results) => settle({ results, isLoading: false, hasFailed: false, hasSettled: true }),
|
|
1837
|
+
() => settle({ results: [], isLoading: false, hasFailed: true, hasSettled: true })
|
|
1838
|
+
);
|
|
1839
|
+
}, debounceMs);
|
|
1840
|
+
return () => {
|
|
1841
|
+
clearTimeout(timer);
|
|
1842
|
+
controller.abort();
|
|
1843
|
+
};
|
|
1844
|
+
}, [query, enabled, debounceMs]);
|
|
1845
|
+
return state;
|
|
1846
|
+
}
|
|
1847
|
+
|
|
1848
|
+
// src/TypeaheadControl/hooks/useTypeaheadState.ts
|
|
1849
|
+
var NO_HIGHLIGHT = -1;
|
|
1850
|
+
var FORWARD = 1;
|
|
1851
|
+
var BACKWARD = -1;
|
|
1852
|
+
var NO_ROWS = [];
|
|
1853
|
+
function nextHighlight(current, count, delta) {
|
|
1854
|
+
if (count === 0) return NO_HIGHLIGHT;
|
|
1855
|
+
if (current === NO_HIGHLIGHT) return delta > 0 ? 0 : count - 1;
|
|
1856
|
+
return (current + delta + count) % count;
|
|
1857
|
+
}
|
|
1858
|
+
function searchStatusText(found, search) {
|
|
1859
|
+
if (found.hasFailed) return search.errorText;
|
|
1860
|
+
if (found.results.length > 0) return void 0;
|
|
1861
|
+
if (found.isLoading) return search.loadingText;
|
|
1862
|
+
return found.hasSettled ? search.emptyText : void 0;
|
|
1863
|
+
}
|
|
1864
|
+
function useTypeaheadRows(input, isOpen, isPicked) {
|
|
1865
|
+
const { options, search, value, minChars, maxSuggestions } = input;
|
|
1866
|
+
const query = value.trim();
|
|
1867
|
+
const isSearching = search !== void 0 && isOpen && !isPicked && query.length >= minChars;
|
|
1868
|
+
const found = useTypeaheadSearch(search?.load, query, isSearching, search?.debounceMs ?? DEFAULT_TYPEAHEAD_DEBOUNCE_MS);
|
|
1869
|
+
const staticRows = React2.useMemo(() => {
|
|
1870
|
+
if (options === void 0 || options.some((o) => o.label === value)) return NO_ROWS;
|
|
1871
|
+
return suggestOptions(options, value, minChars, maxSuggestions);
|
|
1872
|
+
}, [options, value, minChars, maxSuggestions]);
|
|
1873
|
+
const foundRows = React2.useMemo(() => found.results.slice(0, maxSuggestions), [found.results, maxSuggestions]);
|
|
1874
|
+
if (search === void 0) return { rows: staticRows, statusText: void 0 };
|
|
1875
|
+
return { rows: foundRows, statusText: searchStatusText(found, search) };
|
|
1876
|
+
}
|
|
1877
|
+
function useTypeaheadState(input) {
|
|
1878
|
+
const { search, value, onChange, onSubmit } = input;
|
|
1700
1879
|
const [isOpen, setIsOpen] = React2.useState(false);
|
|
1701
|
-
const
|
|
1702
|
-
const
|
|
1703
|
-
|
|
1704
|
-
|
|
1880
|
+
const [picked, setPicked] = React2.useState(null);
|
|
1881
|
+
const [highlightIndex, setHighlightIndex] = React2.useState(NO_HIGHLIGHT);
|
|
1882
|
+
const { rows, statusText } = useTypeaheadRows(input, isOpen, picked !== null && picked.label === value);
|
|
1883
|
+
const rowKey = rows.map((row) => row.value).join("\n");
|
|
1884
|
+
const highlighted = isOpen ? rows[highlightIndex] : void 0;
|
|
1885
|
+
React2.useEffect(() => setHighlightIndex(NO_HIGHLIGHT), [rowKey]);
|
|
1886
|
+
React2.useEffect(() => setPicked((current) => current !== null && current.label !== value ? null : current), [value]);
|
|
1887
|
+
const open = React2.useCallback(() => setIsOpen(true), []);
|
|
1888
|
+
const close = React2.useCallback(() => {
|
|
1889
|
+
setIsOpen(false);
|
|
1890
|
+
setHighlightIndex(NO_HIGHLIGHT);
|
|
1891
|
+
}, []);
|
|
1892
|
+
const pick = React2.useCallback(
|
|
1893
|
+
(option) => {
|
|
1894
|
+
setPicked(option);
|
|
1895
|
+
onChange(option.label);
|
|
1896
|
+
search?.onPick(option);
|
|
1897
|
+
close();
|
|
1898
|
+
},
|
|
1899
|
+
[onChange, search, close]
|
|
1900
|
+
);
|
|
1901
|
+
const selectValue = React2.useCallback(
|
|
1902
|
+
(optionValue) => {
|
|
1903
|
+
const option = rows.find((row) => row.value === optionValue);
|
|
1904
|
+
if (option !== void 0) pick(option);
|
|
1905
|
+
},
|
|
1906
|
+
[rows, pick]
|
|
1705
1907
|
);
|
|
1706
|
-
const showMenu = isOpen && suggestions.length > 0;
|
|
1707
1908
|
const handleChange = React2.useCallback(
|
|
1708
1909
|
(next) => {
|
|
1910
|
+
if (picked !== null) {
|
|
1911
|
+
setPicked(null);
|
|
1912
|
+
search?.onPick(null);
|
|
1913
|
+
}
|
|
1709
1914
|
onChange(next);
|
|
1710
1915
|
setIsOpen(true);
|
|
1916
|
+
setHighlightIndex(NO_HIGHLIGHT);
|
|
1711
1917
|
},
|
|
1712
|
-
[onChange]
|
|
1713
|
-
);
|
|
1714
|
-
const pick = React2.useCallback(
|
|
1715
|
-
(optionValue) => {
|
|
1716
|
-
const opt = options.find((o) => o.value === optionValue);
|
|
1717
|
-
onChange(opt?.label ?? optionValue);
|
|
1718
|
-
setIsOpen(false);
|
|
1719
|
-
},
|
|
1720
|
-
[options, onChange]
|
|
1918
|
+
[picked, search, onChange]
|
|
1721
1919
|
);
|
|
1722
|
-
const
|
|
1723
|
-
setTimeout(() => setIsOpen(false), CLOSE_DELAY_MS2);
|
|
1724
|
-
}, []);
|
|
1920
|
+
const handleKeyPress = useTypeaheadKeys({ rowCount: rows.length, isOpen, highlighted, setIsOpen, setHighlightIndex, close, pick });
|
|
1725
1921
|
const handleSubmit = React2.useCallback(() => {
|
|
1726
|
-
|
|
1922
|
+
if (highlighted !== void 0) {
|
|
1923
|
+
pick(highlighted);
|
|
1924
|
+
return;
|
|
1925
|
+
}
|
|
1926
|
+
close();
|
|
1727
1927
|
onSubmit?.();
|
|
1728
|
-
}, [onSubmit]);
|
|
1928
|
+
}, [highlighted, pick, close, onSubmit]);
|
|
1929
|
+
return { rows, statusText, isOpen, picked, highlighted, open, close, selectValue, handleChange, handleKeyPress, handleSubmit };
|
|
1930
|
+
}
|
|
1931
|
+
function useTypeaheadKeys(input) {
|
|
1932
|
+
const { rowCount, isOpen, highlighted, setIsOpen, setHighlightIndex, close, pick } = input;
|
|
1933
|
+
return React2.useCallback(
|
|
1934
|
+
(event) => {
|
|
1935
|
+
const { key } = event.nativeEvent;
|
|
1936
|
+
if (key === "ArrowDown" || key === "ArrowUp") {
|
|
1937
|
+
event.preventDefault();
|
|
1938
|
+
setIsOpen(true);
|
|
1939
|
+
setHighlightIndex((current) => nextHighlight(current, rowCount, key === "ArrowDown" ? FORWARD : BACKWARD));
|
|
1940
|
+
} else if (key === "Escape" && isOpen) {
|
|
1941
|
+
event.preventDefault();
|
|
1942
|
+
close();
|
|
1943
|
+
} else if (key === "Enter" && highlighted !== void 0) {
|
|
1944
|
+
event.preventDefault();
|
|
1945
|
+
pick(highlighted);
|
|
1946
|
+
}
|
|
1947
|
+
},
|
|
1948
|
+
[rowCount, isOpen, highlighted, setIsOpen, setHighlightIndex, close, pick]
|
|
1949
|
+
);
|
|
1950
|
+
}
|
|
1951
|
+
var DEFAULT_TYPEAHEAD_MIN_CHARS = 1;
|
|
1952
|
+
var DEFAULT_TYPEAHEAD_MAX_SUGGESTIONS = 8;
|
|
1953
|
+
function comboboxAria(testID, isExpanded, highlighted) {
|
|
1954
|
+
return {
|
|
1955
|
+
role: "combobox",
|
|
1956
|
+
"aria-autocomplete": "list",
|
|
1957
|
+
"aria-expanded": isExpanded,
|
|
1958
|
+
"aria-controls": isExpanded ? listboxDomId(testID) : void 0,
|
|
1959
|
+
"aria-activedescendant": highlighted !== void 0 ? optionDomId(testID, highlighted.value) : void 0
|
|
1960
|
+
};
|
|
1961
|
+
}
|
|
1962
|
+
function TypeaheadControlImpl(props, ref) {
|
|
1963
|
+
const { value, onChange, onSubmit, placeholder, accessibilityLabel, accessibilityHint, optionHint = "", error, minChars = DEFAULT_TYPEAHEAD_MIN_CHARS, style, testID } = props;
|
|
1964
|
+
const { id, describedById } = props;
|
|
1965
|
+
const search = "search" in props ? props.search : void 0;
|
|
1966
|
+
const options = "options" in props ? props.options : void 0;
|
|
1967
|
+
const maxSuggestions = ("search" in props ? props.search.maxResults : props.maxSuggestions) ?? DEFAULT_TYPEAHEAD_MAX_SUGGESTIONS;
|
|
1968
|
+
const { theme } = uiFeedback.useUi();
|
|
1969
|
+
const { colors, palette } = theme;
|
|
1970
|
+
const anchorRef = React2.useRef(null);
|
|
1971
|
+
const state = useTypeaheadState({ options, search, value, minChars, maxSuggestions, onChange, onSubmit });
|
|
1972
|
+
const { handleFocus, handleBlur } = useDelayedBlurClose(state.open, state.close);
|
|
1973
|
+
const showMenu = state.isOpen && (state.rows.length > 0 || state.statusText !== void 0);
|
|
1974
|
+
const isExpanded = state.isOpen && state.rows.length > 0;
|
|
1729
1975
|
const hasError = error !== void 0 && error !== "";
|
|
1976
|
+
useKeepAnchorInRoom(anchorRef, search?.scrollMarginTop ?? 0, search !== void 0 && state.isOpen);
|
|
1730
1977
|
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { ref: anchorRef, style: [controlStyles.anchor, style], children: [
|
|
1731
1978
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1732
1979
|
reactNative.TextInput,
|
|
1733
1980
|
{
|
|
1981
|
+
ref,
|
|
1982
|
+
id,
|
|
1983
|
+
...comboboxAria(testID, isExpanded, state.highlighted),
|
|
1984
|
+
...webFieldA11y({ describedById }),
|
|
1734
1985
|
accessibilityLabel,
|
|
1735
1986
|
accessibilityHint,
|
|
1736
1987
|
autoCapitalize: "none",
|
|
1988
|
+
autoComplete: "off",
|
|
1737
1989
|
autoCorrect: false,
|
|
1990
|
+
blurOnSubmit: search === void 0,
|
|
1738
1991
|
placeholder,
|
|
1739
1992
|
placeholderTextColor: colors.textSecondary,
|
|
1740
1993
|
spellCheck: false,
|
|
1741
1994
|
value,
|
|
1742
|
-
onChangeText: handleChange,
|
|
1743
|
-
onFocus:
|
|
1995
|
+
onChangeText: state.handleChange,
|
|
1996
|
+
onFocus: handleFocus,
|
|
1744
1997
|
onBlur: handleBlur,
|
|
1745
|
-
|
|
1998
|
+
onKeyPress: state.handleKeyPress,
|
|
1999
|
+
onSubmitEditing: state.handleSubmit,
|
|
1746
2000
|
style: [controlStyles.input, { borderColor: hasError ? fieldErrorInk(theme) : colors.border, backgroundColor: colors.surface, color: colors.text }],
|
|
1747
|
-
testID: `${testID}-input`
|
|
2001
|
+
testID: search?.inputTestID ?? `${testID}-input`
|
|
1748
2002
|
}
|
|
1749
2003
|
),
|
|
1750
2004
|
showMenu ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1751
2005
|
AnchoredMenu,
|
|
1752
2006
|
{
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
2007
|
+
accessibilityLabel,
|
|
2008
|
+
options: state.rows,
|
|
2009
|
+
selectedValue: search !== void 0 ? state.picked?.value ?? "" : value,
|
|
2010
|
+
onSelect: state.selectValue,
|
|
2011
|
+
onDismiss: state.close,
|
|
2012
|
+
colors: { text: colors.text, textSecondary: colors.textSecondary, border: colors.border, surface: colors.surface, brand: palette.primary["500"] },
|
|
1758
2013
|
optionHint,
|
|
1759
2014
|
testID,
|
|
1760
2015
|
anchorRef,
|
|
2016
|
+
listbox: { highlightedValue: state.highlighted?.value ?? "", statusText: state.statusText },
|
|
1761
2017
|
usePortal: true
|
|
1762
2018
|
}
|
|
1763
2019
|
) : null,
|
|
1764
2020
|
hasError ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { role: "alert", style: [controlStyles.error, { color: fieldErrorInk(theme) }], testID: `${testID}-error`, children: error }) : null
|
|
1765
2021
|
] });
|
|
1766
2022
|
}
|
|
2023
|
+
var TypeaheadControl = React2.forwardRef(TypeaheadControlImpl);
|
|
1767
2024
|
var WEB_DATE_PROPS = typeof document !== "undefined" ? { type: "date" } : {};
|
|
1768
2025
|
function DateInput(p) {
|
|
1769
2026
|
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: controlStyles.dateCol, children: [
|
|
@@ -1864,7 +2121,7 @@ var ROW_GAP = 4;
|
|
|
1864
2121
|
var TAB_PADDING = 4;
|
|
1865
2122
|
var INDICATOR_WIDTH = 2;
|
|
1866
2123
|
var TAB_FONT_SIZE = 12;
|
|
1867
|
-
var
|
|
2124
|
+
var styles11 = reactNative.StyleSheet.create({
|
|
1868
2125
|
row: { flexDirection: "row", flexWrap: "nowrap", gap: ROW_GAP },
|
|
1869
2126
|
tab: {
|
|
1870
2127
|
borderBottomWidth: INDICATOR_WIDTH,
|
|
@@ -1904,13 +2161,13 @@ var StepperTab = ({
|
|
|
1904
2161
|
accessibilityRole: "tab",
|
|
1905
2162
|
accessibilityState: { selected },
|
|
1906
2163
|
"aria-selected": selected,
|
|
1907
|
-
style: [
|
|
2164
|
+
style: [styles11.tab, { borderBottomColor: indicator }, ring.ringStyle],
|
|
1908
2165
|
testID,
|
|
1909
2166
|
onBlur: ring.onBlur,
|
|
1910
2167
|
onFocus: ring.onFocus,
|
|
1911
2168
|
onPress: () => onStep(step.key),
|
|
1912
2169
|
...webKeyProps,
|
|
1913
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [
|
|
2170
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles11.text, { color: theme.colors.text }, selected ? styles11.textSelected : void 0], children: step.label })
|
|
1914
2171
|
}
|
|
1915
2172
|
);
|
|
1916
2173
|
};
|
|
@@ -1920,7 +2177,7 @@ var StepperTabs = ({
|
|
|
1920
2177
|
onStep,
|
|
1921
2178
|
stepHint,
|
|
1922
2179
|
testID
|
|
1923
|
-
}) => /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { accessibilityRole: "tablist", style:
|
|
2180
|
+
}) => /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { accessibilityRole: "tablist", style: styles11.row, testID, children: steps.map((step) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1924
2181
|
StepperTab,
|
|
1925
2182
|
{
|
|
1926
2183
|
hint: stepHint,
|
|
@@ -1939,7 +2196,7 @@ function resolveStepNeighbours(steps, current) {
|
|
|
1939
2196
|
return { previous: steps[index - 1] ?? null, next: steps[index + 1] ?? null };
|
|
1940
2197
|
}
|
|
1941
2198
|
var ROW_GAP2 = 8;
|
|
1942
|
-
var
|
|
2199
|
+
var styles12 = reactNative.StyleSheet.create({
|
|
1943
2200
|
cell: { flex: 1, minWidth: 0 },
|
|
1944
2201
|
row: { flexDirection: "row", gap: ROW_GAP2 }
|
|
1945
2202
|
});
|
|
@@ -1951,8 +2208,8 @@ var StepperNav = ({
|
|
|
1951
2208
|
testID
|
|
1952
2209
|
}) => {
|
|
1953
2210
|
const { previous, next } = resolveStepNeighbours(steps, current);
|
|
1954
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style:
|
|
1955
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style:
|
|
2211
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles12.row, testID, children: [
|
|
2212
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles12.cell, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1956
2213
|
uiButtons.Button,
|
|
1957
2214
|
{
|
|
1958
2215
|
fullWidth: true,
|
|
@@ -1968,7 +2225,7 @@ var StepperNav = ({
|
|
|
1968
2225
|
}
|
|
1969
2226
|
}
|
|
1970
2227
|
) }),
|
|
1971
|
-
next === null ? null : /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style:
|
|
2228
|
+
next === null ? null : /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles12.cell, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1972
2229
|
uiButtons.Button,
|
|
1973
2230
|
{
|
|
1974
2231
|
fullWidth: true,
|
|
@@ -1982,12 +2239,29 @@ var StepperNav = ({
|
|
|
1982
2239
|
) })
|
|
1983
2240
|
] });
|
|
1984
2241
|
};
|
|
2242
|
+
var STATUS_FONT = 16;
|
|
2243
|
+
var styles13 = reactNative.StyleSheet.create({
|
|
2244
|
+
line: { fontSize: STATUS_FONT }
|
|
2245
|
+
});
|
|
2246
|
+
function FormStatusLine({ message, testID, style }) {
|
|
2247
|
+
const { theme } = uiFeedback.useUi();
|
|
2248
|
+
if (message === null || message === void 0 || message === "") return null;
|
|
2249
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { role: "alert", style: [styles13.line, { color: theme.colors.text }, style], testID, children: message });
|
|
2250
|
+
}
|
|
2251
|
+
function useFocusFirstInvalid(refs) {
|
|
2252
|
+
const latest = React2.useRef(refs);
|
|
2253
|
+
latest.current = refs;
|
|
2254
|
+
return React2.useCallback((invalid) => {
|
|
2255
|
+
const first = invalid.map((field) => latest.current[field].current).find((node) => node !== null);
|
|
2256
|
+
first?.focus();
|
|
2257
|
+
}, []);
|
|
2258
|
+
}
|
|
1985
2259
|
var DEFAULT_PREVIEW_PX = 48;
|
|
1986
2260
|
var PREVIEW_RADIUS = 8;
|
|
1987
2261
|
var GAP = 8;
|
|
1988
2262
|
var TITLE_FONT_SIZE = 14;
|
|
1989
2263
|
var HELP_FONT_SIZE = 13;
|
|
1990
|
-
var
|
|
2264
|
+
var styles14 = reactNative.StyleSheet.create({
|
|
1991
2265
|
help: { flex: 1, fontSize: HELP_FONT_SIZE },
|
|
1992
2266
|
root: { gap: GAP },
|
|
1993
2267
|
tile: { alignItems: "center", flexDirection: "row", gap: GAP },
|
|
@@ -2009,11 +2283,11 @@ var UploadWithLinkField = ({
|
|
|
2009
2283
|
const url = value ?? "";
|
|
2010
2284
|
const [pasting, setPasting] = React2.useState(url !== "");
|
|
2011
2285
|
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:
|
|
2286
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles14.root, children: [
|
|
2287
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles14.title, { color: theme.colors.text }], children: labels.title }),
|
|
2288
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles14.tile, children: [
|
|
2015
2289
|
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: [
|
|
2290
|
+
labels.help === void 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles14.help, { color: theme.colors.text }], children: labels.help })
|
|
2017
2291
|
] }),
|
|
2018
2292
|
uploadControl,
|
|
2019
2293
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2024,12 +2298,12 @@ var UploadWithLinkField = ({
|
|
|
2024
2298
|
accessibilityRole: "button",
|
|
2025
2299
|
accessibilityState: { expanded: pasting },
|
|
2026
2300
|
"aria-expanded": pasting,
|
|
2027
|
-
style: [
|
|
2301
|
+
style: [styles14.toggle, ring.ringStyle],
|
|
2028
2302
|
testID: `${testID}-paste`,
|
|
2029
2303
|
onBlur: ring.onBlur,
|
|
2030
2304
|
onFocus: ring.onFocus,
|
|
2031
2305
|
onPress: () => setPasting(!pasting),
|
|
2032
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [
|
|
2306
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles14.toggleText, { color: theme.colors.text }], children: labels.pasteToggle })
|
|
2033
2307
|
}
|
|
2034
2308
|
),
|
|
2035
2309
|
pasting ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2062,6 +2336,7 @@ exports.FormCheckbox = FormCheckbox;
|
|
|
2062
2336
|
exports.FormField = FormField;
|
|
2063
2337
|
exports.FormGrid = FormGrid;
|
|
2064
2338
|
exports.FormSection = FormSection;
|
|
2339
|
+
exports.FormStatusLine = FormStatusLine;
|
|
2065
2340
|
exports.FormSwitch = FormSwitch;
|
|
2066
2341
|
exports.INLINE_FIELD_ROW_MIN_WIDTH = INLINE_FIELD_ROW_MIN_WIDTH;
|
|
2067
2342
|
exports.InlineFieldRow = InlineFieldRow;
|
|
@@ -2079,6 +2354,7 @@ exports.resolveGroupSelection = resolveGroupSelection;
|
|
|
2079
2354
|
exports.resolveStepNeighbours = resolveStepNeighbours;
|
|
2080
2355
|
exports.suggestOptions = suggestOptions;
|
|
2081
2356
|
exports.toggleGroupSelection = toggleGroupSelection;
|
|
2357
|
+
exports.useFocusFirstInvalid = useFocusFirstInvalid;
|
|
2082
2358
|
exports.useRecentValues = useRecentValues;
|
|
2083
2359
|
exports.useThemedInput = useThemedInput;
|
|
2084
2360
|
//# sourceMappingURL=index.js.map
|