Skip to content

Commit a9a5b60

Browse files
authored
Merge pull request #1 from freckle/sl/initialize-package
Initialize Package
2 parents 23564af + ad2f6d5 commit a9a5b60

File tree

17 files changed

+5983
-0
lines changed

17 files changed

+5983
-0
lines changed

.flowconfig

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[ignore]
2+
.*/node_modules/resolve/test/resolver/malformed_package_json/package.json
3+
4+
5+
[include]
6+
7+
[libs]
8+
9+
[lints]
10+
11+
[options]
12+
13+
[strict]

.github/workflows/ci.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
name: CI
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches: main
7+
8+
jobs:
9+
build:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v2
13+
- uses: actions/setup-node@v2
14+
with:
15+
cache: yarn
16+
- run: yarn install
17+
- run: yarn build
18+
- run: yarn gen-flow
19+
- run: yarn test
20+
- run: yarn run check-git-clean

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules

.restyled.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
exclude:
2+
- "**/dist/**/*"
3+
- "**/*.patch"
4+
- "**/node_modules/**/*"
5+
- "**/vendor/**/*"
6+
- ".github/workflows/**/*" # https://github.com/restyled-io/restyler/issues/73
7+
8+
restylers:
9+
- clang-format:
10+
enabled: false
11+
- jq:
12+
enabled: false # prefer prettier-json
13+
- prettier:
14+
include:
15+
- 'src/**/*.js'

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2021 Renaissance Learning Inc
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# @freckle/react-hooks
2+
3+
Provides a collection of React hooks.

check-git-clean.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/bin/bash -e
2+
3+
if ! git diff --quiet; then echo "
4+
5+
The CI build resulted in additional changed files.
6+
Typically this is due to not running yarn build locally before
7+
submitting a pull request.
8+
9+
The following changes were found:
10+
";
11+
12+
git diff --exit-code;
13+
fi;

dist/index.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
"use strict";
2+
3+
Object.defineProperty(exports, "__esModule", {
4+
value: true
5+
});
6+
Object.defineProperty(exports, "unCallbackFn", {
7+
enumerable: true,
8+
get: function get() {
9+
return _useExtraDeps.unCallbackFn;
10+
}
11+
});
12+
Object.defineProperty(exports, "unsafeMkCallbackFn", {
13+
enumerable: true,
14+
get: function get() {
15+
return _useExtraDeps.unsafeMkCallbackFn;
16+
}
17+
});
18+
Object.defineProperty(exports, "useExtraDeps", {
19+
enumerable: true,
20+
get: function get() {
21+
return _useExtraDeps.useExtraDeps;
22+
}
23+
});
24+
25+
var _useExtraDeps = require("./use-extra-deps");

dist/index.js.flow

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// @flow
2+
3+
export type { PrimitiveDep, CallbackFn, ExtraDeps } from "./use-extra-deps";
4+
5+
export {
6+
unCallbackFn,
7+
unsafeMkCallbackFn,
8+
useExtraDeps,
9+
} from "./use-extra-deps";

dist/use-extra-deps/index.js

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
"use strict";
2+
3+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4+
5+
var _typeof = require("@babel/runtime/helpers/typeof");
6+
7+
Object.defineProperty(exports, "__esModule", {
8+
value: true
9+
});
10+
exports.unCallbackFn = void 0;
11+
exports.unsafeMkCallbackFn = unsafeMkCallbackFn;
12+
exports.useExtraDeps = useExtraDeps;
13+
14+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
15+
16+
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
17+
18+
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
19+
20+
var React = _interopRequireWildcard(require("react"));
21+
22+
var _pickBy = _interopRequireDefault(require("lodash/pickBy"));
23+
24+
var _omitBy = _interopRequireDefault(require("lodash/omitBy"));
25+
26+
var _isFunction = _interopRequireDefault(require("lodash/isFunction"));
27+
28+
var _mapValues = _interopRequireDefault(require("lodash/mapValues"));
29+
30+
var _values = _interopRequireDefault(require("lodash/values"));
31+
32+
var _isEqual = _interopRequireDefault(require("lodash/isEqual"));
33+
34+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
35+
36+
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
37+
38+
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
39+
40+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
41+
42+
var unCallbackFn = function unCallbackFn(fn) {
43+
return fn;
44+
}; // Used only by `useSafeCallback`
45+
46+
47+
exports.unCallbackFn = unCallbackFn;
48+
49+
function unsafeMkCallbackFn(f) {
50+
return f;
51+
}
52+
53+
// Hook used to help avoid pitfalls surrounding misuse of objects and arrays in
54+
// the deps of `useEffect` et. al.
55+
//
56+
// By only allowing `PrimitiveDep`s in the `deps` array and forcing functions
57+
// and non-primitives through `extraDeps`, we can ensure that we are not doing
58+
// naive reference equality like React does for the `deps` array.
59+
//
60+
// See `useSafeEffect` for usage of this hook
61+
//
62+
// Returns an object based upon deps and extraDeps: { allDeps: An array that is
63+
// suitable to use as a deps array for things like `useEffect` , extraDepValues:
64+
// An object that has the same keys as extraDeps but contains their plain values
65+
// }
66+
//
67+
function useExtraDeps(deps, extraDeps) {
68+
var _React$useState = React.useState(Symbol()),
69+
_React$useState2 = (0, _slicedToArray2["default"])(_React$useState, 2),
70+
run = _React$useState2[0],
71+
setRun = _React$useState2[1];
72+
73+
var nonFnsRef = React.useRef(null);
74+
var fns = (0, _pickBy["default"])(extraDeps, _isFunction["default"]);
75+
var nonFns = (0, _omitBy["default"])(extraDeps, _isFunction["default"]);
76+
77+
var hasChange = function hasChange() {
78+
if (nonFnsRef.current === null || nonFnsRef.current === undefined) {
79+
return true;
80+
}
81+
82+
for (var _key in nonFns) {
83+
if (!nonFns[_key].comparator(nonFns[_key].value, nonFnsRef.current[_key].value)) {
84+
return true;
85+
}
86+
}
87+
88+
return false;
89+
};
90+
91+
if (hasChange()) {
92+
setRun(Symbol());
93+
nonFnsRef.current = nonFns;
94+
}
95+
96+
return {
97+
allDeps: [].concat((0, _toConsumableArray2["default"])(deps), (0, _toConsumableArray2["default"])((0, _values["default"])(fns)), [run]),
98+
extraDepValues: _objectSpread(_objectSpread({}, (0, _mapValues["default"])(nonFns, function (_ref) {
99+
var value = _ref.value;
100+
return value;
101+
})), fns)
102+
};
103+
}

