@webkrafters/react-observable-context 6.0.6 → 7.0.0-rc.1

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
@@ -25,36 +25,151 @@
25
25
  <table BORDER-COLOR="0a0" BORDER-WIDTH="2">
26
26
  <td VALIGN="middle" ALIGN="center" FONT-WEIGHT="BOLD" COLOR="#333" HEIGHT="250px" width="1250px">
27
27
  COMPATIBLE WITH REACT VERSIONS 16.8 to 18.x.x.<br />
28
- A VERSION 7.0.0 FOR REACT 19+ IS CURRENTLY UNDER DEVELOPMENT.
28
+ A NEW EAGLEEYE BASED PRODUCT WILL BE DEVELOPED SPECIFICALLY FOR REACT 19+<br /><br />
29
+ PLEASE STAY TUNED.
29
30
  </td>
30
31
  </table>
31
32
 
32
33
  <ul>
33
- <li> Auto-immutable update-friendly context. See <a href="https://eagleeye.js.org/concepts/store/setstate"><code>store.setState</code></a>.</li>
34
- <li> A context bearing an observable consumer <a href="https://eagleeye.js.org/concepts/store">store</a>.</li>
35
- <li> Recognizes <b>negative array indexing</b>. Please see <a href="https://eagleeye.js.org/concepts/property-path">Property Path</a> and <code>store.setState</code> <a href="https://eagleeye.js.org/concepts/store/setstate#indexing">Indexing</a>.</li>
36
- <li> Only re-renders subscribing components (<a href="https://eagleeye.js.org/concepts/client">clients</a>) on context state changes.</li>
34
+ <li> Ready for use anywhere in the app. No Provider components needed.</li>
35
+ <li> Auto-immutable update-friendly context. See <a href="https://eagleeye.js.org/concepts/store/setstate"><code>store.setState</code> (under revision)</a>.</li>
36
+ <li> A context bearing an observable consumer <a href="https://eagleeye.js.org/concepts/store">store (under revision)</a>.</li>
37
+ <li> Recognizes <b>negative array indexing</b>. Please see <a href="https://eagleeye.js.org/concepts/property-path">Property Path (under revision)</a> and <code>store.setState</code> <a href="https://eagleeye.js.org/concepts/store/setstate#indexing">Indexing (under revision)</a>.</li>
38
+ <li> Only re-renders subscribing components (<a href="https://eagleeye.js.org/concepts/client">clients (under revision)</a>) on context state changes.</li>
37
39
  <li> Subscribing component decides which context state properties' changes to trigger its update.</li>
38
40
  </ul>
39
41
 
40
42
  **Name:** React-Observable-Context
41
43
 
42
- **Moniker:** Eagle Eye
44
+ **Moniker:** Legacy Eagle Eye
43
45
 
44
- **Usage:** Please see <b><a href="https://eagleeye.js.org/getting-started">Getting Started</a></b>.
46
+ **Usage:** Please see <b><a href="https://eagleeye.js.org/getting-started">Getting Started (under revision)</a></b>.
45
47
 
