@cleanweb/react 1.1.1-beta.21 → 1.1.1-beta.23

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.
@@ -71,9 +71,9 @@ var MergedState = /** @class */ (function () {
71
71
  return MergedState;
72
72
  }());
73
73
  var useMergedState = function (initialState) {
74
- var cleanState = (0, react_1.useMemo)(function () {
74
+ var cleanState = (0, react_1.useRef)((0, react_1.useMemo)(function () {
75
75
  return new MergedState(initialState);
76
- }, []);
76
+ }, [])).current;
77
77
  MergedState.useRefresh.call(cleanState);
78
78
  return cleanState;
79
79
  };
@@ -23,3 +23,19 @@ type UseMethods = {
23
23
  */
24
24
  declare const useMethods: UseMethods;
25
25
  export { useMethods };
26
+ /** /testing: {
27
+ let a = async () => {
28
+ const a: object = {b: ''};
29
+
30
+ type t = keyof typeof a;
31
+
32
+ class MyMethods extends ComponentMethods<WeakEmptyObject, null> {
33
+ // static getInitialState = () => ({});
34
+ };
35
+
36
+ const { useCleanState } = (await import('./state.js'));
37
+
38
+ const self = useMethods(MyMethods, {});
39
+ self.state;
40
+ }
41
+ }/**/
@@ -46,7 +46,7 @@ var useMethods = function () {
46
46
  return methods;
47
47
  };
48
48
  exports.useMethods = useMethods;
49
- /*testing: {
49
+ /** /testing: {
50
50
  let a = async () => {
51
51
  const a: object = {b: ''};
52
52
 
@@ -61,4 +61,4 @@ exports.useMethods = useMethods;
61
61
  const self = useMethods(MyMethods, {});
62
62
  self.state;
63
63
  }
64
- }*/
64
+ }/**/
@@ -4,12 +4,15 @@ import type { IComponentInstanceClass } from './instance';
4
4
  import { ComponentInstance } from './instance';
5
5
  import { THooksBase } from './logic';
6
6
  export declare const useRerender: () => () => void;
7
- type ComponentClassParams = ConstructorParameters<typeof ClassComponent>;
8
7
  type o = object;
9
- export interface IComponentClass<Instance extends ClassComponent<o, o, THooksBase> = ClassComponent, Params extends ComponentClassParams = ComponentClassParams> extends IComponentInstanceClass<Instance, Params> {
8
+ type ComponentClassOwnStaticKeys = Exclude<keyof typeof ClassComponent, keyof IComponentInstanceClass>;
9
+ type ComponentClassOwnStatics = {
10
+ [Key in ComponentClassOwnStaticKeys]: (typeof ClassComponent)[Key];
11
+ };
12
+ export interface IComponentClass<Instance extends ClassComponent<o, o, THooksBase> = ClassComponent> extends Constructor<Instance>, ComponentClassOwnStatics, IComponentInstanceClass<Instance> {
10
13
  }
11
- type Extractor = <TComponent extends typeof ClassComponent<o, o, THooksBase>>(this: NonNullable<typeof _Component>, _Component?: TComponent & IComponentClass<InstanceType<TComponent>>) => VoidFunctionComponent<InstanceType<TComponent>['props']>;
12
- type ReactTemplate = React.JSX.Element | null;
14
+ type BaseClassComponent = ClassComponent<o, o, THooksBase>;
15
+ type Extractor = <TComponent extends IComponentClass<BaseClassComponent>>(this: NonNullable<typeof _Component>, _Component?: TComponent) => VoidFunctionComponent<InstanceType<TComponent>['props']>;
13
16
  /**
14
17
  * A superset of {@link ComponentInstance} that allows defining your
15
18
  * component's JSX template directly inside the class.
@@ -63,7 +66,7 @@ export declare class ClassComponent<TProps extends o = WeakEmptyObject, TState e
63
66
  * }
64
67
  * ```
65
68
  */
66
- template?: () => ReactTemplate;
69
+ template?: () => (React.JSX.Element | null);
67
70
  /**
68
71
  * Manually trigger a rerender of your component.
69
72
  * You should rarely ever need this. But if you are migrating
@@ -77,16 +80,31 @@ export declare class ClassComponent<TProps extends o = WeakEmptyObject, TState e
77
80
  * Function Component Extractor *
78
81
  **************************************/
79
82
  /**
80
- * Extract a function component which can be used to render
81
- * your ClassComponent just like any other component.
83
+ * Extract a Function Component (FC) which can be used to render
84
+ * your ClassComponent just like any other React component.
82
85
  *
83
- * Each JSX reference to this returned component will render with
86
+ * Each JSX reference to the returned component will render with
84
87
  * a separate instance of your class.
85
88
  *
86
89
  * So you only need to call `YourClassComponent.FC()` once, then use the returned
87
90
  * function component as many times as you need.
91
+ *
92
+ * It is recommended to store this returned value as a static member of
93
+ * your ClassComponent. While this value may be given any name, the name
94
+ * RC (for "React Component") is the recommended convention.
95
+ *
96
+ * @example <caption>Calling FC in your ClassComponent</caption>
97
+ * class Button extends ClassComponent {
98
+ * static readonly RC = this.FC();
99
+ * // Because of the static keyword, `this` here refers to the class itself, same as calling `Button.FC()`.
100
+ * }
101
+ *
102
+ * // Render with `<Button.RC />`, or export RC to use the component in other files.
103
+ * export default Button.RC;
88
104
  */
89
105
  static readonly FC: Extractor;
106
+ /** @see {@link ClassComponent.FC} */
107
+ static readonly extract: Extractor;
90
108
  }
