insite-subscriptions-react 2.3.3 → 2.4.0

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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024 Eugene Nesvetaev
3
+ Copyright (c) 2026 Eugene Nesvetaev
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,13 +1,210 @@
1
- # inSite subscriptions React components
1
+ # insite-subscriptions-react
2
+
3
+ React components for subscribing to inSite publications over WebSocket.
4
+
5
+ Part of [inSite](../../README.md) — requires [insite-ws](../ws/README.md) and [insite-subscriptions-client](../subscriptions-client/README.md).
2
6
 
3
7
  ## Installation
4
8
 
5
9
  ```sh
6
- $ npm install insite-subscriptions-react
10
+ npm install insite-subscriptions-react
7
11
  ```
8
12
 
9
- Or
13
+ Or:
10
14
 
11
15
  ```sh
12
- $ bun add insite-subscriptions-react
16
+ bun add insite-subscriptions-react
17
+ ```
18
+
19
+ ## Setup
20
+
21
+ Before using the components, bind the library to your WebSocket instance:
22
+
23
+ ```ts
24
+ import { WS } from "insite-ws/client";
25
+ import { Subscription } from "insite-subscriptions-react";
26
+
27
+ const ws = new WS({ url: "wss://example.com" });
28
+ Subscription.bindTo(ws);
29
+ ```
30
+
31
+ `Subscription.bindTo(ws)` wires the subscription protocol to the given `WS` instance. Without it, creating subscriptions will throw.
32
+
33
+ ## Overview
34
+
35
+ **Subscription** — Single publication subscription. Supports three data shapes: object (default), array, and map. Subscribes on mount, unsubscribes on unmount. Renders via a render-prop `children(isActive, value)`.
36
+
37
+ **SubscriptionGroup** — Multiple subscriptions with shared lifecycle. Uses definition-based configuration from [insite-subscriptions-client](../subscriptions-client/README.md). Subscribes on mount, unsubscribes on unmount. Renders via `children(isLoaded, values)`.
38
+
39
+ Both components support two update modes:
40
+
41
+ - **consistent** — uses `forceUpdate()` when data changes; no `shouldComponentUpdate` override
42
+ - **inconsistent** (default for Subscription) — uses `setState({})` when data changes; `shouldComponentUpdate` returns `false` when only `publication`/`params` or `definitions` change, and renews/redefines instead of full re-render
43
+
44
+ ## Public API
45
+
46
+ ### Exports
47
+
48
+ | Export | Description |
49
+ |--------|-------------|
50
+ | `Subscription` | Class component for a single publication |
51
+ | `SubscriptionGroup` | Class component for multiple publications |
52
+
53
+ Both components expose static `bindTo`, which delegates to `Subscription.bindTo` from [insite-subscriptions-client](../subscriptions-client/README.md).
54
+
55
+ ---
56
+
57
+ ### Subscription
58
+
59
+ Class component that wraps `SubscriptionObject.WithSubscription`, `SubscriptionArray.WithSubscription`, or `SubscriptionMap.WithSubscription` depending on props.
60
+
61
+ | Prop | Type | Default | Description |
62
+ |-----|------|---------|-------------|
63
+ | `publication` | `string` | — | Publication name to subscribe to |
64
+ | `params` | `unknown[]` | `[]` | Arguments passed to the publication |
65
+ | `map` | `boolean` | — | Use `SubscriptionMap` when `true` |
66
+ | `array` | `boolean` | — | Use `SubscriptionArray` when `true` |
67
+ | `Item` | `SubscriptionMap["Item"]` | — | Custom item class for map (map only) |
68
+ | `valueRef` | `(value: Value) => void` | — | Called with the subscription value in constructor |
69
+ | `consistent` | `boolean` | — | Use `forceUpdate` instead of `setState` when `true` |
70
+ | `children` | `(isActive: boolean, value: Value) => ReactNode` | — | Render prop |
71
+ | `onUpdate` | `(value: Value) => void` | — | Called when data updates |
72
+
73
+ **Value type:** `SubscriptionObjectWithSubscription | SubscriptionArrayWithSubscription | SubscriptionMapWithSubscription` (from [insite-subscriptions-client](../subscriptions-client/README.md))
74
+
75
+ **Instance properties (via ref):**
76
+
77
+ | Property | Type | Description |
78
+ |----------|------|-------------|
79
+ | `value` | `Value` | The underlying subscription container |
80
+ | `isActive` | `boolean` | `true` when data is loaded, `false` when connection is closed |
81
+
82
+ **Instance methods (via ref):**
83
+
84
+ | Method | Description |
85
+ |--------|-------------|
86
+ | `renew(publicationName: string, params: unknown[])` | Renew subscription with new publication/params |
87
+ | `subscribe()` | Subscribe (called automatically on mount) |
88
+ | `unsubscribe()` | Unsubscribe (called automatically on unmount) |
89
+
90
+ ---
91
+
92
+ ### SubscriptionGroup
93
+
94
+ Class component that wraps `SubscriptionGroup` from [insite-subscriptions-client](../subscriptions-client/README.md).
95
+
96
+ | Prop | Type | Description |
97
+ |-----|------|-------------|
98
+ | `definitions` | `SubscriptionGroupUnparsedDefinition[]` | Subscription definitions (object or tuple form) |
99
+ | `target` | `object` | Object to bind subscription values to (`target[name] = value`) |
100
+ | `debounce` | `number` | Debounce ms for update events |
101
+ | `valuesRef` | `(values: SubscriptionGroupValues) => void` | Called with `group.values` in constructor |
102
+ | `consistent` | `boolean` | Use `forceUpdate` instead of `setState` when `true` |
103
+ | `children` | `(isLoaded: boolean, values: SubscriptionGroupValues) => ReactNode` | Render prop |
104
+ | `onUpdate` | `(group: SubscriptionGroup) => void` | Called when any subscription in the group updates |
105
+
106
+ **SubscriptionGroupValues:** `any[] & Record<string, any>` — array of values indexed by definition name
107
+
108
+ **Instance properties (via ref):**
109
+
110
+ | Property | Type | Description |
111
+ |----------|------|-------------|
112
+ | `group` | `SubscriptionGroup` | The underlying group instance |
113
+ | `values` | `SubscriptionGroupValues` | Current values by definition name |
114
+ | `isLoaded` | `boolean` | `true` when all subscriptions have loaded |
115
+ | `isInited` | `boolean` | `true` when all subscriptions have inited |
116
+
117
+ **Instance methods (via ref):**
118
+
119
+ | Method | Description |
120
+ |--------|-------------|
121
+ | `redefine(definitions: SubscriptionGroupUnparsedDefinition[])` | Replace definitions, reattach changed, detach removed |
122
+ | `subscribe()` | Subscribe all (called automatically on mount) |
123
+ | `unsubscribe()` | Unsubscribe all (called automatically on unmount) |
124
+
125
+ ---
126
+
127
+ ### SubscriptionGroup Definition Format
128
+
129
+ Each definition describes one subscription in the group. See [insite-subscriptions-client](../subscriptions-client/README.md) for full details.
130
+
131
+ **Object form:**
132
+
133
+ ```ts
134
+ {
135
+ name: string;
136
+ type?: "object" | "array" | "map";
137
+ publicationName?: string; // defaults to name
138
+ params?: unknown[];
139
+ value?: SubscriptionObjectWithSubscription | SubscriptionArrayWithSubscription | SubscriptionMapWithSubscription;
140
+ handle?: (updated, group) => void;
141
+ onBeforeInit?: (value) => void;
142
+ debounce?: number;
143
+ preventBind?: boolean;
144
+ }
145
+ ```
146
+
147
+ **Tuple form:** `[name, type?, publicationName?, params?, handle?, onBeforeInit?, debounce?, preventBind?]`
148
+
149
+ ## Usage Examples
150
+
151
+ **Subscription (object):**
152
+
153
+ ```tsx
154
+ import { Subscription } from "insite-subscriptions-react";
155
+
156
+ <Subscription publication="currentUser" params={[]}>
157
+ {(isActive, value) => isActive && <div>{value.name}</div>}
158
+ </Subscription>
159
+ ```
160
+
161
+ **Subscription (array) with valueRef:**
162
+
163
+ ```tsx
164
+ const valueRef = useRef(null);
165
+
166
+ <Subscription
167
+ publication="users"
168
+ params={[]}
169
+ array
170
+ valueRef={(value) => { valueRef.current = value; }}
171
+ >
172
+ {(isActive, value) => isActive && <UserList items={value} />}
173
+ </Subscription>
13
174
  ```
