@cleanweb/react 1.0.10 → 1.1.1-beta.0
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/build/base/merged-state.js +2 -1
- package/build/base/methods.d.ts +1 -2
- package/build/base/methods.js +2 -2
- package/build/base/state.d.ts +16 -12
- package/build/base/state.js +57 -24
- package/build/classy/class.d.ts +7 -8
- package/build/classy/class.js +31 -11
- package/build/classy/instance.d.ts +14 -8
- package/build/classy/instance.js +60 -23
- package/build/classy/logic.d.ts +14 -5
- package/build/classy/logic.js +46 -10
- package/build/globals.d.ts +63 -52
- package/build/globals.js +22 -0
- package/build/globals.private.d.ts +48 -0
- package/build/globals.private.js +40 -0
- package/build/tsconfig.json +5 -2
- package/package.json +18 -2
@@ -26,7 +26,8 @@ var MergedState = /** @class */ (function () {
|
|
26
26
|
this.valueKeys = [];
|
27
27
|
this._initialValues_ = __assign({}, initialState);
|
28
28
|
this._values_ = __assign({}, initialState);
|
29
|
-
Object.keys(initialState).forEach(function (
|
29
|
+
Object.keys(initialState).forEach(function (_key) {
|
30
|
+
var key = _key;
|
30
31
|
if (_this.reservedKeys.includes(key)) {
|
31
32
|
throw new Error("The name \"".concat(key, "\" is reserved by CleanState and cannot be used to index state variables. Please use a different key."));
|
32
33
|
}
|
package/build/base/methods.d.ts
CHANGED
@@ -3,7 +3,6 @@ export declare class ComponentMethods<TState extends object, TProps extends obje
|
|
3
3
|
state: TCleanState<TState>;
|
4
4
|
props: TProps;
|
5
5
|
}
|
6
|
-
type
|
7
|
-
type UseMethods = <MethodsClass extends ComponentMethodsConstructor>(Methods: MethodsClass, state: InstanceType<MethodsClass>['state'], props: InstanceType<MethodsClass>['props']) => InstanceType<MethodsClass>;
|
6
|
+
type UseMethods = <TMethods extends ComponentMethods<any, any>>(Methods: Constructor<TMethods>, state: TMethods['state'], props: TMethods['props']) => TMethods;
|
8
7
|
export declare const useMethods: UseMethods;
|
9
8
|
export {};
|
package/build/base/methods.js
CHANGED
@@ -14,10 +14,10 @@ var useMethods = function (Methods, state, props) {
|
|
14
14
|
// causing the instance to be unexpectedly recreated in the middle of the components lifecycle.
|
15
15
|
// But useRef and useState values appear to always be preserved whenever this happens.
|
16
16
|
// So those two are the only cross-render-persistence methods we can consider safe.
|
17
|
-
var methods = (0, react_1.useMemo)(function () {
|
17
|
+
var methods = (0, react_1.useRef)((0, react_1.useMemo)(function () {
|
18
18
|
// See useLogic implementation for a discussion of this type assertion.
|
19
19
|
return new Methods();
|
20
|
-
}, []);
|
20
|
+
}, [])).current;
|
21
21
|
methods.state = state;
|
22
22
|
methods.props = props;
|
23
23
|
return methods;
|
package/build/base/state.d.ts
CHANGED
@@ -1,4 +1,12 @@
|
|
1
|
-
|
1
|
+
/**
|
2
|
+
* Returns a value that is false before the component has been mounted,
|
3
|
+
* then true during all subsequent rerenders.
|
4
|
+
*/
|
5
|
+
export declare const useMountState: () => boolean;
|
6
|
+
type PutState<TState extends object> = {
|
7
|
+
[Key in keyof TState]: React.Dispatch<React.SetStateAction<TState[Key]>>;
|
8
|
+
};
|
9
|
+
declare class CleanStateBase<TState extends Record<string, any>> {
|
2
10
|
reservedKeys: string[];
|
3
11
|
valueKeys: string[];
|
4
12
|
private _values_;
|
@@ -6,20 +14,16 @@ declare class CleanStateBase<TState extends object> {
|
|
6
14
|
private _setters_;
|
7
15
|
constructor(initialState: TState);
|
8
16
|
static update: <TState_1 extends object>(this: CleanStateBase<TState_1>) => void;
|
9
|
-
get put():
|
17
|
+
get put(): PutState<TState>;
|
10
18
|
get initialState(): TState;
|
11
19
|
putMany: (newValues: Partial<TState>) => void;
|
12
20
|
}
|
13
21
|
type TCleanStateInstance<TState extends object> = TState & CleanStateBase<TState>;
|
14
22
|
export type TCleanState<TState extends object> = TCleanStateInstance<TState>;
|
15
|
-
type
|
16
|
-
type
|
17
|
-
type
|
18
|
-
type
|
19
|
-
|
20
|
-
|
21
|
-
* Returns a value that is false before the component has been mounted,
|
22
|
-
* then true during all subsequent rerenders.
|
23
|
-
*/
|
24
|
-
export declare const useMountState: () => boolean;
|
23
|
+
export type TState<YourCleanState extends CleanStateBase<{}>> = Omit<YourCleanState, keyof CleanStateBase<{}>>;
|
24
|
+
type StateInitFunction = (...args: any[]) => object;
|
25
|
+
type StateInit = object | StateInitFunction;
|
26
|
+
type TInitialState<Initializer extends StateInit> = Initializer extends (...args: any[]) => (infer TState extends object) ? TState : Initializer;
|
27
|
+
type TUseCleanState = <TInit extends StateInit>(_initialState: TInit, ...props: TInit extends (...args: infer TProps extends any[]) => (infer TState extends object) ? TProps : []) => TCleanStateInstance<TInitialState<TInit>>;
|
28
|
+
export declare const useCleanState: TUseCleanState;
|
25
29
|
export {};
|
package/build/base/state.js
CHANGED
@@ -11,8 +11,26 @@ var __assign = (this && this.__assign) || function () {
|
|
11
11
|
return __assign.apply(this, arguments);
|
12
12
|
};
|
13
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
14
|
-
exports.
|
14
|
+
exports.useCleanState = exports.useMountState = void 0;
|
15
15
|
var react_1 = require("react");
|
16
|
+
/**
|
17
|
+
* Returns a value that is false before the component has been mounted,
|
18
|
+
* then true during all subsequent rerenders.
|
19
|
+
*/
|
20
|
+
var useMountState = function () {
|
21
|
+
/**
|
22
|
+
* This must not be a stateful value. It should not be the cause of a rerender.
|
23
|
+
* It merely provides information about the render count,
|
24
|
+
* without influencing that count itself.
|
25
|
+
* So `mounted` should never be set with `useState`.
|
26
|
+
*/
|
27
|
+
var mounted = (0, react_1.useRef)(false);
|
28
|
+
(0, react_1.useEffect)(function () {
|
29
|
+
mounted.current = true;
|
30
|
+
}, []);
|
31
|
+
return mounted.current;
|
32
|
+
};
|
33
|
+
exports.useMountState = useMountState;
|
16
34
|
var CleanStateBase = /** @class */ (function () {
|
17
35
|
function CleanStateBase(initialState) {
|
18
36
|
var _this = this;
|
@@ -81,7 +99,14 @@ var CleanStateBase = /** @class */ (function () {
|
|
81
99
|
var retrieveState = react_1.useState;
|
82
100
|
this.valueKeys.forEach(function (key) {
|
83
101
|
var _a;
|
84
|
-
|
102
|
+
// @todo Make state updates accessible immediately. Use state.staged to access the scheduled updates.
|
103
|
+
var setter;
|
104
|
+
// @todo Support SetStateAction callback signature in state.put(...);
|
105
|
+
_a = retrieveState(_this.initialState[key]), _this._values_[key] = _a[0], setter = _a[1];
|
106
|
+
_this._setters_[key] = (function (valueOrCallback) {
|
107
|
+
// this._staged_[key] = value;
|
108
|
+
setter(valueOrCallback);
|
109
|
+
});
|
85
110
|
});
|
86
111
|
/* Object.entries<TUseStateArray<TState>>(stateAndSetters).forEach(([key, responseFromUseState]) => {
|
87
112
|
[this._values_[key], this._setters_[key]] = responseFromUseState;
|
@@ -92,29 +117,37 @@ var CleanStateBase = /** @class */ (function () {
|
|
92
117
|
}());
|
93
118
|
;
|
94
119
|
var CleanState = CleanStateBase;
|
95
|
-
var useCleanState = function (_initialState
|
96
|
-
|
97
|
-
var
|
98
|
-
|
120
|
+
var useCleanState = function (_initialState) {
|
121
|
+
var props = [];
|
122
|
+
for (var _i = 1; _i < arguments.length; _i++) {
|
123
|
+
props[_i - 1] = arguments[_i];
|
124
|
+
}
|
125
|
+
var mounted = (0, exports.useMountState)();
|
126
|
+
var initialState = typeof _initialState === 'function'
|
127
|
+
? (0, react_1.useMemo)(function () { return _initialState.apply(void 0, props); }, [])
|
128
|
+
: _initialState;
|
129
|
+
;
|
130
|
+
var freshInstance = {};
|
131
|
+
if (!mounted)
|
132
|
+
freshInstance = new CleanState(initialState);
|
133
|
+
if (!freshInstance.put)
|
134
|
+
throw new Error('useCleanState failed to initialized a state instance.');
|
135
|
+
var cleanState = (0, react_1.useRef)(freshInstance).current;
|
99
136
|
CleanState.update.call(cleanState);
|
100
137
|
return cleanState;
|
101
138
|
};
|
102
139
|
exports.useCleanState = useCleanState;
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
}, []);
|
118
|
-
return mounted.current;
|
119
|
-
};
|
120
|
-
exports.useMountState = useMountState;
|
140
|
+
// Should be valid.
|
141
|
+
// useCleanState((a: number) => ({b: a.toString(), q: 1}), 6);
|
142
|
+
// useCleanState((a: boolean) => ({b: a.toString()}), true);
|
143
|
+
// useCleanState((a: number, c?: string) => ({ b: `${a}` }), 6);
|
144
|
+
// useCleanState((a: number, c?: string) => ({ b: `${a}` }), 6, 'word');
|
145
|
+
// useCleanState((a: number, c: string) => ({ b: a + c, f: true }), 6, 'text');
|
146
|
+
// useCleanState({ d: 5000 });
|
147
|
+
// Should fail.
|
148
|
+
// useCleanState((a: number) => ({b: a.toString(), q: 1}), 6, false);
|
149
|
+
// useCleanState((a: boolean) => ({b: a.toString()}));
|
150
|
+
// useCleanState((a: number, c?: string) => ({ b: `${a}` }), '6');
|
151
|
+
// useCleanState((a: number, c?: string) => ({ b: `${a}` }));
|
152
|
+
// useCleanState((a: number, c: string) => ({ b: a + c, f: true }), 6, 7);
|
153
|
+
// useCleanState({ d: 5000 }, true);
|
package/build/classy/class.d.ts
CHANGED
@@ -1,13 +1,12 @@
|
|
1
|
-
import type {
|
2
|
-
import type {
|
1
|
+
import type { VoidFunctionComponent } from 'react';
|
2
|
+
import type { TComponentClass } from './logic';
|
3
3
|
import { ComponentInstance } from './instance';
|
4
|
-
type
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
static FC:
|
4
|
+
type Extractor = <TComponent extends ClassComponent<object, object, object>>(this: TComponentClass<TComponent, typeof ClassComponent>, _Component?: TComponentClass<TComponent, typeof ClassComponent>) => VoidFunctionComponent;
|
5
|
+
export declare class ClassComponent<TState extends object = EmptyObject, TProps extends object = EmptyObject, THooks extends object = EmptyObject> extends ComponentInstance<TState, TProps, THooks> {
|
6
|
+
Render: VoidFunctionComponent<{}>;
|
7
|
+
static renderAs: 'component' | 'template';
|
8
|
+
static FC: Extractor;
|
9
9
|
}
|
10
|
-
type AnyFunction = (...args: any) => any;
|
11
10
|
interface HookWrapperProps<THookFunction extends AnyFunction> {
|
12
11
|
hook: THookFunction;
|
13
12
|
argumentsList: Parameters<THookFunction>;
|
package/build/classy/class.js
CHANGED
@@ -16,6 +16,7 @@ var __extends = (this && this.__extends) || (function () {
|
|
16
16
|
})();
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
18
18
|
exports.Use = exports.ClassComponent = void 0;
|
19
|
+
var jsx_runtime_1 = require("react/jsx-runtime");
|
19
20
|
var react_1 = require("react");
|
20
21
|
var instance_1 = require("./instance");
|
21
22
|
/** Provide more useful stack traces for otherwise non-specific function names. */
|
@@ -31,37 +32,56 @@ var setFunctionName = function (func, newName) {
|
|
31
32
|
console.warn(error);
|
32
33
|
}
|
33
34
|
};
|
35
|
+
// eslint-enable no-use-before-define
|
34
36
|
var ClassComponent = /** @class */ (function (_super) {
|
35
37
|
__extends(ClassComponent, _super);
|
36
38
|
function ClassComponent() {
|
37
39
|
return _super !== null && _super.apply(this, arguments) || this;
|
38
40
|
}
|
41
|
+
ClassComponent.renderAs = 'component';
|
39
42
|
ClassComponent.FC = function FC(_Component) {
|
40
|
-
var Component = _Component
|
43
|
+
var Component = _Component !== null && _Component !== void 0 ? _Component : this;
|
41
44
|
var isClassComponentType = Component.prototype instanceof ClassComponent;
|
42
45
|
if (!Component.getInitialState || !isClassComponentType)
|
43
46
|
throw new Error('Attempted to initialize ClassComponent with invalid Class type. Either pass a class that extends ClassComponent to FC (e.g `export FC(MyComponent);`), or ensure it is called as a method on a ClassComponent constructor type (e.g `export MyComponent.FC()`).');
|
44
|
-
var Wrapper = function (props) {
|
47
|
+
var Wrapper = function (props, context) {
|
45
48
|
var Render = (0, instance_1.useInstance)(Component, props).Render;
|
46
49
|
// Add calling component name to Render function name in stack traces.
|
47
|
-
(0, react_1.useMemo)(function () { return setFunctionName(Render, "".concat(Component.name, "
|
50
|
+
(0, react_1.useMemo)(function () { return setFunctionName(Render, "".concat(Component.name, ".Render")); }, [Render]);
|
48
51
|
/**
|
49
|
-
*
|
52
|
+
* Normally a component can update it's own state in the "before-render" stage to
|
53
|
+
* skip DOM updates and trigger and immediate rerun of the rendering with the new state.
|
54
|
+
*
|
55
|
+
* It may be impossible to do this within the body of Render, if we call it as JSX here,
|
50
56
|
* since technically, the Wrapper component owns the state and not the Render component.
|
51
|
-
*
|
52
|
-
|
53
|
-
|
54
|
-
|
57
|
+
* Using it as JSX establishes a component boundary, and React will throw an error if we try to set
|
58
|
+
* state in the "before-render" stage of `Render`, since it will be attempting to update it's parent's
|
59
|
+
* state (i.e `Wrapper` component) rather than it's own state.
|
60
|
+
*
|
61
|
+
* Consider using this as a function call instead of JSX to avoid that. This way, we avoid
|
62
|
+
* establishing a component boundary between `Wrapper` and `Render`.
|
63
|
+
*
|
64
|
+
* Although, since beforeRender() is called earlier from a hook, this is probably
|
65
|
+
* a non-issue. It will only force users to move their logic into `beforeRender` instead
|
66
|
+
* of doing it directly in `Render`. This might mean cleaner Render functions,
|
67
|
+
* so there's probably no real value lost if we keep the component boundary.
|
68
|
+
**/
|
69
|
+
if (Component.renderAs === 'template')
|
70
|
+
return Render({}, context);
|
71
|
+
// With the existence of useContext(),
|
72
|
+
// what exactly does the context argument to FunctionComponent represent?
|
73
|
+
// Do we need to find a way to pass that context value to <Render /> here?
|
74
|
+
return (0, jsx_runtime_1.jsx)(Render, {});
|
55
75
|
};
|
56
76
|
// Include calling component name in wrapper function name on stack traces.
|
57
|
-
setFunctionName(Wrapper, "".concat(Component.name, "
|
77
|
+
setFunctionName(Wrapper, "".concat(Component.name, " < Wrapper")); // ${Wrapper.name}
|
58
78
|
return Wrapper;
|
59
79
|
};
|
60
80
|
return ClassComponent;
|
61
81
|
}(instance_1.ComponentInstance));
|
62
82
|
exports.ClassComponent = ClassComponent;
|
63
|
-
var Use = function (
|
64
|
-
var useGenericHook =
|
83
|
+
var Use = function (params) {
|
84
|
+
var useGenericHook = params.hook, argumentsList = params.argumentsList, onUpdate = params.onUpdate;
|
65
85
|
var output = useGenericHook.apply(void 0, argumentsList);
|
66
86
|
(0, react_1.useEffect)(function () {
|
67
87
|
onUpdate(output);
|
@@ -1,9 +1,8 @@
|
|
1
|
-
import type {
|
1
|
+
import type { TComponentClass } from './logic';
|
2
2
|
import { ComponentLogic } from './logic';
|
3
|
-
type Obj = Record<string, any>;
|
4
3
|
type AsyncAllowedEffectCallback = () => Awaitable<IVoidFunction>;
|
5
4
|
export declare const noOp: () => void;
|
6
|
-
export declare class ComponentInstance<TState extends
|
5
|
+
export declare class ComponentInstance<TState extends object = EmptyObject, TProps extends object = EmptyObject, THooks extends object = EmptyObject> extends ComponentLogic<TState, TProps, THooks> {
|
7
6
|
/**
|
8
7
|
* Runs only _before_ first render, i.e before the component instance is mounted.
|
9
8
|
* Useful for logic that is involved in determining what to render.
|
@@ -48,10 +47,17 @@ export declare class ComponentInstance<TState extends Obj = {}, TProps extends O
|
|
48
47
|
*/
|
49
48
|
cleanUp: IVoidFunction;
|
50
49
|
}
|
51
|
-
type
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
50
|
+
type UseInstance = <TClass extends ComponentInstance<object, object, object>>(Class: TComponentClass<TClass>, ...props: valueof<TClass['props']> extends never ? ([] | [EmptyObject] | [TClass['props']]) : [TClass['props']]) => TClass;
|
51
|
+
/**
|
52
|
+
* To ensure successful type checking, the second parameter must be written with spread syntax.
|
53
|
+
* Likely because of the `exactOptionalPropertyTypes` config option turned on,
|
54
|
+
* and `UseInstance` using an empty tuple in its rest parameter type, attempting to simply
|
55
|
+
* retrieve the second argument directly causes an error when that argument is passed on to `useLogic`.
|
56
|
+
* But directly working with the rest array bypasses the problem. Also note that the issue persists even when
|
57
|
+
* the second param is given `{}` as a default follow to account for the empty tuple case. TypeScript
|
58
|
+
* just wants us to use the rest parameter explicitly by force.
|
59
|
+
*/
|
56
60
|
export declare const useInstance: UseInstance;
|
61
|
+
type UseMountCallbacks = <TInstance extends ComponentInstance<any, any, any>>(instance: TInstance) => void;
|
62
|
+
export declare const useMountCallbacks: UseMountCallbacks;
|
57
63
|
export {};
|
package/build/classy/instance.js
CHANGED
@@ -14,8 +14,17 @@ var __extends = (this && this.__extends) || (function () {
|
|
14
14
|
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
15
15
|
};
|
16
16
|
})();
|
17
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
18
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
19
|
+
if (ar || !(i in from)) {
|
20
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
21
|
+
ar[i] = from[i];
|
22
|
+
}
|
23
|
+
}
|
24
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
25
|
+
};
|
17
26
|
Object.defineProperty(exports, "__esModule", { value: true });
|
18
|
-
exports.
|
27
|
+
exports.useMountCallbacks = exports.useInstance = exports.ComponentInstance = exports.noOp = void 0;
|
19
28
|
var react_1 = require("react");
|
20
29
|
var state_1 = require("../base/state");
|
21
30
|
var logic_1 = require("./logic");
|
@@ -74,6 +83,56 @@ var ComponentInstance = /** @class */ (function (_super) {
|
|
74
83
|
}(logic_1.ComponentLogic));
|
75
84
|
exports.ComponentInstance = ComponentInstance;
|
76
85
|
;
|
86
|
+
/**
|
87
|
+
* To ensure successful type checking, the second parameter must be written with spread syntax.
|
88
|
+
* Likely because of the `exactOptionalPropertyTypes` config option turned on,
|
89
|
+
* and `UseInstance` using an empty tuple in its rest parameter type, attempting to simply
|
90
|
+
* retrieve the second argument directly causes an error when that argument is passed on to `useLogic`.
|
91
|
+
* But directly working with the rest array bypasses the problem. Also note that the issue persists even when
|
92
|
+
* the second param is given `{}` as a default follow to account for the empty tuple case. TypeScript
|
93
|
+
* just wants us to use the rest parameter explicitly by force.
|
94
|
+
*/
|
95
|
+
var useInstance = function (Component) {
|
96
|
+
var _a;
|
97
|
+
var args = [];
|
98
|
+
for (var _i = 1; _i < arguments.length; _i++) {
|
99
|
+
args[_i - 1] = arguments[_i];
|
100
|
+
}
|
101
|
+
// useHooks.
|
102
|
+
var instance = logic_1.useLogic.apply(void 0, __spreadArray([Component], args, false)); // Must spread rest parameter, rather than passing a single `props` argument directly.
|
103
|
+
/**
|
104
|
+
* Argument of type '
|
105
|
+
* [
|
106
|
+
(valueof<TClass["props"]> extends never
|
107
|
+
? [] | [CEmptyObject]
|
108
|
+
: [ TClass["props"] ]
|
109
|
+
)[0]
|
110
|
+
]
|
111
|
+
' is not assignable to parameter of type '
|
112
|
+
valueof<TClass["props"]> extends never
|
113
|
+
? [] | [CEmptyObject] // | [undefined]
|
114
|
+
: [ TClass["props"] ]
|
115
|
+
'
|
116
|
+
*/
|
117
|
+
// beforeMount, onMount, cleanUp.
|
118
|
+
// eslint-disable-next-line no-use-before-define
|
119
|
+
(0, exports.useMountCallbacks)(instance);
|
120
|
+
// beforeRender.
|
121
|
+
(_a = instance.beforeRender) === null || _a === void 0 ? void 0 : _a.call(instance);
|
122
|
+
// onRender.
|
123
|
+
(0, react_1.useEffect)(function () {
|
124
|
+
var _a;
|
125
|
+
var cleanupAfterRerender = (_a = instance.onRender) === null || _a === void 0 ? void 0 : _a.call(instance);
|
126
|
+
return function () {
|
127
|
+
if (typeof cleanupAfterRerender === 'function')
|
128
|
+
cleanupAfterRerender();
|
129
|
+
else
|
130
|
+
cleanupAfterRerender === null || cleanupAfterRerender === void 0 ? void 0 : cleanupAfterRerender.then(function (cleanUp) { return cleanUp === null || cleanUp === void 0 ? void 0 : cleanUp(); });
|
131
|
+
};
|
132
|
+
});
|
133
|
+
return instance;
|
134
|
+
};
|
135
|
+
exports.useInstance = useInstance;
|
77
136
|
var useMountCallbacks = function (instance) {
|
78
137
|
var _a;
|
79
138
|
var mounted = (0, state_1.useMountState)();
|
@@ -99,25 +158,3 @@ var useMountCallbacks = function (instance) {
|
|
99
158
|
}, []);
|
100
159
|
};
|
101
160
|
exports.useMountCallbacks = useMountCallbacks;
|
102
|
-
var useInstance = function (Component, props) {
|
103
|
-
var _a;
|
104
|
-
// useHooks.
|
105
|
-
var instance = (0, logic_1.useLogic)(Component, props);
|
106
|
-
// beforeMount, onMount, cleanUp.
|
107
|
-
(0, exports.useMountCallbacks)(instance);
|
108
|
-
// beforeRender.
|
109
|
-
(_a = instance.beforeRender) === null || _a === void 0 ? void 0 : _a.call(instance);
|
110
|
-
// onRender.
|
111
|
-
(0, react_1.useEffect)(function () {
|
112
|
-
var _a;
|
113
|
-
var cleanupAfterRerender = (_a = instance.onRender) === null || _a === void 0 ? void 0 : _a.call(instance);
|
114
|
-
return function () {
|
115
|
-
if (typeof cleanupAfterRerender === 'function')
|
116
|
-
cleanupAfterRerender();
|
117
|
-
else
|
118
|
-
cleanupAfterRerender === null || cleanupAfterRerender === void 0 ? void 0 : cleanupAfterRerender.then(function (cleanUp) { return cleanUp === null || cleanUp === void 0 ? void 0 : cleanUp(); });
|
119
|
-
};
|
120
|
-
});
|
121
|
-
return instance;
|
122
|
-
};
|
123
|
-
exports.useInstance = useInstance;
|
package/build/classy/logic.d.ts
CHANGED
@@ -1,13 +1,22 @@
|
|
1
|
-
import type { TCleanState } from '../base/state';
|
2
|
-
export declare class ComponentLogic<TState extends object, TProps extends object, THooks extends object> {
|
1
|
+
import type { TCleanState, TState } from '../base/state';
|
2
|
+
export declare class ComponentLogic<TState extends object = EmptyObject, TProps extends object = EmptyObject, THooks extends object = EmptyObject> {
|
3
3
|
state: TCleanState<TState>;
|
4
4
|
props: TProps;
|
5
5
|
hooks: THooks;
|
6
|
+
static getInitialState: IComponentClass['getInitialState'];
|
6
7
|
useHooks?: () => THooks;
|
7
8
|
}
|
8
|
-
|
9
|
-
|
9
|
+
type CnstPrm = ConstructorParameters<typeof ComponentLogic>;
|
10
|
+
export interface IComponentClass<Instance extends ComponentLogic = ComponentLogic> {
|
11
|
+
new (...params: CnstPrm): Instance;
|
12
|
+
getInitialState: (props?: Instance['props']) => TState<Instance['state']>;
|
10
13
|
}
|
11
|
-
type
|
14
|
+
export type ComponentClassStatics<Instance extends ComponentLogic<object, object, object>> = {
|
15
|
+
getInitialState: (props?: Instance['props']) => TState<Instance['state']>;
|
16
|
+
};
|
17
|
+
export type TComponentClass<Instance extends ComponentLogic<object, object, object>, Statics extends ComponentClassStatics<Instance> = ComponentClassStatics<Instance>, Params extends CnstPrm = CnstPrm> = Statics & Constructor<Instance, Params>;
|
18
|
+
export interface IEmpty extends EmptyObject {
|
19
|
+
}
|
20
|
+
type UseLogic = <CLogic extends ComponentLogic<object, object, object>>(Methods: TComponentClass<CLogic>, ...props: valueof<CLogic['props']> extends never ? ([] | [EmptyObject] | [CLogic['props']]) : [CLogic['props']]) => CLogic;
|
12
21
|
export declare const useLogic: UseLogic;
|
13
22
|
export {};
|
package/build/classy/logic.js
CHANGED
@@ -1,4 +1,20 @@
|
|
1
1
|
"use strict";
|
2
|
+
var __extends = (this && this.__extends) || (function () {
|
3
|
+
var extendStatics = function (d, b) {
|
4
|
+
extendStatics = Object.setPrototypeOf ||
|
5
|
+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
6
|
+
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
7
|
+
return extendStatics(d, b);
|
8
|
+
};
|
9
|
+
return function (d, b) {
|
10
|
+
if (typeof b !== "function" && b !== null)
|
11
|
+
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
12
|
+
extendStatics(d, b);
|
13
|
+
function __() { this.constructor = d; }
|
14
|
+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
15
|
+
};
|
16
|
+
})();
|
17
|
+
var _a;
|
2
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
19
|
exports.useLogic = exports.ComponentLogic = void 0;
|
4
20
|
var react_1 = require("react");
|
@@ -10,22 +26,42 @@ var ComponentLogic = /** @class */ (function () {
|
|
10
26
|
}());
|
11
27
|
exports.ComponentLogic = ComponentLogic;
|
12
28
|
;
|
29
|
+
testing: {
|
30
|
+
var A = (_a = /** @class */ (function (_super) {
|
31
|
+
__extends(C, _super);
|
32
|
+
function C() {
|
33
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
34
|
+
}
|
35
|
+
return C;
|
36
|
+
}(ComponentLogic)),
|
37
|
+
_a.getInitialState = function () { return ({}); },
|
38
|
+
_a);
|
39
|
+
A.getInitialState();
|
40
|
+
}
|
41
|
+
;
|
13
42
|
var useLogic = function (Methods, props) {
|
14
|
-
var
|
43
|
+
var _b;
|
15
44
|
if (props === void 0) { props = {}; }
|
16
45
|
var state = (0, state_1.useCleanState)(Methods.getInitialState, props);
|
17
|
-
|
18
|
-
// completely ignoring the type specified for Methods in the function's type definition.
|
19
|
-
// `new Methods()` should return whatever the InstanceType of TClass is, as that is the type explicitly specified for Methods.
|
20
|
-
// Ignoring the specified type to gin up something else and then complain about it is quite weird.
|
21
|
-
// Regardless, even when `extends ComponentLogicConstructor<TState, TProps, THooks>` is specified using generics instead of a set type,
|
22
|
-
// the issue persists. Which is absurd since this should ensure that InstanceType<Class> should exactly match ComponentLogic<TState, TProps, THooks>
|
23
|
-
var methods = (0, react_1.useMemo)(function () {
|
46
|
+
var methods = (0, react_1.useRef)((0, react_1.useMemo)(function () {
|
24
47
|
return new Methods();
|
25
|
-
}, []);
|
48
|
+
}, [])).current;
|
26
49
|
methods.state = state;
|
27
50
|
methods.props = props;
|
28
|
-
methods.hooks = ((
|
51
|
+
methods.hooks = ((_b = methods.useHooks) === null || _b === void 0 ? void 0 : _b.call(methods)) || {};
|
29
52
|
return methods;
|
30
53
|
};
|
31
54
|
exports.useLogic = useLogic;
|
55
|
+
testing: {
|
56
|
+
var a = { b: '' };
|
57
|
+
var MyComponentLogic = /** @class */ (function (_super) {
|
58
|
+
__extends(MyComponentLogic, _super);
|
59
|
+
function MyComponentLogic() {
|
60
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
61
|
+
}
|
62
|
+
MyComponentLogic.getInitialState = function () { return ({}); };
|
63
|
+
return MyComponentLogic;
|
64
|
+
}(ComponentLogic));
|
65
|
+
;
|
66
|
+
(0, exports.useLogic)(MyComponentLogic);
|
67
|
+
}
|
package/build/globals.d.ts
CHANGED
@@ -1,56 +1,67 @@
|
|
1
|
-
|
2
|
-
type Optional<
|
3
|
-
BaseType,
|
4
|
-
AllowNull extends boolean = true
|
5
|
-
> = (
|
6
|
-
AllowNull extends true
|
7
|
-
? BaseType | undefined | null
|
8
|
-
: BaseType | undefined
|
9
|
-
)
|
10
|
-
|
11
|
-
type Awaitable<Type> = Type | Promise<Type>;
|
12
|
-
|
13
|
-
type Constructor<
|
14
|
-
TInstance extends any = any,
|
15
|
-
TParams extends any[] = never[]
|
16
|
-
> = new (...args: TParams) => TInstance
|
17
|
-
|
18
|
-
|
19
1
|
/**
|
2
|
+
* @file
|
3
|
+
* This file is an "Ambient declarations file". The types defined here are available globally.
|
4
|
+
* More info here: https://stackoverflow.com/a/73389225/985454
|
5
|
+
*
|
6
|
+
* Don't use `import` and `export` in this file directly! It breaks ambience.
|
7
|
+
* To import external types in an ambient declarations file (this file) use the following:
|
8
|
+
*
|
20
9
|
* @example
|
21
|
-
*
|
22
|
-
*
|
23
|
-
*
|
10
|
+
* declare type React = typeof import('react');
|
11
|
+
*
|
12
|
+
* To contribute ambient declarations from any file, even non-ambient ones, use this:
|
13
|
+
*
|
14
|
+
* @example
|
15
|
+
* declare global {
|
16
|
+
* interface Window {
|
17
|
+
* ethereum: any
|
18
|
+
* }
|
24
19
|
* }
|
25
|
-
|
26
|
-
*/
|
27
|
-
declare
|
28
|
-
|
29
|
-
|
30
|
-
> = (...
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
}
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
}
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
20
|
+
**/
|
21
|
+
/** */
|
22
|
+
declare global {
|
23
|
+
type Optional<BaseType, AllowNull extends boolean = true> = (AllowNull extends true ? BaseType | undefined | null : BaseType | undefined);
|
24
|
+
type Awaitable<Type> = Type | Promise<Type>;
|
25
|
+
type Constructor<TInstance extends any = any, TParams extends any[] = never[]> = new (...args: TParams) => TInstance;
|
26
|
+
/**
|
27
|
+
* @example
|
28
|
+
* ```js
|
29
|
+
* const getNumber: AsyncFunction<number> = async () => {
|
30
|
+
* return 5;
|
31
|
+
* }
|
32
|
+
* ```
|
33
|
+
*/
|
34
|
+
type AsyncFunction<TReturnValue extends any = void, Params extends any[] = never[]> = (...params: Params) => Promise<TReturnValue>;
|
35
|
+
/**
|
36
|
+
* A function that takes no arguments and returns nothing.
|
37
|
+
* Pass a type argument to set whether `async` and/or `sync` functions are allowed.
|
38
|
+
*/
|
39
|
+
interface IVoidFunction<AsyncType extends 'async' | 'sync' | 'both' = 'both'> {
|
40
|
+
(): AsyncType extends 'async' ? Promise<void> : AsyncType extends 'sync' ? void : Promise<void> | void;
|
41
|
+
}
|
42
|
+
type AnyFunction = (...args: any) => any;
|
43
|
+
type FunctionType = AnyFunction;
|
44
|
+
type TFunction = AnyFunction;
|
45
|
+
interface Window {
|
46
|
+
}
|
47
|
+
namespace JSX {
|
48
|
+
interface IntrinsicElements {
|
49
|
+
}
|
50
|
+
}
|
51
|
+
namespace NodeJS {
|
52
|
+
interface ProcessEnv {
|
53
|
+
}
|
54
|
+
}
|
55
|
+
type __FromPrivateHelpers = typeof import('./globals.private');
|
56
|
+
type TEmptyObject1 = {
|
57
|
+
''?: never;
|
58
|
+
};
|
59
|
+
type TEmptyObject2 = Record<symbol, never>;
|
60
|
+
type EmptyObject = __FromPrivateHelpers['EmptyObject'];
|
61
|
+
type EmptyObject2 = __FromPrivateHelpers['EmptyObject2'];
|
62
|
+
type EmptyObject3 = __FromPrivateHelpers['EmptyObject3'];
|
63
|
+
type valueof<TObject> = TObject[keyof TObject];
|
64
|
+
interface T extends __FromPrivateHelpers {
|
65
|
+
}
|
56
66
|
}
|
67
|
+
export {};
|
package/build/globals.js
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
"use strict";
|
2
|
+
/**
|
3
|
+
* @file
|
4
|
+
* This file is an "Ambient declarations file". The types defined here are available globally.
|
5
|
+
* More info here: https://stackoverflow.com/a/73389225/985454
|
6
|
+
*
|
7
|
+
* Don't use `import` and `export` in this file directly! It breaks ambience.
|
8
|
+
* To import external types in an ambient declarations file (this file) use the following:
|
9
|
+
*
|
10
|
+
* @example
|
11
|
+
* declare type React = typeof import('react');
|
12
|
+
*
|
13
|
+
* To contribute ambient declarations from any file, even non-ambient ones, use this:
|
14
|
+
*
|
15
|
+
* @example
|
16
|
+
* declare global {
|
17
|
+
* interface Window {
|
18
|
+
* ethereum: any
|
19
|
+
* }
|
20
|
+
* }
|
21
|
+
**/
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
@@ -0,0 +1,48 @@
|
|
1
|
+
/**
|
2
|
+
* @file
|
3
|
+
* This file is created specifically to augment the declarations in
|
4
|
+
* [globals.d.ts]({@link ./globals.d.ts}).
|
5
|
+
*
|
6
|
+
* **You should not import this file directly.**
|
7
|
+
*/
|
8
|
+
/** */
|
9
|
+
declare const UniqueSecretSymbolKey: unique symbol;
|
10
|
+
declare class CEmptyObject {
|
11
|
+
[key: keyof any]: never;
|
12
|
+
}
|
13
|
+
declare class CEmptyObject2 {
|
14
|
+
[UniqueSecretSymbolKey]?: never;
|
15
|
+
}
|
16
|
+
declare class CEmptyObject3 {
|
17
|
+
/**
|
18
|
+
* It appears keys of the base `symbol` type are excluded from
|
19
|
+
* excess property checks. This is likely a bug in TypeScript.
|
20
|
+
* Even the "has no properties in common" error disappears if the
|
21
|
+
* value being placed into a variable has a key typed as `symbol`.
|
22
|
+
* This only applies to the base `symbol` type. Specifc `'unique symbol'`
|
23
|
+
* types are unaffected.
|
24
|
+
*
|
25
|
+
* @example
|
26
|
+
* // Consider the following object:
|
27
|
+
* const myUniqueSymbol = Symbol('lkjhgfc');
|
28
|
+
* let myObj = { [myUniqueSymbol]?: 'a string value' };
|
29
|
+
*
|
30
|
+
* // We can attempt to reassign `myObj` with the expectation that TS will
|
31
|
+
* // warn if any key other than `myUniqueSymbol` is used in the new object.
|
32
|
+
* // But this breaks in one specific scenario.
|
33
|
+
*
|
34
|
+
* // No excess property check when this is used as a key.
|
35
|
+
* // Error "no properties in common" also suppressed when this is used as a key.
|
36
|
+
* const differentBasicSymbol = Symbol('qwertiop[') as symbol;
|
37
|
+
* myObj = { [differentBasicSymbol]: 5 };
|
38
|
+
*
|
39
|
+
* // Errors emitted as expected when this is used as a key.
|
40
|
+
* const differentUniqueSymbol = Symbol('zxcvbnm');
|
41
|
+
* myObj = { [differentUniqueSymbol]: 5 };
|
42
|
+
*/
|
43
|
+
[key: symbol]: never;
|
44
|
+
}
|
45
|
+
export declare const EmptyObject: CEmptyObject;
|
46
|
+
export declare const EmptyObject2: CEmptyObject2;
|
47
|
+
export declare const EmptyObject3: CEmptyObject3;
|
48
|
+
export {};
|
@@ -0,0 +1,40 @@
|
|
1
|
+
"use strict";
|
2
|
+
/**
|
3
|
+
* @file
|
4
|
+
* This file is created specifically to augment the declarations in
|
5
|
+
* [globals.d.ts]({@link ./globals.d.ts}).
|
6
|
+
*
|
7
|
+
* **You should not import this file directly.**
|
8
|
+
*/
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
10
|
+
exports.EmptyObject3 = exports.EmptyObject2 = exports.EmptyObject = void 0;
|
11
|
+
/** */
|
12
|
+
var UniqueSecretSymbolKey = Symbol('asdfghjkliuytrewqaxcvb,nb');
|
13
|
+
var CEmptyObject = /** @class */ (function () {
|
14
|
+
function CEmptyObject() {
|
15
|
+
}
|
16
|
+
return CEmptyObject;
|
17
|
+
}());
|
18
|
+
var CEmptyObject2 = /** @class */ (function () {
|
19
|
+
function CEmptyObject2() {
|
20
|
+
}
|
21
|
+
return CEmptyObject2;
|
22
|
+
}());
|
23
|
+
var CEmptyObject3 = /** @class */ (function () {
|
24
|
+
function CEmptyObject3() {
|
25
|
+
}
|
26
|
+
return CEmptyObject3;
|
27
|
+
}());
|
28
|
+
exports.EmptyObject = new CEmptyObject();
|
29
|
+
exports.EmptyObject2 = new CEmptyObject2();
|
30
|
+
exports.EmptyObject3 = new CEmptyObject3();
|
31
|
+
testing: {
|
32
|
+
var mySymbol = Symbol('asdfgh');
|
33
|
+
var tt = {
|
34
|
+
// [mySymbol]: '' as never,
|
35
|
+
// [UniqueSecretSymbolKey]: '',
|
36
|
+
// '': '',
|
37
|
+
};
|
38
|
+
var TT = new CEmptyObject();
|
39
|
+
TT = tt;
|
40
|
+
}
|
package/build/tsconfig.json
CHANGED
@@ -28,10 +28,13 @@
|
|
28
28
|
"resolveJsonModule": true,
|
29
29
|
"isolatedModules": true,
|
30
30
|
"jsx": "react-jsx",
|
31
|
-
"strictNullChecks": true
|
31
|
+
"strictNullChecks": true,
|
32
|
+
"noImplicitAny": true,
|
33
|
+
"noUncheckedIndexedAccess": true,
|
34
|
+
"strictBindCallApply": true,
|
35
|
+
// "exactOptionalPropertyTypes": true
|
32
36
|
},
|
33
37
|
"include": [
|
34
|
-
"next-env.d.ts",
|
35
38
|
"**/*.ts",
|
36
39
|
"**/*.tsx"
|
37
40
|
],
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@cleanweb/react",
|
3
|
-
"version": "1.0
|
3
|
+
"version": "1.1.1-beta.0",
|
4
4
|
"description": "A suite of helpers for writing cleaner React function components.",
|
5
5
|
"engines": {
|
6
6
|
"node": ">=18"
|
@@ -34,8 +34,17 @@
|
|
34
34
|
"_": "",
|
35
35
|
"prepublishOnly": "npm run build",
|
36
36
|
"publish:patch": "npm version patch && npm publish",
|
37
|
+
"publish:minor": "npm version minor && npm publish",
|
38
|
+
"publish:major": "npm version major && npm publish",
|
39
|
+
"__": "/// Increment beta number for the current patch version. ///",
|
40
|
+
"publish:beta:current": "npm version prerelease --preid beta && npm publish --tag beta",
|
41
|
+
"___": "/// Create a beta.0 for a new patch/minor/major version ///",
|
42
|
+
"publish:beta:new-patch": "npm version prepatch --preid beta && npm publish --tag beta",
|
43
|
+
"publish:beta:new-minor": "npm version preminor --preid beta && npm publish --tag beta",
|
44
|
+
"publish:beta:new-major": "npm version premajor --preid beta && npm publish --tag beta",
|
45
|
+
"____": "",
|
37
46
|
"//postpublish": "cd ./mirror-pkg && npm publish && cd ..",
|
38
|
-
"
|
47
|
+
"______": "",
|
39
48
|
"test": "echo \"No tests ATM\""
|
40
49
|
},
|
41
50
|
"keywords": [
|
@@ -55,9 +64,16 @@
|
|
55
64
|
},
|
56
65
|
"license": "MIT",
|
57
66
|
"devDependencies": {
|
67
|
+
"@babel/eslint-parser": "^7.25.9",
|
68
|
+
"@babel/preset-typescript": "^7.26.0",
|
58
69
|
"@types/node": "20.14.10",
|
59
70
|
"@types/react": "^16",
|
71
|
+
"babel-preset-react-app": "^10.0.1",
|
60
72
|
"copyfiles": "^2.4.1",
|
73
|
+
"eslint": "^9.15.0",
|
74
|
+
"eslint-plugin-jsdoc": "^50.5.0",
|
75
|
+
"eslint-plugin-react": "^7.37.2",
|
76
|
+
"globals": "^15.12.0",
|
61
77
|
"rimraf": "^6.0.1",
|
62
78
|
"tsc-alias": "1.8.10",
|
63
79
|
"typescript": "^5.6.2"
|