91
109
  interface HookWrapperProps<THookFunction extends AnyFunction> {
92
110
  /**
@@ -115,3 +133,19 @@ type ClassComponentHookWrapper = <Hook extends AnyFunction>(props: HookWrapperPr
115
133
  */
116
134
  export declare const Use: ClassComponentHookWrapper;
117
135
  export {};
136
+ /** /testing: {
137
+ const a: object = {b: ''};
138
+
139
+ type t = keyof typeof a;
140
+
141
+ class MyComponentLogic extends ClassComponent<{}, {a: ''}> {
142
+ static getInitialState = () => ({a: '' as const});
143
+ // a = () => this.hooks.a = '';
144
+
145
+ useHooks = () => {
146
+ this.state.a;
147
+ };
148
+ };
149
+
150
+ const Template = MyComponentLogic.FC();
151
+ }/**/
@@ -56,24 +56,37 @@ var ClassComponent = /** @class */ (function (_super) {
56
56
  function ClassComponent() {
57
57
  return _super !== null && _super.apply(this, arguments) || this;
58
58
  }
59
+ var _a;
60
+ _a = ClassComponent;
59
61
  /*************************************
60
62
  * Function Component Extractor *
61
63
  **************************************/
62
- // @todo Attempt using implicit `this` value to allow rendering <MyComponent.FC /> directly.
63
- // const FC = (props) => { const self = useMemo(() => useInstance(this, props), {}); return self.template(); }
64
64
  /**
65
- * Extract a function component which can be used to render
66
- * your ClassComponent just like any other component.
65
+ * Extract a Function Component (FC) which can be used to render
66
+ * your ClassComponent just like any other React component.
67
67
  *
68
- * Each JSX reference to this returned component will render with
68
+ * Each JSX reference to the returned component will render with
69
69
  * a separate instance of your class.
70
70
  *
71
71
  * So you only need to call `YourClassComponent.FC()` once, then use the returned
72
72
  * function component as many times as you need.
73
+ *
74
+ * It is recommended to store this returned value as a static member of
75
+ * your ClassComponent. While this value may be given any name, the name
76
+ * RC (for "React Component") is the recommended convention.
77
+ *
78
+ * @example <caption>Calling FC in your ClassComponent</caption>
79
+ * class Button extends ClassComponent {
80
+ * static readonly RC = this.FC();
81
+ * // Because of the static keyword, `this` here refers to the class itself, same as calling `Button.FC()`.
82
+ * }
83
+ *
84
+ * // Render with `<Button.RC />`, or export RC to use the component in other files.
85
+ * export default Button.RC;
73
86
  */
74
87
  ClassComponent.FC = function FC(_Component) {
75
88
  var Component = _Component !== null && _Component !== void 0 ? _Component : this;
76
- var isClassComponentType = Component.prototype instanceof ClassComponent;
89
+ var isClassComponentType = Component.prototype instanceof _a;
77
90
  if (!Component.getInitialState || !isClassComponentType)
78
91
  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()`).');
79
92
  /*************************************
@@ -139,6 +152,8 @@ var ClassComponent = /** @class */ (function (_super) {
139
152
  setFunctionName(Wrapper, "$".concat(Component.name, "$"));
140
153
  return Wrapper;
141
154
  };
155
+ /** @see {@link ClassComponent.FC} */
156
+ ClassComponent.extract = _a.FC;
142
157
  return ClassComponent;
143
158
  }(instance_1.ComponentInstance));
144
159
  exports.ClassComponent = ClassComponent;
@@ -1,5 +1,5 @@
1
- import type { TStateData } from '../base/state';
2
- import type { THooksBase, IComponentLogicClass } from './logic';
1
+ import type { ExtractCleanStateData, TStateData } from '../base/state';
2
+ import type { THooksBase } from './logic';
3
3
  import { ComponentLogic } from './logic';
4
4
  type AsyncAllowedEffectCallback = () => Awaitable<IVoidFunction>;
5
5
  /** An empty function. It returns (void) without performing any operations. */
@@ -9,7 +9,7 @@ export declare const noOp: () => void;
9
9
  * This provides a declarative API for working with your React function component's lifecycle,
10
10
  * a simpler alternative to the imperative approach with `useEffect` and/or `useMemo`.
11
11
  */
12
- export declare class ComponentInstance<TProps extends o = {}, TState extends TStateData = WeakEmptyObject, THooks extends THooksBase = void> extends ComponentLogic<TProps, TState, THooks> {
12
+ export declare class ComponentInstance<TProps extends o = {}, TState extends TStateData = WeakEmptyObject, THooks extends THooksBase = void> extends ComponentLogic.Class<TProps, TState, THooks> {
13
13
  /**
14
14
  * Runs only _before_ first render, i.e before the component instance is mounted.
15
15
  * Useful for logic that is involved in determining what to render.
@@ -55,12 +55,36 @@ export declare class ComponentInstance<TProps extends o = {}, TState extends TSt
55
55
  cleanUp: IVoidFunction;
56
56
  }
57
57
  type o = object;
58
- type InstanceClassParams = ConstructorParameters<typeof ComponentInstance<o, o, o>>;
59
- export interface IComponentInstanceClass<Instance extends ComponentInstance<o, o, THooksBase> = ComponentInstance, Params extends InstanceClassParams = InstanceClassParams> extends IComponentLogicClass<Instance, Params> {
58
+ type ComponentInstanceOwnStaticKeys = Exclude<keyof typeof ComponentInstance, keyof ComponentLogic.ClassType>;
59
+ type ComponentInstanceOwnStatics = {
60
+ [Key in ComponentInstanceOwnStaticKeys]: (typeof ComponentInstance)[Key];
61
+ };
62
+ export interface IComponentInstance<Instance extends ComponentInstance<o, o, THooksBase>> extends ComponentLogic.Instance<Instance>, Omit<ComponentInstance<Instance['props'], ExtractCleanStateData<Instance['state']>, Instance['_thooks']>, 'useHooks'> {
63
+ }
64
+ export interface IComponentInstanceClass<Instance extends ComponentInstance<o, o, THooksBase> = ComponentInstance> extends Constructor<IComponentInstance<Instance>>, ComponentInstanceOwnStatics, ComponentLogic.ClassType<Instance> {
60
65
  }
61
66
  type UseInstance = {
62
- <Class extends typeof ComponentInstance<HardEmptyObject, o, THooksBase>>(Methods: Class & IComponentInstanceClass<InstanceType<Class>>): InstanceType<Class>;
63
- <Class extends typeof ComponentInstance<o, o, THooksBase>>(Methods: Class & IComponentInstanceClass<InstanceType<Class>>, props: InstanceType<Class>['props']): InstanceType<Class>;
67
+ <Class extends IComponentInstanceClass<ComponentInstance<o, o, THooksBase>>>(Methods: Class): InstanceType<Class>;
68
+ <Class extends IComponentInstanceClass<ComponentInstance<o, o, THooksBase>>>(Methods: Class, props: InstanceType<Class>['props']): InstanceType<Class>;
64
69
  };
65
70
  export declare const useInstance: UseInstance;
66
71
  export {};
72
+ /** /testing: {
73
+ class A extends ComponentInstance<{}, {}, object> {
74
+ static getInitialState: (p?: object) => ({putan: ''});
75
+ // k = this.props.o
76
+ a = this.state['_initialValues_']
77
+
78
+ // useHooks: (() => void | HardEmptyObject) | undefined;
79
+ // hard empty has every key
80
+ // weak empty has no key
81
+ // weak empty is not assignable to hard empty
82
+ }
83
+
84
+ const a = useInstance(A, {o: ''});
85
+ a.a;
86
+
87
+ // a.props['o'];
88
+ type bbbb = A['state'];
89
+ type ttt = bbbb['put'];
90
+ }/**/
@@ -102,7 +102,7 @@ var ComponentInstance = /** @class */ (function (_super) {
102
102
  return _this;
103
103
  }
104
104
  return ComponentInstance;
105
- }(logic_1.ComponentLogic));
105
+ }(logic_1.ComponentLogic.Class));
106
106
  exports.ComponentInstance = ComponentInstance;
107
107
  ;
108
108
  ;
@@ -156,21 +156,22 @@ var useInstance = function () {
156
156
  return instance;
157
157
  };
158
158
  exports.useInstance = useInstance;
159
- /*testing: {
160
- class A extends ComponentInstance {
159
+ /** /testing: {
160
+ class A extends ComponentInstance<{}, {}, object> {
161
161
  static getInitialState: (p?: object) => ({putan: ''});
162
162
  // k = this.props.o
163
163
  a = this.state['_initialValues_']
164
164
 
165
+ // useHooks: (() => void | HardEmptyObject) | undefined;
165
166
  // hard empty has every key
166
167
  // weak empty has no key
167
168
  // weak empty is not assignable to hard empty
168
169
  }
169
170
 
170
- const p = {k: ''}
171
171
  const a = useInstance(A, {o: ''});
172
+ a.a;
172
173
 
173
174
  // a.props['o'];
174
175
  type bbbb = A['state'];
175
176
  type ttt = bbbb['put'];
176
- }*/
177
+ }/**/
@@ -0,0 +1,18 @@
1
+ import type { ComponentLogic } from '.';
2
+ import type { CLBaseType, IComponentLogic } from './instance-types';
3
+ import type { IComponentLogicClass } from './static-types';
4
+ /*************************************
5
+ * # Hooks *
6
+ **************************************/
7
+ /** */
8
+ type ULClassParam = IComponentLogicClass<IComponentLogic<CLBaseType>>;
9
+ export type UseLogic = {
10
+ <Class extends ULClassParam>(Methods: Class): InstanceType<Class>;
11
+ <Class extends ULClassParam>(Methods: Class, props: InstanceType<Class>['props']): InstanceType<Class>;
12
+ };
13
+ export type ULParams = [
14
+ Class: ComponentLogic.ClassType<ComponentLogic.Instance<CLBaseType>>,
15
+ props?: object
16
+ ];
17
+ export type ULReturn = CLBaseType;
18
+ export {};
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,77 @@
1
+ import type { TCleanState, TStateData } from '../../base/state';
2
+ import type { IComponentLogicClass } from './static-types';
3
+ import type { CLBaseType, IComponentLogic } from './instance-types';
4
+ import type { UseLogic } from './hook-types';
5
+ export type HardEmpty = HardEmptyObject;
6
+ export type WeakEmpty = WeakEmptyObject;
7
+ export type THooksBase = object | void;
8
+ /**
9
+ * Base class for a class that holds methods intended for use in a function component,
10
+ * as well as a static method for initializing state.
11
+ *
12
+ * These methods will have access to the components state and props via
13
+ * `this.state` and `this.props` respectively.
14
+ *
15
+ * The special {@link Class['useHooks'] | useHooks} method allows you to consume
16
+ * React hooks within this class.
17
+ *
18
+ * Call the {@link useLogic} hook inside your function component to instantiate the class.
19
+ */
20
+ export declare class ComponentLogic<TProps extends object = {}, TState extends TStateData = WeakEmpty, THooks extends THooksBase = void> {
21
+ readonly state: TCleanState<TState>;
22
+ readonly props: TProps;
23
+ readonly hooks: THooks extends object ? THooks : WeakEmptyObject;
24
+ /**
25
+ * Called before each instance of your component is mounted.
26
+ * It receives the initial `props` object and should return
27
+ * an object with the initial values for your component's state.
28
+ *
29
+ * PS: `p?: object` wierdly causes TS error in v^5.5.4; object is not assignable to the component's TProps.
30
+ */
31
+ static getInitialState: (p?: any) => object;
32
+ /** Do not use. Will be undefined at runtime. */
33
+ readonly _thooks: THooks;
34
+ /**
35
+ * Call React hooks and expose any values your component
36
+ * needs by return an object with said values. The returned
37
+ * object will be accessible as `this.hooks`;
38
+ */
39
+ useHooks: () => void;
40
+ }
41
+ export declare const useLogic: UseLogic;
42
+ export declare namespace ComponentLogic {
43
+ class Class<TProps extends object = {}, TState extends TStateData = WeakEmpty, THooks extends THooksBase = void> extends ComponentLogic<TProps, TState, THooks> {
44
+ }
45
+ type Instance<Instance extends CLBaseType = Class> = IComponentLogic<Instance>;
46
+ type ClassType<Instance extends CLBaseType = Class> = IComponentLogicClass<Instance>;
47
+ }
48
+ /** /testing: {
49
+ const a: object = {b: ''};
50
+
51
+ type t = keyof typeof a;
52
+
53
+ class MyComponentLogic extends ComponentLogic.Class<{}, {b: number}, {a: string}> {
54
+ static getInitialState = () => ({b: 7});
55
+ // b = this.state.put[''] + this.props.b;
56
+
57
+ useHooks = () => ({a: 'undefined'});
58
+ };
59
+
60
+ type tt = keyof {};
61
+
62
+ MyComponentLogic.getInitialState
63
+ const self = useLogic(MyComponentLogic);
64
+ self.useHooks();
65
+
66
+
67
+ const A = class C extends ComponentLogic.Class {
68
+ // static getInitialState = () => ({a: 'l'});
69
+ // a = () => this.state.yyy = '';
70
+ }
71
+
72
+ A.getInitialState();
73
+
74
+ // const oa = {['a' as unknown as symbol]: 'boo'};
75
+ const oa = {['a']: 'boo'};
76
+ useLogic(A, oa);
77
+ }/**/
@@ -0,0 +1,120 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.useLogic = exports.ComponentLogic = void 0;
19
+ var react_1 = require("react");
20
+ var state_1 = require("../../base/state");
21
+ /**
22
+ * Base class for a class that holds methods intended for use in a function component,
23
+ * as well as a static method for initializing state.
24
+ *
25
+ * These methods will have access to the components state and props via
26
+ * `this.state` and `this.props` respectively.
27
+ *
28
+ * The special {@link Class['useHooks'] | useHooks} method allows you to consume
29
+ * React hooks within this class.
30
+ *
31
+ * Call the {@link useLogic} hook inside your function component to instantiate the class.
32
+ */
33
+ var ComponentLogic = /** @class */ (function () {
34
+ function ComponentLogic() {
35
+ /**
36
+ * Call React hooks and expose any values your component
37
+ * needs by return an object with said values. The returned
38
+ * object will be accessible as `this.hooks`;
39
+ */
40
+ this.useHooks = function () { };
41
+ }
42
+ /**
43
+ * Called before each instance of your component is mounted.
44
+ * It receives the initial `props` object and should return
45
+ * an object with the initial values for your component's state.
46
+ *
47
+ * PS: `p?: object` wierdly causes TS error in v^5.5.4; object is not assignable to the component's TProps.
48
+ */
49
+ ComponentLogic.getInitialState = function (p) { return ({}); };
50
+ return ComponentLogic;
51
+ }());
52
+ exports.ComponentLogic = ComponentLogic;
53
+ ;
54
+ var useLogic = function () {
55
+ var _a;
56
+ var args = [];
57
+ for (var _i = 0; _i < arguments.length; _i++) {
58
+ args[_i] = arguments[_i];
59
+ }
60
+ var Logic = args[0], _b = args[1], props = _b === void 0 ? {} : _b;
61
+ var state = (0, state_1.useCleanState)(Logic.getInitialState, props);
62
+ var self = (0, react_1.useRef)((0, react_1.useMemo)(function () {
63
+ return new Logic();
64
+ }, [])).current;
65
+ /** A proxy variable to allow typechecking of the assignment to `self.props` despite the need for "readonly" error suppression. */
66
+ var _propsProxy_;
67
+ /** A proxy variable to allow typechecking of the assignment to `self.state` despite the need for "readonly" error suppression. */
68
+ var _stateProxy_;
69
+ /** A proxy variable to allow typechecking of the assignment to `self.hooks` despite the need for "readonly" error suppression. */
70
+ var _hooksProxy_;
71
+ // @ts-expect-error
72
+ self.props = (_propsProxy_ = props);
73
+ // @ts-expect-error
74
+ self.state = (_stateProxy_ = state);
75
+ // @ts-expect-error
76
+ self.hooks = (_hooksProxy_ = (_a = self.useHooks()) !== null && _a !== void 0 ? _a : {});
77
+ return self;
78
+ };
79
+ exports.useLogic = useLogic;
80
+ (function (ComponentLogic) {
81
+ var Class = /** @class */ (function (_super) {
82
+ __extends(Class, _super);
83
+ function Class() {
84
+ return _super !== null && _super.apply(this, arguments) || this;
85
+ }
86
+ return Class;
87
+ }(ComponentLogic));
88
+ ComponentLogic.Class = Class;
89
+ ;
90
+ })(ComponentLogic || (exports.ComponentLogic = ComponentLogic = {}));
91
+ /** /testing: {
92
+ const a: object = {b: ''};
93
+
94
+ type t = keyof typeof a;
95
+
96
+ class MyComponentLogic extends ComponentLogic.Class<{}, {b: number}, {a: string}> {
97
+ static getInitialState = () => ({b: 7});
98
+ // b = this.state.put[''] + this.props.b;
99
+
100
+ useHooks = () => ({a: 'undefined'});
101
+ };
102
+
103
+ type tt = keyof {};
104
+
105
+ MyComponentLogic.getInitialState
106
+ const self = useLogic(MyComponentLogic);
107
+ self.useHooks();
108
+
109
+
110
+ const A = class C extends ComponentLogic.Class {
111
+ // static getInitialState = () => ({a: 'l'});
112
+ // a = () => this.state.yyy = '';
113
+ }
114
+
115
+ A.getInitialState();
116
+
117
+ // const oa = {['a' as unknown as symbol]: 'boo'};
118
+ const oa = {['a']: 'boo'};
119
+ useLogic(A, oa);
120
+ }/**/
@@ -0,0 +1,19 @@
1
+ import type { ExtractCleanStateData } from '../../base';
2
+ import type { ComponentLogic, THooksBase } from '.';
3
+ /*************************************
4
+ * # Utils *
5
+ **************************************/
6
+ /** */
7
+ export type CLBaseType = ComponentLogic<object, object, THooksBase>;
8
+ type CLFromSubType<SubType extends CLBaseType> = ComponentLogic<SubType['props'], ExtractCleanStateData<SubType['state']>, SubType['_thooks']>;
9
+ /*************************************
10
+ * # Instance Type *
11
+ **************************************/
12
+ /** */
13
+ interface InstanceOverrides<Instance extends CLBaseType = ComponentLogic> {
14
+ useHooks: Instance['_thooks'] extends void ? () => (void | HardEmptyObject) : () => Instance['_thooks'];
15
+ }
16
+ type BaseInstance<Instance extends CLBaseType = ComponentLogic> = Omit<CLFromSubType<Instance>, keyof InstanceOverrides>;
17
+ export interface IComponentLogic<Instance extends CLBaseType = ComponentLogic> extends BaseInstance<Instance>, InstanceOverrides<Instance> {
18
+ }
19
+ export {};
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,17 @@
1
+ import type { ExtractCleanStateData } from '../../base';
2
+ import type { ComponentLogic, THooksBase } from '.';
3
+ import type { CLBaseType } from './instance-types';
4
+ /*************************************
5
+ * # Utils *
6
+ **************************************/
7
+ type o = object;
8
+ /*************************************
9
+ * # Class Static Side *
10
+ **************************************/
11
+ interface StaticOverrides<Instance extends CLBaseType = ComponentLogic> extends Constructor<Instance> {
12
+ getInitialState: (props?: Instance['props']) => ExtractCleanStateData<Instance['state']>;
13
+ }
14
+ type BaseStatics = Omit<typeof ComponentLogic, 'prototype' | keyof StaticOverrides>;
15
+ export interface IComponentLogicClass<Instance extends ComponentLogic<o, o, THooksBase> = ComponentLogic> extends BaseStatics, StaticOverrides<Instance> {
16
+ }
17
+ export {};
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,4 +1,16 @@
1
1
  declare const UniqueSecretSymbolKey: unique symbol;
2
+ /** /testing: {
3
+ const mySymbol = Symbol('asdfgh') as symbol;
4
+
5
+ const tt = {
6
+ // [mySymbol]: '' as never,
7
+ // [UniqueSecretSymbolKey]: '',
8
+ // '': '',
9
+ }
10
+
11
+ let TT: WeakEmptyObject = {};
12
+ TT = tt;
13
+ }/**/
2
14
  declare global {
3
15
  type Optional<BaseType, AllowNull extends boolean = true> = (AllowNull extends true ? BaseType | undefined | null : BaseType | undefined);
4
16
  type Awaitable<Type> = Type | Promise<Type>;
@@ -29,6 +29,7 @@
29
29
  "isolatedModules": true,
30
30
  "jsx": "react-jsx",
31
31
  "strictNullChecks": true,
32
+ "strictPropertyInitialization": true,
32
33
  "noImplicitAny": true,
33
34
  "noUncheckedIndexedAccess": true,
34
35
  "strictBindCallApply": true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cleanweb/react",
3
- "version": "1.1.1-beta.21",
3
+ "version": "1.1.1-beta.23",
4
4
  "description": "A suite of helpers for writing cleaner React function components.",
5
5
  "engines": {
6
6
  "node": ">=18"
@@ -1,57 +0,0 @@
1
- import type { TCleanState, ExtractCleanStateData, TStateData } from '../base/state';
2
- export type HardEmpty = HardEmptyObject;
3
- export type WeakEmpty = WeakEmptyObject;
4
- export type THooksBase = o | void;
5
- type o = object;
6
- /**
7
- * Base class for a class that holds methods intended for use in a function component,
8
- * as well as a static method for initializing state.
9
- *
10
- * These methods will have access to the components state and props via
11
- * `this.state` and `this.props` respectively.
12
- *
13
- * The special {@link ComponentLogic.useHooks | useHooks} method allows you to consume
14
- * React hooks within this class.
15
- *
16
- * Call the {@link useLogic} hook inside your function component to instantiate the class.
17
- */
18
- export declare class ComponentLogic<
19
- /** Describe the values your component expects to be passed as props. */
20
- TProps extends object = {},
21
- /** An object type that descibes your component's state. */
22
- TState extends TStateData = WeakEmpty,
23
- /** The object type returned by your component's {@link useHooks} method. */
24
- THooks extends THooksBase = void> {
25
- state: TCleanState<TState>;
26
- readonly props: TProps;
27
- readonly hooks: THooks extends object ? THooks : WeakEmptyObject;
28
- /**
29
- * Called before each instance of your component is mounted.
30
- * It receives the initial `props` object and should return
31
- * an object with the initial values for your component's state.
32
- */
33
- static getInitialState: (p?: any) => object;
34
- /**
35
- * This allows you to seamlessly consume React hooks in
36
- * your class component.
37
- *
38
- * It is called after state and props are updated on each render.
39
- * Call any hooks (e.g `useEffect`) you which to consume inside this function.
40
- *
41
- * To expose any returned values from your hooks to the rest of your component,
42
- * return an object that contains all the relevant values.
43
- *
44
- * This object will be accessible as `this.hooks` to the rest of your class.
45
- */
46
- useHooks: THooks extends void ? undefined | (() => void | HardEmptyObject) : () => THooks;
47
- }
48
- type LogicClassParams = ConstructorParameters<typeof ComponentLogic>;
49
- export interface IComponentLogicClass<Instance extends ComponentLogic<o, o, THooksBase> = ComponentLogic, Params extends LogicClassParams = LogicClassParams> extends Constructor<Instance, Params> {
50
- getInitialState: (props?: Instance['props']) => ExtractCleanStateData<Instance['state']>;
51
- }
52
- type UseLogic = {
53
- <Class extends typeof ComponentLogic<HardEmptyObject, o, THooksBase>>(Methods: Class & IComponentLogicClass<InstanceType<Class>>): InstanceType<Class>;
54
- <Class extends typeof ComponentLogic<o, o, THooksBase>>(Methods: Class & IComponentLogicClass<InstanceType<Class>>, props: InstanceType<Class>['props']): InstanceType<Class>;
55
- };
56
- declare const useLogic: UseLogic;
57
- export { useLogic };
@@ -1,81 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useLogic = exports.ComponentLogic = void 0;
4
- var react_1 = require("react");
5
- var state_1 = require("../base/state");
6
- /**
7
- * Base class for a class that holds methods intended for use in a function component,
8
- * as well as a static method for initializing state.
9
- *
10
- * These methods will have access to the components state and props via
11
- * `this.state` and `this.props` respectively.
12
- *
13
- * The special {@link ComponentLogic.useHooks | useHooks} method allows you to consume
14
- * React hooks within this class.
15
- *
16
- * Call the {@link useLogic} hook inside your function component to instantiate the class.
17
- */
18
- var ComponentLogic = /** @class */ (function () {
19
- function ComponentLogic() {
20
- }
21
- /**
22
- * Called before each instance of your component is mounted.
23
- * It receives the initial `props` object and should return
24
- * an object with the initial values for your component's state.
25
- */
26
- ComponentLogic.getInitialState = function (p) { return ({}); };
27
- return ComponentLogic;
28
- }());
29
- exports.ComponentLogic = ComponentLogic;
30
- ;
31
- var useLogic = function () {
32
- var _a, _b;
33
- var args = [];
34
- for (var _i = 0; _i < arguments.length; _i++) {
35
- args[_i] = arguments[_i];
36
- }
37
- var Logic = args[0], _c = args[1], props = _c === void 0 ? {} : _c;
38
- var state = (0, state_1.useCleanState)(Logic.getInitialState, props);
39
- var self = (0, react_1.useRef)((0, react_1.useMemo)(function () {
40
- return new Logic();
41
- }, [])).current;
42
- /** A proxy variable to allow typechecking of the assignment to `self.props` despite the need for "readonly" error suppression. */
43
- var _propsProxy_;
44
- /** A proxy variable to allow typechecking of the assignment to `self.hooks` despite the need for "readonly" error suppression. */
45
- var _hooksProxy_;
46
- self.state = state;
47
- // @ts-expect-error
48
- self.props = (_propsProxy_ = props);
49
- // @ts-expect-error
50
- self.hooks = (_hooksProxy_ = (_b = (_a = self.useHooks) === null || _a === void 0 ? void 0 : _a.call(self)) !== null && _b !== void 0 ? _b : {} // @todo Improve UseLogic types to reflect that this may be undefined.
51
- );
52
- return self;
53
- };
54
- exports.useLogic = useLogic;
55
- /*testing: {
56
- const a: object = {b: ''};
57
-
58
- type t = keyof typeof a;
59
-
60
- class MyComponentLogic extends ComponentLogic<{a: string}> {
61
- static getInitialState = () => ({a: '' as const});
62
- // b = this.state.put[''] + this.props.b;
63
- };
64
-
65
- type tt = keyof {};
66
-
67
- MyComponentLogic.getInitialState
68
- // const self = useLogic(MyComponentLogic);
69
-
70
-
71
- const A = class C extends ComponentLogic {
72
- // static getInitialState = () => ({a: 'l'});
73
- // a = () => this.state.yyy = '';
74
- }
75
-
76
- A.getInitialState();
77
-
78
- // const oa = {['a' as unknown as symbol]: 'boo'};
79
- const oa = {['a']: 'boo'};
80
- // const self = useLogic(A, oa);
81
- }*/