@raster-app/react 0.1.0-canary-2e1834e → 0.1.0-canary-fd0f8dd
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 +64 -78
- package/package.json +2 -4
package/README.md
CHANGED
|
@@ -1,26 +1,28 @@
|
|
|
1
1
|
# @raster-app/react
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
Raster's asset picker for React, and hooks to build your own Raster UI.
|
|
4
|
+
|
|
5
|
+
## Documentation
|
|
6
|
+
|
|
7
|
+
[raster.app/docs](https://raster.app/docs)
|
|
8
|
+
|
|
9
|
+
## Requirements
|
|
10
|
+
|
|
11
|
+
- React 18 or 19
|
|
12
|
+
- Node.js 24 or later
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
7
15
|
|
|
8
16
|
```sh
|
|
9
17
|
npm install @raster-app/react
|
|
10
18
|
```
|
|
11
19
|
|
|
12
|
-
It
|
|
13
|
-
|
|
14
|
-
from `@raster-app/react` too.
|
|
20
|
+
It includes [`@raster-app/sdk`](https://www.npmjs.com/package/@raster-app/sdk) and re-exports all
|
|
21
|
+
of it, so import the client, `toUserMessage` and types such as `Asset` from `@raster-app/react`.
|
|
15
22
|
|
|
16
|
-
##
|
|
23
|
+
## Usage
|
|
17
24
|
|
|
18
|
-
|
|
19
|
-
grant or an API key, Raster's organization switcher, the organization's libraries, search, and
|
|
20
|
-
infinite scroll. A tile opens its asset large, with Pick asset and Open in Raster, which goes
|
|
21
|
-
through the host's `openExternal`, over the asset's versions, where a variant is uploaded or set as
|
|
22
|
-
the default. It uploads into a library from its menu or a drop. An organization or a library is
|
|
23
|
-
read as the pointer reaches it, so it opens at once. It fills its container.
|
|
25
|
+
### Add the picker
|
|
24
26
|
|
|
25
27
|
```tsx
|
|
26
28
|
import {
|
|
@@ -31,11 +33,11 @@ import {
|
|
|
31
33
|
} from '@raster-app/react'
|
|
32
34
|
import '@raster-app/react/styles.css'
|
|
33
35
|
|
|
34
|
-
function Picker({ onImage }: { onImage: (url: string) => void }) {
|
|
36
|
+
export function Picker({ onImage }: { onImage: (url: string) => void }) {
|
|
35
37
|
return (
|
|
36
38
|
<RasterProvider
|
|
37
39
|
config={{
|
|
38
|
-
host: { name: '
|
|
40
|
+
host: { name: 'My App', openExternal: (url) => window.open(url, '_blank') },
|
|
39
41
|
credentials: localStorageCredentialStore(),
|
|
40
42
|
}}
|
|
41
43
|
>
|
|
@@ -45,19 +47,23 @@ function Picker({ onImage }: { onImage: (url: string) => void }) {
|
|
|
45
47
|
}
|
|
46
48
|
```
|
|
47
49
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
| `onError` | Called once with each `RasterApiError` the picker shows, for the host to log. |
|
|
54
|
-
| `theme` | `'light'` or `'dark'`. The system's color scheme when unset. |
|
|
50
|
+
`host.name` is the name Raster's sign-in page shows for your app, and `openExternal` opens that page
|
|
51
|
+
in the user's browser. `credentials` is where the sign-in is kept.
|
|
52
|
+
|
|
53
|
+
The picker signs the user in, browses their organizations and libraries, searches, uploads, and
|
|
54
|
+
lets them pick an asset or one of its versions. It fills its container.
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
| Prop | What it does |
|
|
57
|
+
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
|
|
58
|
+
| `onPick(asset, organizationId)` | Called with the picked asset. `getFullSizeUrl(asset)` is its image. |
|
|
59
|
+
| `organizationId` | Limits sign-in to this organization. |
|
|
60
|
+
| `scope` | `'org'` to ask for one organization, `'user'` for the whole account. Defaults to `'org'` with an `organizationId`. |
|
|
61
|
+
| `onError(error)` | Called with each error the picker shows, for logging. |
|
|
62
|
+
| `theme` | `'light'` or `'dark'`. Follows the system when unset. |
|
|
57
63
|
|
|
58
|
-
|
|
64
|
+
### Build your own UI
|
|
59
65
|
|
|
60
|
-
|
|
66
|
+
The same provider gives your components hooks.
|
|
61
67
|
|
|
62
68
|
```tsx
|
|
63
69
|
import {
|
|
@@ -65,73 +71,53 @@ import {
|
|
|
65
71
|
createRasterClient,
|
|
66
72
|
localStorageCredentialStore,
|
|
67
73
|
useAssets,
|
|
68
|
-
useLibraries,
|
|
69
74
|
useSession,
|
|
70
75
|
} from '@raster-app/react'
|
|
71
76
|
|
|
72
|
-
//
|
|
77
|
+
// Create the client once, outside any component.
|
|
73
78
|
const client = createRasterClient({
|
|
74
|
-
host: { name: '
|
|
79
|
+
host: { name: 'My App', openExternal: (url) => window.open(url, '_blank') },
|
|
75
80
|
credentials: localStorageCredentialStore(),
|
|
76
81
|
})
|
|
77
82
|
|
|
78
|
-
function App() {
|
|
83
|
+
export function App() {
|
|
79
84
|
return (
|
|
80
85
|
<RasterProvider client={client}>
|
|
81
|
-
<
|
|
86
|
+
<Library />
|
|
82
87
|
</RasterProvider>
|
|
83
88
|
)
|
|
84
89
|
}
|
|
85
90
|
|
|
86
|
-
function
|
|
87
|
-
const { isConfigured } = useSession()
|
|
88
|
-
const
|
|
89
|
-
const assets = useAssets({ organizationId: 'acme', libraryId: 'lib-1' })
|
|
91
|
+
function Library() {
|
|
92
|
+
const { credentials, isConfigured } = useSession()
|
|
93
|
+
const { assets, hasMore, loadMore } = useAssets({ organizationId: 'acme', libraryId: 'lib-1' })
|
|
90
94
|
|
|
95
|
+
if (credentials === undefined) return null // still loading
|
|
91
96
|
if (!isConfigured) return <SignIn />
|
|
92
|
-
return <Grid assets={assets
|
|
97
|
+
return <Grid assets={assets ?? []} onEnd={hasMore ? loadMore : undefined} />
|
|
93
98
|
}
|
|
94
99
|
```
|
|
95
100
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
|
99
|
-
|
|
|
100
|
-
| `
|
|
101
|
-
| `
|
|
102
|
-
| `
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
- **The provider fixes its client on mount.** An inline `config` builds one client for the
|
|
121
|
-
provider's life, and a later `client` prop is ignored: remount with a new `key` to switch.
|
|
122
|
-
Two clients for one credential would each refresh it, spending each other's refresh token.
|
|
123
|
-
- **`credentials` is `undefined` while the store is read.** Gate the sign-in screen on
|
|
124
|
-
`isConfigured` once it has settled, or it flashes on every launch.
|
|
125
|
-
- **Every fetch aborts when superseded**, which frees its connection for the requests that
|
|
126
|
-
follow.
|
|
127
|
-
- **The cache belongs to a sign-in.** Query keys carry the session's `credentialIdentity()`,
|
|
128
|
-
and a sign-out or a different account drops the previous one's queries. For an API key that
|
|
129
|
-
identity is a digest of the key, so the key itself stays out of the cache.
|
|
130
|
-
- **Errors are `RasterApiError`s.** Branch on `code`, and show `toUserMessage(error)`.
|
|
131
|
-
- **Raster finishes uploads and promotes after answering.** Both hooks poll until the work
|
|
132
|
-
lands, and settle as `timed-out` when it outlasts the wait: the work is still running, and a
|
|
133
|
-
later refetch shows it.
|
|
134
|
-
|
|
135
|
-
## Preact
|
|
136
|
-
|
|
137
|
-
To use the hooks with Preact, alias `react` and `react-dom` to `preact/compat` in the bundler.
|
|
101
|
+
| Hook | What it gives you |
|
|
102
|
+
| ------------------------------------------ | ---------------------------------------------------------------------- |
|
|
103
|
+
| `useSession()` | `isConfigured`, `isSignedIn`, `userName` and `signOut()`. |
|
|
104
|
+
| `useSignIn()` | Sign-in with Raster's device flow or an API key. |
|
|
105
|
+
| `useOrganizations()` | The organizations the user can reach, in `data`. |
|
|
106
|
+
| `useLibraries({ organizationId })` | An organization's libraries, in `data`, each with the user's `access`. |
|
|
107
|
+
| `useAssets({ organizationId, libraryId })` | A library's `assets`, with `loadMore()`. |
|
|
108
|
+
| `useAssetSearch(scope, query)` | Search results, `hits` and `found`, as the user types. |
|
|
109
|
+
| `useAssetUpload()` | `upload()` a file, then wait for Raster to process it. |
|
|
110
|
+
| `usePromoteVariant()` | Make a variant its asset's default. |
|
|
111
|
+
| `useRasterNavigation({ organizations })` | The open organization, library and asset, remembered between visits. |
|
|
112
|
+
|
|
113
|
+
`RasterProvider` takes a `client`, or a `config` to create one, and `state`, where navigation is
|
|
114
|
+
remembered: `memoryStateStore()` by default, or `localStorageStateStore()`.
|
|
115
|
+
|
|
116
|
+
### Errors
|
|
117
|
+
|
|
118
|
+
Every failure is a `RasterApiError`. Show the user `toUserMessage(error)`, and branch on
|
|
119
|
+
`error.code`.
|
|
120
|
+
|
|
121
|
+
## License
|
|
122
|
+
|
|
123
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@raster-app/react",
|
|
3
|
-
"version": "0.1.0-canary-
|
|
3
|
+
"version": "0.1.0-canary-fd0f8dd",
|
|
4
4
|
"description": "React provider and hooks for the Raster SDK: session, organizations, libraries, assets, search and uploads.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://raster.app/docs",
|
|
@@ -10,8 +10,6 @@
|
|
|
10
10
|
"assets",
|
|
11
11
|
"react",
|
|
12
12
|
"hooks",
|
|
13
|
-
"figma",
|
|
14
|
-
"sanity",
|
|
15
13
|
"plugin"
|
|
16
14
|
],
|
|
17
15
|
"type": "module",
|
|
@@ -42,7 +40,7 @@
|
|
|
42
40
|
"test": "bun test"
|
|
43
41
|
},
|
|
44
42
|
"dependencies": {
|
|
45
|
-
"@raster-app/sdk": "0.1.0-canary-
|
|
43
|
+
"@raster-app/sdk": "0.1.0-canary-fd0f8dd",
|
|
46
44
|
"@tanstack/react-query": "^5.103.1"
|
|
47
45
|
},
|
|
48
46
|
"peerDependencies": {
|