@lotics/app-sdk 0.87.4 → 0.87.6
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/src/hooks.js +9 -3
- package/dist/src/row.d.ts +3 -1
- package/dist/src/row.js +3 -1
- package/docs/data_fetching.md +5 -2
- package/docs/workflows.md +18 -1
- package/package.json +1 -1
package/dist/src/hooks.js
CHANGED
|
@@ -71,6 +71,14 @@ function swrConfig(revalidateOnFocus) {
|
|
|
71
71
|
revalidateOnFocus,
|
|
72
72
|
revalidateOnReconnect: revalidateOnFocus,
|
|
73
73
|
shouldRetryOnError: false,
|
|
74
|
+
// A query's KEY carries its params, filter and sort, so anything derived
|
|
75
|
+
// from the rows on screen re-keys the moment they change. Without this SWR
|
|
76
|
+
// answers a new key with `undefined`, `rows` falls to `[]`, and every list
|
|
77
|
+
// renders empty for a frame — unmounting each row's images, which remount
|
|
78
|
+
// blank. That is the behaviour the `loading` contract above already
|
|
79
|
+
// promises against, and what the product app sets globally for the same
|
|
80
|
+
// reason.
|
|
81
|
+
keepPreviousData: true,
|
|
74
82
|
};
|
|
75
83
|
}
|
|
76
84
|
/**
|
|
@@ -289,9 +297,7 @@ export function usePaginatedQuery(alias, params, opts) {
|
|
|
289
297
|
offset: page * pageSize,
|
|
290
298
|
sort,
|
|
291
299
|
filter,
|
|
292
|
-
}),
|
|
293
|
-
// Keep the previous page's rows on screen while the next page loads.
|
|
294
|
-
{ keepPreviousData: true, ...swrConfig(revalidateOnFocus) });
|
|
300
|
+
}), swrConfig(revalidateOnFocus));
|
|
295
301
|
// Not counted when the caller supplies the total, when the hook is disabled,
|
|
296
302
|
// or under a fixture — see `useCountRead` for why the key drops page and sort.
|
|
297
303
|
const countSwr = useCountRead(alias, params, filter, !mockRows && enabled && !callerOwnsTotal, revalidateOnFocus);
|
package/dist/src/row.d.ts
CHANGED
|
@@ -86,7 +86,9 @@ export interface AppFile {
|
|
|
86
86
|
/**
|
|
87
87
|
* files field → the attached files with their presigned `url` (empty if none).
|
|
88
88
|
* Skips entries the server didn't presign (no `url`) so a consumer never renders
|
|
89
|
-
* an unservable file.
|
|
89
|
+
* an unservable file. Pass one to `toDisplayFile` from `@lotics/ui/file_thumbnail`
|
|
90
|
+
* for FileThumbnail/Gallery — the kit owns that conversion, so don't re-declare
|
|
91
|
+
* it per app.
|
|
90
92
|
*/
|
|
91
93
|
export declare function readFiles(v: unknown): AppFile[];
|
|
92
94
|
/**
|
package/dist/src/row.js
CHANGED
|
@@ -113,7 +113,9 @@ export function readLinks(v) {
|
|
|
113
113
|
/**
|
|
114
114
|
* files field → the attached files with their presigned `url` (empty if none).
|
|
115
115
|
* Skips entries the server didn't presign (no `url`) so a consumer never renders
|
|
116
|
-
* an unservable file.
|
|
116
|
+
* an unservable file. Pass one to `toDisplayFile` from `@lotics/ui/file_thumbnail`
|
|
117
|
+
* for FileThumbnail/Gallery — the kit owns that conversion, so don't re-declare
|
|
118
|
+
* it per app.
|
|
117
119
|
*/
|
|
118
120
|
export function readFiles(v) {
|
|
119
121
|
if (!Array.isArray(v))
|
package/docs/data_fetching.md
CHANGED
|
@@ -136,8 +136,11 @@ server validates system conditions by `type` and never reads `field_key` on them
|
|
|
136
136
|
are no rows yet. It stays `false` during background revalidation of a key that already has rows,
|
|
137
137
|
so consumers never blank loaded data to a spinner on refetch. A key *change* (new params, sort,
|
|
138
138
|
filter, or page) is a fresh load: `loading` goes `true` again unless that key is already cached —
|
|
139
|
-
|
|
140
|
-
gate on `loading && rows.length === 0`, never `loading`
|
|
139
|
+
but the previous key's rows STAY on screen while it resolves, for every query, so `rows` never
|
|
140
|
+
empties mid-flight. That is why skeletons gate on `loading && rows.length === 0`, never `loading`
|
|
141
|
+
alone: a filter derived from what is on screen re-keys on every keystroke, and gating on
|
|
142
|
+
`loading` swaps the list for a spinner each time — which unmounts everything the rows contained,
|
|
143
|
+
images included. **`isValidating`** is `true`
|
|
141
144
|
whenever any request is in flight — use it for a subtle refresh indicator.
|
|
142
145
|
- **`error`** is a `string | null`. A failed query surfaces immediately — there is **no automatic
|
|
143
146
|
retry** (no retry loop that masks the error). The last successful rows for the same key stay
|
package/docs/workflows.md
CHANGED
|
@@ -489,7 +489,7 @@ differ from `<` / `>` (code-unit order) and from the database's collation.
|
|
|
489
489
|
| `set` | `{ fld_x: value }` | write the whole value. `null` **clears** the field |
|
|
490
490
|
| `set_skip_null` | `{ fld_x: value }` | same shape, but `null`/`undefined` entries are **dropped** — absent means "leave unchanged" |
|
|
491
491
|
| `add_to` / `remove_from` / `replace` | `{ fld_x: [items] }` | surgical edits on multi-value fields (files, multi select, multi member, record links) |
|
|
492
|
-
| `increment` | `{ fld_x: delta }` | move a **number** field by a signed amount. Negative decrements; there is no separate decrement op |
|
|
492
|
+
| `increment` | `{ fld_x: delta }` | move a **number** field by a signed amount, the SAME delta on every record named. Negative decrements; there is no separate decrement op |
|
|
493
493
|
| `field_edits` | `[{ field, op, value }]` | the multi-value ops with the field named by a **string expression** — the only way to target a field chosen at run time. `increment` has no value-form: its payload is a scalar, not an item list |
|
|
494
494
|
|
|
495
495
|
`add_to`, `remove_from` and `increment` are RELATIVE: the server resolves them against the record
|
|
@@ -505,6 +505,23 @@ stating its value.
|
|
|
505
505
|
and visibly so. It is rejected on formula, rollup, lookup and autonumber fields: those come from
|
|
506
506
|
their own definition, so change what they aggregate instead.
|
|
507
507
|
|
|
508
|
+
A **different** delta per record is per-record mode with `row_op: "increment"` — every row value is
|
|
509
|
+
read as a delta rather than a value to write. That is the shape a stock move needs, since each item
|
|
510
|
+
moves by its own quantity:
|
|
511
|
+
|
|
512
|
+
```ts
|
|
513
|
+
await update_records({
|
|
514
|
+
table_id: "tbl_items",
|
|
515
|
+
record_ids: ids,
|
|
516
|
+
field_keys: ["fld_stock"],
|
|
517
|
+
rows: [[-12], [-3]],
|
|
518
|
+
row_op: "increment",
|
|
519
|
+
});
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
It also removes the read: the deltas are what the workflow already computed, so there is nothing to
|
|
523
|
+
look up first.
|
|
524
|
+
|
|
508
525
|
Inside `set` and `create_records.records`: `null` clears (persisted), `undefined` or an omitted
|
|
509
526
|
key preserves. So passing a possibly-null read straight through is safe. Use
|
|
510
527
|
`coalesce(x, fallback)` only when you want a real fallback, never to "strip" null.
|