lecodes-sdk 2.2.3 → 2.2.5
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/global.d.ts +3 -1
- package/dist/types/animate/tween/spec.d.ts +4 -5
- package/dist/types/g2/Scene2D.d.ts +5 -4
- package/dist/types/gl/Scene.d.ts +5 -4
- package/dist/types/inject.d.ts +1 -1
- package/dist/types/server/db/fields.d.ts +6 -3
- package/dist/types/server/db/marci/query.d.ts +21 -2
- package/dist/types/server/db/types.d.ts +26 -12
- package/dist/types/server/errors.d.ts +4 -1
- package/dist/types/server/files/models.d.ts +4 -0
- package/dist/types/server/inject.d.ts +6 -0
- package/dist/types/ui/NativeView.d.ts +3 -3
- package/dist/types/ui/UI.d.ts +1 -1
- package/dist/types/ui/UILayer.d.ts +25 -18
- package/dist/types/ui/UINode.d.ts +8 -1
- package/dist/types/ui/UIScreen.d.ts +11 -1
- package/dist/types/ui/UIVideo.d.ts +3 -3
- package/dist/types/ui/UIVirtualizedList.d.ts +64 -18
- package/dist/types/ui/UIWidget.d.ts +24 -15
- package/dist/types/ui/presentable.d.ts +7 -7
- package/dist/types/version.d.ts +1 -1
- package/dist/types.json +1 -1
- package/package.json +2 -2
- package/prompts/3d-scene-files.md +2 -2
- package/prompts/3d-scene.md +1 -1
- package/prompts/dist/2d-game.md +13 -13
- package/prompts/dist/3d-app.md +21 -18
- package/prompts/dist/ar-app.md +13 -13
- package/prompts/dist/ui-app.md +13 -13
- package/prompts/ui.md +3 -1
- package/src/animate/tween/spec.ts +8 -13
- package/src/chisel.ts +3 -3
- package/src/compile/serverSplit.ts +5 -3
- package/src/g2/Scene2D.ts +9 -7
- package/src/gl/Scene.ts +9 -7
- package/src/inject.ts +1 -1
- package/src/server/db/defineDb.ts +17 -21
- package/src/server/db/fields.ts +7 -4
- package/src/server/db/httpTransport.ts +19 -3
- package/src/server/db/marci/query.ts +34 -8
- package/src/server/db/types.ts +33 -14
- package/src/server/errors.ts +4 -1
- package/src/server/files/db.ts +26 -7
- package/src/server/files/host.ts +45 -17
- package/src/server/files/models.ts +4 -0
- package/src/server/host.ts +3 -3
- package/src/server/inject.ts +3 -0
- package/src/server/runtime.ts +65 -4
- package/src/ui/NativeView.ts +11 -9
- package/src/ui/UI.ts +1 -1
- package/src/ui/UILayer.ts +90 -42
- package/src/ui/UINode.ts +33 -11
- package/src/ui/UIPopover.ts +3 -3
- package/src/ui/UIScreen.ts +50 -2
- package/src/ui/UIVideo.ts +11 -9
- package/src/ui/UIVirtualizedList.ts +159 -31
- package/src/ui/UIWidget.ts +41 -18
- package/src/ui/presentable.ts +8 -8
- package/src/ui/transitions.ts +1 -1
- package/src/version.ts +1 -1
- package/tests/helpers/fakeTree.ts +6 -1
package/dist/global.d.ts
CHANGED
|
@@ -124,7 +124,6 @@ declare global {
|
|
|
124
124
|
const UIImage: typeof SDK.UIImage
|
|
125
125
|
const UIInput: typeof SDK.UIInput
|
|
126
126
|
const UIModal: typeof SDK.UIModal
|
|
127
|
-
const UIOverlay: typeof SDK.UIOverlay
|
|
128
127
|
const UIPager: typeof SDK.UIPager
|
|
129
128
|
const UIPopover: typeof SDK.UIPopover
|
|
130
129
|
const UIRow: typeof SDK.UIRow
|
|
@@ -566,6 +565,7 @@ declare global {
|
|
|
566
565
|
type UIVideoStyle = SDK.UIVideoStyle
|
|
567
566
|
type UIVirtualizedList<T = unknown> = SDK.UIVirtualizedList<T>
|
|
568
567
|
type UIWidget = SDK.UIWidget
|
|
568
|
+
type UIWidgetChild = SDK.UIWidgetChild
|
|
569
569
|
type UIWidgetContent = SDK.UIWidgetContent
|
|
570
570
|
type UIWidgetStyle = SDK.UIWidgetStyle
|
|
571
571
|
type Unit = SDK.Unit
|
|
@@ -583,9 +583,11 @@ declare global {
|
|
|
583
583
|
type WebSocket = SDK.WebSocket
|
|
584
584
|
type Wheel = SDK.Wheel
|
|
585
585
|
type WheelSuspension = SDK.WheelSuspension
|
|
586
|
+
type WidgetSet<Owner> = SDK.WidgetSet<Owner>
|
|
586
587
|
type With<N, A extends Aspect<any, any, any>> = SDK.With<N, A>
|
|
587
588
|
// ---- server globals (available in *.server.ts; using them in client code is a build error) ----
|
|
588
589
|
const ApiError: typeof SERVER.ApiError
|
|
590
|
+
const SvgSource: typeof SERVER.SvgSource
|
|
589
591
|
const channel: typeof SERVER.channel
|
|
590
592
|
const defineDb: typeof SERVER.defineDb
|
|
591
593
|
const model: typeof SERVER.model
|
|
@@ -124,11 +124,10 @@ export declare const uiValue: (v: unknown) => ({
|
|
|
124
124
|
* function is unknown (the caller falls back to matrix decomposition on the host). `scale(2)` and
|
|
125
125
|
* `translate(5px)` complete their second argument like CSS.
|
|
126
126
|
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
|
|
131
|
-
export declare const parseTransformList: (s: string, percent?: boolean) => {
|
|
127
|
+
* A `%` in a translate is a percent of the target's own box (`translateX(100%)` → `translateX%`
|
|
128
|
+
* [100]; a translate mixing the units splits into its two axes), the way the runtime reads a
|
|
129
|
+
* style's transform: the box is measured when the matrix is composed, so a track fits any size. */
|
|
130
|
+
export declare const parseTransformList: (s: string) => {
|
|
132
131
|
sig: string;
|
|
133
132
|
lanes: number[];
|
|
134
133
|
} | null;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type ColorInput } from "../core/color";
|
|
2
2
|
import { type Aspect, type AspectCtor, type FieldOf, type TargetOf } from "../core/Aspect";
|
|
3
3
|
import { Presentable, type DismissOptions, type PresentOptions } from "../ui/presentable";
|
|
4
|
-
import { type
|
|
4
|
+
import { type WidgetSet } from "../ui/UILayer";
|
|
5
5
|
import { type Vec2Like } from "../math/vec";
|
|
6
6
|
import type { ClickEvent, TouchStartEvent } from "../runtime/touch";
|
|
7
7
|
import { Camera2D } from "./Camera2D";
|
|
@@ -68,9 +68,10 @@ export declare class Scene2D implements Presentable {
|
|
|
68
68
|
/** @deprecated Renamed `onBack` (2026-09-26). An alias for the projects compiled before the
|
|
69
69
|
* rename; removed with the release that recompiles them. */
|
|
70
70
|
onBackPressed(callback: () => void): this;
|
|
71
|
-
/** The
|
|
72
|
-
*
|
|
73
|
-
|
|
71
|
+
/** The widgets over the scene while it is presented — a HUD, a dialog, a sheet: `scene.widgets(hud)`
|
|
72
|
+
* sets them, `widgets.append` / `.remove` manage them, `widgets.list` reads them. Laid out
|
|
73
|
+
* over it; touches outside a widget's box reach the scene. */
|
|
74
|
+
get widgets(): WidgetSet<this>;
|
|
74
75
|
/** Make this the active scene — shows it as the current destination (replaces a screen /
|
|
75
76
|
* another scene; only the active scene renders). */
|
|
76
77
|
open(options?: PresentOptions): this;
|
package/dist/types/gl/Scene.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type ColorInput } from "../core/color";
|
|
2
2
|
import { type Aspect, type AspectCtor, type FieldOf, type TargetOf } from "../core/Aspect";
|
|
3
3
|
import { Presentable, type DismissOptions, type PresentOptions } from "../ui/presentable";
|
|
4
|
-
import { type
|
|
4
|
+
import { type WidgetSet } from "../ui/UILayer";
|
|
5
5
|
import type { ClickEvent, TouchStartEvent } from "../runtime/touch";
|
|
6
6
|
import type { FetchResponse } from "../runtime/fetch";
|
|
7
7
|
import { Camera } from "./Camera";
|
|
@@ -233,9 +233,10 @@ export declare class Scene implements Presentable {
|
|
|
233
233
|
/** @deprecated Renamed `onBack` (2026-09-26). An alias for the projects compiled before the
|
|
234
234
|
* rename; removed with the release that recompiles them. */
|
|
235
235
|
onBackPressed(callback: () => void): this;
|
|
236
|
-
/** The
|
|
237
|
-
*
|
|
238
|
-
|
|
236
|
+
/** The widgets over the scene while it is presented — a HUD, a dialog, a sheet: `scene.widgets(hud)`
|
|
237
|
+
* sets them, `widgets.append` / `.remove` manage them, `widgets.list` reads them. Laid out
|
|
238
|
+
* over it; touches outside a widget's box reach the scene. */
|
|
239
|
+
get widgets(): WidgetSet<this>;
|
|
239
240
|
/** Make this the active scene — shows it as the current destination (replaces a screen /
|
|
240
241
|
* another scene; only the active scene renders). The runtime activates the engine as part of
|
|
241
242
|
* presenting the destination. */
|
package/dist/types/inject.d.ts
CHANGED
|
@@ -56,7 +56,7 @@ export { defineScene2d, Scene2dHandle } from "./g2/defineScene2d";
|
|
|
56
56
|
export type { Scene2dDef, Scene2dNodeDef, Scene2dEnv, SpriteSourceDef, TilemapSourceDef, Camera2dNodeDef, LoadedScene2d } from "./g2/defineScene2d";
|
|
57
57
|
export { cells, encodeCells, type CellsData } from "./g2/cells";
|
|
58
58
|
export { CameraFollow } from "./g2/scenarios2d";
|
|
59
|
-
export { UIScreen, type UIScreenStyle, UIRow, UIColumn, UIBox, type UIContainerStyle, UIText, type UITextStyle, UIButton, type UIButtonStyle, UIImage, type UIImageStyle, UIVideo, type UIVideoStyle, UIInput, UITextArea, type UIInputStyle, UIScrollable, type UIScrollableStyle, UIPager, type UIPagerStyle, UITabs, type UITabDef, defineTabs, type TabDef, type TabsHandle, UIWidget, type UIWidgetStyle,
|
|
59
|
+
export { UIScreen, type UIScreenStyle, UIRow, UIColumn, UIBox, type UIContainerStyle, UIText, type UITextStyle, UIButton, type UIButtonStyle, UIImage, type UIImageStyle, UIVideo, type UIVideoStyle, UIInput, UITextArea, type UIInputStyle, UIScrollable, type UIScrollableStyle, UIPager, type UIPagerStyle, UITabs, type UITabDef, defineTabs, type TabDef, type TabsHandle, UIWidget, type UIWidgetStyle, type WidgetSet, type UIWidgetContent, type UIWidgetChild, UIModal, type UIModalStyle, UIBottomSheet, type UIBottomSheetStyle, UIPopover, type UIPopoverStyle, UISpacer, type UISpacerStyle, UIVirtualizedList, Router, NativeView, type UINativeViewStyle, registerFont, __uiMap, __UIColumn, __UIRow, __UIBox, __UIButton, __UIScreen, __UIScrollable, __UIWidget, } from "./ui/UI";
|
|
60
60
|
export { Presentable } from "./ui/UI";
|
|
61
61
|
export type { DismissOptions, PresentOptions, Transition, TransitionName, TransitionPose, TransitionSpec } from "./ui/UI";
|
|
62
62
|
export type { UINode, UINodeChild } from "./ui/UINode";
|
|
@@ -41,7 +41,8 @@ export type FieldDef = {
|
|
|
41
41
|
kind: FieldKind;
|
|
42
42
|
scalar?: ScalarKind;
|
|
43
43
|
optional: boolean;
|
|
44
|
-
unique
|
|
44
|
+
/** `true` = `@unique`; a string = `@unique(<group>)`: the fields of a model sharing the group are unique together. */
|
|
45
|
+
unique: boolean | string;
|
|
45
46
|
index: boolean;
|
|
46
47
|
hasDefault: boolean;
|
|
47
48
|
default?: unknown;
|
|
@@ -73,8 +74,10 @@ export interface Field<T, M extends FieldMeta = FieldMeta> {
|
|
|
73
74
|
readonly def: FieldDef;
|
|
74
75
|
/** Nullable column (`String?`). */
|
|
75
76
|
optional(): Field<T, SetMeta<M, "optional", true>>;
|
|
76
|
-
/** `@unique` (on a relation: one-to-one).
|
|
77
|
-
|
|
77
|
+
/** `@unique` (on a relation: one-to-one). With a group name, the fields of the model that share it are
|
|
78
|
+
* unique TOGETHER — `user: t.one("User").unique("pair"), post: t.one("Post").unique("pair")` is one
|
|
79
|
+
* like per user and post; a null part is not constrained. */
|
|
80
|
+
unique(group?: string): Field<T, M>;
|
|
78
81
|
/** `@index` — used by `$where`, `$order`, aggregations. */
|
|
79
82
|
index(): Field<T, M>;
|
|
80
83
|
/** `@default(...)`; `"now"` on `t.date()` → `now()`. Makes the field optional on insert. */
|
|
@@ -197,6 +197,8 @@ export type MarciOp = {
|
|
|
197
197
|
query?: any;
|
|
198
198
|
data?: any;
|
|
199
199
|
id?: any;
|
|
200
|
+
key?: any;
|
|
201
|
+
onInsert?: any;
|
|
200
202
|
journal?: JournalArgs;
|
|
201
203
|
};
|
|
202
204
|
/** The arguments of a journal action (`$journalOpen` / `$journalRead` / `$journalDrop`). `wait` is in seconds. */
|
|
@@ -255,9 +257,11 @@ export interface Query<T extends ModelTypes, Sel = T["scalars"]> extends Promise
|
|
|
255
257
|
readonly [__sel]: Effective<T, Sel>;
|
|
256
258
|
/** Filter (marcidb `$where`). Repeated calls are ANDed. */
|
|
257
259
|
where(where: T["where"]): Query<T, Sel>;
|
|
258
|
-
/** Sort
|
|
260
|
+
/** Sort: `order("age", "desc")` or `order({ age: "desc" })`. A second `order()` adds the next key — ties on
|
|
261
|
+
* the first are broken by it (`order("createdAt", "desc").order("id")`); the keys may also come as an array
|
|
262
|
+
* in one call. Several keys sort in memory. */
|
|
259
263
|
order(field: keyof T["order"] & string, direction?: "asc" | "desc"): Query<T, Sel>;
|
|
260
|
-
order(order: T["order"]): Query<T, Sel>;
|
|
264
|
+
order(order: T["order"] | T["order"][]): Query<T, Sel>;
|
|
261
265
|
limit(n: number): Query<T, Sel>;
|
|
262
266
|
skip(n: number): Query<T, Sel>;
|
|
263
267
|
/** Keyset cursor: rows strictly after this id in the current order (`$cursor`). */
|
|
@@ -287,6 +291,18 @@ export interface Query<T extends ModelTypes, Sel = T["scalars"]> extends Promise
|
|
|
287
291
|
select: S;
|
|
288
292
|
}): Promise<Rows<T, S>>;
|
|
289
293
|
update(id: IdArg<T["id"]>, data: T["update"]): Op<void>;
|
|
294
|
+
/** Writes the row `key` names — the id, or the fields of ONE unique index (a `@unique` field, all the fields of
|
|
295
|
+
* a `@unique(<name>)` group): an update of `data` when it exists, an insert of key + data when not. `data` is
|
|
296
|
+
* in the insert form (plain values, `{ id }` for a relation; no `$` operators). `onInsert` adds fields used
|
|
297
|
+
* only when the row is created. Resolves to the id, like `insert`. */
|
|
298
|
+
upsert<K extends Partial<T["insert"]> | T["id"]>(key: K, data: Omit<T["insert"], keyof K>, options?: {
|
|
299
|
+
onInsert?: Partial<T["insert"]>;
|
|
300
|
+
}): Op<T["id"]>;
|
|
301
|
+
/** The row written, by `select`'s shape — as stored, whichever path the upsert took. */
|
|
302
|
+
upsert<K extends Partial<T["insert"]> | T["id"], S extends T["query"]>(key: K, data: Omit<T["insert"], keyof K>, options: {
|
|
303
|
+
onInsert?: Partial<T["insert"]>;
|
|
304
|
+
select: S;
|
|
305
|
+
}): Promise<Rows<T, S>>;
|
|
290
306
|
/** Applies `data` to every row the chain's `where` matches (all rows without one); resolves to the number of rows. */
|
|
291
307
|
updateMany(data: T["update"]): Op<number>;
|
|
292
308
|
/** @deprecated pass the filter through the chain: `db.user.where(w).updateMany(data)` (removed in the next minor). */
|
|
@@ -354,6 +370,9 @@ export type QueryLayerOptions = {
|
|
|
354
370
|
run(op: MarciOp): Promise<any>;
|
|
355
371
|
/** Hook for `insert` payloads (the lecodes SDK generates uuid ids here). */
|
|
356
372
|
prepareInsert?(model: string, data: any): any;
|
|
373
|
+
/** Hook for the `onInsert` part of an `upsert` — the fields used only when the row is created (the lecodes SDK
|
|
374
|
+
* puts a uuid id here). Receives what the caller gave (or undefined), returns what is sent. */
|
|
375
|
+
prepareUpsert?(model: string, onInsert: any): any;
|
|
357
376
|
};
|
|
358
377
|
/**
|
|
359
378
|
* The query builder over a set of models and a `run` function. Returns `op(descriptor)` — a lazy operation
|
|
@@ -66,20 +66,21 @@ export type Scalars<S, N extends keyof S> = Pick<Row<S, N>, (ScalarKeys<FieldsOf
|
|
|
66
66
|
export type ScalarSelect<S, N extends keyof S> = {
|
|
67
67
|
[K in (ScalarKeys<FieldsOf<S[N]>> | keyof Id<S, N>) & keyof Row<S, N>]: true;
|
|
68
68
|
};
|
|
69
|
-
type FieldInsert<S, Fld, M extends FieldMeta = MetaOf<Fld>> = M["kind"] extends "one" ? Nullable<M, Id<S, ModelName<S, Fld>>> : M["kind"] extends "many" | "list" ? Id<S, ModelName<S, Fld>>[] : M["kind"] extends "struct" ? Nullable<M, StructInsert<S, StructFieldsOf<Fld
|
|
69
|
+
type FieldInsert<S, Fld, FW, M extends FieldMeta = MetaOf<Fld>> = M["kind"] extends "one" ? Nullable<M, Id<S, ModelName<S, Fld>>> : M["kind"] extends "many" | "list" ? Id<S, ModelName<S, Fld>>[] : M["kind"] extends "struct" ? Nullable<M, StructInsert<S, StructFieldsOf<Fld>, FW>> : M["kind"] extends "file" ? Nullable<M, Arr<M, FW>> : Nullable<M, Arr<M, TsOf<Fld>>>;
|
|
70
70
|
type RequiredKeys<F extends Fields> = {
|
|
71
71
|
[K in keyof F]: K extends IdKeys<F> ? never : MetaOf<F[K]>["optional"] extends true ? never : MetaOf<F[K]>["hasDefault"] extends true ? never : MetaOf<F[K]>["kind"] extends "many" | "list" ? never : MetaOf<F[K]>["kind"] extends "file" ? (MetaOf<F[K]>["array"] extends true ? never : K) : K;
|
|
72
72
|
}[keyof F];
|
|
73
73
|
type Simplify<T> = {
|
|
74
74
|
[K in keyof T]: T[K];
|
|
75
75
|
} & {};
|
|
76
|
-
type InsertOf<S, F extends Fields> = Simplify<{
|
|
77
|
-
[K in RequiredKeys<F>]: FieldInsert<S, F[K]>;
|
|
76
|
+
type InsertOf<S, F extends Fields, FW = FileWrite> = Simplify<{
|
|
77
|
+
[K in RequiredKeys<F>]: FieldInsert<S, F[K], FW>;
|
|
78
78
|
} & {
|
|
79
|
-
[K in Exclude<keyof F, RequiredKeys<F>>]?: FieldInsert<S, F[K]>;
|
|
79
|
+
[K in Exclude<keyof F, RequiredKeys<F>>]?: FieldInsert<S, F[K], FW>;
|
|
80
80
|
}>;
|
|
81
|
-
|
|
82
|
-
type
|
|
81
|
+
/** `FW` is what a file field is written with: an upload of the call; in a seed, a resource of the project as well. */
|
|
82
|
+
export type Insert<S, N extends keyof S, FW = FileWrite> = InsertOf<S, FieldsOf<S[N]>, FW>;
|
|
83
|
+
type StructInsert<S, F extends Fields, FW = FileWrite> = InsertOf<S, F, FW>;
|
|
83
84
|
type FieldUpdate<S, Fld, M extends FieldMeta = MetaOf<Fld>> = M["kind"] extends "one" ? Nullable<M, RefUpdate<Id<S, ModelName<S, Fld>>>> : M["kind"] extends "many" ? RefListUpdate<Id<S, ModelName<S, Fld>>> : M["kind"] extends "list" ? RefListUpdateOrdered<Id<S, ModelName<S, Fld>>> : M["kind"] extends "struct" ? RefUpdateStruct<StructInsert<S, StructFieldsOf<Fld>>, UpdateOf<S, StructFieldsOf<Fld>>> | null : M["kind"] extends "file" ? Nullable<M, Arr<M, FileWrite | StoredFile>> : M["array"] extends true ? TsOf<Fld>[] | PrimitiveListUpdate<TsOf<Fld>> : Nullable<M, TsOf<Fld> | (IsNum<M> extends true ? UpdateNumValue : never)>;
|
|
84
85
|
type UpdateOf<S, F extends Fields> = {
|
|
85
86
|
[K in Exclude<keyof F, IdKeys<F>>]?: FieldUpdate<S, F[K]>;
|
|
@@ -103,7 +104,8 @@ type IdWhere<S, N extends keyof S> = {
|
|
|
103
104
|
export type Where<S, N extends keyof S> = WhereValue<WhereFieldsOf<S, FieldsOf<S[N]>> & IdWhere<S, N>>;
|
|
104
105
|
type StructWhereFields<S, F extends Fields> = WhereFieldsOf<S, F>;
|
|
105
106
|
type OrderKeys<S, N extends keyof S> = (ValueKeys<FieldsOf<S[N]>> | keyof Id<S, N>) & keyof Row<S, N>;
|
|
106
|
-
/**
|
|
107
|
+
/** One field and its direction. Several keys are several of these, in an array (`$order: [{ createdAt: "desc" },
|
|
108
|
+
* { id: "asc" }]`) or chained `.order()` calls — an object with two keys is refused, since JSON promises no key order. */
|
|
107
109
|
export type Order<S, N extends keyof S> = {
|
|
108
110
|
[K in OrderKeys<S, N>]: {
|
|
109
111
|
[P in K]: "asc" | "desc";
|
|
@@ -114,7 +116,7 @@ export type Order<S, N extends keyof S> = {
|
|
|
114
116
|
/** The query object — marcidb's wire form: a select shape plus the `$`-clauses. */
|
|
115
117
|
export type QueryObject<S, N extends keyof S> = Select<S, N> & {
|
|
116
118
|
$where?: Where<S, N>;
|
|
117
|
-
$order?: Order<S, N
|
|
119
|
+
$order?: Order<S, N> | Order<S, N>[];
|
|
118
120
|
$limit?: number;
|
|
119
121
|
$skip?: number;
|
|
120
122
|
$cursor?: Id<S, N>;
|
|
@@ -128,7 +130,7 @@ export type AggregateQuery<S, N extends keyof S> = {
|
|
|
128
130
|
$max?: (ValueKeys<FieldsOf<S[N]>> | keyof Id<S, N>) & string;
|
|
129
131
|
};
|
|
130
132
|
/** The per-model type bag marcidb's generic `Query<T>` is parametrised by (what its codegen emits as `UserTypes`). */
|
|
131
|
-
export type Types<S, N extends keyof S> = {
|
|
133
|
+
export type Types<S, N extends keyof S, FW = FileWrite> = {
|
|
132
134
|
name: N & string;
|
|
133
135
|
model: Row<S, N>;
|
|
134
136
|
id: Id<S, N>;
|
|
@@ -137,7 +139,7 @@ export type Types<S, N extends keyof S> = {
|
|
|
137
139
|
query: QueryObject<S, N>;
|
|
138
140
|
where: Where<S, N>;
|
|
139
141
|
order: Order<S, N>;
|
|
140
|
-
insert: Insert<S, N>;
|
|
142
|
+
insert: Insert<S, N, FW>;
|
|
141
143
|
update: Update<S, N>;
|
|
142
144
|
aggregate: AggregateQuery<S, N>;
|
|
143
145
|
reindex: false;
|
|
@@ -148,7 +150,7 @@ export type Types<S, N extends keyof S> = {
|
|
|
148
150
|
* `updateMany(data)`/`deleteMany()` write through the chain's `where`; a query placed in another query's
|
|
149
151
|
* select is a sub-query. `Sel` is the projection: id + scalars until `select(...)` sets a shape.
|
|
150
152
|
*/
|
|
151
|
-
export type Query<S, N extends keyof S, Sel = ScalarSelect<S, N
|
|
153
|
+
export type Query<S, N extends keyof S, Sel = ScalarSelect<S, N>, FW = FileWrite> = MarciQuery<Types<S, N, FW>, Sel>;
|
|
152
154
|
/** The rows a query with projection `Q` resolves to (no field keys = id + scalars; sub-queries resolved). */
|
|
153
155
|
export type Result<S, N extends keyof S, Q> = Rows<Types<S, N>, Q>;
|
|
154
156
|
/** `db.<model>` — the root query of a model. */
|
|
@@ -168,7 +170,18 @@ type DbBase<S extends Schema> = {
|
|
|
168
170
|
}>;
|
|
169
171
|
/** The `.marci` schema text this db syncs with. */
|
|
170
172
|
readonly $schema: string;
|
|
173
|
+
/**
|
|
174
|
+
* The first rows of this database: run by the host ONCE, on a database that is empty, wherever the
|
|
175
|
+
* database opens (a check, a dev backend, the first deploy). Part of the definition, like sign-in:
|
|
176
|
+
* written on `defineDb(...)` itself. Inside, a file field takes a resource of the project — the path
|
|
177
|
+
* of a picture the design shows (`photo: row.photo`) — and stores it the way an upload is stored.
|
|
178
|
+
*/
|
|
179
|
+
seed(fn: (db: SeedDb<S>) => Promise<void>): Db<S>;
|
|
171
180
|
};
|
|
181
|
+
/** The db a seed writes through: the same queries, a file field taking a resource of the project (its path) too. */
|
|
182
|
+
export type SeedDb<S extends Schema> = {
|
|
183
|
+
[N in keyof S & string as Uncapitalize<N>]: Query<Full<S>, N, ScalarSelect<Full<S>, N>, FileWrite | string>;
|
|
184
|
+
} & Pick<DbBase<S>, "$transaction">;
|
|
172
185
|
export type Db<S extends Schema> = DbBase<S> & {
|
|
173
186
|
/**
|
|
174
187
|
* Sign-in for this database: `model` is the project's model of a user. Adds the platform's `Session`
|
|
@@ -180,8 +193,9 @@ export type Db<S extends Schema> = DbBase<S> & {
|
|
|
180
193
|
model: N;
|
|
181
194
|
}): DbWithAuth<S, N>;
|
|
182
195
|
};
|
|
183
|
-
export type DbWithAuth<S extends Schema, N extends keyof S & string> = DbBase<S> & {
|
|
196
|
+
export type DbWithAuth<S extends Schema, N extends keyof S & string> = Omit<DbBase<S>, "seed"> & {
|
|
184
197
|
readonly auth: Auth<S, N>;
|
|
198
|
+
seed(fn: (db: SeedDb<S>) => Promise<void>): DbWithAuth<S, N>;
|
|
185
199
|
};
|
|
186
200
|
/**
|
|
187
201
|
* The user of the current request, as a query over the project's user model: `select(shape)` picks the
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `throw new ApiError(404, "Not found")` inside an endpoint → the client's promise rejects with the
|
|
3
|
-
* same status + message.
|
|
3
|
+
* same status + message. A write the database refused for a reason a person could have caused reaches
|
|
4
|
+
* the app the same way, in the database's words: a taken unique value, a pointer at no row, a delete
|
|
5
|
+
* other rows forbid are 409, a row that is gone 404. Any other throw is a 500 (message hidden, logged
|
|
6
|
+
* to the server console).
|
|
4
7
|
*/
|
|
5
8
|
export declare class ApiError extends Error {
|
|
6
9
|
readonly status: number;
|
|
@@ -124,6 +124,10 @@ export type FilesSeam = {
|
|
|
124
124
|
/** The id of the `File` row behind an upload of the current request; undefined for anything else —
|
|
125
125
|
* a value the app sent as JSON is never an upload, whatever it looks like. */
|
|
126
126
|
uploaded(value: unknown): string | undefined;
|
|
127
|
+
/** While a seed runs: the id of a `File` row made from a resource of the project named by its path
|
|
128
|
+
* (what a path literal of the design is in the server bundle); undefined for a path that is no file
|
|
129
|
+
* of the project. Absent outside a seed: a string the app sent is never a file. */
|
|
130
|
+
resource?(path: string): Promise<string | undefined>;
|
|
127
131
|
url(id: string, name: string): string;
|
|
128
132
|
/** Make the upload `id` fit for a `t.image()` field (its bytes are rewritten in place) and say what
|
|
129
133
|
* it is now. Throws an `ApiError` for what is no picture. */
|
|
@@ -3,3 +3,9 @@ export { ApiError } from "./errors";
|
|
|
3
3
|
export { channel } from "./channel";
|
|
4
4
|
export { request } from "./context";
|
|
5
5
|
export type { StoredFile, StoredImage } from "./files/models";
|
|
6
|
+
/** The value an SVG source is to the client (`assetIcon(…)` compiles to `SvgSource(…)`): a shared module of
|
|
7
|
+
* the design that names an icon per row loads on the server too. The server draws nothing with it. */
|
|
8
|
+
export declare const SvgSource: (svg: string) => {
|
|
9
|
+
svg: string;
|
|
10
|
+
tintColor: string | null;
|
|
11
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type WidgetSet } from "./UILayer";
|
|
2
2
|
import { type DismissOptions, type PresentOptions } from "./presentable";
|
|
3
3
|
import { type BaseStyle, type DrawableStyle, type ElementStyle, type UIElementBase } from "./UINode";
|
|
4
4
|
export type UINativeViewStyle = ElementStyle & DrawableStyle;
|
|
@@ -27,8 +27,8 @@ export interface NativeView extends UIElementBase<UINativeViewStyle, DrawableSty
|
|
|
27
27
|
/** Subscribe to an event the native view emits (`map.on("markerTap", cb)`). */
|
|
28
28
|
on(event: string, callback: (data?: any) => void): this;
|
|
29
29
|
off(event: string, callback: (data?: any) => void): this;
|
|
30
|
-
/** The
|
|
31
|
-
|
|
30
|
+
/** The widgets over the view when it is presented (`Presentable.widgets`): `map.widgets(header, card)`. */
|
|
31
|
+
readonly widgets: WidgetSet<this>;
|
|
32
32
|
}
|
|
33
33
|
/**
|
|
34
34
|
* Create an instance of a host-registered platform view. `NativeView.isSupported(name)` reports
|
package/dist/types/ui/UI.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export { UIImage, type UIImageStyle } from './UIImage';
|
|
|
7
7
|
export { UIVideo, type UIVideoStyle } from './UIVideo';
|
|
8
8
|
export { UIInput, UITextArea, type UIInputStyle } from './UIInput';
|
|
9
9
|
export { UIWidget, type UIWidgetStyle } from './UIWidget';
|
|
10
|
-
export {
|
|
10
|
+
export { type WidgetSet, type UIWidgetContent, type UIWidgetChild } from './UILayer';
|
|
11
11
|
export { UIModal, type UIModalStyle } from './UIModal';
|
|
12
12
|
export { UIBottomSheet, type UIBottomSheetStyle } from './UIBottomSheet';
|
|
13
13
|
export { UIPopover, type UIPopoverStyle, type UIPopoverAnchor } from './UIPopover';
|
|
@@ -1,25 +1,32 @@
|
|
|
1
1
|
import type { UIWidget } from "./UIWidget";
|
|
2
|
-
|
|
2
|
+
/** A widget slot: a widget, or a falsy value (skipped). */
|
|
3
|
+
export type UIWidgetChild = UIWidget | null | undefined | false;
|
|
4
|
+
/** The widgets of a destination as `widgets()` takes them: a list, or a function for reactive
|
|
5
|
+
* content (re-run when a signal read inside it changes, reconciled against the shown ones). */
|
|
6
|
+
export type UIWidgetContent = UIWidgetChild[] | (() => UIWidgetChild[]);
|
|
3
7
|
/**
|
|
4
|
-
* The
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* `
|
|
8
|
+
* The widgets of a destination — a dialog, a sheet, a HUD: what floats over it, laid out and
|
|
9
|
+
* painted in its box above everything else. Call it to set them (`screen.widgets(dialog)`, same
|
|
10
|
+
* argument forms as `UIColumn`: widgets, arrays of them, or ONE function for reactive content);
|
|
11
|
+
* `append` / `remove` manage them one at a time; `list` reads them. A widget shows with its
|
|
12
|
+
* destination unless its style says `display: "none"`; `show()` / `hide()` flip that, and
|
|
13
|
+
* `show()` puts it on top of the others.
|
|
8
14
|
*
|
|
9
15
|
* ```ts
|
|
10
|
-
*
|
|
11
|
-
*
|
|
16
|
+
* const home = UIScreen(content).widgets(dialog, sheet)
|
|
17
|
+
* scene.widgets(hud)
|
|
18
|
+
* scene.widgets(() => [hud, paused() && pauseMenu])
|
|
19
|
+
* home.widgets.append(toast); home.widgets.remove(toast)
|
|
20
|
+
* home.widgets.list // [dialog, sheet] — never in `children`
|
|
12
21
|
* ```
|
|
13
22
|
*/
|
|
14
|
-
export
|
|
23
|
+
export interface WidgetSet<Owner> {
|
|
24
|
+
(...widgets: (UIWidgetChild | UIWidgetChild[])[]): Owner;
|
|
25
|
+
(widgets: UIWidgetContent): Owner;
|
|
15
26
|
/** Add widgets at the end (on top). */
|
|
16
|
-
append(...widgets:
|
|
17
|
-
/**
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
setContent(content: UIWidgetContent): void;
|
|
23
|
-
/** The layer's widgets, bottom to top (a snapshot read from the runtime). */
|
|
24
|
-
readonly children: UIWidget[];
|
|
25
|
-
}>;
|
|
27
|
+
append(...widgets: UIWidgetChild[]): void;
|
|
28
|
+
/** Take widgets out (they stay valid while you hold them; a dropped one is freed). */
|
|
29
|
+
remove(...widgets: UIWidgetChild[]): void;
|
|
30
|
+
/** The widgets, bottom to top — a snapshot read from the runtime. */
|
|
31
|
+
readonly list: UIWidget[];
|
|
32
|
+
}
|
|
@@ -27,6 +27,9 @@ export type Color = ColorInput | null;
|
|
|
27
27
|
/** Style props every element accepts. */
|
|
28
28
|
export type BaseStyle = {
|
|
29
29
|
opacity?: number | `${number}`;
|
|
30
|
+
/** A CSS-style list of `translate` / `scale` / `rotate`. A `%` in a translate is a percent of the
|
|
31
|
+
* element's own box (`translate(-50%, -50%)` centres it on its corner), kept as a percent: it
|
|
32
|
+
* follows the box through every layout. */
|
|
30
33
|
transform?: string | null;
|
|
31
34
|
/** Pivot of `transform` (CSS `transform-origin` subset): one or two values, each a keyword
|
|
32
35
|
* (`left`/`center`/`right`, `top`/`center`/`bottom`), a percentage of the box, or a px length
|
|
@@ -373,11 +376,15 @@ export type ChildrenFn = () => UINodeChild[];
|
|
|
373
376
|
* results it behaves exactly like Array.prototype.map — a wrong rewrite can't change behavior.
|
|
374
377
|
*/
|
|
375
378
|
export declare function __uiMap(list: any, render: (item: any, index: number) => any, slot: string): any[];
|
|
379
|
+
/** A widget slot of `widgets(...)` takes a widget (falsy = conditional, skipped silently);
|
|
380
|
+
* anything else is reported and skipped. */
|
|
381
|
+
export declare const acceptWidget: (owner: {
|
|
382
|
+
type: string;
|
|
383
|
+
}, node: any) => boolean;
|
|
376
384
|
export declare class ContainerElement<T extends string> extends Element<T> {
|
|
377
385
|
constructor(type: T, style: any, children: any[] | ChildrenFn);
|
|
378
386
|
/** The children — a snapshot read from the runtime (falsy entries were never mounted). */
|
|
379
387
|
get children(): any[];
|
|
380
|
-
private _insertAt;
|
|
381
388
|
/** Append children (falsy entries are skipped). */
|
|
382
389
|
append(...nodes: UINodeChild[]): this;
|
|
383
390
|
/** Insert children at `index`. */
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { TouchStartEvent } from "../runtime/touch";
|
|
2
2
|
import { type DismissOptions, type PresentOptions } from "./presentable";
|
|
3
3
|
import { ContainerElement, type BaseStyle, type ContainerStyle, type DrawableStyle, type PaddingStyle, type UIChildArg, type UIContainerBase, type UINodeChild, type ChildrenFn } from "./UINode";
|
|
4
|
+
import { type WidgetHost, type WidgetSet } from "./UILayer";
|
|
4
5
|
export type UIScreenStyle = ContainerStyle & DrawableStyle & PaddingStyle & BaseStyle;
|
|
5
6
|
/** A screen — the root the router/host mounts, sized to its slot. A screen NEVER scrolls: it is
|
|
6
7
|
* fixed chrome (header, tab bar) plus, when the content overflows, one `UIScrollable` body child
|
|
@@ -46,9 +47,18 @@ export interface UIScreen extends UIContainerBase<UIScreenStyle, DrawableStyle &
|
|
|
46
47
|
url(route: string | null): this;
|
|
47
48
|
/** Touch began on the screen; `ev.track(...)` takes over the rest of the gesture. */
|
|
48
49
|
onTouchStart(callback: (ev: TouchStartEvent<UIScreen>) => void): this;
|
|
50
|
+
/** The screen's widgets — a dialog, a sheet, a toast: `UIScreen(content).widgets(dialog)` sets
|
|
51
|
+
* them, `widgets.append` / `.remove` manage them, `widgets.list` reads them. Never among
|
|
52
|
+
* `children`: that is the content. A widget is laid out and painted over the whole screen (on a
|
|
53
|
+
* pager page: over the pager too) and shows with it unless its style says `display: "none"`. */
|
|
54
|
+
readonly widgets: WidgetSet<this>;
|
|
49
55
|
}
|
|
50
|
-
export declare class ScreenElement extends ContainerElement<"screen"> {
|
|
56
|
+
export declare class ScreenElement extends ContainerElement<"screen"> implements WidgetHost {
|
|
51
57
|
constructor(type: "screen", style: any, children: any);
|
|
58
|
+
/** The content — the children read from the runtime without the widget tail. */
|
|
59
|
+
get children(): any[];
|
|
60
|
+
private _widgetSet?;
|
|
61
|
+
get widgets(): WidgetSet<this>;
|
|
52
62
|
open(options?: PresentOptions): void;
|
|
53
63
|
close(options?: DismissOptions): void;
|
|
54
64
|
protected ol: (() => void)[];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { VideoPlayer } from "../runtime/media";
|
|
2
|
-
import { type
|
|
2
|
+
import { type WidgetSet } from "./UILayer";
|
|
3
3
|
import { type DismissOptions, type PresentOptions } from "./presentable";
|
|
4
4
|
import { type BaseStyle, type DrawableStyle, type ElementStyle, type UIElementBase } from "./UINode";
|
|
5
5
|
export type UIVideoStyle = ElementStyle & DrawableStyle & {
|
|
@@ -22,8 +22,8 @@ export interface UIVideo extends UIElementBase<UIVideoStyle, DrawableStyle & Bas
|
|
|
22
22
|
onClose(callback: () => void): this;
|
|
23
23
|
/** Hardware/system back while current. */
|
|
24
24
|
onBack(callback: () => void): this;
|
|
25
|
-
/** The
|
|
26
|
-
|
|
25
|
+
/** The widgets over the video when it is presented (`Presentable.widgets`): `video.widgets(controls)`. */
|
|
26
|
+
readonly widgets: WidgetSet<this>;
|
|
27
27
|
}
|
|
28
28
|
/** Create a video node showing `player`'s output. */
|
|
29
29
|
export declare function UIVideo(player: VideoPlayer): UIVideo;
|
|
@@ -6,20 +6,14 @@ export type UIVirtualizedListStyle = DrawableStyle & ElementStyle & {
|
|
|
6
6
|
* matter how the history is scrolled. */
|
|
7
7
|
keyboardDismissMode?: "interactive" | "scroll" | "none";
|
|
8
8
|
};
|
|
9
|
-
|
|
10
|
-
/** The rows, read reactively: the list follows the signals this reads, the way a container's
|
|
11
|
-
* function children do. Rows are told apart by `keyOf`; a row whose item is another object
|
|
12
|
-
* re-renders. Appended rows and rows added at the start are told from a rewrite (a chat at
|
|
13
|
-
* its bottom follows what is appended; older history above moves nothing). */
|
|
14
|
-
data: () => T[];
|
|
9
|
+
interface VListBaseConfig<T> {
|
|
15
10
|
/** Stable unique key of an item. */
|
|
16
11
|
keyOf: (item: T) => string;
|
|
17
12
|
/** Subtree factory — called when the item enters the window; the subtree lives until it
|
|
18
13
|
* leaves. */
|
|
19
14
|
render: (item: T) => UINodeChild;
|
|
20
15
|
/** Height estimate (px) used before the first measurement — a number, or a per-item function
|
|
21
|
-
* (chat: `msg => 40 + Math.ceil(msg.text.length / 35) * 20`).
|
|
22
|
-
* added. */
|
|
16
|
+
* (chat: `msg => 40 + Math.ceil(msg.text.length / 35) * 20`). Read when the item is added. */
|
|
23
17
|
estimatedHeight: number | ((item: T) => number);
|
|
24
18
|
/** Extra px around the viewport kept mounted. Default: one viewport height. */
|
|
25
19
|
overscan?: number;
|
|
@@ -27,9 +21,23 @@ export interface VListConfig<T> {
|
|
|
27
21
|
* list sits at the bottom. */
|
|
28
22
|
inverted?: boolean;
|
|
29
23
|
}
|
|
30
|
-
/** A
|
|
31
|
-
*
|
|
32
|
-
export interface
|
|
24
|
+
/** A list fed by `data`: the rows are read reactively, the way a container's function children
|
|
25
|
+
* are. Such a list has no imperative feed (`append` and the rest are not on its type). */
|
|
26
|
+
export interface VListBoundConfig<T> extends VListBaseConfig<T> {
|
|
27
|
+
/** The rows, read reactively: the list follows the signals this reads. Rows are told apart by
|
|
28
|
+
* `keyOf`; a row whose item is another object re-renders. The change is told from the keys:
|
|
29
|
+
* rows gone are removals, new rows are inserts where they stand (a chat at its bottom follows
|
|
30
|
+
* an append; rows above the reader move nothing), a reorder rewrites the keys. */
|
|
31
|
+
data: () => T[];
|
|
32
|
+
}
|
|
33
|
+
/** A list fed by hand: `setData` / `append` / `prepend` / `update` / `removeByKey`. */
|
|
34
|
+
export interface VListFedConfig<T> extends VListBaseConfig<T> {
|
|
35
|
+
data?: undefined;
|
|
36
|
+
}
|
|
37
|
+
export type VListConfig<T> = VListBoundConfig<T> | VListFedConfig<T>;
|
|
38
|
+
/** What both forms of the list share: the items held, scrolling, the scroll / refresh / edge
|
|
39
|
+
* callbacks. */
|
|
40
|
+
export interface UIVirtualizedListBase<T = unknown> extends UIElementBase<UIVirtualizedListStyle> {
|
|
33
41
|
readonly type: "vlist";
|
|
34
42
|
/** Number of data items (mounted or not). */
|
|
35
43
|
readonly itemCount: number;
|
|
@@ -51,7 +59,29 @@ export interface UIVirtualizedList<T = unknown> extends UIElementBase<UIVirtuali
|
|
|
51
59
|
/** Same, for the top edge — chat history loading. */
|
|
52
60
|
onStartReached(thresholdPx: number, callback: () => void): this;
|
|
53
61
|
}
|
|
54
|
-
|
|
62
|
+
/** A virtualized list fed by `data` (a function over signals): write the signal, the list follows. */
|
|
63
|
+
export interface UIBoundVirtualizedList<T = unknown> extends UIVirtualizedListBase<T> {
|
|
64
|
+
}
|
|
65
|
+
/** A virtualized list fed by hand. Each call goes straight to the runtime: `append` is O(1). */
|
|
66
|
+
export interface UIFedVirtualizedList<T = unknown> extends UIVirtualizedListBase<T> {
|
|
67
|
+
/** Replace the data wholesale — diffed by key like a `data` write (vanished keys are removed,
|
|
68
|
+
* new ones inserted where they stand, a reorder rewrites). */
|
|
69
|
+
setData(items: T[]): this;
|
|
70
|
+
/** Append items to the end (auto-scrolls when `inverted` and resting at the bottom). */
|
|
71
|
+
append(...items: T[]): this;
|
|
72
|
+
/** Insert at the start WITHOUT a scroll jump (the runtime compensates the offset). */
|
|
73
|
+
prepend(...items: T[]): this;
|
|
74
|
+
/** Update items with the same keys: mounted ones re-render; the cached height persists until
|
|
75
|
+
* re-measured. */
|
|
76
|
+
update(...items: T[]): this;
|
|
77
|
+
/** Remove items by key. */
|
|
78
|
+
removeByKey(...keys: string[]): this;
|
|
79
|
+
}
|
|
80
|
+
/** A windowed (virtualized) list: only the items near the viewport are mounted — for long feeds
|
|
81
|
+
* and chats. Fed by `data`, a function over signals, or by hand (`append` and the rest); which
|
|
82
|
+
* one is the config's and the type's. */
|
|
83
|
+
export type UIVirtualizedList<T = unknown> = UIBoundVirtualizedList<T> | UIFedVirtualizedList<T>;
|
|
84
|
+
export declare class VListElement<T> extends Element<"vlist"> implements UIFedVirtualizedList<T> {
|
|
55
85
|
private readonly sl;
|
|
56
86
|
private readonly erl;
|
|
57
87
|
private readonly strl;
|
|
@@ -64,15 +94,28 @@ export declare class VListElement<T> extends Element<"vlist"> implements UIVirtu
|
|
|
64
94
|
private estimate;
|
|
65
95
|
private readonly _overscan;
|
|
66
96
|
private readonly _inverted;
|
|
97
|
+
private readonly _bound;
|
|
67
98
|
private _endThreshold;
|
|
68
99
|
private _startThreshold;
|
|
69
100
|
private _inited;
|
|
70
101
|
constructor(config: VListConfig<T>);
|
|
71
102
|
private _ensure;
|
|
72
|
-
/** The
|
|
73
|
-
*
|
|
74
|
-
|
|
103
|
+
/** The two feeds are exclusive per list: a hand-made change to a list `data` feeds would be
|
|
104
|
+
* undone by the binding's next run, so it is refused and logged. */
|
|
105
|
+
private _fed;
|
|
106
|
+
/** The data as it is now against what the runtime holds. Keys gone are removals, keys new are
|
|
107
|
+
* inserts where they stand in the new order — both anchored by the runtime (a chat follows an
|
|
108
|
+
* append, rows above the reader move nothing) — as long as the keys kept keep their order;
|
|
109
|
+
* a reorder rewrites the keys (measured heights stay). A mounted row whose item is another
|
|
110
|
+
* object re-renders. */
|
|
75
111
|
private _apply;
|
|
112
|
+
/** The new rows of `items` (keys not held yet, repeats dropped), registered. */
|
|
113
|
+
private _register;
|
|
114
|
+
setData(items: T[]): this;
|
|
115
|
+
append(...items: T[]): this;
|
|
116
|
+
prepend(...items: T[]): this;
|
|
117
|
+
update(...items: T[]): this;
|
|
118
|
+
removeByKey(...keys: string[]): this;
|
|
76
119
|
get itemCount(): number;
|
|
77
120
|
getItem(key: string): T | undefined;
|
|
78
121
|
scrollTo(offset: number, animated?: boolean): void;
|
|
@@ -83,6 +126,9 @@ export declare class VListElement<T> extends Element<"vlist"> implements UIVirtu
|
|
|
83
126
|
onEndReached(thresholdPx: number, callback: () => void): this;
|
|
84
127
|
onStartReached(thresholdPx: number, callback: () => void): this;
|
|
85
128
|
}
|
|
86
|
-
/** Create a virtualized list
|
|
87
|
-
*
|
|
88
|
-
|
|
129
|
+
/** Create a virtualized list (`keyOf` + `render` + `estimatedHeight` required). With `data` the
|
|
130
|
+
* list follows the signals it reads and has no hand feed; without it, feed it with `setData` /
|
|
131
|
+
* `append` / `prepend` / `update` / `removeByKey`. Give it a size (`flexGrow: 1` as a screen body). */
|
|
132
|
+
export declare function UIVirtualizedList<T>(config: VListBoundConfig<T>): UIBoundVirtualizedList<T>;
|
|
133
|
+
export declare function UIVirtualizedList<T>(config: VListFedConfig<T>): UIFedVirtualizedList<T>;
|
|
134
|
+
export {};
|