@ai-matrx/records-ui 0.3.1

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.
@@ -0,0 +1,1117 @@
1
+ import * as react from 'react';
2
+ import { ReactNode } from 'react';
3
+ import { Uuid as Uuid$1, Table, RecordsError, Field as Field$1, RecordDocument, ValueEnvelope, ParityFieldType, ReadRow as ReadRow$1, RuleExpression, AggregateBucket, AggregateMeasure, DocTemplateRow, DocRenderRow, AnonTokenBinding, RecordsConfig, RecordsActor, RecordsDataSource } from '@ai-matrx/records';
4
+ import { Uuid, Field, ReadRow } from '@ai-matrx/records/react';
5
+ import { MatrxColumnDef } from '@ai-matrx/design-system/data-table/types';
6
+ import { RecordsClient } from '@ai-matrx/records/core';
7
+
8
+ /** One named piece of grounding, shaped the way the platform's context slice takes them. */
9
+ interface RecordChatEntry {
10
+ key: string;
11
+ value: unknown;
12
+ label: string;
13
+ /** `text` for a scalar, `json` for a structure. The host maps this to its own vocabulary. */
14
+ type: "text" | "json";
15
+ }
16
+ /** A Field the STORE masked for this reader, named rather than silently dropped. */
17
+ interface RecordChatWithheld {
18
+ key: string;
19
+ label: string;
20
+ /** The store's own reason. */
21
+ reason: string;
22
+ }
23
+ /** Everything the host's chat surface needs, and nothing about how it should look. */
24
+ interface RecordChatContext {
25
+ /**
26
+ * A unique key per mounted conversation. Two record panels open at once must
27
+ * not fight over focus, so this is derived from the record and never a
28
+ * constant.
29
+ */
30
+ surfaceKey: string;
31
+ tableId: Uuid;
32
+ recordId: Uuid;
33
+ tableName: string;
34
+ /** The record's own title, for the panel's one-row header and the chip. */
35
+ title: string;
36
+ /** The grounding, already read through the read door. */
37
+ entries: RecordChatEntry[];
38
+ /** What this reader is NOT being given, with the store's reason for each. */
39
+ withheld: RecordChatWithheld[];
40
+ }
41
+ declare const NO_CHAT_REASON: string;
42
+ interface RecordChatProps {
43
+ tableId: Uuid;
44
+ recordId: Uuid;
45
+ className?: string | undefined;
46
+ }
47
+ declare function RecordChat({ tableId, recordId, className }: RecordChatProps): react.JSX.Element;
48
+
49
+ /** What the host is asked to have the server's `records` tool do. */
50
+ interface EnrichAsk {
51
+ tableId: Uuid;
52
+ recordId: Uuid;
53
+ /** The agent Fields to refill, each with why this panel thinks it is due. */
54
+ fields: Array<{
55
+ key: string;
56
+ label: string;
57
+ because: string;
58
+ }>;
59
+ }
60
+ interface EnrichOutcome {
61
+ ok: boolean;
62
+ /** What happened, in a sentence — the server's own words when it has some. */
63
+ message: string;
64
+ }
65
+ declare const NO_ENRICH_REASON: string;
66
+ interface EnrichPanelProps {
67
+ tableId: Uuid;
68
+ recordId: Uuid;
69
+ className?: string | undefined;
70
+ }
71
+ declare function EnrichPanel({ tableId, recordId, className }: EnrichPanelProps): react.JSX.Element;
72
+
73
+ /** What a person may do to one table. The words are the store's, not ours. */
74
+ interface TableRights {
75
+ /** SCR-2: holders of `admin` on the table see the "+" and the settings panel. */
76
+ admin: boolean;
77
+ /** SCR-18: `commenter` and no higher right. */
78
+ comment: boolean;
79
+ /** May write records at all. */
80
+ write: boolean;
81
+ /**
82
+ * Why this answer, in a sentence a person can read. Never empty: a right that
83
+ * is false without a reason is the silent failure this package refuses.
84
+ */
85
+ reason: string;
86
+ }
87
+ declare const NO_RIGHTS: TableRights;
88
+ interface RecordsUiHost {
89
+ /** Answer the rights question for one table. Synchronous: a screen renders now. */
90
+ rights?: (table: Table) => TableRights;
91
+ /** Where a record's own page lives, when the host has one. A peek is used when it does not. */
92
+ hrefForRecord?: (args: {
93
+ table: Table;
94
+ recordId: Uuid$1;
95
+ }) => string | undefined;
96
+ /** The host's own link element, so routing stays the host's business. */
97
+ Link?: (props: {
98
+ href: string;
99
+ children: ReactNode;
100
+ className?: string;
101
+ }) => ReactNode;
102
+ /** Toasts. Absent means the screen shows the sentence inline instead — never silence. */
103
+ notify?: {
104
+ success: (message: string) => void;
105
+ error: (message: string) => void;
106
+ };
107
+ /** Density for every table this package renders. */
108
+ density?: "condensed" | "normal" | "spacious";
109
+ /**
110
+ * OPTIONAL. Where a file a person attached actually goes. A File is a record
111
+ * in the kernel File Table (REC-31), but the BYTES are the host's file
112
+ * service, not this package's business — so this is a port.
113
+ *
114
+ * Unbound, an attachment question does NOT draw a file chooser that quietly
115
+ * loses the file: it says, in one sentence, that no file store is bound and
116
+ * names this port. Absent or honest, never dead.
117
+ */
118
+ upload?: (file: File) => Promise<{
119
+ ok: true;
120
+ fileId: Uuid$1;
121
+ } | {
122
+ ok: false;
123
+ reason: string;
124
+ }>;
125
+ /**
126
+ * OPTIONAL. The organization's saved views as `platform.saved_view` holds
127
+ * them — which is what a subscription points at (DOOR-18). The record store
128
+ * has NO door onto that table, because it is the platform's and not the
129
+ * store's, so this is a port rather than a read this package invents.
130
+ *
131
+ * Unbound, `NotifyRuleEditor` shows the subscriptions that exist and says, in
132
+ * one sentence, that it cannot offer a view to subscribe to. It never renders
133
+ * an empty picker that looks like "you have no views".
134
+ */
135
+ savedViews?: () => Promise<Array<{
136
+ id: Uuid$1;
137
+ name: string;
138
+ }>>;
139
+ /**
140
+ * OPTIONAL. THE HOST'S OWN CHAT SURFACE (SCR-26).
141
+ *
142
+ * This package ships no chat UI, on purpose: AI Matrx has exactly one, it
143
+ * lives in matrx-frontend (`AgentConversationColumn`), and it reads that app's
144
+ * Redux store — so a second one here would drift within a month and a package
145
+ * that imported the first would stop being a package. `RecordChat` therefore
146
+ * builds the CONTEXT (the record, through the read door, with the masked
147
+ * fields named) and hands it to this port.
148
+ *
149
+ * Unbound, the panel is ABSENT with that reason, never a composer that goes
150
+ * nowhere.
151
+ */
152
+ chat?: (context: RecordChatContext) => ReactNode;
153
+ /**
154
+ * OPTIONAL. THE SERVER'S `records` TOOL (SCR-27).
155
+ *
156
+ * An AI fill must be written with actor `agent` on behalf of the person, and
157
+ * only the server can honestly say that — a browser stamping itself `agent`
158
+ * is a browser claiming to be one. So `EnrichPanel` asks here, and the host
159
+ * calls the server's own `records` tool (`action: "record_write"`), which
160
+ * stamps `_actor` and `_on_behalf_of` itself.
161
+ *
162
+ * Unbound, no Fill control is drawn at all and the reason names this port.
163
+ */
164
+ enrich?: (ask: EnrichAsk) => Promise<EnrichOutcome>;
165
+ /**
166
+ * OPTIONAL. WHERE AN OFFLINE CAPTURE WAITS (SCR-30).
167
+ *
168
+ * `CaptureSheet` mints the id for a capture BEFORE it tries to send it, so a
169
+ * phone with no signal has already decided what the write will be called.
170
+ * Where that queue physically lives is the host's business — IndexedDB in a
171
+ * browser, a file in a desktop app — so it is a port. Unbound, the sheet
172
+ * keeps its queue in memory for the life of the page AND SAYS SO, because a
173
+ * queue that silently died with the tab is the failure this exists to avoid.
174
+ */
175
+ captureQueue?: CaptureQueuePort;
176
+ }
177
+ /** The durable half of offline capture: read the queue, write it, that is all. */
178
+ interface CaptureQueuePort {
179
+ load: () => Promise<PendingCapture[]>;
180
+ save: (pending: PendingCapture[]) => Promise<void>;
181
+ }
182
+ /** One capture waiting to be written, with the id the CLIENT minted for it. */
183
+ interface PendingCapture {
184
+ /**
185
+ * The client key. Minted offline, before the first attempt, and never
186
+ * re-minted on retry — that is exactly what lets the store's replay ledger
187
+ * tell a retry from a second capture.
188
+ */
189
+ clientKey: string;
190
+ tableId: Uuid$1;
191
+ payload: Record<string, unknown>;
192
+ capturedAt: string;
193
+ device: string;
194
+ /** How many times sending has been tried, and what the store last said. */
195
+ attempts: number;
196
+ lastRefusal?: string | null;
197
+ }
198
+ /** The sentence the notify editor shows when no saved-view port is bound. */
199
+ declare const NO_SAVED_VIEWS_REASON: string;
200
+ /** The sentence an attachment question shows when no file store is bound. */
201
+ declare const NO_UPLOAD_REASON: string;
202
+ declare function RecordsUiProvider({ value, children }: {
203
+ value: RecordsUiHost;
204
+ children: ReactNode;
205
+ }): react.JSX.Element;
206
+ declare function useRecordsUi(): RecordsUiHost;
207
+ /** The rights for one table — `NO_RIGHTS`, with its reason, when nothing is bound. */
208
+ declare function useTableRights(table: Table | null | undefined): TableRights;
209
+
210
+ declare function RefusalNotice({ error, className, actions, }: {
211
+ error: RecordsError;
212
+ className?: string | undefined;
213
+ actions?: ReactNode | undefined;
214
+ }): react.JSX.Element;
215
+ /** A small inline one, for a cell or a field where a block would break the layout. */
216
+ declare function RefusalLine({ error, className }: {
217
+ error: RecordsError;
218
+ className?: string | undefined;
219
+ }): react.JSX.Element;
220
+
221
+ interface GridProps {
222
+ tableId: Uuid;
223
+ /** Rows per page. The table's own pagination handles the rest. */
224
+ pageSize?: number | undefined;
225
+ /** Opened when a row is clicked. A host that has a record page passes its own. */
226
+ onOpenRecord?: ((recordId: Uuid) => void) | undefined;
227
+ /** SCR-2. Called when an admin clicks the "+" at the end of the headers. */
228
+ onAddField?: (() => void) | undefined;
229
+ /** Extra toolbar content — the view switcher, the export menu, the view bar. */
230
+ toolbarActions?: ReactNode | undefined;
231
+ className?: string | undefined;
232
+ }
233
+ declare function Grid({ tableId, pageSize, onOpenRecord, onAddField, toolbarActions, className, }: GridProps): react.JSX.Element;
234
+ /** One Field becomes one column. The header is the Field's label; the cell is the value, rendered by its parity type. */
235
+ declare function columnForField(field: Field): MatrxColumnDef<ReadRow>;
236
+
237
+ interface ExportMenuProps {
238
+ tableId: Uuid;
239
+ /** The rows on screen. Absent means "this table's first page", read the same way. */
240
+ rows?: ReadRow[] | undefined;
241
+ /** What the file is called. The table's name by default. */
242
+ label?: string | undefined;
243
+ className?: string | undefined;
244
+ }
245
+ declare function ExportMenu({ tableId, rows, label, className }: ExportMenuProps): react.JSX.Element;
246
+
247
+ interface ImportWizardProps {
248
+ tableId: Uuid;
249
+ /** SCR-N-7: what "add this as a field" does. Absent means the offer is not made. */
250
+ onProposeField?: ((header: string) => void) | undefined;
251
+ onDone?: ((written: number) => void) | undefined;
252
+ className?: string | undefined;
253
+ }
254
+ declare function ImportWizard({ tableId, onProposeField, onDone, className }: ImportWizardProps): react.JSX.Element;
255
+
256
+ interface CustomFieldsSectionProps {
257
+ /**
258
+ * The Table the Fields extend. For a standard entity this is the Table record
259
+ * that stands for that entity — the host passes it, because which entity a
260
+ * page is showing is the page's own fact.
261
+ *
262
+ * A page that knows the entity's TOKEN rather than its id passes `entityToken`
263
+ * instead, and this section resolves it: an entity page must not have to run
264
+ * a lookup of its own to add one line.
265
+ */
266
+ tableId?: Uuid | undefined;
267
+ /** The entity's registered token (REC-33), e.g. `party`. Resolved to its Table. */
268
+ entityToken?: string | undefined;
269
+ recordId: Uuid;
270
+ /** The heading. One row, no subtitle restating it. */
271
+ title?: string | undefined;
272
+ className?: string | undefined;
273
+ }
274
+ declare function CustomFieldsSection({ tableId, entityToken, recordId, title, className, }: CustomFieldsSectionProps): react.JSX.Element | null;
275
+
276
+ interface FieldEditorProps {
277
+ tableId: Uuid$1;
278
+ /** The Field being edited. Absent means a new one. */
279
+ field?: Field$1 | undefined;
280
+ onSaved?: (() => void) | undefined;
281
+ onCancel?: (() => void) | undefined;
282
+ className?: string | undefined;
283
+ }
284
+ declare function FieldEditor({ tableId, field, onSaved, onCancel, className }: FieldEditorProps): react.JSX.Element;
285
+
286
+ interface FieldProposalRow {
287
+ id: string;
288
+ /** What the agent proposed, in the Field shape the store would store. */
289
+ field: Partial<Field> & {
290
+ key: string;
291
+ label?: string;
292
+ };
293
+ why: string;
294
+ proposed_by: string;
295
+ }
296
+ interface TableSettingsProps {
297
+ tableId: Uuid;
298
+ /**
299
+ * SCR-5. Pending field proposals. The door that lists them
300
+ * (`custom.field_propose`) does not exist yet — `@ai-matrx/records` answers
301
+ * `door_absent` by name for it — so a host passes what it has, and when it
302
+ * has nothing the section says so rather than pretending there is nothing to
303
+ * approve.
304
+ */
305
+ proposals?: FieldProposalRow[] | undefined;
306
+ onAcceptProposal?: ((proposal: FieldProposalRow) => void) | undefined;
307
+ onRejectProposal?: ((proposal: FieldProposalRow) => void) | undefined;
308
+ className?: string | undefined;
309
+ }
310
+ declare function TableSettings({ tableId, proposals, onAcceptProposal, onRejectProposal, className, }: TableSettingsProps): react.JSX.Element;
311
+
312
+ interface PeekProps {
313
+ tableId: Uuid;
314
+ recordId: Uuid;
315
+ onClose?: (() => void) | undefined;
316
+ className?: string | undefined;
317
+ }
318
+ declare function Peek({ tableId, recordId, onClose, className }: PeekProps): react.JSX.Element;
319
+
320
+ interface RecordFormProps {
321
+ tableId: Uuid;
322
+ /** Absent means "create". Present means "edit that record". */
323
+ recordId?: Uuid | undefined;
324
+ /** FLD-10: which Fields apply is the store's decision, and it takes the record type. */
325
+ recordType?: string | undefined;
326
+ onSaved?: ((recordId: Uuid) => void) | undefined;
327
+ onCancel?: (() => void) | undefined;
328
+ className?: string | undefined;
329
+ }
330
+ declare function RecordForm({ tableId, recordId, recordType, onSaved, onCancel, className, }: RecordFormProps): react.JSX.Element;
331
+
332
+ interface RelationPickerProps {
333
+ field: Field$1;
334
+ value: unknown;
335
+ onChange: (value: unknown) => void;
336
+ disabled?: boolean | undefined;
337
+ id?: string | undefined;
338
+ className?: string | undefined;
339
+ }
340
+ declare function RelationPicker({ field, value, onChange, disabled, id, className }: RelationPickerProps): react.JSX.Element;
341
+
342
+ interface FieldEditorControlProps {
343
+ field: Field$1;
344
+ value: unknown;
345
+ onChange: (value: unknown) => void;
346
+ disabled?: boolean | undefined;
347
+ id?: string | undefined;
348
+ }
349
+ /** The label row every editor shares: one line, the label, the unit, the required mark. */
350
+ declare function FieldLabel({ field, htmlFor, children }: {
351
+ field: Field$1;
352
+ htmlFor: string;
353
+ children?: ReactNode;
354
+ }): react.JSX.Element;
355
+ declare function FieldControl({ field, value, onChange, disabled, id }: FieldEditorControlProps): react.JSX.Element;
356
+ /** The chip a picked record shows as — REC-2's "a record is a chip" in one place. */
357
+ declare function RecordChip({ title, onRemove, className, }: {
358
+ title: string;
359
+ onRemove?: (() => void) | undefined;
360
+ className?: string | undefined;
361
+ }): react.JSX.Element;
362
+
363
+ /** The envelope for one key, when the document carries one. */
364
+ declare function envelopeFor(document: RecordDocument | undefined, key: string): ValueEnvelope | undefined;
365
+ declare function renderValue(field: Field$1, value: unknown, document?: RecordDocument): react.JSX.Element;
366
+ /** The text of one scalar, with the Field's UNIT and FORMAT applied — FLD-N-1 says both change the MEANING. */
367
+ declare function scalarText(field: Field$1, value: unknown): string;
368
+ /** The provenance badge a value carries when the store interned a source for it (SCR-27). */
369
+ declare function ProvenanceBadge({ document, fieldKey }: {
370
+ document: RecordDocument | undefined;
371
+ fieldKey: string;
372
+ }): react.JSX.Element | null;
373
+
374
+ declare const PARITY_LABEL: Record<ParityFieldType, string>;
375
+ /** The "made of" sentence the store itself publishes, for the field editor's help text. */
376
+ declare const PARITY_MADE_OF: Record<string, string>;
377
+ /** Plain text and plain number are behaviours with no parity type of their own. */
378
+ type EditorKind = ParityFieldType | "relation" | "text" | "number" | "boolean" | "date" | "long_text";
379
+ /**
380
+ * Which editor one Field wants. Reads the Field's own declaration only — the
381
+ * behaviour, the modifiers, the format, the relation target and the config —
382
+ * because those are what the store stores, and a screen that guessed from a
383
+ * value would draw a different editor for an empty record.
384
+ */
385
+ declare function editorKindFor(field: Field$1): EditorKind;
386
+ /** The type word a person sees in a header or a settings row. */
387
+ declare function fieldTypeLabel(field: Field$1): string;
388
+
389
+ /** One Field of a package-owned Table, in the store's own words. */
390
+ interface SystemFieldSpec {
391
+ key: string;
392
+ label: string;
393
+ /** FLD-1: one of the five behaviours. `text` covers the json-ish ones too. */
394
+ type: "text" | "range" | "list" | "relation" | "formula";
395
+ sort: number;
396
+ required?: boolean;
397
+ multi?: boolean;
398
+ config?: Record<string, unknown>;
399
+ }
400
+ interface SystemTableSpec {
401
+ /** The token this Table is addressed by. Every package table starts `records_ui_`. */
402
+ slug: string;
403
+ name: string;
404
+ labelSingular: string;
405
+ labelPlural: string;
406
+ titleField: string;
407
+ fields: SystemFieldSpec[];
408
+ }
409
+ /** Find this organization's copy of a package-owned Table, declaring it the first time. */
410
+ declare function ensureSystemTable(client: RecordsClient, spec: SystemTableSpec): Promise<{
411
+ ok: true;
412
+ data: Uuid$1;
413
+ } | {
414
+ ok: false;
415
+ error: RecordsError;
416
+ }>;
417
+ interface UseSystemTableState {
418
+ tableId: Uuid$1 | null;
419
+ loading: boolean;
420
+ error: RecordsError | null;
421
+ }
422
+ /** The hook every package-owned component opens with. */
423
+ declare function useSystemTable(spec: SystemTableSpec): UseSystemTableState;
424
+
425
+ /** The four ways one saved view can be looked at (SCR-6). */
426
+ declare const VIEW_LAYOUTS: readonly ["grid", "kanban", "calendar", "gallery"];
427
+ type ViewLayout = (typeof VIEW_LAYOUTS)[number];
428
+ declare const LAYOUT_LABEL: Record<ViewLayout, string>;
429
+ /**
430
+ * What each layout needs before it can draw anything, in one sentence a screen
431
+ * prints. A layout that is missing its Field says so instead of rendering an
432
+ * empty board that looks like "no records".
433
+ */
434
+ declare const LAYOUT_NEEDS: Record<ViewLayout, string | null>;
435
+ /** One sort clause. The Field's key and a direction; nothing else is a sort. */
436
+ interface ViewSort {
437
+ field: string;
438
+ direction: "asc" | "desc";
439
+ }
440
+ /**
441
+ * THE DECLARATIVE SPEC. An agent writes this whole object; a person tweaks it.
442
+ * Every builder component in this package takes one of these as a prop.
443
+ */
444
+ interface SavedViewSpec {
445
+ name: string;
446
+ /** The Table this view looks at. */
447
+ subject: Uuid$1;
448
+ layout: ViewLayout;
449
+ /** Kanban: the Field whose value becomes a column. */
450
+ groupField?: string | null;
451
+ /** Calendar: the Field that places a record in the month. */
452
+ dateField?: string | null;
453
+ /** Gallery: the Field shown large on the card. */
454
+ imageField?: string | null;
455
+ sorts?: ViewSort[];
456
+ /**
457
+ * The membership Rule. The STORE decides who is in this view; this is a
458
+ * reference to its Rule record, never a predicate this package evaluates.
459
+ */
460
+ ruleId?: Uuid$1 | null;
461
+ isDefault?: boolean;
462
+ }
463
+ /** A saved view as it comes back out of the store, with its record's own id. */
464
+ interface SavedView extends SavedViewSpec {
465
+ id: Uuid$1;
466
+ /**
467
+ * The record's version AT LOAD, read from `custom.io_revisions` for the one
468
+ * record being edited. The read door answers documents and not versions, so
469
+ * this is null until it has been read — and a save with a null version is an
470
+ * ordinary last-writer-wins write, exactly as the store defines it.
471
+ */
472
+ version: number | null;
473
+ }
474
+ /** The package-owned Table every saved view is a record of. */
475
+ declare const VIEW_TABLE: SystemTableSpec;
476
+ /** The spec as the one document the store holds. */
477
+ declare function viewDocument(spec: SavedViewSpec): Record<string, unknown>;
478
+ /** One stored record back into the spec a screen and an agent both read. */
479
+ declare function viewFromRecord(row: ReadRow$1): SavedView;
480
+
481
+ interface ViewSwitcherProps {
482
+ /**
483
+ * THE DECLARATIVE SPEC — an agent writes the whole thing, a person tweaks it.
484
+ * `ViewBar` passes the saved view it loaded; a host with no saved views at all
485
+ * can pass a literal here and the switcher works.
486
+ */
487
+ view: SavedViewSpec;
488
+ /** Called when the person picks another layout, so the host can save it. */
489
+ onLayoutChange?: ((layout: ViewLayout) => void) | undefined;
490
+ onOpenRecord?: ((recordId: Uuid) => void) | undefined;
491
+ pageSize?: number | undefined;
492
+ className?: string | undefined;
493
+ }
494
+ /** The records this view holds: its Rule's members when it names one, the table otherwise. */
495
+ declare function useViewRecords(view: SavedViewSpec, pageSize?: number): {
496
+ rows: ReadRow[];
497
+ loading: boolean;
498
+ error: RecordsError | null;
499
+ /** Where membership came from, in a sentence. A screen that hides this is hiding the view's meaning. */
500
+ membership: string;
501
+ };
502
+ declare function ViewSwitcher({ view, onLayoutChange, onOpenRecord, pageSize, className }: ViewSwitcherProps): react.JSX.Element;
503
+
504
+ interface ViewBarProps {
505
+ /** The Table whose views these are. */
506
+ tableId: Uuid;
507
+ /** The view that is showing. Leave it out and the bar picks the default, then the first. */
508
+ activeViewId?: Uuid | null | undefined;
509
+ onActiveView?: ((view: SavedView) => void) | undefined;
510
+ /**
511
+ * COMPLETE DECLARATIVE SPECS an agent wrote. Any of these whose name this
512
+ * table does not have yet is saved as a record the first time the bar loads.
513
+ * The person tweaks them afterwards like any other view.
514
+ */
515
+ seed?: SavedViewSpec[] | undefined;
516
+ className?: string | undefined;
517
+ }
518
+ declare function ViewBar({ tableId, activeViewId, onActiveView, seed, className }: ViewBarProps): react.JSX.Element;
519
+
520
+ /** One proposed change, in the proposer's words plus the exact act it asks for. */
521
+ interface ProposedChange {
522
+ id: string;
523
+ act: "add" | "update" | "remove";
524
+ /** The Table the change lands in. */
525
+ table: Uuid;
526
+ /** The record it changes. Required for `update` and `remove`. */
527
+ record?: Uuid | undefined;
528
+ /** The document for `add`, or the patch for `update`. */
529
+ data?: Record<string, unknown> | undefined;
530
+ /** What this change is, in one line a person reads. */
531
+ label: string;
532
+ /** Why the proposer asks for it. Optional, and shown when it is there. */
533
+ why?: string | undefined;
534
+ }
535
+ type ProposalOutcome = {
536
+ settled: "accepted";
537
+ sentence: string;
538
+ } | {
539
+ settled: "rejected";
540
+ sentence: string;
541
+ } | {
542
+ settled: "refused";
543
+ sentence: string;
544
+ };
545
+ interface ProposalRowProps {
546
+ change: ProposedChange;
547
+ /** What already happened to this change, when the host remembers decisions. */
548
+ outcome?: ProposalOutcome | undefined;
549
+ /**
550
+ * The apply port. Left unbound, the row applies the change through the record
551
+ * store itself — the default that makes the component plug and play. A host
552
+ * whose proposals land somewhere else (a different store, a server lane)
553
+ * binds this and keeps the SAME row.
554
+ */
555
+ onApply?: ((change: ProposedChange) => Promise<ProposalOutcome>) | undefined;
556
+ onReject?: ((change: ProposedChange) => Promise<ProposalOutcome> | ProposalOutcome) | undefined;
557
+ /** Absent controls with this reason, instead of dead ones. */
558
+ readOnlyReason?: string | undefined;
559
+ onSettled?: ((outcome: ProposalOutcome) => void) | undefined;
560
+ className?: string | undefined;
561
+ }
562
+ declare function ProposalRow({ change, outcome, onApply, onReject, readOnlyReason, onSettled, className, }: ProposalRowProps): react.JSX.Element;
563
+
564
+ /** The three things that land in the queue. One word each, closed. */
565
+ declare const ACTION_KINDS: readonly ["approval", "assignment", "proposal"];
566
+ type ActionKind = (typeof ACTION_KINDS)[number];
567
+ /** The package-owned Table every queued action is a record of. */
568
+ declare const ACTION_TABLE: SystemTableSpec;
569
+ /**
570
+ * THE DECLARATIVE SPEC an agent writes. One `record_write` of this document puts
571
+ * a decision in front of a person — there is no per-feature approval plumbing
572
+ * anywhere in the platform.
573
+ */
574
+ interface QueuedActionSpec {
575
+ kind: ActionKind;
576
+ title: string;
577
+ why?: string | undefined;
578
+ assignee?: Uuid | null | undefined;
579
+ subjectTable?: Uuid | null | undefined;
580
+ subject?: Uuid | null | undefined;
581
+ /** For a proposal: the exact acts being asked for. */
582
+ changes?: ProposedChange[] | undefined;
583
+ }
584
+ interface QueuedAction extends QueuedActionSpec {
585
+ id: Uuid;
586
+ /**
587
+ * The version this row was read at. The read door answers documents and not
588
+ * versions, so a queue row carries null and settling it is the store's
589
+ * ordinary last-writer-wins write — the row's own `status` is what a second
590
+ * settler then sees.
591
+ */
592
+ version: number | null;
593
+ status: "open" | "accepted" | "rejected" | "refused";
594
+ answer: string | null;
595
+ at: string;
596
+ }
597
+ declare function actionDocument(spec: QueuedActionSpec): Record<string, unknown>;
598
+ interface ActionInboxProps {
599
+ /** Narrow the queue to one table's actions. Left out, it is everything waiting. */
600
+ tableId?: Uuid | null | undefined;
601
+ /** Show settled actions too. The default is what is still waiting. */
602
+ includeSettled?: boolean | undefined;
603
+ /**
604
+ * COMPLETE DECLARATIVE SPECS an agent wrote. Any of these the queue does not
605
+ * already hold (by title) is filed as a record on first load.
606
+ */
607
+ seed?: QueuedActionSpec[] | undefined;
608
+ onOpenRecord?: ((recordId: Uuid, tableId: Uuid) => void) | undefined;
609
+ className?: string | undefined;
610
+ }
611
+ declare function ActionInbox({ tableId, includeSettled, seed, onOpenRecord, className }: ActionInboxProps): react.JSX.Element;
612
+
613
+ interface HistoryPanelProps {
614
+ tableId: Uuid;
615
+ recordId: Uuid;
616
+ className?: string | undefined;
617
+ }
618
+ declare function HistoryPanel({ tableId, recordId, className }: HistoryPanelProps): react.JSX.Element;
619
+
620
+ /** The package-owned Table every comment is a record of. */
621
+ declare const COMMENT_TABLE: SystemTableSpec;
622
+ interface CommentThreadProps {
623
+ /** The Table the commented-on record belongs to — its rights decide the composer. */
624
+ tableId: Uuid;
625
+ /** The record being discussed. */
626
+ recordId: Uuid;
627
+ className?: string | undefined;
628
+ }
629
+ declare function CommentThread({ tableId, recordId, className }: CommentThreadProps): react.JSX.Element;
630
+
631
+ /** How a form is put in front of a person. */
632
+ declare const FORM_FLOWS: readonly ["one-at-a-time", "single-page"];
633
+ type FormFlow = (typeof FORM_FLOWS)[number];
634
+ /** One question. It ASKS FOR one Field of the subject Table — never its own column. */
635
+ interface FormQuestionSpec {
636
+ /** The Field's key on the subject Table. */
637
+ field: string;
638
+ /** Ask it in the form's own words. Left out, the Field's own label is the question. */
639
+ ask?: string | null;
640
+ /** One line under the question. */
641
+ help?: string | null;
642
+ /** Override the Field's own `required`. Left out, the Field decides. */
643
+ required?: boolean | null;
644
+ /**
645
+ * CONDITIONAL LOGIC, AS A RULE. `{"op":"eq","args":[{"field":"<field id>"},{"const":"Yes"}]}`
646
+ * — the store answers it, this package never does. An UNDECIDED answer (the
647
+ * store's `null`, which is what an unanswered question gives) SHOWS the
648
+ * question: a person is never silently skipped past something.
649
+ */
650
+ showIf?: RuleExpression | null;
651
+ }
652
+ /** The look. Tokens, so light and dark both come out right without a second theme. */
653
+ interface FormTheme {
654
+ /** A design-system accent class or a CSS color. Left out, the app's own accent. */
655
+ accent?: string | null;
656
+ align?: "left" | "center" | null;
657
+ }
658
+ /** THE COMPLETE DECLARATIVE SPEC. One `record_write` and the form exists. */
659
+ interface FormSpec {
660
+ name: string;
661
+ /** The Table a submission lands in. */
662
+ subject: Uuid$1;
663
+ intro?: string | null;
664
+ questions: FormQuestionSpec[];
665
+ flow?: FormFlow | null;
666
+ theme?: FormTheme | null;
667
+ thankYou?: {
668
+ title: string;
669
+ body?: string | null;
670
+ } | null;
671
+ submitLabel?: string | null;
672
+ /**
673
+ * Is this form meant to be answerable by someone who is not signed in? The
674
+ * runner does NOT make that true by itself — it needs the anonymous write
675
+ * door, and until that door exists it says so BY NAME rather than writing as
676
+ * whoever happens to be signed in and calling it public.
677
+ */
678
+ isPublic?: boolean;
679
+ }
680
+ /** A form as it comes back out of the store, with its record's own id and version. */
681
+ interface SavedForm extends FormSpec {
682
+ id: Uuid$1;
683
+ /**
684
+ * The record's version AT LOAD, read from `custom.io_revisions` for the one
685
+ * record being edited. The read door answers documents and not versions, so
686
+ * this is null until it has been read — and a save with a null version is an
687
+ * ordinary last-writer-wins write, exactly as the store defines it.
688
+ */
689
+ version: number | null;
690
+ }
691
+ /** The package-owned Table every form is a record of. */
692
+ declare const FORM_TABLE: SystemTableSpec;
693
+ /** The spec as the one document the store holds. */
694
+ declare function formDocument(spec: FormSpec): Record<string, unknown>;
695
+ /** One stored record back into the spec a screen and an agent both read. */
696
+ declare function formFromRecord(row: ReadRow$1): SavedForm;
697
+ /**
698
+ * THE SOURCE STAMP every submission carries. A record that arrived through a
699
+ * form is not indistinguishable from one somebody typed into the grid: it says
700
+ * which form, which version of it, when, and who was acting. `_source` is a
701
+ * stamp on the document beside the answers, so it travels with the record
702
+ * through export, History and the agent's context without a parallel table.
703
+ */
704
+ declare function submissionStamp(args: {
705
+ formId: Uuid$1 | null;
706
+ formName: string;
707
+ actor: string;
708
+ onBehalfOf?: string | null;
709
+ }): Record<string, unknown>;
710
+
711
+ interface FormBuilderProps {
712
+ /** The Table this form collects into. A form is a view on a real Table. */
713
+ tableId: Uuid;
714
+ /**
715
+ * COMPLETE DECLARATIVE SPECS an agent wrote. Any of these whose name this
716
+ * table does not have yet is saved as a record the first time the builder
717
+ * loads. A seed whose name exists is LEFT ALONE — an agent re-running never
718
+ * overwrites what a person has since tweaked.
719
+ */
720
+ seed?: FormSpec[] | undefined;
721
+ activeFormId?: Uuid | null | undefined;
722
+ onActiveForm?: ((form: SavedForm) => void) | undefined;
723
+ className?: string | undefined;
724
+ }
725
+ declare function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }: FormBuilderProps): react.JSX.Element;
726
+
727
+ /** The shapes a block can take. Closed: a shape nobody drew is not offered. */
728
+ declare const CHART_KINDS: readonly ["bar", "column", "line", "donut", "number", "table"];
729
+ type ChartKind = (typeof CHART_KINDS)[number];
730
+ declare const CHART_KIND_LABEL: Record<ChartKind, string>;
731
+ /** What each shape needs before it can draw, in one sentence a block prints. */
732
+ declare const CHART_NEEDS: Record<ChartKind, string | null>;
733
+ /** ONE BLOCK: the question and the shape, in one declarative object. */
734
+ interface ChartSpec {
735
+ title: string;
736
+ /** The Table this block asks about. */
737
+ subject: Uuid$1;
738
+ kind: ChartKind;
739
+ /** Field keys whose values become the groups. */
740
+ groupBy?: string[];
741
+ /** A date Field truncated to a period — what a line runs along. */
742
+ bucket?: {
743
+ key: string;
744
+ by: AggregateBucket;
745
+ } | null;
746
+ /** `count` needs no key; every other measure reads one Field. */
747
+ measures?: AggregateMeasure[];
748
+ /** Equality only, and the store puts it in the SAME WHERE as visibility. */
749
+ filter?: Record<string, string>;
750
+ limit?: number;
751
+ /** How wide this block sits on the canvas, in twelfths. */
752
+ span?: number;
753
+ }
754
+ /** THE WHOLE DASHBOARD, as one object an agent writes in one call. */
755
+ interface DashboardSpec {
756
+ name: string;
757
+ /** The Table most of its blocks are about. A block may name another. */
758
+ subject: Uuid$1;
759
+ blocks: ChartSpec[];
760
+ }
761
+ interface SavedDashboard extends DashboardSpec {
762
+ id: Uuid$1;
763
+ /**
764
+ * The record's version AT LOAD, read from `custom.io_revisions` for the one
765
+ * record being edited. The read door answers documents and not versions, so
766
+ * this is null until it has been read — and a save with a null version is an
767
+ * ordinary last-writer-wins write, exactly as the store defines it.
768
+ */
769
+ version: number | null;
770
+ }
771
+ /** The package-owned Table every dashboard is a record of. */
772
+ declare const DASHBOARD_TABLE: SystemTableSpec;
773
+ declare function dashboardDocument(spec: DashboardSpec): Record<string, unknown>;
774
+ declare function dashboardFromRecord(row: ReadRow$1): SavedDashboard;
775
+ /**
776
+ * The series palette. Six SEMANTIC tokens the design system already flips for
777
+ * dark mode, so a chart is correct in both themes without a second palette and
778
+ * without a hex code anywhere in this package.
779
+ */
780
+ declare const SERIES_COLORS: readonly ["hsl(var(--primary))", "hsl(var(--info))", "hsl(var(--success))", "hsl(var(--warning))", "hsl(var(--destructive))", "hsl(var(--accent-foreground))"];
781
+ /** The label one aggregate row carries — its groups, joined the way a person reads them. */
782
+ declare function groupLabel(groups: Record<string, string | null>): string;
783
+
784
+ /** The one token form, written the way the store's own pattern reads it. */
785
+ declare function fieldToken(fieldId: Uuid$1): string;
786
+ /** THE DECLARATIVE SPEC an agent writes. One template, whole, in one object. */
787
+ interface DocTemplateSpec {
788
+ name: string;
789
+ /** The body, tokens and all. */
790
+ body: string;
791
+ }
792
+ /**
793
+ * A template written in terms of Field KEYS — which is how an agent thinks and
794
+ * how a person reads — turned into the store's id-based tokens. The agent writes
795
+ * `{{title}}`; what is stored points at the Field's id, so a rename never
796
+ * silently empties the document.
797
+ *
798
+ * A key this Table does not have is LEFT EXACTLY AS IT IS, so
799
+ * `custom.doc_unresolved_tokens` names it and the screen shows the store's own
800
+ * reason — it is never quietly deleted from the body.
801
+ */
802
+ declare function bodyFromKeys(body: string, fields: Field$1[]): string;
803
+ /** The reverse, for a person reading a stored body: ids shown as the Field's label. */
804
+ declare function bodyForReading(body: string, fields: Field$1[]): string;
805
+ /** VAL-10: a signature is a Value on a text Field whose format is `signature`. */
806
+ declare function isSignatureField(field: Field$1): boolean;
807
+
808
+ interface DocTemplateProps {
809
+ /** The Table these templates render. */
810
+ tableId: Uuid;
811
+ /** COMPLETE templates an agent wrote, in Field keys. Saved once, never overwritten. */
812
+ seed?: DocTemplateSpec[] | undefined;
813
+ activeTemplateId?: Uuid | null | undefined;
814
+ onActiveTemplate?: ((template: DocTemplateRow) => void) | undefined;
815
+ className?: string | undefined;
816
+ }
817
+ declare function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, className }: DocTemplateProps): react.JSX.Element;
818
+
819
+ interface DocRenderProps {
820
+ templateId: Uuid;
821
+ recordId: Uuid;
822
+ /** A name for the file when somebody takes the PDF. */
823
+ filename?: string | undefined;
824
+ onRendered?: ((render: DocRenderRow) => void) | undefined;
825
+ className?: string | undefined;
826
+ }
827
+ declare function DocRender({ templateId, recordId, filename, onRendered, className }: DocRenderProps): react.JSX.Element;
828
+
829
+ interface SignBlockProps {
830
+ tableId: Uuid;
831
+ recordId: Uuid;
832
+ /** The frozen version being signed. Without one there is nothing to seal. */
833
+ render: DocRenderRow | null;
834
+ className?: string | undefined;
835
+ }
836
+ declare function SignBlock({ tableId, recordId, render, className }: SignBlockProps): react.JSX.Element;
837
+
838
+ /** THE DECLARATIVE SPEC an agent writes. One declaration and a person is told. */
839
+ interface NotifyRuleSpec {
840
+ name: string;
841
+ savedViewId: Uuid;
842
+ /** `immediate` fires on the change; `digest` is collected and sent on a schedule. */
843
+ cadence?: string;
844
+ /** The digest's schedule, in the store's own words. Meaningless for `immediate`. */
845
+ schedule?: string | null;
846
+ channel?: string;
847
+ /** Who is told. Left out, the person setting it up — "tell ME". */
848
+ recipientUserId?: Uuid | null;
849
+ eventKey?: string;
850
+ }
851
+ interface NotifyRuleEditorProps {
852
+ /** The Table these subscriptions are about — the Rule's scope. */
853
+ tableId: Uuid;
854
+ /** COMPLETE declarative subscriptions an agent wrote. Saved once, never overwritten. */
855
+ seed?: NotifyRuleSpec[] | undefined;
856
+ className?: string | undefined;
857
+ }
858
+ declare function NotifyRuleEditor({ tableId, seed, className }: NotifyRuleEditorProps): react.JSX.Element;
859
+
860
+ interface ChartBlockProps {
861
+ spec: ChartSpec;
862
+ className?: string | undefined;
863
+ }
864
+ declare function ChartBlock({ spec, className }: ChartBlockProps): react.JSX.Element;
865
+
866
+ interface DashboardCanvasProps {
867
+ /** The Table these blocks are about. */
868
+ tableId: Uuid;
869
+ /** COMPLETE declarative dashboards an agent wrote. Saved once, never overwritten. */
870
+ seed?: DashboardSpec[] | undefined;
871
+ activeDashboardId?: Uuid | null | undefined;
872
+ className?: string | undefined;
873
+ }
874
+ declare function DashboardCanvas({ tableId, seed, activeDashboardId, className }: DashboardCanvasProps): react.JSX.Element;
875
+
876
+ interface FormRunnerProps {
877
+ /** The complete spec. An agent wrote it; `FormBuilder` saved it; this runs it. */
878
+ form: FormSpec | SavedForm;
879
+ /** Preview mode answers the questions but writes nothing, and says so. */
880
+ preview?: boolean | undefined;
881
+ onSubmitted?: ((recordId: Uuid) => void) | undefined;
882
+ className?: string | undefined;
883
+ }
884
+ declare function FormRunner({ form, preview, onSubmitted, className }: FormRunnerProps): react.JSX.Element;
885
+
886
+ /** THE COMPLETE DECLARATIVE SPEC — one object, one `record_write`, a whole checklist. */
887
+ interface ChecklistSpec {
888
+ name: string;
889
+ /** The Table the steps become records in. */
890
+ subject: Uuid;
891
+ steps: ChecklistStepSpec[];
892
+ }
893
+ interface ChecklistStepSpec {
894
+ /** The document this step's record starts life with. `title` is what a person reads. */
895
+ title: string;
896
+ /** Anything else the subject Table's Fields take. */
897
+ data?: Record<string, unknown>;
898
+ }
899
+ /**
900
+ * The package-owned Table a checklist RUN is recorded in. The steps are records
901
+ * in the subject Table — this holds only which template was instantiated and
902
+ * when, so re-opening a checklist finds the same steps rather than making new
903
+ * ones. (Running the same checklist twice on purpose is two rows here, which is
904
+ * the correct answer: they are two runs.)
905
+ */
906
+ declare const CHECKLIST_TABLE: SystemTableSpec;
907
+ interface ChecklistRunnerProps {
908
+ /** The Table the steps live in — normally the same Table the checklist is about. */
909
+ tableId: Uuid;
910
+ /** The agent's half. Each spec not already run is instantiated once. */
911
+ seed?: ChecklistSpec[] | undefined;
912
+ className?: string | undefined;
913
+ }
914
+ declare function ChecklistRunner({ tableId, seed, className }: ChecklistRunnerProps): react.JSX.Element;
915
+
916
+ interface BookingSlotsProps {
917
+ /** The Table holds are taken against, and the Table a booking lands in. */
918
+ tableId: Uuid;
919
+ /** The form a person fills in once they hold a slot. Its `subject` is the Table. */
920
+ form: FormSpec;
921
+ /** Availability — the organization's opinion, with a default rather than a question. */
922
+ availability?: {
923
+ /** First hour offered, 24h. Default 9. */
924
+ fromHour?: number;
925
+ /** Last hour offered, exclusive. Default 17. */
926
+ toHour?: number;
927
+ /** Minutes per slot. Default 60. */
928
+ everyMinutes?: number;
929
+ /** How many days ahead to offer. Default 5. */
930
+ days?: number;
931
+ };
932
+ /** How long a hold lasts before the store lets the slot go. Default 15 minutes. */
933
+ holdFor?: string;
934
+ onBooked?: ((recordId: Uuid) => void) | undefined;
935
+ className?: string | undefined;
936
+ }
937
+ declare function BookingSlots({ tableId, form, availability, holdFor, onBooked, className, }: BookingSlotsProps): react.JSX.Element;
938
+
939
+ /** The three things a phone captures. Each one writes the SAME kind of record. */
940
+ declare const CAPTURE_MODES: readonly ["reading", "photo", "voice"];
941
+ type CaptureMode = (typeof CAPTURE_MODES)[number];
942
+ declare const IN_MEMORY_QUEUE_REASON: string;
943
+ interface CaptureSheetProps {
944
+ /** The Table a capture becomes a record in. */
945
+ tableId: Uuid;
946
+ /** Which Field a reading's number goes in. Defaults to the first range Field. */
947
+ readingField?: string | undefined;
948
+ /** Which Field the note goes in. Defaults to the Table's title field. */
949
+ noteField?: string | undefined;
950
+ /** Which Field an attachment's file id goes in. */
951
+ attachmentField?: string | undefined;
952
+ className?: string | undefined;
953
+ }
954
+ declare function CaptureSheet({ tableId, readingField, noteField, attachmentField, className, }: CaptureSheetProps): react.JSX.Element;
955
+
956
+ interface PortalShellProps {
957
+ /** The Table the outsider's records belong to. */
958
+ tableId: Uuid;
959
+ /** OPTIONAL. A form the outsider may send — their one way to put something in. */
960
+ form?: FormSpec | undefined;
961
+ /** What the resources are called in `iam`'s own vocabulary. Default `record`. */
962
+ resourceType?: string;
963
+ className?: string | undefined;
964
+ }
965
+ declare function PortalShell({ tableId, form, resourceType, className }: PortalShellProps): react.JSX.Element;
966
+
967
+ interface PublicViewPageProps {
968
+ /** The public address, exactly as it appears in the URL. */
969
+ slug: string;
970
+ className?: string | undefined;
971
+ }
972
+ declare function PublicViewPage({ slug, className }: PublicViewPageProps): react.JSX.Element;
973
+
974
+ interface EmbedFrameProps {
975
+ /** The Table whose rights decide whether an embed may be issued at all. */
976
+ tableId: Uuid;
977
+ /** A write embed names the form it writes into. */
978
+ formId?: Uuid | null | undefined;
979
+ /** A read embed names the saved view or the record it shows. */
980
+ savedViewId?: Uuid | null | undefined;
981
+ recordId?: Uuid | null | undefined;
982
+ /** Where the embedded page is served from — the `src` of the iframe. */
983
+ embedUrl: string;
984
+ className?: string | undefined;
985
+ }
986
+ declare function EmbedFrame({ tableId, formId, savedViewId, recordId, embedUrl, className, }: EmbedFrameProps): react.JSX.Element;
987
+ /**
988
+ * THE OTHER HALF, RUNNING INSIDE THE IFRAME ON SOMEBODY ELSE'S PAGE.
989
+ *
990
+ * It hands the secret and this page's own origin to the store and uses whatever
991
+ * comes back. It decides nothing itself: a handshake that checked the origin in
992
+ * JavaScript would be a handshake an attacker can edit.
993
+ *
994
+ * `origin` is taken from `window.location.origin` by default rather than from a
995
+ * prop, because a prop is a value the embedding page controls and the origin
996
+ * must not be.
997
+ */
998
+ declare function useEmbedHandshake(args: {
999
+ secret: string;
1000
+ requiredMode?: "read" | "write";
1001
+ origin?: string;
1002
+ }): {
1003
+ binding: AnonTokenBinding | null;
1004
+ error: RecordsError | null;
1005
+ loading: boolean;
1006
+ };
1007
+
1008
+ declare const STORE_DECIDES_REASON: string;
1009
+ declare const KERNEL_REASON: string;
1010
+ /**
1011
+ * The rights answer for a host whose authority IS the record store's doors.
1012
+ * Offers the control; the store refuses with its own sentence if it must.
1013
+ */
1014
+ declare function storeDecidesRights(table: Table): TableRights;
1015
+ interface RecordsMountProps {
1016
+ /** The store config: the host's session-carrying client, the actor, the organization. */
1017
+ config: RecordsConfig;
1018
+ /** What this host binds on top — links, toasts, uploads, rights. */
1019
+ host?: RecordsUiHost | undefined;
1020
+ /**
1021
+ * Use `storeDecidesRights` when the host binds no `rights` of its own. Left
1022
+ * off, an unbound host gets `NO_RIGHTS` and every administering control is
1023
+ * absent with its reason.
1024
+ */
1025
+ letTheStoreDecideRights?: boolean | undefined;
1026
+ children: ReactNode;
1027
+ }
1028
+ declare function RecordsMount({ config, host, letTheStoreDecideRights, children, }: RecordsMountProps): react.JSX.Element;
1029
+ /**
1030
+ * The actor a signed-in person is. `user` is the store's own word (the closed
1031
+ * ACTOR_VOCABULARY is `user` · `agent` · `system`), and AGT-N-4 means an agent
1032
+ * acting for this person carries exactly this authority and no other.
1033
+ */
1034
+ declare function personActor(userId: Uuid$1 | null | undefined): RecordsActor;
1035
+ /**
1036
+ * A supabase-js client AS this package's data seam.
1037
+ *
1038
+ * `RecordsDataSource` is deliberately a small structural subset of
1039
+ * `SupabaseClient` — the package holds no key and opens no connection, the host
1040
+ * hands it a client that already carries the person's session. Structurally the
1041
+ * two agree. PROVING it does not fit in the type checker's budget: a generated
1042
+ * `Database` type makes `schema().from().select()` enormous, and a host app
1043
+ * that passes its client straight into `config` gets
1044
+ * `TS2589: Type instantiation is excessively deep and possibly infinite` in its
1045
+ * own build (matrx-frontend, 2026-09-18, on all three campaign routes at once).
1046
+ *
1047
+ * So the assertion is made HERE, once, where it is explained — rather than as a
1048
+ * cast copied into every route that mounts a screen.
1049
+ */
1050
+ declare function recordsDataSource(client: object, schema?: string): RecordsDataSource;
1051
+
1052
+ type TableLane = "mine" | "organization" | "system" | "community";
1053
+ /** The four lanes, in the order a person reads them. Never a flat list. */
1054
+ declare const TABLE_LANES: readonly TableLane[];
1055
+ declare const LANE_TITLE: Record<TableLane, string>;
1056
+ /** What fills an empty lane. A heading with nothing under it must still teach. */
1057
+ declare const LANE_EMPTY: Record<TableLane, string>;
1058
+ /** Which lane one Table belongs to, from the record's own columns. */
1059
+ declare function laneFor(table: Table): TableLane;
1060
+ interface TablesHomeProps {
1061
+ /** Where a table opens. Absent and the card is a plain row with no pretend link. */
1062
+ onOpenTable?: ((tableId: Uuid$1) => void) | undefined;
1063
+ className?: string | undefined;
1064
+ }
1065
+ declare function TablesHome({ onOpenTable, className }: TablesHomeProps): react.JSX.Element;
1066
+
1067
+ interface TablePageProps {
1068
+ tableId: Uuid$1;
1069
+ /** Rows per page for every layout. */
1070
+ pageSize?: number | undefined;
1071
+ className?: string | undefined;
1072
+ }
1073
+ declare function TablePage({ tableId, pageSize, className }: TablePageProps): react.JSX.Element;
1074
+
1075
+ /** One Field a person asked for, in the store's own behaviour words (FLD-1). */
1076
+ interface NewFieldSpec {
1077
+ key: string;
1078
+ label: string;
1079
+ /** A parity type — the thirteen come from the store, see `PARITY_FIELD_TYPES`. */
1080
+ type: string;
1081
+ sort?: number;
1082
+ required?: boolean;
1083
+ multi?: boolean;
1084
+ config?: Record<string, unknown>;
1085
+ }
1086
+ interface NewTableSpec {
1087
+ name: string;
1088
+ /** The token the Table is addressed by. Derived from the name when absent. */
1089
+ slug?: string;
1090
+ labelSingular?: string;
1091
+ labelPlural?: string;
1092
+ /** The Field whose value is the record's title (REC-2). Defaults to the first Field. */
1093
+ titleField?: string;
1094
+ fields?: NewFieldSpec[];
1095
+ }
1096
+ type DeclareResult = {
1097
+ ok: true;
1098
+ data: Uuid$1;
1099
+ } | {
1100
+ ok: false;
1101
+ error: RecordsError;
1102
+ };
1103
+ /** `My Sales Pipeline` → `my_sales_pipeline`. A token, never a sentence. */
1104
+ declare function tokenFor(name: string): string;
1105
+ /** The one Field a Table cannot be declared without: something to call a record. */
1106
+ declare const DEFAULT_FIELDS: NewFieldSpec[];
1107
+ declare function declareTable(client: RecordsClient, spec: NewTableSpec): Promise<DeclareResult>;
1108
+ /** Write Field records for an existing Table. Used by the create path and by import. */
1109
+ declare function addFields(client: RecordsClient, tableId: Uuid$1, fields: NewFieldSpec[]): Promise<{
1110
+ ok: true;
1111
+ data: Uuid$1;
1112
+ } | {
1113
+ ok: false;
1114
+ error: RecordsError;
1115
+ }>;
1116
+
1117
+ export { ACTION_KINDS, ACTION_TABLE, ActionInbox, type ActionInboxProps, type ActionKind, BookingSlots, type BookingSlotsProps, CAPTURE_MODES, CHART_KINDS, CHART_KIND_LABEL, CHART_NEEDS, CHECKLIST_TABLE, COMMENT_TABLE, type CaptureMode, type CaptureQueuePort, CaptureSheet, type CaptureSheetProps, ChartBlock, type ChartBlockProps, type ChartKind, type ChartSpec, ChecklistRunner, type ChecklistRunnerProps, type ChecklistSpec, type ChecklistStepSpec, CommentThread, type CommentThreadProps, CustomFieldsSection, type CustomFieldsSectionProps, DASHBOARD_TABLE, DEFAULT_FIELDS, DashboardCanvas, type DashboardCanvasProps, type DashboardSpec, type DeclareResult, DocRender, type DocRenderProps, DocTemplate, type DocTemplateProps, type DocTemplateSpec, type EditorKind, EmbedFrame, type EmbedFrameProps, type EnrichAsk, type EnrichOutcome, EnrichPanel, type EnrichPanelProps, ExportMenu, type ExportMenuProps, FORM_FLOWS, FORM_TABLE, FieldControl, FieldEditor, type FieldEditorControlProps, type FieldEditorProps, FieldLabel, type FieldProposalRow, FormBuilder, type FormBuilderProps, type FormFlow, type FormQuestionSpec, FormRunner, type FormRunnerProps, type FormSpec, type FormTheme, Grid, type GridProps, HistoryPanel, type HistoryPanelProps, IN_MEMORY_QUEUE_REASON, ImportWizard, type ImportWizardProps, KERNEL_REASON, LANE_EMPTY, LANE_TITLE, LAYOUT_LABEL, LAYOUT_NEEDS, NO_CHAT_REASON, NO_ENRICH_REASON, NO_RIGHTS, NO_SAVED_VIEWS_REASON, NO_UPLOAD_REASON, type NewFieldSpec, type NewTableSpec, NotifyRuleEditor, type NotifyRuleEditorProps, type NotifyRuleSpec, PARITY_LABEL, PARITY_MADE_OF, Peek, type PeekProps, type PendingCapture, PortalShell, type PortalShellProps, type ProposalOutcome, ProposalRow, type ProposalRowProps, type ProposedChange, ProvenanceBadge, PublicViewPage, type PublicViewPageProps, type QueuedAction, type QueuedActionSpec, RecordChat, type RecordChatContext, type RecordChatEntry, type RecordChatProps, type RecordChatWithheld, RecordChip, RecordForm, type RecordFormProps, RecordsMount, type RecordsMountProps, type RecordsUiHost, RecordsUiProvider, RefusalLine, RefusalNotice, RelationPicker, type RelationPickerProps, SERIES_COLORS, STORE_DECIDES_REASON, type SavedDashboard, type SavedForm, type SavedView, type SavedViewSpec, SignBlock, type SignBlockProps, type SystemFieldSpec, type SystemTableSpec, TABLE_LANES, type TableLane, TablePage, type TablePageProps, type TableRights, TableSettings, type TableSettingsProps, TablesHome, type TablesHomeProps, type UseSystemTableState, VIEW_LAYOUTS, VIEW_TABLE, ViewBar, type ViewBarProps, type ViewLayout, type ViewSort, ViewSwitcher, type ViewSwitcherProps, actionDocument, addFields, bodyForReading, bodyFromKeys, columnForField, dashboardDocument, dashboardFromRecord, declareTable, editorKindFor, ensureSystemTable, envelopeFor, fieldToken, fieldTypeLabel, formDocument, formFromRecord, groupLabel, isSignatureField, laneFor, personActor, recordsDataSource, renderValue, scalarText, storeDecidesRights, submissionStamp, tokenFor, useEmbedHandshake, useRecordsUi, useSystemTable, useTableRights, useViewRecords, viewDocument, viewFromRecord };