@slimr/react 2.1.45

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,120 @@
1
+ # 🪶 @slimr/react [![npm package](https://img.shields.io/npm/v/@slimr/react.svg?style=flat-square)](https://npmjs.org/package/@slimr/react)
2
+
3
+ A collection of useful 1st and third party react components, hooks, and util. Includes several other @slimr libs for convenience
4
+
5
+ ## Context
6
+
7
+ `@slimr` is a set of slim React (hence '@slimr') libs:
8
+
9
+ - [@slimr/css](https://www.npmjs.com/package/@slimr/css) - Framework agnostic css-in-js features inspired by the popular Emotion lib
10
+ - [@slimr/forms](https://www.npmjs.com/package/@slimr/forms) - A minimalistic form hook
11
+ - [@slimr/hooks](https://www.npmjs.com/package/@slimr/hooks) - A collection of useful 1st and third party react hooks
12
+ - [@slimr/markdown](https://www.npmjs.com/package/@slimr/markdown) - A simple component and slim markdown-to-html parser
13
+ - [@slimr/mdi-paths](https://www.npmjs.com/package/@slimr/mdi-paths) - A basic Icon component and Material Design icon svg paths, code-split by path.
14
+ - [@slimr/router](https://www.npmjs.com/package/@slimr/router) - A novel React-web router that supports stack routing
15
+ - [@slimr/styled](https://www.npmjs.com/package/@slimr/styled) - css-in-js features inspired by the popular styled-components and Chakra-UI libs
16
+ - [@slimr/swr](https://www.npmjs.com/package/@slimr/swr) - A React hook for fetching data that supports stale-while-refresh eager rendering
17
+ - [@slimr/util](https://www.npmjs.com/package/@slimr/util) - Framework agnostic Javascript polyfills
18
+
19
+ ## Setup
20
+
21
+ - Install using normal methods (`npm i`, `yarn i`, ...etc)
22
+ - There is a known conflict with vitest, which you can resolve by adding the following to `vite.config.js`
23
+
24
+ ```javascript
25
+ export default defineConfig({
26
+ test: {
27
+ deps: {
28
+ inline: ['@slimr/hooks'],
29
+ },
30
+ },
31
+ })
32
+ ```
33
+
34
+ ## API
35
+
36
+ ### Bundled from other libs
37
+
38
+ - [@slimr/forms](https://www.npmjs.com/package/@slimr/forms) - A minimalistic form hook
39
+ - [@slimr/hooks](https://www.npmjs.com/package/@slimr/hooks) - A collection of useful 1st and third party react hooks
40
+ - [@slimr/markdown](https://www.npmjs.com/package/@slimr/markdown) - A simple component and slim markdown-to-html parser
41
+ - [@slimr/router](https://www.npmjs.com/package/@slimr/router) - A novel React-web router that supports stack routing
42
+ - [@slimr/styled](https://www.npmjs.com/package/@slimr/styled) - css-in-js features inspired by the popular styled-components and Chakra-UI libs
43
+ - [@slimr/swr](https://www.npmjs.com/package/@slimr/swr) - A React hook for fetching data that supports stale-while-refresh eager rendering
44
+ - [@slimr/util](https://www.npmjs.com/package/@slimr/util) - Framework agnostic Javascript polyfills
45
+ - [react-use](https://www.npmjs.com/package/react-use) - an excellent collection of hooks
46
+
47
+ ### useDeepCompareMemo and useShallowCompareMemo
48
+
49
+ like react-use's useDeepEffects, but for memos
50
+
51
+ ### useForm, FormError
52
+
53
+ A hook and custom Error from [@slimr/forms](https://www.npmjs.com/package/@slimr/forms), which returns a Form component and reactive form state.
54
+
55
+ ```tsx
56
+ import {FormError, useForm} from '@slimr/forms'
57
+ import {formToValues} from '@slimr/util'
58
+
59
+ function MyForm() {
60
+ const { Form, submitting, submitted, accepted, errors} = useForm()
61
+
62
+ const onSubmit = async (e: React.FormEventHandler<HTMLFormElement> => {
63
+ const vals = formToJson(e.target as HTMLFormElement)
64
+ const errors: Record<string, string> = {}
65
+ if (!vals.name) {
66
+ errors.name = 'Name is required'
67
+ }
68
+ if (!vals.terms) {
69
+ errors.checkbox = 'You must agree to the terms'
70
+ }
71
+ if (Object.keys(errors).length) {
72
+ throw new FormError(errors)
73
+ }
74
+ }
75
+
76
+ return (
77
+ <Form onSubmit={onSubmit}>
78
+ <input disabled={submitting || accepted} name="name" />
79
+ <div>{errors.name}<div>
80
+ <input disabled={submitting || accepted} name="terms" type="checkbox" />
81
+ <div>{errors.terms}<div>
82
+ <button type="submit">Submit</button>
83
+ <button type="reset">Reset</button>
84
+ </Form>
85
+ )
86
+ }
87
+ ```
88
+
89
+ ### useSet2
90
+
91
+ Returns a set-like object that intercepts the setter function to trigger re-renders on change. Also adds a toggle and reset method. `@slimr/hooks` also exports a `useSet` from `react-use`, which is similar but has a different, less desirable (imho) pattern.
92
+
93
+ ```typescript
94
+ function MyComponent() {
95
+ const optionalInitialValue = new Set()
96
+ const [set1, set1Setters] = useSet(optionalInitialValue)
97
+ const set2 = useSet2(optionalInitialValue)
98
+
99
+ // Use set2 like you would a vanilla JS Set
100
+ ```
101
+
102
+ ### useSWR
103
+
104
+ A hook that accepts a function callback, calls the function and returns a reactive callback state. Uses a cache and will return the cache value if available while waiting for the callback to complete, then update the return on complete. This is often called 'stale-while-refresh' and abbreviated as 'SWR', hence the name of the hook. Source is in [@slimr/swr](https://www.npmjs.com/package/@slimr/swr)
105
+
106
+ ```tsx
107
+ import {useSWR} from `@slimr/swr`
108
+
109
+ function MyComponent({ page }: number) {
110
+ const { result, loading, refresh} = useSWR(() => getPageData(page), [page], {throttle: Infinity})
111
+ if (loading) return null
112
+ return (
113
+ <section>
114
+ <h1>{result.title}</h1>
115
+ <p>{result.description}</h1>
116
+ <button onClick={refresh}>Refresh</button>
117
+ </section>
118
+ )
119
+ }
120
+ ```
@@ -0,0 +1 @@
1
+ type Fnc = (...args: any) => any
package/cjs/index.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ export * from '@slimr/forms';
2
+ export * from '@slimr/markdown';
3
+ export * from '@slimr/router';
4
+ export * from '@slimr/styled';
5
+ export * from '@slimr/swr';
6
+ export * from '@slimr/util';
7
+ export * from 'react-use';
8
+ export * from './useMemos.js';
9
+ export * from './useSet2.js';
package/cjs/index.js ADDED
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("@slimr/forms"), exports);
18
+ __exportStar(require("@slimr/markdown"), exports);
19
+ __exportStar(require("@slimr/router"), exports);
20
+ __exportStar(require("@slimr/styled"), exports);
21
+ __exportStar(require("@slimr/swr"), exports);
22
+ __exportStar(require("@slimr/util"), exports);
23
+ __exportStar(require("react-use"), exports);
24
+ __exportStar(require("./useMemos.js"), exports);
25
+ __exportStar(require("./useSet2.js"), exports);
26
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,+CAA4B;AAC5B,kDAA+B;AAC/B,gDAA6B;AAC7B,gDAA6B;AAC7B,6CAA0B;AAC1B,8CAA2B;AAC3B,4CAAyB;AAEzB,gDAA6B;AAC7B,+CAA4B"}
package/cjs/index.ts ADDED
@@ -0,0 +1,10 @@
1
+ export * from '@slimr/forms'
2
+ export * from '@slimr/markdown'
3
+ export * from '@slimr/router'
4
+ export * from '@slimr/styled'
5
+ export * from '@slimr/swr'
6
+ export * from '@slimr/util'
7
+ export * from 'react-use'
8
+
9
+ export * from './useMemos.js'
10
+ export * from './useSet2.js'
@@ -0,0 +1,14 @@
1
+ type Fnc = (...args: any[]) => any;
2
+ /**
3
+ * Like useMemo, but does a deep compare instead default compare
4
+ * to avoid misfires. Is more expensive than useMemo though,
5
+ * so use it intensionally.
6
+ */
7
+ export declare function useDeepCompareMemo(callback: Fnc, varsToWatch: any[]): any;
8
+ /**
9
+ * Like useMemo, but does a shallow compare instead default compare
10
+ * to avoid misfires. Is more expensive than useMemo though, but
11
+ * less than useDeepCompareMemo, so use it intentionally.
12
+ */
13
+ export declare function useShallowCompareMemo(callback: Fnc, varsToWatch: any[]): any;
14
+ export {};
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useShallowCompareMemo = exports.useDeepCompareMemo = void 0;
4
+ const util_1 = require("@slimr/util");
5
+ const react_1 = require("react");
6
+ /**
7
+ * Like useMemo, but does a deep compare instead default compare
8
+ * to avoid misfires. Is more expensive than useMemo though,
9
+ * so use it intensionally.
10
+ */
11
+ function useDeepCompareMemo(callback, varsToWatch) {
12
+ const [lastSeenProps, setLastSeenProps] = (0, react_1.useState)(varsToWatch);
13
+ (0, react_1.useEffect)(() => {
14
+ if ((0, util_1.areNotEqualDeep)(varsToWatch, lastSeenProps)) {
15
+ setLastSeenProps(varsToWatch);
16
+ }
17
+ }, varsToWatch);
18
+ return (0, react_1.useMemo)(callback, [lastSeenProps]);
19
+ }
20
+ exports.useDeepCompareMemo = useDeepCompareMemo;
21
+ /**
22
+ * Like useMemo, but does a shallow compare instead default compare
23
+ * to avoid misfires. Is more expensive than useMemo though, but
24
+ * less than useDeepCompareMemo, so use it intentionally.
25
+ */
26
+ function useShallowCompareMemo(callback, varsToWatch) {
27
+ const [lastSeenProps, setLastSeenProps] = (0, react_1.useState)(varsToWatch);
28
+ (0, react_1.useEffect)(() => {
29
+ if ((0, util_1.areNotEqualDeep)(varsToWatch, lastSeenProps)) {
30
+ setLastSeenProps(varsToWatch);
31
+ }
32
+ }, varsToWatch);
33
+ return (0, react_1.useMemo)(callback, [lastSeenProps]);
34
+ }
35
+ exports.useShallowCompareMemo = useShallowCompareMemo;
36
+ //# sourceMappingURL=useMemos.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useMemos.js","sourceRoot":"","sources":["../src/useMemos.ts"],"names":[],"mappings":";;;AAAA,sCAA2C;AAC3C,iCAAkD;AAIlD;;;;GAIG;AACH,SAAgB,kBAAkB,CAAC,QAAa,EAAE,WAAkB;IAClE,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,IAAA,gBAAQ,EAAC,WAAW,CAAC,CAAA;IAC/D,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,IAAI,IAAA,sBAAe,EAAC,WAAW,EAAE,aAAa,CAAC,EAAE;YAC/C,gBAAgB,CAAC,WAAW,CAAC,CAAA;SAC9B;IACH,CAAC,EAAE,WAAW,CAAC,CAAA;IACf,OAAO,IAAA,eAAO,EAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,CAAC,CAAA;AAC3C,CAAC;AARD,gDAQC;AAED;;;;GAIG;AACH,SAAgB,qBAAqB,CAAC,QAAa,EAAE,WAAkB;IACrE,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,IAAA,gBAAQ,EAAC,WAAW,CAAC,CAAA;IAC/D,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,IAAI,IAAA,sBAAe,EAAC,WAAW,EAAE,aAAa,CAAC,EAAE;YAC/C,gBAAgB,CAAC,WAAW,CAAC,CAAA;SAC9B;IACH,CAAC,EAAE,WAAW,CAAC,CAAA;IACf,OAAO,IAAA,eAAO,EAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,CAAC,CAAA;AAC3C,CAAC;AARD,sDAQC"}
@@ -0,0 +1,34 @@
1
+ import {areNotEqualDeep} from '@slimr/util'
2
+ import {useEffect, useMemo, useState} from 'react'
3
+
4
+ type Fnc = (...args: any[]) => any
5
+
6
+ /**
7
+ * Like useMemo, but does a deep compare instead default compare
8
+ * to avoid misfires. Is more expensive than useMemo though,
9
+ * so use it intensionally.
10
+ */
11
+ export function useDeepCompareMemo(callback: Fnc, varsToWatch: any[]) {
12
+ const [lastSeenProps, setLastSeenProps] = useState(varsToWatch)
13
+ useEffect(() => {
14
+ if (areNotEqualDeep(varsToWatch, lastSeenProps)) {
15
+ setLastSeenProps(varsToWatch)
16
+ }
17
+ }, varsToWatch)
18
+ return useMemo(callback, [lastSeenProps])
19
+ }
20
+
21
+ /**
22
+ * Like useMemo, but does a shallow compare instead default compare
23
+ * to avoid misfires. Is more expensive than useMemo though, but
24
+ * less than useDeepCompareMemo, so use it intentionally.
25
+ */
26
+ export function useShallowCompareMemo(callback: Fnc, varsToWatch: any[]) {
27
+ const [lastSeenProps, setLastSeenProps] = useState(varsToWatch)
28
+ useEffect(() => {
29
+ if (areNotEqualDeep(varsToWatch, lastSeenProps)) {
30
+ setLastSeenProps(varsToWatch)
31
+ }
32
+ }, varsToWatch)
33
+ return useMemo(callback, [lastSeenProps])
34
+ }
@@ -0,0 +1,24 @@
1
+ export interface UseSet2<T> extends Set<T> {
2
+ _add: Set<T>['add'];
3
+ _clear: Set<T>['clear'];
4
+ _delete: Set<T>['delete'];
5
+ toggle(v: T): void;
6
+ reset(): void;
7
+ _union(other: Set<T>): Set<T>;
8
+ union(other: Set<T>): Set<T>;
9
+ }
10
+ /**
11
+ * Returns a set-like object that intercepts the setter function to
12
+ * trigger re-renders on change. Also adds a toggle and reset method.
13
+ *
14
+ * @example
15
+ *
16
+ * ```typescript
17
+ * function MyComponent() {
18
+ * const optionalInitialValue = new Set()
19
+ * const set = useSet2(optionalInitialValue)
20
+
21
+ * // ... Use set like you would a vanilla JS Set
22
+ * ```
23
+ */
24
+ export declare function useSet2<T>(initial?: Set<T>): UseSet2<T>;
package/cjs/useSet2.js ADDED
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useSet2 = void 0;
4
+ const react_1 = require("react");
5
+ const react_use_1 = require("react-use");
6
+ /**
7
+ * Returns a set-like object that intercepts the setter function to
8
+ * trigger re-renders on change. Also adds a toggle and reset method.
9
+ *
10
+ * @example
11
+ *
12
+ * ```typescript
13
+ * function MyComponent() {
14
+ * const optionalInitialValue = new Set()
15
+ * const set = useSet2(optionalInitialValue)
16
+
17
+ * // ... Use set like you would a vanilla JS Set
18
+ * ```
19
+ */
20
+ function useSet2(initial = new Set()) {
21
+ const rerender = (0, react_use_1.useUpdate)();
22
+ const setRef = (0, react_1.useRef)(initial);
23
+ const set = setRef.current;
24
+ if (!set._add) {
25
+ set._add = set.add;
26
+ set.add = v => {
27
+ set._add(v);
28
+ rerender();
29
+ return set;
30
+ };
31
+ set._clear = set.clear;
32
+ set.clear = () => {
33
+ set._clear();
34
+ rerender();
35
+ return set;
36
+ };
37
+ set._delete = set.delete;
38
+ set.delete = v => {
39
+ const res = set._delete(v);
40
+ rerender();
41
+ return res;
42
+ };
43
+ set.reset = () => {
44
+ set._clear();
45
+ set._union(initial);
46
+ rerender();
47
+ return set;
48
+ };
49
+ set.toggle = v => {
50
+ if (set.has(v))
51
+ set._delete(v);
52
+ else
53
+ set._add(v);
54
+ rerender();
55
+ return set;
56
+ };
57
+ set._union = (other) => {
58
+ for (const elem of other) {
59
+ set._add(elem);
60
+ }
61
+ return set;
62
+ };
63
+ set.union = (other) => {
64
+ set._union(other);
65
+ rerender();
66
+ return set;
67
+ };
68
+ }
69
+ return set;
70
+ }
71
+ exports.useSet2 = useSet2;
72
+ //# sourceMappingURL=useSet2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSet2.js","sourceRoot":"","sources":["../src/useSet2.ts"],"names":[],"mappings":";;;AAAA,iCAA4B;AAC5B,yCAAmC;AAYnC;;;;;;;;;;;;;GAaG;AACH,SAAgB,OAAO,CAAI,UAAkB,IAAI,GAAG,EAAE;IACpD,MAAM,QAAQ,GAAG,IAAA,qBAAS,GAAE,CAAA;IAC5B,MAAM,MAAM,GAAG,IAAA,cAAM,EAAC,OAAgC,CAAC,CAAA;IACvD,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAA;IAE1B,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE;QACb,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,GAAG,CAAA;QAClB,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE;YACZ,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACX,QAAQ,EAAE,CAAA;YACV,OAAO,GAAG,CAAA;QACZ,CAAC,CAAA;QAED,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,KAAK,CAAA;QACtB,GAAG,CAAC,KAAK,GAAG,GAAG,EAAE;YACf,GAAG,CAAC,MAAM,EAAE,CAAA;YACZ,QAAQ,EAAE,CAAA;YACV,OAAO,GAAG,CAAA;QACZ,CAAC,CAAA;QAED,GAAG,CAAC,OAAO,GAAG,GAAG,CAAC,MAAM,CAAA;QACxB,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE;YACf,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;YAC1B,QAAQ,EAAE,CAAA;YACV,OAAO,GAAG,CAAA;QACZ,CAAC,CAAA;QAED,GAAG,CAAC,KAAK,GAAG,GAAG,EAAE;YACf,GAAG,CAAC,MAAM,EAAE,CAAA;YACZ,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;YACnB,QAAQ,EAAE,CAAA;YACV,OAAO,GAAG,CAAA;QACZ,CAAC,CAAA;QAED,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE;YACf,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;gBAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;;gBACzB,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YAChB,QAAQ,EAAE,CAAA;YACV,OAAO,GAAG,CAAA;QACZ,CAAC,CAAA;QAED,GAAG,CAAC,MAAM,GAAG,CAAC,KAAa,EAAE,EAAE;YAC7B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;gBACxB,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;aACf;YACD,OAAO,GAAG,CAAA;QACZ,CAAC,CAAA;QAED,GAAG,CAAC,KAAK,GAAG,CAAC,KAAa,EAAE,EAAE;YAC5B,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;YACjB,QAAQ,EAAE,CAAA;YACV,OAAO,GAAG,CAAA;QACZ,CAAC,CAAA;KACF;IAED,OAAO,GAAG,CAAA;AACZ,CAAC;AAxDD,0BAwDC"}
package/cjs/useSet2.ts ADDED
@@ -0,0 +1,84 @@
1
+ import {useRef} from 'react'
2
+ import {useUpdate} from 'react-use'
3
+
4
+ export interface UseSet2<T> extends Set<T> {
5
+ _add: Set<T>['add']
6
+ _clear: Set<T>['clear']
7
+ _delete: Set<T>['delete']
8
+ toggle(v: T): void
9
+ reset(): void
10
+ _union(other: Set<T>): Set<T>
11
+ union(other: Set<T>): Set<T>
12
+ }
13
+
14
+ /**
15
+ * Returns a set-like object that intercepts the setter function to
16
+ * trigger re-renders on change. Also adds a toggle and reset method.
17
+ *
18
+ * @example
19
+ *
20
+ * ```typescript
21
+ * function MyComponent() {
22
+ * const optionalInitialValue = new Set()
23
+ * const set = useSet2(optionalInitialValue)
24
+
25
+ * // ... Use set like you would a vanilla JS Set
26
+ * ```
27
+ */
28
+ export function useSet2<T>(initial: Set<T> = new Set()) {
29
+ const rerender = useUpdate()
30
+ const setRef = useRef(initial as unknown as UseSet2<T>)
31
+ const set = setRef.current
32
+
33
+ if (!set._add) {
34
+ set._add = set.add
35
+ set.add = v => {
36
+ set._add(v)
37
+ rerender()
38
+ return set
39
+ }
40
+
41
+ set._clear = set.clear
42
+ set.clear = () => {
43
+ set._clear()
44
+ rerender()
45
+ return set
46
+ }
47
+
48
+ set._delete = set.delete
49
+ set.delete = v => {
50
+ const res = set._delete(v)
51
+ rerender()
52
+ return res
53
+ }
54
+
55
+ set.reset = () => {
56
+ set._clear()
57
+ set._union(initial)
58
+ rerender()
59
+ return set
60
+ }
61
+
62
+ set.toggle = v => {
63
+ if (set.has(v)) set._delete(v)
64
+ else set._add(v)
65
+ rerender()
66
+ return set
67
+ }
68
+
69
+ set._union = (other: Set<T>) => {
70
+ for (const elem of other) {
71
+ set._add(elem)
72
+ }
73
+ return set
74
+ }
75
+
76
+ set.union = (other: Set<T>) => {
77
+ set._union(other)
78
+ rerender()
79
+ return set
80
+ }
81
+ }
82
+
83
+ return set
84
+ }
@@ -0,0 +1 @@
1
+ type Fnc = (...args: any) => any
package/esm/index.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ export * from '@slimr/forms';
2
+ export * from '@slimr/markdown';
3
+ export * from '@slimr/router';
4
+ export * from '@slimr/styled';
5
+ export * from '@slimr/swr';
6
+ export * from '@slimr/util';
7
+ export * from 'react-use';
8
+ export * from './useMemos.js';
9
+ export * from './useSet2.js';
package/esm/index.js ADDED
@@ -0,0 +1,10 @@
1
+ export * from '@slimr/forms';
2
+ export * from '@slimr/markdown';
3
+ export * from '@slimr/router';
4
+ export * from '@slimr/styled';
5
+ export * from '@slimr/swr';
6
+ export * from '@slimr/util';
7
+ export * from 'react-use';
8
+ export * from './useMemos.js';
9
+ export * from './useSet2.js';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA;AAC5B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,eAAe,CAAA;AAC7B,cAAc,eAAe,CAAA;AAC7B,cAAc,YAAY,CAAA;AAC1B,cAAc,aAAa,CAAA;AAC3B,cAAc,WAAW,CAAA;AAEzB,cAAc,eAAe,CAAA;AAC7B,cAAc,cAAc,CAAA"}
package/esm/index.ts ADDED
@@ -0,0 +1,10 @@
1
+ export * from '@slimr/forms'
2
+ export * from '@slimr/markdown'
3
+ export * from '@slimr/router'
4
+ export * from '@slimr/styled'
5
+ export * from '@slimr/swr'
6
+ export * from '@slimr/util'
7
+ export * from 'react-use'
8
+
9
+ export * from './useMemos.js'
10
+ export * from './useSet2.js'
@@ -0,0 +1,14 @@
1
+ type Fnc = (...args: any[]) => any;
2
+ /**
3
+ * Like useMemo, but does a deep compare instead default compare
4
+ * to avoid misfires. Is more expensive than useMemo though,
5
+ * so use it intensionally.
6
+ */
7
+ export declare function useDeepCompareMemo(callback: Fnc, varsToWatch: any[]): any;
8
+ /**
9
+ * Like useMemo, but does a shallow compare instead default compare
10
+ * to avoid misfires. Is more expensive than useMemo though, but
11
+ * less than useDeepCompareMemo, so use it intentionally.
12
+ */
13
+ export declare function useShallowCompareMemo(callback: Fnc, varsToWatch: any[]): any;
14
+ export {};
@@ -0,0 +1,31 @@
1
+ import { areNotEqualDeep } from '@slimr/util';
2
+ import { useEffect, useMemo, useState } from 'react';
3
+ /**
4
+ * Like useMemo, but does a deep compare instead default compare
5
+ * to avoid misfires. Is more expensive than useMemo though,
6
+ * so use it intensionally.
7
+ */
8
+ export function useDeepCompareMemo(callback, varsToWatch) {
9
+ const [lastSeenProps, setLastSeenProps] = useState(varsToWatch);
10
+ useEffect(() => {
11
+ if (areNotEqualDeep(varsToWatch, lastSeenProps)) {
12
+ setLastSeenProps(varsToWatch);
13
+ }
14
+ }, varsToWatch);
15
+ return useMemo(callback, [lastSeenProps]);
16
+ }
17
+ /**
18
+ * Like useMemo, but does a shallow compare instead default compare
19
+ * to avoid misfires. Is more expensive than useMemo though, but
20
+ * less than useDeepCompareMemo, so use it intentionally.
21
+ */
22
+ export function useShallowCompareMemo(callback, varsToWatch) {
23
+ const [lastSeenProps, setLastSeenProps] = useState(varsToWatch);
24
+ useEffect(() => {
25
+ if (areNotEqualDeep(varsToWatch, lastSeenProps)) {
26
+ setLastSeenProps(varsToWatch);
27
+ }
28
+ }, varsToWatch);
29
+ return useMemo(callback, [lastSeenProps]);
30
+ }
31
+ //# sourceMappingURL=useMemos.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useMemos.js","sourceRoot":"","sources":["../src/useMemos.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAC,MAAM,aAAa,CAAA;AAC3C,OAAO,EAAC,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAC,MAAM,OAAO,CAAA;AAIlD;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,QAAa,EAAE,WAAkB;IAClE,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAA;IAC/D,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,eAAe,CAAC,WAAW,EAAE,aAAa,CAAC,EAAE;YAC/C,gBAAgB,CAAC,WAAW,CAAC,CAAA;SAC9B;IACH,CAAC,EAAE,WAAW,CAAC,CAAA;IACf,OAAO,OAAO,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,CAAC,CAAA;AAC3C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAAa,EAAE,WAAkB;IACrE,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAA;IAC/D,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,eAAe,CAAC,WAAW,EAAE,aAAa,CAAC,EAAE;YAC/C,gBAAgB,CAAC,WAAW,CAAC,CAAA;SAC9B;IACH,CAAC,EAAE,WAAW,CAAC,CAAA;IACf,OAAO,OAAO,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,CAAC,CAAA;AAC3C,CAAC"}
@@ -0,0 +1,34 @@
1
+ import {areNotEqualDeep} from '@slimr/util'
2
+ import {useEffect, useMemo, useState} from 'react'
3
+
4
+ type Fnc = (...args: any[]) => any
5
+
6
+ /**
7
+ * Like useMemo, but does a deep compare instead default compare
8
+ * to avoid misfires. Is more expensive than useMemo though,
9
+ * so use it intensionally.
10
+ */
11
+ export function useDeepCompareMemo(callback: Fnc, varsToWatch: any[]) {
12
+ const [lastSeenProps, setLastSeenProps] = useState(varsToWatch)
13
+ useEffect(() => {
14
+ if (areNotEqualDeep(varsToWatch, lastSeenProps)) {
15
+ setLastSeenProps(varsToWatch)
16
+ }
17
+ }, varsToWatch)
18
+ return useMemo(callback, [lastSeenProps])
19
+ }
20
+
21
+ /**
22
+ * Like useMemo, but does a shallow compare instead default compare
23
+ * to avoid misfires. Is more expensive than useMemo though, but
24
+ * less than useDeepCompareMemo, so use it intentionally.
25
+ */
26
+ export function useShallowCompareMemo(callback: Fnc, varsToWatch: any[]) {
27
+ const [lastSeenProps, setLastSeenProps] = useState(varsToWatch)
28
+ useEffect(() => {
29
+ if (areNotEqualDeep(varsToWatch, lastSeenProps)) {
30
+ setLastSeenProps(varsToWatch)
31
+ }
32
+ }, varsToWatch)
33
+ return useMemo(callback, [lastSeenProps])
34
+ }
@@ -0,0 +1,24 @@
1
+ export interface UseSet2<T> extends Set<T> {
2
+ _add: Set<T>['add'];
3
+ _clear: Set<T>['clear'];
4
+ _delete: Set<T>['delete'];
5
+ toggle(v: T): void;
6
+ reset(): void;
7
+ _union(other: Set<T>): Set<T>;
8
+ union(other: Set<T>): Set<T>;
9
+ }
10
+ /**
11
+ * Returns a set-like object that intercepts the setter function to
12
+ * trigger re-renders on change. Also adds a toggle and reset method.
13
+ *
14
+ * @example
15
+ *
16
+ * ```typescript
17
+ * function MyComponent() {
18
+ * const optionalInitialValue = new Set()
19
+ * const set = useSet2(optionalInitialValue)
20
+
21
+ * // ... Use set like you would a vanilla JS Set
22
+ * ```
23
+ */
24
+ export declare function useSet2<T>(initial?: Set<T>): UseSet2<T>;
package/esm/useSet2.js ADDED
@@ -0,0 +1,68 @@
1
+ import { useRef } from 'react';
2
+ import { useUpdate } from 'react-use';
3
+ /**
4
+ * Returns a set-like object that intercepts the setter function to
5
+ * trigger re-renders on change. Also adds a toggle and reset method.
6
+ *
7
+ * @example
8
+ *
9
+ * ```typescript
10
+ * function MyComponent() {
11
+ * const optionalInitialValue = new Set()
12
+ * const set = useSet2(optionalInitialValue)
13
+
14
+ * // ... Use set like you would a vanilla JS Set
15
+ * ```
16
+ */
17
+ export function useSet2(initial = new Set()) {
18
+ const rerender = useUpdate();
19
+ const setRef = useRef(initial);
20
+ const set = setRef.current;
21
+ if (!set._add) {
22
+ set._add = set.add;
23
+ set.add = v => {
24
+ set._add(v);
25
+ rerender();
26
+ return set;
27
+ };
28
+ set._clear = set.clear;
29
+ set.clear = () => {
30
+ set._clear();
31
+ rerender();
32
+ return set;
33
+ };
34
+ set._delete = set.delete;
35
+ set.delete = v => {
36
+ const res = set._delete(v);
37
+ rerender();
38
+ return res;
39
+ };
40
+ set.reset = () => {
41
+ set._clear();
42
+ set._union(initial);
43
+ rerender();
44
+ return set;
45
+ };
46
+ set.toggle = v => {
47
+ if (set.has(v))
48
+ set._delete(v);
49
+ else
50
+ set._add(v);
51
+ rerender();
52
+ return set;
53
+ };
54
+ set._union = (other) => {
55
+ for (const elem of other) {
56
+ set._add(elem);
57
+ }
58
+ return set;
59
+ };
60
+ set.union = (other) => {
61
+ set._union(other);
62
+ rerender();
63
+ return set;
64
+ };
65
+ }
66
+ return set;
67
+ }
68
+ //# sourceMappingURL=useSet2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSet2.js","sourceRoot":"","sources":["../src/useSet2.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAC,MAAM,OAAO,CAAA;AAC5B,OAAO,EAAC,SAAS,EAAC,MAAM,WAAW,CAAA;AAYnC;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,OAAO,CAAI,UAAkB,IAAI,GAAG,EAAE;IACpD,MAAM,QAAQ,GAAG,SAAS,EAAE,CAAA;IAC5B,MAAM,MAAM,GAAG,MAAM,CAAC,OAAgC,CAAC,CAAA;IACvD,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAA;IAE1B,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE;QACb,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,GAAG,CAAA;QAClB,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE;YACZ,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACX,QAAQ,EAAE,CAAA;YACV,OAAO,GAAG,CAAA;QACZ,CAAC,CAAA;QAED,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,KAAK,CAAA;QACtB,GAAG,CAAC,KAAK,GAAG,GAAG,EAAE;YACf,GAAG,CAAC,MAAM,EAAE,CAAA;YACZ,QAAQ,EAAE,CAAA;YACV,OAAO,GAAG,CAAA;QACZ,CAAC,CAAA;QAED,GAAG,CAAC,OAAO,GAAG,GAAG,CAAC,MAAM,CAAA;QACxB,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE;YACf,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;YAC1B,QAAQ,EAAE,CAAA;YACV,OAAO,GAAG,CAAA;QACZ,CAAC,CAAA;QAED,GAAG,CAAC,KAAK,GAAG,GAAG,EAAE;YACf,GAAG,CAAC,MAAM,EAAE,CAAA;YACZ,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;YACnB,QAAQ,EAAE,CAAA;YACV,OAAO,GAAG,CAAA;QACZ,CAAC,CAAA;QAED,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE;YACf,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;gBAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;;gBACzB,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YAChB,QAAQ,EAAE,CAAA;YACV,OAAO,GAAG,CAAA;QACZ,CAAC,CAAA;QAED,GAAG,CAAC,MAAM,GAAG,CAAC,KAAa,EAAE,EAAE;YAC7B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;gBACxB,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;aACf;YACD,OAAO,GAAG,CAAA;QACZ,CAAC,CAAA;QAED,GAAG,CAAC,KAAK,GAAG,CAAC,KAAa,EAAE,EAAE;YAC5B,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;YACjB,QAAQ,EAAE,CAAA;YACV,OAAO,GAAG,CAAA;QACZ,CAAC,CAAA;KACF;IAED,OAAO,GAAG,CAAA;AACZ,CAAC"}
package/esm/useSet2.ts ADDED
@@ -0,0 +1,84 @@
1
+ import {useRef} from 'react'
2
+ import {useUpdate} from 'react-use'
3
+
4
+ export interface UseSet2<T> extends Set<T> {
5
+ _add: Set<T>['add']
6
+ _clear: Set<T>['clear']
7
+ _delete: Set<T>['delete']
8
+ toggle(v: T): void
9
+ reset(): void
10
+ _union(other: Set<T>): Set<T>
11
+ union(other: Set<T>): Set<T>
12
+ }
13
+
14
+ /**
15
+ * Returns a set-like object that intercepts the setter function to
16
+ * trigger re-renders on change. Also adds a toggle and reset method.
17
+ *
18
+ * @example
19
+ *
20
+ * ```typescript
21
+ * function MyComponent() {
22
+ * const optionalInitialValue = new Set()
23
+ * const set = useSet2(optionalInitialValue)
24
+
25
+ * // ... Use set like you would a vanilla JS Set
26
+ * ```
27
+ */
28
+ export function useSet2<T>(initial: Set<T> = new Set()) {
29
+ const rerender = useUpdate()
30
+ const setRef = useRef(initial as unknown as UseSet2<T>)
31
+ const set = setRef.current
32
+
33
+ if (!set._add) {
34
+ set._add = set.add
35
+ set.add = v => {
36
+ set._add(v)
37
+ rerender()
38
+ return set
39
+ }
40
+
41
+ set._clear = set.clear
42
+ set.clear = () => {
43
+ set._clear()
44
+ rerender()
45
+ return set
46
+ }
47
+
48
+ set._delete = set.delete
49
+ set.delete = v => {
50
+ const res = set._delete(v)
51
+ rerender()
52
+ return res
53
+ }
54
+
55
+ set.reset = () => {
56
+ set._clear()
57
+ set._union(initial)
58
+ rerender()
59
+ return set
60
+ }
61
+
62
+ set.toggle = v => {
63
+ if (set.has(v)) set._delete(v)
64
+ else set._add(v)
65
+ rerender()
66
+ return set
67
+ }
68
+
69
+ set._union = (other: Set<T>) => {
70
+ for (const elem of other) {
71
+ set._add(elem)
72
+ }
73
+ return set
74
+ }
75
+
76
+ set.union = (other: Set<T>) => {
77
+ set._union(other)
78
+ rerender()
79
+ return set
80
+ }
81
+ }
82
+
83
+ return set
84
+ }
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@slimr/react",
3
+ "version": "2.1.45",
4
+ "author": "Brian Dombrowski",
5
+ "license": "ISC",
6
+ "private": false,
7
+ "sideEffects": false,
8
+ "keywords": [
9
+ "preact",
10
+ "react",
11
+ "swr"
12
+ ],
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "https://github.com/bdombro/slimr.git"
16
+ },
17
+ "type": "module",
18
+ "main": "./cjs/index.js",
19
+ "module": "./esm/index.js",
20
+ "exports": {
21
+ ".": {
22
+ "require": "./cjs/index.js",
23
+ "import": "./esm/index.js"
24
+ }
25
+ },
26
+ "scripts": {
27
+ "build": "run-p build:*",
28
+ "build:esm": "OUT=esm; tsc -d --outDir $OUT --noEmit false && cp -r src/* $OUT",
29
+ "build:cjs": "OUT=cjs; tsc -d -m commonjs --moduleResolution node --outDir $OUT --noEmit false && cp -r src/* $OUT",
30
+ "clean": "rm -rf esm cjs",
31
+ "prepack": "run-s build",
32
+ "start": "nodemon -w src -e '*' -x 'npm run build && cd ../demo && npm start'"
33
+ },
34
+ "dependencies": {
35
+ "@slimr/forms": "^4.1.42",
36
+ "@slimr/swr": "^2.1.33",
37
+ "@slimr/util": "^3.2.36",
38
+ "react-use": "17"
39
+ },
40
+ "peerDependencies": {
41
+ "@types/react": "^16.8 || ^17 || ^18",
42
+ "@types/react-dom": "^16.8 || ^17 || ^18",
43
+ "react": "^16.8 || ^17 || ^18",
44
+ "react-dom": "^16.8 || ^17 || ^18"
45
+ }
46
+ }
@@ -0,0 +1 @@
1
+ type Fnc = (...args: any) => any
package/src/index.ts ADDED
@@ -0,0 +1,10 @@
1
+ export * from '@slimr/forms'
2
+ export * from '@slimr/markdown'
3
+ export * from '@slimr/router'
4
+ export * from '@slimr/styled'
5
+ export * from '@slimr/swr'
6
+ export * from '@slimr/util'
7
+ export * from 'react-use'
8
+
9
+ export * from './useMemos.js'
10
+ export * from './useSet2.js'
@@ -0,0 +1,34 @@
1
+ import {areNotEqualDeep} from '@slimr/util'
2
+ import {useEffect, useMemo, useState} from 'react'
3
+
4
+ type Fnc = (...args: any[]) => any
5
+
6
+ /**
7
+ * Like useMemo, but does a deep compare instead default compare
8
+ * to avoid misfires. Is more expensive than useMemo though,
9
+ * so use it intensionally.
10
+ */
11
+ export function useDeepCompareMemo(callback: Fnc, varsToWatch: any[]) {
12
+ const [lastSeenProps, setLastSeenProps] = useState(varsToWatch)
13
+ useEffect(() => {
14
+ if (areNotEqualDeep(varsToWatch, lastSeenProps)) {
15
+ setLastSeenProps(varsToWatch)
16
+ }
17
+ }, varsToWatch)
18
+ return useMemo(callback, [lastSeenProps])
19
+ }
20
+
21
+ /**
22
+ * Like useMemo, but does a shallow compare instead default compare
23
+ * to avoid misfires. Is more expensive than useMemo though, but
24
+ * less than useDeepCompareMemo, so use it intentionally.
25
+ */
26
+ export function useShallowCompareMemo(callback: Fnc, varsToWatch: any[]) {
27
+ const [lastSeenProps, setLastSeenProps] = useState(varsToWatch)
28
+ useEffect(() => {
29
+ if (areNotEqualDeep(varsToWatch, lastSeenProps)) {
30
+ setLastSeenProps(varsToWatch)
31
+ }
32
+ }, varsToWatch)
33
+ return useMemo(callback, [lastSeenProps])
34
+ }
package/src/useSet2.ts ADDED
@@ -0,0 +1,84 @@
1
+ import {useRef} from 'react'
2
+ import {useUpdate} from 'react-use'
3
+
4
+ export interface UseSet2<T> extends Set<T> {
5
+ _add: Set<T>['add']
6
+ _clear: Set<T>['clear']
7
+ _delete: Set<T>['delete']
8
+ toggle(v: T): void
9
+ reset(): void
10
+ _union(other: Set<T>): Set<T>
11
+ union(other: Set<T>): Set<T>
12
+ }
13
+
14
+ /**
15
+ * Returns a set-like object that intercepts the setter function to
16
+ * trigger re-renders on change. Also adds a toggle and reset method.
17
+ *
18
+ * @example
19
+ *
20
+ * ```typescript
21
+ * function MyComponent() {
22
+ * const optionalInitialValue = new Set()
23
+ * const set = useSet2(optionalInitialValue)
24
+
25
+ * // ... Use set like you would a vanilla JS Set
26
+ * ```
27
+ */
28
+ export function useSet2<T>(initial: Set<T> = new Set()) {
29
+ const rerender = useUpdate()
30
+ const setRef = useRef(initial as unknown as UseSet2<T>)
31
+ const set = setRef.current
32
+
33
+ if (!set._add) {
34
+ set._add = set.add
35
+ set.add = v => {
36
+ set._add(v)
37
+ rerender()
38
+ return set
39
+ }
40
+
41
+ set._clear = set.clear
42
+ set.clear = () => {
43
+ set._clear()
44
+ rerender()
45
+ return set
46
+ }
47
+
48
+ set._delete = set.delete
49
+ set.delete = v => {
50
+ const res = set._delete(v)
51
+ rerender()
52
+ return res
53
+ }
54
+
55
+ set.reset = () => {
56
+ set._clear()
57
+ set._union(initial)
58
+ rerender()
59
+ return set
60
+ }
61
+
62
+ set.toggle = v => {
63
+ if (set.has(v)) set._delete(v)
64
+ else set._add(v)
65
+ rerender()
66
+ return set
67
+ }
68
+
69
+ set._union = (other: Set<T>) => {
70
+ for (const elem of other) {
71
+ set._add(elem)
72
+ }
73
+ return set
74
+ }
75
+
76
+ set.union = (other: Set<T>) => {
77
+ set._union(other)
78
+ rerender()
79
+ return set
80
+ }
81
+ }
82
+
83
+ return set
84
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,4 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "include": ["src"]
4
+ }