@phreshos/react 0.1.11 → 0.1.13
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
|
@@ -16,7 +16,7 @@ dependencies.
|
|
|
16
16
|
|
|
17
17
|
It provides two kinds of adapter:
|
|
18
18
|
|
|
19
|
-
- `
|
|
19
|
+
- `ContextProvider` resolves exactly the runtime values named by its required
|
|
20
20
|
`provide` prop, then exposes them synchronously through `useProgram()`,
|
|
21
21
|
`useProcess()`, and `useParent()`.
|
|
22
22
|
- `SystemProvider` subscribes before reading exactly the system values named by its
|
|
@@ -33,8 +33,8 @@ It provides two kinds of adapter:
|
|
|
33
33
|
while `useObserveAnswers()` adapts a Server traffic surface's answer
|
|
34
34
|
observation.
|
|
35
35
|
|
|
36
|
-
Window needs no React resolution: `
|
|
37
|
-
silent capability object. `
|
|
36
|
+
Window needs no React resolution: `context.window` is already a synchronous,
|
|
37
|
+
silent capability object. `ContextProvider` therefore has no `window` selection
|
|
38
38
|
and the React SDK exposes no pass-through `useWindow()` hook.
|
|
39
39
|
|
|
40
40
|
The domain state hooks return only mutable state; identity and immutable
|
|
@@ -111,13 +111,14 @@ because either SDK was imported, and an unselected system value never enters the
|
|
|
111
111
|
Client. `pointerPosition` is permission-guarded: selecting it does not request
|
|
112
112
|
permission, and resolution fails unless the Program already holds `pointer`.
|
|
113
113
|
The provider renders its optional fallback, or `null`, until every selected
|
|
114
|
-
value resolves. `useDesktopPreferences()` is a pure state adapter
|
|
115
|
-
|
|
114
|
+
value resolves. `useDesktopPreferences()` is a pure state adapter. The System
|
|
115
|
+
communicates its effective scheme through the Client iframe, while each Client
|
|
116
|
+
HTML document declares which schemes it supports.
|
|
116
117
|
|
|
117
118
|
```tsx
|
|
118
|
-
import {
|
|
119
|
+
import { context } from "@phreshos/client"
|
|
119
120
|
import {
|
|
120
|
-
|
|
121
|
+
ContextProvider,
|
|
121
122
|
useProgram,
|
|
122
123
|
useSubscribe
|
|
123
124
|
} from "@phreshos/react"
|
|
@@ -125,7 +126,7 @@ import {
|
|
|
125
126
|
function Counter() {
|
|
126
127
|
const program = useProgram()
|
|
127
128
|
|
|
128
|
-
const count = useSubscribe(
|
|
129
|
+
const count = useSubscribe(context, "count", message => {
|
|
129
130
|
return Number(message.payload)
|
|
130
131
|
})
|
|
131
132
|
|
|
@@ -134,14 +135,14 @@ function Counter() {
|
|
|
134
135
|
|
|
135
136
|
export default function App() {
|
|
136
137
|
return (
|
|
137
|
-
<
|
|
138
|
+
<ContextProvider provide={["program"]} fallback={<p>Loading…</p>} waitServer>
|
|
138
139
|
<Counter />
|
|
139
|
-
</
|
|
140
|
+
</ContextProvider>
|
|
140
141
|
)
|
|
141
142
|
}
|
|
142
143
|
```
|
|
143
144
|
|
|
144
|
-
Using a
|
|
145
|
+
Using a context or system hook outside its provider, or without selecting its
|
|
145
146
|
value, throws a configuration error. Neither provider supplies an implicit
|
|
146
147
|
"everything" selection, so adding a future capability cannot make it enter an
|
|
147
148
|
existing application.
|
|
@@ -1,34 +1,34 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
2
|
import { type Process, type Program } from "@phreshos/client";
|
|
3
3
|
declare const provisionNames: readonly ["program", "process", "parent"];
|
|
4
|
-
/** Resolves only the
|
|
5
|
-
export default function
|
|
4
|
+
/** Resolves only the runtime handles explicitly selected by the program. */
|
|
5
|
+
export default function ContextProvider({ children, fallback, provide, waitServer }: ContextProviderProperties): import("react").FunctionComponentElement<SelectedContextProviderProperties>;
|
|
6
6
|
/** Returns the current Program selected by the nearest provider. */
|
|
7
7
|
export declare function useProgram(): Program;
|
|
8
8
|
/** Returns the current Process selected by the nearest provider. */
|
|
9
9
|
export declare function useProcess(): Process;
|
|
10
10
|
/** Returns the current Process's selected visible parent. */
|
|
11
11
|
export declare function useParent(): Process | null;
|
|
12
|
-
/** Values that
|
|
13
|
-
export type
|
|
14
|
-
/** Required non-empty selection of
|
|
15
|
-
export type
|
|
16
|
-
/** Properties accepted by
|
|
17
|
-
export interface
|
|
18
|
-
/** Content rendered after every selected
|
|
12
|
+
/** Values that ContextProvider can resolve. */
|
|
13
|
+
export type ContextProvisionName = typeof provisionNames[number];
|
|
14
|
+
/** Required non-empty selection of runtime values. */
|
|
15
|
+
export type ContextProvision = readonly [ContextProvisionName, ...ContextProvisionName[]];
|
|
16
|
+
/** Properties accepted by ContextProvider. */
|
|
17
|
+
export interface ContextProviderProperties {
|
|
18
|
+
/** Content rendered after every selected runtime handle has resolved. */
|
|
19
19
|
readonly children: ReactNode;
|
|
20
20
|
/** Content rendered while selected handles or optional Server readiness resolve. */
|
|
21
21
|
readonly fallback?: ReactNode;
|
|
22
|
-
/** Exact
|
|
23
|
-
readonly provide:
|
|
22
|
+
/** Exact runtime values made available to descendant hooks. */
|
|
23
|
+
readonly provide: ContextProvision;
|
|
24
24
|
/**
|
|
25
25
|
* Waits for the Process's Server before rendering children.
|
|
26
26
|
* `true` uses the default ten-second deadline; a number sets milliseconds.
|
|
27
27
|
*/
|
|
28
28
|
readonly waitServer?: boolean | number;
|
|
29
29
|
}
|
|
30
|
-
type
|
|
31
|
-
selection: readonly
|
|
30
|
+
type SelectedContextProviderProperties = Omit<ContextProviderProperties, "provide" | "waitServer"> & Readonly<{
|
|
31
|
+
selection: readonly ContextProvisionName[];
|
|
32
32
|
waitServer: boolean | number;
|
|
33
33
|
}>;
|
|
34
34
|
export {};
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { createContext, createElement, useContext, useEffect, useMemo, useState } from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { context } from "@phreshos/client";
|
|
3
3
|
const provisionNames = ["program", "process", "parent"];
|
|
4
|
-
const
|
|
5
|
-
/** Resolves only the
|
|
6
|
-
export default function
|
|
4
|
+
const RuntimeContext = createContext(null);
|
|
5
|
+
/** Resolves only the runtime handles explicitly selected by the program. */
|
|
6
|
+
export default function ContextProvider({ children, fallback = null, provide, waitServer = false }) {
|
|
7
7
|
const normalized = normalizeProvision(provide);
|
|
8
8
|
const selectionKey = normalized.join("\0");
|
|
9
9
|
const selection = useMemo(() => normalized, [selectionKey]);
|
|
10
|
-
return createElement(
|
|
10
|
+
return createElement(SelectedContextProvider, {
|
|
11
11
|
children,
|
|
12
12
|
fallback,
|
|
13
13
|
key: `${selectionKey}\0${String(waitServer)}`,
|
|
@@ -15,12 +15,12 @@ export default function CurrentProvider({ children, fallback = null, provide, wa
|
|
|
15
15
|
waitServer
|
|
16
16
|
});
|
|
17
17
|
}
|
|
18
|
-
function
|
|
18
|
+
function SelectedContextProvider({ children, fallback, selection, waitServer }) {
|
|
19
19
|
const [resolution, setResolution] = useState({ status: "pending" });
|
|
20
20
|
useEffect(() => {
|
|
21
21
|
let active = true;
|
|
22
22
|
setResolution({ status: "pending" });
|
|
23
|
-
void
|
|
23
|
+
void resolveContext(selection, waitServer).then(value => {
|
|
24
24
|
if (active)
|
|
25
25
|
setResolution({ status: "ready", value });
|
|
26
26
|
}, error => {
|
|
@@ -33,12 +33,12 @@ function SelectedCurrentProvider({ children, fallback, selection, waitServer })
|
|
|
33
33
|
return fallback;
|
|
34
34
|
if (resolution.status === "error")
|
|
35
35
|
throw resolution.error;
|
|
36
|
-
return createElement(
|
|
36
|
+
return createElement(RuntimeContext.Provider, { value: resolution.value }, children);
|
|
37
37
|
}
|
|
38
|
-
async function
|
|
38
|
+
async function resolveContext(selection, waitServer) {
|
|
39
39
|
const serverReady = typeof waitServer === "number"
|
|
40
|
-
?
|
|
41
|
-
: waitServer ?
|
|
40
|
+
? context.server.waitReady(waitServer)
|
|
41
|
+
: waitServer ? context.server.waitReady() : undefined;
|
|
42
42
|
const [entries] = await Promise.all([
|
|
43
43
|
Promise.all(selection.map(resolveProvision)),
|
|
44
44
|
serverReady
|
|
@@ -50,9 +50,9 @@ async function resolveCurrent(selection, waitServer) {
|
|
|
50
50
|
}
|
|
51
51
|
async function resolveProvision(name) {
|
|
52
52
|
switch (name) {
|
|
53
|
-
case "program": return [name, await
|
|
54
|
-
case "process": return [name, await
|
|
55
|
-
case "parent": return [name, await
|
|
53
|
+
case "program": return [name, await context.program()];
|
|
54
|
+
case "process": return [name, await context.process()];
|
|
55
|
+
case "parent": return [name, await context.parent()];
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
/** Returns the current Program selected by the nearest provider. */
|
|
@@ -68,22 +68,22 @@ export function useParent() {
|
|
|
68
68
|
return useProvided("parent");
|
|
69
69
|
}
|
|
70
70
|
function useProvided(name) {
|
|
71
|
-
const
|
|
72
|
-
if (!
|
|
73
|
-
throw new Error(`use${hookName(name)} must be used inside
|
|
74
|
-
if (!
|
|
75
|
-
throw new Error(`use${hookName(name)} requires "${name}" in
|
|
76
|
-
return
|
|
71
|
+
const providedContext = useContext(RuntimeContext);
|
|
72
|
+
if (!providedContext)
|
|
73
|
+
throw new Error(`use${hookName(name)} must be used inside ContextProvider`);
|
|
74
|
+
if (!providedContext.provided.has(name))
|
|
75
|
+
throw new Error(`use${hookName(name)} requires "${name}" in ContextProvider's provide prop`);
|
|
76
|
+
return providedContext.values[name];
|
|
77
77
|
}
|
|
78
78
|
function normalizeProvision(provide) {
|
|
79
79
|
if (!Array.isArray(provide) || provide.length === 0)
|
|
80
|
-
throw new Error("
|
|
80
|
+
throw new Error("ContextProvider's provide prop must select at least one runtime value");
|
|
81
81
|
const selected = new Set();
|
|
82
82
|
for (const name of provide) {
|
|
83
83
|
if (!provisionNames.includes(name))
|
|
84
|
-
throw new Error(`
|
|
84
|
+
throw new Error(`ContextProvider cannot provide "${String(name)}"`);
|
|
85
85
|
if (selected.has(name))
|
|
86
|
-
throw new Error(`
|
|
86
|
+
throw new Error(`ContextProvider's provide prop selects "${name}" more than once`);
|
|
87
87
|
selected.add(name);
|
|
88
88
|
}
|
|
89
89
|
return [...selected];
|
package/dist/main.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { default as
|
|
1
|
+
export { default as ContextProvider, useParent, useProcess, useProgram, type ContextProvision, type ContextProvisionName, type ContextProviderProperties } from "./context-provider.js";
|
|
2
2
|
export { default as SystemProvider, usePointerPosition, useDesktopSize, useDesktopPreferences, useSystemAppearance, type SystemProvision, type SystemProvisionName, type SystemProviderProperties } from "./system-provider.js";
|
|
3
3
|
export { default as useSubscribe } from "./use-subscribe.js";
|
|
4
4
|
export { default as useObserve } from "./use-observe.js";
|
package/dist/main.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { default as
|
|
1
|
+
export { default as ContextProvider, useParent, useProcess, useProgram } from "./context-provider.js";
|
|
2
2
|
export { default as SystemProvider, usePointerPosition, useDesktopSize, useDesktopPreferences, useSystemAppearance } from "./system-provider.js";
|
|
3
3
|
export { default as useSubscribe } from "./use-subscribe.js";
|
|
4
4
|
export { default as useObserve } from "./use-observe.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Service } from "@phreshos/client";
|
|
2
2
|
/** Live availability of one exact service identity. */
|
|
3
3
|
export type ServiceState = Readonly<{
|
|
4
4
|
enabled: boolean;
|
|
5
5
|
}>;
|
|
6
6
|
/** Explicitly reads and follows one service while this hook is mounted. */
|
|
7
|
-
export default function useServiceState(service:
|
|
7
|
+
export default function useServiceState(service: Service): ServiceState | undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phreshos/react",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.13",
|
|
4
4
|
"description": "React adapters for the Client SDK.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/main.js",
|
|
@@ -47,13 +47,13 @@
|
|
|
47
47
|
"prepack": "node --run test && node --run build"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
|
-
"@phreshos/client": "^0.1.
|
|
51
|
-
"@phreshos/core": "^0.1.
|
|
50
|
+
"@phreshos/client": "^0.1.25",
|
|
51
|
+
"@phreshos/core": "^0.1.24",
|
|
52
52
|
"react": "^19.2.0"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
-
"@phreshos/client": "^0.1.
|
|
56
|
-
"@phreshos/core": "^0.1.
|
|
55
|
+
"@phreshos/client": "^0.1.25",
|
|
56
|
+
"@phreshos/core": "^0.1.24",
|
|
57
57
|
"@testing-library/react": "^16.3.0",
|
|
58
58
|
"@types/react": "^19.2.18",
|
|
59
59
|
"@types/react-dom": "^19.2.4",
|