175
+
176
+ **SubscriptionGroup:**
177
+
178
+ ```tsx
179
+ import { SubscriptionGroup } from "insite-subscriptions-react";
180
+
181
+ const target = {};
182
+ const definitions = [
183
+ { name: "users", type: "array", publicationName: "users", params: [] },
184
+ { name: "profile", type: "object", publicationName: "profile", params: [] }
185
+ ];
186
+
187
+ <SubscriptionGroup
188
+ definitions={definitions}
189
+ target={target}
190
+ debounce={8}
191
+ consistent={false}
192
+ valuesRef={() => {}}
193
+ onUpdate={() => {}}
194
+ >
195
+ {(isLoaded, values) => isLoaded && (
196
+ <div>
197
+ <UserList users={values.users} />
198
+ <Profile data={values.profile} />
199
+ </div>
200
+ )}
201
+ </SubscriptionGroup>
202
+ ```
203
+
204
+ ## Related
205
+
206
+ - [insite-subscriptions-client](../subscriptions-client/README.md), [insite-ws](../ws/README.md)
207
+
208
+ ## License
209
+
210
+ MIT
@@ -1 +1 @@
1
- {"version":3,"file":"Subscription.d.ts","sourceRoot":"","sources":["../src/Subscription.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAElD,OAAO,EAIN,YAAY,EAEZ,iCAAiC,EACjC,eAAe,EACf,+BAA+B,EAE/B,kCAAkC,EAElC,MAAM,6BAA6B,CAAC;AAGrC,KAAK,KAAK,GAAG,iCAAiC,GAAG,+BAA+B,GAAG,kCAAkC,CAAC;AAEtH,KAAK,KAAK,GAAG;IACZ,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,OAAO,EAAE,CAAC;IAClB,IAAI,CAAC,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;IAC/B,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,KAAK,SAAS,CAAC;IAC1D,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC,CAAC;AAEF,KAAK,KAAK,GAAG,MAAM,GAAG,SAAS,CAAC;AAOhC,qBAAa,qBAAsB,SAAQ,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC;gBACrD,KAAK,EAAE,KAAK;IAmBxB,KAAK,iBAGA;IAEL,KAAK;;sIAAC;IAEN,mBAAmB,qBAG0C;IAE7D,IAAI,QAAQ,YAEX;IAED,KAAK,CAAC,eAAe,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE;IAIhD,SAAS;IAIT,WAAW;IAKX,qBAAqB,6EAGqC;IAE1D,MAAM;IAKN,YAAY;IAMZ,iBAAiB;IAWjB,oBAAoB;IASpB,MAAM,CAAC,iCAAiC,CAAC,IAAI,EAAE,qBAAqB,EAAE,SAAS,EAAE,KAAK;IAYtF,MAAM,CAAC,sBAAsB,CAAC,IAAI,EAAE,qBAAqB;IAOzD,MAAM,CAAC,wBAAwB,CAAC,IAAI,EAAE,qBAAqB;IAO3D,MAAM,CAAC,YAAY;;MAEjB;IAEF,MAAM,CAAC,MAAM,6BAAuB;CAEpC"}
1
+ {"version":3,"file":"Subscription.d.ts","sourceRoot":"","sources":["../src/Subscription.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAElD,OAAO,EAIN,YAAY,EAEZ,iCAAiC,EACjC,eAAe,EACf,+BAA+B,EAE/B,kCAAkC,EAElC,MAAM,6BAA6B,CAAC;AAMrC,KAAK,KAAK,GAAG,iCAAiC,GAAG,+BAA+B,GAAG,kCAAkC,CAAC;AAEtH,KAAK,KAAK,GAAG;IACZ,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,OAAO,EAAE,CAAC;IAClB,IAAI,CAAC,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;IAC/B,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,KAAK,SAAS,CAAC;IAC1D,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC,CAAC;AAEF,KAAK,KAAK,GAAG,MAAM,GAAG,SAAS,CAAC;AAOhC,qBAAa,qBAAsB,SAAQ,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC;gBACrD,KAAK,EAAE,KAAK;IAmBxB,KAAK,iBAGA;IAEL,KAAK;;sIAAC;IAEN,mBAAmB,qBAG0C;IAE7D,IAAI,QAAQ,YAEX;IAED,KAAK,CAAC,eAAe,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE;IAIhD,SAAS;IAIT,WAAW;IAKX,qBAAqB,6EAGqC;IAE1D,MAAM;IAKN,YAAY;IAMZ,iBAAiB;IAWjB,oBAAoB;IASpB,MAAM,CAAC,iCAAiC,CAAC,IAAI,EAAE,qBAAqB,EAAE,SAAS,EAAE,KAAK;IAYtF,MAAM,CAAC,sBAAsB,CAAC,IAAI,EAAE,qBAAqB;IAOzD,MAAM,CAAC,wBAAwB,CAAC,IAAI,EAAE,qBAAqB;IAO3D,MAAM,CAAC,YAAY;;MAEjB;IAEF,MAAM,CAAC,MAAM,6BAAuB;CAEpC"}
@@ -1 +1 @@
1
- {"version":3,"file":"SubscriptionGroup.d.ts","sourceRoot":"","sources":["../src/SubscriptionGroup.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAE7C,OAAO,EACN,YAAY,EACZ,iBAAiB,EACjB,KAAK,wBAAwB,EAC7B,KAAK,mCAAmC,EACxC,MAAM,6BAA6B,CAAC;AAGrC,KAAK,uBAAuB,GAAG,GAAG,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAE3D,KAAK,KAAK,GAAG;IACZ,WAAW,EAAE,mCAAmC,EAAE,CAAC;IACnD,MAAM,EAAE,wBAAwB,CAAC,QAAQ,CAAC,CAAC;IAC3C,QAAQ,EAAE,wBAAwB,CAAC,UAAU,CAAC,CAAC;IAC/C,SAAS,EAAE,CAAC,MAAM,EAAE,uBAAuB,KAAK,IAAI,CAAC;IACrD,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,uBAAuB,KAAK,SAAS,CAAC;IAC5E,QAAQ,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;CAC7C,CAAC;AAEF,KAAK,KAAK,GAAG,MAAM,GAAG,SAAS,CAAC;AAGhC,qBAAa,0BAA2B,SAAQ,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC;gBAC1D,KAAK,EAAE,KAAK;IAexB,KAAK,2DAAC;IAEN,KAAK,iBAA0C;IAE/C,mBAAmB,qBAA8E;IAEjG,IAAI,QAAQ,YAEX;IAED,IAAI,QAAQ,YAEX;IAED,IAAI,MAAM,gCAET;IAED,QAAQ,GAAI,aAAa,mCAAmC,EAAE,kpBAAsC;IAEpG,SAAS,eAAgC;IAEzC,WAAW,6BAAkC;IAG7C,qBAAqB,kFAG0C;IAE/D,MAAM;IAKN,YAAY;IAMZ,iBAAiB;IAWjB,oBAAoB;IASpB,MAAM,CAAC,iCAAiC,CAAC,IAAI,EAAE,0BAA0B,EAAE,SAAS,EAAE,KAAK;IAe3F,MAAM,CAAC,sBAAsB,CAAC,IAAI,EAAE,0BAA0B;IAO9D,MAAM,CAAC,wBAAwB,CAAC,IAAI,EAAE,0BAA0B;IAOhE,MAAM,CAAC,MAAM,6BAAuB;CAEpC"}
1
+ {"version":3,"file":"SubscriptionGroup.d.ts","sourceRoot":"","sources":["../src/SubscriptionGroup.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAE7C,OAAO,EACN,YAAY,EACZ,iBAAiB,EACjB,KAAK,wBAAwB,EAC7B,KAAK,mCAAmC,EACxC,MAAM,6BAA6B,CAAC;AAMrC,KAAK,uBAAuB,GAAG,GAAG,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAE3D,KAAK,KAAK,GAAG;IACZ,WAAW,EAAE,mCAAmC,EAAE,CAAC;IACnD,MAAM,EAAE,wBAAwB,CAAC,QAAQ,CAAC,CAAC;IAC3C,QAAQ,EAAE,wBAAwB,CAAC,UAAU,CAAC,CAAC;IAC/C,SAAS,EAAE,CAAC,MAAM,EAAE,uBAAuB,KAAK,IAAI,CAAC;IACrD,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,uBAAuB,KAAK,SAAS,CAAC;IAC5E,QAAQ,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;CAC7C,CAAC;AAEF,KAAK,KAAK,GAAG,MAAM,GAAG,SAAS,CAAC;AAGhC,qBAAa,0BAA2B,SAAQ,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC;gBAC1D,KAAK,EAAE,KAAK;IAexB,KAAK,2DAAC;IAEN,KAAK,iBAA0C;IAE/C,mBAAmB,qBAA8E;IAEjG,IAAI,QAAQ,YAEX;IAED,IAAI,QAAQ,YAEX;IAED,IAAI,MAAM,gCAET;IAED,QAAQ,GAAI,aAAa,mCAAmC,EAAE,kpBAAsC;IAEpG,SAAS,eAAgC;IAEzC,WAAW,6BAAkC;IAG7C,qBAAqB,kFAG0C;IAE/D,MAAM;IAKN,YAAY;IAMZ,iBAAiB;IAWjB,oBAAoB;IASpB,MAAM,CAAC,iCAAiC,CAAC,IAAI,EAAE,0BAA0B,EAAE,SAAS,EAAE,KAAK;IAe3F,MAAM,CAAC,sBAAsB,CAAC,IAAI,EAAE,0BAA0B;IAO9D,MAAM,CAAC,wBAAwB,CAAC,IAAI,EAAE,0BAA0B;IAOhE,MAAM,CAAC,MAAM,6BAAuB;CAEpC"}
package/package.json CHANGED
@@ -1,34 +1,52 @@
1
1
  {
2
- "name": "insite-subscriptions-react",
3
- "version": "2.3.3",
4
- "description": "inSite subscriptions React components",
5
- "type": "module",
6
- "main": "./src/index.js",
7
- "module": "./src/index.js",
8
- "packageManager": "bun@1.2.18",
9
- "scripts": {
10
- "test": "echo \"Error: no test specified\" && exit 1",
11
- "build": "tsc -p ."
12
- },
13
- "repository": {
14
- "type": "git",
15
- "url": "git+https://github.com/nesvet/insite-subscriptions-react.git"
16
- },
17
- "keywords": [
18
- "insite",
19
- "subscriptions",
20
- "react"
21
- ],
22
- "author": "Eugene Nesvetaev <dev@nesvet.dev> (https://nesvet.dev/)",
23
- "license": "MIT",
24
- "dependencies": {
25
- "@nesvet/n": "^1.2.1",
26
- "insite-subscriptions-client": "^2.3.3",
27
- "react": "~18.2.0"
28
- },
29
- "devDependencies": {
30
- "@nesvet/eslint-config": "^2.1.2",
31
- "@types/react": "^18.3.23",
32
- "typescript": "^5.8.3"
33
- }
2
+ "name": "insite-subscriptions-react",
3
+ "version": "2.4.0",
4
+ "description": "React hooks and components for inSite subscriptions",
5
+ "keywords": [
6
+ "insite",
7
+ "subscriptions",
8
+ "react",
9
+ "hooks"
10
+ ],
11
+ "homepage": "https://github.com/nesvet/insite#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/nesvet/insite/issues"
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "https://github.com/nesvet/insite.git",
18
+ "directory": "packages/subscriptions-react"
19
+ },
20
+ "funding": {
21
+ "type": "patreon",
22
+ "url": "https://www.patreon.com/nesvet"
23
+ },
24
+ "license": "MIT",
25
+ "author": "Eugene Nesvetaev <dev@nesvet.dev> (https://nesvet.dev/)",
26
+ "type": "module",
27
+ "main": "./dist/index.js",
28
+ "module": "./dist/index.js",
29
+ "types": "./dist/index.d.ts",
30
+ "files": [
31
+ "dist",
32
+ "README.md",
33
+ "LICENSE"
34
+ ],
35
+ "scripts": {
36
+ "build": "tsc -p .",
37
+ "clean": "rm -rf dist",
38
+ "test": "echo \"Error: no test specified\" && exit 1",
39
+ "typecheck": "tsc --noEmit"
40
+ },
41
+ "dependencies": {
42
+ "@nesvet/n": "^1.2.1",
43
+ "insite-subscriptions-client": "^2.4.0"
44
+ },
45
+ "peerDependencies": {
46
+ "react": "^18.2.0"
47
+ },
48
+ "packageManager": "bun@1.3.9",
49
+ "engines": {
50
+ "node": ">=20.0.0"
51
+ }
34
52
  }
@@ -1,156 +0,0 @@
1
- import { Component, type ReactNode } from "react";
2
- import { noop } from "@nesvet/n";
3
- import {
4
- getSubscriptionSymbol,
5
- renewSymbol,
6
- subscribeSymbol,
7
- Subscription,
8
- SubscriptionArray,
9
- SubscriptionArrayWithSubscription,
10
- SubscriptionMap,
11
- SubscriptionMapWithSubscription,
12
- SubscriptionObject,
13
- SubscriptionObjectWithSubscription,
14
- unsubscribeSymbol
15
- } from "insite-subscriptions-client";
16
-
17
-
18
- type Value = SubscriptionArrayWithSubscription | SubscriptionMapWithSubscription | SubscriptionObjectWithSubscription;
19
-
20
- type Props = {
21
- map?: boolean;
22
- array?: boolean;
23
- publication: string;
24
- params: unknown[];
25
- Item?: SubscriptionMap["Item"];
26
- valueRef: (value: Value) => void;
27
- consistent?: boolean;
28
- children?: (isActive: boolean, value: Value) => ReactNode;
29
- onUpdate?: (value: Value) => void;
30
- };
31
-
32
- type State = object | undefined;
33
-
34
- function isValueSubscriptionMap(props: Props, value: Value): value is SubscriptionMapWithSubscription {
35
- return props.map === true;
36
- }
37
-
38
-
39
- export class SubscriptionComponent extends Component<Props, State> {
40
- constructor(props: Props) {
41
- super(props);
42
-
43
- const target =
44
- props.map ?
45
- new SubscriptionMap.WithSubscription(props.publication, props.params, (() => this.handleUpdate()), false) :
46
- props.array ?
47
- new SubscriptionArray.WithSubscription(props.publication, props.params, (() => this.handleUpdate()), false) :
48
- new SubscriptionObject.WithSubscription(props.publication, props.params, (() => this.handleUpdate()), false);
49
-
50
- this.value = target;
51
-
52
- if (isValueSubscriptionMap(props, target) && props.Item)
53
- target.Item = props.Item;
54
-
55
- props.valueRef?.(this.value);
56
-
57
- }
58
-
59
- state =
60
- this.props.consistent ?
61
- undefined :
62
- {};
63
-
64
- value;
65
-
66
- publicationSnapshot =
67
- this.props.consistent ?
68
- undefined :
69
- JSON.stringify(this.props.params) + this.props.publication;
70
-
71
- get isActive() {
72
- return this.value[getSubscriptionSymbol]()?.isActive ?? false;
73
- }
74
-
75
- renew(publicationName: string, params: unknown[]) {
76
- return this.value[renewSymbol](publicationName, params);
77
- }
78
-
79
- subscribe() {
80
- return this.value[subscribeSymbol]();
81
- }
82
-
83
- unsubscribe() {
84
- return this.value[unsubscribeSymbol]();
85
- }
86
-
87
-
88
- shouldComponentUpdate =
89
- this.props.consistent ?
90
- undefined :
91
- SubscriptionComponent.inconsistentShouldComponentUpdate;
92
-
93
- render() {
94
- return this.props.children?.(this.isActive, this.value) || null;
95
- }
96
-
97
-
98
- handleUpdate() {
99
-
100
- this.props.onUpdate?.(this.value);
101
-
102
- }
103
-
104
- componentDidMount() {
105
-
106
- this.subscribe();
107
-
108
- this.handleUpdate =
109
- this.props.consistent ?
110
- SubscriptionComponent.consistentHandleUpdate :
111
- SubscriptionComponent.inconsistentHandleUpdate;
112
-
113
- }
114
-
115
- componentWillUnmount() {
116
-
117
- this.handleUpdate = noop;
118
-
119
- this.unsubscribe();
120
-
121
- }
122
-
123
-
124
- static inconsistentShouldComponentUpdate(this: SubscriptionComponent, nextProps: Props) {
125
- const publicationSnapshot = JSON.stringify(nextProps.params) + nextProps.publication;
126
-
127
- if (this.publicationSnapshot === publicationSnapshot)
128
- return true;
129
-
130
- this.publicationSnapshot = publicationSnapshot;
131
- this.renew(nextProps.publication, nextProps.params);
132
-
133
- return false;
134
- }
135
-
136
- static consistentHandleUpdate(this: SubscriptionComponent) {
137
-
138
- this.props.onUpdate?.(this.value);
139
- this.forceUpdate();
140
-
141
- }
142
-
143
- static inconsistentHandleUpdate(this: SubscriptionComponent) {
144
-
145
- this.props.onUpdate?.(this.value);
146
- this.setState({});
147
-
148
- }
149
-
150
- static defaultProps = {
151
- params: []
152
- };
153
-
154
- static bindTo = Subscription.bindTo;
155
-
156
- }
@@ -1,134 +0,0 @@
1
- import { Component, ReactNode } from "react";
2
- import { noop } from "@nesvet/n";
3
- import {
4
- Subscription,
5
- SubscriptionGroup,
6
- type SubscriptionGroupOptions,
7
- type SubscriptionGroupUnparsedDefinition
8
- } from "insite-subscriptions-client";
9
-
10
-
11
- type SubscriptionGroupValues = any[] & Record<string, any>;// eslint-disable-line @typescript-eslint/no-explicit-any
12
-
13
- type Props = {
14
- definitions: SubscriptionGroupUnparsedDefinition[];
15
- target: SubscriptionGroupOptions["target"];
16
- debounce: SubscriptionGroupOptions["debounce"];
17
- valuesRef: (values: SubscriptionGroupValues) => void;
18
- consistent: boolean;
19
- children: (isLoaded: boolean, values: SubscriptionGroupValues) => ReactNode;
20
- onUpdate: (group: SubscriptionGroup) => void;
21
- };
22
-
23
- type State = object | undefined;
24
-
25
-
26
- export class SubscriptionGroupComponent extends Component<Props, State> {
27
- constructor(props: Props) {
28
- super(props);
29
-
30
- this.group = new SubscriptionGroup(props.definitions, {
31
- target: props.target,
32
- debounce: props.debounce,
33
- immediately: false
34
- });
35
-
36
- this.group.on("update", () => this.handleUpdate());
37
-
38
- props.valuesRef?.(this.group.values);
39
-
40
- }
41
-
42
- group;
43
-
44
- state = this.props.consistent ? undefined : {};
45
-
46
- definitionsSnapshot = this.props.consistent ? undefined : JSON.stringify(this.props.definitions);
47
-
48
- get isLoaded() {
49
- return this.group.isLoaded;
50
- }
51
-
52
- get isInited() {
53
- return this.group.isInited;
54
- }
55
-
56
- get values() {
57
- return this.group.values;
58
- }
59
-
60
- redefine = (definitions: SubscriptionGroupUnparsedDefinition[]) => this.group.redefine(definitions);
61
-
62
- subscribe = () => this.group.subscribe();
63
-
64
- unsubscribe = () => this.group.unsubscribe();
65
-
66
-
67
- shouldComponentUpdate =
68
- this.props.consistent ?
69
- undefined :
70
- SubscriptionGroupComponent.inconsistentShouldComponentUpdate;
71
-
72
- render() {
73
- return this.props.children?.(this.group.isLoaded, this.group.values) || null;
74
- }
75
-
76
-
77
- handleUpdate() {
78
-
79
- this.props.onUpdate?.(this.group);
80
-
81
- }
82
-
83
- componentDidMount() {
84
-
85
- this.subscribe();
86
-
87
- this.handleUpdate =
88
- this.props.consistent ?
89
- SubscriptionGroupComponent.consistentHandleUpdate :
90
- SubscriptionGroupComponent.inconsistentHandleUpdate;
91
-
92
- }
93
-
94
- componentWillUnmount() {
95
-
96
- this.handleUpdate = noop;
97
-
98
- this.unsubscribe();
99
-
100
- }
101
-
102
-
103
- static inconsistentShouldComponentUpdate(this: SubscriptionGroupComponent, nextProps: Props) {
104
- if (this.props.target !== nextProps.target || this.props.debounce !== nextProps.debounce)
105
- this.group.applyOptions({ target: nextProps.target, debounceLimit: nextProps.debounce });
106
-
107
- const definitionsSnapshot = JSON.stringify(nextProps.definitions);
108
-
109
- if (this.definitionsSnapshot === definitionsSnapshot)
110
- return true;
111
-
112
- this.definitionsSnapshot = definitionsSnapshot;
113
- void this.redefine(nextProps.definitions);
114
-
115
- return false;
116
- }
117
-
118
- static consistentHandleUpdate(this: SubscriptionGroupComponent) {
119
-
120
- this.props.onUpdate?.(this.group);
121
- this.forceUpdate();
122
-
123
- }
124
-
125
- static inconsistentHandleUpdate(this: SubscriptionGroupComponent) {
126
-
127
- this.props.onUpdate?.(this.group);
128
- this.setState({});
129
-
130
- }
131
-
132
- static bindTo = Subscription.bindTo;
133
-
134
- }
package/src/index.ts DELETED
@@ -1,2 +0,0 @@
1
- export { SubscriptionComponent as Subscription } from "./Subscription";
2
- export { SubscriptionGroupComponent as SubscriptionGroup } from "./SubscriptionGroup";