@choice-ui/react 2.0.1 → 2.0.2

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.
Files changed (36) hide show
  1. package/dist/components/button/dist/index.js +7 -0
  2. package/dist/components/checkbox/dist/index.d.ts +10 -1
  3. package/dist/components/checkbox/dist/index.js +49 -5
  4. package/dist/components/colors/dist/index.d.ts +39 -6
  5. package/dist/components/colors/src/color-image-paint/color-image-paint.js +2 -2
  6. package/dist/components/command/dist/index.d.ts +13 -0
  7. package/dist/components/dropdown/dist/index.d.ts +6 -0
  8. package/dist/components/dropdown/dist/index.js +20 -10
  9. package/dist/components/emoji-picker/dist/index.d.ts +29 -1
  10. package/dist/components/emoji-picker/dist/index.js +144 -42
  11. package/dist/components/form/src/adapters/range-adapter.js +2 -2
  12. package/dist/components/icon-button/dist/index.d.ts +1 -1
  13. package/dist/components/icon-button/dist/index.js +39 -0
  14. package/dist/components/list/dist/index.d.ts +1 -1
  15. package/dist/components/md-render/src/md-render.js +4 -0
  16. package/dist/components/md-render/src/types.d.ts +3 -0
  17. package/dist/components/menus/dist/index.d.ts +5 -0
  18. package/dist/components/menus/dist/index.js +32 -3
  19. package/dist/components/numeric-input/dist/index.d.ts +2 -0
  20. package/dist/components/numeric-input/dist/index.js +64 -24
  21. package/dist/components/numeric-input/src/hooks/use-input-interactions.d.ts +3 -1
  22. package/dist/components/numeric-input/src/hooks/use-input-interactions.js +7 -3
  23. package/dist/components/numeric-input/src/hooks/use-numeric-input.js +15 -4
  24. package/dist/components/numeric-input/src/numeric-input.js +5 -4
  25. package/dist/components/numeric-input/src/utils/value-comparator.js +1 -5
  26. package/dist/components/radio/dist/index.d.ts +9 -1
  27. package/dist/components/radio/dist/index.js +50 -6
  28. package/dist/components/range/dist/index.d.ts +276 -20
  29. package/dist/components/range/dist/index.js +1030 -602
  30. package/dist/components/scroll-area/dist/index.d.ts +4 -27
  31. package/dist/components/scroll-area/dist/index.js +96 -123
  32. package/dist/components/textarea/dist/index.js +3 -1
  33. package/dist/components/tooltip/dist/index.d.ts +2 -0
  34. package/dist/components/tooltip/dist/index.js +23 -5
  35. package/dist/components/virtual-select/dist/index.d.ts +48 -0
  36. package/package.json +19 -31
@@ -1,5 +1,5 @@
1
1
  import { Tooltip } from "../../tooltip/dist/index.js";
2
- import { forwardRef, useRef, useState, useMemo, createContext, cloneElement, memo, useEffect, useCallback, Children, isValidElement, useContext } from "react";
2
+ import { forwardRef, useRef, useState, useMemo, createContext, cloneElement, memo, useCallback, useEffect, Children, isValidElement, useContext } from "react";
3
3
  import { useEventCallback } from "usehooks-ts";
4
4
  import { jsx, jsxs } from "react/jsx-runtime";
5
5
  import { IconButton } from "../../icon-button/dist/index.js";
@@ -774,9 +774,6 @@ function compareNumberResults(result1, result2) {
774
774
  const isSameObject = compareNumericObjects(result1.object, result2.object);
775
775
  return isSameArray || isSameObject;
776
776
  }
