@dloizides/ui-forms 1.11.1 → 1.13.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 +16 -1
- package/dist/index.d.mts +32 -10
- package/dist/index.d.ts +32 -10
- package/dist/index.js +97 -17
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +98 -18
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import React2, { useState, useCallback, useMemo, useRef, useEffect } from 'react';
|
|
1
|
+
import React2, { useState, useCallback, useMemo, useRef, useEffect, useLayoutEffect } from 'react';
|
|
2
2
|
import { Platform, StyleSheet, TextInput, View, Text, Switch, Pressable, TouchableOpacity } from 'react-native';
|
|
3
3
|
import { useUi } from '@dloizides/ui-feedback';
|
|
4
4
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
5
5
|
import { Button } from '@dloizides/ui-buttons';
|
|
6
6
|
import { MIN_TOUCH_TARGET_PX } from '@dloizides/a11y';
|
|
7
|
+
import { createPortal } from 'react-dom';
|
|
7
8
|
|
|
8
9
|
// src/Field/Field.tsx
|
|
9
10
|
function attachControlId(child, candidateId, describedById) {
|
|
@@ -606,23 +607,33 @@ var ThemedTextInput = React2.forwardRef(function ThemedTextInput2({
|
|
|
606
607
|
});
|
|
607
608
|
var FormField = ({
|
|
608
609
|
label,
|
|
610
|
+
labelHidden = false,
|
|
609
611
|
required = false,
|
|
610
612
|
error,
|
|
611
613
|
containerStyle,
|
|
612
614
|
...textInputProps
|
|
613
|
-
}) => /* @__PURE__ */ jsx(
|
|
614
|
-
|
|
615
|
+
}) => /* @__PURE__ */ jsx(
|
|
616
|
+
Field,
|
|
615
617
|
{
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
618
|
+
containerStyle,
|
|
619
|
+
error,
|
|
620
|
+
label: labelHidden ? void 0 : label,
|
|
621
|
+
required,
|
|
622
|
+
children: ({ describedById, hasError, controlId }) => /* @__PURE__ */ jsx(
|
|
623
|
+
ThemedTextInput,
|
|
624
|
+
{
|
|
625
|
+
accessibilityHint: `Enter ${label}`,
|
|
626
|
+
accessibilityLabel: label,
|
|
627
|
+
describedById,
|
|
628
|
+
hasError,
|
|
629
|
+
id: controlId,
|
|
630
|
+
requiredField: required,
|
|
631
|
+
testID: "form-field-input",
|
|
632
|
+
...textInputProps
|
|
633
|
+
}
|
|
634
|
+
)
|
|
624
635
|
}
|
|
625
|
-
)
|
|
636
|
+
);
|
|
626
637
|
var TRANSPARENT_COLOR = "transparent";
|
|
627
638
|
var WHITE_COLOR = "#fff";
|
|
628
639
|
var SOLID_RADIUS = 20;
|
|
@@ -991,13 +1002,76 @@ var FormCheckbox = ({
|
|
|
991
1002
|
}
|
|
992
1003
|
);
|
|
993
1004
|
};
|
|
994
|
-
var IS_WEB5 =
|
|
1005
|
+
var IS_WEB5 = Platform.OS === "web";
|
|
1006
|
+
var MENU_PORTAL_Z_INDEX = 1e3;
|
|
1007
|
+
var MENU_TOP_GAP2 = 4;
|
|
1008
|
+
function toDomNode(ref) {
|
|
1009
|
+
const node = ref.current;
|
|
1010
|
+
if (node === null || typeof node.getBoundingClientRect !== "function") return null;
|
|
1011
|
+
return node;
|
|
1012
|
+
}
|
|
1013
|
+
function readAnchorRect(ref) {
|
|
1014
|
+
if (!IS_WEB5) return null;
|
|
1015
|
+
const node = toDomNode(ref);
|
|
1016
|
+
if (node === null) return null;
|
|
1017
|
+
const r = node.getBoundingClientRect();
|
|
1018
|
+
return { top: r.top, left: r.left, width: r.width, bottom: r.bottom };
|
|
1019
|
+
}
|
|
1020
|
+
function buildPortalPopoverStyle(rect) {
|
|
1021
|
+
return {
|
|
1022
|
+
// RN's ViewStyle union omits 'fixed', but react-native-web honours it at runtime.
|
|
1023
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- web-only position value
|
|
1024
|
+
position: "fixed",
|
|
1025
|
+
top: rect.bottom + MENU_TOP_GAP2,
|
|
1026
|
+
left: rect.left,
|
|
1027
|
+
width: rect.width,
|
|
1028
|
+
zIndex: MENU_PORTAL_Z_INDEX
|
|
1029
|
+
};
|
|
1030
|
+
}
|
|
1031
|
+
function useAnchorRect(ref, enabled) {
|
|
1032
|
+
const [rect, setRect] = useState(null);
|
|
1033
|
+
useLayoutEffect(() => {
|
|
1034
|
+
if (!IS_WEB5 || !enabled) {
|
|
1035
|
+
setRect(null);
|
|
1036
|
+
return void 0;
|
|
1037
|
+
}
|
|
1038
|
+
let frame = null;
|
|
1039
|
+
let disposed = false;
|
|
1040
|
+
const apply = () => {
|
|
1041
|
+
frame = null;
|
|
1042
|
+
if (disposed) return;
|
|
1043
|
+
setRect(readAnchorRect(ref));
|
|
1044
|
+
};
|
|
1045
|
+
const schedule = () => {
|
|
1046
|
+
if (frame !== null) return;
|
|
1047
|
+
frame = window.requestAnimationFrame(apply);
|
|
1048
|
+
};
|
|
1049
|
+
apply();
|
|
1050
|
+
document.addEventListener("scroll", schedule, true);
|
|
1051
|
+
window.addEventListener("resize", schedule);
|
|
1052
|
+
const node = toDomNode(ref);
|
|
1053
|
+
const observer = typeof ResizeObserver === "function" ? new ResizeObserver(schedule) : null;
|
|
1054
|
+
if (observer !== null) {
|
|
1055
|
+
if (node !== null) observer.observe(node);
|
|
1056
|
+
observer.observe(document.body);
|
|
1057
|
+
}
|
|
1058
|
+
return () => {
|
|
1059
|
+
disposed = true;
|
|
1060
|
+
if (frame !== null) window.cancelAnimationFrame(frame);
|
|
1061
|
+
document.removeEventListener("scroll", schedule, true);
|
|
1062
|
+
window.removeEventListener("resize", schedule);
|
|
1063
|
+
if (observer !== null) observer.disconnect();
|
|
1064
|
+
};
|
|
1065
|
+
}, [ref, enabled]);
|
|
1066
|
+
return IS_WEB5 && enabled ? rect : null;
|
|
1067
|
+
}
|
|
1068
|
+
var IS_WEB6 = typeof document !== "undefined";
|
|
995
1069
|
var ESCAPE_KEY = "Escape";
|
|
996
1070
|
var ACTIVE_WEIGHT = "700";
|
|
997
1071
|
var IDLE_WEIGHT = "400";
|
|
998
1072
|
function useDismiss(anchorRef, menuRef, onDismiss) {
|
|
999
1073
|
useEffect(() => {
|
|
1000
|
-
if (!
|
|
1074
|
+
if (!IS_WEB6) return void 0;
|
|
1001
1075
|
const onMouseDown = (event) => {
|
|
1002
1076
|
const anchorNode = anchorRef.current;
|
|
1003
1077
|
const menuNode = menuRef.current;
|
|
@@ -1025,16 +1099,19 @@ function AnchoredMenu({
|
|
|
1025
1099
|
colors,
|
|
1026
1100
|
optionHint,
|
|
1027
1101
|
testID,
|
|
1028
|
-
anchorRef
|
|
1102
|
+
anchorRef,
|
|
1103
|
+
usePortal = false
|
|
1029
1104
|
}) {
|
|
1030
1105
|
const menuRef = React2.useRef(null);
|
|
1031
1106
|
useDismiss(anchorRef, menuRef, onDismiss);
|
|
1032
|
-
|
|
1107
|
+
const rect = useAnchorRect(anchorRef, usePortal);
|
|
1108
|
+
const portalStyle = rect !== null ? buildPortalPopoverStyle(rect) : null;
|
|
1109
|
+
const menu = /* @__PURE__ */ jsx(
|
|
1033
1110
|
View,
|
|
1034
1111
|
{
|
|
1035
1112
|
ref: menuRef,
|
|
1036
1113
|
accessibilityRole: "menu",
|
|
1037
|
-
style: [controlStyles.menu, { borderColor: colors.border, backgroundColor: colors.surface }],
|
|
1114
|
+
style: [controlStyles.menu, { borderColor: colors.border, backgroundColor: colors.surface }, portalStyle],
|
|
1038
1115
|
testID: `${testID}-menu`,
|
|
1039
1116
|
children: options.map((opt) => {
|
|
1040
1117
|
const active = opt.value === selectedValue;
|
|
@@ -1056,6 +1133,8 @@ function AnchoredMenu({
|
|
|
1056
1133
|
})
|
|
1057
1134
|
}
|
|
1058
1135
|
);
|
|
1136
|
+
if (usePortal && IS_WEB6) return createPortal(menu, document.body);
|
|
1137
|
+
return menu;
|
|
1059
1138
|
}
|
|
1060
1139
|
var CHEVRON_DOWN = "\u25BE";
|
|
1061
1140
|
var CHEVRON_UP = "\u25B4";
|
|
@@ -1239,7 +1318,8 @@ function TypeaheadControl({
|
|
|
1239
1318
|
colors: { text: colors.text, border: colors.border, surface: colors.surface, brand: palette.primary["500"] },
|
|
1240
1319
|
optionHint,
|
|
1241
1320
|
testID,
|
|
1242
|
-
anchorRef
|
|
1321
|
+
anchorRef,
|
|
1322
|
+
usePortal: true
|
|
1243
1323
|
}
|
|
1244
1324
|
) : null,
|
|
1245
1325
|
hasError ? /* @__PURE__ */ jsx(Text, { role: "alert", style: [controlStyles.error, { color: semantic.error["500"] }], testID: `${testID}-error`, children: error }) : null
|