dist/use-extra-deps/index.js.flow

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// @flow
2+
3+
import * as React from "react";
4+
import pickBy from "lodash/pickBy";
5+
import omitBy from "lodash/omitBy";
6+
import isFunction from "lodash/isFunction";
7+
import mapValues from "lodash/mapValues";
8+
import values from "lodash/values";
9+
import isEqual from "lodash/isEqual";
10+
11+
// Dependencies that are safe to use in the normal `useEffect` deps array
12+
export type PrimitiveDep = boolean | string | number | null | void | Symbol;
13+
14+
// Wrapper around a function that has been wrapped in `useSafeCallback`. This
15+
// type is here to avoid cyclical dependencies.
16+
export opaque type CallbackFn<F> = F;
17+
18+
export const unCallbackFn = <F>(fn: CallbackFn<F>): F => fn;
19+
20+
// Used only by `useSafeCallback`
21+
export function unsafeMkCallbackFn<F: (...Array<any>) => any>(
22+
f: F
23+
): CallbackFn<F> {
24+
return f;
25+
}
26+
27+
export type ExtraDeps<V> =
28+
| {| value: V, comparator: (a: V, b: V) => boolean |}
29+
| CallbackFn<V>;
30+
31+
// Hook used to help avoid pitfalls surrounding misuse of objects and arrays in
32+
// the deps of `useEffect` et. al.
33+
//
34+
// By only allowing `PrimitiveDep`s in the `deps` array and forcing functions
35+
// and non-primitives through `extraDeps`, we can ensure that we are not doing
36+
// naive reference equality like React does for the `deps` array.
37+
//
38+
// See `useSafeEffect` for usage of this hook
39+
//
40+
// Returns an object based upon deps and extraDeps: { allDeps: An array that is
41+
// suitable to use as a deps array for things like `useEffect` , extraDepValues:
42+
// An object that has the same keys as extraDeps but contains their plain values
43+
// }
44+
//
45+
export function useExtraDeps<S: { [key: string]: any }>(
46+
deps: $ReadOnlyArray<PrimitiveDep>,
47+
extraDeps: S
48+
): {|
49+
allDeps: $ReadOnlyArray<any>,
50+
extraDepValues: $ObjMap<S, <V>(ExtraDeps<V>) => V>,
51+
|} {
52+
const [run, setRun] = React.useState<Symbol>(Symbol());
53+
const nonFnsRef = React.useRef(null);
54+
55+
const fns = pickBy(extraDeps, isFunction);
56+
const nonFns = omitBy(extraDeps, isFunction);
57+
58+
const hasChange = () => {
59+
if (nonFnsRef.current === null || nonFnsRef.current === undefined) {
60+
return true;
61+
}
62+
for (const key in nonFns) {
63+
if (
64+
!nonFns[key].comparator(nonFns[key].value, nonFnsRef.current[key].value)
65+
) {
66+
return true;
67+
}
68+
}
69+
return false;
70+
};
71+
72+
if (hasChange()) {
73+
setRun(Symbol());
74+
nonFnsRef.current = nonFns;
75+
}
76+
77+
return {
78+
allDeps: [...deps, ...values(fns), run],
79+
extraDepValues: { ...mapValues(nonFns, ({ value }) => value), ...fns },
80+
};
81+
}

0 commit comments

Comments
 (0)