@mpen/react-basic-inputs 0.1.11 → 0.2.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/dist/bundle.cjs DELETED
@@ -1,328 +0,0 @@
1
- "use strict";
2
-
3
- var jsxRuntime = require("react/jsx-runtime");
4
-
5
- var React = require("react");
6
-
7
- const NOOP = Object.freeze((() => {}));
8
-
9
- function identity(x) {
10
- return x;
11
- }
12
-
13
- let useEventHandler;
14
-
15
- if (typeof window !== "undefined") {
16
- useEventHandler = callback => {
17
- React.useDebugValue(callback);
18
- const latestRef = React.useRef(useEvent_shouldNotBeInvokedBeforeMount);
19
- React.useInsertionEffect((() => {
20
- latestRef.current = callback;
21
- }), [ callback ]);
22
- const stableRef = React.useRef(null);
23
- if (!stableRef.current) {
24
- stableRef.current = function() {
25
- return latestRef.current.apply(this, arguments);
26
- };
27
- }
28
- return stableRef.current;
29
- };
30
- } else {
31
- useEventHandler = NOOP;
32
- }
33
-
34
- function useEvent(handler) {
35
- return useEventHandler(handler);
36
- }
37
-
38
- function useEvent_shouldNotBeInvokedBeforeMount() {
39
- throw new Error("INVALID_USE_EVENT_INVOCATION: the callback from useEvent cannot be invoked before the component has mounted.");
40
- }
41
-
42
- function resolveValue(val, ...args) {
43
- return typeof val === "function" ? val(...args) : val;
44
- }
45
-
46
- function useFirstMountState() {
47
- var isFirst = React.useRef(true);
48
- if (isFirst.current) {
49
- isFirst.current = false;
50
- return true;
51
- }
52
- return isFirst.current;
53
- }
54
-
55
- var useUpdateEffect = function(effect, deps) {
56
- var isFirstMount = useFirstMountState();
57
- React.useEffect((function() {
58
- if (!isFirstMount) {
59
- return effect();
60
- }
61
- }), deps);
62
- };
63
-
64
- var useUpdateEffect$1 = useUpdateEffect;
65
-
66
- function defaultMakeKey(opt, idx) {
67
- if (opt.key != null) {
68
- return resolveValue(opt.key, opt, idx);
69
- } else if (typeof opt.value === "string" || typeof opt.value === "number") {
70
- return opt.value;
71
- }
72
- return idx;
73
- }
74
-
75
- class KeyFixer {
76
- usedKeys=new Map;
77
- fix(opt, idx) {
78
- let fixedKey = defaultMakeKey(opt, idx);
79
- for (;;) {
80
- let suffix = this.usedKeys.get(fixedKey);
81
- if (suffix === undefined) {
82
- this.usedKeys.set(fixedKey, 1);
83
- break;
84
- }
85
- this.usedKeys.set(fixedKey, ++suffix);
86
- fixedKey = `${fixedKey}(${suffix})`;
87
- }
88
- return fixedKey;
89
- }
90
- }
91
-
92
- const defaultMakeInvalidValueOption = value => ({
93
- value,
94
- text: String(value),
95
- disabled: true,
96
- key: INVALID_OPTION_KEY
97
- });
98
-
99
- const PLACEHOLDER_KEY = "3c9369b7-0a5e-46ea-93c2-e8b9fec67fdb";
100
-
101
- const INVALID_OPTION_KEY = "1a53f789-77f5-4ce6-a829-b00e563f1ee8";
102
-
103
- function Select({options, value, invalidValueOption = defaultMakeInvalidValueOption, onChange, placeholder, ...selectAttrs}) {
104
- const isNotSelected = value == null;
105
- const isValid = React.useMemo((() => value != null && options.some((o => o.value == value))), [ options, value ]);
106
- const extraOption = React.useMemo((() => {
107
- if (value == null || !invalidValueOption) return null;
108
- return invalidValueOption(value);
109
- }), [ invalidValueOption, value ]);
110
- const fixedOptions = React.useMemo((() => {
111
- if (isValid) return options;
112
- const fixedOptions = [ ...options ];
113
- if (isNotSelected) {
114
- if (placeholder != null) {
115
- fixedOptions.unshift({
116
- text: placeholder,
117
- hidden: true,
118
- value: null,
119
- key: PLACEHOLDER_KEY
120
- });
121
- }
122
- } else if (extraOption) {
123
- fixedOptions.push(extraOption);
124
- }
125
- return fixedOptions;
126
- }), [ isValid, options, isNotSelected, extraOption, placeholder ]);
127
- const handleChange = useEvent((ev => {
128
- const idx = ev.target.selectedIndex;
129
- const opt = fixedOptions[idx];
130
- onChange?.({
131
- value: opt.value,
132
- index: idx,
133
- type: "change",
134
- timeStamp: ev.timeStamp,
135
- target: ev.target
136
- });
137
- }));
138
- const ref = React.useRef(null);
139
- const refreshSelectedIndex = React.useCallback((() => {
140
- if (!ref.current) return;
141
- if (ref.current.selectedIndex < 0 || fixedOptions[ref.current.selectedIndex].value != value) {
142
- ref.current.selectedIndex = fixedOptions.findIndex((opt => opt.value == value));
143
- }
144
- }), [ fixedOptions, value ]);
145
- const setRef = el => {
146
- ref.current = el;
147
- refreshSelectedIndex();
148
- };
149
- useUpdateEffect$1((() => {
150
- refreshSelectedIndex();
151
- }), [ refreshSelectedIndex ]);
152
- const fixer = new KeyFixer;
153
- return jsxRuntime.jsx("select", {
154
- ...selectAttrs,
155
- onChange: handleChange,
156
- ref: setRef,
157
- children: fixedOptions.map(((opt, idx) => {
158
- const {value, text, key, ...optAttrs} = opt;
159
- const fixedKey = fixer.fix(opt, idx);
160
- return React.createElement("option", {
161
- ...optAttrs,
162
- key: fixedKey,
163
- value: fixedKey
164
- }, opt.text);
165
- }))
166
- });
167
- }
168
-
169
- function collapseWhitespace(str) {
170
- if (!str) return "";
171
- return String(str).replace(/\s+/gu, " ").trim();
172
- }
173
-
174
- const Input = React.forwardRef((function Input({value = "", onChange, onInput, onBlur, formatOnChange = identity, ...otherProps}, ref) {
175
- const [currentValue, setCurrentValue] = React.useState(value);
176
- const lastValue = React.useRef(value);
177
- const modified = React.useRef(false);
178
- useUpdateEffect$1((() => {
179
- setCurrentValue(value);
180
- modified.current = false;
181
- lastValue.current = value;
182
- }), [ value ]);
183
- const props = {
184
- type: "text",
185
- ...otherProps,
186
- value: currentValue,
187
- onChange: ev => {
188
- setCurrentValue(ev.target.value);
189
- },
190
- onInput: ev => {
191
- modified.current = true;
192
- onInput?.(ev);
193
- },
194
- onBlur: ev => {
195
- const formattedValue = formatOnChange(currentValue);
196
- if (modified.current) {
197
- if (formattedValue !== lastValue.current) {
198
- onChange?.({
199
- type: "change",
200
- value: formattedValue,
201
- timeStamp: ev.timeStamp,
202
- target: ev.target
203
- });
204
- lastValue.current = formattedValue;
205
- }
206
- if (formattedValue !== ev.target.value) {
207
- setCurrentValue(formattedValue);
208
- }
209
- }
210
- onBlur?.(ev);
211
- }
212
- };
213
- return jsxRuntime.jsx("input", {
214
- ...props,
215
- ref
216
- });
217
- }));
218
-
219
- function TextInput({formatOnChange = collapseWhitespace, ...otherProps}) {
220
- return jsxRuntime.jsx(Input, {
221
- formatOnChange,
222
- ...otherProps,
223
- type: "text"
224
- });
225
- }
226
-
227
- const TextArea = React.forwardRef((function TextArea({onInput, style, initialHeight = "auto", ...rest}, fwdRef) {
228
- const ref = React.useRef(null);
229
- const [height, setHeight] = React.useState(initialHeight);
230
- const adjustHeight = React.useCallback((() => {
231
- const textarea = ref.current;
232
- if (!textarea) return;
233
- textarea.style.height = initialHeight;
234
- const newHeight = `${textarea.scrollHeight}px`;
235
- setHeight(newHeight);
236
- textarea.style.height = newHeight;
237
- }), [ initialHeight ]);
238
- React.useImperativeHandle(fwdRef, (() => ({
239
- element: ref.current,
240
- adjustHeight
241
- })), [ adjustHeight ]);
242
- const input = useEventHandler((ev => {
243
- adjustHeight();
244
- onInput?.(ev);
245
- }));
246
- React.useLayoutEffect((() => {
247
- adjustHeight();
248
- const textarea = ref.current;
249
- if (!textarea) return;
250
- const resizeObserver = new ResizeObserver((entries => {
251
- adjustHeight();
252
- }));
253
- resizeObserver.observe(textarea);
254
- return () => {
255
- resizeObserver.unobserve(textarea);
256
- };
257
- }), [ adjustHeight ]);
258
- return jsxRuntime.jsx("textarea", {
259
- ...rest,
260
- style: {
261
- overflow: "hidden",
262
- resize: "none",
263
- ...style,
264
- height
265
- },
266
- onInput: input,
267
- ref
268
- });
269
- }));
270
-
271
- function RadioMenu(menu) {
272
- const defaultId = React.useId();
273
- const name = menu.name ?? defaultId;
274
- const eq = menu.valueEquals ?? Object.is;
275
- const fixedOptions = menu.options ?? [];
276
- const fixer = new KeyFixer;
277
- const onChange = useEventHandler((ev => {
278
- const selectedIndex = Number(ev.target.value);
279
- const selectedOption = fixedOptions[selectedIndex];
280
- if (selectedOption != null && menu.onChange != null) {
281
- menu.onChange({
282
- value: selectedOption.value,
283
- index: selectedIndex,
284
- type: "change",
285
- timeStamp: ev.timeStamp,
286
- target: ev.target
287
- });
288
- }
289
- }));
290
- return jsxRuntime.jsx("ul", {
291
- className: menu.className,
292
- children: fixedOptions.map(((opt, idx) => {
293
- const {value, text, key, itemClassName, labelClassName, inputClassName, textClassName, ...rest} = opt;
294
- const fixedKey = fixer.fix(opt, idx);
295
- if (menu.value !== undefined) {
296
- rest.checked = eq(value, menu.value);
297
- }
298
- return jsxRuntime.jsx("li", {
299
- className: itemClassName,
300
- "aria-disabled": rest.disabled,
301
- children: jsxRuntime.jsxs("label", {
302
- className: labelClassName,
303
- children: [ jsxRuntime.jsx("input", {
304
- ...rest,
305
- className: inputClassName,
306
- value: idx,
307
- onChange,
308
- name,
309
- type: "radio"
310
- }), jsxRuntime.jsx("span", {
311
- className: textClassName,
312
- children: text
313
- }) ]
314
- })
315
- }, fixedKey);
316
- }))
317
- });
318
- }
319
-
320
- exports.Input = Input;
321
-
322
- exports.RadioMenu = RadioMenu;
323
-
324
- exports.Select = Select;
325
-
326
- exports.TextArea = TextArea;
327
-
328
- exports.TextInput = TextInput;
package/dist/bundle.d.ts DELETED
@@ -1,5 +0,0 @@
1
- export * from './components/Select';
2
- export * from './components/TextInput';
3
- export * from './components/Input';
4
- export * from './components/TextArea';
5
- export * from './components/RadioMenu';
package/dist/bundle.mjs DELETED
@@ -1,318 +0,0 @@
1
- import { jsx, jsxs } from "react/jsx-runtime";
2
-
3
- import { useDebugValue, useRef, useInsertionEffect, useEffect, useMemo, useCallback, createElement, forwardRef, useState, useImperativeHandle, useLayoutEffect, useId } from "react";
4
-
5
- const NOOP = Object.freeze((() => {}));
6
-
7
- function identity(x) {
8
- return x;
9
- }
10
-
11
- let useEventHandler;
12
-
13
- if (typeof window !== "undefined") {
14
- useEventHandler = callback => {
15
- useDebugValue(callback);
16
- const latestRef = useRef(useEvent_shouldNotBeInvokedBeforeMount);
17
- useInsertionEffect((() => {
18
- latestRef.current = callback;
19
- }), [ callback ]);
20
- const stableRef = useRef(null);
21
- if (!stableRef.current) {
22
- stableRef.current = function() {
23
- return latestRef.current.apply(this, arguments);
24
- };
25
- }
26
- return stableRef.current;
27
- };
28
- } else {
29
- useEventHandler = NOOP;
30
- }
31
-
32
- function useEvent(handler) {
33
- return useEventHandler(handler);
34
- }
35
-
36
- function useEvent_shouldNotBeInvokedBeforeMount() {
37
- throw new Error("INVALID_USE_EVENT_INVOCATION: the callback from useEvent cannot be invoked before the component has mounted.");
38
- }
39
-
40
- function resolveValue(val, ...args) {
41
- return typeof val === "function" ? val(...args) : val;
42
- }
43
-
44
- function useFirstMountState() {
45
- var isFirst = useRef(true);
46
- if (isFirst.current) {
47
- isFirst.current = false;
48
- return true;
49
- }
50
- return isFirst.current;
51
- }
52
-
53
- var useUpdateEffect = function(effect, deps) {
54
- var isFirstMount = useFirstMountState();
55
- useEffect((function() {
56
- if (!isFirstMount) {
57
- return effect();
58
- }
59
- }), deps);
60
- };
61
-
62
- var useUpdateEffect$1 = useUpdateEffect;
63
-
64
- function defaultMakeKey(opt, idx) {
65
- if (opt.key != null) {
66
- return resolveValue(opt.key, opt, idx);
67
- } else if (typeof opt.value === "string" || typeof opt.value === "number") {
68
- return opt.value;
69
- }
70
- return idx;
71
- }
72
-
73
- class KeyFixer {
74
- usedKeys=new Map;
75
- fix(opt, idx) {
76
- let fixedKey = defaultMakeKey(opt, idx);
77
- for (;;) {
78
- let suffix = this.usedKeys.get(fixedKey);
79
- if (suffix === undefined) {
80
- this.usedKeys.set(fixedKey, 1);
81
- break;
82
- }
83
- this.usedKeys.set(fixedKey, ++suffix);
84
- fixedKey = `${fixedKey}(${suffix})`;
85
- }
86
- return fixedKey;
87
- }
88
- }
89
-
90
- const defaultMakeInvalidValueOption = value => ({
91
- value,
92
- text: String(value),
93
- disabled: true,
94
- key: INVALID_OPTION_KEY
95
- });
96
-
97
- const PLACEHOLDER_KEY = "3c9369b7-0a5e-46ea-93c2-e8b9fec67fdb";
98
-
99
- const INVALID_OPTION_KEY = "1a53f789-77f5-4ce6-a829-b00e563f1ee8";
100
-
101
- function Select({options, value, invalidValueOption = defaultMakeInvalidValueOption, onChange, placeholder, ...selectAttrs}) {
102
- const isNotSelected = value == null;
103
- const isValid = useMemo((() => value != null && options.some((o => o.value == value))), [ options, value ]);
104
- const extraOption = useMemo((() => {
105
- if (value == null || !invalidValueOption) return null;
106
- return invalidValueOption(value);
107
- }), [ invalidValueOption, value ]);
108
- const fixedOptions = useMemo((() => {
109
- if (isValid) return options;
110
- const fixedOptions = [ ...options ];
111
- if (isNotSelected) {
112
- if (placeholder != null) {
113
- fixedOptions.unshift({
114
- text: placeholder,
115
- hidden: true,
116
- value: null,
117
- key: PLACEHOLDER_KEY
118
- });
119
- }
120
- } else if (extraOption) {
121
- fixedOptions.push(extraOption);
122
- }
123
- return fixedOptions;
124
- }), [ isValid, options, isNotSelected, extraOption, placeholder ]);
125
- const handleChange = useEvent((ev => {
126
- const idx = ev.target.selectedIndex;
127
- const opt = fixedOptions[idx];
128
- onChange?.({
129
- value: opt.value,
130
- index: idx,
131
- type: "change",
132
- timeStamp: ev.timeStamp,
133
- target: ev.target
134
- });
135
- }));
136
- const ref = useRef(null);
137
- const refreshSelectedIndex = useCallback((() => {
138
- if (!ref.current) return;
139
- if (ref.current.selectedIndex < 0 || fixedOptions[ref.current.selectedIndex].value != value) {
140
- ref.current.selectedIndex = fixedOptions.findIndex((opt => opt.value == value));
141
- }
142
- }), [ fixedOptions, value ]);
143
- const setRef = el => {
144
- ref.current = el;
145
- refreshSelectedIndex();
146
- };
147
- useUpdateEffect$1((() => {
148
- refreshSelectedIndex();
149
- }), [ refreshSelectedIndex ]);
150
- const fixer = new KeyFixer;
151
- return jsx("select", {
152
- ...selectAttrs,
153
- onChange: handleChange,
154
- ref: setRef,
155
- children: fixedOptions.map(((opt, idx) => {
156
- const {value, text, key, ...optAttrs} = opt;
157
- const fixedKey = fixer.fix(opt, idx);
158
- return createElement("option", {
159
- ...optAttrs,
160
- key: fixedKey,
161
- value: fixedKey
162
- }, opt.text);
163
- }))
164
- });
165
- }
166
-
167
- function collapseWhitespace(str) {
168
- if (!str) return "";
169
- return String(str).replace(/\s+/gu, " ").trim();
170
- }
171
-
172
- const Input = forwardRef((function Input({value = "", onChange, onInput, onBlur, formatOnChange = identity, ...otherProps}, ref) {
173
- const [currentValue, setCurrentValue] = useState(value);
174
- const lastValue = useRef(value);
175
- const modified = useRef(false);
176
- useUpdateEffect$1((() => {
177
- setCurrentValue(value);
178
- modified.current = false;
179
- lastValue.current = value;
180
- }), [ value ]);
181
- const props = {
182
- type: "text",
183
- ...otherProps,
184
- value: currentValue,
185
- onChange: ev => {
186
- setCurrentValue(ev.target.value);
187
- },
188
- onInput: ev => {
189
- modified.current = true;
190
- onInput?.(ev);
191
- },
192
- onBlur: ev => {
193
- const formattedValue = formatOnChange(currentValue);
194
- if (modified.current) {
195
- if (formattedValue !== lastValue.current) {
196
- onChange?.({
197
- type: "change",
198
- value: formattedValue,
199
- timeStamp: ev.timeStamp,
200
- target: ev.target
201
- });
202
- lastValue.current = formattedValue;
203
- }
204
- if (formattedValue !== ev.target.value) {
205
- setCurrentValue(formattedValue);
206
- }
207
- }
208
- onBlur?.(ev);
209
- }
210
- };
211
- return jsx("input", {
212
- ...props,
213
- ref
214
- });
215
- }));
216
-
217
- function TextInput({formatOnChange = collapseWhitespace, ...otherProps}) {
218
- return jsx(Input, {
219
- formatOnChange,
220
- ...otherProps,
221
- type: "text"
222
- });
223
- }
224
-
225
- const TextArea = forwardRef((function TextArea({onInput, style, initialHeight = "auto", ...rest}, fwdRef) {
226
- const ref = useRef(null);
227
- const [height, setHeight] = useState(initialHeight);
228
- const adjustHeight = useCallback((() => {
229
- const textarea = ref.current;
230
- if (!textarea) return;
231
- textarea.style.height = initialHeight;
232
- const newHeight = `${textarea.scrollHeight}px`;
233
- setHeight(newHeight);
234
- textarea.style.height = newHeight;
235
- }), [ initialHeight ]);
236
- useImperativeHandle(fwdRef, (() => ({
237
- element: ref.current,
238
- adjustHeight
239
- })), [ adjustHeight ]);
240
- const input = useEventHandler((ev => {
241
- adjustHeight();
242
- onInput?.(ev);
243
- }));
244
- useLayoutEffect((() => {
245
- adjustHeight();
246
- const textarea = ref.current;
247
- if (!textarea) return;
248
- const resizeObserver = new ResizeObserver((entries => {
249
- adjustHeight();
250
- }));
251
- resizeObserver.observe(textarea);
252
- return () => {
253
- resizeObserver.unobserve(textarea);
254
- };
255
- }), [ adjustHeight ]);
256
- return jsx("textarea", {
257
- ...rest,
258
- style: {
259
- overflow: "hidden",
260
- resize: "none",
261
- ...style,
262
- height
263
- },
264
- onInput: input,
265
- ref
266
- });
267
- }));
268
-
269
- function RadioMenu(menu) {
270
- const defaultId = useId();
271
- const name = menu.name ?? defaultId;
272
- const eq = menu.valueEquals ?? Object.is;
273
- const fixedOptions = menu.options ?? [];
274
- const fixer = new KeyFixer;
275
- const onChange = useEventHandler((ev => {
276
- const selectedIndex = Number(ev.target.value);
277
- const selectedOption = fixedOptions[selectedIndex];
278
- if (selectedOption != null && menu.onChange != null) {
279
- menu.onChange({
280
- value: selectedOption.value,
281
- index: selectedIndex,
282
- type: "change",
283
- timeStamp: ev.timeStamp,
284
- target: ev.target
285
- });
286
- }
287
- }));
288
- return jsx("ul", {
289
- className: menu.className,
290
- children: fixedOptions.map(((opt, idx) => {
291
- const {value, text, key, itemClassName, labelClassName, inputClassName, textClassName, ...rest} = opt;
292
- const fixedKey = fixer.fix(opt, idx);
293
- if (menu.value !== undefined) {
294
- rest.checked = eq(value, menu.value);
295
- }
296
- return jsx("li", {
297
- className: itemClassName,
298
- "aria-disabled": rest.disabled,
299
- children: jsxs("label", {
300
- className: labelClassName,
301
- children: [ jsx("input", {
302
- ...rest,
303
- className: inputClassName,
304
- value: idx,
305
- onChange,
306
- name,
307
- type: "radio"
308
- }), jsx("span", {
309
- className: textClassName,
310
- children: text
311
- }) ]
312
- })
313
- }, fixedKey);
314
- }))
315
- });
316
- }
317
-
318
- export { Input, RadioMenu, Select, TextArea, TextInput };
@@ -1,25 +0,0 @@
1
- /// <reference types="react" />
2
- import { EventCallback, HtmlInputElement, OverrideProps } from "../types/utility";
3
- export type InputChangeEvent = {
4
- value: string;
5
- type: 'change';
6
- timeStamp: number;
7
- target: HtmlInputElement;
8
- };
9
- export type InputChangeEventHandler = EventCallback<InputChangeEvent>;
10
- export type InputProps = OverrideProps<'input', {
11
- onChange?: InputChangeEventHandler;
12
- value?: string;
13
- /**
14
- * Function used to format value on blur.
15
- */
16
- formatOnChange?: (value: string) => string;
17
- }>;
18
- export declare const Input: import("react").ForwardRefExoticComponent<Omit<Omit<import("react").DetailedHTMLProps<import("react").InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref">, "value" | "onChange" | "formatOnChange"> & {
19
- onChange?: InputChangeEventHandler;
20
- value?: string;
21
- /**
22
- * Function used to format value on blur.
23
- */
24
- formatOnChange?: (value: string) => string;
25
- } & import("react").RefAttributes<HTMLInputElement>>;
@@ -1,33 +0,0 @@
1
- import { EventCallback, HtmlInputElement, NonNil, OverrideProps } from '../types/utility';
2
- import { Key, ReactNode } from 'react';
3
- import { Resolvable } from '../util/resolvable';
4
- import { JSX } from 'react/jsx-runtime';
5
- export type RadioMenuOption<T extends NonNil> = OverrideProps<'input', {
6
- value: T;
7
- text: ReactNode;
8
- key?: Resolvable<Key, [RadioMenuOption<T>, number]>;
9
- itemClassName?: string;
10
- labelClassName?: string;
11
- inputClassName?: string;
12
- textClassName?: string;
13
- }, 'type' | 'children' | 'checked' | 'name' | 'className'>;
14
- export type RadioMenuChangeEvent<T> = {
15
- value: T;
16
- index: number;
17
- type: 'change';
18
- timeStamp: number;
19
- target: HtmlInputElement;
20
- };
21
- export type RadioMenuChangeEventHandler<T> = EventCallback<RadioMenuChangeEvent<T>>;
22
- export type RadioMenuProps<T extends NonNil> = {
23
- options: RadioMenuOption<T>[];
24
- value?: T | null;
25
- className?: string;
26
- /**
27
- * Value comparison function. Defaults to {@linkcode https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is|Object.is}
28
- */
29
- valueEquals?: (a: T, b: T) => boolean;
30
- onChange?: RadioMenuChangeEventHandler<T>;
31
- name?: string;
32
- };
33
- export declare function RadioMenu<T extends NonNil>(menu: RadioMenuProps<T>): JSX.Element;