lecodes-sdk 2.0.3 → 2.0.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.
Files changed (84) hide show
  1. package/README.md +104 -76
  2. package/dist/global.d.ts +3 -5
  3. package/dist/host.d.ts +3 -0
  4. package/dist/types/inject.d.ts +4 -4
  5. package/dist/types/net/codec.d.ts +3 -2
  6. package/dist/types/net/core.d.ts +10 -1
  7. package/dist/types/net/index.d.ts +22 -5
  8. package/dist/types/net/replication.d.ts +23 -2
  9. package/dist/types/runtime/device.d.ts +7 -0
  10. package/dist/types/runtime/rpc.d.ts +11 -17
  11. package/dist/types/runtime/wire.d.ts +53 -0
  12. package/dist/types/server/auth/api.d.ts +42 -0
  13. package/dist/types/server/auth/appConfig.d.ts +1 -5
  14. package/dist/types/server/auth/models.d.ts +119 -70
  15. package/dist/types/server/auth/types.d.ts +19 -43
  16. package/dist/types/server/channel.d.ts +57 -19
  17. package/dist/types/server/context.d.ts +2 -2
  18. package/dist/types/server/db/defineDb.d.ts +10 -0
  19. package/dist/types/server/db/index.d.ts +1 -1
  20. package/dist/types/server/db/types.d.ts +76 -6
  21. package/dist/types/server/inject.d.ts +0 -1
  22. package/dist/types/ui/UINode.d.ts +19 -5
  23. package/dist/types/ui/UIScreen.d.ts +1 -0
  24. package/dist/types/ui/UITabs.d.ts +8 -6
  25. package/dist/types/ui/theme.d.ts +48 -13
  26. package/dist/types/version.d.ts +1 -1
  27. package/dist/types.json +1 -1
  28. package/package.json +4 -2
  29. package/prompts/README.md +1 -1
  30. package/prompts/design.md +19 -19
  31. package/prompts/dist/2d-game.md +45 -31
  32. package/prompts/dist/3d-app.md +45 -31
  33. package/prompts/dist/ar-app.md +45 -31
  34. package/prompts/dist/design.md +25 -24
  35. package/prompts/dist/ui-app.md +45 -31
  36. package/prompts/ui-design.md +6 -5
  37. package/prompts/ui.md +25 -22
  38. package/src/animate/tween/read.ts +146 -0
  39. package/src/bridges/device.d.ts +9 -0
  40. package/src/bridges/tree.d.ts +5 -0
  41. package/src/canvas/gen/cssColor.ts +1 -1
  42. package/src/canvas/gen/recorder.ts +1 -1
  43. package/src/canvas/gen/spec.ts +1 -1
  44. package/src/chisel.ts +1 -1
  45. package/src/compile/bundler.ts +6 -0
  46. package/src/compile/compileProject.ts +3 -1
  47. package/src/compile/index.ts +3 -1
  48. package/src/compile/serverSplit.ts +58 -11
  49. package/src/compile/serverTypes.ts +189 -8
  50. package/src/host.d.ts +3 -0
  51. package/src/inject.ts +7 -7
  52. package/src/net/codec.ts +19 -10
  53. package/src/net/core.ts +18 -5
  54. package/src/net/index.ts +30 -9
  55. package/src/net/replication.ts +63 -28
  56. package/src/runtime/device.ts +12 -0
  57. package/src/runtime/rpc.ts +101 -40
  58. package/src/runtime/wire.ts +35 -0
  59. package/src/server/auth/api.ts +94 -0
  60. package/src/server/auth/appConfig.ts +2 -3
  61. package/src/server/auth/host.ts +244 -174
  62. package/src/server/auth/models.ts +45 -62
  63. package/src/server/auth/types.ts +19 -34
  64. package/src/server/channel.ts +97 -29
  65. package/src/server/channelHub.ts +153 -0
  66. package/src/server/context.ts +2 -2
  67. package/src/server/db/defineDb.ts +96 -36
  68. package/src/server/db/index.ts +1 -1
  69. package/src/server/db/types.ts +76 -8
  70. package/src/server/host.ts +25 -10
  71. package/src/server/inject.ts +2 -2
  72. package/src/server/runtime.ts +34 -12
  73. package/src/ui/UINode.ts +22 -5
  74. package/src/ui/UIScreen.ts +5 -0
  75. package/src/ui/UITabs.ts +19 -17
  76. package/src/ui/styleColor.ts +10 -1
  77. package/src/ui/theme.ts +96 -41
  78. package/src/version.ts +1 -1
  79. package/tests/helpers/fakeTree.ts +1 -0
  80. package/dist/types/plugins/oauth.d.ts +0 -25
  81. package/dist/types/server/auth/global.d.ts +0 -56
  82. package/src/plugins/oauth.ts +0 -61
  83. package/src/server/auth/global.ts +0 -80
  84. package/tests/helpers/memoryMarci.ts +0 -124
