@cleanweb/oore 2.0.0-alpha.15 → 2.0.0-alpha.18
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/_cjs/base/index.d.ts +3 -0
- package/build/_cjs/base/index.js +19 -0
- package/build/_cjs/base/merged-state.d.ts +20 -0
- package/build/_cjs/base/merged-state.js +61 -0
- package/build/_cjs/base/methods.d.ts +58 -0
- package/build/_cjs/base/methods.js +95 -0
- package/build/_cjs/base/state/class-types.d.ts +20 -0
- package/build/_cjs/base/state/class-types.js +2 -0
- package/build/_cjs/base/state/class.d.ts +69 -0
- package/build/_cjs/base/state/class.js +129 -0
- package/build/_cjs/base/state/hook-types.d.ts +32 -0
- package/build/_cjs/base/state/hook-types.js +2 -0
- package/build/_cjs/base/state/hooks.d.ts +12 -0
- package/build/_cjs/base/state/hooks.js +41 -0
- package/build/_cjs/base/state/index.d.ts +9 -0
- package/build/_cjs/base/state/index.js +35 -0
- package/build/_cjs/classy/class/index.d.ts +128 -0
- package/build/_cjs/classy/class/index.js +174 -0
- package/build/_cjs/classy/class/types/extractor.d.ts +5 -0
- package/build/_cjs/classy/class/types/extractor.js +2 -0
- package/build/_cjs/classy/class/utils/function-name.d.ts +2 -0
- package/build/_cjs/classy/class/utils/function-name.js +17 -0
- package/build/_cjs/classy/index.d.ts +3 -0
- package/build/_cjs/classy/index.js +19 -0
- package/build/_cjs/classy/instance/index.d.ts +144 -0
- package/build/_cjs/classy/instance/index.js +177 -0
- package/build/_cjs/classy/instance/mount-callbacks.d.ts +5 -0
- package/build/_cjs/classy/instance/mount-callbacks.js +30 -0
- package/build/_cjs/classy/instance/types/hook.d.ts +13 -0
- package/build/_cjs/classy/instance/types/hook.js +2 -0
- package/build/_cjs/classy/logic/index.d.ts +116 -0
- package/build/_cjs/classy/logic/index.js +123 -0
- package/build/_cjs/classy/logic/types/hook.d.ts +16 -0
- package/build/_cjs/classy/logic/types/hook.js +2 -0
- package/build/_cjs/docs-src/api/base-classes.d.ts +3 -0
- package/build/_cjs/docs-src/api/base-classes.js +9 -0
- package/build/_cjs/docs-src/api/index.d.ts +13 -0
- package/build/_cjs/docs-src/api/index.js +44 -0
- package/build/_cjs/docs-src/api/references.d.ts +5 -0
- package/build/_cjs/docs-src/api/references.js +31 -0
- package/build/_cjs/helpers/errors.d.ts +10 -0
- package/build/_cjs/helpers/errors.js +21 -0
- package/build/_cjs/helpers/index.d.ts +13 -0
- package/build/_cjs/helpers/index.js +31 -0
- package/build/_cjs/helpers/mount-state.d.ts +5 -0
- package/build/_cjs/helpers/mount-state.js +25 -0
- package/build/_cjs/helpers/rerender.d.ts +24 -0
- package/build/_cjs/helpers/rerender.js +42 -0
- package/build/_cjs/helpers/type-guards.d.ts +1 -0
- package/build/_cjs/helpers/type-guards.js +8 -0
- package/build/_cjs/helpers/use-component/index.d.ts +6 -0
- package/build/_cjs/helpers/use-component/index.js +17 -0
- package/build/_cjs/helpers/use-component/types.d.ts +22 -0
- package/build/_cjs/helpers/use-component/types.js +2 -0
- package/build/_cjs/index.d.ts +3 -0
- package/build/_cjs/index.js +19 -0
- package/build/_cjs/slots/hook.d.ts +20 -0
- package/build/_cjs/slots/hook.js +143 -0
- package/build/_cjs/slots/index.d.ts +1 -0
- package/build/_cjs/slots/index.js +17 -0
- package/build/_cjs/slots/types.d.ts +131 -0
- package/build/_cjs/slots/types.js +2 -0
- package/build/base/merged-state.js +30 -53
- package/build/base/methods.d.ts +2 -3
- package/build/base/methods.js +18 -23
- package/build/base/state/class.js +45 -68
- package/build/base/state/hooks.js +6 -10
- package/build/classy/class/index.d.ts +15 -2
- package/build/classy/class/index.js +96 -83
- package/build/classy/class/utils/function-name.js +1 -1
- package/build/classy/instance/index.d.ts +1 -1
- package/build/classy/instance/index.js +57 -82
- package/build/classy/instance/mount-callbacks.js +8 -8
- package/build/classy/logic/index.js +21 -26
- package/build/globals.d.ts +130 -83
- package/build/helpers/errors.js +1 -1
- package/build/helpers/index.js +1 -1
- package/build/helpers/mount-state.js +6 -6
- package/build/helpers/rerender.js +12 -12
- package/build/helpers/type-guards.js +2 -2
- package/build/helpers/use-component/index.js +5 -5
- package/build/index.d.ts +0 -1
- package/build/slots/hook.js +28 -36
- package/build/tsconfig.json +5 -6
- package/package.json +31 -11
- package/build/globals.js +0 -4
|
@@ -1,22 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __assign = (this && this.__assign) || function () {
|
|
3
|
-
__assign = Object.assign || function(t) {
|
|
4
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
-
s = arguments[i];
|
|
6
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
-
t[p] = s[p];
|
|
8
|
-
}
|
|
9
|
-
return t;
|
|
10
|
-
};
|
|
11
|
-
return __assign.apply(this, arguments);
|
|
12
|
-
};
|
|
13
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
3
|
exports.CleanState = exports.CleanStateBase = void 0;
|
|
15
|
-
|
|
4
|
+
const react_1 = require("react");
|
|
16
5
|
/** @internal */
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
var _this = this;
|
|
6
|
+
class CleanStateBase {
|
|
7
|
+
constructor(initialState) {
|
|
20
8
|
this._values_ = {};
|
|
21
9
|
this._setters_ = {};
|
|
22
10
|
/**
|
|
@@ -72,10 +60,10 @@ var CleanStateBase = /** @class */ (function () {
|
|
|
72
60
|
* </>;
|
|
73
61
|
* };
|
|
74
62
|
*/
|
|
75
|
-
this.putMany =
|
|
76
|
-
Object.entries(newValues).forEach(
|
|
77
|
-
|
|
78
|
-
|
|
63
|
+
this.putMany = (newValues) => {
|
|
64
|
+
Object.entries(newValues).forEach((entry) => {
|
|
65
|
+
const [key, value] = entry;
|
|
66
|
+
this.put[key](value);
|
|
79
67
|
});
|
|
80
68
|
};
|
|
81
69
|
this.reservedKeys = Object.keys(this);
|
|
@@ -89,64 +77,53 @@ var CleanStateBase = /** @class */ (function () {
|
|
|
89
77
|
* and they will always be processed in a consistent order during rerenders.
|
|
90
78
|
*/
|
|
91
79
|
this.valueKeys = Object.keys(initialState);
|
|
92
|
-
this._initialValues_ =
|
|
93
|
-
this.valueKeys.forEach(
|
|
94
|
-
if (
|
|
95
|
-
throw new Error(
|
|
96
|
-
|
|
97
|
-
Object.defineProperty(
|
|
98
|
-
get
|
|
80
|
+
this._initialValues_ = Object.assign({}, initialState);
|
|
81
|
+
this.valueKeys.forEach((key) => {
|
|
82
|
+
if (this.reservedKeys.includes(key))
|
|
83
|
+
throw new Error(`The name "${key}" is reserved by CleanState and cannot be used to index state variables. Please use a different key.`);
|
|
84
|
+
const self = this;
|
|
85
|
+
Object.defineProperty(this, key, {
|
|
86
|
+
get() {
|
|
99
87
|
return self._values_[key];
|
|
100
88
|
},
|
|
101
|
-
set
|
|
89
|
+
set(value) {
|
|
102
90
|
self._setters_[key](value);
|
|
103
91
|
},
|
|
104
92
|
enumerable: true,
|
|
105
93
|
});
|
|
106
94
|
});
|
|
107
95
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
Object.defineProperty(CleanStateBase.prototype, "initialState", {
|
|
116
|
-
get: function () {
|
|
117
|
-
return __assign({}, this._initialValues_);
|
|
118
|
-
},
|
|
119
|
-
enumerable: false,
|
|
120
|
-
configurable: true
|
|
121
|
-
});
|
|
122
|
-
CleanStateBase.update = function update() {
|
|
123
|
-
var _this = this;
|
|
124
|
-
if (!(this instanceof exports.CleanState))
|
|
125
|
-
throw new Error('CleanState.update must be called with `this` value set to a CleanState instance. Did you forget to use `.call` or `.apply`? Example: CleanState.update.call(cleanState);');
|
|
126
|
-
/**
|
|
127
|
-
* Linters complain about the use of a React hook within a loop because:
|
|
128
|
-
* > By following this rule, you ensure that Hooks are called in the same order each time a component renders.
|
|
129
|
-
* > That’s what allows React to correctly preserve the state of Hooks between multiple useState and useEffect calls.
|
|
130
|
-
* To resolve this, we're calling `useState` via an alias `retrieveState`.
|
|
131
|
-
* Bypassing this rule is safe here because `useCleanState` is a special case,
|
|
132
|
-
* and it guarantees that the same useState calls will be made on every render in the exact same order.
|
|
133
|
-
* Therefore, it is safe to silence the linters, and required for this implementation to work smoothly.
|
|
134
|
-
*/
|
|
135
|
-
var retrieveState = react_1.useState;
|
|
136
|
-
this.valueKeys.forEach(function (key) {
|
|
137
|
-
var _a;
|
|
138
|
-
// @todo Make state updates accessible immediately. Use state.staged to access the scheduled updates.
|
|
139
|
-
var setter;
|
|
140
|
-
_a = retrieveState(_this.initialState[key]), _this._values_[key] = _a[0], setter = _a[1];
|
|
141
|
-
_this._setters_[key] = (function (valueOrCallback) {
|
|
142
|
-
// this._staged_[key] = value;
|
|
143
|
-
setter(valueOrCallback);
|
|
144
|
-
});
|
|
145
|
-
});
|
|
146
|
-
};
|
|
147
|
-
return CleanStateBase;
|
|
148
|
-
}());
|
|
96
|
+
get put() {
|
|
97
|
+
return Object.assign({}, this._setters_);
|
|
98
|
+
}
|
|
99
|
+
get initialState() {
|
|
100
|
+
return Object.assign({}, this._initialValues_);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
149
103
|
exports.CleanStateBase = CleanStateBase;
|
|
104
|
+
CleanStateBase.update = function update() {
|
|
105
|
+
if (!(this instanceof exports.CleanState))
|
|
106
|
+
throw new Error('CleanState.update must be called with `this` value set to a CleanState instance. Did you forget to use `.call` or `.apply`? Example: CleanState.update.call(cleanState);');
|
|
107
|
+
/**
|
|
108
|
+
* Linters complain about the use of a React hook within a loop because:
|
|
109
|
+
* > By following this rule, you ensure that Hooks are called in the same order each time a component renders.
|
|
110
|
+
* > That’s what allows React to correctly preserve the state of Hooks between multiple useState and useEffect calls.
|
|
111
|
+
* To resolve this, we're calling `useState` via an alias `retrieveState`.
|
|
112
|
+
* Bypassing this rule is safe here because `useCleanState` is a special case,
|
|
113
|
+
* and it guarantees that the same useState calls will be made on every render in the exact same order.
|
|
114
|
+
* Therefore, it is safe to silence the linters, and required for this implementation to work smoothly.
|
|
115
|
+
*/
|
|
116
|
+
const retrieveState = react_1.useState;
|
|
117
|
+
this.valueKeys.forEach((key) => {
|
|
118
|
+
// @todo Make state updates accessible immediately. Use state.staged to access the scheduled updates.
|
|
119
|
+
let setter;
|
|
120
|
+
[this._values_[key], setter] = retrieveState(this.initialState[key]);
|
|
121
|
+
this._setters_[key] = ((valueOrCallback) => {
|
|
122
|
+
// this._staged_[key] = value;
|
|
123
|
+
setter(valueOrCallback);
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
};
|
|
150
127
|
;
|
|
151
128
|
/** @internal */
|
|
152
129
|
exports.CleanState = (CleanStateBase);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.useCleanState = void 0;
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const class_1 = require("./class");
|
|
6
6
|
/**
|
|
7
7
|
* Creates a state object, which includes the provided values,
|
|
8
8
|
* as well as helper methods for updating those values and automatically
|
|
@@ -13,16 +13,12 @@ var class_1 = require("./class");
|
|
|
13
13
|
*
|
|
14
14
|
* Discussion: [When to `useCleanState`](https://cleanjsweb.github.io/neat-react/documents/Clean_State.html).
|
|
15
15
|
*/
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
props[_i - 1] = arguments[_i];
|
|
20
|
-
}
|
|
21
|
-
var initialState = typeof _initialState === 'function'
|
|
22
|
-
? (0, react_1.useMemo)(function () { return _initialState.apply(void 0, props); }, [])
|
|
16
|
+
const useCleanState = (_initialState, ...props) => {
|
|
17
|
+
const initialState = typeof _initialState === 'function'
|
|
18
|
+
? (0, react_1.useMemo)(() => _initialState(...props), [])
|
|
23
19
|
: _initialState;
|
|
24
20
|
;
|
|
25
|
-
|
|
21
|
+
const cleanState = (0, react_1.useRef)((0, react_1.useMemo)(() => {
|
|
26
22
|
return new class_1.CleanState(initialState);
|
|
27
23
|
}, [])).current;
|
|
28
24
|
class_1.CleanState.update.call(cleanState);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type React from 'react';
|
|
1
2
|
import type { TPropsBase } from '../logic';
|
|
2
3
|
import type { Extractor } from './types/extractor';
|
|
3
4
|
import { ComponentInstance } from '../instance';
|
|
@@ -65,6 +66,14 @@ export declare class ClassComponent<TProps extends TPropsBase = null> extends Co
|
|
|
65
66
|
* Note that the callback argument is currently not supported.
|
|
66
67
|
*/
|
|
67
68
|
readonly forceUpdate: VoidFunction;
|
|
69
|
+
/**
|
|
70
|
+
* A standard React function component that works like any
|
|
71
|
+
* other function component and can be rendered as JSX.
|
|
72
|
+
* \`<MyComponent.FC />\`
|
|
73
|
+
*/
|
|
74
|
+
static _FC<T extends typeof ClassComponent>(this: T, props: InstanceType<T>['props']): JSX.Element | null;
|
|
75
|
+
static _BoundFC: typeof this._FC | undefined;
|
|
76
|
+
static get FC(): typeof ClassComponent._FC;
|
|
68
77
|
/*************************************
|
|
69
78
|
* Function Component Extractor *
|
|
70
79
|
**************************************/
|
|
@@ -92,8 +101,12 @@ export declare class ClassComponent<TProps extends TPropsBase = null> extends Co
|
|
|
92
101
|
* export default Button.RC;
|
|
93
102
|
*/
|
|
94
103
|
static readonly extract: Extractor;
|
|
95
|
-
/**
|
|
96
|
-
|
|
104
|
+
/**
|
|
105
|
+
* A standard React function component that works like any
|
|
106
|
+
* other function component and can be rendered as JSX.
|
|
107
|
+
* \`<MyComponent.RC />\`
|
|
108
|
+
*/
|
|
109
|
+
static readonly RC: React.VoidFunctionComponent<object | EmptyObject>;
|
|
97
110
|
}
|
|
98
111
|
export { ClassComponent as Component };
|
|
99
112
|
/** /
|
|
@@ -1,25 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
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
|
-
})();
|
|
2
|
+
var _a;
|
|
17
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
4
|
exports.Component = exports.ClassComponent = void 0;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const instance_1 = require("../instance");
|
|
7
|
+
const function_name_1 = require("./utils/function-name");
|
|
8
|
+
const rerender_1 = require("../../helpers/rerender");
|
|
23
9
|
/**
|
|
24
10
|
* @summary
|
|
25
11
|
* A modern class component for React that is fully compatible with
|
|
@@ -37,10 +23,9 @@ var rerender_1 = require("../../helpers/rerender");
|
|
|
37
23
|
* making it easier to migrate older class components to the newer hooks-based system
|
|
38
24
|
* with little to no changes to their existing semantics/implementation.
|
|
39
25
|
*/
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
var _this = _super !== null && _super.apply(this, arguments) || this;
|
|
26
|
+
class ClassComponent extends instance_1.ComponentInstance {
|
|
27
|
+
constructor() {
|
|
28
|
+
super(...arguments);
|
|
44
29
|
/**
|
|
45
30
|
* Analogous to {@link React.Component.render}. A function that returns
|
|
46
31
|
* your component's JSX template.
|
|
@@ -77,71 +62,99 @@ var ClassComponent = /** @class */ (function (_super) {
|
|
|
77
62
|
* }
|
|
78
63
|
* ```
|
|
79
64
|
*/
|
|
80
|
-
|
|
81
|
-
return _this;
|
|
65
|
+
this.template = () => null;
|
|
82
66
|
}
|
|
83
|
-
var _a;
|
|
84
|
-
_a = ClassComponent;
|
|
85
|
-
/*************************************
|
|
86
|
-
* Function Component Extractor *
|
|
87
|
-
**************************************/
|
|
88
67
|
/**
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
* Each JSX reference to the returned component will render with
|
|
93
|
-
* a separate instance of your class.
|
|
94
|
-
*
|
|
95
|
-
* So you only need to call `YourClassComponent.extract()` (or `*.FC()`) once,
|
|
96
|
-
* then use the returned function component as many times as you need.
|
|
97
|
-
*
|
|
98
|
-
* It is recommended to store this returned value as a static member of
|
|
99
|
-
* your ClassComponent. While this value may be given any name, the name
|
|
100
|
-
* RC (for "React Component") is the recommended convention.
|
|
101
|
-
*
|
|
102
|
-
* @example <caption>Calling `extract` in your ClassComponent</caption>
|
|
103
|
-
* class Button extends ClassComponent {
|
|
104
|
-
* static readonly RC = this.extract(); // or this.FC();
|
|
105
|
-
* // Because of the static keyword, `this` here refers to the class itself, same as calling `Button.extract()`.
|
|
106
|
-
* }
|
|
107
|
-
*
|
|
108
|
-
* // Render with `<Button.RC />`, or export RC to use the component in other files.
|
|
109
|
-
* export default Button.RC;
|
|
68
|
+
* A standard React function component that works like any
|
|
69
|
+
* other function component and can be rendered as JSX.
|
|
70
|
+
* \`<MyComponent.FC />\`
|
|
110
71
|
*/
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
return template(templateContext);
|
|
132
|
-
};
|
|
133
|
-
/**************************************
|
|
134
|
-
* 👆🏼 End Function Component *
|
|
135
|
-
**************************************/
|
|
136
|
-
(0, function_name_1.setFunctionName)(Wrapper, "$".concat(Component.name, "$"));
|
|
137
|
-
return Object.assign(Wrapper, properties);
|
|
138
|
-
};
|
|
139
|
-
/** @see {@link ClassComponent.extract} */
|
|
140
|
-
ClassComponent.FC = _a.extract;
|
|
141
|
-
return ClassComponent;
|
|
142
|
-
}(instance_1.ComponentInstance));
|
|
72
|
+
static _FC(props) {
|
|
73
|
+
const instance = (0, instance_1.useInstance)(this, props);
|
|
74
|
+
const { template, templateContext } = instance;
|
|
75
|
+
let _forceUpdate;
|
|
76
|
+
// @ts-expect-error (Cannot assign to 'forceUpdate' because it is a read-only property.ts(2540))
|
|
77
|
+
instance.forceUpdate = (_forceUpdate = (0, rerender_1.useRerender)() // Moved this to separate line to allow TS errors. Use proxy local variable to regain some type checking for the assignment to `instance.forceUpdate`.
|
|
78
|
+
);
|
|
79
|
+
// Add calling component name to template function name in stack traces.
|
|
80
|
+
(0, react_1.useMemo)(() => {
|
|
81
|
+
(0, function_name_1.setFunctionName)(template, `${this.name}.template`);
|
|
82
|
+
}, [template]);
|
|
83
|
+
return template(templateContext);
|
|
84
|
+
}
|
|
85
|
+
;
|
|
86
|
+
static get FC() {
|
|
87
|
+
if (this._BoundFC)
|
|
88
|
+
return this._BoundFC;
|
|
89
|
+
return this._BoundFC = this._FC.bind(this);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
143
92
|
exports.ClassComponent = ClassComponent;
|
|
144
93
|
exports.Component = ClassComponent;
|
|
94
|
+
_a = ClassComponent;
|
|
95
|
+
(() => {
|
|
96
|
+
(0, function_name_1.setFunctionName)(_a._FC, `$${_a.name}$`);
|
|
97
|
+
})();
|
|
98
|
+
/*************************************
|
|
99
|
+
* Function Component Extractor *
|
|
100
|
+
**************************************/
|
|
101
|
+
/**
|
|
102
|
+
* Extract a Function Component (FC) which can be used to render
|
|
103
|
+
* your ClassComponent just like any other React component.
|
|
104
|
+
*
|
|
105
|
+
* Each JSX reference to the returned component will render with
|
|
106
|
+
* a separate instance of your class.
|
|
107
|
+
*
|
|
108
|
+
* So you only need to call `YourClassComponent.extract()` (or `*.FC()`) once,
|
|
109
|
+
* then use the returned function component as many times as you need.
|
|
110
|
+
*
|
|
111
|
+
* It is recommended to store this returned value as a static member of
|
|
112
|
+
* your ClassComponent. While this value may be given any name, the name
|
|
113
|
+
* RC (for "React Component") is the recommended convention.
|
|
114
|
+
*
|
|
115
|
+
* @example <caption>Calling `extract` in your ClassComponent</caption>
|
|
116
|
+
* class Button extends ClassComponent {
|
|
117
|
+
* static readonly RC = this.extract(); // or this.FC();
|
|
118
|
+
* // Because of the static keyword, `this` here refers to the class itself, same as calling `Button.extract()`.
|
|
119
|
+
* }
|
|
120
|
+
*
|
|
121
|
+
* // Render with `<Button.RC />`, or export RC to use the component in other files.
|
|
122
|
+
* export default Button.RC;
|
|
123
|
+
*/
|
|
124
|
+
ClassComponent.extract = function FC(_Component, properties) {
|
|
125
|
+
const Component = _Component !== null && _Component !== void 0 ? _Component : this;
|
|
126
|
+
const isClassComponentType = Component.prototype instanceof _a;
|
|
127
|
+
if (!isClassComponentType)
|
|
128
|
+
throw new Error('Attempted to initialize ClassComponent with invalid Class type. Either pass, as an argument to FC(), a class that extends ClassComponent (e.g `export FC(MyComponent);`), or ensure FC() is called as a method on a ClassComponent constructor type (e.g `export MyComponent.FC()`).');
|
|
129
|
+
/*************************************
|
|
130
|
+
* Begin Function Component *
|
|
131
|
+
**************************************/
|
|
132
|
+
/** A class-based, React function component created with `@cleanweb/oore`. {@link ClassComponent} */
|
|
133
|
+
const Wrapper = (props) => {
|
|
134
|
+
const instance = (0, instance_1.useInstance)(Component, props);
|
|
135
|
+
const { template, templateContext } = instance;
|
|
136
|
+
let _forceUpdate;
|
|
137
|
+
// @ts-expect-error (Cannot assign to 'forceUpdate' because it is a read-only property.ts(2540))
|
|
138
|
+
instance.forceUpdate = (_forceUpdate = (0, rerender_1.useRerender)() // Moved this to separate line to allow TS errors. Use proxy local variable to regain some type checking for the assignment to `instance.forceUpdate`.
|
|
139
|
+
);
|
|
140
|
+
// Add calling component name to template function name in stack traces.
|
|
141
|
+
(0, react_1.useMemo)(() => {
|
|
142
|
+
(0, function_name_1.setFunctionName)(template, `${Component.name}.template`);
|
|
143
|
+
}, [template]);
|
|
144
|
+
return template(templateContext);
|
|
145
|
+
};
|
|
146
|
+
/**************************************
|
|
147
|
+
* 👆🏼 End Function Component *
|
|
148
|
+
**************************************/
|
|
149
|
+
(0, function_name_1.setFunctionName)(Wrapper, `$${Component.name}$`);
|
|
150
|
+
return Object.assign(Wrapper, properties);
|
|
151
|
+
};
|
|
152
|
+
/**
|
|
153
|
+
* A standard React function component that works like any
|
|
154
|
+
* other function component and can be rendered as JSX.
|
|
155
|
+
* \`<MyComponent.RC />\`
|
|
156
|
+
*/
|
|
157
|
+
ClassComponent.RC = _a.extract();
|
|
145
158
|
/** /
|
|
146
159
|
testing: {
|
|
147
160
|
const a: object = {b: ''};
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.setFunctionName = void 0;
|
|
4
4
|
/** Provide more useful stack traces for otherwise non-specific function names. */
|
|
5
|
-
|
|
5
|
+
const setFunctionName = (func, newName) => {
|
|
6
6
|
try {
|
|
7
7
|
// Must use try block, as `name` is not configurable on older browsers, and may yield a TypeError.
|
|
8
8
|
Object.defineProperty(func, 'name', {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { UseInstance } from './types/hook';
|
|
2
2
|
import type { TPropsBase } from '../../classy/logic';
|
|
3
3
|
import { ComponentLogic } from '../../classy/logic';
|
|
4
|
-
type AsyncAllowedEffectCallback = () => Awaitable<IVoidFunction>;
|
|
4
|
+
type AsyncAllowedEffectCallback = () => Awaitable<IVoidFunction | void>;
|
|
5
5
|
/**
|
|
6
6
|
* A superset of {@link ComponentLogic} that adds support for lifecycle methods.
|
|
7
7
|
* This provides a declarative API for working with your React function component's lifecycle,
|
|
@@ -1,25 +1,10 @@
|
|
|
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
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
3
|
exports.useInstance = exports.ComponentInstance = void 0;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const logic_1 = require("../../classy/logic");
|
|
6
|
+
const mount_callbacks_1 = require("./mount-callbacks");
|
|
7
|
+
const helpers_1 = require("../../helpers");
|
|
23
8
|
/**
|
|
24
9
|
* A superset of {@link ComponentLogic} that adds support for lifecycle methods.
|
|
25
10
|
* This provides a declarative API for working with your React function component's lifecycle,
|
|
@@ -27,10 +12,9 @@ var helpers_1 = require("../../helpers");
|
|
|
27
12
|
*
|
|
28
13
|
* @see https://github.com/cleanjsweb/neat-react#lifecycle-useinstance
|
|
29
14
|
*/
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
var _this = _super !== null && _super.apply(this, arguments) || this;
|
|
15
|
+
class ComponentInstance extends logic_1.ComponentLogic {
|
|
16
|
+
constructor() {
|
|
17
|
+
super(...arguments);
|
|
34
18
|
/**
|
|
35
19
|
* Runs only _before_ the first render,
|
|
36
20
|
* i.e before the component instance is mounted.
|
|
@@ -41,7 +25,7 @@ var ComponentInstance = /** @class */ (function (_super) {
|
|
|
41
25
|
* PS: You can conditionally update state from here, but with certain caveats.
|
|
42
26
|
* {@link https://react.dev/reference/react/useState#storing-information-from-previous-renders | See the React docs for details}.
|
|
43
27
|
*/
|
|
44
|
-
|
|
28
|
+
this.beforeMount = () => { };
|
|
45
29
|
/**
|
|
46
30
|
* Runs only **_after_** the first render, i.e after the component instance is mounted.
|
|
47
31
|
* It is ignored on subsequent rerenders.
|
|
@@ -53,7 +37,7 @@ var ComponentInstance = /** @class */ (function (_super) {
|
|
|
53
37
|
*
|
|
54
38
|
* Uses `useEffect()` under the hood.
|
|
55
39
|
*/
|
|
56
|
-
|
|
40
|
+
this.onMount = () => helpers_1.noOp;
|
|
57
41
|
/**
|
|
58
42
|
* Runs _before_ every render cycle, including the first.
|
|
59
43
|
* Useful for logic that is involved in determining what to render.
|
|
@@ -69,7 +53,7 @@ var ComponentInstance = /** @class */ (function (_super) {
|
|
|
69
53
|
* PS: You can conditionally update state from here, but with certain caveats.
|
|
70
54
|
* {@link https://react.dev/reference/react/useState#storing-information-from-previous-renders | See the React docs for details}.
|
|
71
55
|
*/
|
|
72
|
-
|
|
56
|
+
this.beforeRender = () => ({});
|
|
73
57
|
/**
|
|
74
58
|
* Runs **_after_** every render cycle, including the first.
|
|
75
59
|
*
|
|
@@ -80,55 +64,49 @@ var ComponentInstance = /** @class */ (function (_super) {
|
|
|
80
64
|
*
|
|
81
65
|
* @returns A cleanup function.
|
|
82
66
|
*/
|
|
83
|
-
|
|
67
|
+
this.onRender = () => helpers_1.noOp;
|
|
84
68
|
/**
|
|
85
69
|
* Runs when the component is unmounted.
|
|
86
70
|
* It is called _after_ the cleanup function returned by onMount.
|
|
87
71
|
*/
|
|
88
|
-
|
|
89
|
-
return _this;
|
|
72
|
+
this.cleanUp = () => { };
|
|
90
73
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
enumerable: false,
|
|
128
|
-
configurable: true
|
|
129
|
-
});
|
|
130
|
-
return ComponentInstance;
|
|
131
|
-
}(logic_1.ComponentLogic));
|
|
74
|
+
/**
|
|
75
|
+
* Exposes the object returned by {@link beforeRender}.
|
|
76
|
+
*
|
|
77
|
+
* This is useful when you need to render some state or props
|
|
78
|
+
* in a transformed format. Put the transformation logic
|
|
79
|
+
* in {@link beforeRender} to the keep the main
|
|
80
|
+
* function component body clean.
|
|
81
|
+
*
|
|
82
|
+
* ******
|
|
83
|
+
*
|
|
84
|
+
* @example <caption>Using `templateContext`.</caption>
|
|
85
|
+
*
|
|
86
|
+
* ```tsx
|
|
87
|
+
* class MyComponentLogic extends ComponentInstance {
|
|
88
|
+
* beforeRender = () => {
|
|
89
|
+
* const title = `My Site | ${this.props.title}`;
|
|
90
|
+
* return { title };
|
|
91
|
+
* }
|
|
92
|
+
* }
|
|
93
|
+
* const MyComponent = (props) => {
|
|
94
|
+
* const self = useInstance(MyComponentLogic, props);
|
|
95
|
+
* const { templateContext: ctx, state } = self;
|
|
96
|
+
*
|
|
97
|
+
* return (
|
|
98
|
+
* <h1>
|
|
99
|
+
* {ctx.title}
|
|
100
|
+
* </h1>
|
|
101
|
+
* <p>{props.description}</p>
|
|
102
|
+
* );
|
|
103
|
+
* }
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
get templateContext() {
|
|
107
|
+
return this._templateContext;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
132
110
|
exports.ComponentInstance = ComponentInstance;
|
|
133
111
|
;
|
|
134
112
|
/**
|
|
@@ -144,15 +122,11 @@ exports.ComponentInstance = ComponentInstance;
|
|
|
144
122
|
*
|
|
145
123
|
* The provided class should be a subclass of {@link ComponentInstance}.
|
|
146
124
|
*/
|
|
147
|
-
|
|
125
|
+
const useInstance = (...args) => {
|
|
148
126
|
var _a;
|
|
149
|
-
|
|
150
|
-
for (var _i = 0; _i < arguments.length; _i++) {
|
|
151
|
-
args[_i] = arguments[_i];
|
|
152
|
-
}
|
|
153
|
-
var Component = args[0], _b = args[1], props = _b === void 0 ? {} : _b;
|
|
127
|
+
const [Component, props = {}] = args;
|
|
154
128
|
// useHooks.
|
|
155
|
-
|
|
129
|
+
const instance = (0, logic_1.useLogic)(Component, props);
|
|
156
130
|
// beforeMount, onMount, cleanUp.
|
|
157
131
|
(0, mount_callbacks_1.useMountCallbacks)(instance);
|
|
158
132
|
// beforeRender.
|
|
@@ -160,20 +134,21 @@ var useInstance = function () {
|
|
|
160
134
|
* A proxy variable to allow typechecking of the assignment
|
|
161
135
|
* to `self.templateContext` despite the need for "readonly" error suppression.
|
|
162
136
|
*/
|
|
163
|
-
|
|
137
|
+
let _templateContextProxy_;
|
|
164
138
|
// @ts-expect-error Assigning to a readonly property.
|
|
165
139
|
instance._templateContext = (_templateContextProxy_ = (_a = instance.beforeRender) === null || _a === void 0 ? void 0 : _a.call(instance));
|
|
166
140
|
// onRender.
|
|
167
|
-
(0, react_1.useEffect)(
|
|
141
|
+
(0, react_1.useEffect)(() => {
|
|
168
142
|
var _a;
|
|
169
|
-
|
|
170
|
-
return
|
|
143
|
+
const cleanupAfterRerender = (_a = instance.onRender) === null || _a === void 0 ? void 0 : _a.call(instance);
|
|
144
|
+
return () => {
|
|
171
145
|
if (typeof cleanupAfterRerender === 'function')
|
|
172
146
|
cleanupAfterRerender();
|
|
173
147
|
else
|
|
174
|
-
cleanupAfterRerender === null || cleanupAfterRerender === void 0 ? void 0 : cleanupAfterRerender.then(
|
|
148
|
+
cleanupAfterRerender === null || cleanupAfterRerender === void 0 ? void 0 : cleanupAfterRerender.then((cleanUp) => cleanUp === null || cleanUp === void 0 ? void 0 : cleanUp());
|
|
175
149
|
};
|
|
176
150
|
});
|
|
151
|
+
// class FormValues<TValues> extends BrowserMemStore<TValues> {}
|
|
177
152
|
return instance;
|
|
178
153
|
};
|
|
179
154
|
exports.useInstance = useInstance;
|