@kosdev-code/kos-asset-manager 0.0.1-next.25 → 0.0.1-next.29
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 +113 -31
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -119,37 +119,114 @@ keys when the declaration is generated:
|
|
|
119
119
|
|
|
120
120
|
A pattern that matches nothing is reported during the build.
|
|
121
121
|
|
|
122
|
-
##
|
|
122
|
+
## Installing
|
|
123
|
+
|
|
124
|
+
```sh
|
|
125
|
+
npm install @kosdev-code/kos-asset-manager
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
The package is ESM. `@kosdev-code/kos-ui-sdk` (`~3.0.0`) and React 18 or
|
|
129
|
+
newer are peer dependencies, so it uses the copies the application already
|
|
130
|
+
has.
|
|
131
|
+
|
|
132
|
+
## Setting it up
|
|
133
|
+
|
|
134
|
+
Register the models where the application registers everything else. Note the
|
|
135
|
+
second call — `registerAssetModels` returns a function.
|
|
123
136
|
|
|
124
137
|
```ts
|
|
125
|
-
import {
|
|
138
|
+
import { KosModelRegistry } from '@kosdev-code/kos-dispense-sdk';
|
|
139
|
+
import { registerAssetModels } from '@kosdev-code/kos-asset-manager';
|
|
126
140
|
|
|
127
|
-
|
|
128
|
-
|
|
141
|
+
KosModelRegistry.dispense.models();
|
|
142
|
+
registerAssetModels(KosModelRegistry)();
|
|
143
|
+
```
|
|
129
144
|
|
|
130
|
-
|
|
131
|
-
|
|
145
|
+
Then wrap the tree in the provider, which loads the declarations everything
|
|
146
|
+
else reads:
|
|
132
147
|
|
|
133
|
-
|
|
134
|
-
|
|
148
|
+
```tsx
|
|
149
|
+
import { KosAssetProvider } from '@kosdev-code/kos-asset-manager';
|
|
150
|
+
|
|
151
|
+
const App = () => (
|
|
152
|
+
<KosTranslationProvider>
|
|
153
|
+
<KosAssetProvider contexts={['my.app.id']} gate>
|
|
154
|
+
<MyScreens />
|
|
155
|
+
</KosAssetProvider>
|
|
156
|
+
</KosTranslationProvider>
|
|
157
|
+
);
|
|
158
|
+
```
|
|
135
159
|
|
|
136
|
-
|
|
137
|
-
|
|
160
|
+
`contexts` names the applications whose assets this ui uses, so it loads only
|
|
161
|
+
what it needs; omit it to load everything the device declares, which is what
|
|
162
|
+
a tool that browses them wants. `gate` holds the children back until the
|
|
163
|
+
assets have loaded, which is worth it when the first screen renders them.
|
|
164
|
+
|
|
165
|
+
`contexts` is also the tie-break order for a bare key: named contexts are
|
|
166
|
+
searched first, in the order given, then everything else.
|
|
167
|
+
|
|
168
|
+
For an application that would rather drive its own loading UI,
|
|
169
|
+
`useAssetManager(contexts?)` is what the provider uses internally and returns
|
|
170
|
+
`{ model, ready, status, KosModelLoader }`. `useKosAssetContext()` returns
|
|
171
|
+
`{ model }` for components that want the model rather than the helpers.
|
|
172
|
+
|
|
173
|
+
## Using assets
|
|
174
|
+
|
|
175
|
+
```tsx
|
|
176
|
+
import { kosComponent } from '@kosdev-code/kos-ui-sdk';
|
|
177
|
+
import { wrapAsset } from '@kosdev-code/kos-asset-manager';
|
|
178
|
+
|
|
179
|
+
export const Header = kosComponent(() => {
|
|
180
|
+
const logo = wrapAsset('brand/logo-primary');
|
|
181
|
+
|
|
182
|
+
return (
|
|
183
|
+
<img src={logo.src} width={logo.width} height={logo.height} alt="Home" />
|
|
184
|
+
);
|
|
185
|
+
});
|
|
138
186
|
```
|
|
139
187
|
|
|
188
|
+
`wrapAsset(key)` returns a `ResolvedAsset`: `src`, `width`, `height`,
|
|
189
|
+
`poster`, `type`, `size`, `hash`, `tags`, `key`, `context` and `exists`.
|
|
190
|
+
Images are measured when the declaration is generated, so passing `width` and
|
|
191
|
+
`height` reserves the space and nothing reflows when the file arrives. An
|
|
192
|
+
unknown key logs a warning and comes back with `exists: false` and an empty
|
|
193
|
+
`src` rather than throwing, so a missing asset never takes a screen down.
|
|
194
|
+
|
|
195
|
+
Two things to get right. The helpers read MobX models, so a component that
|
|
196
|
+
reads them should be a `kosComponent` — otherwise it renders once with
|
|
197
|
+
whatever was loaded at the time and never updates. And resolve inside the
|
|
198
|
+
component rather than at module scope: a value computed when the module loads
|
|
199
|
+
runs before the provider has loaded anything.
|
|
200
|
+
|
|
201
|
+
`resolveAsset(key)` is the url on its own, for anywhere a url is expected:
|
|
202
|
+
|
|
203
|
+
```ts
|
|
204
|
+
element.style.backgroundImage = `url(${resolveAsset('brand/logo-primary')})`;
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
`hasAsset(key)` is true when a loaded application declares the key, for
|
|
208
|
+
branching on an optional asset without the warning `wrapAsset` logs.
|
|
209
|
+
|
|
210
|
+
A key resolves in the contexts named at the provider, first match winning,
|
|
211
|
+
unless it names one: `other.app.id:brand/logo-primary`.
|
|
212
|
+
|
|
213
|
+
## Selecting sets
|
|
214
|
+
|
|
140
215
|
Sets of assets are selected rather than named, so adding a file to a folder
|
|
141
216
|
is all it takes to include it:
|
|
142
217
|
|
|
143
218
|
```ts
|
|
219
|
+
listAssets({ tag: 'beverage-logo' }).map((asset) => asset.src);
|
|
220
|
+
|
|
144
221
|
await preloadAssets({ prefix: 'beverages/' }); // a folder
|
|
145
222
|
await preloadAssets({ tag: 'beverage-logo' }); // a tag, across folders
|
|
146
223
|
await preloadAssets({ type: 'video/' }); // by mime type
|
|
147
|
-
|
|
148
|
-
listAssets({ tag: 'beverage-logo' }).map((asset) => asset.src);
|
|
149
224
|
```
|
|
150
225
|
|
|
151
|
-
|
|
152
|
-
|
|
226
|
+
An `AssetSelector` has `context`, `prefix`, `tag`, `type` and `keys`, and the
|
|
227
|
+
fields combine — `{ prefix: 'brand/', type: 'image/svg+xml' }` is the svg
|
|
228
|
+
files in that folder. `listAssets()` with no selector is everything loaded,
|
|
229
|
+
and `contextNames()` is the application ids that declared assets.
|
|
153
230
|
|
|
154
231
|
## Preloading during bootstrap
|
|
155
232
|
|
|
@@ -160,6 +237,15 @@ which is what makes images pop into view on lower powered hardware. Paying
|
|
|
160
237
|
for it during a bootstrap sequence trades a couple of seconds at startup for
|
|
161
238
|
screens that render immediately afterwards.
|
|
162
239
|
|
|
240
|
+
`preloadAssets` takes a group name, a key, an array of either, or a selector:
|
|
241
|
+
|
|
242
|
+
```ts
|
|
243
|
+
await preloadAssets('boot'); // a group from the declaration
|
|
244
|
+
await preloadAssets('brand/logo-primary'); // one key
|
|
245
|
+
await preloadAssets(['boot', 'checkout']); // several
|
|
246
|
+
await preloadAssets({ prefix: 'beverages/' }); // a selector
|
|
247
|
+
```
|
|
248
|
+
|
|
163
249
|
```ts
|
|
164
250
|
await preloadAssets({ prefix: 'beverages/' }, {
|
|
165
251
|
concurrency: 4,
|
|
@@ -167,23 +253,19 @@ await preloadAssets({ prefix: 'beverages/' }, {
|
|
|
167
253
|
});
|
|
168
254
|
```
|
|
169
255
|
|
|
170
|
-
Assets are readied a few at a time
|
|
171
|
-
only thrashes. A single asset that cannot be
|
|
172
|
-
`onProgress` with `ok: false` and never fails the
|
|
173
|
-
cannot stop a device from starting.
|
|
174
|
-
|
|
175
|
-
Images are measured when the declaration is generated, so the space they
|
|
176
|
-
take can be reserved and nothing reflows when they arrive:
|
|
256
|
+
Assets are readied a few at a time (`concurrency`, 4 by default), because a
|
|
257
|
+
wide fan out on a slow device only thrashes. A single asset that cannot be
|
|
258
|
+
readied is reported through `onProgress` with `ok: false` and never fails the
|
|
259
|
+
sequence, so one bad file cannot stop a device from starting.
|
|
177
260
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
261
|
+
`preloadDeclared(options?)` readies every loaded asset whose declaration set
|
|
262
|
+
`preload: true`, so the application doesn't have to know which those are.
|
|
263
|
+
`releaseAssets()` drops the decoded images preloading is holding — worth
|
|
264
|
+
calling when leaving a section whose assets are large and won't be shown
|
|
265
|
+
again.
|
|
182
266
|
|
|
183
|
-
|
|
184
|
-
worth it only when an asset must survive the content going away.
|
|
185
|
-
`releaseAssets()` drops everything preloading is holding.
|
|
267
|
+
## Where the files come from
|
|
186
268
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
269
|
+
Urls are built against the `host` query parameter when there is one, and the
|
|
270
|
+
page's own origin otherwise, so a ui run on a laptop against a device
|
|
271
|
+
resolves assets by opening it with `?host=http://device-address`.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kosdev-code/kos-asset-manager",
|
|
3
|
-
"version": "0.0.1-next.
|
|
3
|
+
"version": "0.0.1-next.29",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"types": "./index.d.ts",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
"kos": {
|
|
27
27
|
"build": {
|
|
28
|
-
"gitHash": "
|
|
28
|
+
"gitHash": "1b2fc996563150e3da055a9506a28b7cb132c060"
|
|
29
29
|
}
|
|
30
30
|
},
|
|
31
31
|
"publishConfig": {
|