@cleanweb/react 1.1.1-beta.8 → 1.1.1-beta.9

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.
@@ -1,5 +1,5 @@
1
- import type { TCleanState } from './state';
2
- export declare class ComponentMethods<TProps extends object, TState extends object> {
1
+ import type { TCleanState, TStateData } from './state';
2
+ export declare class ComponentMethods<TProps extends object, TState extends TStateData> {
3
3
  props: TProps;
4
4
  state: TCleanState<TState>;
5
5
  }
@@ -66,7 +66,6 @@ var useMethods = function (Methods, props, state) {
66
66
  // But useRef and useState values appear to always be preserved whenever this happens.
67
67
  // So those two are the only cross-render-persistence methods we can consider safe.
68
68
  var methods = (0, react_1.useRef)((0, react_1.useMemo)(function () {
69
- // See useLogic implementation for a discussion of this type assertion.
70
69
  return new Methods();
71
70
  }, [])).current;
72
71
  methods.props = props;
@@ -7,8 +7,8 @@ type PutState<TState extends object> = {
7
7
  [Key in keyof TState]: React.Dispatch<React.SetStateAction<TState[Key]>>;
8
8
  };
9
9
  declare class CleanStateBase<TState extends Record<string, any>> {
10
- reservedKeys: string[];
11
- valueKeys: string[];
10
+ readonly reservedKeys: string[];
11
+ readonly valueKeys: string[];
12
12
  private _values_;
13
13
  private _initialValues_;
14
14
  private _setters_;
@@ -16,14 +16,16 @@ declare class CleanStateBase<TState extends Record<string, any>> {
16
16
  static update: <TState_1 extends object>(this: CleanStateBase<TState_1>) => void;
17
17
  get put(): PutState<TState>;
18
18
  get initialState(): TState;
19
- putMany: (newValues: Partial<TState>) => void;
19
+ readonly putMany: (newValues: Partial<TState>) => void;
20
20
  }
21
- type TCleanStateInstance<TState extends object> = TState & CleanStateBase<TState>;
22
- export type TCleanState<TState extends object> = TCleanStateInstance<TState>;
23
- export type TState<YourCleanState extends CleanStateBase<{}>> = Omit<YourCleanState, keyof CleanStateBase<{}>>;
21
+ export type TStateData = object & {
22
+ [Key in keyof CleanStateBase<{}>]?: never;
23
+ };
24
+ export type TCleanState<TState extends TStateData> = (CleanStateBase<TState> & Omit<TState, keyof CleanStateBase<{}>>);
25
+ export type ExtractCleanStateData<YourCleanState extends CleanStateBase<{}>> = Omit<YourCleanState, keyof CleanStateBase<{}>>;
24
26
  type StateInitFunction = (...args: any[]) => object;
25
27
  type StateInit = object | StateInitFunction;
26
28
  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>>;
29
+ type TUseCleanState = <TInit extends StateInit>(_initialState: TInit, ...props: TInit extends (...args: infer TProps extends any[]) => (infer TState extends object) ? TProps : []) => TCleanState<TInitialState<TInit>>;
28
30
  export declare const useCleanState: TUseCleanState;
29
31
  export {};
@@ -122,17 +122,13 @@ var useCleanState = function (_initialState) {
122
122
  for (var _i = 1; _i < arguments.length; _i++) {
123
123
  props[_i - 1] = arguments[_i];
124
124
  }
125
- var mounted = (0, exports.useMountState)();
126
125
  var initialState = typeof _initialState === 'function'
127
126
  ? (0, react_1.useMemo)(function () { return _initialState.apply(void 0, props); }, [])
128
127
  : _initialState;
129
128
  ;
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;
129
+ var cleanState = (0, react_1.useRef)((0, react_1.useMemo)(function () {
130
+ return new CleanState(initialState);
131
+ }, [])).current;
136
132
  CleanState.update.call(cleanState);
137
133
  return cleanState;
138
134
  };
@@ -1,15 +1,17 @@
1
1
  import type { VoidFunctionComponent } from 'react';
2
2
  import type { IComponentInstanceClass } from './instance';
3
+ import type { TStateData } from '../base';
3
4
  import { ComponentInstance } from './instance';
4
5
  type ComponentClassParams = ConstructorParameters<typeof ClassComponent>;
5
6
  type o = object;
6
7
  export interface IComponentClass<Instance extends ClassComponent<o, o, o> = ClassComponent, Params extends ComponentClassParams = ComponentClassParams> extends IComponentInstanceClass<Instance, Params> {
7
8
  }
8
9
  type Extractor = <TComponent extends typeof ClassComponent<o, o, o>>(this: NonNullable<typeof _Component>, _Component?: TComponent & IComponentClass<InstanceType<TComponent>>) => VoidFunctionComponent<InstanceType<TComponent>['props']>;
9
- export declare class ClassComponent<TProps extends o = EmptyObject, TState extends o = EmptyObject, THooks extends o = EmptyObject> extends ComponentInstance<TProps, TState, THooks> {
10
- Render: VoidFunctionComponent<{}>;
10
+ type ReactTemplate = React.JSX.Element | null;
11
+ export declare class ClassComponent<TProps extends o = EmptyObject, TState extends TStateData = EmptyObject, THooks extends o = EmptyObject> extends ComponentInstance<TProps, TState, THooks> {
12
+ Render?: VoidFunctionComponent<{}>;
13
+ template?: ReactTemplate | (() => ReactTemplate);
11
14
  readonly forceUpdate: VoidFunction;
12
- static renderAs: 'component' | 'template';
13
15
  static readonly FC: Extractor;
14
16
  }
15
17
  interface HookWrapperProps<THookFunction extends AnyFunction> {
@@ -47,21 +47,25 @@ var ClassComponent = /** @class */ (function (_super) {
47
47
  function ClassComponent() {
48
48
  return _super !== null && _super.apply(this, arguments) || this;
49
49
  }
50
- ClassComponent.renderAs = 'component';
51
50
  ClassComponent.FC = function FC(_Component) {
52
51
  var Component = _Component !== null && _Component !== void 0 ? _Component : this;
53
52
  var isClassComponentType = Component.prototype instanceof ClassComponent;
54
53
  if (!Component.getInitialState || !isClassComponentType)
55
54
  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()`).');
56
- var Wrapper = function (props, context) {
55
+ var Wrapper = function (props) {
57
56
  var instance = (0, instance_1.useInstance)(Component, props);
58
- var Render = instance.Render;
57
+ var Render = instance.Render, template = instance.template;
59
58
  var _forceUpdate;
60
59
  // @ts-expect-error (Cannot assign to 'forceUpdate' because it is a read-only property.ts(2540))
61
60
  instance.forceUpdate = (_forceUpdate = useRerender() // Moved this to separate line to allow TS errors. Use proxy local variable to regain some type checking for the assignment.
62
61
  );
63
62
  // Add calling component name to Render function name in stack traces.
64
- (0, react_1.useMemo)(function () { return setFunctionName(Render, "".concat(Component.name, ".Render")); }, [Render]);
63
+ (0, react_1.useMemo)(function () {
64
+ if (typeof template === 'function')
65
+ setFunctionName(template, "".concat(Component.name, ".template"));
66
+ else if (typeof Render === 'function')
67
+ setFunctionName(Render, "".concat(Component.name, ".Render"));
68
+ }, [Render, template]);
65
69
  /**
66
70
  * Normally a component can update it's own state in the "before-render" stage to
67
71
  * skip DOM updates and trigger and immediate rerun of the rendering with the new state.
@@ -80,15 +84,25 @@ var ClassComponent = /** @class */ (function (_super) {
80
84
  * of doing it directly in `Render`. This might mean cleaner Render functions,
81
85
  * so there's probably no real value lost if we keep the component boundary.
82
86
  **/
83
- if (Component.renderAs === 'template')
84
- return Render({}, context);
85
- // With the existence of useContext(),
86
- // what exactly does the context argument to FunctionComponent represent?
87
- // Do we need to find a way to pass that context value to <Render /> here?
88
- return (0, jsx_runtime_1.jsx)(Render, {});
87
+ switch (typeof template) {
88
+ case 'undefined':
89
+ if (typeof Render === 'function')
90
+ return (0, jsx_runtime_1.jsx)(Render, {});
91
+ else
92
+ throw new Error([
93
+ 'A ClassComponent must have either a `template` or a `Render` property. But neither was found.',
94
+ 'Add a `template` member to your class and assign a valid (JSX.Element | null) to it. (or a function that returns that).',
95
+ 'Alternatively, add a `Render` method and assign a FunctionComponent to it.',
96
+ '\n\n',
97
+ 'Expected `Render` to be a Function Component because `template` was `undefined`.',
98
+ "Instead got the following '".concat(typeof Render, "': $o"),
99
+ ].join(' '), Render);
100
+ case 'function': return template();
101
+ default: return template;
102
+ }
89
103
  };
90
104
  // Include calling component name in wrapper function name on stack traces.
91
- setFunctionName(Wrapper, "".concat(Component.name, " < Wrapper")); // ${Wrapper.name}
105
+ setFunctionName(Wrapper, "$".concat(Component.name, "$"));
92
106
  return Wrapper;
93
107
  };
94
108
  return ClassComponent;
@@ -1,9 +1,10 @@
1
+ import { TStateData } from '../base/state';
1
2
  import { ComponentLogic, IComponentLogicClass } from './logic';
2
3
  type AsyncAllowedEffectCallback = () => Awaitable<IVoidFunction>;
3
4
  type UseMountCallbacks = <TInstance extends ComponentInstance<any, any, any>>(instance: TInstance) => void;
4
5
  export declare const useMountCallbacks: UseMountCallbacks;
5
6
  export declare const noOp: () => void;
6
- export declare class ComponentInstance<TProps extends o = EmptyObject, TState extends o = EmptyObject, THooks extends o = EmptyObject> extends ComponentLogic<TProps, TState, THooks> {
7
+ export declare class ComponentInstance<TProps extends o = EmptyObject, TState extends TStateData = EmptyObject, THooks extends o = EmptyObject> extends ComponentLogic<TProps, TState, THooks> {
7
8
  /**
8
9
  * Runs only _before_ first render, i.e before the component instance is mounted.
9
10
  * Useful for logic that is involved in determining what to render.
@@ -150,3 +150,12 @@ var useInstance = function () {
150
150
  return instance;
151
151
  };
152
152
  exports.useInstance = useInstance;
153
+ testing: {
154
+ var A = /** @class */ (function (_super) {
155
+ __extends(A, _super);
156
+ function A() {
157
+ return _super !== null && _super.apply(this, arguments) || this;
158
+ }
159
+ return A;
160
+ }(ComponentInstance));
161
+ }
@@ -1,16 +1,16 @@
1
- import type { TCleanState, TState } from '../base/state';
1
+ import type { TCleanState, ExtractCleanStateData, TStateData } from '../base/state';
2
2
  export type Empty = EmptyObject;
3
3
  type o = object;
4
- export declare class ComponentLogic<TProps extends o = Empty, TState extends o = Empty, THooks extends o = Empty> {
4
+ export declare class ComponentLogic<TProps extends o = Empty, TState extends TStateData = Empty, THooks extends o = Empty> {
5
5
  state: TCleanState<TState>;
6
6
  props: TProps;
7
7
  hooks: THooks;
8
- static getInitialState: (p?: o) => {};
9
- useHooks?: () => THooks;
8
+ static getInitialState: (p?: object) => {};
9
+ useHooks: THooks extends Empty ? undefined | (() => Empty | undefined) : () => THooks;
10
10
  }
11
11
  type LogicClassParams = ConstructorParameters<typeof ComponentLogic>;
12
12
  export interface IComponentLogicClass<Instance extends ComponentLogic<o, o, o> = ComponentLogic, Params extends LogicClassParams = LogicClassParams> extends Constructor<Instance, Params> {
13
- getInitialState: (props?: Instance['props']) => TState<Instance['state']>;
13
+ getInitialState: (props?: Instance['props']) => ExtractCleanStateData<Instance['state']>;
14
14
  }
15
15
  type UseLogic2 = {
16
16
  <Class extends typeof ComponentLogic<Empty, o, o>>(Methods: Class & IComponentLogicClass<InstanceType<Class>>, ...props: ([] | [EmptyObject])): InstanceType<Class>;
@@ -14,6 +14,7 @@ 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 _a;
17
18
  Object.defineProperty(exports, "__esModule", { value: true });
18
19
  exports.useLogic = exports.ComponentLogic = void 0;
19
20
  var react_1 = require("react");
@@ -68,7 +69,9 @@ testing: {
68
69
  return C;
69
70
  }(ComponentLogic));
70
71
  A.getInitialState();
71
- var self_2 = useLogic(A, { a: 'boo' });
72
+ // const oa = {['a' as unknown as symbol]: 'boo'};
73
+ var oa = (_a = {}, _a['a'] = 'boo', _a);
74
+ // const self = useLogic(A, oa);
72
75
  }
73
76
  // export type ComponentClassStatics<Instance extends ComponentLogic<object, object, object>> = {
74
77
  // getInitialState: (props?: Instance['props']) => TState<Instance['state']>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cleanweb/react",
3
- "version": "1.1.1-beta.8",
3
+ "version": "1.1.1-beta.9",
4
4
  "description": "A suite of helpers for writing cleaner React function components.",
5
5
  "engines": {
6
6
  "node": ">=18"