@voltro/client 0.53.0 → 0.55.0

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/index.d.ts CHANGED
@@ -16,6 +16,7 @@ import { RpcGroup } from '@effect/rpc';
16
16
  import { Schema } from 'effect';
17
17
  import { Stream } from 'effect';
18
18
  import { SubscriptionEvent } from '@voltro/protocol';
19
+ import { TargetRelations } from '@voltro/protocol';
19
20
  import { UIEvent as UIEvent_2 } from 'react';
20
21
  import { WorkflowDomainEventRow } from '@voltro/protocol';
21
22
  import { WorkflowEventDeliveryRow } from '@voltro/protocol';
@@ -315,6 +316,12 @@ export declare interface AutoApplyTarget {
315
316
  * nested-array item when `path` is set. Typed to the item, not the output.
316
317
  * 2nd arg is the optimistic id (insert) or the current item (update). */
317
318
  readonly shapeItem?: ((input: Record<string, unknown>, currentOrOptimisticId: unknown) => Record<string, unknown>) | undefined;
319
+ /** Declared many-to-many relations (`{ inputField: { junction, anchorColumn,
320
+ * targetColumn } }`). Drives JUNCTION auto-optimistic: entries sourced on the
321
+ * junction table get their link rows for this anchor reconciled against
322
+ * `input[inputField]` immediately, instead of waiting for the server delta
323
+ * while every scalar field of the same form has already flipped. */
324
+ readonly relations?: TargetRelations | undefined;
318
325
  }
319
326
 
320
327
  /**
@@ -822,6 +829,9 @@ export declare const deriveEntityAdmins: (manifest: CapabilityManifest) => Reado
822
829
  * outside a browser. Primary subtag only (`de-AT` → `de`). */
823
830
  export declare const documentLocale: () => string;
824
831
 
832
+ /** The empty value — what an unfilled rich-text field holds. */
833
+ export declare const emptyRichTextDocument: RichTextDocument;
834
+
825
835
  export declare const enqueueEntry: (queue: Outbox, id: string, tag: string, input: unknown) => Outbox;
826
836
 
827
837
  /**
@@ -1101,6 +1111,28 @@ export declare interface FormBinding<Input, Output> {
1101
1111
  readonly focusFirstInvalid: () => void;
1102
1112
  }
1103
1113
 
1114
+ /**
1115
+ * Make one binding reachable to every field component below, so
1116
+ * {@link useFormField} can find it WITHOUT the binding being threaded through
1117
+ * each one as a prop.
1118
+ *
1119
+ * That thread is what stops an incremental migration. A deployment moving a
1120
+ * hundred-plus forms keeps its own field context and swaps engines per form
1121
+ * with a single prop; `useFormField(form, path)` would have forced the binding
1122
+ * down to every one of their ~30 field components at once, so they adopted the
1123
+ * binding and declined the narrow subscription — the exact optimisation they
1124
+ * had the most forms to gain from.
1125
+ *
1126
+ * <FormBindingProvider binding={form}>{children}</FormBindingProvider>
1127
+ * // deeper: const f = useFormField('address.city')
1128
+ *
1129
+ * `<AutoForm>` mounts one for you.
1130
+ */
1131
+ export declare const FormBindingProvider: (props: {
1132
+ readonly binding: FormBinding<never, never> | FormBinding<Record<string, unknown>, unknown>;
1133
+ readonly children?: ReactNode;
1134
+ }) => ReactElement;
1135
+
1104
1136
  /**
1105
1137
  * Convert posted form entries into the input object the mutation's schema
1106
1138
  * decodes — the shape `validateFields` (and the RPC payload) expects.
@@ -1301,6 +1333,20 @@ export declare const getMutations: () => ReadonlyArray<MutationEvent>;
1301
1333
  */
1302
1334
  export declare const globalContext: <T>(key: string, initial: T) => Context<T>;
1303
1335
 
