@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 +120 -0
- package/cjs/@types/global.d.ts +1 -0
- package/cjs/index.d.ts +9 -0
- package/cjs/index.js +26 -0
- package/cjs/index.js.map +1 -0
- package/cjs/index.ts +10 -0
- package/cjs/useMemos.d.ts +14 -0
- package/cjs/useMemos.js +36 -0
- package/cjs/useMemos.js.map +1 -0
- package/cjs/useMemos.ts +34 -0
- package/cjs/useSet2.d.ts +24 -0
- package/cjs/useSet2.js +72 -0
- package/cjs/useSet2.js.map +1 -0
- package/cjs/useSet2.ts +84 -0
- package/esm/@types/global.d.ts +1 -0
- package/esm/index.d.ts +9 -0
- package/esm/index.js +10 -0
- package/esm/index.js.map +1 -0
- package/esm/index.ts +10 -0
- package/esm/useMemos.d.ts +14 -0
- package/esm/useMemos.js +31 -0
- package/esm/useMemos.js.map +1 -0
- package/esm/useMemos.ts +34 -0
- package/esm/useSet2.d.ts +24 -0
- package/esm/useSet2.js +68 -0
- package/esm/useSet2.js.map +1 -0
- package/esm/useSet2.ts +84 -0
- package/package.json +46 -0
- package/src/@types/global.d.ts +1 -0
- package/src/index.ts +10 -0
- package/src/useMemos.ts +34 -0
- package/src/useSet2.ts +84 -0
- package/tsconfig.json +4 -0
package/README.md
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# 🪶 @slimr/react [](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
|
package/cjs/index.js.map
ADDED
|
@@ -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 {};
|
package/cjs/useMemos.js
ADDED
|
@@ -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"}
|
package/cjs/useMemos.ts
ADDED
|
@@ -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/cjs/useSet2.d.ts
ADDED
|
@@ -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
|
package/esm/index.js.map
ADDED
|
@@ -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 {};
|
package/esm/useMemos.js
ADDED
|
@@ -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"}
|
package/esm/useMemos.ts
ADDED
|
@@ -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/esm/useSet2.d.ts
ADDED
|
@@ -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'
|
package/src/useMemos.ts
ADDED
|
@@ -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