@dloizides/ui-forms 1.14.0 → 1.16.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 +19 -0
- package/dist/index.d.mts +98 -16
- package/dist/index.d.ts +98 -16
- package/dist/index.js +220 -96
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +218 -97
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -952,56 +952,19 @@ var FormField = ({
|
|
|
952
952
|
}
|
|
953
953
|
}
|
|
954
954
|
);
|
|
955
|
+
|
|
956
|
+
// src/ChipSelector/constants.ts
|
|
955
957
|
var TRANSPARENT_COLOR = "transparent";
|
|
956
|
-
var
|
|
958
|
+
var CHIP_HIT_SLOP = { top: 10, bottom: 10, left: 4, right: 4 };
|
|
959
|
+
var CHIP_GUTTER = 8;
|
|
960
|
+
var DEFAULT_CHIP_TESTID_PREFIX = "chip-selector-chip";
|
|
957
961
|
var SOLID_RADIUS = 20;
|
|
958
962
|
var OUTLINE_RADIUS = 999;
|
|
959
963
|
var OUTLINE_PAD_H = 12;
|
|
960
964
|
var OUTLINE_PAD_V = 5;
|
|
961
965
|
var OUTLINE_FONT_SIZE = 13;
|
|
962
|
-
var
|
|
963
|
-
var
|
|
964
|
-
var HEX_RADIX2 = 16;
|
|
965
|
-
var RGB_R_START = 0;
|
|
966
|
-
var RGB_R_END = 2;
|
|
967
|
-
var RGB_G_END = 4;
|
|
968
|
-
var RGB_B_END = 6;
|
|
969
|
-
var CHIP_HIT_SLOP = { top: 10, bottom: 10, left: 4, right: 4 };
|
|
970
|
-
var CHIP_GUTTER = 8;
|
|
971
|
-
var DEFAULT_CHIP_TESTID_PREFIX = "chip-selector-chip";
|
|
972
|
-
var ON_BRAND_SCALE = "onBrand";
|
|
973
|
-
var MAIN_STEP = "500";
|
|
974
|
-
function onBrandInk(palette) {
|
|
975
|
-
const scales = palette;
|
|
976
|
-
return scales[ON_BRAND_SCALE]?.[MAIN_STEP] ?? WHITE_COLOR;
|
|
977
|
-
}
|
|
978
|
-
function withAlpha2(hex, alpha) {
|
|
979
|
-
const normalized = hex.replace("#", "");
|
|
980
|
-
const isShort = normalized.length === HEX_SHORT_LENGTH2;
|
|
981
|
-
const full = isShort ? normalized.split("").map((c) => c + c).join("") : normalized;
|
|
982
|
-
const r = parseInt(full.slice(RGB_R_START, RGB_R_END), HEX_RADIX2);
|
|
983
|
-
const g = parseInt(full.slice(RGB_R_END, RGB_G_END), HEX_RADIX2);
|
|
984
|
-
const b = parseInt(full.slice(RGB_G_END, RGB_B_END), HEX_RADIX2);
|
|
985
|
-
const isValid = !Number.isNaN(r) && !Number.isNaN(g) && !Number.isNaN(b);
|
|
986
|
-
return isValid ? `rgba(${r}, ${g}, ${b}, ${alpha})` : hex;
|
|
987
|
-
}
|
|
988
|
-
var styles5 = reactNative.StyleSheet.create({
|
|
989
|
-
chipContainer: {
|
|
990
|
-
flexDirection: "row",
|
|
991
|
-
flexWrap: "wrap",
|
|
992
|
-
// `gap`, NOT per-chip margins plus a compensating negative container margin.
|
|
993
|
-
//
|
|
994
|
-
// The old form was `chipWrapper { marginRight: 8, marginBottom: 8 }` with
|
|
995
|
-
// `chipContainer { marginBottom: -8 }`. Its comment blamed `Field`'s 16px container margin —
|
|
996
|
-
// that was WRONG, and worth recording: F3 was briefed on the belief that the -8 compensated for
|
|
997
|
-
// `Field` and had to move in lockstep with it. It did not. -8 cancelled the CHIP's own gutter
|
|
998
|
-
// hanging off the last row, identically whether `Field` contributed 16, 0, or anything else.
|
|
999
|
-
//
|
|
1000
|
-
// The pair is still the wrong tool: it holds only while the two constants agree, and it leaves
|
|
1001
|
-
// a real negative margin any measuring parent inherits. `gap` produces the byte-identical box
|
|
1002
|
-
// and is correct under BOTH of `Field`'s spacing models, not just the one it was tuned against.
|
|
1003
|
-
gap: CHIP_GUTTER
|
|
1004
|
-
},
|
|
966
|
+
var CHIP_ICON_GAP = 6;
|
|
967
|
+
var chipStyles = reactNative.StyleSheet.create({
|
|
1005
968
|
chip: {
|
|
1006
969
|
paddingHorizontal: 12,
|
|
1007
970
|
paddingVertical: 6,
|
|
@@ -1015,28 +978,21 @@ var styles5 = reactNative.StyleSheet.create({
|
|
|
1015
978
|
borderRadius: OUTLINE_RADIUS,
|
|
1016
979
|
borderWidth: 1
|
|
1017
980
|
},
|
|
981
|
+
chipContent: { flexDirection: "row", alignItems: "center", gap: CHIP_ICON_GAP },
|
|
1018
982
|
chipText: {},
|
|
1019
983
|
chipTextOutline: { fontSize: OUTLINE_FONT_SIZE }
|
|
1020
984
|
});
|
|
1021
|
-
function
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
};
|
|
985
|
+
function ChipContent({ icon, label, textStyle }) {
|
|
986
|
+
const text = /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: textStyle, children: label });
|
|
987
|
+
if (icon === void 0 || icon === null)
|
|
988
|
+
return text;
|
|
989
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: chipStyles.chipContent, children: [
|
|
990
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { "aria-hidden": true, children: icon }),
|
|
991
|
+
text
|
|
992
|
+
] });
|
|
1029
993
|
}
|
|
1030
|
-
function OutlineChip({
|
|
1031
|
-
option,
|
|
1032
|
-
selected,
|
|
1033
|
-
disabled,
|
|
1034
|
-
colors,
|
|
1035
|
-
testID,
|
|
1036
|
-
accessibilityHint,
|
|
1037
|
-
ariaPressed,
|
|
1038
|
-
onPress
|
|
1039
|
-
}) {
|
|
994
|
+
function OutlineChip(props) {
|
|
995
|
+
const { option, selected, disabled, colors, testID, accessibilityHint, onPress } = props;
|
|
1040
996
|
const [hovered, setHovered] = React2__default.default.useState(false);
|
|
1041
997
|
const active = selected || hovered;
|
|
1042
998
|
const borderColor = active ? colors.primary : colors.border;
|
|
@@ -1045,49 +1001,179 @@ function OutlineChip({
|
|
|
1045
1001
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1046
1002
|
reactNative.Pressable,
|
|
1047
1003
|
{
|
|
1004
|
+
ref: props.hostRef,
|
|
1048
1005
|
accessibilityHint,
|
|
1049
1006
|
accessibilityLabel: option.label,
|
|
1050
|
-
accessibilityRole:
|
|
1007
|
+
accessibilityRole: props.accessibilityRole,
|
|
1051
1008
|
accessibilityState: { selected, disabled },
|
|
1052
|
-
"aria-
|
|
1009
|
+
"aria-checked": props.ariaChecked,
|
|
1010
|
+
"aria-pressed": props.ariaPressed,
|
|
1053
1011
|
disabled,
|
|
1054
1012
|
hitSlop: CHIP_HIT_SLOP,
|
|
1013
|
+
tabIndex: props.tabIndex,
|
|
1055
1014
|
testID,
|
|
1056
1015
|
onHoverIn: () => setHovered(true),
|
|
1057
1016
|
onHoverOut: () => setHovered(false),
|
|
1058
1017
|
onPress,
|
|
1059
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [
|
|
1018
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [chipStyles.chipOutline, { borderColor, backgroundColor }], children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1019
|
+
ChipContent,
|
|
1020
|
+
{
|
|
1021
|
+
icon: option.icon,
|
|
1022
|
+
label: option.label,
|
|
1023
|
+
textStyle: [chipStyles.chipText, chipStyles.chipTextOutline, { color: textColor }]
|
|
1024
|
+
}
|
|
1025
|
+
) })
|
|
1060
1026
|
}
|
|
1061
1027
|
);
|
|
1062
1028
|
}
|
|
1063
|
-
function SolidChip({
|
|
1064
|
-
option,
|
|
1065
|
-
selected,
|
|
1066
|
-
disabled,
|
|
1067
|
-
colors,
|
|
1068
|
-
testID,
|
|
1069
|
-
accessibilityHint,
|
|
1070
|
-
ariaPressed,
|
|
1071
|
-
onPress
|
|
1072
|
-
}) {
|
|
1029
|
+
function SolidChip(props) {
|
|
1030
|
+
const { option, selected, disabled, colors, testID, accessibilityHint, onPress } = props;
|
|
1073
1031
|
const backgroundColor = selected ? colors.primary : TRANSPARENT_COLOR;
|
|
1074
1032
|
const textColor = selected ? colors.onPrimary : colors.textStrong;
|
|
1033
|
+
const rovingTabStop = { tabIndex: props.tabIndex };
|
|
1075
1034
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1076
1035
|
reactNative.TouchableOpacity,
|
|
1077
1036
|
{
|
|
1037
|
+
ref: props.hostRef,
|
|
1078
1038
|
accessibilityHint,
|
|
1079
1039
|
accessibilityLabel: option.label,
|
|
1080
|
-
accessibilityRole:
|
|
1040
|
+
accessibilityRole: props.accessibilityRole,
|
|
1081
1041
|
accessibilityState: { selected, disabled },
|
|
1082
|
-
"aria-
|
|
1042
|
+
"aria-checked": props.ariaChecked,
|
|
1043
|
+
"aria-pressed": props.ariaPressed,
|
|
1083
1044
|
disabled,
|
|
1084
1045
|
hitSlop: CHIP_HIT_SLOP,
|
|
1085
1046
|
testID,
|
|
1086
1047
|
onPress,
|
|
1087
|
-
|
|
1048
|
+
...rovingTabStop,
|
|
1049
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [chipStyles.chip, { borderColor: colors.border, backgroundColor }], children: /* @__PURE__ */ jsxRuntime.jsx(ChipContent, { icon: option.icon, label: option.label, textStyle: [chipStyles.chipText, { color: textColor }] }) })
|
|
1088
1050
|
}
|
|
1089
1051
|
);
|
|
1090
1052
|
}
|
|
1053
|
+
|
|
1054
|
+
// src/ChipSelector/utils/radioKeyboard.ts
|
|
1055
|
+
var SPACE_KEYS = [" ", "Spacebar"];
|
|
1056
|
+
var NEXT_KEYS = ["ArrowRight", "ArrowDown"];
|
|
1057
|
+
var PREVIOUS_KEYS = ["ArrowLeft", "ArrowUp"];
|
|
1058
|
+
var ROVING_TAB_STOP = 0;
|
|
1059
|
+
var ROVING_SKIPPED = -1;
|
|
1060
|
+
function radioKeyTarget(key, index, count) {
|
|
1061
|
+
const isOutOfRange = index < 0 || index >= count;
|
|
1062
|
+
if (isOutOfRange)
|
|
1063
|
+
return null;
|
|
1064
|
+
if (SPACE_KEYS.includes(key))
|
|
1065
|
+
return index;
|
|
1066
|
+
const isArrow = NEXT_KEYS.includes(key) || PREVIOUS_KEYS.includes(key);
|
|
1067
|
+
if (!isArrow || count === 1)
|
|
1068
|
+
return null;
|
|
1069
|
+
const step = NEXT_KEYS.includes(key) ? 1 : -1;
|
|
1070
|
+
return (index + step + count) % count;
|
|
1071
|
+
}
|
|
1072
|
+
function radioTabIndex(index, selectedIndex, disabled) {
|
|
1073
|
+
if (disabled)
|
|
1074
|
+
return ROVING_SKIPPED;
|
|
1075
|
+
const tabStop = selectedIndex >= 0 ? selectedIndex : 0;
|
|
1076
|
+
return index === tabStop ? ROVING_TAB_STOP : ROVING_SKIPPED;
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
// src/ChipSelector/hooks/useRadioKeyboard.ts
|
|
1080
|
+
var NO_GROUP_PROPS = {};
|
|
1081
|
+
function useRadioKeyboard(config) {
|
|
1082
|
+
const { enabled, disabled, values, selectedIndex, onChange } = config;
|
|
1083
|
+
const nodes = React2__default.default.useRef([]);
|
|
1084
|
+
const chipRef = React2__default.default.useCallback((index) => (node) => {
|
|
1085
|
+
nodes.current[index] = node;
|
|
1086
|
+
}, []);
|
|
1087
|
+
const onKeyDown = (event) => {
|
|
1088
|
+
if (disabled)
|
|
1089
|
+
return;
|
|
1090
|
+
const index = nodes.current.indexOf(event.target);
|
|
1091
|
+
const target = radioKeyTarget(event.key, index, values.length);
|
|
1092
|
+
const nextValue = target === null ? void 0 : values[target];
|
|
1093
|
+
if (target === null || nextValue === void 0)
|
|
1094
|
+
return;
|
|
1095
|
+
event.preventDefault();
|
|
1096
|
+
if (target !== index)
|
|
1097
|
+
nodes.current[target]?.focus?.();
|
|
1098
|
+
onChange(nextValue);
|
|
1099
|
+
};
|
|
1100
|
+
return {
|
|
1101
|
+
chipRef,
|
|
1102
|
+
tabIndexFor: (index) => enabled ? radioTabIndex(index, selectedIndex, disabled) : void 0,
|
|
1103
|
+
// `onKeyDown` is a web-only View prop RN's types do not declare; RNW forwards it to the DOM.
|
|
1104
|
+
groupProps: enabled ? { onKeyDown } : NO_GROUP_PROPS
|
|
1105
|
+
};
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
// src/ChipSelector/utils/chipColors.ts
|
|
1109
|
+
var WHITE_COLOR = "#fff";
|
|
1110
|
+
var OUTLINE_TINT_ALPHA = 0.1;
|
|
1111
|
+
var HEX_SHORT_LENGTH2 = 3;
|
|
1112
|
+
var HEX_RADIX2 = 16;
|
|
1113
|
+
var RGB_R_START = 0;
|
|
1114
|
+
var RGB_R_END = 2;
|
|
1115
|
+
var RGB_G_END = 4;
|
|
1116
|
+
var RGB_B_END = 6;
|
|
1117
|
+
var ON_BRAND_SCALE = "onBrand";
|
|
1118
|
+
var MAIN_STEP = "500";
|
|
1119
|
+
function onBrandInk(palette) {
|
|
1120
|
+
const scales = palette;
|
|
1121
|
+
return scales[ON_BRAND_SCALE]?.[MAIN_STEP] ?? WHITE_COLOR;
|
|
1122
|
+
}
|
|
1123
|
+
function withAlpha2(hex, alpha) {
|
|
1124
|
+
const normalized = hex.replace("#", "");
|
|
1125
|
+
const isShort = normalized.length === HEX_SHORT_LENGTH2;
|
|
1126
|
+
const full = isShort ? normalized.split("").map((c) => c + c).join("") : normalized;
|
|
1127
|
+
const r = parseInt(full.slice(RGB_R_START, RGB_R_END), HEX_RADIX2);
|
|
1128
|
+
const g = parseInt(full.slice(RGB_R_END, RGB_G_END), HEX_RADIX2);
|
|
1129
|
+
const b = parseInt(full.slice(RGB_G_END, RGB_B_END), HEX_RADIX2);
|
|
1130
|
+
const isValid = !Number.isNaN(r) && !Number.isNaN(g) && !Number.isNaN(b);
|
|
1131
|
+
return isValid ? `rgba(${r}, ${g}, ${b}, ${alpha})` : hex;
|
|
1132
|
+
}
|
|
1133
|
+
function buildChipColors(colors, palette) {
|
|
1134
|
+
const primary = palette.primary[500];
|
|
1135
|
+
return {
|
|
1136
|
+
border: colors.border,
|
|
1137
|
+
textStrong: colors.text,
|
|
1138
|
+
textMuted: colors.textSecondary,
|
|
1139
|
+
primary,
|
|
1140
|
+
onPrimary: onBrandInk(palette),
|
|
1141
|
+
muted: colors.background,
|
|
1142
|
+
tint: withAlpha2(primary, OUTLINE_TINT_ALPHA)
|
|
1143
|
+
};
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
// src/ChipSelector/utils/chipIdentity.ts
|
|
1147
|
+
function chipIdentity(option, selected, config) {
|
|
1148
|
+
const isRadio = config.radio === true && !config.multiple;
|
|
1149
|
+
return {
|
|
1150
|
+
testID: `${config.prefix}-${String(option.value)}`,
|
|
1151
|
+
// The English default is retained verbatim: erevna/katalogos assert the exact string
|
|
1152
|
+
// `Selects Red`. Consumers that localize pass `optionAccessibilityHint`.
|
|
1153
|
+
accessibilityHint: config.hint ?? `Selects ${option.label}`,
|
|
1154
|
+
ariaPressed: config.multiple ? selected : void 0,
|
|
1155
|
+
accessibilityRole: isRadio ? "radio" : "button",
|
|
1156
|
+
ariaChecked: isRadio ? selected : void 0
|
|
1157
|
+
};
|
|
1158
|
+
}
|
|
1159
|
+
var styles5 = reactNative.StyleSheet.create({
|
|
1160
|
+
chipContainer: {
|
|
1161
|
+
flexDirection: "row",
|
|
1162
|
+
flexWrap: "wrap",
|
|
1163
|
+
// `gap`, NOT per-chip margins plus a compensating negative container margin.
|
|
1164
|
+
//
|
|
1165
|
+
// The old form was `chipWrapper { marginRight: 8, marginBottom: 8 }` with
|
|
1166
|
+
// `chipContainer { marginBottom: -8 }`. Its comment blamed `Field`'s 16px container margin —
|
|
1167
|
+
// that was WRONG, and worth recording: F3 was briefed on the belief that the -8 compensated for
|
|
1168
|
+
// `Field` and had to move in lockstep with it. It did not. -8 cancelled the CHIP's own gutter
|
|
1169
|
+
// hanging off the last row, identically whether `Field` contributed 16, 0, or anything else.
|
|
1170
|
+
//
|
|
1171
|
+
// The pair is still the wrong tool: it holds only while the two constants agree, and it leaves
|
|
1172
|
+
// a real negative margin any measuring parent inherits. `gap` produces the byte-identical box
|
|
1173
|
+
// and is correct under BOTH of `Field`'s spacing models, not just the one it was tuned against.
|
|
1174
|
+
gap: CHIP_GUTTER
|
|
1175
|
+
}
|
|
1176
|
+
});
|
|
1091
1177
|
var ChipSelector = ({
|
|
1092
1178
|
label,
|
|
1093
1179
|
options,
|
|
@@ -1102,28 +1188,26 @@ var ChipSelector = ({
|
|
|
1102
1188
|
error,
|
|
1103
1189
|
testID,
|
|
1104
1190
|
chipTestIDPrefix = DEFAULT_CHIP_TESTID_PREFIX,
|
|
1105
|
-
optionAccessibilityHint
|
|
1191
|
+
optionAccessibilityHint,
|
|
1192
|
+
singleSelectRole = "button"
|
|
1106
1193
|
}) => {
|
|
1194
|
+
const isRadioGroup = !multiple && singleSelectRole === "radio";
|
|
1107
1195
|
const { theme } = uiFeedback.useUi();
|
|
1108
1196
|
const { colors, palette } = theme;
|
|
1109
|
-
const chipColors = React2__default.default.useMemo(() =>
|
|
1110
|
-
const primary = palette.primary["500"];
|
|
1111
|
-
return {
|
|
1112
|
-
border: colors.border,
|
|
1113
|
-
textStrong: colors.text,
|
|
1114
|
-
textMuted: colors.textSecondary,
|
|
1115
|
-
primary,
|
|
1116
|
-
onPrimary: onBrandInk(palette),
|
|
1117
|
-
muted: colors.background,
|
|
1118
|
-
tint: withAlpha2(primary, OUTLINE_TINT_ALPHA)
|
|
1119
|
-
};
|
|
1120
|
-
}, [colors.border, colors.text, colors.textSecondary, colors.background, palette]);
|
|
1197
|
+
const chipColors = React2__default.default.useMemo(() => buildChipColors(colors, palette), [colors, palette]);
|
|
1121
1198
|
function isSelected(optionValue) {
|
|
1122
1199
|
if (multiple && Array.isArray(value))
|
|
1123
1200
|
return value.includes(optionValue);
|
|
1124
1201
|
return value === optionValue;
|
|
1125
1202
|
}
|
|
1126
|
-
|
|
1203
|
+
const radio = useRadioKeyboard({
|
|
1204
|
+
enabled: isRadioGroup,
|
|
1205
|
+
disabled,
|
|
1206
|
+
values: options.map((option) => option.value),
|
|
1207
|
+
selectedIndex: options.findIndex((option) => isSelected(option.value)),
|
|
1208
|
+
onChange
|
|
1209
|
+
});
|
|
1210
|
+
function renderChip(option, index) {
|
|
1127
1211
|
const selected = isSelected(option.value);
|
|
1128
1212
|
const chipProps = {
|
|
1129
1213
|
colors: chipColors,
|
|
@@ -1133,8 +1217,13 @@ var ChipSelector = ({
|
|
|
1133
1217
|
...chipIdentity(option, selected, {
|
|
1134
1218
|
prefix: chipTestIDPrefix,
|
|
1135
1219
|
hint: optionAccessibilityHint,
|
|
1136
|
-
multiple
|
|
1220
|
+
multiple,
|
|
1221
|
+
radio: isRadioGroup
|
|
1137
1222
|
}),
|
|
1223
|
+
// Radio mode only: roving tab stop + host node for arrow-key focus moves. Both stay
|
|
1224
|
+
// `undefined` otherwise, so button / multi chips keep their existing tab order.
|
|
1225
|
+
tabIndex: radio.tabIndexFor(index),
|
|
1226
|
+
hostRef: isRadioGroup ? radio.chipRef(index) : void 0,
|
|
1138
1227
|
onPress: () => onChange(option.value)
|
|
1139
1228
|
};
|
|
1140
1229
|
const key = String(option.value);
|
|
@@ -1149,7 +1238,16 @@ var ChipSelector = ({
|
|
|
1149
1238
|
required,
|
|
1150
1239
|
spacing,
|
|
1151
1240
|
testID,
|
|
1152
|
-
children: ({ describedById, hasError }) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1241
|
+
children: ({ describedById, hasError }) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1242
|
+
reactNative.View,
|
|
1243
|
+
{
|
|
1244
|
+
accessibilityRole: isRadioGroup ? "radiogroup" : void 0,
|
|
1245
|
+
style: styles5.chipContainer,
|
|
1246
|
+
...webFieldA11y({ describedById, hasError }),
|
|
1247
|
+
...radio.groupProps,
|
|
1248
|
+
children: options.map(renderChip)
|
|
1249
|
+
}
|
|
1250
|
+
)
|
|
1153
1251
|
}
|
|
1154
1252
|
);
|
|
1155
1253
|
};
|
|
@@ -1207,8 +1305,7 @@ var FormSwitch = ({
|
|
|
1207
1305
|
{
|
|
1208
1306
|
accessibilityHint: accessibilityHint ?? label,
|
|
1209
1307
|
accessibilityLabel: label,
|
|
1210
|
-
|
|
1211
|
-
accessibilityState: { checked: value },
|
|
1308
|
+
accessibilityState: { checked: value, disabled },
|
|
1212
1309
|
disabled,
|
|
1213
1310
|
testID,
|
|
1214
1311
|
value,
|
|
@@ -1582,6 +1679,30 @@ function DateRangeControl({
|
|
|
1582
1679
|
] });
|
|
1583
1680
|
}
|
|
1584
1681
|
|
|
1682
|
+
// src/groupSelection/groupSelection.ts
|
|
1683
|
+
var NONE = 0;
|
|
1684
|
+
function countSelected(selected, groupKeys) {
|
|
1685
|
+
return groupKeys.filter((key) => selected.includes(key)).length;
|
|
1686
|
+
}
|
|
1687
|
+
function resolveGroupSelection(selected, groupKeys) {
|
|
1688
|
+
const count = countSelected(selected, groupKeys);
|
|
1689
|
+
if (count === NONE) return { all: false, some: false };
|
|
1690
|
+
return count === groupKeys.length ? { all: true, some: false } : { all: false, some: true };
|
|
1691
|
+
}
|
|
1692
|
+
function groupAriaChecked(state) {
|
|
1693
|
+
if (state.all) return true;
|
|
1694
|
+
return state.some ? "mixed" : false;
|
|
1695
|
+
}
|
|
1696
|
+
function toggleGroupSelection(selected, groupKeys, order) {
|
|
1697
|
+
const { all } = resolveGroupSelection(selected, groupKeys);
|
|
1698
|
+
if (all) return selected.filter((key) => !groupKeys.includes(key));
|
|
1699
|
+
const merged = [...selected];
|
|
1700
|
+
groupKeys.forEach((key) => {
|
|
1701
|
+
if (!merged.includes(key)) merged.push(key);
|
|
1702
|
+
});
|
|
1703
|
+
return order === void 0 ? merged : order.filter((key) => merged.includes(key));
|
|
1704
|
+
}
|
|
1705
|
+
|
|
1585
1706
|
exports.AnchoredMenu = AnchoredMenu;
|
|
1586
1707
|
exports.ChipSelector = ChipSelector;
|
|
1587
1708
|
exports.DEFAULT_MAX_RECENTS = DEFAULT_MAX_RECENTS;
|
|
@@ -1601,8 +1722,11 @@ exports.SelectControl = SelectControl;
|
|
|
1601
1722
|
exports.ThemedTextInput = ThemedTextInput;
|
|
1602
1723
|
exports.TypeaheadControl = TypeaheadControl;
|
|
1603
1724
|
exports.controlStyles = controlStyles;
|
|
1725
|
+
exports.groupAriaChecked = groupAriaChecked;
|
|
1604
1726
|
exports.isUnmatched = isUnmatched;
|
|
1727
|
+
exports.resolveGroupSelection = resolveGroupSelection;
|
|
1605
1728
|
exports.suggestOptions = suggestOptions;
|
|
1729
|
+
exports.toggleGroupSelection = toggleGroupSelection;
|
|
1606
1730
|
exports.useRecentValues = useRecentValues;
|
|
1607
1731
|
exports.useThemedInput = useThemedInput;
|
|
1608
1732
|
//# sourceMappingURL=index.js.map
|