@@ -7,6 +7,7 @@
7
7
  * Naming: `S` = the schema record (model name → Model), `N` = a model name, `F` = a fields record.
8
8
  */
9
9
  import type { Field, FieldMeta } from "./fields";
10
+ import type { IdentityPublicFields, SessionPublicFields } from "../auth/models";
10
11
  import type { CompareNumValue, CompareRefListValue, CompareRefValue, CompareStrValue, CompareValue, CustomSearchValue, FullTextSearch, JsonCondition, JsonPathWhere, Op, PrimitiveListUpdate, Query as MarciQuery, RefListUpdate, RefListUpdateOrdered, RefUpdate, RefUpdateStruct, Rows, Sub, UpdateNumValue, VectorSearch, WhereValue } from "./marci/query";
11
12
  export type Fields = Record<string, Field<any, any>>;
12
13
  export type Model<F extends Fields = Fields> = {
@@ -86,7 +87,7 @@ type StructSelect<S, F extends Fields> = {
86
87
  [K in keyof F]?: FieldSelect<S, F[K]>;
87
88
  };
88
89
  type ScalarWhere<T, M extends FieldMeta> = Nullable<M, CompareValue<T>> | (IsNum<M> extends true ? CompareNumValue<T> : M["scalar"] extends "string" ? CompareStrValue<T> : never);
89
- type FieldWhere<S, Fld, M extends FieldMeta = MetaOf<Fld>> = M["kind"] extends "one" ? CompareRefValue<Where<S, ModelName<S, Fld>> | null> : M["kind"] extends "many" | "list" ? CompareRefListValue<Where<S, ModelName<S, Fld>>> : M["kind"] extends "struct" ? CompareRefValue<WhereValue<StructWhereFields<S, StructFieldsOf<Fld>>> | null> : M["kind"] extends "json" ? JsonPathWhere | JsonCondition : M["array"] extends true ? CompareValue<TsOf<Fld>> : ScalarWhere<TsOf<Fld>, M> | CustomSearchValue<FullTextSearch> | CustomSearchValue<VectorSearch>;
90
+ type FieldWhere<S, Fld, M extends FieldMeta = MetaOf<Fld>> = M["kind"] extends "one" ? CompareRefValue<Where<S, ModelName<S, Fld>> | null> : M["kind"] extends "many" | "list" ? CompareRefListValue<Where<S, ModelName<S, Fld>>> : M["kind"] extends "struct" ? CompareRefValue<WhereValue<StructWhereFields<S, StructFieldsOf<Fld>>> | null> : M["kind"] extends "json" ? JsonPathWhere | JsonCondition : M["array"] extends true ? TsOf<Fld>[] : ScalarWhere<TsOf<Fld>, M> | CustomSearchValue<FullTextSearch> | CustomSearchValue<VectorSearch>;
90
91
  type WhereFieldsOf<S, F extends Fields> = {
91
92
  [K in keyof F]?: FieldWhere<S, F[K]>;
92
93
  };
@@ -95,9 +96,15 @@ type IdWhere<S, N extends keyof S> = {
95
96
  };
96
97
  export type Where<S, N extends keyof S> = WhereValue<WhereFieldsOf<S, FieldsOf<S[N]>> & IdWhere<S, N>>;
97
98
  type StructWhereFields<S, F extends Fields> = WhereFieldsOf<S, F>;
99
+ type OrderKeys<S, N extends keyof S> = (ScalarKeys<FieldsOf<S[N]>> | keyof Id<S, N>) & keyof Row<S, N>;
100
+ /** ONE field and its direction: the engine sorts by a single field, so a second key is a type error. */
98
101
  export type Order<S, N extends keyof S> = {
99
- [K in (ScalarKeys<FieldsOf<S[N]>> | keyof Id<S, N>) & keyof Row<S, N>]?: "asc" | "desc";
100
- };
102
+ [K in OrderKeys<S, N>]: {
103
+ [P in K]: "asc" | "desc";
104
+ } & {
105
+ [P in Exclude<OrderKeys<S, N>, K>]?: never;
106
+ };
107
+ }[OrderKeys<S, N>];
101
108
  /** The query object — marcidb's wire form: a select shape plus the `$`-clauses. */
