@holo-js/flux-react 0.1.4 → 0.1.5
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/dist/index.d.ts +27 -7
- package/dist/index.mjs +34 -3
- package/package.json +12 -10
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,26 @@
|
|
|
1
1
|
import { FluxClient, FluxConnectionStatus, FluxListenerControls } from '@holo-js/flux';
|
|
2
|
-
import { GeneratedBroadcastManifest, BroadcastPayloadFor } from '@holo-js/broadcast';
|
|
2
|
+
import { GeneratedBroadcastManifest, BroadcastPayloadFor, BroadcastJsonObject } from '@holo-js/broadcast';
|
|
3
3
|
|
|
4
|
+
type ManifestEventName<TManifest extends GeneratedBroadcastManifest> = TManifest['events'][number]['name'] & string;
|
|
5
|
+
type ManifestChannelPattern<TManifest extends GeneratedBroadcastManifest> = TManifest['channels'][number]['pattern'] & string;
|
|
6
|
+
type ManifestChannelEntryByPattern<TManifest extends GeneratedBroadcastManifest, TPattern extends string> = Extract<TManifest['channels'][number], {
|
|
7
|
+
pattern: TPattern;
|
|
8
|
+
}>;
|
|
9
|
+
type ManifestPresenceMember<TManifest extends GeneratedBroadcastManifest, TPattern extends string> = Extract<ManifestChannelEntryByPattern<TManifest, TPattern>, {
|
|
10
|
+
member: unknown;
|
|
11
|
+
}> extends {
|
|
12
|
+
member: infer TMember;
|
|
13
|
+
} ? TMember : BroadcastJsonObject;
|
|
14
|
+
type ManifestEventNamesForPattern<TManifest extends GeneratedBroadcastManifest, TPattern extends string> = TManifest['events'][number] extends infer TEvent ? TEvent extends {
|
|
15
|
+
readonly name: infer TName;
|
|
16
|
+
readonly channels: readonly {
|
|
17
|
+
readonly pattern: infer TEventPattern;
|
|
18
|
+
}[];
|
|
19
|
+
} ? TPattern extends TEventPattern & string ? TName & string : never : never : never;
|
|
20
|
+
type ManifestSubscriptionEventName<TManifest extends GeneratedBroadcastManifest, TChannel extends string> = string extends ManifestEventName<TManifest> ? string : TChannel extends ManifestChannelPattern<TManifest> ? ManifestEventNamesForPattern<TManifest, TChannel> : never;
|
|
21
|
+
type ManifestHookChannel<TManifest extends GeneratedBroadcastManifest> = string extends ManifestChannelPattern<TManifest> ? string : ManifestChannelPattern<TManifest>;
|
|
22
|
+
type ManifestHookEvent<TManifest extends GeneratedBroadcastManifest, TChannel extends string, TEvent extends string> = TEvent & ManifestSubscriptionEventName<TManifest, TChannel>;
|
|
23
|
+
type ManifestHookPresenceMember<TMember, TManifest extends GeneratedBroadcastManifest, TChannel extends string> = unknown extends TMember ? string extends ManifestChannelPattern<TManifest> ? BroadcastJsonObject : ManifestPresenceMember<TManifest, TChannel> : TMember;
|
|
4
24
|
interface FluxHookOptions<TManifest extends GeneratedBroadcastManifest = GeneratedBroadcastManifest> {
|
|
5
25
|
readonly client?: FluxClient<TManifest>;
|
|
6
26
|
readonly onUnmount?: (cleanup: () => void) => void;
|
|
@@ -14,12 +34,12 @@ interface FluxPresenceHookCallbacks<TMember = unknown> {
|
|
|
14
34
|
type FluxPresenceHookState<TMember = unknown> = FluxListenerControls & {
|
|
15
35
|
readonly members: readonly TMember[];
|
|
16
36
|
};
|
|
17
|
-
declare function useFlux<TEvent extends string, TManifest extends GeneratedBroadcastManifest = GeneratedBroadcastManifest>(channel:
|
|
18
|
-
declare function useFluxPublic<TEvent extends string, TManifest extends GeneratedBroadcastManifest = GeneratedBroadcastManifest>(channel:
|
|
19
|
-
declare function useFluxPrivate<TEvent extends string, TManifest extends GeneratedBroadcastManifest = GeneratedBroadcastManifest>(channel:
|
|
20
|
-
declare function useFluxPresence<TMember = unknown, TManifest extends GeneratedBroadcastManifest = GeneratedBroadcastManifest>(channel:
|
|
21
|
-
declare function useFluxNotification<TManifest extends GeneratedBroadcastManifest = GeneratedBroadcastManifest>(channel:
|
|
22
|
-
declare function useFluxModel<TEvent extends string, TManifest extends GeneratedBroadcastManifest = GeneratedBroadcastManifest>(channel:
|
|
37
|
+
declare function useFlux<TEvent extends string, TManifest extends GeneratedBroadcastManifest = GeneratedBroadcastManifest, TChannel extends ManifestHookChannel<TManifest> = ManifestHookChannel<TManifest>>(channel: TChannel & ManifestHookChannel<NoInfer<TManifest>>, events: ManifestHookEvent<NoInfer<TManifest>, TChannel, TEvent> | readonly ManifestHookEvent<NoInfer<TManifest>, TChannel, TEvent>[], callback: (payload: BroadcastPayloadFor<TEvent>) => void, options?: FluxHookOptions<TManifest>): FluxListenerControls;
|
|
38
|
+
declare function useFluxPublic<TEvent extends string, TManifest extends GeneratedBroadcastManifest = GeneratedBroadcastManifest, TChannel extends ManifestHookChannel<TManifest> = ManifestHookChannel<TManifest>>(channel: TChannel & ManifestHookChannel<NoInfer<TManifest>>, events: ManifestHookEvent<NoInfer<TManifest>, TChannel, TEvent> | readonly ManifestHookEvent<NoInfer<TManifest>, TChannel, TEvent>[], callback: (payload: BroadcastPayloadFor<TEvent>) => void, options?: FluxHookOptions<TManifest>): FluxListenerControls;
|
|
39
|
+
declare function useFluxPrivate<TEvent extends string, TManifest extends GeneratedBroadcastManifest = GeneratedBroadcastManifest, TChannel extends ManifestHookChannel<TManifest> = ManifestHookChannel<TManifest>>(channel: TChannel & ManifestHookChannel<NoInfer<TManifest>>, events: ManifestHookEvent<NoInfer<TManifest>, TChannel, TEvent> | readonly ManifestHookEvent<NoInfer<TManifest>, TChannel, TEvent>[], callback: (payload: BroadcastPayloadFor<TEvent>) => void, options?: FluxHookOptions<TManifest>): FluxListenerControls;
|
|
40
|
+
declare function useFluxPresence<TMember = unknown, TManifest extends GeneratedBroadcastManifest = GeneratedBroadcastManifest, TChannel extends ManifestHookChannel<TManifest> = ManifestHookChannel<TManifest>>(channel: TChannel & ManifestHookChannel<NoInfer<TManifest>>, callbacks?: FluxPresenceHookCallbacks<ManifestHookPresenceMember<TMember, TManifest, TChannel>>, options?: FluxHookOptions<TManifest>): FluxPresenceHookState<ManifestHookPresenceMember<TMember, TManifest, TChannel>>;
|
|
41
|
+
declare function useFluxNotification<TManifest extends GeneratedBroadcastManifest = GeneratedBroadcastManifest, TChannel extends ManifestHookChannel<TManifest> = ManifestHookChannel<TManifest>>(channel: TChannel & ManifestHookChannel<NoInfer<TManifest>>, callback: (payload: unknown) => void, options?: FluxHookOptions<TManifest>): FluxListenerControls;
|
|
42
|
+
declare function useFluxModel<TEvent extends string, TManifest extends GeneratedBroadcastManifest = GeneratedBroadcastManifest, TChannel extends ManifestHookChannel<TManifest> = ManifestHookChannel<TManifest>>(channel: TChannel & ManifestHookChannel<NoInfer<TManifest>>, events: ManifestHookEvent<NoInfer<TManifest>, TChannel, TEvent> | readonly ManifestHookEvent<NoInfer<TManifest>, TChannel, TEvent>[], callback: (payload: BroadcastPayloadFor<TEvent>) => void, options?: FluxHookOptions<TManifest>): FluxListenerControls;
|
|
23
43
|
declare function useFluxConnectionStatus<TManifest extends GeneratedBroadcastManifest = GeneratedBroadcastManifest>(options?: FluxConnectionStatusHookOptions<TManifest>): FluxConnectionStatus;
|
|
24
44
|
|
|
25
45
|
export { type FluxConnectionStatusHookOptions, type FluxHookOptions, type FluxPresenceHookCallbacks, type FluxPresenceHookState, useFlux, useFluxConnectionStatus, useFluxModel, useFluxNotification, useFluxPresence, useFluxPrivate, useFluxPublic };
|
package/dist/index.mjs
CHANGED
|
@@ -23,6 +23,20 @@ function useLatestRef(value) {
|
|
|
23
23
|
function serializeEventDependency(events) {
|
|
24
24
|
return Array.isArray(events) ? events.map(String).join("\0") : String(events);
|
|
25
25
|
}
|
|
26
|
+
function memberKey(member) {
|
|
27
|
+
return JSON.stringify(member) ?? String(member);
|
|
28
|
+
}
|
|
29
|
+
function appendPresenceMember(members, member) {
|
|
30
|
+
return Object.freeze([...members, member]);
|
|
31
|
+
}
|
|
32
|
+
function removePresenceMember(members, member) {
|
|
33
|
+
const key = memberKey(member);
|
|
34
|
+
const index = members.findIndex((candidate) => Object.is(candidate, member) || memberKey(candidate) === key);
|
|
35
|
+
if (index < 0) {
|
|
36
|
+
return members;
|
|
37
|
+
}
|
|
38
|
+
return Object.freeze(members.filter((_, candidateIndex) => candidateIndex !== index));
|
|
39
|
+
}
|
|
26
40
|
function useControls(createSubscription, onUnmount, dependencies = []) {
|
|
27
41
|
const controlsRef = useRef(createNoopControls());
|
|
28
42
|
const onUnmountRef = useLatestRef(onUnmount);
|
|
@@ -105,32 +119,49 @@ function useFluxPresence(channel, callbacks = {}, options = {}) {
|
|
|
105
119
|
const onUnmountRef = useLatestRef(options.onUnmount);
|
|
106
120
|
useEffect(() => {
|
|
107
121
|
const subscription = client.presence(channel);
|
|
122
|
+
let active = true;
|
|
108
123
|
const updateMembers = (members) => {
|
|
109
124
|
membersRef.current = members;
|
|
110
125
|
callbacksRef.current.onHere?.(membersRef.current);
|
|
111
126
|
rerender();
|
|
112
127
|
};
|
|
113
|
-
updateMembers(subscription.members);
|
|
114
|
-
const stop = subscription.__onPresenceChange?.(updateMembers);
|
|
115
128
|
const cleanup = () => {
|
|
116
|
-
|
|
129
|
+
active = false;
|
|
117
130
|
subscription.leaveChannel();
|
|
118
131
|
};
|
|
119
132
|
controlsRef.current = Object.freeze({
|
|
120
133
|
leave: () => {
|
|
134
|
+
active = false;
|
|
121
135
|
subscription.leave();
|
|
122
136
|
},
|
|
123
137
|
leaveChannel: () => {
|
|
138
|
+
active = false;
|
|
124
139
|
subscription.leaveChannel();
|
|
125
140
|
},
|
|
126
141
|
listen: () => {
|
|
142
|
+
active = true;
|
|
127
143
|
subscription.listen();
|
|
144
|
+
updateMembers(subscription.members);
|
|
128
145
|
return controlsRef.current;
|
|
129
146
|
},
|
|
130
147
|
stopListening: () => {
|
|
148
|
+
active = false;
|
|
131
149
|
subscription.stopListening();
|
|
132
150
|
}
|
|
133
151
|
});
|
|
152
|
+
subscription.here((members) => {
|
|
153
|
+
if (active) {
|
|
154
|
+
updateMembers(members);
|
|
155
|
+
}
|
|
156
|
+
}).joining((member) => {
|
|
157
|
+
if (active) {
|
|
158
|
+
updateMembers(appendPresenceMember(membersRef.current, member));
|
|
159
|
+
}
|
|
160
|
+
}).leaving((member) => {
|
|
161
|
+
if (active) {
|
|
162
|
+
updateMembers(removePresenceMember(membersRef.current, member));
|
|
163
|
+
}
|
|
164
|
+
}).listen();
|
|
134
165
|
onUnmountRef.current?.(cleanup);
|
|
135
166
|
return cleanup;
|
|
136
167
|
}, [channel, client, callbacksRef, onUnmountRef]);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@holo-js/flux-react",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Holo-JS Framework - React and Next hook skeletons for Flux",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -19,24 +19,26 @@
|
|
|
19
19
|
"scripts": {
|
|
20
20
|
"build": "tsup",
|
|
21
21
|
"stub": "tsup",
|
|
22
|
-
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
22
|
+
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.type-tests.json --noEmit",
|
|
23
23
|
"test": "vitest --run"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@holo-js/broadcast": "^0.1.
|
|
27
|
-
"@holo-js/flux": "^0.1.
|
|
26
|
+
"@holo-js/broadcast": "^0.1.5",
|
|
27
|
+
"@holo-js/flux": "^0.1.5"
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
30
|
-
"react": "^
|
|
30
|
+
"react": "^19.2.6"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
|
-
"@types/react": "^
|
|
34
|
-
"@types/react-
|
|
33
|
+
"@types/react": "^19.2.14",
|
|
34
|
+
"@types/react-dom": "^19.2.3",
|
|
35
|
+
"@types/react-test-renderer": "^19.1.0",
|
|
35
36
|
"@types/node": "^22.10.2",
|
|
36
|
-
"react": "^
|
|
37
|
-
"react-
|
|
37
|
+
"react": "^19.2.6",
|
|
38
|
+
"react-dom": "^19.2.6",
|
|
39
|
+
"react-test-renderer": "^19.2.6",
|
|
38
40
|
"tsup": "^8.3.5",
|
|
39
41
|
"typescript": "^5.7.2",
|
|
40
|
-
"vitest": "^
|
|
42
|
+
"vitest": "^4.1.5"
|
|
41
43
|
}
|
|
42
44
|
}
|