@affordant/react 0.2.0 → 0.3.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/README.md +19 -13
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -3
- package/package.json +3 -25
- package/dist/effect.d.ts +0 -29
- package/dist/effect.d.ts.map +0 -1
- package/dist/effect.js +0 -20
- package/dist/effect.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
# @affordant/react
|
|
2
2
|
|
|
3
|
-
React adapter for [Affordant](https://leroy-florian.github.io/Affordant/). Gate your UI on what the server offers, and
|
|
3
|
+
React adapter for [Affordant](https://leroy-florian.github.io/Affordant/). Gate your UI on what the server offers, and follow affordances with hooks. No runtime dependency beyond React.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm install @affordant/react react
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Gating
|
|
6
12
|
|
|
7
13
|
```tsx
|
|
8
14
|
import { useAffordance } from '@affordant/react'
|
|
@@ -14,7 +20,7 @@ function CancelButton({ order }) {
|
|
|
14
20
|
}
|
|
15
21
|
```
|
|
16
22
|
|
|
17
|
-
##
|
|
23
|
+
## Following
|
|
18
24
|
|
|
19
25
|
```tsx
|
|
20
26
|
import { useAffordance, useFollow } from '@affordant/react'
|
|
@@ -27,20 +33,20 @@ const { run, running } = useFollow()
|
|
|
27
33
|
</button>
|
|
28
34
|
```
|
|
29
35
|
|
|
30
|
-
|
|
36
|
+
`run` resolves with the raw `Response` and re-throws on failure, with `error` set.
|
|
31
37
|
|
|
32
|
-
|
|
38
|
+
## Using Effect
|
|
33
39
|
|
|
34
|
-
|
|
35
|
-
import { makeEffectHooks } from 'effect-react-bridge'
|
|
36
|
-
import { makeAffordanceHooks } from '@affordant/react/effect'
|
|
40
|
+
There is no Effect entry point, and none is needed: `run` (and the underlying `follow`) return a `Promise<Response>`, which drops into Effect with a one-line wrap — `Effect.tryPromise(() => follow(action, init))`. Affordant stays Effect-compatible without shipping an Effect dependency.
|
|
37
41
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
+
## API
|
|
43
|
+
|
|
44
|
+
| Export | Description |
|
|
45
|
+
|---|---|
|
|
46
|
+
| `useAffordance(resource, rel)` | `{ can, action }` — memoised, null-safe gating over `can` / `actionFor`. |
|
|
47
|
+
| `useFollow()` | `{ running, error, run }` — follow an action, tracking request state. |
|
|
42
48
|
|
|
43
|
-
`react` is a peer dependency
|
|
49
|
+
`react` is a peer dependency.
|
|
44
50
|
|
|
45
51
|
## License
|
|
46
52
|
|
package/dist/index.d.ts
CHANGED
|
@@ -27,9 +27,9 @@ export interface UseFollowResult extends FollowState {
|
|
|
27
27
|
readonly run: (action: HateoasAction, init?: FollowInit) => Promise<Response>;
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
30
|
+
* Follow an affordance from a hook: tracks `running` / `error` around the
|
|
31
|
+
* client's `follow`. `run` resolves with the raw `Response` and re-throws on
|
|
32
|
+
* failure (with `error` set).
|
|
33
33
|
*/
|
|
34
34
|
export declare function useFollow(): UseFollowResult;
|
|
35
35
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -13,9 +13,9 @@ export function useAffordance(resource, rel) {
|
|
|
13
13
|
return useMemo(() => ({ can: can(resource, rel), action: actionFor(resource, rel) }), [resource, rel]);
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
16
|
+
* Follow an affordance from a hook: tracks `running` / `error` around the
|
|
17
|
+
* client's `follow`. `run` resolves with the raw `Response` and re-throws on
|
|
18
|
+
* failure (with `error` set).
|
|
19
19
|
*/
|
|
20
20
|
export function useFollow() {
|
|
21
21
|
const [state, setState] = useState({ running: false, error: null });
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@affordant/react",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "React adapter for Affordant: gate UI on the server's affordances and
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "React adapter for Affordant: gate UI on the server's affordances and follow them with hooks. Zero runtime dependencies beyond React.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Florian Leroy",
|
|
7
7
|
"repository": {
|
|
@@ -26,10 +26,6 @@
|
|
|
26
26
|
".": {
|
|
27
27
|
"types": "./dist/index.d.ts",
|
|
28
28
|
"import": "./dist/index.js"
|
|
29
|
-
},
|
|
30
|
-
"./effect": {
|
|
31
|
-
"types": "./dist/effect.d.ts",
|
|
32
|
-
"import": "./dist/effect.js"
|
|
33
29
|
}
|
|
34
30
|
},
|
|
35
31
|
"files": [
|
|
@@ -43,25 +39,7 @@
|
|
|
43
39
|
"@affordant/contract": "^0.2.0"
|
|
44
40
|
},
|
|
45
41
|
"peerDependencies": {
|
|
46
|
-
"react": ">=18"
|
|
47
|
-
"effect": "^3.21.0",
|
|
48
|
-
"effect-react-bridge": ">=0.1.0",
|
|
49
|
-
"@affordant/effect": ">=0.1.0"
|
|
50
|
-
},
|
|
51
|
-
"peerDependenciesMeta": {
|
|
52
|
-
"effect": {
|
|
53
|
-
"optional": true
|
|
54
|
-
},
|
|
55
|
-
"effect-react-bridge": {
|
|
56
|
-
"optional": true
|
|
57
|
-
},
|
|
58
|
-
"@affordant/effect": {
|
|
59
|
-
"optional": true
|
|
60
|
-
}
|
|
61
|
-
},
|
|
62
|
-
"devDependencies": {
|
|
63
|
-
"@affordant/effect": "*",
|
|
64
|
-
"effect-react-bridge": "*"
|
|
42
|
+
"react": ">=18"
|
|
65
43
|
},
|
|
66
44
|
"scripts": {
|
|
67
45
|
"build": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.build.json",
|
package/dist/effect.d.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import type { EffectHooks } from 'effect-react-bridge';
|
|
2
|
-
import { type FollowError } from '@affordant/effect';
|
|
3
|
-
import type { FollowInit } from 'affordant';
|
|
4
|
-
import type { HateoasAction } from '@affordant/contract';
|
|
5
|
-
export interface EffectFollowResult {
|
|
6
|
-
readonly running: boolean;
|
|
7
|
-
readonly error: FollowError | null;
|
|
8
|
-
readonly run: (action: HateoasAction, init?: FollowInit) => Promise<Response>;
|
|
9
|
-
}
|
|
10
|
-
export interface AffordanceEffectHooks {
|
|
11
|
-
/**
|
|
12
|
-
* The Effect invoker as a hook, run through the supplied
|
|
13
|
-
* `effect-react-bridge` runtime: tracks `running` / `error` and interrupts
|
|
14
|
-
* the request when the component unmounts.
|
|
15
|
-
*/
|
|
16
|
-
useFollow(): EffectFollowResult;
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Compose the Effect invoker (`@affordant/effect`) with an
|
|
20
|
-
* `effect-react-bridge` runtime to get React hooks. The bridge stays
|
|
21
|
-
* domain-agnostic; this is the thin Affordant-specific glue.
|
|
22
|
-
*
|
|
23
|
-
* ```ts
|
|
24
|
-
* const { useEffectFn } = makeEffectHooks({ runtime })
|
|
25
|
-
* const affordances = makeAffordanceHooks({ useEffectFn } as EffectHooks<never>)
|
|
26
|
-
* ```
|
|
27
|
-
*/
|
|
28
|
-
export declare function makeAffordanceHooks<R>(hooks: EffectHooks<R>): AffordanceEffectHooks;
|
|
29
|
-
//# sourceMappingURL=effect.d.ts.map
|
package/dist/effect.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"effect.d.ts","sourceRoot":"","sources":["../src/effect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,EAA0B,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC5E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAC3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAExD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAAA;IAClC,QAAQ,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,CAAC,EAAE,UAAU,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;CAC9E;AAED,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,SAAS,IAAI,kBAAkB,CAAA;CAChC;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,qBAAqB,CASnF"}
|
package/dist/effect.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { follow as effectFollow } from '@affordant/effect';
|
|
2
|
-
/**
|
|
3
|
-
* Compose the Effect invoker (`@affordant/effect`) with an
|
|
4
|
-
* `effect-react-bridge` runtime to get React hooks. The bridge stays
|
|
5
|
-
* domain-agnostic; this is the thin Affordant-specific glue.
|
|
6
|
-
*
|
|
7
|
-
* ```ts
|
|
8
|
-
* const { useEffectFn } = makeEffectHooks({ runtime })
|
|
9
|
-
* const affordances = makeAffordanceHooks({ useEffectFn } as EffectHooks<never>)
|
|
10
|
-
* ```
|
|
11
|
-
*/
|
|
12
|
-
export function makeAffordanceHooks(hooks) {
|
|
13
|
-
return {
|
|
14
|
-
useFollow() {
|
|
15
|
-
const { running, error, run } = hooks.useEffectFn((action, init) => effectFollow(action, init));
|
|
16
|
-
return { running, error, run };
|
|
17
|
-
},
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
//# sourceMappingURL=effect.js.map
|
package/dist/effect.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"effect.js","sourceRoot":"","sources":["../src/effect.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,IAAI,YAAY,EAAoB,MAAM,mBAAmB,CAAA;AAmB5E;;;;;;;;;GASG;AACH,MAAM,UAAU,mBAAmB,CAAI,KAAqB;IAC1D,OAAO;QACL,SAAS;YACP,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC,WAAW,CAC/C,CAAC,MAAqB,EAAE,IAAiB,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,CACzE,CAAA;YACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,CAAA;QAChC,CAAC;KACF,CAAA;AACH,CAAC"}
|