@cleanweb/react 1.1.1-beta.27 → 1.1.1-beta.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -247,7 +247,7 @@ class Button extends ClassComponent {
247
247
  }
248
248
 
249
249
  /** Button Template */
250
- Render = () => {
250
+ template = () => {
251
251
  const { Paragraphs, submit, state } = this;
252
252
 
253
253
  return <>
@@ -1,4 +1,3 @@
1
- import type { VoidFunctionComponent } from 'react';
2
1
  import type { TStateData } from '../../base';
3
2
  import type { THooksBase } from '../logic';
4
3
  import type { Extractor } from './types/extractor';
@@ -13,19 +12,6 @@ type o = object;
13
12
  * with little to no changes to their existing semantics/implementation.
14
13
  */
15
14
  export declare class ClassComponent<TProps extends o = WeakEmptyObject, TState extends TStateData = WeakEmptyObject, THooks extends THooksBase = void> extends ComponentInstance<TProps, TState, THooks> {
16
- /**
17
- * @deprecated An older alternative to {@link template}.
18
- *
19
- * Using this will add a component boundary between your JSX template
20
- * and the function component returned from ClassComponent.FC();
21
- *
22
- * This means that from React's perspective, your template won't "own" the state and props it consumes.
23
- * This could lead to subtle unexpected changes in behaviour.
24
- *
25
- * In most cases, you should use {@link template} instead, as it allows your class component
26
- * to function more predictably as a single unit.
27
- */
28
- Render?: VoidFunctionComponent<{}>;
29
15
  /**
30
16
  * Analogous to {@link React.Component.render}. A function that returns
31
17
  * your component's JSX template.
@@ -57,7 +43,7 @@ export declare class ClassComponent<TProps extends o = WeakEmptyObject, TState e
57
43
  * }
58
44
  * ```
59
45
  */
60
- template?: () => (React.JSX.Element | null);
46
+ template: () => (React.JSX.Element | null);
61
47
  /**
62
48
  * Manually trigger a rerender of your component.
63
49
  * You should rarely ever need this. But if you are migrating
@@ -93,9 +79,9 @@ export declare class ClassComponent<TProps extends o = WeakEmptyObject, TState e
93
79
  * // Render with `<Button.RC />`, or export RC to use the component in other files.
94
80
  * export default Button.RC;
95
81
  */
96
- static readonly FC: Extractor;
97
- /** @see {@link ClassComponent.FC} */
98
82
  static readonly extract: Extractor;
83
+ /** @see {@link ClassComponent.extract} */
84
+ static readonly FC: Extractor;
99
85
  }
100
86
  export { ClassComponent as Component };
101
87
  /** /testing: {
@@ -16,7 +16,6 @@ var __extends = (this && this.__extends) || (function () {
16
16
  })();
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
18
  exports.Component = exports.ClassComponent = void 0;
19
- var jsx_runtime_1 = require("react/jsx-runtime");
20
19
  var react_1 = require("react");
21
20
  var instance_1 = require("../instance");
22
21
  var function_name_1 = require("./utils/function-name");
@@ -32,7 +31,40 @@ var rerender_1 = require("./utils/rerender");
32
31
  var ClassComponent = /** @class */ (function (_super) {
33
32
  __extends(ClassComponent, _super);
34
33
  function ClassComponent() {
35
- return _super !== null && _super.apply(this, arguments) || this;
34
+ var _this = _super !== null && _super.apply(this, arguments) || this;
35
+ /**
36
+ * Analogous to {@link React.Component.render}. A function that returns
37
+ * your component's JSX template.
38
+ *
39
+ * You should place most logic that would usually go here
40
+ * in {@link ComponentInstance.beforeRender | `beforeRender`} instead.
41
+ * This helps to separate concerns and keep the template itself clean.
42
+ *
43
+ * ******
44
+ *
45
+ * Ideally the template method should only be concerned with defining the HTML/JSX structure of
46
+ * your component's UI. This may include destructuring nested instance members
47
+ * into more easily accessible local variables, or some simple transformation of data from props/state
48
+ * into a more appropriate format for display.
49
+ *
50
+ * ******
51
+ *
52
+ * @example < caption>Using a template function that returns JSX.</ caption>
53
+ *
54
+ * ```tsx
55
+ * template = () => {
56
+ * const { title } = this.props;
57
+ *
58
+ * return (
59
+ * <h1>
60
+ * {this.props.title}
61
+ * </h1>
62
+ * );
63
+ * }
64
+ * ```
65
+ */
66
+ _this.template = function () { return null; };
67
+ return _this;
36
68
  }
37
69
  var _a;
38
70
  _a = ClassComponent;
@@ -62,7 +94,7 @@ var ClassComponent = /** @class */ (function (_super) {
62
94
  * // Render with `<Button.RC />`, or export RC to use the component in other files.
63
95
  * export default Button.RC;
64
96
  */
65
- ClassComponent.FC = function FC(_Component) {
97
+ ClassComponent.extract = function FC(_Component) {
66
98
  var Component = _Component !== null && _Component !== void 0 ? _Component : this;
67
99
  var isClassComponentType = Component.prototype instanceof _a;
68
100
  if (!Component.getInitialState || !isClassComponentType)
@@ -73,56 +105,16 @@ var ClassComponent = /** @class */ (function (_super) {
73
105
  /** A class-based React function component created with (@cleanweb/react).{@link ClassComponent} */
74
106
  var Wrapper = function (props) {
75
107
  var instance = (0, instance_1.useInstance)(Component, props);
76
- var Render = instance.Render, template = instance.template;
108
+ var template = instance.template;
77
109
  var _forceUpdate;
78
110
  // @ts-expect-error (Cannot assign to 'forceUpdate' because it is a read-only property.ts(2540))
79
111
  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`.
80
112
  );
81
- // Add calling component name to Render function name in stack traces.
113
+ // Add calling component name to template function name in stack traces.
82
114
  (0, react_1.useMemo)(function () {
83
- if (typeof template === 'function')
84
- (0, function_name_1.setFunctionName)(template, "".concat(Component.name, ".template"));
85
- else if (typeof Render === 'function')
86
- (0, function_name_1.setFunctionName)(Render, "".concat(Component.name, ".Render"));
87
- }, [Render, template]);
88
- /**
89
- * Normally a component can update it's own state in the "before-render" stage to
90
- * skip DOM updates and trigger and immediate rerun of the rendering with the new state.
91
- *
92
- * It may be impossible to do this within the body of Render, if we call it as JSX here,
93
- * since technically, the Wrapper component owns the state and not the Render component.
94
- * Using it as JSX establishes a component boundary, and React will throw an error if we try to set
95
- * state in the "before-render" stage of `Render`, since it will be attempting to update it's parent's
96
- * state (i.e `Wrapper` component) rather than it's own state.
97
- *
98
- * Users should favor using the `template()` method instead. This way, we avoid
99
- * establishing a component boundary between `Wrapper` and `Render`.
100
- *
101
- * Although, since beforeRender() is called earlier from a hook, this is probably
102
- * a non-issue. It will only force users to move their logic into `beforeRender` instead
103
- * of doing it directly in `Render`. Even if `template` is being used, the `beforeRender` method
104
- * is the preferred location for such logic to maintain a high level of separation of concerns,
105
- * which is what this library exists to provide.
106
- *
107
- * So there's probably no real value lost with the component boundary. Users should just use
108
- * `beforeRender` + `template`.
109
- **/
110
- switch (typeof template) {
111
- case 'undefined':
112
- if (typeof Render === 'function')
113
- return (0, jsx_runtime_1.jsx)(Render, {});
114
- else
115
- throw new Error([
116
- 'A ClassComponent must have either a `template` or a `Render` property. But neither was found.',
117
- 'Add a `template: (JSX.Element | null);` member to your class, (or a `template` method that returns the same type).',
118
- 'Alternatively, add a `Render: FunctionComponent;` method.',
119
- '\n\n',
120
- 'Expected `Render` to be a Function Component because `template` was `undefined`.',
121
- "Instead got the following '".concat(typeof Render, "': $o"),
122
- ].join(' '), Render);
123
- case 'function': return template();
124
- default: return template;
125
- }
115
+ (0, function_name_1.setFunctionName)(template, "".concat(Component.name, ".template"));
116
+ }, [template]);
117
+ return template();
126
118
  };
127
119
  /**************************************
128
120
  * End Function Component *
@@ -130,9 +122,25 @@ var ClassComponent = /** @class */ (function (_super) {
130
122
  (0, function_name_1.setFunctionName)(Wrapper, "$".concat(Component.name, "$"));
131
123
  return Wrapper;
132
124
  };
133
- /** @see {@link ClassComponent.FC} */
134
- ClassComponent.extract = _a.FC;
125
+ /** @see {@link ClassComponent.extract} */
126
+ ClassComponent.FC = _a.extract;
135
127
  return ClassComponent;
136
128
  }(instance_1.ComponentInstance));
137
129
  exports.ClassComponent = ClassComponent;
138
130
  exports.Component = ClassComponent;
131
+ /** /testing: {
132
+ const a: object = {b: ''};
133
+
134
+ type t = keyof typeof a;
135
+
136
+ class MyComponentLogic extends ClassComponent<{}, {a: ''}> {
137
+ static getInitialState = () => ({a: '' as const});
138
+ // a = () => this.hooks.a = '';
139
+
140
+ useHooks = () => {
141
+ this.state.a;
142
+ };
143
+ };
144
+
145
+ const Template = MyComponentLogic.FC();
146
+ }/**/
@@ -2,5 +2,5 @@ import type { VoidFunctionComponent } from 'react';
2
2
  import type { BaseClassComponent, IClassComponent } from './class/instance';
3
3
  import type { IClassComponentConstructor } from './class/static';
4
4
  type BaseCCConstructor = IClassComponentConstructor<BaseClassComponent>;
5
- export type Extractor = <TComponent extends BaseCCConstructor>(this: TComponent & Constructor<IClassComponent<InstanceType<TComponent>>>, Component?: TComponent & Constructor<IClassComponent<InstanceType<TComponent>>>) => VoidFunctionComponent<InstanceType<TComponent>['props']>;
5
+ export type Extractor = <TComponent extends BaseCCConstructor>(this: TComponent & IClassComponentConstructor<IClassComponent<InstanceType<TComponent>>>, Component?: TComponent & IClassComponentConstructor<IClassComponent<InstanceType<TComponent>>>) => VoidFunctionComponent<InstanceType<TComponent>['props']>;
6
6
  export {};
@@ -25,8 +25,6 @@ export declare class ComponentLogic<TProps extends object = {}, TState extends T
25
25
  * Called before each instance of your component is mounted.
26
26
  * It receives the initial `props` object and should return
27
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
28
  */
31
29
  static getInitialState: (p?: any) => object;
32
30
  /** Do not use. Will be undefined at runtime. */
@@ -43,8 +43,6 @@ var ComponentLogic = /** @class */ (function () {
43
43
  * Called before each instance of your component is mounted.
44
44
  * It receives the initial `props` object and should return
45
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
46
  */
49
47
  ComponentLogic.getInitialState = function (p) { return ({}); };
50
48
  return ComponentLogic;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cleanweb/react",
3
- "version": "1.1.1-beta.27",
3
+ "version": "1.1.1-beta.28",
4
4
  "description": "A suite of helpers for writing cleaner React function components.",
5
5
  "engines": {
6
6
  "node": ">=18"