1336
+ /** True when `value` is structurally a rich-text document (a cheap render-side
1337
+ * guard; the decode remains the boundary). */
1338
+ export declare const isRichTextDocument: (value: unknown) => value is RichTextDocument;
1339
+
1340
+ /**
1341
+ * Is this `href` safe to put in a document?
1342
+ *
1343
+ * ALLOWLIST, never a denylist — a denylist is a list of the bypasses somebody
1344
+ * already thought of. Accepted: absolute `http(s)`, `mailto:`, a same-document
1345
+ * fragment, and a root-relative path. Everything else, `javascript:` and
1346
+ * `data:` included, is refused.
1347
+ */
1348
+ export declare const isSafeHref: (href: string) => boolean;
1349
+
1304
1350
  /** Is this the framework's `Unauthenticated`? Matched on `_tag`, the wire
1305
1351
  * contract, rather than on an instance — the error crosses a package boundary
1306
1352
  * and may be re-created by the decoder. */
@@ -1586,6 +1632,13 @@ export declare interface OutboxPersistence {
1586
1632
 
1587
1633
  export declare type OutboxStatus = 'pending' | 'sent' | 'failed' | 'conflict';
1588
1634
 
1635
+ /**
1636
+ * Parse the widget's markdown-subset SOURCE into a document. Total: every input
1637
+ * yields a valid document, because everything unrecognised is text. Not a
1638
+ * security boundary — see the header; the decode is.
1639
+ */
1640
+ export declare const parseRichText: (source: string) => RichTextDocument;
1641
+
1589
1642
  /** Provide the current subject's scopes to `useCan`. Mount it once high in the
1590
1643
  * tree, fed by your session subscription so it updates on role changes. */
1591
1644
  export declare function PermissionProvider(props: PermissionProviderProps): ReactNode;
@@ -1848,6 +1901,15 @@ export declare interface RecordState<R> {
1848
1901
  readonly error: unknown | undefined;
1849
1902
  }
1850
1903
 
1904
+ /**
1905
+ * Make an api's client descriptors visible to a SERVER render.
1906
+ *
1907
+ * Called by the boot paths before rendering a page; harmless in the browser,
1908
+ * where the real handle carries them. Idempotent — descriptors are static per
1909
+ * api, so last write wins.
1910
+ */
1911
+ export declare const registerSsrDescriptors: (apiName: string, descriptors: Readonly<Record<string, ClientDescriptor>>) => void;
1912
+
1851
1913
  /**
1852
1914
  * The entries to replay, in FIFO order, UP TO (not including) the first
1853
1915
  * conflict — a conflicted write blocks everything after it (causality). Sent
@@ -1872,6 +1934,9 @@ export declare const _resetFrameworkRuntimesWarning: () => void;
1872
1934
  /** Drop all applied client-side seeds. Tests only. */
1873
1935
  export declare const resetPreloadSeeds: () => void;
1874
1936
 
1937
+ /** Test-only: forget every registration. */
1938
+ export declare const _resetSsrDescriptors: () => void;
1939
+
1875
1940
  /** Test helper: forget every defined store. NEVER call this in app code. */
1876
1941
  export declare const resetStoreRegistryForTests: () => void;
1877
1942
 
@@ -1939,6 +2004,33 @@ export declare interface ResourceCansResult {
1939
2004
  readonly allowedIds: ReadonlyArray<string>;
1940
2005
  }
1941
2006
 
2007
+ /**
2008
+ * Keep only the keys the input schema DECLARES.
2009
+ *
2010
+ * The two submit paths had drifted apart on this, and the server sided with
2011
+ * neither: `formDataToInput` (the no-JS path) documents "unknown keys are
2012
+ * dropped", while the JS path validated with a decode that IGNORES excess
2013
+ * properties and then sent the object UNCHANGED. Since 0.37 the server
2014
+ * refuses an undeclared input field — so a form carrying anything beyond the
2015
+ * mutation's input (a display toggle, a repeat control, a file held before
2016
+ * upload, which is nearly every real form) passed client validation and was
2017
+ * rejected on the wire, with a message pointing at no field. Measured by a
2018
+ * deployment with `renderFormBinding`, our own harness.
2019
+ *
2020
+ * `toInput` is the seam for this and stays the recommended one — but it only
2021
+ * protects a form that HAS one, and the failure mode of not having one was a
2022
+ * green tick followed by a server refusal. Dropping matches the no-JS path,
2023
+ * so the two submits now agree; a genuinely mistyped key still surfaces,
2024
+ * because the field it was meant to be is then missing and fails validation.
2025
+ *
2026
+ * Non-struct schemas (a scalar input) are returned untouched — there is no
2027
+ * declared key set to restrict against.
2028
+ */
2029
+ export declare const restrictToSchema: (schema: Schema.Schema.Any, input: unknown) => {
2030
+ readonly input: unknown;
2031
+ readonly dropped: ReadonlyArray<string>;
2032
+ };
2033
+
1942
2034
  export declare interface ResumableAgentStreamControls<E> extends ResumableAgentStreamState<E> {
1943
2035
  /** Begin a run. `input` MUST carry the resume key (`streamId`) so reconnects
1944
2036
  * target the same server-side log; `fromSeq` is injected by the hook. */
@@ -2004,6 +2096,339 @@ export declare type ResumableStreamMethod<E> = (payload: unknown) => Stream.Stre
2004
2096
 
2005
2097
  export declare type ResumableStreamStatus = 'idle' | 'streaming' | 'reconnecting' | 'done' | 'error';
2006
2098
 
2099
+ /** Marks a text run may carry. Closed set — a mark is a NAME, never a style
2100
+ * string or attribute bag, so nothing here can express behaviour. */
2101
+ export declare const RICH_TEXT_MARKS: readonly ["bold", "italic", "code", "strike"];
2102
+
2103
+ /** Upper bound on the node count of one document. A refusal, not a hang: an
2104
+ * unbounded tree is a decode bomb on a server thread. */
2105
+ export declare const RICH_TEXT_MAX_NODES = 5000;
2106
+
2107
+ export declare type RichTextBlock = typeof RichTextBlock_2.Type;
2108
+
2109
+ declare const RichTextBlock_2: Schema.Union<[Schema.Struct<{
2110
+ type: Schema.Literal<["paragraph"]>;
2111
+ content: Schema.Array$<Schema.Union<[Schema.Struct<{
2112
+ type: Schema.Literal<["text"]>;
2113
+ text: typeof Schema.String;
2114
+ marks: Schema.optional<Schema.Array$<Schema.Literal<["bold", "italic", "code", "strike"]>>>;
2115
+ }>, Schema.Struct<{
2116
+ type: Schema.Literal<["link"]>;
2117
+ href: Schema.filter<typeof Schema.String>;
2118
+ content: Schema.Array$<Schema.Struct<{
2119
+ type: Schema.Literal<["text"]>;
2120
+ text: typeof Schema.String;
2121
+ marks: Schema.optional<Schema.Array$<Schema.Literal<["bold", "italic", "code", "strike"]>>>;
2122
+ }>>;
2123
+ }>]>>;
2124
+ }>, Schema.Struct<{
2125
+ type: Schema.Literal<["heading"]>;
2126
+ level: Schema.Literal<[1, 2, 3]>;
2127
+ content: Schema.Array$<Schema.Union<[Schema.Struct<{
2128
+ type: Schema.Literal<["text"]>;
2129
+ text: typeof Schema.String;
2130
+ marks: Schema.optional<Schema.Array$<Schema.Literal<["bold", "italic", "code", "strike"]>>>;
2131
+ }>, Schema.Struct<{
2132
+ type: Schema.Literal<["link"]>;
2133
+ href: Schema.filter<typeof Schema.String>;
2134
+ content: Schema.Array$<Schema.Struct<{
2135
+ type: Schema.Literal<["text"]>;
2136
+ text: typeof Schema.String;
2137
+ marks: Schema.optional<Schema.Array$<Schema.Literal<["bold", "italic", "code", "strike"]>>>;
2138
+ }>>;
2139
+ }>]>>;
2140
+ }>, Schema.Struct<{
2141
+ type: Schema.Literal<["blockquote"]>;
2142
+ content: Schema.Array$<Schema.Union<[Schema.Struct<{
2143
+ type: Schema.Literal<["text"]>;
2144
+ text: typeof Schema.String;
2145
+ marks: Schema.optional<Schema.Array$<Schema.Literal<["bold", "italic", "code", "strike"]>>>;
2146
+ }>, Schema.Struct<{
2147
+ type: Schema.Literal<["link"]>;
2148
+ href: Schema.filter<typeof Schema.String>;
2149
+ content: Schema.Array$<Schema.Struct<{
2150
+ type: Schema.Literal<["text"]>;
2151
+ text: typeof Schema.String;
2152
+ marks: Schema.optional<Schema.Array$<Schema.Literal<["bold", "italic", "code", "strike"]>>>;
2153
+ }>>;
2154
+ }>]>>;
2155
+ }>, Schema.Struct<{
2156
+ type: Schema.Literal<["bulletList"]>;
2157
+ content: Schema.Array$<Schema.Struct<{
2158
+ type: Schema.Literal<["listItem"]>;
2159
+ content: Schema.Array$<Schema.Union<[Schema.Struct<{
2160
+ type: Schema.Literal<["text"]>;
2161
+ text: typeof Schema.String;
2162
+ marks: Schema.optional<Schema.Array$<Schema.Literal<["bold", "italic", "code", "strike"]>>>;
2163
+ }>, Schema.Struct<{
2164
+ type: Schema.Literal<["link"]>;
2165
+ href: Schema.filter<typeof Schema.String>;
2166
+ content: Schema.Array$<Schema.Struct<{
2167
+ type: Schema.Literal<["text"]>;
2168
+ text: typeof Schema.String;
2169
+ marks: Schema.optional<Schema.Array$<Schema.Literal<["bold", "italic", "code", "strike"]>>>;
2170
+ }>>;
2171
+ }>]>>;
2172
+ }>>;
2173
+ }>, Schema.Struct<{
2174
+ type: Schema.Literal<["orderedList"]>;
2175
+ content: Schema.Array$<Schema.Struct<{
2176
+ type: Schema.Literal<["listItem"]>;
2177
+ content: Schema.Array$<Schema.Union<[Schema.Struct<{
2178
+ type: Schema.Literal<["text"]>;
2179
+ text: typeof Schema.String;
2180
+ marks: Schema.optional<Schema.Array$<Schema.Literal<["bold", "italic", "code", "strike"]>>>;
2181
+ }>, Schema.Struct<{
2182
+ type: Schema.Literal<["link"]>;
2183
+ href: Schema.filter<typeof Schema.String>;
2184
+ content: Schema.Array$<Schema.Struct<{
2185
+ type: Schema.Literal<["text"]>;
2186
+ text: typeof Schema.String;
2187
+ marks: Schema.optional<Schema.Array$<Schema.Literal<["bold", "italic", "code", "strike"]>>>;
2188
+ }>>;
2189
+ }>]>>;
2190
+ }>>;
2191
+ }>, Schema.Struct<{
2192
+ type: Schema.Literal<["codeBlock"]>;
2193
+ text: typeof Schema.String;
2194
+ }>]>;
2195
+
2196
+ declare type RichTextBlock = typeof RichTextBlock_2.Type;
2197
+
2198
+ /**
2199
+ * The rich-text field's value. Use it directly in a mutation input:
2200
+ *
2201
+ * Schema.Struct({ id: Schema.String, body: RichTextDocument })
2202
+ *
2203
+ * It carries the `rich-text` widget annotation, so `<AutoForm>` renders the
2204
+ * editor with no extra `formField({ widget })` call — and the decode that
2205
+ * validates the mutation input IS the sanitizing boundary (see the header).
2206
+ */
2207
+ export declare const RichTextDocument: Schema.refine<{
2208
+ readonly type: "doc";
2209
+ readonly content: readonly ({
2210
+ readonly type: "paragraph";
2211
+ readonly content: readonly ({
2212
+ readonly text: string;
2213
+ readonly type: "text";
2214
+ readonly marks?: readonly ("bold" | "strike" | "code" | "italic")[] | undefined;
2215
+ } | {
2216
+ readonly type: "link";
2217
+ readonly href: string;
2218
+ readonly content: readonly {
2219
+ readonly text: string;
2220
+ readonly type: "text";
2221
+ readonly marks?: readonly ("bold" | "strike" | "code" | "italic")[] | undefined;
2222
+ }[];
2223
+ })[];
2224
+ } | {
2225
+ readonly type: "heading";
2226
+ readonly level: 1 | 2 | 3;
2227
+ readonly content: readonly ({
2228
+ readonly text: string;
2229
+ readonly type: "text";
2230
+ readonly marks?: readonly ("bold" | "strike" | "code" | "italic")[] | undefined;
2231
+ } | {
2232
+ readonly type: "link";
2233
+ readonly href: string;
2234
+ readonly content: readonly {
2235
+ readonly text: string;
2236
+ readonly type: "text";
2237
+ readonly marks?: readonly ("bold" | "strike" | "code" | "italic")[] | undefined;
2238
+ }[];
2239
+ })[];
2240
+ } | {
2241
+ readonly type: "blockquote";
2242
+ readonly content: readonly ({
2243
+ readonly text: string;
2244
+ readonly type: "text";
2245
+ readonly marks?: readonly ("bold" | "strike" | "code" | "italic")[] | undefined;
2246
+ } | {
2247
+ readonly type: "link";
2248
+ readonly href: string;
2249
+ readonly content: readonly {
2250
+ readonly text: string;
2251
+ readonly type: "text";
2252
+ readonly marks?: readonly ("bold" | "strike" | "code" | "italic")[] | undefined;
2253
+ }[];
2254
+ })[];
2255
+ } | {
2256
+ readonly type: "bulletList";
2257
+ readonly content: readonly {
2258
+ readonly type: "listItem";
2259
+ readonly content: readonly ({
2260
+ readonly text: string;
2261
+ readonly type: "text";
2262
+ readonly marks?: readonly ("bold" | "strike" | "code" | "italic")[] | undefined;
2263
+ } | {
2264
+ readonly type: "link";
2265
+ readonly href: string;
2266
+ readonly content: readonly {
2267
+ readonly text: string;
2268
+ readonly type: "text";
2269
+ readonly marks?: readonly ("bold" | "strike" | "code" | "italic")[] | undefined;
2270
+ }[];
2271
+ })[];
2272
+ }[];
2273
+ } | {
2274
+ readonly type: "orderedList";
2275
+ readonly content: readonly {
2276
+ readonly type: "listItem";
2277
+ readonly content: readonly ({
2278
+ readonly text: string;
2279
+ readonly type: "text";
2280
+ readonly marks?: readonly ("bold" | "strike" | "code" | "italic")[] | undefined;
2281
+ } | {
2282
+ readonly type: "link";
2283
+ readonly href: string;
2284
+ readonly content: readonly {
2285
+ readonly text: string;
2286
+ readonly type: "text";
2287
+ readonly marks?: readonly ("bold" | "strike" | "code" | "italic")[] | undefined;
2288
+ }[];
2289
+ })[];
2290
+ }[];
2291
+ } | {
2292
+ readonly text: string;
2293
+ readonly type: "codeBlock";
2294
+ })[];
2295
+ }, Schema.Struct<{
2296
+ type: Schema.Literal<["doc"]>;
2297
+ content: Schema.Array$<Schema.Union<[Schema.Struct<{
2298
+ type: Schema.Literal<["paragraph"]>;
2299
+ content: Schema.Array$<Schema.Union<[Schema.Struct<{
2300
+ type: Schema.Literal<["text"]>;
2301
+ text: typeof Schema.String;
2302
+ marks: Schema.optional<Schema.Array$<Schema.Literal<["bold", "italic", "code", "strike"]>>>;
2303
+ }>, Schema.Struct<{
2304
+ type: Schema.Literal<["link"]>;
2305
+ href: Schema.filter<typeof Schema.String>;
2306
+ content: Schema.Array$<Schema.Struct<{
2307
+ type: Schema.Literal<["text"]>;
2308
+ text: typeof Schema.String;
2309
+ marks: Schema.optional<Schema.Array$<Schema.Literal<["bold", "italic", "code", "strike"]>>>;
2310
+ }>>;
2311
+ }>]>>;
2312
+ }>, Schema.Struct<{
2313
+ type: Schema.Literal<["heading"]>;
2314
+ level: Schema.Literal<[1, 2, 3]>;
2315
+ content: Schema.Array$<Schema.Union<[Schema.Struct<{
2316
+ type: Schema.Literal<["text"]>;
2317
+ text: typeof Schema.String;
2318
+ marks: Schema.optional<Schema.Array$<Schema.Literal<["bold", "italic", "code", "strike"]>>>;
2319
+ }>, Schema.Struct<{
2320
+ type: Schema.Literal<["link"]>;
2321
+ href: Schema.filter<typeof Schema.String>;
2322
+ content: Schema.Array$<Schema.Struct<{
2323
+ type: Schema.Literal<["text"]>;
2324
+ text: typeof Schema.String;
2325
+ marks: Schema.optional<Schema.Array$<Schema.Literal<["bold", "italic", "code", "strike"]>>>;
2326
+ }>>;
2327
+ }>]>>;
2328
+ }>, Schema.Struct<{
2329
+ type: Schema.Literal<["blockquote"]>;
2330
+ content: Schema.Array$<Schema.Union<[Schema.Struct<{
2331
+ type: Schema.Literal<["text"]>;
2332
+ text: typeof Schema.String;
2333
+ marks: Schema.optional<Schema.Array$<Schema.Literal<["bold", "italic", "code", "strike"]>>>;
2334
+ }>, Schema.Struct<{
2335
+ type: Schema.Literal<["link"]>;
2336
+ href: Schema.filter<typeof Schema.String>;
2337
+ content: Schema.Array$<Schema.Struct<{
2338
+ type: Schema.Literal<["text"]>;
2339
+ text: typeof Schema.String;
2340
+ marks: Schema.optional<Schema.Array$<Schema.Literal<["bold", "italic", "code", "strike"]>>>;
2341
+ }>>;
2342
+ }>]>>;
2343
+ }>, Schema.Struct<{
2344
+ type: Schema.Literal<["bulletList"]>;
2345
+ content: Schema.Array$<Schema.Struct<{
2346
+ type: Schema.Literal<["listItem"]>;
2347
+ content: Schema.Array$<Schema.Union<[Schema.Struct<{
2348
+ type: Schema.Literal<["text"]>;
2349
+ text: typeof Schema.String;
2350
+ marks: Schema.optional<Schema.Array$<Schema.Literal<["bold", "italic", "code", "strike"]>>>;
2351
+ }>, Schema.Struct<{
2352
+ type: Schema.Literal<["link"]>;
2353
+ href: Schema.filter<typeof Schema.String>;
2354
+ content: Schema.Array$<Schema.Struct<{
2355
+ type: Schema.Literal<["text"]>;
2356
+ text: typeof Schema.String;
2357
+ marks: Schema.optional<Schema.Array$<Schema.Literal<["bold", "italic", "code", "strike"]>>>;
2358
+ }>>;
2359
+ }>]>>;
2360
+ }>>;
2361
+ }>, Schema.Struct<{
2362
+ type: Schema.Literal<["orderedList"]>;
2363
+ content: Schema.Array$<Schema.Struct<{
2364
+ type: Schema.Literal<["listItem"]>;
2365
+ content: Schema.Array$<Schema.Union<[Schema.Struct<{
2366
+ type: Schema.Literal<["text"]>;
2367
+ text: typeof Schema.String;
2368
+ marks: Schema.optional<Schema.Array$<Schema.Literal<["bold", "italic", "code", "strike"]>>>;
2369
+ }>, Schema.Struct<{
2370
+ type: Schema.Literal<["link"]>;
2371
+ href: Schema.filter<typeof Schema.String>;
2372
+ content: Schema.Array$<Schema.Struct<{
2373
+ type: Schema.Literal<["text"]>;
2374
+ text: typeof Schema.String;
2375
+ marks: Schema.optional<Schema.Array$<Schema.Literal<["bold", "italic", "code", "strike"]>>>;
2376
+ }>>;
2377
+ }>]>>;
2378
+ }>>;
2379
+ }>, Schema.Struct<{
2380
+ type: Schema.Literal<["codeBlock"]>;
2381
+ text: typeof Schema.String;
2382
+ }>]>>;
2383
+ }>>;
2384
+
2385
+ export declare type RichTextDocument = typeof RichTextDocument.Type;
2386
+
2387
+ export declare type RichTextInline = typeof RichTextInline_2.Type;
2388
+
2389
+ declare const RichTextInline_2: Schema.Union<[Schema.Struct<{
2390
+ type: Schema.Literal<["text"]>;
2391
+ text: typeof Schema.String;
2392
+ marks: Schema.optional<Schema.Array$<Schema.Literal<["bold", "italic", "code", "strike"]>>>;
2393
+ }>, Schema.Struct<{
2394
+ type: Schema.Literal<["link"]>;
2395
+ href: Schema.filter<typeof Schema.String>;
2396
+ content: Schema.Array$<Schema.Struct<{
2397
+ type: Schema.Literal<["text"]>;
2398
+ text: typeof Schema.String;
2399
+ marks: Schema.optional<Schema.Array$<Schema.Literal<["bold", "italic", "code", "strike"]>>>;
2400
+ }>>;
2401
+ }>]>;
2402
+
2403
+ declare type RichTextInline = typeof RichTextInline_2.Type;
2404
+
2405
+ export declare type RichTextListItem = typeof RichTextListItem_2.Type;
2406
+
2407
+ declare const RichTextListItem_2: Schema.Struct<{
2408
+ type: Schema.Literal<["listItem"]>;
2409
+ content: Schema.Array$<Schema.Union<[Schema.Struct<{
2410
+ type: Schema.Literal<["text"]>;
2411
+ text: typeof Schema.String;
2412
+ marks: Schema.optional<Schema.Array$<Schema.Literal<["bold", "italic", "code", "strike"]>>>;
2413
+ }>, Schema.Struct<{
2414
+ type: Schema.Literal<["link"]>;
2415
+ href: Schema.filter<typeof Schema.String>;
2416
+ content: Schema.Array$<Schema.Struct<{
2417
+ type: Schema.Literal<["text"]>;
2418
+ text: typeof Schema.String;
2419
+ marks: Schema.optional<Schema.Array$<Schema.Literal<["bold", "italic", "code", "strike"]>>>;
2420
+ }>>;
2421
+ }>]>>;
2422
+ }>;
2423
+
2424
+ declare type RichTextListItem = typeof RichTextListItem_2.Type;
2425
+
2426
+ export declare type RichTextMark = (typeof RICH_TEXT_MARKS)[number];
2427
+
2428
+ /** The document's text, with no markers — for search indexing, excerpts and
2429
+ * plain-text notification bodies. */
2430
+ export declare const richTextToPlainText: (value: unknown) => string;
2431
+
2007
2432
  /** Pure: map source rows → `{ value, label }` options. Falls back to the value
2008
2433
  * when the label field is absent. Exported for direct testing + reuse. */
2009
2434
  export declare const rowsToOptions: (rows: ReadonlyArray<Record<string, unknown>>, labelField: string, valueField: string) => ReadonlyArray<FieldOption>;
@@ -2157,6 +2582,10 @@ export declare type SequenceResult<Ctx> = {
2157
2582
  }>;
2158
2583
  };
2159
2584
 
2585
+ /** Render a document back to the widget's source form. Accepts anything —
2586
+ * a field that has never been filled holds `undefined`. */
2587
+ export declare const serializeRichText: (value: unknown) => string;
2588
+
2160
2589
  export declare const ServerRequestContext: Context<ServerRequestContextValue | null>;
2161
2590
 
2162
2591
  export declare interface ServerRequestContextValue {
@@ -2255,6 +2684,9 @@ export declare const sourceValues: (sources: Record<string, unknown>) => Readonl
2255
2684
 
2256
2685
  export declare const ssrClientProxy: unknown;
2257
2686
 
2687
+ /** Registered SSR descriptors for `apiName`, if any. */
2688
+ export declare const ssrDescriptorsFor: (apiName: string) => Readonly<Record<string, ClientDescriptor>> | undefined;
2689
+
2258
2690
  export declare const ssrStubHandle: ApiHandle;
2259
2691
 
2260
2692
  /**
@@ -2828,9 +3260,13 @@ export declare interface SubscriptionMeta {
2828
3260
  * screen. Those still reach the api's error bus — subscribe with
2829
3261
  * `useOnRpcError` for connection-level UX.
2830
3262
  *
2831
- * A cold-start failure leaves `loading` TRUE (there is still nothing to
2832
- * render), so a component that branches on `loading` alone renders a skeleton
2833
- * forever. Check `error` to break out of it. */
3263
+ * A cold-start failure is its own STATE: `loading` is `false`, `failed` is
3264
+ * `true`, and this field is non-optional there (see
3265
+ * {@link SubscriptionFailed}). It used to leave `loading` true this
3266
+ * comment predicted the consequence, a deployment hit it, and the fix was
3267
+ * to stop making `loading` mean two things rather than to keep warning
3268
+ * about it. Branching on `loading` alone no longer renders a skeleton
3269
+ * forever. */
2834
3270
  readonly error: unknown | undefined;
2835
3271
  /** Number of live optimistic patches currently applied. Useful for
2836
3272
  * rendering a faint "syncing…" indicator when > 0. */
@@ -3424,6 +3860,9 @@ export declare interface UseEventOptions {
3424
3860
 
3425
3861
  export declare const useFormBinding: <Input extends Record<string, unknown> = Record<string, unknown>, Output = unknown>(apiName: string, mutationTag: string, options: UseFormBindingOptions<Input>) => FormBinding<Input, Output>;
3426
3862
 
3863
+ /** The enclosing binding, if a {@link FormBindingProvider} is mounted. */
3864
+ export declare const useFormBindingContext: () => FormBinding<Record<string, unknown>, unknown> | undefined;
3865
+
3427
3866
  export declare interface UseFormBindingOptions<Input> {
3428
3867
  /** The mutation's input `Schema`. Optional: when omitted it is resolved from
3429
3868
  * the mounted client descriptor (`descriptors[tag].input`, the capability
@@ -3478,6 +3917,17 @@ export declare interface UseFormBindingOptions<Input> {
3478
3917
  }) => Promise<unknown>;
3479
3918
  /** Ran after a successful submit with the mutation's output. */
3480
3919
  readonly onSuccess?: (output: unknown) => void;
3920
+ /**
3921
+ * Ran when a submit failed with something NO field can carry — a store
3922
+ * refusal, a constraint violation, a failure raised by a composed
3923
+ * `onSubmit`. The same value lands in `state.submitError`, so a banner
3924
+ * bound to that needs nothing here; this is for a toast or a report sink.
3925
+ *
3926
+ * `submit()` does not reject for these. It resolves `undefined` and the
3927
+ * failure is state, because a form calls `submit()` from a handler that
3928
+ * cannot await it — a rejection there has nowhere to go but the console.
3929
+ */
3930
+ readonly onError?: (error: unknown) => void;
3481
3931
  /**
3482
3932
  * Async field checks `submit` must wait for. Pass each field's
3483
3933
  * `useAsyncValidation` result under its field path:
@@ -3517,7 +3967,9 @@ export declare interface UseFormBindingOptions<Input> {
3517
3967
  * return <input id={f.a11y.id} value={String(f.value ?? '')} onChange={(e) => f.setValue(e.target.value)} onBlur={f.onBlur} />
3518
3968
  * }
3519
3969
  */
3520
- export declare const useFormField: (binding: FormBinding<never, never> | FormBinding<Record<string, unknown>, unknown>, path: string) => FormFieldHandle;
3970
+ export declare function useFormField(path: string): FormFieldHandle;
3971
+
3972
+ export declare function useFormField(binding: FormBinding<never, never> | FormBinding<Record<string, unknown>, unknown>, path: string): FormFieldHandle;
3521
3973
 
3522
3974
  /**
3523
3975
  * The failed-no-JS-POST payload for ONE form, or `undefined`.
@@ -3835,7 +4287,7 @@ export declare const validationStatus: (args: {
3835
4287
  /** The default widget kinds the framework can render from a schema. `'custom'`
3836
4288
  * means "no default widget" — the field needs a render-prop (a nested object,
3837
4289
  * an array of objects, or a multi-branch union). Mirrors innovation/01's set. */
3838
- export declare type WidgetKind = 'text' | 'textarea' | 'number' | 'checkbox' | 'switch' | 'select' | 'radio' | 'async-select' | 'multi-select' | 'date' | 'datetime' | 'daterange' | 'file' | 'hidden' | 'array' | 'reference' | 'custom';
4290
+ export declare type WidgetKind = 'text' | 'textarea' | 'rich-text' | 'number' | 'checkbox' | 'switch' | 'select' | 'radio' | 'async-select' | 'multi-select' | 'date' | 'datetime' | 'daterange' | 'file' | 'hidden' | 'array' | 'reference' | 'custom';
3839
4291
 
3840
4292
  export declare interface WindowedSubscriptionState<Row> {
3841
4293
  /** The in-window rows (live). */