46
- **Demo:** [Play with the app on codesandbox](https://codesandbox.io/s/github/webKrafters/react-observable-context-app)\
48
+ **Demo:** [Play with the app on codesandbox (under revision)](https://codesandbox.io/s/github/webKrafters/react-observable-context-app)\
47
49
  If sandbox fails to load app, please refresh dependencies on its lower left.
48
50
 
49
51
  **Install:**\
50
- npm i -S @webkrafters/react-observable-context\
51
- Defunct: npm i -S react-eagleeye
52
+ npm install --save @webkrafters/react-observable-context\
52
53
 
53
- May also see <b><a href="https://eagleeye.js.org/history/features">What's Changed?</a></b>
54
+ ## Usage:
55
+
56
+ ```tsx
57
+ import { FC } from 'react';
58
+ import { createEagleEye } from '@webkrafters/react-observable-context';
59
+
60
+ const context = createEagleEye(
61
+ T|AutoImmutable<T>?,
62
+ Prehooks<T>?,
63
+ IStorage<T>?
64
+ );
65
+
66
+ // component consuming change stream manually
67
+ const useStream = context.useStream;
68
+ const Component1 : FC = () => {
69
+ const {
70
+ data,
71
+ resetState,
72
+ setState
73
+ } = useStream( SelectorMap );
74
+ ...
75
+ };
76
+
77
+ // components consuming change stream through a reusable adapter
78
+ const connect = context.connect( SelectorMap? );
79
+ const Component2 = connect(({ data, resetState, setState, ...ownProps }) => {...});
80
+ const Component3 = connect(({ data, resetState, setState, ...ownProps }) => {...});
81
+
82
+ const App : FC = () => (
83
+ <>
84
+ <Component1 />
85
+ <Component2 />
86
+ <Component3 />
87
+ </>
88
+ );
89
+
90
+ ```
91
+
92
+ ### Releasing context resources.
93
+ ```tsx
94
+ context.dispose();
95
+ ```
96
+ Deactivates this context by:
97
+ <ol>
98
+ <li>unsubscribing all observers to it</li>
99
+ <li>severing connections to data stores</li>
100
+ <li>unsetting all resources</li>
101
+ </ol>
102
+
103
+ ### Accessing external store reference.
104
+ ```tsx
105
+ const store = context.store;
106
+ // https://eagleeye.js.org/concepts/store/resetstate/
107
+ store.resetState( Array<string>? );
108
+ // https://eagleeye.js.org/concepts/store/setstate/
109
+ store.setState( Changes<T> );
110
+ // https://eagleeye.js.org/concepts/store/getstate/
111
+ const state = store.getState( Array<string> );
112
+ // https://eagleeye.js.org/concepts/store/subscribe/
113
+ const unsubscribeFn = store.subscribe( eventType, listener );
114
+ ```
115
+ Any actions taken here is applied to all components streaming affected state slices.\
116
+ Caveat 1: Parameterless <code>context.store.getState</code> returns the whole state.\
117
+ Caveat 2: Parameterless <code>context.store.resetState</code> is a no-op.
118
+
119
+ ### Joining the context stream.
120
+ A context stream allows a client to set up a dedicated channel through which it receives automatic updates whenever its selected slices of state change. It can also update the context through this channel.
121
+ ```tsx
122
+ const useStream = context.stream;
123
+ // joining the stream twice
124
+ // for more on selectorMap - https://eagleeye.js.org/concepts/selector-map/
125
+ const store1 = useStream(SelectorMap?);
126
+ const store2 = useStream(SelectorMap?);
127
+ // access the current data value monitored by this store
128
+ console.log( 'data', store1.data );
129
+ // https://eagleeye.js.org/concepts/store/resetstate/
130
+ store1.resetState( Array<string>? ); // changes are context-wide
131
+ // https://eagleeye.js.org/concepts/store/setstate/
132
+ store1.setState( Changes<T> ); // changes are context-wide
133
+ ```
134
+ Any actions taken here is applied to all components streaming affected state slices.\
135
+ Caveat 1: Parameterless <code>store.resetState</code> resets state slices consumed by this store.\
136
+ Caveat 2: Parameterless <code>store.resetState</code> for stores not consuming state is a no-op.
137
+
138
+ ### Accessing underlying cache.
139
+ ```tsx
140
+ const cache = context.cache;
141
+ ```
142
+
143
+ ### Accessing `close` status.
144
+ ```tsx
145
+ const closed = context.closed;
146
+ ```
147
+
148
+ ### Accessing current state update `prehooks`.
149
+ ```tsx
150
+ const prehooks = context.prehooks;
151
+ ```
152
+
153
+ ### Updating state update `prehooks`.
154
+ ```tsx
155
+ context.prehooks = Prehooks<T>?;
156
+ ```
157
+
158
+ ### Accessing context `storage`.
159
+ ```tsx
160
+ const storage = context.storage;
161
+ ```
162
+
163
+ ### Updating context `storage`.
164
+ ```tsx
165
+ context.storage = IStorage<T>?;
166
+ ```
167
+
168
+ May also see <b><a href="https://eagleeye.js.org/history/features">What's Changed? (currently uunder revision)</a></b>
54
169
 
55
170
  ## Please see full documentation here:
56
- **[eagleeye.js.org](https://eagleeye.js.org)**
171
+ **[eagleeye.js.org](https://eagleeye.js.org)** (currently out-of-date pending revision)
57
172
 
58
173
  # License
59
174
 
60
- MIT
175
+ GPLv3
package/dist/index.d.ts CHANGED
@@ -1,16 +1,8 @@
1
- import type { ComponentType, ForwardRefExoticComponent, MemoExoticComponent, NamedExoticComponent, ReactNode, PropsWithoutRef, RefAttributes } from 'react';
2
- import type { Changes as BaseChanges, Connection, Immutable, Value } from '@webkrafters/auto-immutable';
3
- import { FULL_STATE_SELECTOR } from './constants';
1
+ import type { ComponentType, ForwardRefExoticComponent, MemoExoticComponent, NamedExoticComponent, PropsWithoutRef, RefAttributes } from 'react';
4
2
  export type { BaseType, ClearCommand, KeyType, MoveCommand, PushCommand, ReplaceCommand, SetCommand, SpliceCommand, TagCommand, TagType, UpdateStats, UpdatePayload, UpdatePayloadArray } from '@webkrafters/auto-immutable';
5
- export type State = Value;
6
- export type Listener<T extends State = {}> = (changes: Changes<T>, changedPathsTokens: Readonly<Array<Array<string>>>, netChanges: Readonly<T>, mayHaveChangesAt: (pathTokens: Array<string>) => boolean) => void;
7
- export type ObservableProvider<T extends State> = ForwardRefExoticComponent<ProviderProps<T> & RefAttributes<StoreRef<T>>>;
8
- export interface ProviderProps<T extends State> {
9
- children?: ReactNode;
10
- prehooks?: Prehooks<T>;
11
- storage?: IStorage<T>;
12
- value: PartialState<T>;
13
- }
3
+ export type { ArraySelector, Changes, Channel, Data, FullStateSelector, IStorage, IStore, Listener, ObjectSelector, Prehooks, ProviderProps, SelectorMap, State, Store, StoreInternal, StoreRef, Stream, Text, Unsubscribe } from '@webkrafters/eagleeye';
4
+ import { SelectorMap, State, Store } from '@webkrafters/eagleeye';
5
+ export { CLEAR_TAG, DELETE_TAG, FULL_STATE_SELECTOR, MOVE_TAG, NULL_SELECTOR, PUSH_TAG, REPLACE_TAG, SET_TAG, SPLICE_TAG, Tag, } from '@webkrafters/eagleeye';
14
6
  export type ConnectProps<OWNPROPS extends OwnProps = IProps, STATE extends State = State, SELECTOR_MAP extends SelectorMap = SelectorMap> = {
15
7
  [K in keyof Store<STATE, SELECTOR_MAP>]: Store<STATE, SELECTOR_MAP>[K];
16
8
  } & Omit<OWNPROPS, "ref"> & RefAttributes<OWNPROPS["ref"]>;
@@ -21,68 +13,4 @@ export interface IProps {
21
13
  ref?: unknown;
22
14
  }
23
15
  export type OwnProps = IProps & Record<any, any>;
24
- export type Text = string | number;
25
- export type FullStateSelector = typeof FULL_STATE_SELECTOR;
26
- export type ObjectSelector = Record<Text, Text | FullStateSelector>;
27
- export type ArraySelector = Array<Text | FullStateSelector>;
28
- export type SelectorMap = ObjectSelector | ArraySelector | void;
29
- type ReplacePathSeps<P extends Text, T extends string> = P extends `${infer U}${T}${infer V}` ? ReplacePathSeps<`${U}.${V}`, T> : P;
30
- type TrimPathSep<P extends Text> = P extends `${infer U}]${never}` ? U : P;
31
- type NormalizePath<P extends Text> = TrimPathSep<ReplacePathSeps<ReplacePathSeps<ReplacePathSeps<P, ']['>, '].'>, '['>>;
32
- type Datum<P extends Text, S extends Record<Text, any> = State> = P extends `${infer K}.${infer P_1}` ? Datum<P_1, S[K]> : P extends '' ? S : any;
33
- type DataPoint<P extends Text, S extends State> = P extends FullStateSelector ? S : Datum<NormalizePath<P>, S>;
34
- export type Data<SELECTOR_MAP extends SelectorMap, STATE extends State = State> = (SELECTOR_MAP extends ObjectSelector ? {
35
- [S_KEY in keyof SELECTOR_MAP]: DataPoint<SELECTOR_MAP[S_KEY], STATE>;
36
- } : SELECTOR_MAP extends ArraySelector ? {
37
- [S_NUM: number]: DataPoint<SELECTOR_MAP[number], STATE>;
38
- } : Array<any>);
39
- export type Changes<T extends State = State> = BaseChanges<T>;
40
- export interface IStorage<T extends State = State> {
41
- clone: (data: T) => T;
42
- getItem: (key: string) => T;
43
- removeItem: (key: string) => void;
44
- setItem: (key: string, data: T) => void;
45
- }
46
- export type NonReactUsageReport = (...args: Array<unknown>) => void;
47
- export type PartialState<T extends State> = T extends Partial<infer U> ? T : Partial<T>;
48
- export interface Prehooks<T extends State = State> {
49
- resetState?: (resetData: PartialState<T>, state: {
50
- current: T;
51
- original: T;
52
- }) => boolean;
53
- setState?: (newChanges: Changes<T>) => boolean;
54
- }
55
- export type Subscribe = <T extends State>(listener: Listener<T>) => Unsubscribe;
56
- export type Unsubscribe = (...args: Array<unknown>) => void;
57
- export interface IStore {
58
- resetState: Function;
59
- setState: Function;
60
- }
61
- export interface IStoreInternal extends IStore {
62
- subscribe: Function;
63
- }
64
- export interface Store<T extends State, SELECTOR_MAP extends SelectorMap = SelectorMap> extends IStore {
65
- data: Data<SELECTOR_MAP>;
66
- resetState: (propertyPaths?: Array<string>) => void;
67
- setState: (changes: Changes<T>) => void;
68
- }
69
- export interface StoreInternal<T extends State> extends IStoreInternal {
70
- cache: Immutable<Partial<T>>;
71
- resetState: (connection: Connection<T>, propertyPaths?: Array<string>) => void;
72
- setState: (connection: Connection<T>, changes: Changes<T>) => void;
73
- subscribe: Subscribe;
74
- }
75
- export interface StorePlaceholder extends IStoreInternal {
76
- getState: NonReactUsageReport;
77
- resetState: NonReactUsageReport;
78
- setState: NonReactUsageReport;
79
- subscribe: NonReactUsageReport;
80
- }
81
- export interface StoreRef<T extends State = State> extends StorePlaceholder {
82
- getState: (propertyPaths?: Array<string>) => T;
83
- resetState: (propertyPaths?: Array<string>) => void;
84
- setState: (changes: Changes<T>) => void;
85
- subscribe: Subscribe;
86
- }
87
- export { CLEAR_TAG, DELETE_TAG, FULL_STATE_SELECTOR, MOVE_TAG, NULL_SELECTOR, PUSH_TAG, REPLACE_TAG, SET_TAG, SPLICE_TAG, Tag, } from './constants';
88
- export { connect, createContext, ObservableContext, UsageError, useContext } from './main';
16
+ export { createContext as createEagleEye } from './main';
package/dist/index.js CHANGED
@@ -3,102 +3,72 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.useContext = exports.UsageError = exports.ObservableContext = exports.createContext = exports.connect = exports.Tag = exports.SPLICE_TAG = exports.SET_TAG = exports.REPLACE_TAG = exports.PUSH_TAG = exports.NULL_SELECTOR = exports.MOVE_TAG = exports.FULL_STATE_SELECTOR = exports.DELETE_TAG = exports.CLEAR_TAG = void 0;
7
- ;
8
- ;
9
- ;
10
- ;
11
- ;
12
- ;
13
- var constants_1 = require("./constants");
6
+ exports.createEagleEye = exports.Tag = exports.SPLICE_TAG = exports.SET_TAG = exports.REPLACE_TAG = exports.PUSH_TAG = exports.NULL_SELECTOR = exports.MOVE_TAG = exports.FULL_STATE_SELECTOR = exports.DELETE_TAG = exports.CLEAR_TAG = void 0;
7
+ var eagleeye_1 = require("@webkrafters/eagleeye");
14
8
  Object.defineProperty(exports, "CLEAR_TAG", {
15
9
  enumerable: true,
16
10
  get: function get() {
17
- return constants_1.CLEAR_TAG;
11
+ return eagleeye_1.CLEAR_TAG;
18
12
  }
19
13
  });
20
14
  Object.defineProperty(exports, "DELETE_TAG", {
21
15
  enumerable: true,
22
16
  get: function get() {
23
- return constants_1.DELETE_TAG;
17
+ return eagleeye_1.DELETE_TAG;
24
18
  }
25
19
  });
26
20
  Object.defineProperty(exports, "FULL_STATE_SELECTOR", {
27
21
  enumerable: true,
28
22
  get: function get() {
29
- return constants_1.FULL_STATE_SELECTOR;
23
+ return eagleeye_1.FULL_STATE_SELECTOR;
30
24
  }
31
25
  });
32
26
  Object.defineProperty(exports, "MOVE_TAG", {
33
27
  enumerable: true,
34
28
  get: function get() {
35
- return constants_1.MOVE_TAG;
29
+ return eagleeye_1.MOVE_TAG;
36
30
  }
37
31
  });
38
32
  Object.defineProperty(exports, "NULL_SELECTOR", {
39
33
  enumerable: true,
40
34
  get: function get() {
41
- return constants_1.NULL_SELECTOR;
35
+ return eagleeye_1.NULL_SELECTOR;
42
36
  }
43
37
  });
44
38
  Object.defineProperty(exports, "PUSH_TAG", {
45
39
  enumerable: true,
46
40
  get: function get() {
47
- return constants_1.PUSH_TAG;
41
+ return eagleeye_1.PUSH_TAG;
48
42
  }
49
43
  });
50
44
  Object.defineProperty(exports, "REPLACE_TAG", {
51
45
  enumerable: true,
52
46
  get: function get() {
53
- return constants_1.REPLACE_TAG;
47
+ return eagleeye_1.REPLACE_TAG;
54
48
  }
55
49
  });
56
50
  Object.defineProperty(exports, "SET_TAG", {
57
51
  enumerable: true,
58
52
  get: function get() {
59
- return constants_1.SET_TAG;
53
+ return eagleeye_1.SET_TAG;
60
54
  }
61
55
  });
62
56
  Object.defineProperty(exports, "SPLICE_TAG", {
63
57
  enumerable: true,
64
58
  get: function get() {
65
- return constants_1.SPLICE_TAG;
59
+ return eagleeye_1.SPLICE_TAG;
66
60
  }
67
61
  });
68
62
  Object.defineProperty(exports, "Tag", {
69
63
  enumerable: true,
70
64
  get: function get() {
71
- return constants_1.Tag;
65
+ return eagleeye_1.Tag;
72
66
  }
73
67
  });
74
68
  var main_1 = require("./main");
75
- Object.defineProperty(exports, "connect", {
76
- enumerable: true,
77
- get: function get() {
78
- return main_1.connect;
79
- }
80
- });
81
- Object.defineProperty(exports, "createContext", {
69
+ Object.defineProperty(exports, "createEagleEye", {
82
70
  enumerable: true,
83
71
  get: function get() {
84
72
  return main_1.createContext;
85
73
  }
86
- });
87
- Object.defineProperty(exports, "ObservableContext", {
88
- enumerable: true,
89
- get: function get() {
90
- return main_1.ObservableContext;
91
- }
92
- });
93
- Object.defineProperty(exports, "UsageError", {
94
- enumerable: true,
95
- get: function get() {
96
- return main_1.UsageError;
97
- }
98
- });
99
- Object.defineProperty(exports, "useContext", {
100
- enumerable: true,
101
- get: function get() {
102
- return main_1.useContext;
103
- }
104
74
  });
@@ -1,22 +1,24 @@
1
1
  import type { ElementType, NamedExoticComponent } from 'react';
2
- import type { ConnectedComponent, ConnectProps, ExtractInjectedProps, IStoreInternal, ObservableProvider, SelectorMap, State, Store } from '..';
3
- import React from 'react';
4
- declare const __CTX_SYM__: unique symbol;
2
+ import type { ConnectedComponent, ConnectProps, ExtractInjectedProps, SelectorMap, Store } from '..';
3
+ import { AutoImmutable, IStorage, Prehooks, State } from "@webkrafters/eagleeye";
5
4
  export declare class ObservableContext<T extends State> {
6
- private cxt;
7
- private provider;
8
- constructor();
9
- get [__CTX_SYM__](): React.Context<IStoreInternal>;
10
- get Consumer(): React.Consumer<IStoreInternal>;
11
- get Provider(): ObservableProvider<T>;
5
+ private consumer;
6
+ constructor(value?: T, prehooks?: Prehooks<T>, storage?: IStorage<T>);
7
+ constructor(value?: AutoImmutable<T>, prehooks?: Prehooks<T>, storage?: IStorage<T>);
8
+ get cache(): AutoImmutable<T>;
9
+ get closed(): boolean;
10
+ get connect(): <S extends SelectorMap>(selectorMap?: S) => {
11
+ <P extends ExtractInjectedProps<T, S>>(WrappedComponent: ElementType<ConnectProps<P, T, S>>): ConnectedComponent<P>;
12
+ <P extends ExtractInjectedProps<T, S>>(WrappedComponent: NamedExoticComponent<ConnectProps<P, T, S>>): ConnectedComponent<P>;
13
+ };
14
+ get prehooks(): Prehooks<T>;
15
+ get storage(): IStorage<T>;
16
+ get store(): import("@webkrafters/eagleeye").StoreRef<T>;
17
+ get useStream(): <S extends SelectorMap>(selectorMap?: S) => Store<T, S>;
18
+ set prehooks(prehooks: Prehooks<T>);
19
+ set storage(storage: IStorage<T>);
20
+ private _connect;
21
+ dispose(): void;
12
22
  }
13
- export declare class UsageError extends Error {
14
- }
15
- export declare function connect<STATE extends State = State, SELECTOR_MAP extends SelectorMap = SelectorMap>(context: ObservableContext<STATE>, selectorMap?: SELECTOR_MAP): {
16
- <P extends ExtractInjectedProps<STATE, SELECTOR_MAP>>(WrappedComponent: ElementType<ConnectProps<P, STATE, SELECTOR_MAP>>): ConnectedComponent<P>;
17
- <P extends ExtractInjectedProps<STATE, SELECTOR_MAP>>(WrappedComponent: NamedExoticComponent<ConnectProps<P, STATE, SELECTOR_MAP>>): ConnectedComponent<P>;
18
- };
19
- export declare function createContext<T extends State = State>(): ObservableContext<T>;
20
- export declare function mkReadonly(v: any): any;
21
- export declare function useContext<STATE extends State, SELECTOR_MAP extends SelectorMap>(context: ObservableContext<STATE>, selectorMap?: SELECTOR_MAP): Store<STATE, SELECTOR_MAP>;
22
- export {};
23
+ export declare function createContext<T extends State>(value?: T, prehooks?: Prehooks<T>, storage?: IStorage<T>): ObservableContext<T>;
24
+ export declare function createContext<T extends State>(value?: AutoImmutable<T>, prehooks?: Prehooks<T>, storage?: IStorage<T>): ObservableContext<T>;