@mpen/react-basic-inputs 0.1.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.
package/README.md ADDED
@@ -0,0 +1,37 @@
1
+ # react-basic-inputs
2
+
3
+ Thin wrappers around native input elements to make them behave better.
4
+
5
+ ## Installation
6
+
7
+ ```sh
8
+ yarn add @mnpenner/react-basic-inputs
9
+ # or
10
+ npm install @mnpenner/react-basic-inputs
11
+ ```
12
+
13
+ ## Links
14
+
15
+ - Docs: https://mnpenner.github.io/react-basic-inputs
16
+ - Repo: https://github.com/mnpenner/react-basic-inputs
17
+ - Code: https://github.com/mnpenner/react-basic-inputs/tree/default/src
18
+ - Issues: https://github.com/mnpenner/react-basic-inputs/issues
19
+ - Npm: https://www.npmjs.com/package/@mnpenner/react-basic-inputs
20
+ - Yarn: https://yarnpkg.com/package/@mnpenner/react-basic-inputs
21
+ - Bundlephobia: https://bundlephobia.com/package/@mnpenner/react-basic-inputs
22
+ - Unpkg: https://unpkg.com/@mnpenner/react-basic-inputs/dist/bundle.mjs
23
+ - jsDelivr: https://cdn.jsdelivr.net/npm/@mnpenner/react-basic-inputs/dist/bundle.mjs
24
+
25
+ ## Components
26
+
27
+ ### Select
28
+
29
+ Like `<select>` but takes an `options` prop instead of `children`.
30
+
31
+ - The values are typed; they can be anything, not just `string`
32
+ - Duplicate values are OK. e.g. if you want to put "United States" at the top of your country list and then again in
33
+ alphabetical order, it will just work
34
+ - Each `<option>` will automatically be assigned a unique React `key`
35
+ - If the current `value` cannot be found in the list of `options` it will be appended to the end
36
+ - If you want to override this behavior, set `invalidValueOption`
37
+ - `placeholder` prop
@@ -0,0 +1,212 @@
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 useEvent;
14
+
15
+ if (typeof window !== "undefined") {
16
+ useEvent = handler => {
17
+ React.useDebugValue(handler);
18
+ const handlerRef = React.useRef(handler);
19
+ React.useLayoutEffect((() => {
20
+ handlerRef.current = handler;
21
+ }), [ handler ]);
22
+ return React.useCallback((ev => {
23
+ handlerRef.current(ev);
24
+ }), []);
25
+ };
26
+ } else {
27
+ useEvent = NOOP;
28
+ }
29
+
30
+ var useEvent$1 = useEvent;
31
+
32
+ function resolveValue(val, ...args) {
33
+ return typeof val === "function" ? val(...args) : val;
34
+ }
35
+
36
+ function useFirstMountState() {
37
+ var isFirst = React.useRef(true);
38
+ if (isFirst.current) {
39
+ isFirst.current = false;
40
+ return true;
41
+ }
42
+ return isFirst.current;
43
+ }
44
+
45
+ var useUpdateEffect = function(effect, deps) {
46
+ var isFirstMount = useFirstMountState();
47
+ React.useEffect((function() {
48
+ if (!isFirstMount) {
49
+ return effect();
50
+ }
51
+ }), deps);
52
+ };
53
+
54
+ var useUpdateEffect$1 = useUpdateEffect;
55
+
56
+ const defaultMakeInvalidValueOption = value => ({
57
+ value,
58
+ text: String(value),
59
+ disabled: true,
60
+ key: INVALID_OPTION_KEY
61
+ });
62
+
63
+ function defaultMakeKey(opt, idx) {
64
+ if (opt.key != null) {
65
+ return resolveValue(opt.key, opt, idx);
66
+ } else if (typeof opt.value === "string" || typeof opt.value === "number") {
67
+ return opt.value;
68
+ }
69
+ return idx;
70
+ }
71
+
72
+ const PLACEHOLDER_KEY = "3c9369b7-0a5e-46ea-93c2-e8b9fec67fdb";
73
+
74
+ const INVALID_OPTION_KEY = "1a53f789-77f5-4ce6-a829-b00e563f1ee8";
75
+
76
+ function Select({options, value, invalidValueOption = defaultMakeInvalidValueOption, onChange, placeholder, ...selectAttrs}) {
77
+ const isNotSelected = value == null;
78
+ const isValid = React.useMemo((() => value != null && options.some((o => o.value == value))), [ options, value ]);
79
+ const extraOption = React.useMemo((() => {
80
+ if (value == null || !invalidValueOption) return null;
81
+ return invalidValueOption(value);
82
+ }), [ invalidValueOption, value ]);
83
+ const fixedOptions = React.useMemo((() => {
84
+ if (isValid) return options;
85
+ const fixedOptions = [ ...options ];
86
+ if (isNotSelected) {
87
+ if (placeholder != null) {
88
+ fixedOptions.unshift({
89
+ text: placeholder,
90
+ hidden: true,
91
+ value: null,
92
+ key: PLACEHOLDER_KEY
93
+ });
94
+ }
95
+ } else if (extraOption) {
96
+ fixedOptions.push(extraOption);
97
+ }
98
+ return fixedOptions;
99
+ }), [ isValid, options, isNotSelected, extraOption, placeholder ]);
100
+ const handleChange = useEvent$1((ev => {
101
+ const idx = ev.target.selectedIndex;
102
+ const opt = fixedOptions[idx];
103
+ onChange?.({
104
+ value: opt.value,
105
+ index: idx,
106
+ type: "change",
107
+ timeStamp: ev.timeStamp,
108
+ target: ev.target
109
+ });
110
+ }));
111
+ const ref = React.useRef(null);
112
+ const refreshSelectedIndex = React.useCallback((() => {
113
+ if (!ref.current) return;
114
+ if (ref.current.selectedIndex < 0 || fixedOptions[ref.current.selectedIndex].value != value) {
115
+ ref.current.selectedIndex = fixedOptions.findIndex((opt => opt.value == value));
116
+ }
117
+ }), [ fixedOptions, value ]);
118
+ const setRef = el => {
119
+ ref.current = el;
120
+ refreshSelectedIndex();
121
+ };
122
+ useUpdateEffect$1((() => {
123
+ refreshSelectedIndex();
124
+ }), [ refreshSelectedIndex ]);
125
+ const usedKeys = new Map;
126
+ return jsxRuntime.jsx("select", {
127
+ ...selectAttrs,
128
+ onChange: handleChange,
129
+ ref: setRef,
130
+ children: fixedOptions.map(((opt, idx) => {
131
+ const {value, text, key, ...optAttrs} = opt;
132
+ let fixedKey = defaultMakeKey(opt, idx);
133
+ for (;;) {
134
+ let suffix = usedKeys.get(fixedKey);
135
+ if (suffix === undefined) {
136
+ usedKeys.set(fixedKey, 1);
137
+ break;
138
+ }
139
+ usedKeys.set(fixedKey, ++suffix);
140
+ fixedKey = `${fixedKey}(${suffix})`;
141
+ }
142
+ return React.createElement("option", {
143
+ ...optAttrs,
144
+ key: fixedKey
145
+ }, opt.text);
146
+ }))
147
+ });
148
+ }
149
+
150
+ function collapseWhitespace(str) {
151
+ if (!str) return "";
152
+ return String(str).replace(/\s+/gu, " ").trim();
153
+ }
154
+
155
+ const Input = React.forwardRef((function Input({value = "", onChange, onInput, onBlur, formatOnChange = identity, ...otherProps}, ref) {
156
+ const [currentValue, setCurrentValue] = React.useState(value);
157
+ const lastValue = React.useRef(value);
158
+ const modified = React.useRef(false);
159
+ useUpdateEffect$1((() => {
160
+ setCurrentValue(value);
161
+ modified.current = false;
162
+ lastValue.current = value;
163
+ }), [ value ]);
164
+ const props = {
165
+ type: "text",
166
+ ...otherProps,
167
+ value: currentValue,
168
+ onChange: ev => {
169
+ setCurrentValue(ev.target.value);
170
+ },
171
+ onInput: ev => {
172
+ modified.current = true;
173
+ onInput?.(ev);
174
+ },
175
+ onBlur: ev => {
176
+ const formattedValue = formatOnChange(currentValue);
177
+ if (modified.current) {
178
+ if (formattedValue !== lastValue.current) {
179
+ onChange?.({
180
+ type: "change",
181
+ value: formattedValue,
182
+ timeStamp: ev.timeStamp,
183
+ target: ev.target
184
+ });
185
+ lastValue.current = formattedValue;
186
+ }
187
+ if (formattedValue !== ev.target.value) {
188
+ setCurrentValue(formattedValue);
189
+ }
190
+ }
191
+ onBlur?.(ev);
192
+ }
193
+ };
194
+ return jsxRuntime.jsx("input", {
195
+ ...props,
196
+ ref
197
+ });
198
+ }));
199
+
200
+ function TextInput({formatOnChange = collapseWhitespace, ...otherProps}) {
201
+ return jsxRuntime.jsx(Input, {
202
+ formatOnChange,
203
+ ...otherProps,
204
+ type: "text"
205
+ });
206
+ }
207
+
208
+ exports.Input = Input;
209
+
210
+ exports.Select = Select;
211
+
212
+ exports.TextInput = TextInput;
@@ -0,0 +1,3 @@
1
+ export { Select } from './components/Select';
2
+ export { TextInput } from './components/TextInput';
3
+ export { Input } from './components/Input';
@@ -0,0 +1,206 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+
3
+ import { useDebugValue, useRef, useLayoutEffect, useCallback, useEffect, useMemo, createElement, forwardRef, useState } from "react";
4
+
5
+ const NOOP = Object.freeze((() => {}));
6
+
7
+ function identity(x) {
8
+ return x;
9
+ }
10
+
11
+ let useEvent;
12
+
13
+ if (typeof window !== "undefined") {
14
+ useEvent = handler => {
15
+ useDebugValue(handler);
16
+ const handlerRef = useRef(handler);
17
+ useLayoutEffect((() => {
18
+ handlerRef.current = handler;
19
+ }), [ handler ]);
20
+ return useCallback((ev => {
21
+ handlerRef.current(ev);
22
+ }), []);
23
+ };
24
+ } else {
25
+ useEvent = NOOP;
26
+ }
27
+
28
+ var useEvent$1 = useEvent;
29
+
30
+ function resolveValue(val, ...args) {
31
+ return typeof val === "function" ? val(...args) : val;
32
+ }
33
+
34
+ function useFirstMountState() {
35
+ var isFirst = useRef(true);
36
+ if (isFirst.current) {
37
+ isFirst.current = false;
38
+ return true;
39
+ }
40
+ return isFirst.current;
41
+ }
42
+
43
+ var useUpdateEffect = function(effect, deps) {
44
+ var isFirstMount = useFirstMountState();
45
+ useEffect((function() {
46
+ if (!isFirstMount) {
47
+ return effect();
48
+ }
49
+ }), deps);
50
+ };
51
+
52
+ var useUpdateEffect$1 = useUpdateEffect;
53
+
54
+ const defaultMakeInvalidValueOption = value => ({
55
+ value,
56
+ text: String(value),
57
+ disabled: true,
58
+ key: INVALID_OPTION_KEY
59
+ });
60
+
61
+ function defaultMakeKey(opt, idx) {
62
+ if (opt.key != null) {
63
+ return resolveValue(opt.key, opt, idx);
64
+ } else if (typeof opt.value === "string" || typeof opt.value === "number") {
65
+ return opt.value;
66
+ }
67
+ return idx;
68
+ }
69
+
70
+ const PLACEHOLDER_KEY = "3c9369b7-0a5e-46ea-93c2-e8b9fec67fdb";
71
+
72
+ const INVALID_OPTION_KEY = "1a53f789-77f5-4ce6-a829-b00e563f1ee8";
73
+
74
+ function Select({options, value, invalidValueOption = defaultMakeInvalidValueOption, onChange, placeholder, ...selectAttrs}) {
75
+ const isNotSelected = value == null;
76
+ const isValid = useMemo((() => value != null && options.some((o => o.value == value))), [ options, value ]);
77
+ const extraOption = useMemo((() => {
78
+ if (value == null || !invalidValueOption) return null;
79
+ return invalidValueOption(value);
80
+ }), [ invalidValueOption, value ]);
81
+ const fixedOptions = useMemo((() => {
82
+ if (isValid) return options;
83
+ const fixedOptions = [ ...options ];
84
+ if (isNotSelected) {
85
+ if (placeholder != null) {
86
+ fixedOptions.unshift({
87
+ text: placeholder,
88
+ hidden: true,
89
+ value: null,
90
+ key: PLACEHOLDER_KEY
91
+ });
92
+ }
93
+ } else if (extraOption) {
94
+ fixedOptions.push(extraOption);
95
+ }
96
+ return fixedOptions;
97
+ }), [ isValid, options, isNotSelected, extraOption, placeholder ]);
98
+ const handleChange = useEvent$1((ev => {
99
+ const idx = ev.target.selectedIndex;
100
+ const opt = fixedOptions[idx];
101
+ onChange?.({
102
+ value: opt.value,
103
+ index: idx,
104
+ type: "change",
105
+ timeStamp: ev.timeStamp,
106
+ target: ev.target
107
+ });
108
+ }));
109
+ const ref = useRef(null);
110
+ const refreshSelectedIndex = useCallback((() => {
111
+ if (!ref.current) return;
112
+ if (ref.current.selectedIndex < 0 || fixedOptions[ref.current.selectedIndex].value != value) {
113
+ ref.current.selectedIndex = fixedOptions.findIndex((opt => opt.value == value));
114
+ }
115
+ }), [ fixedOptions, value ]);
116
+ const setRef = el => {
117
+ ref.current = el;
118
+ refreshSelectedIndex();
119
+ };
120
+ useUpdateEffect$1((() => {
121
+ refreshSelectedIndex();
122
+ }), [ refreshSelectedIndex ]);
123
+ const usedKeys = new Map;
124
+ return jsx("select", {
125
+ ...selectAttrs,
126
+ onChange: handleChange,
127
+ ref: setRef,
128
+ children: fixedOptions.map(((opt, idx) => {
129
+ const {value, text, key, ...optAttrs} = opt;
130
+ let fixedKey = defaultMakeKey(opt, idx);
131
+ for (;;) {
132
+ let suffix = usedKeys.get(fixedKey);
133
+ if (suffix === undefined) {
134
+ usedKeys.set(fixedKey, 1);
135
+ break;
136
+ }
137
+ usedKeys.set(fixedKey, ++suffix);
138
+ fixedKey = `${fixedKey}(${suffix})`;
139
+ }
140
+ return createElement("option", {
141
+ ...optAttrs,
142
+ key: fixedKey
143
+ }, opt.text);
144
+ }))
145
+ });
146
+ }
147
+
148
+ function collapseWhitespace(str) {
149
+ if (!str) return "";
150
+ return String(str).replace(/\s+/gu, " ").trim();
151
+ }
152
+
153
+ const Input = forwardRef((function Input({value = "", onChange, onInput, onBlur, formatOnChange = identity, ...otherProps}, ref) {
154
+ const [currentValue, setCurrentValue] = useState(value);
155
+ const lastValue = useRef(value);
156
+ const modified = useRef(false);
157
+ useUpdateEffect$1((() => {
158
+ setCurrentValue(value);
159
+ modified.current = false;
160
+ lastValue.current = value;
161
+ }), [ value ]);
162
+ const props = {
163
+ type: "text",
164
+ ...otherProps,
165
+ value: currentValue,
166
+ onChange: ev => {
167
+ setCurrentValue(ev.target.value);
168
+ },
169
+ onInput: ev => {
170
+ modified.current = true;
171
+ onInput?.(ev);
172
+ },
173
+ onBlur: ev => {
174
+ const formattedValue = formatOnChange(currentValue);
175
+ if (modified.current) {
176
+ if (formattedValue !== lastValue.current) {
177
+ onChange?.({
178
+ type: "change",
179
+ value: formattedValue,
180
+ timeStamp: ev.timeStamp,
181
+ target: ev.target
182
+ });
183
+ lastValue.current = formattedValue;
184
+ }
185
+ if (formattedValue !== ev.target.value) {
186
+ setCurrentValue(formattedValue);
187
+ }
188
+ }
189
+ onBlur?.(ev);
190
+ }
191
+ };
192
+ return jsx("input", {
193
+ ...props,
194
+ ref
195
+ });
196
+ }));
197
+
198
+ function TextInput({formatOnChange = collapseWhitespace, ...otherProps}) {
199
+ return jsx(Input, {
200
+ formatOnChange,
201
+ ...otherProps,
202
+ type: "text"
203
+ });
204
+ }
205
+
206
+ export { Input, Select, TextInput };
@@ -0,0 +1,25 @@
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>>;
@@ -0,0 +1,33 @@
1
+ import { Key, ReactNode } from 'react';
2
+ import { Resolvable } from '../util/resolvable';
3
+ import { EventCallback, HtmlSelectElement, NonNil, OverrideProps } from "../types/utility";
4
+ export type SelectOption<T> = OverrideProps<'option', {
5
+ value: T;
6
+ text: ReactNode;
7
+ key?: Resolvable<Key, [SelectOption<T>, number]>;
8
+ }, 'children' | 'selected'>;
9
+ export interface SelectChangeEvent<T> {
10
+ value: T;
11
+ index: number;
12
+ type: 'change';
13
+ timeStamp: number;
14
+ target: HtmlSelectElement;
15
+ }
16
+ export type SelectChangeEventHandler<T> = EventCallback<SelectChangeEvent<T>>;
17
+ export type InvalidValueToOption<T> = (value: T) => SelectOption<T>;
18
+ export type SelectProps<T extends NonNil> = OverrideProps<'select', {
19
+ options: SelectOption<T>[];
20
+ value?: T | null;
21
+ onChange?: SelectChangeEventHandler<T>;
22
+ /**
23
+ * Function used to create an <option> when `value` cannot be found in the list of `options`.
24
+ * Set to `null` to disable this behavior.
25
+ * By default, stringifies `value`.
26
+ */
27
+ invalidValueOption?: InvalidValueToOption<T> | null;
28
+ /**
29
+ * Text to display when `value` is nullish.
30
+ */
31
+ placeholder?: ReactNode;
32
+ }, 'children' | 'defaultValue'>;
33
+ export declare function Select<T extends NonNil>({ options, value, invalidValueOption, onChange, placeholder, ...selectAttrs }: SelectProps<T>): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,3 @@
1
+ import { InputProps } from "./Input";
2
+ export type TextInputProps = Omit<InputProps, 'text'>;
3
+ export declare function TextInput({ formatOnChange, ...otherProps }: TextInputProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,6 @@
1
+ import { EventCallback } from "../types/utility";
2
+ /**
3
+ * @see https://github.com/reactjs/rfcs/blob/useevent/text/0000-useevent.md
4
+ */
5
+ declare let useEvent: <T>(handler: EventCallback<T>) => (ev: T) => void;
6
+ export default useEvent;
@@ -0,0 +1,30 @@
1
+ export type Fn<TArgs extends ReadonlyArray<unknown> = unknown[], TRet = unknown> = (...args: TArgs[]) => TRet;
2
+ export type AnyFn = (...args: any[]) => any;
3
+ export type EventCallback<T = never> = (ev: T) => void;
4
+ export type VoidFn = () => void;
5
+ export type EmptyObject = Record<PropertyKey, never>;
6
+ export type UnknownObject = Record<PropertyKey, unknown>;
7
+ export type Override<Base, Extension, DeleteKeys extends PropertyKey = never> = Omit<Base, keyof Extension | DeleteKeys> & Extension;
8
+ export type PartiallyRequired<Type, Key extends keyof Type> = Omit<Type, Key> & Required<Pick<Type, Key>>;
9
+ export type Optionalize<T1 extends T2, T2> = Omit<T1, keyof T2> & Partial<Pick<T1, keyof T2>>;
10
+ /**
11
+ * Nullish. Either `null` or `undefined`.
12
+ */
13
+ export type nil = null | undefined;
14
+ /**
15
+ * Not null or undefined.
16
+ */
17
+ export type NonNil = {};
18
+ export type OverrideProps<Base extends import('react').ElementType, Extension, DeleteKeys extends PropertyKey = never> = Override<import('react').ComponentPropsWithoutRef<Base>, Extension, DeleteKeys>;
19
+ export type OmitProps<Base extends import('react').ElementType, DeleteKeys extends PropertyKey> = Omit<import('react').ComponentPropsWithoutRef<Base>, DeleteKeys>;
20
+ export type MapKeyType<M> = M extends Map<infer K, any> ? K : never;
21
+ export type MapValueType<M> = M extends Map<any, infer V> ? V : never;
22
+ /** Hack to de-conflict React's HTMLInputElement vs the standard dom lib */
23
+ export type HtmlInputElement = HTMLElementTagNameMap['input'];
24
+ export type HtmlSelectElement = HTMLElementTagNameMap['select'];
25
+ export type HtmlInputChangeEvent = import('react').ChangeEvent<HtmlInputElement>;
26
+ export type ArrayType<T extends any[]> = T[number];
27
+ type _UnionKeys<T> = T extends T ? keyof T : never;
28
+ type _StrictUnionHelper<T, TAll> = T extends any ? T & Partial<Record<Exclude<_UnionKeys<TAll>, keyof T>, never>> : never;
29
+ export type XOR<T> = _StrictUnionHelper<T, T>;
30
+ export {};
@@ -0,0 +1,5 @@
1
+ import { AnyFn, NonNil } from "../types/utility";
2
+ export declare const EMPTY_OBJECT: Readonly<NonNil>;
3
+ export declare const EMPTY_ARRAY: ReadonlyArray<any>;
4
+ export declare const NOOP: AnyFn;
5
+ export declare function identity<T>(x: T): T;
@@ -0,0 +1,9 @@
1
+ import { nil } from "../types/utility";
2
+ export declare function collapseWhitespace(str: string | nil): string;
3
+ export declare function formatEmail(str: string | nil): string;
4
+ export declare function formatUrl(str: string | nil): string;
5
+ export declare function fullWide(n: number): string;
6
+ export declare function stringToNumber(n: string): number;
7
+ export declare function numberToString(f: number): string;
8
+ export declare function formatStrNumber(n: string): string;
9
+ export declare function formatUsername(str: string | nil): string;
@@ -0,0 +1,4 @@
1
+ import { Fn } from "../types/utility";
2
+ export type Resolvable<TValue = unknown, TArgs extends ReadonlyArray<unknown> = []> = TValue extends any ? TValue | ((...args: TArgs) => TValue) : never;
3
+ export type Resolved<T> = T extends Fn ? ReturnType<T> : T;
4
+ export declare function resolveValue<TValue, TArgs extends ReadonlyArray<any>>(val: Resolvable<TValue, TArgs>, ...args: TArgs): TValue;
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@mpen/react-basic-inputs",
3
+ "version": "0.1.2",
4
+ "packageManager": "yarn@3.5.0",
5
+ "exports": {
6
+ ".": {
7
+ "import": "./dist/bundle.mjs",
8
+ "require": "./dist/bundle.cjs",
9
+ "types": "./dist/bundle.d.ts"
10
+ }
11
+ },
12
+ "type": "module",
13
+ "files": [
14
+ "./dist"
15
+ ],
16
+ "scripts": {
17
+ "dev:build": "rollup -cw",
18
+ "dev:serve": "serve -l tcp://0.0.0.0:8080",
19
+ "dev": "run-p \"dev:**\"",
20
+ "serve": "bun run --hot dev/serve.ts",
21
+ "bundle:clean": "rimraf -g \"dist/*\"",
22
+ "bundle:build": "rollup -c",
23
+ "bundle": "run-s bundle:clean bundle:build",
24
+ "patch": "npm version patch && VER=$(jq -r '.version' package.json) && hg ci -m \"Publish v$VER\" && hg tag \"v$VER\"",
25
+ "release": "run-s bundle patch && npm publish --access=public && hg push"
26
+ },
27
+ "devDependencies": {
28
+ "@rollup/plugin-commonjs": "^25.0.4",
29
+ "@rollup/plugin-node-resolve": "^15.2.1",
30
+ "@rollup/plugin-replace": "^5.0.2",
31
+ "@rollup/plugin-terser": "^0.4.3",
32
+ "@rollup/plugin-typescript": "^11.1.3",
33
+ "@types/eslint": "^8",
34
+ "@types/jest": "^29.5.0",
35
+ "@types/react": "^18.2.21",
36
+ "@types/react-dom": "^18.2.7",
37
+ "@typescript-eslint/eslint-plugin": "^5.57.1",
38
+ "@typescript-eslint/parser": "^5.57.1",
39
+ "eslint": "^8.38.0",
40
+ "eslint-plugin-react": "^7.32.2",
41
+ "eslint-plugin-react-hooks": "^4.6.0",
42
+ "jest": "^29.5.0",
43
+ "npm-run-all": "^4.1.5",
44
+ "react": ">=17 <19",
45
+ "react-dom": ">=17 <19",
46
+ "react-use": "^17.4.0",
47
+ "rimraf": "^5.0.0",
48
+ "rollup": "^3.20.2",
49
+ "serve": "^14.2.0",
50
+ "ts-jest": "^29.1.0",
51
+ "tslib": "^2.5.0",
52
+ "typescript": "^5.2.2"
53
+ },
54
+ "peerDependencies": {
55
+ "react": ">=17 <19",
56
+ "react-dom": ">=17 <19"
57
+ }
58
+ }