777
- function isExpressionInput(displayValue, processedValue) {
778
- return displayValue !== processedValue.string;
779
- }
780
777
  function useInputInteractions({
781
778
  inputRef,
782
779
  displayValue,
@@ -787,6 +784,7 @@ function useInputInteractions({
787
784
  min,
788
785
  max,
789
786
  decimal,
787
+ defaultValue,
790
788
  disabled,
791
789
  readOnly,
792
790
  innerValue,
@@ -794,11 +792,14 @@ function useInputInteractions({
794
792
  updateValue,
795
793
  getCurrentStep,
796
794
  onChange,
795
+ onRawInputEditingChange,
797
796
  onEmpty,
798
797
  value
799
798
  }) {
800
799
  const initialValueRef = useRef("");
800
+ const outputShapeSource = value ?? defaultValue;
801
801
  const handleInputChange = useEventCallback((e) => {
802
+ onRawInputEditingChange == null ? void 0 : onRawInputEditingChange(true);
802
803
  setDisplayValue(e.target.value);
803
804
  });
804
805
  const handleInputFocus = useEventCallback((e) => {
@@ -807,6 +808,7 @@ function useInputInteractions({
807
808
  e.target.select();
808
809
  });
809
810
  const handleInputBlur = useEventCallback(() => {
811
+ onRawInputEditingChange == null ? void 0 : onRawInputEditingChange(false);
810
812
  setIsFocused(false);
811
813
  if (disabled || readOnly) return;
812
814
  try {
@@ -817,7 +819,6 @@ function useInputInteractions({
817
819
  min,
818
820
  decimal
819
821
  });
820
- const isExpressionInputValue = isExpressionInput(displayValue, valuePre);
821
822
  const isSameValue = compareNumberResults(innerValue, valuePre);
822
823
  if (isSameValue) {
823
824
  setDisplayValue(valuePre.string);
@@ -826,7 +827,7 @@ function useInputInteractions({
826
827
  }
827
828
  setValue(valuePre);
828
829
  onChange == null ? void 0 : onChange(
829
- typeof value === "string" ? valuePre.string : typeof value === "number" ? valuePre.array[0] : Array.isArray(value) ? valuePre.array : valuePre.object,
830
+ typeof outputShapeSource === "string" ? valuePre.string : typeof outputShapeSource === "number" ? valuePre.array[0] : Array.isArray(outputShapeSource) ? valuePre.array : valuePre.object,
830
831
  valuePre
831
832
  );
832
833
  setDisplayValue(valuePre.string);
@@ -919,11 +920,16 @@ function useNumericInput(props) {
919
920
  step = 1,
920
921
  value,
921
922
  onChange,
923
+ onChangeEnd,
922
924
  onEmpty,
923
925
  onPressEnd,
924
926
  onPressStart
925
927
  } = props;
926
928
  const innerRef = useRef(null);
929
+ const dragHasChangedRef = useRef(false);
930
+ const dragEndValueRef = useRef(void 0);
931
+ const dragEndDetailRef = useRef(void 0);
932
+ const hasPendingRawInputRef = useRef(false);
927
933
  const [isFocused, setIsFocused] = useState(false);
928
934
  const [displayValue, setDisplayValue] = useState("");
929
935
  const { shiftPressed, metaPressed } = useModifierKeys(disabled);
@@ -941,9 +947,16 @@ function useNumericInput(props) {
941
947
  defaultValue: defaultValuePre,
942
948
  allowEmpty: true
943
949
  });
950
+ const outputShapeSource = value ?? defaultValue;
951
+ const mapResultToOutputValue = useCallback(
952
+ (result) => typeof outputShapeSource === "string" ? result.string : typeof outputShapeSource === "number" ? result.array[0] : Array.isArray(outputShapeSource) ? result.array : result.object,
953
+ [outputShapeSource]
954
+ );
944
955
  useEffect(() => {
945
956
  if (!innerValue) {
946
- setDisplayValue("");
957
+ if (!hasPendingRawInputRef.current) {
958
+ setDisplayValue("");
959
+ }
947
960
  return;
948
961
  }
949
962
  const valuePre2 = dealWithNumericInputValue({
@@ -956,11 +969,14 @@ function useNumericInput(props) {
956
969
  if (JSON.stringify(valuePre2.object) !== JSON.stringify(innerValue.object)) {
957
970
  setValue(valuePre2);
958
971
  }
959
- setDisplayValue(valuePre2.string);
972
+ if (!hasPendingRawInputRef.current) {
973
+ setDisplayValue(valuePre2.string);
974
+ }
960
975
  }, [innerValue, expression, max, min, decimal, setValue]);
961
976
  const updateValue = useCallback(
962
- (updateFn) => {
977
+ (updateFn, options) => {
963
978
  if (disabled || readOnly) return;
979
+ hasPendingRawInputRef.current = false;
964
980
  setValue((prev) => {
965
981
  if (!prev) {
966
982
  const initialValue = dealWithNumericInputValue({
@@ -971,10 +987,13 @@ function useNumericInput(props) {
971
987
  min,
972
988
  decimal
973
989
  });
974
- onChange == null ? void 0 : onChange(
975
- typeof value === "string" ? initialValue.string : typeof value === "number" ? initialValue.array[0] : Array.isArray(value) ? initialValue.array : initialValue.object,
976
- initialValue
977
- );
990
+ const nextValue = mapResultToOutputValue(initialValue);
991
+ onChange == null ? void 0 : onChange(nextValue, initialValue);
992
+ if ((options == null ? void 0 : options.source) === "drag") {
993
+ dragHasChangedRef.current = true;
994
+ dragEndValueRef.current = nextValue;
995
+ dragEndDetailRef.current = initialValue;
996
+ }
978
997
  return initialValue;
979
998
  }
980
999
  const valuePre2 = dealWithNumericInputValue({
@@ -998,15 +1017,18 @@ function useNumericInput(props) {
998
1017
  return true;
999
1018
  })();
1000
1019
  if (hasChanged) {
1001
- onChange == null ? void 0 : onChange(
1002
- typeof value === "string" ? valuePre2.string : typeof value === "number" ? valuePre2.array[0] : Array.isArray(value) ? valuePre2.array : valuePre2.object,
1003
- valuePre2
1004
- );
1020
+ const nextValue = mapResultToOutputValue(valuePre2);
1021
+ onChange == null ? void 0 : onChange(nextValue, valuePre2);
1022
+ if ((options == null ? void 0 : options.source) === "drag") {
1023
+ dragHasChangedRef.current = true;
1024
+ dragEndValueRef.current = nextValue;
1025
+ dragEndDetailRef.current = valuePre2;
1026
+ }
1005
1027
  }
1006
1028
  return valuePre2;
1007
1029
  });
1008
1030
  },
1009
- [disabled, readOnly, setValue, max, min, decimal, onChange, value]
1031
+ [disabled, readOnly, setValue, max, min, decimal, onChange, expressionRef, mapResultToOutputValue]
1010
1032
  );
1011
1033
  const { inputHandlers } = useInputInteractions({
1012
1034
  inputRef: innerRef,
@@ -1018,6 +1040,7 @@ function useNumericInput(props) {
1018
1040
  min,
1019
1041
  max,
1020
1042
  decimal,
1043
+ defaultValue,
1021
1044
  disabled,
1022
1045
  readOnly,
1023
1046
  innerValue,
@@ -1025,12 +1048,18 @@ function useNumericInput(props) {
1025
1048
  updateValue,
1026
1049
  getCurrentStep,
1027
1050
  onChange,
1051
+ onRawInputEditingChange: (editing) => {
1052
+ hasPendingRawInputRef.current = editing;
1053
+ },
1028
1054
  onEmpty,
1029
1055
  value
1030
1056
  });
1031
1057
  const { isPressed: handlerPressed, pressMoveProps } = usePressMove({
1032
1058
  disabled,
1033
1059
  onPressStart: (e) => {
1060
+ dragHasChangedRef.current = false;
1061
+ dragEndValueRef.current = void 0;
1062
+ dragEndDetailRef.current = void 0;
1034
1063
  const wasFocused = isFocused;
1035
1064
  if (onPressStart && "nativeEvent" in e) {
1036
1065
  onPressStart(e.nativeEvent);
@@ -1056,12 +1085,18 @@ function useNumericInput(props) {
1056
1085
  onPressEnd(e.nativeEvent);
1057
1086
  }
1058
1087
  onPressEnd == null ? void 0 : onPressEnd(e);
1088
+ if (dragHasChangedRef.current && dragEndValueRef.current !== void 0 && dragEndDetailRef.current !== void 0) {
1089
+ onChangeEnd == null ? void 0 : onChangeEnd(dragEndValueRef.current, dragEndDetailRef.current);
1090
+ }
1091
+ dragHasChangedRef.current = false;
1092
+ dragEndValueRef.current = void 0;
1093
+ dragEndDetailRef.current = void 0;
1059
1094
  },
1060
1095
  onPressMoveLeft: (delta) => {
1061
- updateValue((value2) => value2 - delta * getCurrentStep());
1096
+ updateValue((value2) => value2 - delta * getCurrentStep(), { source: "drag" });
1062
1097
  },
1063
1098
  onPressMoveRight: (delta) => {
1064
- updateValue((value2) => value2 + delta * getCurrentStep());
1099
+ updateValue((value2) => value2 + delta * getCurrentStep(), { source: "drag" });
1065
1100
  }
1066
1101
  });
1067
1102
  const inputProps = {
@@ -1104,6 +1139,7 @@ var NumericInputBase = forwardRef((props, ref) => {
1104
1139
  selected = false,
1105
1140
  tooltip,
1106
1141
  onChange,
1142
+ onChangeEnd,
1107
1143
  onEmpty,
1108
1144
  onPressEnd,
1109
1145
  onPressStart,
@@ -1127,6 +1163,7 @@ var NumericInputBase = forwardRef((props, ref) => {
1127
1163
  step,
1128
1164
  value,
1129
1165
  onChange,
1166
+ onChangeEnd,
1130
1167
  onEmpty,
1131
1168
  onPressEnd,
1132
1169
  onPressStart,
@@ -1134,6 +1171,7 @@ var NumericInputBase = forwardRef((props, ref) => {
1134
1171
  });
1135
1172
  const { disableScrollProps } = useDisableScroll({ ref: inputRef });
1136
1173
  const [isFocused, setIsFocused] = useState(false);
1174
+ const mergedFocused = focused || isFocused;
1137
1175
  const handleFocus = useEventCallback((e) => {
1138
1176
  var _a;
1139
1177
  onIsEditingChange == null ? void 0 : onIsEditingChange(true);
@@ -1156,7 +1194,7 @@ var NumericInputBase = forwardRef((props, ref) => {
1156
1194
  disabled,
1157
1195
  readOnly,
1158
1196
  selected,
1159
- focused,
1197
+ focused: mergedFocused,
1160
1198
  handlerPressed,
1161
1199
  // Configuration
1162
1200
  min,
@@ -1167,6 +1205,7 @@ var NumericInputBase = forwardRef((props, ref) => {
1167
1205
  expression,
1168
1206
  // Event handling methods
1169
1207
  onChange,
1208
+ onChangeEnd,
1170
1209
  onEmpty,
1171
1210
  onPressStart,
1172
1211
  onPressEnd,
@@ -1182,7 +1221,7 @@ var NumericInputBase = forwardRef((props, ref) => {
1182
1221
  disabled,
1183
1222
  readOnly,
1184
1223
  selected,
1185
- focused,
1224
+ mergedFocused,
1186
1225
  handlerPressed,
1187
1226
  min,
1188
1227
  max,
@@ -1191,6 +1230,7 @@ var NumericInputBase = forwardRef((props, ref) => {
1191
1230
  decimal,
1192
1231
  expression,
1193
1232
  onChange,
1233
+ onChangeEnd,
1194
1234
  onEmpty,
1195
1235
  onPressStart,
1196
1236
  onPressEnd,
@@ -1234,7 +1274,7 @@ var NumericInputBase = forwardRef((props, ref) => {
1234
1274
  variant,
1235
1275
  size,
1236
1276
  selected: selected || handlerPressed,
1237
- focused,
1277
+ focused: mergedFocused,
1238
1278
  disabled,
1239
1279
  prefixElement: !!prefixNode,
1240
1280
  suffixElement: !!suffixNode,
@@ -1277,7 +1317,7 @@ var NumericInputBase = forwardRef((props, ref) => {
1277
1317
  variableNode && cloneElement(variableNode, { hasPrefixElement: !!prefixNode }),
1278
1318
  actionPromptNode && cloneElement(actionPromptNode),
1279
1319
  suffixNode && cloneElement(suffixNode, { position: "suffix" }),
1280
- tooltip && !isFocused && /* @__PURE__ */ jsx(Tooltip, { ...tooltip, children: /* @__PURE__ */ jsx(
1320
+ tooltip && !mergedFocused && /* @__PURE__ */ jsx(Tooltip, { ...tooltip, children: /* @__PURE__ */ jsx(
1281
1321
  "span",
1282
1322
  {
1283
1323
  tabIndex: -1,
@@ -2,6 +2,7 @@ import { default as React, RefObject } from 'react';
2
2
  import { NumberResult, NumericInputValue } from '../types';
3
3
  interface UseInputInteractionsProps<T extends NumericInputValue> {
4
4
  decimal?: number;
5
+ defaultValue?: T;
5
6
  disabled?: boolean;
6
7
  displayValue: string;
7
8
  expression: string;
@@ -12,6 +13,7 @@ interface UseInputInteractionsProps<T extends NumericInputValue> {
12
13
  max?: number;
13
14
  min?: number;
14
15
  onChange?: (value: T, detail: NumberResult) => void;
16
+ onRawInputEditingChange?: (editing: boolean) => void;
15
17
  onEmpty?: () => void;
16
18
  readOnly?: boolean;
17
19
  setDisplayValue: (value: string) => void;
@@ -27,7 +29,7 @@ interface UseInputInteractionsProps<T extends NumericInputValue> {
27
29
  * @param props Input interaction configuration
28
30
  * @returns Input handlers and initial value reference
29
31
  */
30
- export declare function useInputInteractions<T extends NumericInputValue>({ inputRef, displayValue, setDisplayValue, isFocused, setIsFocused, expression, min, max, decimal, disabled, readOnly, innerValue, setValue, updateValue, getCurrentStep, onChange, onEmpty, value, }: UseInputInteractionsProps<T>): {
32
+ export declare function useInputInteractions<T extends NumericInputValue>({ inputRef, displayValue, setDisplayValue, isFocused, setIsFocused, expression, min, max, decimal, defaultValue, disabled, readOnly, innerValue, setValue, updateValue, getCurrentStep, onChange, onRawInputEditingChange, onEmpty, value, }: UseInputInteractionsProps<T>): {
31
33
  inputHandlers: {
32
34
  onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
33
35
  onFocus: (e: React.FocusEvent<HTMLInputElement, Element>) => void;
@@ -1,7 +1,7 @@
1
1
  import { useRef } from "react";
2
2
  import { useEventCallback } from "usehooks-ts";
3
3
  import { dealWithNumericInputValue } from "../utils/numeric-value-processor.js";
4
- import { isExpressionInput, compareNumberResults } from "../utils/value-comparator.js";
4
+ import { compareNumberResults } from "../utils/value-comparator.js";
5
5
  function useInputInteractions({
6
6
  inputRef,
7
7
  displayValue,
@@ -12,6 +12,7 @@ function useInputInteractions({
12
12
  min,
13
13
  max,
14
14
  decimal,
15
+ defaultValue,
15
16
  disabled,
16
17
  readOnly,
17
18
  innerValue,
@@ -19,11 +20,14 @@ function useInputInteractions({
19
20
  updateValue,
20
21
  getCurrentStep,
21
22
  onChange,
23
+ onRawInputEditingChange,
22
24
  onEmpty,
23
25
  value
24
26
  }) {
25
27
  const initialValueRef = useRef("");
28
+ const outputShapeSource = value ?? defaultValue;
26
29
  const handleInputChange = useEventCallback((e) => {
30
+ onRawInputEditingChange == null ? void 0 : onRawInputEditingChange(true);
27
31
  setDisplayValue(e.target.value);
28
32
  });
29
33
  const handleInputFocus = useEventCallback((e) => {
@@ -32,6 +36,7 @@ function useInputInteractions({
32
36
  e.target.select();
33
37
  });
34
38
  const handleInputBlur = useEventCallback(() => {
39
+ onRawInputEditingChange == null ? void 0 : onRawInputEditingChange(false);
35
40
  setIsFocused(false);
36
41
  if (disabled || readOnly) return;
37
42
  try {
@@ -42,7 +47,6 @@ function useInputInteractions({
42
47
  min,
43
48
  decimal
44
49
  });
45
- const isExpressionInputValue = isExpressionInput(displayValue, valuePre);
46
50
  const isSameValue = compareNumberResults(innerValue, valuePre);
47
51
  if (isSameValue) {
48
52
  setDisplayValue(valuePre.string);
@@ -51,7 +55,7 @@ function useInputInteractions({
51
55
  }
52
56
  setValue(valuePre);
53
57
  onChange == null ? void 0 : onChange(
54
- typeof value === "string" ? valuePre.string : typeof value === "number" ? valuePre.array[0] : Array.isArray(value) ? valuePre.array : valuePre.object,
58
+ typeof outputShapeSource === "string" ? valuePre.string : typeof outputShapeSource === "number" ? valuePre.array[0] : Array.isArray(outputShapeSource) ? valuePre.array : valuePre.object,
55
59
  valuePre
56
60
  );
57
61
  setDisplayValue(valuePre.string);
@@ -30,6 +30,7 @@ function useNumericInput(props) {
30
30
  const dragHasChangedRef = useRef(false);
31
31
  const dragEndValueRef = useRef(void 0);
32
32
  const dragEndDetailRef = useRef(void 0);
33
+ const hasPendingRawInputRef = useRef(false);
33
34
  const [isFocused, setIsFocused] = useState(false);
34
35
  const [displayValue, setDisplayValue] = useState("");
35
36
  const { shiftPressed, metaPressed } = useModifierKeys(disabled);
@@ -47,13 +48,16 @@ function useNumericInput(props) {
47
48
  defaultValue: defaultValuePre,
48
49
  allowEmpty: true
49
50
  });
51
+ const outputShapeSource = value ?? defaultValue;
50
52
  const mapResultToOutputValue = useCallback(
51
- (result) => typeof value === "string" ? result.string : typeof value === "number" ? result.array[0] : Array.isArray(value) ? result.array : result.object,
52
- [value]
53
+ (result) => typeof outputShapeSource === "string" ? result.string : typeof outputShapeSource === "number" ? result.array[0] : Array.isArray(outputShapeSource) ? result.array : result.object,
54
+ [outputShapeSource]
53
55
  );
54
56
  useEffect(() => {
55
57
  if (!innerValue) {
56
- setDisplayValue("");
58
+ if (!hasPendingRawInputRef.current) {
59
+ setDisplayValue("");
60
+ }
57
61
  return;
58
62
  }
59
63
  const valuePre2 = dealWithNumericInputValue({
@@ -66,11 +70,14 @@ function useNumericInput(props) {
66
70
  if (JSON.stringify(valuePre2.object) !== JSON.stringify(innerValue.object)) {
67
71
  setValue(valuePre2);
68
72
  }
69
- setDisplayValue(valuePre2.string);
73
+ if (!hasPendingRawInputRef.current) {
74
+ setDisplayValue(valuePre2.string);
75
+ }
70
76
  }, [innerValue, expression, max, min, decimal, setValue]);
71
77
  const updateValue = useCallback(
72
78
  (updateFn, options) => {
73
79
  if (disabled || readOnly) return;
80
+ hasPendingRawInputRef.current = false;
74
81
  setValue((prev) => {
75
82
  if (!prev) {
76
83
  const initialValue = dealWithNumericInputValue({
@@ -134,6 +141,7 @@ function useNumericInput(props) {
134
141
  min,
135
142
  max,
136
143
  decimal,
144
+ defaultValue,
137
145
  disabled,
138
146
  readOnly,
139
147
  innerValue,
@@ -141,6 +149,9 @@ function useNumericInput(props) {
141
149
  updateValue,
142
150
  getCurrentStep,
143
151
  onChange,
152
+ onRawInputEditingChange: (editing) => {
153
+ hasPendingRawInputRef.current = editing;
154
+ },
144
155
  onEmpty,
145
156
  value
146
157
  });
@@ -67,6 +67,7 @@ const NumericInputBase = forwardRef((props, ref) => {
67
67
  });
68
68
  const { disableScrollProps } = useDisableScroll({ ref: inputRef });
69
69
  const [isFocused, setIsFocused] = useState(false);
70
+ const mergedFocused = focused || isFocused;
70
71
  const handleFocus = useEventCallback((e) => {
71
72
  var _a;
72
73
  onIsEditingChange == null ? void 0 : onIsEditingChange(true);
@@ -89,7 +90,7 @@ const NumericInputBase = forwardRef((props, ref) => {
89
90
  disabled,
90
91
  readOnly,
91
92
  selected,
92
- focused,
93
+ focused: mergedFocused,
93
94
  handlerPressed,
94
95
  // Configuration
95
96
  min,
@@ -116,7 +117,7 @@ const NumericInputBase = forwardRef((props, ref) => {
116
117
  disabled,
117
118
  readOnly,
118
119
  selected,
119
- focused,
120
+ mergedFocused,
120
121
  handlerPressed,
121
122
  min,
122
123
  max,
@@ -169,7 +170,7 @@ const NumericInputBase = forwardRef((props, ref) => {
169
170
  variant,
170
171
  size,
171
172
  selected: selected || handlerPressed,
172
- focused,
173
+ focused: mergedFocused,
173
174
  disabled,
174
175
  prefixElement: !!prefixNode,
175
176
  suffixElement: !!suffixNode,
@@ -212,7 +213,7 @@ const NumericInputBase = forwardRef((props, ref) => {
212
213
  variableNode && cloneElement(variableNode, { hasPrefixElement: !!prefixNode }),
213
214
  actionPromptNode && cloneElement(actionPromptNode),
214
215
  suffixNode && cloneElement(suffixNode, { position: "suffix" }),
215
- tooltip && !isFocused && /* @__PURE__ */ jsx(Tooltip, { ...tooltip, children: /* @__PURE__ */ jsx(
216
+ tooltip && !mergedFocused && /* @__PURE__ */ jsx(Tooltip, { ...tooltip, children: /* @__PURE__ */ jsx(
216
217
  "span",
217
218
  {
218
219
  tabIndex: -1,
@@ -21,12 +21,8 @@ function compareNumberResults(result1, result2) {
21
21
  const isSameObject = compareNumericObjects(result1.object, result2.object);
22
22
  return isSameArray || isSameObject;
23
23
  }
24
- function isExpressionInput(displayValue, processedValue) {
25
- return displayValue !== processedValue.string;
26
- }
27
24
  export {
28
25
  compareNumberResults,
29
26
  compareNumericArrays,
30
- compareNumericObjects,
31
- isExpressionInput
27
+ compareNumericObjects
32
28
  };
@@ -1,6 +1,13 @@
1
1
  import { HTMLProps, ReactNode } from 'react';
2
2
  import * as react from 'react';
3
3
 
4
+ interface RadioIconProps extends Omit<HTMLProps<HTMLDivElement>, "children"> {
5
+ children?: ReactNode | ((props: {
6
+ value?: boolean;
7
+ }) => ReactNode);
8
+ }
9
+ declare const RadioIcon: react.MemoExoticComponent<react.ForwardRefExoticComponent<Omit<RadioIconProps, "ref"> & react.RefAttributes<HTMLDivElement>>>;
10
+
4
11
  interface RadioLabelProps extends Omit<HTMLProps<HTMLLabelElement>, "htmlFor" | "id" | "disabled"> {
5
12
  children: ReactNode;
6
13
  }
@@ -19,6 +26,7 @@ interface RadioType {
19
26
  (props: RadioProps & {
20
27
  ref?: React.Ref<HTMLInputElement>;
21
28
  }): JSX.Element;
29
+ Icon: typeof RadioIcon;
22
30
  Label: typeof RadioLabel;
23
31
  displayName?: string;
24
32
  }
@@ -50,4 +58,4 @@ interface RadioGroupType {
50
58
  }
51
59
  declare const RadioGroup: RadioGroupType;
52
60
 
53
- export { Radio, RadioGroup, type RadioGroupProps, type RadioProps };
61
+ export { Radio, RadioGroup, type RadioGroupProps, type RadioIconProps, type RadioLabelProps, type RadioProps };
@@ -1,5 +1,5 @@
1
1
  import { Dot } from "@choiceform/icons-react";
2
- import { memo, forwardRef, useId, useMemo, createContext, useContext } from "react";
2
+ import { memo, forwardRef, useId, useMemo, createContext, useContext, Children, isValidElement } from "react";
3
3
  import { useEventCallback } from "usehooks-ts";
4
4
  import { jsx, jsxs } from "react/jsx-runtime";
5
5
  import { tcx, tcv } from "../../../shared/utils/tcx/tcx.js";
@@ -145,6 +145,38 @@ var radioTv = tcv({
145
145
  focused: false
146
146
  }
147
147
  });
148
+ var RadioIcon = memo(
149
+ forwardRef(function RadioIcon2(props, ref) {
150
+ const { className, children, ...rest } = props;
151
+ const { value, disabled, variant } = useRadioContext();
152
+ const tv = radioTv({
153
+ type: "radio",
154
+ variant,
155
+ disabled,
156
+ checked: value
157
+ });
158
+ const renderIcon = () => {
159
+ if (typeof children === "function") {
160
+ return children({ value });
161
+ }
162
+ if (children !== void 0) {
163
+ return children;
164
+ }
165
+ return value ? /* @__PURE__ */ jsx(Dot, {}) : null;
166
+ };
167
+ return /* @__PURE__ */ jsx(
168
+ "div",
169
+ {
170
+ ref,
171
+ className: tcx(tv.box(), className),
172
+ "data-active": value,
173
+ ...rest,
174
+ children: renderIcon()
175
+ }
176
+ );
177
+ })
178
+ );
179
+ RadioIcon.displayName = "Radio.Icon";
148
180
  var RadioLabel = memo(
149
181
  forwardRef(function RadioLabel2(props, ref) {
150
182
  const { children, className, ...rest } = props;
@@ -201,13 +233,24 @@ var RadioBase = forwardRef(function Radio(props, ref) {
201
233
  }
202
234
  onKeyDown == null ? void 0 : onKeyDown(e);
203
235
  });
236
+ const isIconElement = (child) => {
237
+ var _a;
238
+ return isValidElement(child) && (child.type === RadioIcon || ((_a = child.type) == null ? void 0 : _a.displayName) === "Radio.Icon");
239
+ };
240
+ const childArray = Children.toArray(children);
241
+ const iconChild = childArray.find(isIconElement);
242
+ const otherChildren = childArray.filter((child) => !isIconElement(child));
204
243
  const renderChildren = () => {
205
- if (typeof children === "string" || typeof children === "number") {
206
- return /* @__PURE__ */ jsx(RadioLabel, { children });
244
+ if (otherChildren.length === 1) {
245
+ const child = otherChildren[0];
246
+ if (typeof child === "string" || typeof child === "number") {
247
+ return /* @__PURE__ */ jsx(RadioLabel, { children: child });
248
+ }
207
249
  }
208
- return children;
250
+ return otherChildren;
209
251
  };
210
- return /* @__PURE__ */ jsx(RadioContext.Provider, { value: { id, descriptionId, disabled }, children: /* @__PURE__ */ jsxs("div", { className: tcx(tv.root(), className), children: [
252
+ const renderDefaultIcon = () => /* @__PURE__ */ jsx("div", { className: tv.box(), children: value && /* @__PURE__ */ jsx(Dot, {}) });
253
+ return /* @__PURE__ */ jsx(RadioContext.Provider, { value: { id, descriptionId, disabled, value, variant }, children: /* @__PURE__ */ jsxs("div", { className: tcx(tv.root(), className), children: [
211
254
  /* @__PURE__ */ jsxs("div", { className: "pointer-events-none relative", children: [
212
255
  /* @__PURE__ */ jsx(
213
256
  "input",
@@ -229,13 +272,14 @@ var RadioBase = forwardRef(function Radio(props, ref) {
229
272
  ...rest
230
273
  }
231
274
  ),
232
- /* @__PURE__ */ jsx("div", { className: tv.box(), children: value && /* @__PURE__ */ jsx(Dot, {}) })
275
+ iconChild ?? renderDefaultIcon()
233
276
  ] }),
234
277
  renderChildren()
235
278
  ] }) });
236
279
  });
237
280
  var MemoizedRadio = memo(RadioBase);
238
281
  var Radio2 = MemoizedRadio;
282
+ Radio2.Icon = RadioIcon;
239
283
  Radio2.Label = RadioLabel;
240
284
  Radio2.displayName = "Radio";
241
285
  var RadioGroupItem = memo(