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

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,3 +1,4 @@
1
+ import '../globals';
1
2
  declare class MergedState<TState extends object> {
2
3
  static useRefresh<TState extends object>(this: MergedState<TState>): void;
3
4
  reservedKeys: string[];
@@ -12,6 +12,7 @@ var __assign = (this && this.__assign) || function () {
12
12
  };
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
14
14
  exports.useMergedState = void 0;
15
+ require("../globals");
15
16
  var react_1 = require("react");
16
17
  var MergedState = /** @class */ (function () {
17
18
  function MergedState(initialState) {
@@ -70,7 +71,9 @@ var MergedState = /** @class */ (function () {
70
71
  return MergedState;
71
72
  }());
72
73
  var useMergedState = function (initialState) {
73
- var cleanState = (0, react_1.useMemo)(function () { return new MergedState(initialState); }, []);
74
+ var cleanState = (0, react_1.useMemo)(function () {
75
+ return new MergedState(initialState);
76
+ }, []);
74
77
  MergedState.useRefresh.call(cleanState);
75
78
  return cleanState;
76
79
  };
@@ -1,8 +1,25 @@
1
- import type { TCleanState } from './state';
2
- export declare class ComponentMethods<TState extends object, TProps extends object> {
3
- state: TCleanState<TState>;
4
- props: TProps;
1
+ import type { TCleanState, TStateData } from './state';
2
+ /**
3
+ * Base class for a class that holds methods intended for use in a function component.
4
+ * These methods will have access to the components state and props via
5
+ * `this.state` and `this.props` respectively.
6
+ *
7
+ * Call the {@link useMethods} hook inside your function component to instantiate the class.
8
+ */
9
+ export declare class ComponentMethods<TProps extends object = {}, TState extends TStateData | null = null> {
10
+ readonly props: TProps;
11
+ state: TState extends TStateData ? TCleanState<TState> : null;
5
12
  }
6
- type UseMethods = <TMethods extends typeof ComponentMethods<any, any>, Instance extends InstanceType<TMethods> = InstanceType<TMethods>>(Methods: TMethods & Constructor<InstanceType<TMethods>>, state: InstanceType<TMethods>['state'], props: InstanceType<TMethods>['props']) => InstanceType<TMethods>;
7
- export declare const useMethods: UseMethods;
8
- export {};
13
+ type UseMethods = {
14
+ <Class extends typeof ComponentMethods<object, object>>(Methods: Class & Constructor<InstanceType<Class>>, props: InstanceType<Class>['props'], state: InstanceType<Class>['state']): InstanceType<Class>;
15
+ <Class extends typeof ComponentMethods<object, null>>(Methods: Class & Constructor<InstanceType<Class>>, props: InstanceType<Class>['props'], state?: null): InstanceType<Class>;
16
+ <Class extends typeof ComponentMethods<HardEmptyObject, null>>(Methods: Class & Constructor<InstanceType<Class>>): InstanceType<Class>;
17
+ };
18
+ /**
19
+ * Returns an instance of the provided class,
20
+ * with the state and props arguments added as instance members.
21
+ *
22
+ * `state` must be an instance of `CleanState` created with {@link useCleanState}.
23
+ */
24
+ declare const useMethods: UseMethods;
25
+ export { useMethods };
@@ -1,58 +1,15 @@
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 __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
18
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
19
- return new (P || (P = Promise))(function (resolve, reject) {
20
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
21
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
22
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
23
- step((generator = generator.apply(thisArg, _arguments || [])).next());
24
- });
25
- };
26
- var __generator = (this && this.__generator) || function (thisArg, body) {
27
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
28
- return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
29
- function verb(n) { return function (v) { return step([n, v]); }; }
30
- function step(op) {
31
- if (f) throw new TypeError("Generator is already executing.");
32
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
33
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
34
- if (y = 0, t) op = [op[0] & 2, t.value];
35
- switch (op[0]) {
36
- case 0: case 1: t = op; break;
37
- case 4: _.label++; return { value: op[1], done: false };
38
- case 5: _.label++; y = op[1]; op = [0]; continue;
39
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
40
- default:
41
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
42
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
43
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
44
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
45
- if (t[2]) _.ops.pop();
46
- _.trys.pop(); continue;
47
- }
48
- op = body.call(thisArg, _);
49
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
50
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
51
- }
52
- };
53
2
  Object.defineProperty(exports, "__esModule", { value: true });
54
3
  exports.useMethods = exports.ComponentMethods = void 0;
4
+ // Values
55
5
  var react_1 = require("react");
6
+ /**
7
+ * Base class for a class that holds methods intended for use in a function component.
8
+ * These methods will have access to the components state and props via
9
+ * `this.state` and `this.props` respectively.
10
+ *
11
+ * Call the {@link useMethods} hook inside your function component to instantiate the class.
12
+ */
56
13
  var ComponentMethods = /** @class */ (function () {
57
14
  function ComponentMethods() {
58
15
  }
@@ -60,41 +17,48 @@ var ComponentMethods = /** @class */ (function () {
60
17
  }());
61
18
  exports.ComponentMethods = ComponentMethods;
62
19
  ;
63
- var useMethods = function (Methods, state, props) {
64
- // @todo Switch to useRef. Vite HMR seems to sometimes reinitialize useMemo calls after a hot update,
65
- // causing the instance to be unexpectedly recreated in the middle of the components lifecycle.
20
+ /**
21
+ * Returns an instance of the provided class,
22
+ * with the state and props arguments added as instance members.
23
+ *
24
+ * `state` must be an instance of `CleanState` created with {@link useCleanState}.
25
+ */
26
+ var useMethods = function () {
27
+ var args = [];
28
+ for (var _i = 0; _i < arguments.length; _i++) {
29
+ args[_i] = arguments[_i];
30
+ }
31
+ var Methods = args[0], _a = args[1], props = _a === void 0 ? {} : _a, state = args[2];
32
+ // Vite HMR seems to sometimes reinitialize useMemo calls after a hot update,
33
+ // causing the instance to be unexpectedly recreated in the middle of the component's lifecycle.
66
34
  // But useRef and useState values appear to always be preserved whenever this happens.
67
35
  // So those two are the only cross-render-persistence methods we can consider safe.
36
+ // @todo Provide a way for users to reflect updated methods code on the existing instance after HMR.
68
37
  var methods = (0, react_1.useRef)((0, react_1.useMemo)(function () {
69
- // See useLogic implementation for a discussion of this type assertion.
70
38
  return new Methods();
71
39
  }, [])).current;
72
- methods.state = state;
73
- methods.props = props;
40
+ /** A proxy variable to allow typechecking of the assignment to methods.props despite the need for "readonly" error suppression. */
41
+ var _propsProxy_;
42
+ // @ts-expect-error
43
+ methods.props = (_propsProxy_ = props);
44
+ if (state)
45
+ methods.state = state;
74
46
  return methods;
75
47
  };
76
48
  exports.useMethods = useMethods;
77
- testing: {
78
- var a = function () { return __awaiter(void 0, void 0, void 0, function () {
79
- var a, MyMethods, useCleanState, self;
80
- return __generator(this, function (_a) {
81
- switch (_a.label) {
82
- case 0:
83
- a = { b: '' };
84
- MyMethods = /** @class */ (function (_super) {
85
- __extends(MyMethods, _super);
86
- function MyMethods() {
87
- return _super !== null && _super.apply(this, arguments) || this;
88
- }
89
- return MyMethods;
90
- }(ComponentMethods));
91
- ;
92
- return [4 /*yield*/, import('./state.js')];
93
- case 1:
94
- useCleanState = (_a.sent()).useCleanState;
95
- self = (0, exports.useMethods)(MyMethods, useCleanState({}), {});
96
- return [2 /*return*/];
97
- }
98
- });
99
- }); };
100
- }
49
+ /*testing: {
50
+ let a = async () => {
51
+ const a: object = {b: ''};
52
+
53
+ type t = keyof typeof a;
54
+
55
+ class MyMethods extends ComponentMethods<WeakEmptyObject, null> {
56
+ // static getInitialState = () => ({});
57
+ };
58
+
59
+ const { useCleanState } = (await import('./state.js'));
60
+
61
+ const self = useMethods(MyMethods, {});
62
+ self.state;
63
+ }
64
+ }*/
@@ -1,3 +1,4 @@
1
+ import '../globals';
1
2
  /**
2
3
  * Returns a value that is false before the component has been mounted,
3
4
  * then true during all subsequent rerenders.
@@ -7,8 +8,8 @@ type PutState<TState extends object> = {
7
8
  [Key in keyof TState]: React.Dispatch<React.SetStateAction<TState[Key]>>;
8
9
  };
9
10
  declare class CleanStateBase<TState extends Record<string, any>> {
10
- reservedKeys: string[];
11
- valueKeys: string[];
11
+ readonly reservedKeys: string[];
12
+ readonly valueKeys: string[];
12
13
  private _values_;
13
14
  private _initialValues_;
14
15
  private _setters_;
@@ -16,14 +17,20 @@ declare class CleanStateBase<TState extends Record<string, any>> {
16
17
  static update: <TState_1 extends object>(this: CleanStateBase<TState_1>) => void;
17
18
  get put(): PutState<TState>;
18
19
  get initialState(): TState;
19
- putMany: (newValues: Partial<TState>) => void;
20
+ readonly putMany: (newValues: Partial<TState>) => void;
20
21
  }
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<{}>>;
22
+ export type TStateData = object & {
23
+ [Key in keyof CleanStateBase<{}>]?: never;
24
+ };
25
+ export type TCleanState<TState extends TStateData> = (CleanStateBase<TState> & Omit<TState, keyof CleanStateBase<{}>>);
26
+ export type ExtractCleanStateData<YourCleanState extends CleanStateBase<{}>> = Omit<YourCleanState, keyof CleanStateBase<{}>>;
24
27
  type StateInitFunction = (...args: any[]) => object;
25
28
  type StateInit = object | StateInitFunction;
26
29
  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>>;
30
+ type TUseCleanState = <TInit extends StateInit>(_initialState: TInit, ...props: TInit extends (...args: infer TProps extends any[]) => (infer TState extends object) ? TProps : []) => TCleanState<TInitialState<TInit>>;
31
+ /**
32
+ * Creates a state object, which includes the provided values, and helper methods for
33
+ * updating those values and automatically rerendering your component's UI accordingly.
34
+ */
28
35
  export declare const useCleanState: TUseCleanState;
29
36
  export {};
@@ -12,6 +12,7 @@ var __assign = (this && this.__assign) || function () {
12
12
  };
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
14
14
  exports.useCleanState = exports.useMountState = void 0;
15
+ require("../globals");
15
16
  var react_1 = require("react");
16
17
  /**
17
18
  * Returns a value that is false before the component has been mounted,
@@ -117,22 +118,22 @@ var CleanStateBase = /** @class */ (function () {
117
118
  }());
118
119
  ;
119
120
  var CleanState = CleanStateBase;
121
+ /**
122
+ * Creates a state object, which includes the provided values, and helper methods for
123
+ * updating those values and automatically rerendering your component's UI accordingly.
124
+ */
120
125
  var useCleanState = function (_initialState) {
121
126
  var props = [];
122
127
  for (var _i = 1; _i < arguments.length; _i++) {
123
128
  props[_i - 1] = arguments[_i];
124
129
  }
125
- var mounted = (0, exports.useMountState)();
126
130
  var initialState = typeof _initialState === 'function'
127
131
  ? (0, react_1.useMemo)(function () { return _initialState.apply(void 0, props); }, [])
128
132
  : _initialState;
129
133
  ;
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;
134
+ var cleanState = (0, react_1.useRef)((0, react_1.useMemo)(function () {
135
+ return new CleanState(initialState);
136
+ }, [])).current;
136
137
  CleanState.update.call(cleanState);
137
138
  return cleanState;
138
139
  };
@@ -1,16 +1,117 @@
1
1
  import type { VoidFunctionComponent } from 'react';
2
+ import type { TStateData } from '../base';
3
+ import type { IComponentInstanceClass } from './instance';
2
4
  import { ComponentInstance } from './instance';
3
- type Extractor = <TComponent extends typeof ClassComponent<object, object, object>>(this: TComponent & Constructor<InstanceType<TComponent>>, _Component?: TComponent & Constructor<InstanceType<TComponent>>) => VoidFunctionComponent<InstanceType<TComponent>['props']>;
4
- export declare class ClassComponent<TState extends object = EmptyObject, TProps extends object = EmptyObject, THooks extends object = EmptyObject> extends ComponentInstance<TState, TProps, THooks> {
5
- Render: VoidFunctionComponent<{}>;
6
- static renderAs: 'component' | 'template';
7
- static FC: Extractor;
5
+ import { THooksBase } from './logic';
6
+ export declare const useRerender: () => () => void;
7
+ type ComponentClassParams = ConstructorParameters<typeof ClassComponent>;
8
+ type o = object;
9
+ export interface IComponentClass<Instance extends ClassComponent<o, o, THooksBase> = ClassComponent, Params extends ComponentClassParams = ComponentClassParams> extends IComponentInstanceClass<Instance, Params> {
10
+ }
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;
13
+ /**
14
+ * A superset of {@link ComponentInstance} that allows defining your
15
+ * component's JSX template directly inside the class.
16
+ *
17
+ * This is designed to closely resemble the old {@link React.Component} class,
18
+ * making it easier to migrate older class components to the newer hooks-based system
19
+ * with little to no changes to their existing semantics/implementation.
20
+ */
21
+ export declare class ClassComponent<TProps extends o = WeakEmptyObject, TState extends TStateData = WeakEmptyObject, THooks extends THooksBase = void> extends ComponentInstance<TProps, TState, THooks> {
22
+ /**
23
+ * @deprecated An older alternative to {@link template}.
24
+ *
25
+ * Using this will add a component boundary between your JSX template
26
+ * and the function component returned from ClassComponent.FC();
27
+ *
28
+ * This means that from React's perspective, your template won't "own" the state and props it consumes.
29
+ * This could lead to subtle unexpected changes in behaviour.
30
+ *
31
+ * In most cases, you should use {@link template} instead, as it allows your class component
32
+ * to function more predictably as a single unit.
33
+ */
34
+ Render?: VoidFunctionComponent<{}>;
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
+ template?: () => ReactTemplate;
67
+ /**
68
+ * Manually trigger a rerender of your component.
69
+ * You should rarely ever need this. But if you are migrating
70
+ * an older React.Component class, this should provide similar functionality
71
+ * to the {@link Component.forceUpdate | `forceUpdate`} method provided there.
72
+ *
73
+ * Note that the callback argument is currently not supported.
74
+ */
75
+ readonly forceUpdate: VoidFunction;
76
+ /*************************************
77
+ * Function Component Extractor *
78
+ **************************************/
79
+ /**
80
+ * Extract a function component which can be used to render
81
+ * your ClassComponent just like any other component.
82
+ *
83
+ * Each JSX reference to this returned component will render with
84
+ * a separate instance of your class.
85
+ *
86
+ * So you only need to call `YourClassComponent.FC()` once, then use the returned
87
+ * function component as many times as you need.
88
+ */
89
+ static readonly FC: Extractor;
8
90
  }
9
91
  interface HookWrapperProps<THookFunction extends AnyFunction> {
92
+ /**
93
+ * The React hook you which to consume.
94
+ * Render a separate instance of the `<Use />` component for each hook.
95
+ * You can also create a custom hook that combines multiple hooks,
96
+ * then use that wrapper hook with a single `<Use />` instance.
97
+ */
10
98
  hook: THookFunction;
99
+ /**
100
+ * An array containing the list of arguments
101
+ * to be passed to your hook, in the right order.
102
+ */
11
103
  argumentsList: Parameters<THookFunction>;
104
+ /**
105
+ * A callback that will be called with whatever value your hook returns.
106
+ * Use this to update your component's state with the value.
107
+ * This will allow your component to rerender whenever the hook returns a new value.
108
+ */
12
109
  onUpdate: (output: ReturnType<THookFunction>) => void;
13
110
  }
14
111
  type ClassComponentHookWrapper = <Hook extends AnyFunction>(props: HookWrapperProps<Hook>) => null;
112
+ /**
113
+ * A component you can use to consume hooks
114
+ * in a {@link Component | React.Component} class component.
115
+ */
15
116
  export declare const Use: ClassComponentHookWrapper;
16
117
  export {};
@@ -15,7 +15,7 @@ var __extends = (this && this.__extends) || (function () {
15
15
  };
16
16
  })();
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.Use = exports.ClassComponent = void 0;
18
+ exports.Use = exports.ClassComponent = exports.useRerender = void 0;
19
19
  var jsx_runtime_1 = require("react/jsx-runtime");
20
20
  var react_1 = require("react");
21
21
  var instance_1 = require("./instance");
@@ -32,22 +32,68 @@ var setFunctionName = function (func, newName) {
32
32
  console.warn(error);
33
33
  }
34
34
  };
35
- // eslint-enable no-use-before-define
35
+ var useRerender = function () {
36
+ /*
37
+ * Skip the value, we don't need it.
38
+ * Grab just the setter function.
39
+ */
40
+ var _a = (0, react_1.useState)(Date.now()), _forceRerender = _a[1];
41
+ var rerender = function () { return _forceRerender(Date.now()); };
42
+ return rerender;
43
+ };
44
+ exports.useRerender = useRerender;
45
+ ;
46
+ /**
47
+ * A superset of {@link ComponentInstance} that allows defining your
48
+ * component's JSX template directly inside the class.
49
+ *
50
+ * This is designed to closely resemble the old {@link React.Component} class,
51
+ * making it easier to migrate older class components to the newer hooks-based system
52
+ * with little to no changes to their existing semantics/implementation.
53
+ */
36
54
  var ClassComponent = /** @class */ (function (_super) {
37
55
  __extends(ClassComponent, _super);
38
56
  function ClassComponent() {
39
57
  return _super !== null && _super.apply(this, arguments) || this;
40
58
  }
41
- ClassComponent.renderAs = 'component';
59
+ /*************************************
60
+ * Function Component Extractor *
61
+ **************************************/
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
+ /**
65
+ * Extract a function component which can be used to render
66
+ * your ClassComponent just like any other component.
67
+ *
68
+ * Each JSX reference to this returned component will render with
69
+ * a separate instance of your class.
70
+ *
71
+ * So you only need to call `YourClassComponent.FC()` once, then use the returned
72
+ * function component as many times as you need.
73
+ */
42
74
  ClassComponent.FC = function FC(_Component) {
43
75
  var Component = _Component !== null && _Component !== void 0 ? _Component : this;
44
76
  var isClassComponentType = Component.prototype instanceof ClassComponent;
45
77
  if (!Component.getInitialState || !isClassComponentType)
46
78
  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()`).');
47
- var Wrapper = function (props, context) {
48
- var Render = (0, instance_1.useInstance)(Component, props).Render;
79
+ /*************************************
80
+ * Begin Function Component *
81
+ **************************************/
82
+ /** A class-based React function component created with (@cleanweb/react).ClassComponent */
83
+ var Wrapper = function (props) {
84
+ var instance = (0, instance_1.useInstance)(Component, props);
85
+ var Render = instance.Render, template = instance.template;
86
+ var _forceUpdate;
87
+ // @ts-expect-error (Cannot assign to 'forceUpdate' because it is a read-only property.ts(2540))
88
+ instance.forceUpdate = (_forceUpdate = (0, exports.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`.
89
+ );
49
90
  // Add calling component name to Render function name in stack traces.
50
- (0, react_1.useMemo)(function () { return setFunctionName(Render, "".concat(Component.name, ".Render")); }, [Render]);
91
+ (0, react_1.useMemo)(function () {
92
+ if (typeof template === 'function')
93
+ setFunctionName(template, "".concat(Component.name, ".template"));
94
+ else if (typeof Render === 'function')
95
+ setFunctionName(Render, "".concat(Component.name, ".Render"));
96
+ }, [Render, template]);
51
97
  /**
52
98
  * Normally a component can update it's own state in the "before-render" stage to
53
99
  * skip DOM updates and trigger and immediate rerun of the rendering with the new state.
@@ -58,28 +104,48 @@ var ClassComponent = /** @class */ (function (_super) {
58
104
  * state in the "before-render" stage of `Render`, since it will be attempting to update it's parent's
59
105
  * state (i.e `Wrapper` component) rather than it's own state.
60
106
  *
61
- * Consider using this as a function call instead of JSX to avoid that. This way, we avoid
107
+ * Users should favor using the `template()` method instead. This way, we avoid
62
108
  * establishing a component boundary between `Wrapper` and `Render`.
63
109
  *
64
110
  * Although, since beforeRender() is called earlier from a hook, this is probably
65
111
  * 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.
112
+ * of doing it directly in `Render`. Even if `template` is being used, the `beforeRender` method
113
+ * is the preferred location for such logic to maintain a high level of separation of concerns,
114
+ * which is what this library exists to provide.
115
+ *
116
+ * So there's probably no real value lost with the component boundary. Users should just use
117
+ * `beforeRender` + `template`.
68
118
  **/
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, {});
119
+ switch (typeof template) {
120
+ case 'undefined':
121
+ if (typeof Render === 'function')
122
+ return (0, jsx_runtime_1.jsx)(Render, {});
123
+ else
124
+ throw new Error([
125
+ 'A ClassComponent must have either a `template` or a `Render` property. But neither was found.',
126
+ 'Add a `template: (JSX.Element | null);` member to your class, (or a `template` method that returns the same type).',
127
+ 'Alternatively, add a `Render: FunctionComponent;` method.',
128
+ '\n\n',
129
+ 'Expected `Render` to be a Function Component because `template` was `undefined`.',
130
+ "Instead got the following '".concat(typeof Render, "': $o"),
131
+ ].join(' '), Render);
132
+ case 'function': return template();
133
+ default: return template;
134
+ }
75
135
  };
76
- // Include calling component name in wrapper function name on stack traces.
77
- setFunctionName(Wrapper, "".concat(Component.name, " < Wrapper")); // ${Wrapper.name}
136
+ /*************************************
137
+ * End Function Component *
138
+ **************************************/
139
+ setFunctionName(Wrapper, "$".concat(Component.name, "$"));
78
140
  return Wrapper;
79
141
  };
80
142
  return ClassComponent;
81
143
  }(instance_1.ComponentInstance));
82
144
  exports.ClassComponent = ClassComponent;
145
+ /**
146
+ * A component you can use to consume hooks
147
+ * in a {@link Component | React.Component} class component.
148
+ */
83
149
  var Use = function (params) {
84
150
  var useGenericHook = params.hook, argumentsList = params.argumentsList, onUpdate = params.onUpdate;
85
151
  var output = useGenericHook.apply(void 0, argumentsList);
@@ -1,7 +1,15 @@
1
+ import type { TStateData } from '../base/state';
2
+ import type { THooksBase, IComponentLogicClass } from './logic';
1
3
  import { ComponentLogic } from './logic';
2
4
  type AsyncAllowedEffectCallback = () => Awaitable<IVoidFunction>;
5
+ /** An empty function. It returns (void) without performing any operations. */
3
6
  export declare const noOp: () => void;
4
- export declare class ComponentInstance<TState extends object = EmptyObject, TProps extends object = EmptyObject, THooks extends object = EmptyObject> extends ComponentLogic<TState, TProps, THooks> {
7
+ /**
8
+ * A superset of {@link ComponentLogic} that adds support for special lifecycle methods.
9
+ * This provides a declarative API for working with your React function component's lifecycle,
10
+ * a simpler alternative to the imperative approach with `useEffect` and/or `useMemo`.
11
+ */
12
+ export declare class ComponentInstance<TProps extends o = {}, TState extends TStateData = WeakEmptyObject, THooks extends THooksBase = void> extends ComponentLogic<TProps, TState, THooks> {
5
13
  /**
6
14
  * Runs only _before_ first render, i.e before the component instance is mounted.
7
15
  * Useful for logic that is involved in determining what to render.
@@ -46,17 +54,13 @@ export declare class ComponentInstance<TState extends object = EmptyObject, TPro
46
54
  */
47
55
  cleanUp: IVoidFunction;
48
56
  }
49
- type UseInstance = <TClass extends typeof ComponentInstance<object, object, object>>(Class: TClass & Constructor<InstanceType<TClass>>, ...props: valueof<InstanceType<TClass>['props']> extends never ? ([] | [EmptyObject] | [InstanceType<TClass>['props']]) : [InstanceType<TClass>['props']]) => InstanceType<TClass>;
50
- /**
51
- * To ensure successful type checking, the second parameter must be written with spread syntax.
52
- * Likely because of the `exactOptionalPropertyTypes` config option turned on,
53
- * and `UseInstance` using an empty tuple in its rest parameter type, attempting to simply
54
- * retrieve the second argument directly causes an error when that argument is passed on to `useLogic`.
55
- * But directly working with the rest array bypasses the problem. Also note that the issue persists even when
56
- * the second param is given `{}` as a default follow to account for the empty tuple case. TypeScript
57
- * just wants us to use the rest parameter explicitly by force.
58
- */
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> {
60
+ }
61
+ 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>;
64
+ };
59
65
  export declare const useInstance: UseInstance;
60
- type UseMountCallbacks = <TInstance extends ComponentInstance<any, any, any>>(instance: TInstance) => void;
61
- export declare const useMountCallbacks: UseMountCallbacks;
62
66
  export {};
@@ -14,22 +14,44 @@ 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
- };
26
17
  Object.defineProperty(exports, "__esModule", { value: true });
27
- exports.useMountCallbacks = exports.useInstance = exports.ComponentInstance = exports.noOp = void 0;
18
+ exports.useInstance = exports.ComponentInstance = exports.noOp = void 0;
28
19
  var react_1 = require("react");
29
20
  var state_1 = require("../base/state");
30
21
  var logic_1 = require("./logic");
22
+ var useMountCallbacks = function (instance) {
23
+ var _a;
24
+ var mounted = (0, state_1.useMountState)();
25
+ if (!mounted)
26
+ (_a = instance.beforeMount) === null || _a === void 0 ? void 0 : _a.call(instance);
27
+ (0, react_1.useEffect)(function () {
28
+ var _a;
29
+ var mountHandlerCleanUp = (_a = instance.onMount) === null || _a === void 0 ? void 0 : _a.call(instance);
30
+ return function () {
31
+ var doCleanUp = function (runMountCleaners) {
32
+ var _a;
33
+ runMountCleaners === null || runMountCleaners === void 0 ? void 0 : runMountCleaners();
34
+ // onDismount? willUnmount?
35
+ (_a = instance.cleanUp) === null || _a === void 0 ? void 0 : _a.call(instance);
36
+ };
37
+ if (typeof mountHandlerCleanUp === 'function') {
38
+ doCleanUp(mountHandlerCleanUp);
39
+ }
40
+ else {
41
+ mountHandlerCleanUp === null || mountHandlerCleanUp === void 0 ? void 0 : mountHandlerCleanUp.then(doCleanUp);
42
+ }
43
+ };
44
+ }, []);
45
+ };
46
+ /** An empty function. It returns (void) without performing any operations. */
31
47
  var noOp = function () { };
32
48
  exports.noOp = noOp;
49
+ // @todo Use rollup. Insert globals.ts reference tag to all d.ts output files.
50
+ /**
51
+ * A superset of {@link ComponentLogic} that adds support for special lifecycle methods.
52
+ * This provides a declarative API for working with your React function component's lifecycle,
53
+ * a simpler alternative to the imperative approach with `useEffect` and/or `useMemo`.
54
+ */
33
55
  var ComponentInstance = /** @class */ (function (_super) {
34
56
  __extends(ComponentInstance, _super);
35
57
  function ComponentInstance() {
@@ -83,7 +105,8 @@ var ComponentInstance = /** @class */ (function (_super) {
83
105
  }(logic_1.ComponentLogic));
84
106
  exports.ComponentInstance = ComponentInstance;
85
107
  ;
86
- /**
108
+ ;
109
+ /*
87
110
  * To ensure successful type checking, the second parameter must be written with spread syntax.
88
111
  * Likely because of the `exactOptionalPropertyTypes` config option turned on,
89
112
  * and `UseInstance` using an empty tuple in its rest parameter type, attempting to simply
@@ -92,14 +115,15 @@ exports.ComponentInstance = ComponentInstance;
92
115
  * the second param is given `{}` as a default follow to account for the empty tuple case. TypeScript
93
116
  * just wants us to use the rest parameter explicitly by force.
94
117
  */
95
- var useInstance = function (Component) {
118
+ var useInstance = function () {
96
119
  var _a;
97
120
  var args = [];
98
- for (var _i = 1; _i < arguments.length; _i++) {
99
- args[_i - 1] = arguments[_i];
121
+ for (var _i = 0; _i < arguments.length; _i++) {
122
+ args[_i] = arguments[_i];
100
123
  }
124
+ var Component = args[0], _b = args[1], props = _b === void 0 ? {} : _b;
101
125
  // 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.
126
+ var instance = (0, logic_1.useLogic)(Component, props);
103
127
  /**
104
128
  * Argument of type '
105
129
  * [
@@ -115,8 +139,7 @@ var useInstance = function (Component) {
115
139
  '
116
140
  */
117
141
  // beforeMount, onMount, cleanUp.
118
- // eslint-disable-next-line no-use-before-define
119
- (0, exports.useMountCallbacks)(instance);
142
+ useMountCallbacks(instance);
120
143
  // beforeRender.
121
144
  (_a = instance.beforeRender) === null || _a === void 0 ? void 0 : _a.call(instance);
122
145
  // onRender.
@@ -133,28 +156,21 @@ var useInstance = function (Component) {
133
156
  return instance;
134
157
  };
135
158
  exports.useInstance = useInstance;
136
- var useMountCallbacks = function (instance) {
137
- var _a;
138
- var mounted = (0, state_1.useMountState)();
139
- if (!mounted)
140
- (_a = instance.beforeMount) === null || _a === void 0 ? void 0 : _a.call(instance);
141
- (0, react_1.useEffect)(function () {
142
- var _a;
143
- var mountHandlerCleanUp = (_a = instance.onMount) === null || _a === void 0 ? void 0 : _a.call(instance);
144
- return function () {
145
- var doCleanUp = function (runMountCleaners) {
146
- var _a;
147
- runMountCleaners === null || runMountCleaners === void 0 ? void 0 : runMountCleaners();
148
- // onDismount? willUnmount?
149
- (_a = instance.cleanUp) === null || _a === void 0 ? void 0 : _a.call(instance);
150
- };
151
- if (typeof mountHandlerCleanUp === 'function') {
152
- doCleanUp(mountHandlerCleanUp);
153
- }
154
- else {
155
- mountHandlerCleanUp === null || mountHandlerCleanUp === void 0 ? void 0 : mountHandlerCleanUp.then(doCleanUp);
156
- }
157
- };
158
- }, []);
159
- };
160
- exports.useMountCallbacks = useMountCallbacks;
159
+ /*testing: {
160
+ class A extends ComponentInstance {
161
+ static getInitialState: (p?: object) => ({putan: ''});
162
+ // k = this.props.o
163
+ a = this.state['_initialValues_']
164
+
165
+ // hard empty has every key
166
+ // weak empty has no key
167
+ // weak empty is not assignable to hard empty
168
+ }
169
+
170
+ const p = {k: ''}
171
+ const a = useInstance(A, {o: ''});
172
+
173
+ // a.props['o'];
174
+ type bbbb = A['state'];
175
+ type ttt = bbbb['put'];
176
+ }*/
@@ -1,23 +1,57 @@
1
- import type { TCleanState, TState } from '../base/state';
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;
2
5
  type o = object;
3
- export declare class ComponentLogic<TState_ extends object = EmptyObject, TProps extends object = EmptyObject, THooks extends object = EmptyObject> {
4
- state: TCleanState<TState_>;
5
- props: TProps;
6
- hooks: THooks;
7
- static getInitialState: <ThisT extends typeof ComponentLogic<o, o, o>>(this: ThisT, props?: InstanceType<ThisT>['props']) => TState<InstanceType<ThisT>['state']> & any;
8
- useHooks?: () => THooks;
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;
9
47
  }
10
- type CnstPrm = ConstructorParameters<typeof ComponentLogic>;
11
- export interface IComponentClass<Instance extends ComponentLogic = ComponentLogic> {
12
- new (...params: CnstPrm): Instance;
13
- getInitialState: (props?: Instance['props']) => TState<Instance['state']>;
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']>;
14
51
  }
15
- export type ComponentClassStatics<Instance extends ComponentLogic<object, object, object>> = {
16
- getInitialState: (props?: Instance['props']) => TState<Instance['state']>;
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>;
17
55
  };
18
- export type TComponentClass<Instance extends ComponentLogic<object, object, object>, Statics extends ComponentClassStatics<Instance> = ComponentClassStatics<Instance>, Params extends CnstPrm = CnstPrm> = Statics & Constructor<Instance, Params>;
19
- export interface IEmpty extends EmptyObject {
20
- }
21
- type UseLogic = <Class extends typeof ComponentLogic<object, object, object>, Instance extends InstanceType<Class> = InstanceType<Class>>(Methods: Class & Constructor<Instance>, ...props: valueof<Instance['props']> extends never ? ([] | [EmptyObject] | [Instance['props']]) : [Instance['props']]) => Instance;
22
- export declare const useLogic: UseLogic;
23
- export {};
56
+ declare const useLogic: UseLogic;
57
+ export { useLogic };
@@ -1,67 +1,81 @@
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;
18
2
  Object.defineProperty(exports, "__esModule", { value: true });
19
3
  exports.useLogic = exports.ComponentLogic = void 0;
20
4
  var react_1 = require("react");
21
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
+ */
22
18
  var ComponentLogic = /** @class */ (function () {
23
19
  function ComponentLogic() {
24
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 ({}); };
25
27
  return ComponentLogic;
26
28
  }());
27
29
  exports.ComponentLogic = ComponentLogic;
28
30
  ;
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
- ;
42
- var useLogic = function (Methods, props) {
43
- var _b;
44
- if (props === void 0) { props = {}; }
45
- var state = (0, state_1.useCleanState)(Methods.getInitialState, props);
46
- var methods = (0, react_1.useRef)((0, react_1.useMemo)(function () {
47
- return new Methods();
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();
48
41
  }, [])).current;
49
- methods.state = state;
50
- methods.props = props;
51
- methods.hooks = ((_b = methods.useHooks) === null || _b === void 0 ? void 0 : _b.call(methods)) || {};
52
- return methods;
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
53
  };
54
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
- var self_1 = (0, exports.useLogic)(MyComponentLogic);
67
- }
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
+ }*/
@@ -1,24 +1,4 @@
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
- *
9
- * @example
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
- * }
19
- * }
20
- **/
21
- /** */
1
+ declare const UniqueSecretSymbolKey: unique symbol;
22
2
  declare global {
23
3
  type Optional<BaseType, AllowNull extends boolean = true> = (AllowNull extends true ? BaseType | undefined | null : BaseType | undefined);
24
4
  type Awaitable<Type> = Type | Promise<Type>;
@@ -42,6 +22,15 @@ declare global {
42
22
  type AnyFunction = (...args: any) => any;
43
23
  type FunctionType = AnyFunction;
44
24
  type TFunction = AnyFunction;
25
+ type NotNullish = {};
26
+ type NonPrimitive = object;
27
+ interface WeakEmptyObject {
28
+ [UniqueSecretSymbolKey]?: never;
29
+ }
30
+ interface HardEmptyObject {
31
+ [key: keyof any]: never;
32
+ }
33
+ type valueof<TObject> = TObject[keyof TObject];
45
34
  interface Window {
46
35
  }
47
36
  namespace JSX {
@@ -52,16 +41,5 @@ declare global {
52
41
  interface ProcessEnv {
53
42
  }
54
43
  }
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
- }
66
44
  }
67
45
  export {};
package/build/globals.js CHANGED
@@ -1,22 +1,4 @@
1
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
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ /////////////
4
+ var UniqueSecretSymbolKey = Symbol('asdfghjkliuytrewqaxcvb,nb');
package/build/index.d.ts CHANGED
@@ -1 +1 @@
1
- export * from "./classy";
1
+ export * from './classy';
package/build/index.js CHANGED
@@ -16,7 +16,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./classy"), exports);
18
18
  // PS: Document component inheritance pattern with lifecycle callback arrays and namespaces.
19
- // Due to react's remounting behaviour, components must externally track when some logic has run, if it really really must only ever run once per mounted instance. Tricky to get right for components that may have multiple instance rendered simultaneously at different parts of a page.
19
+ // Due to react's remounting behaviour, components must externally track when some logic has run,
20
+ // if it really really must only ever run once per mounted instance. Tricky to get right for components that may have multiple instance rendered simultaneously at different parts of a page.
20
21
  // useCleanState => useState, separate call for each key
21
22
  // useMergedState => useState, same call for all keys
22
23
  // useMethods => useCallback
@@ -32,13 +32,15 @@
32
32
  "noImplicitAny": true,
33
33
  "noUncheckedIndexedAccess": true,
34
34
  "strictBindCallApply": true,
35
- // "exactOptionalPropertyTypes": true
35
+ "exactOptionalPropertyTypes": true,
36
36
  },
37
37
  "include": [
38
+ // "**/[!globals].ts",
38
39
  "**/*.ts",
39
40
  "**/*.tsx"
40
41
  ],
41
42
  "exclude": [
43
+ "**/globals.ts",
42
44
  "node_modules/**/**.*",
43
45
  "build/**/**.*",
44
46
  "mirror-pkg/**/**.*"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cleanweb/react",
3
- "version": "1.1.1-beta.2",
3
+ "version": "1.1.1-beta.21",
4
4
  "description": "A suite of helpers for writing cleaner React function components.",
5
5
  "engines": {
6
6
  "node": ">=18"
@@ -30,7 +30,7 @@
30
30
  "scripts": {
31
31
  "prebuild": "rimraf ./build",
32
32
  "build": "tsc && tsc-alias",
33
- "postbuild": "copyfiles globals.d.ts tsconfig.json build",
33
+ "postbuild": "copyfiles tsconfig.json build",
34
34
  "_": "",
35
35
  "prepublishOnly": "npm run build",
36
36
  "publish:patch": "npm version patch && npm publish",
@@ -1,48 +0,0 @@
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 {};
@@ -1,40 +0,0 @@
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
- }