102
109
  export type QueryObject<S, N extends keyof S> = Select<S, N> & {
103
110
  $where?: Where<S, N>;
@@ -140,8 +147,14 @@ export type Query<S, N extends keyof S, Sel = ScalarSelect<S, N>> = MarciQuery<T
140
147
  export type Result<S, N extends keyof S, Q> = Rows<Types<S, N>, Q>;
141
148
  /** `db.<model>` — the root query of a model. */
142
149
  export type Collection<S, N extends keyof S> = Query<S, N>;
143
- export type Db<S extends Schema> = {
144
- [N in keyof S & string as Uncapitalize<N>]: Query<S, N>;
150
+ /** The platform's models a project's own may point at (`t.one("Session")`) — see ../auth/models.ts. */
151
+ type PlatformModels = {
152
+ Session: Model<SessionPublicFields>;
153
+ };
154
+ /** What a db's queries are typed against: the project's models and what they may point at. */
155
+ type Full<S> = S & PlatformModels;
156
+ type DbBase<S extends Schema> = {
157
+ [N in keyof S & string as Uncapitalize<N>]: Query<Full<S>, N>;
145
158
  } & {
146
159
  /** Atomic batch: all ops commit or none. `ref("0.id")` feeds a generated id into a later op. */
147
160
  $transaction<P extends readonly Op<any>[]>(ops: [...P]): Promise<{
@@ -150,8 +163,65 @@ export type Db<S extends Schema> = {
150
163
  /** The `.marci` schema text this db syncs with. */
151
164
  readonly $schema: string;
152
165
  };
166
+ export type Db<S extends Schema> = DbBase<S> & {
167
+ /**
168
+ * Sign-in for this database: `model` is the project's model of a user. Adds the platform's `Session`
169
+ * and `Identity` models beside it and gives the db its `auth`. Part of the definition — call it on
170
+ * `defineDb(...)` itself, before the db is used. Every field of the user model must be optional or
171
+ * have a default: the platform creates the row the first time someone signs in.
172
+ */
173
+ withAuth<N extends keyof S & string>(options: {
174
+ model: N;
175
+ }): DbWithAuth<S, N>;
176
+ };
177
+ export type DbWithAuth<S extends Schema, N extends keyof S & string> = DbBase<S> & {
178
+ readonly auth: Auth<S, N>;
179
+ };
180
+ /**
181
+ * The user of the current request, as a query over the project's user model: `select(shape)` picks the
182
+ * fields (id + scalars without it), `await` runs it. Nothing happens until it is awaited — a query that
183
+ * is never awaited checks nothing, which is why the compiler refuses one.
184
+ */
185
+ export interface UserQuery<S, N extends keyof S, Sel, Nil> extends PromiseLike<Result<S, N, Sel> | Nil> {
186
+ select<Q extends Select<S, N>>(shape: Q): UserQuery<S, N, Q, Nil>;
187
+ }
188
+ type AuthTables = {
189
+ Session: Model<SessionPublicFields>;
190
+ Identity: Model<IdentityPublicFields>;
191
+ };
192
+ /** `db.auth` — see ../auth/api.ts. */
193
+ export type Auth<S extends Schema, N extends keyof S & string> = {
194
+ /** The signed-in user, or `null` for a guest. */
195
+ user(): UserQuery<Full<S>, N, ScalarSelect<Full<S>, N>, null>;
196
+ /**
197
+ * The signed-in user; a guest is a 401. With `where` it is a check of access too: a user the filter
198
+ * does not match is a 403 — `await db.auth.requireUser({ role: "admin" }).select({ id: true })`.
199
+ */
200
+ requireUser(where?: Where<Full<S>, N>): UserQuery<Full<S>, N, ScalarSelect<Full<S>, N>, never>;
201
+ /** The device's session — there from the first request, before any sign-in (a guest's cart points at it). */
202
+ readonly sessionId: number;
203
+ /** A new account: `login` is an email or a name (3–32 letters, digits, `. _ -`), `data` the fields of the
204
+ * user's row. 409 when the login is taken. Signs this device in. */
205
+ signUpWithPassword(login: string, password: string, data?: Insert<Full<S>, N>): Promise<void>;
206
+ /** Signs this device in; 401 on any failure (rate-limited per login and ip). */
207
+ signInWithPassword(login: string, password: string): Promise<void>;
208
+ /** Sets the current user's password; every other device is signed out. */
209
+ setPassword(password: string): Promise<void>;
210
+ /** Emails a 6-digit code (always resolves — no "email exists" oracle; rate-limited). */
211
+ sendCode(email: string): Promise<void>;
212
+ /** Checks the code sent to this device, finds or creates the user, signs this device in. */
213
+ signInWithCode(email: string, code: string): Promise<void>;
214
+ /** For a person the project verified itself (a provider's sign-in, Telegram initData, SSO): binds this device to the user. */
215
+ signIn(userId: number): Promise<void>;
216
+ /** The device stays, as a guest. */
217
+ signOut(): Promise<void>;
218
+ /** The current user's devices, as a query: `await`, `.select()`, `.where(...).updateMany({ revoked: true })`. */
219
+ readonly sessions: Query<AuthTables, "Session">;
220
+ /** How the current user signs in, as a query: provider (`"email"` | `"login"`), subject, verifiedAt. */
221
+ readonly identities: Query<AuthTables, "Identity">;
222
+ };
153
223
  type RelKinds = "one" | "many" | "list";
154
- type CheckField<S, Fld> = MetaOf<Fld>["kind"] extends RelKinds ? MetaOf<Fld>["model"] extends keyof S ? Fld : `Unknown model "${MetaOf<Fld>["model"]}" — not a key of defineDb({...})` : Fld;
224
+ type CheckField<S, Fld> = MetaOf<Fld>["kind"] extends RelKinds ? MetaOf<Fld>["model"] extends keyof S | keyof PlatformModels ? Fld : `Unknown model "${MetaOf<Fld>["model"]}" — not a key of defineDb({...})` : Fld;
155
225
  /** Intersected with `S` in `defineDb`'s parameter: an unknown relation target fails to type-check on that field. */
156
226
  export type ValidateRefs<S extends Schema> = {
157
227
  [N in keyof S]: {
@@ -2,4 +2,3 @@ export { t, model, defineDb, ref } from "./db";
2
2
  export { ApiError } from "./errors";
3
3
  export { channel } from "./channel";
4
4
  export { request } from "./context";
5
- export { auth } from "./auth/global";
@@ -1,7 +1,9 @@
1
1
  import type { FetchResponse } from "../runtime/fetch";
2
+ import type { SvgSourceValue } from "../runtime/misc";
2
3
  import type { ColorInput } from "../core/color";
3
4
  import type { Animation } from "../animate/tween/Animation";
4
5
  import { type TweenMeta } from "../animate/tween/spec";
6
+ import { type ThemeRoles } from "./theme";
5
7
  import { type TreeElement } from "./tree";
6
8
  export interface UINode {
7
9
  readonly type: string;
@@ -18,7 +20,7 @@ export type UINodeChild = UINode | null | undefined | false;
18
20
  * needs no spread. */
19
21
  export type UIChildArg = UINodeChild | UINodeChild[];
20
22
  /** A color: any CSS color string (`"#1c1c1e"`, `"rgba(0,0,0,0.5)"`, `"green"`, `"hsl(210 50% 40%)"`),
21
- * a theme reference (`"var(--primaryColor)"`), an opaque `0xRRGGBB` number or `[r, g, b(, a)]` in
23
+ * a theme reference (`"var(--accent)"`), an opaque `0xRRGGBB` number or `[r, g, b(, a)]` in
22
24
  * 0..1; `null` clears. A string is the core's to parse (an unknown one is transparent, as in
23
25
  * CSS); a number or an array that is not a color throws at the write. */
24
26
  export type Color = ColorInput | null;
@@ -37,12 +39,13 @@ export type BaseStyle = {
37
39
  };
38
40
  /** Painted-box props: background, gradient, border, radius. */
39
41
  export type DrawableStyle = {
40
- backgroundImage?: FetchResponse | File | string | null;
42
+ backgroundImage?: FetchResponse | File | SvgSourceValue | string | null;
41
43
  bgGradient?: string;
42
44
  backgroundGradient?: string;
43
- bgImage?: FetchResponse | File | string | null;
44
- backgroundSize?: "cover" | "contain" | "tile";
45
- bgSize?: "cover" | "contain" | "tile";
45
+ bgImage?: FetchResponse | File | SvgSourceValue | string | null;
46
+ /** How the image fills the box. "tile": repeated at its own size from the top-left corner. */
47
+ backgroundSize?: "cover" | "contain" | "fill" | "tile";
48
+ bgSize?: "cover" | "contain" | "fill" | "tile";
46
49
  border?: string | number | null;
47
50
  borderWidth?: number;
48
51
  borderColor?: Color;
@@ -223,6 +226,16 @@ export interface UIElementBase<S extends object, A extends object = S> {
223
226
  name?: string;
224
227
  /** Set the semantic name (chainable). */
225
228
  named(name: string): this;
229
+ /** Theme variables for THIS element's subtree (chainable): the same keys as the app-wide
230
+ * `theme()`, read by everything under the element — and by the kit components there — before
231
+ * the app's table. `null` takes a key out of the scope. Reaches the element's descendants in
232
+ * the tree (a pager's pages and a list's items included); a screen pushed over it and a widget
233
+ * are roots of their own. Re-calling restyles the live subtree.
234
+ * ```ts
235
+ * promo.theme({ accent: "#FF3B30" }) // one card in another accent
236
+ * sheet.theme({ bg: "#000", text: "#FFF" }) // a dark screen in a light app
237
+ * ``` */
238
+ theme(values: ThemeRoles & Record<string, string | number | null>): this;
226
239
  /** Tween to the target style — meta keys `duration`/`delay`/`loop`/…, see {@link AnimateStyle}. */
227
240
  animateTo: AnimateStyle<this, A>;
228
241
  /** Tween from the given style to the current one (entrance animations). */
@@ -305,6 +318,7 @@ export declare class Element<T extends string> implements TreeElement {
305
318
  get name(): string | undefined;
306
319
  set name(value: string | undefined);
307
320
  named(name: string): this;
321
+ theme(values: Record<string, string | number | null>): this;
308
322
  get style(): any;
309
323
  /** Tween to the target style and commit it (unless `commit: false` or looping — a loop is an
310
324
  * effect, not a state change). A prop value may be an array of keyframes; meta keys
@@ -48,6 +48,7 @@ export interface UIScreen extends UIContainerBase<UIScreenStyle, DrawableStyle &
48
48
  onTouchStart(callback: (ev: TouchStartEvent<UIScreen>) => void): this;
49
49
  }
50
50
  export declare class ScreenElement extends ContainerElement<"screen"> {
51
+ constructor(type: "screen", style: any, children: any);
51
52
  open(options?: PresentOptions): void;
52
53
  close(options?: DismissOptions): void;
53
54
  protected ol: (() => void)[];
@@ -23,8 +23,9 @@ export type UITabDef = {
23
23
  * ```
24
24
  *
25
25
  * In-tab navigation stays the pager's: `UIPager.push(detail)` from any screen (bar stays);
26
- * `Router.push` opens above the shell (bar covered). Restyle via `theme()` (primaryColor,
27
- * mutedColor, tabbarBg, …) or the `bar` handle; for a fully custom bar build on `UIPager`.
26
+ * `Router.push` opens above the shell (bar covered). The bar is colored by the theme's roles
27
+ * (`accent`, `textMuted`, `surface`, `border`); `tabs.bar.theme({...})` overrides them for this
28
+ * bar alone, the `bar` handle restyles its box; for a fully custom bar build on `UIPager`.
28
29
  */
29
30
  export interface UITabs extends UIScreen {
30
31
  /** The active tab id. */
@@ -37,7 +38,8 @@ export interface UITabs extends UIScreen {
37
38
  badge(id: string, value: number | string | boolean | null): this;
38
39
  /** The pager under the bar — in-tab stacks (`push`/`pop`/`depth`). */
39
40
  readonly pager: UIPager;
40
- /** The bar row (named "tabbar") — for restyling beyond the theme variables. */
41
+ /** The bar row (named "tabbar") — `bar.theme({ accent, textMuted, surface, border })` for this
42
+ * bar's own colors, `bar.style({...})` for its box. */
41
43
  readonly bar: UIRowType;
42
44
  }
43
45
  export declare class TabsElement extends ScreenElement {
@@ -89,8 +91,8 @@ export type TabsHandle<T extends Record<string, TabDef>> = {
89
91
  * export default () => mainTabs.screen("home", [ ...content ])
90
92
  * ```
91
93
  *
92
- * Restyle through the theme — `theme({ primaryColor, mutedColor, tabbarBg, screenBg })` recolors
93
- * every bar at once. The built app passes the same keys (plus each tab's root screen) to `UITabs`,
94
- * which renders the identical bar interactively.
94
+ * The bar reads the theme's roles (`accent`, `textMuted`, `surface`, `border`), the screen its
95
+ * `bg` — one `theme({...})` colors every bar at once. The built app passes the same keys (plus
96
+ * each tab's root screen) to `UITabs`, which renders the identical bar interactively.
95
97
  */
96
98
  export declare function defineTabs<T extends Record<string, TabDef>>(tabs: T): TabsHandle<T>;
@@ -1,21 +1,56 @@
1
1
  import type { Transition } from "./presentable";
2
2
  export type ThemeValues = Record<string, string | number | null>;
3
+ /** The keys the SDK itself reads — the ROLES of a theme. An app's own keys sit beside them in the
4
+ * same call; kit components (`UITabs`) and the defaults of screens and text read these and nothing
5
+ * else, so one palette colors the app and the kit alike. A color is a string, never a number. */
6
+ export type ThemeRoles = {
7
+ /** The background of every screen. */
8
+ bg?: string | null;
9
+ /** A raised surface — cards, bars, sheets. The tab bar's background (without it: `bg`). */
10
+ surface?: string | null;
11
+ /** Hairlines and outlines. The tab bar's top line. */
12
+ border?: string | null;
13
+ /** Text that names no `color` of its own. */
14
+ text?: string | null;
15
+ /** Secondary text and inactive controls. The tab bar's inactive tabs. */
16
+ textMuted?: string | null;
17
+ /** The brand / active color. The tab bar's active tab. */
18
+ accent?: string | null;
19
+ /** The font of text that names no `fontFamily` of its own. */
20
+ fontFamily?: string | null;
21
+ };
22
+ /** What only the app-wide `theme()` takes: the comfort knobs (logical px) and the Router's default
23
+ * `replace` transition. */
24
+ export type ThemeAppKeys = {
25
+ "comfort-top"?: number | string | null;
26
+ "comfort-bottom"?: number | string | null;
27
+ "comfort-left"?: number | string | null;
28
+ "comfort-right"?: number | string | null;
29
+ replaceTransition?: Transition | null;
30
+ };
31
+ /** The `var(--key)` strings of the keys a `theme()` call defined — plain strings, so a helper's
32
+ * `(color = colors.accent)` parameter takes any color. */
3
33
  export type ThemeAccessors<T> = {
4
- readonly [K in keyof T]: K extends string ? `var(--${K})` : never;
34
+ readonly [K in Exclude<keyof T, "replaceTransition">]: string;
5
35
  };
6
36
  /** App theme: callable to merge variables (`theme({...})` — re-calling re-styles the live UI, so
7
- * dark mode is just a second call), with the system vars as static properties
8
- * (`theme.primaryColor`, `theme["comfort-top"]`, …). */
9
- export declare const theme: (<T extends Record<string, string | number | Transition | null>>(values: T & { [K in Exclude<keyof T, "replaceTransition">]: string | number | null; }) => ThemeAccessors<Omit<T, "replaceTransition">>) & {
10
- /** The app accent color. Kit components will read it via `var(--primaryColor, <fallback>)`. */
11
- readonly primaryColor: "var(--primaryColor)";
12
- /** Secondary / inactive content color for kit components. */
13
- readonly mutedColor: "var(--mutedColor)";
14
- /** DEFAULT text color — text without an explicit `color` follows it (hosts source their
15
- * default from the theme; unset = the host default, white on dark screens). Set it once for
16
- * a light theme instead of `color: "black"` on every label. */
17
- readonly color: "var(--color)";
18
- /** DEFAULT text font — text without an explicit `fontFamily` follows it. */
37
+ * dark mode is just a second call), with the roles as static properties (`theme.accent`,
38
+ * `theme["comfort-top"]`, …) for code that has no tokens module to import. */
39
+ export declare const theme: (<T extends ThemeRoles & ThemeAppKeys & Record<string, string | number | Transition | null>>(values: T & { [K in Exclude<keyof T, "replaceTransition">]: string | number | null; }) => ThemeAccessors<T>) & {
40
+ /** The background of every screen. */
41
+ readonly bg: "var(--bg)";
42
+ /** A raised surface — cards, bars, sheets. */
43
+ readonly surface: "var(--surface)";
44
+ /** Hairlines and outlines. */
45
+ readonly border: "var(--border)";
46
+ /** DEFAULT text color — text without a `color` of its own follows it (unset = the host's
47
+ * default: white). Set it once for a light theme instead of a color on every label. */
48
+ readonly text: "var(--text)";
49
+ /** Secondary text and inactive controls. */
50
+ readonly textMuted: "var(--textMuted)";
51
+ /** The brand / active color. */
52
+ readonly accent: "var(--accent)";
53
+ /** DEFAULT text font — text without a `fontFamily` of its own follows it. */
19
54
  readonly fontFamily: "var(--fontFamily)";
20
55
  /** Raw comfort knobs (logical px). The bare `comfort-top` style TOKEN applies the safe-area
21
56
  * formula — these accessors read the knob value itself, for manual composition. */
@@ -1,4 +1,4 @@
1
- export declare const SDK_VERSION = "2.0.3";
1
+ export declare const SDK_VERSION = "2.0.5";
2
2
  /** The major of a semver string, or null when it is not one. */
3
3
  export declare const sdkMajor: (version: string | null | undefined) => number | null;
4
4
  /** The `// sdk: <version>` line of a compiled bundle's header (sdk/src/compile/header.ts), read from