@nivaro/react 0.1.66 → 0.1.68
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 +1334 -122
- package/dist/index.js +38240 -37960
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { CascadeFilterRule } from '@nivaro/sdk';
|
|
2
2
|
import { default as default_2 } from 'react';
|
|
3
3
|
import { FieldDependencyConfig } from '@nivaro/sdk';
|
|
4
|
-
import
|
|
4
|
+
import { ImportParseResponse } from '@nivaro/sdk';
|
|
5
|
+
import { ImportTemplateSummary } from '@nivaro/sdk';
|
|
5
6
|
import { JSX } from 'react';
|
|
6
7
|
import { JSXElementConstructor } from 'react';
|
|
7
8
|
import { NivaroClient } from '@nivaro/sdk';
|
|
@@ -15,6 +16,56 @@ import { ReportQueryWidgetConfig } from '@nivaro/sdk';
|
|
|
15
16
|
import { UseMutationResult } from '@tanstack/react-query';
|
|
16
17
|
import { UserScopesInfo } from '@nivaro/sdk';
|
|
17
18
|
|
|
19
|
+
export declare function AccessDeniedPanel({ collection, itemId, onBack }: {
|
|
20
|
+
collection: string;
|
|
21
|
+
itemId: string;
|
|
22
|
+
/** Host-provided back action (e.g. navigate(-1)); renders a button when set. */
|
|
23
|
+
onBack?: () => void;
|
|
24
|
+
}): JSX.Element;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Options filter for every nivaro_users picker: mirrors listUsers() — redacted
|
|
28
|
+
* accounts never appear, and suspended users cannot be PICKED (existing values
|
|
29
|
+
* still display, since current-value lookups fetch by id with no filter).
|
|
30
|
+
* Null-safe on status so a fresh install with unset statuses keeps working.
|
|
31
|
+
*/
|
|
32
|
+
export declare const ACTIVE_USER_OPTION_FILTER: {
|
|
33
|
+
_and: ({
|
|
34
|
+
is_redacted: {
|
|
35
|
+
_eq: boolean;
|
|
36
|
+
};
|
|
37
|
+
_or?: undefined;
|
|
38
|
+
} | {
|
|
39
|
+
_or: ({
|
|
40
|
+
status: {
|
|
41
|
+
_neq: string;
|
|
42
|
+
_null?: undefined;
|
|
43
|
+
};
|
|
44
|
+
} | {
|
|
45
|
+
status: {
|
|
46
|
+
_null: boolean;
|
|
47
|
+
_neq?: undefined;
|
|
48
|
+
};
|
|
49
|
+
})[];
|
|
50
|
+
is_redacted?: undefined;
|
|
51
|
+
})[];
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export declare function AddendumPanel({ collection, item, addendumLayoutId, canCreate, onActiveCountChange, onApplied, defaultExpanded, }: {
|
|
55
|
+
collection: string;
|
|
56
|
+
item: string;
|
|
57
|
+
addendumLayoutId?: number | null;
|
|
58
|
+
canCreate?: boolean;
|
|
59
|
+
onActiveCountChange?: (count: number) => void;
|
|
60
|
+
/** Fired after an addendum is approved/rejected/submitted — i.e. whenever the
|
|
61
|
+
* parent record may now read differently. ItemEditForm uses it to refresh a
|
|
62
|
+
* generated PDF so the attached document matches the amended record. */
|
|
63
|
+
onApplied?: () => void;
|
|
64
|
+
defaultExpanded?: boolean;
|
|
65
|
+
}): JSX.Element | null;
|
|
66
|
+
|
|
67
|
+
export declare function agingBucket(hours: number | null): string;
|
|
68
|
+
|
|
18
69
|
export declare function AlertManagerView({ defaultTab, hiddenTabs, onOpenReport, className }: AlertManagerViewProps): JSX.Element;
|
|
19
70
|
|
|
20
71
|
export declare interface AlertManagerViewProps {
|
|
@@ -27,6 +78,91 @@ export declare interface AlertManagerViewProps {
|
|
|
27
78
|
className?: string;
|
|
28
79
|
}
|
|
29
80
|
|
|
81
|
+
declare type AlertOperator = 'gt' | 'gte' | 'lt' | 'lte' | 'eq' | 'change_pct';
|
|
82
|
+
|
|
83
|
+
export declare function AlertRuleDrawer({ open, definitions, editRule, preselectedDefinitionId, scopeSeeds, onClose, onSave, saving }: {
|
|
84
|
+
open: boolean;
|
|
85
|
+
definitions: MetricDefinition[];
|
|
86
|
+
editRule: MetricAlertRule | null;
|
|
87
|
+
preselectedDefinitionId?: number | null;
|
|
88
|
+
/** Pre-seeded filter values (e.g. from the user's scope restrictions), keyed by filter key. */
|
|
89
|
+
scopeSeeds?: Record<string, Array<string | number>>;
|
|
90
|
+
onClose: () => void;
|
|
91
|
+
onSave: (values: Record<string, unknown>) => void;
|
|
92
|
+
saving: boolean;
|
|
93
|
+
}): JSX.Element;
|
|
94
|
+
|
|
95
|
+
declare type AlertUnit = 'percent' | 'dollar' | 'count' | 'days';
|
|
96
|
+
|
|
97
|
+
declare type AllocateDrawerConfig = {
|
|
98
|
+
/** Option collection browsed in the drawer (e.g. workflow_line_items). */
|
|
99
|
+
collection: string;
|
|
100
|
+
/** Grid FK column that receives the picked option's id. */
|
|
101
|
+
target_field: string;
|
|
102
|
+
/** Grid column that receives the entered amount. */
|
|
103
|
+
value_field: string;
|
|
104
|
+
title?: string;
|
|
105
|
+
value_label?: string;
|
|
106
|
+
/** Option filter — same '$parent.<field>' token semantics as option_filter. */
|
|
107
|
+
filter?: Record<string, unknown>;
|
|
108
|
+
/** Display columns over the option rows: dotted paths resolve via nested
|
|
109
|
+
* field expansion; formula entries compute from the option row's values. */
|
|
110
|
+
columns?: Array<string | {
|
|
111
|
+
path?: string;
|
|
112
|
+
label?: string;
|
|
113
|
+
format?: string;
|
|
114
|
+
formula?: string;
|
|
115
|
+
width?: number;
|
|
116
|
+
}>;
|
|
117
|
+
/** Group option rows under collapsible headers by this (dotted) path —
|
|
118
|
+
* EFP grouped allocation lines by workflow. Groups start collapsed;
|
|
119
|
+
* groups containing an existing allocation start expanded. */
|
|
120
|
+
group_by?: string;
|
|
121
|
+
/** Per-row allocation ceiling formula (same tokens as column formulas incl.
|
|
122
|
+
* {{__saved__}} = this row's saved amount): inputs clamp to it on commit
|
|
123
|
+
* and show invalid state while exceeding it. */
|
|
124
|
+
value_max?: string;
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
declare interface AnomalyDefinition {
|
|
128
|
+
id: number;
|
|
129
|
+
key: string;
|
|
130
|
+
name: string;
|
|
131
|
+
description: string | null;
|
|
132
|
+
category: string;
|
|
133
|
+
status: string;
|
|
134
|
+
scope_options: FilterOptionSpec[] | null;
|
|
135
|
+
sensitivity_hints: Record<string, string> | null;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
declare interface AnomalyRule {
|
|
139
|
+
id: number;
|
|
140
|
+
name: string;
|
|
141
|
+
definition_id: number;
|
|
142
|
+
sensitivity: 'low' | 'medium' | 'high' | string;
|
|
143
|
+
scopes: Record<string, Array<string | number>> | null;
|
|
144
|
+
check_frequency: 'daily' | 'weekly' | string;
|
|
145
|
+
delivery_in_app: boolean;
|
|
146
|
+
delivery_email: boolean;
|
|
147
|
+
status: string;
|
|
148
|
+
created_by: string | null;
|
|
149
|
+
definition?: {
|
|
150
|
+
id: number;
|
|
151
|
+
key: string;
|
|
152
|
+
name: string;
|
|
153
|
+
description: string | null;
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export declare function AnomalyRuleDrawer({ open, definitions, editRule, onClose, onSave, saving }: {
|
|
158
|
+
open: boolean;
|
|
159
|
+
definitions: AnomalyDefinition[];
|
|
160
|
+
editRule: AnomalyRule | null;
|
|
161
|
+
onClose: () => void;
|
|
162
|
+
onSave: (values: Record<string, unknown>) => void;
|
|
163
|
+
saving: boolean;
|
|
164
|
+
}): JSX.Element;
|
|
165
|
+
|
|
30
166
|
/**
|
|
31
167
|
* "The API was redeployed since you loaded this page" bar.
|
|
32
168
|
*
|
|
@@ -58,18 +194,72 @@ export declare interface ApiVersionInfo {
|
|
|
58
194
|
environment?: string;
|
|
59
195
|
}
|
|
60
196
|
|
|
197
|
+
/** Evaluate one field validation rule against a value. Returns an error message
|
|
198
|
+
* or null. Shared by useNivaroForm (headless) and ItemEditForm (admin). */
|
|
199
|
+
export declare function applyValidationRule(rule: FormValidationRule_2, value: unknown, label: string): string | null;
|
|
200
|
+
|
|
201
|
+
declare type AutoAllocateConfig = {
|
|
202
|
+
/** Button label; defaults to 'Auto allocate'. */
|
|
203
|
+
label?: string;
|
|
204
|
+
/** drawer_relations entry (by field name) whose `match` supplies the
|
|
205
|
+
* existing-allocation query + create defaults for this grid's rows. */
|
|
206
|
+
relation: string;
|
|
207
|
+
/** Grid row column holding the required quantity. */
|
|
208
|
+
row_qty_field: string;
|
|
209
|
+
/** Quantity column on the allocation rows. */
|
|
210
|
+
alloc_qty_field: string;
|
|
211
|
+
/** FK column on allocation rows pointing at a candidate record. */
|
|
212
|
+
fk_field: string;
|
|
213
|
+
candidates: {
|
|
214
|
+
collection: string;
|
|
215
|
+
/** Same '$parent.*' / '$row.*' token semantics as matched drawer filters. */
|
|
216
|
+
filters: Record<string, unknown>;
|
|
217
|
+
/** Server sort, e.g. 'date' for FIFO. */
|
|
218
|
+
sort?: string;
|
|
219
|
+
/** Gross capacity per candidate row, e.g. '0 - {{quantity}}'. */
|
|
220
|
+
capacity_formula: string;
|
|
221
|
+
/** Candidates with net capacity below this are skipped (default 1). */
|
|
222
|
+
min_capacity?: number;
|
|
223
|
+
};
|
|
224
|
+
};
|
|
225
|
+
|
|
61
226
|
declare type BinaryOp = '+' | '-' | '*' | '/' | '==' | '!=' | '<' | '<=' | '>' | '>=' | '&&' | '||';
|
|
62
227
|
|
|
63
228
|
export declare function BooleanField({ field, value, onChange, error, disabled, readOnly, inputId, errorId }: FieldComponentProps): JSX.Element;
|
|
64
229
|
|
|
230
|
+
export declare function buildGroups<T extends QueueGroupingRow>(rows: T[], attribute: string): QueueGroup<T>[];
|
|
231
|
+
|
|
65
232
|
export declare function canOpenChatRoom(): boolean;
|
|
66
233
|
|
|
67
234
|
export declare function canOpenDm(): boolean;
|
|
68
235
|
|
|
69
236
|
export declare function canPreviewFile(type: string | null | undefined): boolean;
|
|
70
237
|
|
|
238
|
+
/**
|
|
239
|
+
* Grab the replay link for an error being reported right now. Resolves null
|
|
240
|
+
* when no recorder is active (both settings off, recording failed, or the
|
|
241
|
+
* clip upload took longer than 4s) — error reporting must never wait on or
|
|
242
|
+
* break because of replay capture.
|
|
243
|
+
*/
|
|
244
|
+
export declare function captureErrorClip(): Promise<ErrorReplayLink | null>;
|
|
245
|
+
|
|
71
246
|
export { CascadeFilterRule }
|
|
72
247
|
|
|
248
|
+
declare type CascadeRule = {
|
|
249
|
+
parent_field: string;
|
|
250
|
+
child_field: string;
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
export declare function CellCopyLayer(): ReactPortal | null;
|
|
254
|
+
|
|
255
|
+
declare interface ChannelMember {
|
|
256
|
+
user: string;
|
|
257
|
+
first_name: string | null;
|
|
258
|
+
last_name: string | null;
|
|
259
|
+
email: string | null;
|
|
260
|
+
joined_at: string;
|
|
261
|
+
}
|
|
262
|
+
|
|
73
263
|
declare interface ChannelMeta {
|
|
74
264
|
id: number;
|
|
75
265
|
visibility: 'open' | 'role' | 'private';
|
|
@@ -81,6 +271,26 @@ declare interface ChannelMeta {
|
|
|
81
271
|
|
|
82
272
|
export declare function chatAvatarColor(id: string): string;
|
|
83
273
|
|
|
274
|
+
/**
|
|
275
|
+
* Browse and join channels. The sidebar only lists rooms you belong to, so at
|
|
276
|
+
* hundreds of channels this is how you find the rest — the old list rendered
|
|
277
|
+
* every room anyone had ever posted in.
|
|
278
|
+
*/
|
|
279
|
+
export declare function ChatChannelBrowser({ onOpen }: {
|
|
280
|
+
onOpen: (room: string, label: string, channel: ChannelMeta) => void;
|
|
281
|
+
}): JSX.Element;
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Channel settings. Owner or admin edits name/topic/visibility, manages members
|
|
285
|
+
* and archives; everyone else gets the read-only summary, so a member can still
|
|
286
|
+
* see what kind of room they are in and who else is here.
|
|
287
|
+
*/
|
|
288
|
+
export declare function ChatChannelSettings({ channel, label, onBack }: {
|
|
289
|
+
channel: ChannelMeta;
|
|
290
|
+
label: string;
|
|
291
|
+
onBack: () => void;
|
|
292
|
+
}): JSX.Element;
|
|
293
|
+
|
|
84
294
|
export declare interface ChatConfig {
|
|
85
295
|
collections: {
|
|
86
296
|
messages: string;
|
|
@@ -174,7 +384,7 @@ export declare function ChatPanel({ open, onClose, renderMessageBody, requestedD
|
|
|
174
384
|
|
|
175
385
|
export declare function ChatProvider({ children, me, onlineUsers, collections, globalRoom, globalLabel, entityPattern, entityUrl, roomLabel, recordUrl, sessionUrl, realtime, subscribeRooms, setTypingRoom, navigate, sound, theme }: ChatProviderProps): JSX.Element;
|
|
176
386
|
|
|
177
|
-
declare interface ChatProviderProps {
|
|
387
|
+
export declare interface ChatProviderProps {
|
|
178
388
|
children: React.ReactNode;
|
|
179
389
|
me: ChatConfig['me'];
|
|
180
390
|
onlineUsers?: ChatOnlineUser[];
|
|
@@ -239,6 +449,15 @@ export declare function ChatRoomView({ room, label, onBack, onOpenSettings, rend
|
|
|
239
449
|
initialUnread?: number;
|
|
240
450
|
}): JSX.Element;
|
|
241
451
|
|
|
452
|
+
declare interface ChatSearchHit {
|
|
453
|
+
id: number;
|
|
454
|
+
room: string;
|
|
455
|
+
sender: string | null;
|
|
456
|
+
sender_name: string | null;
|
|
457
|
+
message: string;
|
|
458
|
+
date_created: string;
|
|
459
|
+
}
|
|
460
|
+
|
|
242
461
|
/**
|
|
243
462
|
* Nivaro chat UI — a complete team panel (Online tab, grouped rooms, live
|
|
244
463
|
* conversations with mentions, typing, receipts, search).
|
|
@@ -269,9 +488,80 @@ export declare interface ChatTheme {
|
|
|
269
488
|
divider: string;
|
|
270
489
|
}
|
|
271
490
|
|
|
491
|
+
declare type CheckFrequency = 'hourly' | 'daily' | 'weekly';
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* Select-choice display text. Legacy Directus schema imports store choice
|
|
495
|
+
* labels as i18n keys ('$t:published') that Directus resolved through its own
|
|
496
|
+
* translation bundle — Nivaro has no such bundle, so the raw key leaked into
|
|
497
|
+
* dropdowns and read views. Strip the marker and humanize; plain labels pass
|
|
498
|
+
* through untouched.
|
|
499
|
+
*/
|
|
500
|
+
export declare function choiceLabel(text: string | null | undefined): string;
|
|
501
|
+
|
|
272
502
|
/** Clear the schema cache (e.g. after a schema change). */
|
|
273
503
|
export declare function clearFormSchemaCache(collection?: string): void;
|
|
274
504
|
|
|
505
|
+
declare interface ClientAction {
|
|
506
|
+
type: 'open-sidebar';
|
|
507
|
+
collection: string;
|
|
508
|
+
itemId: string;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
export declare function CloneDialog({ collection, itemId, fields, relations, currentValues, onSuccess }: CloneDialogProps): JSX.Element;
|
|
512
|
+
|
|
513
|
+
declare interface CloneDialogProps {
|
|
514
|
+
collection: string;
|
|
515
|
+
itemId: string;
|
|
516
|
+
fields: CMSField[];
|
|
517
|
+
relations: CMSRelation[];
|
|
518
|
+
currentValues: Record<string, unknown>;
|
|
519
|
+
onSuccess: (newId: string | number) => void;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
declare interface CMSField {
|
|
523
|
+
field: string;
|
|
524
|
+
type: string;
|
|
525
|
+
interface: string | null;
|
|
526
|
+
label: string | null;
|
|
527
|
+
required: boolean;
|
|
528
|
+
hidden: boolean;
|
|
529
|
+
readonly: boolean;
|
|
530
|
+
sort: number;
|
|
531
|
+
group_key: string | null;
|
|
532
|
+
options: Record<string, unknown> | string | null;
|
|
533
|
+
computed_formula: string | null;
|
|
534
|
+
computed_type: string | null;
|
|
535
|
+
note: string | null;
|
|
536
|
+
placeholder: string | null;
|
|
537
|
+
repeater_schema: Record<string, unknown>[] | string | null;
|
|
538
|
+
dependency_config: Record<string, unknown> | string | null;
|
|
539
|
+
/** {source_collection, source_fk_field?, field_map:{target:source}} — live copy from a related record when the FK changes. */
|
|
540
|
+
cross_record_defaults?: Record<string, unknown> | string | null;
|
|
541
|
+
validation_rules?: Array<{
|
|
542
|
+
type: string;
|
|
543
|
+
value?: unknown;
|
|
544
|
+
message?: string;
|
|
545
|
+
soft?: boolean;
|
|
546
|
+
}> | string | null;
|
|
547
|
+
layout_assigned?: boolean;
|
|
548
|
+
/** Raw layout-assignment overrides (label, readonly, drilldown, ...) — passed through by field-config. */
|
|
549
|
+
_overrides?: Record<string, unknown> | null;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
declare interface CMSRelation {
|
|
553
|
+
id: number;
|
|
554
|
+
one_collection: string | null;
|
|
555
|
+
one_field: string | null;
|
|
556
|
+
many_collection: string | null;
|
|
557
|
+
many_field: string | null;
|
|
558
|
+
junction_field: string | null;
|
|
559
|
+
/** M2A only — the junction column naming which collection each row's `item` id
|
|
560
|
+
* belongs to (usually 'collection'); one_collection is null on those rows. */
|
|
561
|
+
one_collection_field?: string | null;
|
|
562
|
+
one_allowed_collections?: string | null;
|
|
563
|
+
}
|
|
564
|
+
|
|
275
565
|
/** @deprecated Column model changed to plain field keys — kept for source
|
|
276
566
|
* compatibility with early adopters; maps `path` to a field key. */
|
|
277
567
|
export declare interface CollectionBrowserColumn {
|
|
@@ -317,7 +607,7 @@ export declare function CollectionImportPanel({ initialJobId, onJobOpen }: {
|
|
|
317
607
|
onJobOpen?: (id: string | null) => void;
|
|
318
608
|
}): JSX.Element;
|
|
319
609
|
|
|
320
|
-
declare interface Column<T = Record<string, unknown>> {
|
|
610
|
+
export declare interface Column<T = Record<string, unknown>> {
|
|
321
611
|
key: string;
|
|
322
612
|
header: React_2.ReactNode;
|
|
323
613
|
sortable?: boolean;
|
|
@@ -326,7 +616,7 @@ declare interface Column<T = Record<string, unknown>> {
|
|
|
326
616
|
render?: (row: T, index: number) => React_2.ReactNode;
|
|
327
617
|
}
|
|
328
618
|
|
|
329
|
-
declare type ColumnFormatConfig = {
|
|
619
|
+
export declare type ColumnFormatConfig = {
|
|
330
620
|
type: 'datetime';
|
|
331
621
|
template: string;
|
|
332
622
|
} | {
|
|
@@ -341,6 +631,11 @@ declare type ColumnFormatConfig = {
|
|
|
341
631
|
false_label: string;
|
|
342
632
|
};
|
|
343
633
|
|
|
634
|
+
declare interface ColumnPreset {
|
|
635
|
+
name: string;
|
|
636
|
+
columns: string[];
|
|
637
|
+
}
|
|
638
|
+
|
|
344
639
|
export declare function CommentPanel({ collection, item, title, defaultExpanded, queuedComments, onQueueComment }: {
|
|
345
640
|
collection: string;
|
|
346
641
|
item: string | number;
|
|
@@ -374,7 +669,7 @@ export declare type ComponentOverrides = {
|
|
|
374
669
|
|
|
375
670
|
export declare function DataTable<T = Record<string, unknown>>({ columns, rows, rowKey, total, page, limit, isLoading, isError, errorMessage, sort, onSortChange, onPageChange, onRowClick, searchValue, onSearchChange, searchPlaceholder, filterDefs, filterValues, onFilterChange, toolbarRight, emptyMessage, minBodyHeight, fillHeight, hideFilterRow, nowrapCells, density, pinFirstColumn, columnPins, onColumnPinChange, columnFilterRow, hScrollProxy, selectedIds, onSelectionChange, rowClassName, rowGroups, collapsedGroups, onToggleGroup }: DataTableProps<T>): React_2.JSX.Element;
|
|
376
671
|
|
|
377
|
-
declare interface DataTableProps<T = Record<string, unknown>> {
|
|
672
|
+
export declare interface DataTableProps<T = Record<string, unknown>> {
|
|
378
673
|
columns: Column<T>[];
|
|
379
674
|
rows: T[];
|
|
380
675
|
rowKey?: (row: T, i: number) => string;
|
|
@@ -451,15 +746,37 @@ export declare function DateField({ field, value, onChange, error, disabled, rea
|
|
|
451
746
|
/** The admin's route shape — the default when the host supplies no itemUrl. */
|
|
452
747
|
export declare function defaultItemUrl(t: ItemLinkTarget): string;
|
|
453
748
|
|
|
749
|
+
export declare function deriveGroupKey<T extends QueueGroupingRow>(row: T, attribute: string): string;
|
|
750
|
+
|
|
751
|
+
declare interface DirectoryChannel {
|
|
752
|
+
id: number;
|
|
753
|
+
key: string;
|
|
754
|
+
name: string;
|
|
755
|
+
topic: string | null;
|
|
756
|
+
visibility: 'open' | 'role' | 'private';
|
|
757
|
+
role: string | null;
|
|
758
|
+
joined: boolean;
|
|
759
|
+
members: number;
|
|
760
|
+
}
|
|
761
|
+
|
|
454
762
|
declare type DmOpener = (userId: string, displayName?: string) => void;
|
|
455
763
|
|
|
456
764
|
export declare function dmPeer(room: string, self: string): string | null;
|
|
457
765
|
|
|
458
766
|
export declare function dmRoom(a: string, b: string): string;
|
|
459
767
|
|
|
768
|
+
declare type DrawerRelationConfig = string | {
|
|
769
|
+
field: string;
|
|
770
|
+
hint?: {
|
|
771
|
+
sum_field: string;
|
|
772
|
+
cap_field: string;
|
|
773
|
+
};
|
|
774
|
+
match?: MatchedDrawerConfig;
|
|
775
|
+
};
|
|
776
|
+
|
|
460
777
|
export declare const DrilldownContext: React_2.Context<DrilldownContextValue | null>;
|
|
461
778
|
|
|
462
|
-
declare interface DrilldownContextValue {
|
|
779
|
+
export declare interface DrilldownContextValue {
|
|
463
780
|
open: (target: DrilldownTarget) => void;
|
|
464
781
|
}
|
|
465
782
|
|
|
@@ -482,6 +799,18 @@ export declare function effectiveScopeSeedIds(scopes: {
|
|
|
482
799
|
restricted: Record<string, Array<string | number>>;
|
|
483
800
|
}, dimName: string): Array<string | number>;
|
|
484
801
|
|
|
802
|
+
export declare function ErpFailureBanner({ collection, itemId }: {
|
|
803
|
+
collection: string;
|
|
804
|
+
itemId: string;
|
|
805
|
+
}): JSX.Element | null;
|
|
806
|
+
|
|
807
|
+
export declare interface ErrorReplayLink {
|
|
808
|
+
recording_id: string;
|
|
809
|
+
/** Milliseconds into the recording where the error happened. Null for
|
|
810
|
+
* clips — the whole clip IS the error context. */
|
|
811
|
+
offset_ms: number | null;
|
|
812
|
+
}
|
|
813
|
+
|
|
485
814
|
/** Boolean convenience — for guards and conditions. */
|
|
486
815
|
export declare function evaluateBoolean(src: string, row: TokenResolver | Record<string, unknown>, opts?: EvaluateOptions): boolean;
|
|
487
816
|
|
|
@@ -491,7 +820,7 @@ export declare function evaluateExpression(src: string, resolve: TokenResolver |
|
|
|
491
820
|
/** Numeric convenience — the shape every existing call site wants. */
|
|
492
821
|
export declare function evaluateNumeric(src: string, row: TokenResolver | Record<string, unknown>, opts?: EvaluateOptions): number | null;
|
|
493
822
|
|
|
494
|
-
declare interface EvaluateOptions {
|
|
823
|
+
export declare interface EvaluateOptions {
|
|
495
824
|
/**
|
|
496
825
|
* What an unresolvable or non-numeric token means in arithmetic.
|
|
497
826
|
* 'zero' (default) matches every existing dialect. 'null' propagates, so a
|
|
@@ -500,7 +829,7 @@ declare interface EvaluateOptions {
|
|
|
500
829
|
missing?: 'zero' | 'null';
|
|
501
830
|
}
|
|
502
831
|
|
|
503
|
-
declare type ExprNode = {
|
|
832
|
+
export declare type ExprNode = {
|
|
504
833
|
kind: 'number';
|
|
505
834
|
value: number;
|
|
506
835
|
} | {
|
|
@@ -561,6 +890,18 @@ declare type ExprNode = {
|
|
|
561
890
|
*/
|
|
562
891
|
export declare type ExprValue = number | string | boolean | null;
|
|
563
892
|
|
|
893
|
+
/**
|
|
894
|
+
* Item-header chip summarizing every external (ERP) request this record has
|
|
895
|
+
* sent — badge counts by outcome, click for the full request/response log.
|
|
896
|
+
* Renders nothing when the record has no submissions. Shares the
|
|
897
|
+
* ['erp-submissions', collection, item] cache with ErpFailureBanner, so
|
|
898
|
+
* transition writebacks refresh both.
|
|
899
|
+
*/
|
|
900
|
+
export declare function ExternalRequestsChip({ collection, itemId }: {
|
|
901
|
+
collection: string;
|
|
902
|
+
itemId: string;
|
|
903
|
+
}): JSX.Element | null;
|
|
904
|
+
|
|
564
905
|
/** Field paths an expression reads, without evaluating it. */
|
|
565
906
|
export declare function extractExpressionTokens(src: string): string[];
|
|
566
907
|
|
|
@@ -596,6 +937,31 @@ export declare type FieldComponentProps = {
|
|
|
596
937
|
|
|
597
938
|
export { FieldDependencyConfig }
|
|
598
939
|
|
|
940
|
+
export declare interface FieldDrilldownConfig {
|
|
941
|
+
enabled?: boolean;
|
|
942
|
+
layout_id?: number | null;
|
|
943
|
+
width?: number | string | null;
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
export declare function fieldDrilldownConfig(field: {
|
|
947
|
+
interface?: string | null;
|
|
948
|
+
_overrides?: Record<string, unknown> | null;
|
|
949
|
+
}): FieldDrilldownConfig | null;
|
|
950
|
+
|
|
951
|
+
export declare function FieldRenderer({ field, value, onChange, relations, collection, itemId, cascadeFilter, requiredParentLabel, onCountChange, displayOnly, prefillParentId }: {
|
|
952
|
+
field: CMSField;
|
|
953
|
+
value: unknown;
|
|
954
|
+
onChange: (v: unknown) => void;
|
|
955
|
+
relations: CMSRelation[];
|
|
956
|
+
collection: string;
|
|
957
|
+
itemId: string;
|
|
958
|
+
cascadeFilter?: Record<string, unknown>;
|
|
959
|
+
requiredParentLabel?: string | null;
|
|
960
|
+
onCountChange?: (count: number) => void;
|
|
961
|
+
displayOnly?: boolean;
|
|
962
|
+
prefillParentId?: string;
|
|
963
|
+
}): JSX.Element;
|
|
964
|
+
|
|
599
965
|
export declare type FieldState = {
|
|
600
966
|
value: unknown;
|
|
601
967
|
error: string[] | undefined;
|
|
@@ -621,7 +987,14 @@ export declare function FilePreviewLightbox({ file, onClose }: {
|
|
|
621
987
|
onClose: () => void;
|
|
622
988
|
}): ReactPortal;
|
|
623
989
|
|
|
624
|
-
declare
|
|
990
|
+
export declare function FilterControl({ def, value, onChange, layout }: {
|
|
991
|
+
def: FilterDef;
|
|
992
|
+
value: string | string[];
|
|
993
|
+
onChange: (value: string | string[]) => void;
|
|
994
|
+
layout?: 'inline' | 'stacked' | 'cell';
|
|
995
|
+
}): React_2.JSX.Element;
|
|
996
|
+
|
|
997
|
+
export declare interface FilterDef {
|
|
625
998
|
key: string;
|
|
626
999
|
placeholder: string;
|
|
627
1000
|
/** Defaults to 'select' — every existing FilterDef without this field keeps its current dropdown behavior unchanged. */
|
|
@@ -643,6 +1016,35 @@ declare interface FilterDef {
|
|
|
643
1016
|
restricted?: boolean;
|
|
644
1017
|
}
|
|
645
1018
|
|
|
1019
|
+
export declare function filterDefLabel(def: FilterDef): string;
|
|
1020
|
+
|
|
1021
|
+
declare interface FilterOptionSpec {
|
|
1022
|
+
key: string;
|
|
1023
|
+
label?: string;
|
|
1024
|
+
collection?: string;
|
|
1025
|
+
value_field?: string;
|
|
1026
|
+
label_field?: string;
|
|
1027
|
+
sort?: string;
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
/** Human display for an applied filter value — option labels for comboboxes
|
|
1031
|
+
* (ids → names), ≥/≤ for ranges, first two entries + count for multiselects. */
|
|
1032
|
+
export declare function filterValueDisplay(def: FilterDef, value: string | string[]): string;
|
|
1033
|
+
|
|
1034
|
+
export declare function formatDate(date: string | Date, opts?: Intl.DateTimeFormatOptions): string;
|
|
1035
|
+
|
|
1036
|
+
export declare function formatDateTime(date: string | Date): string;
|
|
1037
|
+
|
|
1038
|
+
export declare function formatFileSize(bytes: number | null | undefined): string;
|
|
1039
|
+
|
|
1040
|
+
export declare function formatMultiValue(raw: string, cfg: ColumnFormatConfig): string;
|
|
1041
|
+
|
|
1042
|
+
export declare function formatNumber(n: number | null | undefined): string;
|
|
1043
|
+
|
|
1044
|
+
export declare function formatRelative(date: string | Date): string;
|
|
1045
|
+
|
|
1046
|
+
export declare function formatValue(raw: string, cfg: ColumnFormatConfig): string;
|
|
1047
|
+
|
|
646
1048
|
export declare type FormDirtyState = {
|
|
647
1049
|
isDirty: boolean;
|
|
648
1050
|
dirtyFields: string[];
|
|
@@ -699,7 +1101,7 @@ export declare type FormFieldType = 'text' | 'textarea' | 'integer' | 'float' |
|
|
|
699
1101
|
export declare type FormGroupDescriptor = {
|
|
700
1102
|
key: string;
|
|
701
1103
|
label: string;
|
|
702
|
-
type: 'section' | 'tab';
|
|
1104
|
+
type: 'section' | 'tab' | 'metadata' | 'container';
|
|
703
1105
|
icon: string | null;
|
|
704
1106
|
sort: number;
|
|
705
1107
|
isCollapsed: boolean;
|
|
@@ -800,6 +1202,13 @@ export declare type FormValidationRule = {
|
|
|
800
1202
|
soft?: boolean;
|
|
801
1203
|
};
|
|
802
1204
|
|
|
1205
|
+
declare type FormValidationRule_2 = {
|
|
1206
|
+
type: string;
|
|
1207
|
+
value?: unknown;
|
|
1208
|
+
message?: string;
|
|
1209
|
+
soft?: boolean;
|
|
1210
|
+
};
|
|
1211
|
+
|
|
803
1212
|
/** A client-evaluable visibility rule. */
|
|
804
1213
|
export declare type FormVisibilityRule = {
|
|
805
1214
|
/** key of the field this rule observes */
|
|
@@ -817,18 +1226,25 @@ export declare function getMentionQuery(text: string, cursorPos: number): string
|
|
|
817
1226
|
|
|
818
1227
|
export declare const GridFlushContext: React_2.Context<GridFlushContextValue | null>;
|
|
819
1228
|
|
|
820
|
-
declare type GridFlushContextValue = {
|
|
1229
|
+
export declare type GridFlushContextValue = {
|
|
821
1230
|
register: (key: string, fn: () => Promise<void>) => void;
|
|
822
1231
|
unregister: (key: string) => void;
|
|
823
1232
|
};
|
|
824
1233
|
|
|
825
|
-
declare interface HeaderWidgetInfo {
|
|
1234
|
+
export declare interface HeaderWidgetInfo {
|
|
826
1235
|
field: string;
|
|
827
1236
|
widgetId: number;
|
|
828
1237
|
label: string | null;
|
|
829
1238
|
inputBindings: InputBinding[];
|
|
830
1239
|
}
|
|
831
1240
|
|
|
1241
|
+
/** Always-visible horizontal scrollbar proxy for the table scroller —
|
|
1242
|
+
* overlay-OS scrollbars hide, so wide tables get a persistent draggable
|
|
1243
|
+
* track pinned above the pagination footer. */
|
|
1244
|
+
export declare function HScrollProxy({ scrollerRef }: {
|
|
1245
|
+
scrollerRef: React_2.RefObject<HTMLDivElement | null>;
|
|
1246
|
+
}): React_2.JSX.Element | null;
|
|
1247
|
+
|
|
832
1248
|
/** Time without real input before someone counts as idle. */
|
|
833
1249
|
export declare const IDLE_AFTER_MS: number;
|
|
834
1250
|
|
|
@@ -878,6 +1294,23 @@ export declare interface ImportDefinition {
|
|
|
878
1294
|
validation?: string | null;
|
|
879
1295
|
}
|
|
880
1296
|
|
|
1297
|
+
export declare function ImportFromFileButton({ collection, templateFilter, getLabel, onParsed, compact }: {
|
|
1298
|
+
collection: string;
|
|
1299
|
+
templateFilter?: (t: ImportTemplateSummary) => boolean;
|
|
1300
|
+
/** Per-template label source; defaults to the template's button_label. */
|
|
1301
|
+
getLabel?: (t: ImportTemplateSummary) => string | null | undefined;
|
|
1302
|
+
onParsed: (result: ImportParseResponse, template: ImportTemplateSummary) => void;
|
|
1303
|
+
/** Grid-toolbar sizing (h-6, 11px) matching other inline-table buttons. */
|
|
1304
|
+
compact?: boolean;
|
|
1305
|
+
}): JSX.Element | null;
|
|
1306
|
+
|
|
1307
|
+
declare type ImportIssue = ImportParseResponse['issues'][number];
|
|
1308
|
+
|
|
1309
|
+
export declare function ImportIssuesPanel({ issues, onDismiss }: {
|
|
1310
|
+
issues: ImportIssue[];
|
|
1311
|
+
onDismiss?: () => void;
|
|
1312
|
+
}): JSX.Element | null;
|
|
1313
|
+
|
|
881
1314
|
export declare interface ImportJob {
|
|
882
1315
|
id: string;
|
|
883
1316
|
collection: string;
|
|
@@ -1006,15 +1439,76 @@ declare interface ImportValidationReport {
|
|
|
1006
1439
|
truncated: boolean;
|
|
1007
1440
|
}
|
|
1008
1441
|
|
|
1442
|
+
export declare function InlineTableField({ relatedCollection, manyField, parentId, parentCollection, layoutId, showRowRevisions, allowRevisionRestore, saveMode, showLineNumbers, enableReorder, parentCascades, rowRules, columnPresets, defaultPreset, drawerRelations, parentContextFields, uniqueBy, sortField, sortDir, sectionGroupBy, rowFilter, rowDefaults, allocateDrawer, autoAllocate, rowBulkActions, uploadTemplate, submissionErrors, prefillParentId, parentFieldKey, readOnly }: {
|
|
1443
|
+
relatedCollection: string;
|
|
1444
|
+
manyField: string;
|
|
1445
|
+
parentId: string;
|
|
1446
|
+
/** Same table display, but no editing: hides the Add toolbar, + Add row,
|
|
1447
|
+
* row delete/undo, and blocks cell edit entry. */
|
|
1448
|
+
readOnly?: boolean;
|
|
1449
|
+
parentCollection?: string;
|
|
1450
|
+
layoutId?: number | null;
|
|
1451
|
+
showRowRevisions?: boolean;
|
|
1452
|
+
allowRevisionRestore?: boolean;
|
|
1453
|
+
saveMode?: 'immediate' | 'pending';
|
|
1454
|
+
showLineNumbers?: boolean;
|
|
1455
|
+
enableReorder?: boolean;
|
|
1456
|
+
parentCascades?: CascadeRule[];
|
|
1457
|
+
rowRules?: RowRule[];
|
|
1458
|
+
columnPresets?: ColumnPreset[];
|
|
1459
|
+
/** Initial view before the user picks one: a preset name or '__all__'. */
|
|
1460
|
+
defaultPreset?: string;
|
|
1461
|
+
drawerRelations?: DrawerRelationConfig[];
|
|
1462
|
+
parentContextFields?: string[];
|
|
1463
|
+
uniqueBy?: string[];
|
|
1464
|
+
sortField?: string;
|
|
1465
|
+
sortDir?: 'asc' | 'desc';
|
|
1466
|
+
/** Dotted relation path on the child collection (e.g. 'item.category.name'):
|
|
1467
|
+
* saved rows render grouped into collapsible sections by the resolved value. */
|
|
1468
|
+
sectionGroupBy?: string;
|
|
1469
|
+
/** Static filter narrowing which child rows this grid shows — flat {col: value}
|
|
1470
|
+
* entries become _eq, object values pass through as filter operators. Lets two
|
|
1471
|
+
* grids on the same relation show disjoint views (e.g. is_osp split). */
|
|
1472
|
+
rowFilter?: Record<string, unknown>;
|
|
1473
|
+
/** Values seeded onto every NEW row created from this grid (e.g. {is_osp: true}). */
|
|
1474
|
+
rowDefaults?: Record<string, unknown>;
|
|
1475
|
+
/** EFP-style allocate drawer: browse all eligible options, type amounts. */
|
|
1476
|
+
allocateDrawer?: AllocateDrawerConfig;
|
|
1477
|
+
autoAllocate?: AutoAllocateConfig;
|
|
1478
|
+
/** Toolbar buttons that rewrite EVERY row in one go from an aggregate of a
|
|
1479
|
+
* related collection — the generic form of EFP's "Close Out Lines" (reduce
|
|
1480
|
+
* each REQ line by the open unbilled amount across its PO lines). */
|
|
1481
|
+
rowBulkActions?: RowBulkActionConfig[];
|
|
1482
|
+
/** Import template NAME — renders that template's upload button in this
|
|
1483
|
+
* grid's toolbar (existing records; wired to ItemEditForm's reimport flow). */
|
|
1484
|
+
uploadTemplate?: string;
|
|
1485
|
+
/** Flag rows a failed ERP push rejected (options.submission_errors) — the
|
|
1486
|
+
* latest failed nivaro_erp_submissions row for the PARENT record is parsed
|
|
1487
|
+
* for "LineNumber N: reason" entries and matching rows tint red with the
|
|
1488
|
+
* reason beneath. `line_field` = the row column holding the pushed line
|
|
1489
|
+
* number (default 'line_number'). Mirrors CatalogPickerField's
|
|
1490
|
+
* submission_errors for catalog grids. */
|
|
1491
|
+
submissionErrors?: {
|
|
1492
|
+
line_field?: string;
|
|
1493
|
+
};
|
|
1494
|
+
prefillParentId?: string;
|
|
1495
|
+
parentFieldKey?: string;
|
|
1496
|
+
}): JSX.Element;
|
|
1497
|
+
|
|
1009
1498
|
declare interface InputBinding {
|
|
1010
1499
|
key: string;
|
|
1011
1500
|
binding_type: 'item_field' | 'static' | 'url_param';
|
|
1012
1501
|
binding_value: string;
|
|
1013
1502
|
}
|
|
1014
1503
|
|
|
1504
|
+
export declare function ItemActionButtons({ collection, itemId }: {
|
|
1505
|
+
collection: string;
|
|
1506
|
+
itemId: string;
|
|
1507
|
+
}): JSX.Element | null;
|
|
1508
|
+
|
|
1015
1509
|
export declare const ItemEditAuthContext: React_2.Context<ItemEditAuthContextValue>;
|
|
1016
1510
|
|
|
1017
|
-
declare type ItemEditAuthContextValue = {
|
|
1511
|
+
export declare type ItemEditAuthContextValue = {
|
|
1018
1512
|
isAdmin: boolean;
|
|
1019
1513
|
userId: string;
|
|
1020
1514
|
};
|
|
@@ -1095,6 +1589,73 @@ export declare function ItemLockBanner({ lockHolder, onTakeOver, takingOver, isA
|
|
|
1095
1589
|
isAdmin?: boolean;
|
|
1096
1590
|
}): JSX.Element | null;
|
|
1097
1591
|
|
|
1592
|
+
export declare function JsonMapEditor({ config, scope }: {
|
|
1593
|
+
config: JsonMapEditorConfig;
|
|
1594
|
+
scope: Record<string, unknown>;
|
|
1595
|
+
}): JSX.Element;
|
|
1596
|
+
|
|
1597
|
+
declare interface JsonMapEditorConfig {
|
|
1598
|
+
collection: string;
|
|
1599
|
+
title?: string;
|
|
1600
|
+
/** Record picker label field (also the required name on create). */
|
|
1601
|
+
label_field?: string;
|
|
1602
|
+
/** Filter for the record picker; '$scope.<field>' tokens resolve from the
|
|
1603
|
+
* host-provided scope. Scope values are also seeded onto created records. */
|
|
1604
|
+
record_filter?: Record<string, unknown>;
|
|
1605
|
+
/** Plain record fields edited beside the picker (small option sets). */
|
|
1606
|
+
fields?: Array<{
|
|
1607
|
+
field: string;
|
|
1608
|
+
label?: string;
|
|
1609
|
+
options: string[];
|
|
1610
|
+
}>;
|
|
1611
|
+
/** JSON-dict columns; each stored under `json_field` on the record. */
|
|
1612
|
+
map_columns: Array<{
|
|
1613
|
+
json_field: string;
|
|
1614
|
+
label: string;
|
|
1615
|
+
min?: number;
|
|
1616
|
+
max?: number;
|
|
1617
|
+
}>;
|
|
1618
|
+
/** Key rows: records of other collections. Template supports one-hop dotted
|
|
1619
|
+
* refs ('{{core_category.name}}'); filter supports '$scope' tokens. */
|
|
1620
|
+
sections: Array<{
|
|
1621
|
+
collection: string;
|
|
1622
|
+
label_template: string;
|
|
1623
|
+
filter?: Record<string, unknown>;
|
|
1624
|
+
section_label?: string;
|
|
1625
|
+
}>;
|
|
1626
|
+
/** Static sentinel keys appended after the sections (bg = row tint). */
|
|
1627
|
+
extra_rows?: Array<{
|
|
1628
|
+
key: string;
|
|
1629
|
+
label: string;
|
|
1630
|
+
bg?: string;
|
|
1631
|
+
}>;
|
|
1632
|
+
/** 'Left to allocate' style hint: shown when record[when_field] ===
|
|
1633
|
+
* when_value; remaining = total − Σ json_field values. */
|
|
1634
|
+
remaining_hint?: {
|
|
1635
|
+
when_field: string;
|
|
1636
|
+
when_value: string;
|
|
1637
|
+
total: number;
|
|
1638
|
+
json_field: string;
|
|
1639
|
+
label?: string;
|
|
1640
|
+
};
|
|
1641
|
+
/** Extra fields seeded onto created records from scope values. */
|
|
1642
|
+
seed_fields?: string[];
|
|
1643
|
+
/** Custom query run after save (recompute hooks); '$scope' tokens. */
|
|
1644
|
+
after_save?: {
|
|
1645
|
+
query_slug: string;
|
|
1646
|
+
params?: Record<string, unknown>;
|
|
1647
|
+
};
|
|
1648
|
+
}
|
|
1649
|
+
|
|
1650
|
+
declare interface LayoutAssignment {
|
|
1651
|
+
field: string;
|
|
1652
|
+
group_key: string | null;
|
|
1653
|
+
sort: number;
|
|
1654
|
+
label_override: string | null;
|
|
1655
|
+
is_visible: boolean | number;
|
|
1656
|
+
overrides?: string | Record<string, unknown> | null;
|
|
1657
|
+
}
|
|
1658
|
+
|
|
1098
1659
|
/**
|
|
1099
1660
|
* Full layout-aware form renderer.
|
|
1100
1661
|
*
|
|
@@ -1153,6 +1714,13 @@ declare type LayoutFormProps = {
|
|
|
1153
1714
|
layoutSlug?: string;
|
|
1154
1715
|
};
|
|
1155
1716
|
|
|
1717
|
+
declare interface LayoutGroup {
|
|
1718
|
+
key: string;
|
|
1719
|
+
label: string;
|
|
1720
|
+
type: string | null;
|
|
1721
|
+
sort: number;
|
|
1722
|
+
}
|
|
1723
|
+
|
|
1156
1724
|
export declare type LayoutItem = FormGroupDescriptor | '__ungrouped__';
|
|
1157
1725
|
|
|
1158
1726
|
declare interface LockHolder {
|
|
@@ -1160,6 +1728,25 @@ declare interface LockHolder {
|
|
|
1160
1728
|
locked_by_name: string | null;
|
|
1161
1729
|
}
|
|
1162
1730
|
|
|
1731
|
+
export declare interface M2MStagingCtx {
|
|
1732
|
+
getStagedLinks: (key: string) => unknown[];
|
|
1733
|
+
getStagedUnlinks: (key: string) => Set<unknown>;
|
|
1734
|
+
stageLink: (key: string, relatedId: unknown) => void;
|
|
1735
|
+
stageUnlink: (key: string, junctionId: unknown) => void;
|
|
1736
|
+
unstageLink: (key: string, relatedId: unknown) => void;
|
|
1737
|
+
unstageUnlink: (key: string, junctionId: unknown) => void;
|
|
1738
|
+
}
|
|
1739
|
+
|
|
1740
|
+
declare type MatchedDrawerConfig = {
|
|
1741
|
+
/** Rows selected by filter instead of an FK to the child row — values may be
|
|
1742
|
+
* '$parent.id', '$parent.<field>', '$row.<field>', or literals; dotted keys
|
|
1743
|
+
* become nested relation filters. Creates are seeded with `defaults`
|
|
1744
|
+
* (same token resolution, plain columns only). */
|
|
1745
|
+
collection: string;
|
|
1746
|
+
filters: Record<string, unknown>;
|
|
1747
|
+
defaults?: Record<string, unknown>;
|
|
1748
|
+
};
|
|
1749
|
+
|
|
1163
1750
|
/** Match a filter surface (by its own key and/or its options collection) to a
|
|
1164
1751
|
* scope dimension. Convention: key === dimension name wins, else the filter's
|
|
1165
1752
|
* options collection === the dimension's target collection. */
|
|
@@ -1168,22 +1755,147 @@ export declare function matchScopeDimension(scopes: UserScopesInfo | null, probe
|
|
|
1168
1755
|
collection?: string;
|
|
1169
1756
|
}): UserScopesInfo['dimensions'][number] | null;
|
|
1170
1757
|
|
|
1758
|
+
export declare function MatrixEditor({ config, initialScope }: {
|
|
1759
|
+
config: MatrixEditorConfig;
|
|
1760
|
+
/** Pre-seed scope pickers (drill-down hosts scope the matrix to a record). */
|
|
1761
|
+
initialScope?: Record<string, unknown>;
|
|
1762
|
+
}): JSX.Element;
|
|
1763
|
+
|
|
1764
|
+
declare interface MatrixEditorConfig {
|
|
1765
|
+
title?: string;
|
|
1766
|
+
target_collection: string;
|
|
1767
|
+
option_collection: string;
|
|
1768
|
+
/** Plain display column (default 'name') — or use option_label_template. */
|
|
1769
|
+
option_label?: string;
|
|
1770
|
+
/** Dotted display template, e.g. '{{core_category.name}} - {{sub_category.name}}'. */
|
|
1771
|
+
option_label_template?: string;
|
|
1772
|
+
/** Filter for the option fetch. '$scope.<field>' tokens resolve from scope. */
|
|
1773
|
+
option_filter?: Record<string, unknown>;
|
|
1774
|
+
key_field: string;
|
|
1775
|
+
value_field: string;
|
|
1776
|
+
value_label?: string;
|
|
1777
|
+
value_format?: 'currency' | 'number';
|
|
1778
|
+
/** Scope pickers. `filter` narrows a picker's options; '$scope.<field>'
|
|
1779
|
+
* tokens resolve from the other scope values (EFP: sub types limited to the
|
|
1780
|
+
* chosen project's linked sub types) — unresolved tokens drop the filter. */
|
|
1781
|
+
scope_fields: Array<{
|
|
1782
|
+
field: string;
|
|
1783
|
+
collection: string;
|
|
1784
|
+
label?: string;
|
|
1785
|
+
filter?: Record<string, unknown>;
|
|
1786
|
+
}>;
|
|
1787
|
+
/** Third level: sub-group options WITHIN a group section by a template over
|
|
1788
|
+
* the option record (EFP region → core category → Labor/Materials/Equipment:
|
|
1789
|
+
* label_template '{{core_category.name}}', row_label_template
|
|
1790
|
+
* '{{sub_category.name}}'). Sub-headers aggregate their children and
|
|
1791
|
+
* collapse independently. */
|
|
1792
|
+
option_section?: {
|
|
1793
|
+
label_template: string;
|
|
1794
|
+
/** Leaf row label; defaults to the full option label. */
|
|
1795
|
+
row_label_template?: string;
|
|
1796
|
+
};
|
|
1797
|
+
/** Second axis: sections per group record; target rows keyed (key, group, scope). */
|
|
1798
|
+
group?: {
|
|
1799
|
+
field: string;
|
|
1800
|
+
collection: string;
|
|
1801
|
+
label_field?: string;
|
|
1802
|
+
filter?: Record<string, unknown>;
|
|
1803
|
+
};
|
|
1804
|
+
/** Extra seeds on created rows, '$<scopeField>.<path>' — path may be dotted
|
|
1805
|
+
* and use [n] (e.g. '$project.funding_years[0].funding_year'). */
|
|
1806
|
+
scope_seeds?: Record<string, string>;
|
|
1807
|
+
/** Auto-fill a scope picker from another scope record when empty, e.g.
|
|
1808
|
+
* {project_sub_type: '$project.default_sub_type'} (EFP default sub type). */
|
|
1809
|
+
scope_defaults?: Record<string, string>;
|
|
1810
|
+
/** Seeds copied from the GROUP record onto rows created in that section,
|
|
1811
|
+
* {targetField: groupField} — e.g. {division: 'division'} (allocation rows
|
|
1812
|
+
* carry the region's division, not one picked from the project). */
|
|
1813
|
+
group_seeds?: Record<string, string>;
|
|
1814
|
+
/** Cap strip: cap value read from a scope record's field; total of all cells
|
|
1815
|
+
* is clamped so it never exceeds the cap (server sum_cap should back this). */
|
|
1816
|
+
cap?: {
|
|
1817
|
+
scope_field: string;
|
|
1818
|
+
field: string;
|
|
1819
|
+
label?: string;
|
|
1820
|
+
};
|
|
1821
|
+
/** Synthetic rows per group for target rows with a NULL key (Uncategorized)
|
|
1822
|
+
* and/or a boolean bucket flag (Inventory: rows with flag true, key null). */
|
|
1823
|
+
specials?: {
|
|
1824
|
+
uncategorized?: {
|
|
1825
|
+
label?: string;
|
|
1826
|
+
metric_value?: number | null;
|
|
1827
|
+
};
|
|
1828
|
+
bucket?: {
|
|
1829
|
+
flag_field: string;
|
|
1830
|
+
label?: string;
|
|
1831
|
+
metric_value?: number | null;
|
|
1832
|
+
};
|
|
1833
|
+
};
|
|
1834
|
+
/** Per-cell read-only metric columns from a custom query. */
|
|
1835
|
+
metrics?: {
|
|
1836
|
+
query_slug: string;
|
|
1837
|
+
params?: Record<string, unknown>;
|
|
1838
|
+
match_option_field: string;
|
|
1839
|
+
match_group_field?: string;
|
|
1840
|
+
columns: Array<{
|
|
1841
|
+
field: string;
|
|
1842
|
+
label?: string;
|
|
1843
|
+
format?: 'currency' | 'number';
|
|
1844
|
+
}>;
|
|
1845
|
+
};
|
|
1846
|
+
}
|
|
1847
|
+
|
|
1171
1848
|
declare interface MessageToken {
|
|
1172
1849
|
text: string;
|
|
1173
1850
|
entity?: string;
|
|
1174
1851
|
mention?: string;
|
|
1175
1852
|
}
|
|
1176
1853
|
|
|
1854
|
+
declare interface MetricAlertRule {
|
|
1855
|
+
id: number;
|
|
1856
|
+
name: string;
|
|
1857
|
+
definition_id: number;
|
|
1858
|
+
operator: string;
|
|
1859
|
+
threshold_value: number;
|
|
1860
|
+
filters: Record<string, Array<string | number>> | null;
|
|
1861
|
+
check_frequency: CheckFrequency | string;
|
|
1862
|
+
is_shared: boolean;
|
|
1863
|
+
status: string;
|
|
1864
|
+
created_by: string | null;
|
|
1865
|
+
created_at: string | null;
|
|
1866
|
+
definition?: {
|
|
1867
|
+
id: number;
|
|
1868
|
+
name: string;
|
|
1869
|
+
description: string | null;
|
|
1870
|
+
category: string;
|
|
1871
|
+
unit: string;
|
|
1872
|
+
};
|
|
1873
|
+
}
|
|
1874
|
+
|
|
1875
|
+
declare interface MetricDefinition {
|
|
1876
|
+
id: number;
|
|
1877
|
+
name: string;
|
|
1878
|
+
description: string | null;
|
|
1879
|
+
metric_key: string;
|
|
1880
|
+
category: string;
|
|
1881
|
+
unit: AlertUnit | string;
|
|
1882
|
+
default_operator: AlertOperator | string;
|
|
1883
|
+
default_threshold: number | null;
|
|
1884
|
+
supported_filters: FilterOptionSpec[] | null;
|
|
1885
|
+
status: string;
|
|
1886
|
+
sort: number | null;
|
|
1887
|
+
}
|
|
1888
|
+
|
|
1177
1889
|
export declare function MyWorkView({ notificationRoutes, onOpenPath }?: {
|
|
1178
1890
|
/** Host page map so notification clicks land on real pages (reports, queues,
|
|
1179
1891
|
* alerts…); without it only record targets are clickable. */
|
|
1180
|
-
notificationRoutes?:
|
|
1892
|
+
notificationRoutes?: NotificationRouteMap;
|
|
1181
1893
|
onOpenPath?: (path: string) => void;
|
|
1182
1894
|
}): JSX.Element;
|
|
1183
1895
|
|
|
1184
1896
|
export declare const NavigationContext: React_2.Context<NavigationContextValue>;
|
|
1185
1897
|
|
|
1186
|
-
declare type NavigationContextValue = {
|
|
1898
|
+
export declare type NavigationContextValue = {
|
|
1187
1899
|
/** `options.state` rides along for hosts whose router supports it (e.g. react-router's
|
|
1188
1900
|
* useNavigate) — hosts that ignore the second argument still navigate correctly. */
|
|
1189
1901
|
navigate: (path: string, options?: {
|
|
@@ -1271,34 +1983,7 @@ export declare function normalizeFieldType(rawType: string, iface: string | null
|
|
|
1271
1983
|
* system collections map to their owning pages, and the pseudo-collection
|
|
1272
1984
|
* `__chat__` carries a chat room key.
|
|
1273
1985
|
*/
|
|
1274
|
-
|
|
1275
1986
|
export declare interface NotificationRouteMap {
|
|
1276
|
-
/** Record route for a business collection — return null when the host has none. */
|
|
1277
|
-
record: (collection: string, item: string) => string | null
|
|
1278
|
-
/** Collection listing (item-less business notifications, e.g. view digests). */
|
|
1279
|
-
list?: (collection: string) => string | null
|
|
1280
|
-
report?: (id: string) => string | null
|
|
1281
|
-
queue?: (id: string) => string | null
|
|
1282
|
-
dashboard?: (id: string) => string | null
|
|
1283
|
-
/** Alert-manager page (metric/anomaly/per-record alert notifications). */
|
|
1284
|
-
alerts?: () => string | null
|
|
1285
|
-
imports?: () => string | null
|
|
1286
|
-
issues?: () => string | null
|
|
1287
|
-
}
|
|
1288
|
-
|
|
1289
|
-
/**
|
|
1290
|
-
* Every in-app notification must land somewhere meaningful — this is the ONE
|
|
1291
|
-
* resolver both bells, the notifications page, and My Work use to decide what
|
|
1292
|
-
* a click does. A row that resolves to null renders as plain text (no hover,
|
|
1293
|
-
* no cursor), which is the honest state for broadcast-style messages; it must
|
|
1294
|
-
* never render as a link that goes nowhere.
|
|
1295
|
-
*
|
|
1296
|
-
* Server writers use `collection` + `item` as the target: business collections
|
|
1297
|
-
* point at records (or the collection list when item is null), a handful of
|
|
1298
|
-
* system collections map to their owning pages, and the pseudo-collection
|
|
1299
|
-
* `__chat__` carries a chat room key.
|
|
1300
|
-
*/
|
|
1301
|
-
declare interface NotificationRouteMap_2 {
|
|
1302
1987
|
/** Record route for a business collection — return null when the host has none. */
|
|
1303
1988
|
record: (collection: string, item: string) => string | null;
|
|
1304
1989
|
/** Collection listing (item-less business notifications, e.g. view digests). */
|
|
@@ -1312,13 +1997,19 @@ declare interface NotificationRouteMap_2 {
|
|
|
1312
1997
|
issues?: () => string | null;
|
|
1313
1998
|
}
|
|
1314
1999
|
|
|
1315
|
-
export declare type NotificationTarget =
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
|
2000
|
+
export declare type NotificationTarget = {
|
|
2001
|
+
type: 'path';
|
|
2002
|
+
path: string;
|
|
2003
|
+
} | {
|
|
2004
|
+
type: 'chat';
|
|
2005
|
+
room: string;
|
|
2006
|
+
} | null;
|
|
1319
2007
|
|
|
1320
2008
|
export declare function NumberField({ field, value, onChange, error, disabled, readOnly, inputId, errorId }: FieldComponentProps): JSX.Element;
|
|
1321
2009
|
|
|
2010
|
+
/** Intl options for a numeric field, honoring its configured precision. */
|
|
2011
|
+
export declare function numericIntlOptions(options: unknown, format?: string): Intl.NumberFormatOptions;
|
|
2012
|
+
|
|
1322
2013
|
declare interface O2MFieldInfo {
|
|
1323
2014
|
field: string;
|
|
1324
2015
|
label: string;
|
|
@@ -1375,6 +2066,13 @@ declare interface OwnerLike {
|
|
|
1375
2066
|
name: string;
|
|
1376
2067
|
}
|
|
1377
2068
|
|
|
2069
|
+
export declare function OwnersSlot({ collection, item, title, defaultExpanded }: {
|
|
2070
|
+
collection: string;
|
|
2071
|
+
item: string;
|
|
2072
|
+
title?: string;
|
|
2073
|
+
defaultExpanded?: boolean;
|
|
2074
|
+
}): JSX.Element | null;
|
|
2075
|
+
|
|
1378
2076
|
export declare function PageRenderer({ slug, hideHeader, className }: PageRendererProps): JSX.Element;
|
|
1379
2077
|
|
|
1380
2078
|
export declare interface PageRendererPage {
|
|
@@ -1413,7 +2111,7 @@ declare interface ParseFailure {
|
|
|
1413
2111
|
position: number;
|
|
1414
2112
|
}
|
|
1415
2113
|
|
|
1416
|
-
declare type ParseResult = ParseSuccess | ParseFailure;
|
|
2114
|
+
export declare type ParseResult = ParseSuccess | ParseFailure;
|
|
1417
2115
|
|
|
1418
2116
|
declare interface ParseSuccess {
|
|
1419
2117
|
ok: true;
|
|
@@ -1428,6 +2126,14 @@ declare interface PendingTask {
|
|
|
1428
2126
|
due_date: string;
|
|
1429
2127
|
}
|
|
1430
2128
|
|
|
2129
|
+
declare interface PinnedMessage {
|
|
2130
|
+
pin_id: number;
|
|
2131
|
+
id: number;
|
|
2132
|
+
sender_name: string | null;
|
|
2133
|
+
message: string;
|
|
2134
|
+
date_created: string;
|
|
2135
|
+
}
|
|
2136
|
+
|
|
1431
2137
|
export declare function PipelinePanel({ collection, item, defaultExpanded, title, showApprovalChain, onBeforeTransition, addendumPending, addendumView }: {
|
|
1432
2138
|
collection: string;
|
|
1433
2139
|
item: string;
|
|
@@ -1445,6 +2151,17 @@ export declare function PipelineTransitionButtons({ collection, item, onBeforeTr
|
|
|
1445
2151
|
onBeforeTransition?: () => boolean | Promise<boolean>;
|
|
1446
2152
|
}): JSX.Element | null;
|
|
1447
2153
|
|
|
2154
|
+
/**
|
|
2155
|
+
* How many decimal places a numeric field wants, from its `precision` option.
|
|
2156
|
+
*
|
|
2157
|
+
* One helper because the answer was hardcoded to 2 in five places — the field
|
|
2158
|
+
* input, the inline grid's cells, its formula and aggregate columns, and the
|
|
2159
|
+
* read-only display — so a field configured for 4 showed 4 in one of them and
|
|
2160
|
+
* 2 everywhere else. Out-of-range or missing values fall back rather than
|
|
2161
|
+
* throwing at Intl, which rejects anything outside 0–20.
|
|
2162
|
+
*/
|
|
2163
|
+
export declare function precisionOf(options: unknown, fallback?: number): number;
|
|
2164
|
+
|
|
1448
2165
|
/**
|
|
1449
2166
|
* Inline attachment preview — click a file, see it, without a download round
|
|
1450
2167
|
* trip. Images, PDFs, video and audio render in an overlay; anything else
|
|
@@ -1467,6 +2184,136 @@ export declare function ProfileView({ userId, className }: {
|
|
|
1467
2184
|
className?: string;
|
|
1468
2185
|
}): JSX.Element;
|
|
1469
2186
|
|
|
2187
|
+
export declare function QueryStatStrip({ stats, rows, effectiveParams, loading }: {
|
|
2188
|
+
stats: QueryWidgetStat[];
|
|
2189
|
+
rows: Array<Record<string, unknown>>;
|
|
2190
|
+
effectiveParams: Record<string, unknown>;
|
|
2191
|
+
loading: boolean;
|
|
2192
|
+
}): JSX.Element | null;
|
|
2193
|
+
|
|
2194
|
+
export declare function QueryTable({ rows, config, onRowClick, pivotYear, rowActions }: {
|
|
2195
|
+
rows: Array<Record<string, unknown>>;
|
|
2196
|
+
config?: QueryTableConfig;
|
|
2197
|
+
/** Makes rows clickable (hover highlight); receives the (post-grouping) row. */
|
|
2198
|
+
onRowClick?: (row: Record<string, unknown>) => void;
|
|
2199
|
+
/** Resolved pivot year (from the widget's params) — overrides config.pivot.year. */
|
|
2200
|
+
pivotYear?: number;
|
|
2201
|
+
/** Trailing action buttons per row (and on the totals row, receiving null). */
|
|
2202
|
+
rowActions?: Array<{
|
|
2203
|
+
label: string;
|
|
2204
|
+
onClick: (row: Record<string, unknown> | null) => void;
|
|
2205
|
+
}>;
|
|
2206
|
+
}): JSX.Element;
|
|
2207
|
+
|
|
2208
|
+
declare interface QueryTableColumn {
|
|
2209
|
+
/** Row key. Omit for pure formula columns. */
|
|
2210
|
+
field?: string;
|
|
2211
|
+
label?: string;
|
|
2212
|
+
format?: 'currency' | 'number' | 'percent' | 'text';
|
|
2213
|
+
/** Arithmetic over {{col}} refs, e.g. '{{carAmount}} - {{allocated}}' or
|
|
2214
|
+
* '{{allocated}} / {{carAmount}} * 100'. Evaluated per row (and over the
|
|
2215
|
+
* totals row for the footer). */
|
|
2216
|
+
formula?: string;
|
|
2217
|
+
/** Include in the totals footer (plain fields sum; formula columns re-run
|
|
2218
|
+
* the formula over the summed values — weighted, not averaged). */
|
|
2219
|
+
sum?: boolean;
|
|
2220
|
+
/** 'progress' renders the value with a bar underneath, filled to
|
|
2221
|
+
* value / progress_max (EFP PUB'd-vs-budget style). Over 100% turns red. */
|
|
2222
|
+
display?: 'progress';
|
|
2223
|
+
/** Denominator for display 'progress': a row field name or a {{col}} formula. */
|
|
2224
|
+
progress_max?: string;
|
|
2225
|
+
/** Column group label. When any column has one, the header renders two
|
|
2226
|
+
* rows — group cells spanning their children ('Jan' over Fcst/Act) — and
|
|
2227
|
+
* alternating groups get a faint band so wide grids stay scannable. */
|
|
2228
|
+
group?: string;
|
|
2229
|
+
/** Cell text color (any CSS color) — EFP forecast/actual column tinting.
|
|
2230
|
+
* color_dark overrides in dark mode (defaults to color). */
|
|
2231
|
+
color?: string;
|
|
2232
|
+
color_dark?: string;
|
|
2233
|
+
/** Second field rendered as a stacked line under the main value in the SAME
|
|
2234
|
+
* cell (EFP month cells: Fcst over Act — halves the column count). Toggles
|
|
2235
|
+
* hide individual lines; the column collapses when both lines hide. */
|
|
2236
|
+
stack?: string;
|
|
2237
|
+
stack_color?: string;
|
|
2238
|
+
stack_color_dark?: string;
|
|
2239
|
+
}
|
|
2240
|
+
|
|
2241
|
+
declare interface QueryTableConfig {
|
|
2242
|
+
columns?: QueryTableColumn[];
|
|
2243
|
+
/** Group rows by this field, summing every numeric column per group. */
|
|
2244
|
+
group_by?: string;
|
|
2245
|
+
/** Render the totals footer row. */
|
|
2246
|
+
totals?: boolean;
|
|
2247
|
+
/** Collapsible section rows: one header row per distinct value of this
|
|
2248
|
+
* field (per-column sums on the header), child rows listed under it.
|
|
2249
|
+
* Unlike group_by (which REPLACES rows with aggregates), children stay. */
|
|
2250
|
+
tree_group_by?: string;
|
|
2251
|
+
/** Sections start collapsed (default false = expanded). */
|
|
2252
|
+
tree_collapsed?: boolean;
|
|
2253
|
+
/** SECOND tree level inside each section, derived by splitting `field` on
|
|
2254
|
+
* its LAST `separator` (default ' - '): left side = collapsible summed
|
|
2255
|
+
* sub-section (category), right side = the leaf's label (Labor/Materials).
|
|
2256
|
+
* Rows without the separator stay directly under the section. */
|
|
2257
|
+
tree_sub_split?: {
|
|
2258
|
+
field: string;
|
|
2259
|
+
separator?: string;
|
|
2260
|
+
};
|
|
2261
|
+
/** Sub-sections start collapsed (default true). */
|
|
2262
|
+
tree_sub_collapsed?: boolean;
|
|
2263
|
+
/** Leaf rows strip a leading '<section name> - ' from the first column —
|
|
2264
|
+
* de-duplicates labels when the section field is the label's prefix. */
|
|
2265
|
+
tree_strip_section_prefix?: boolean;
|
|
2266
|
+
/** Per-row numeric format override: name of a row field holding
|
|
2267
|
+
* 'currency' | 'number' — lets unit-count rows sit alongside dollar rows
|
|
2268
|
+
* (EFP forecasting grid). Falls back to the column format. */
|
|
2269
|
+
row_format_field?: string;
|
|
2270
|
+
/** Pin the first column and the header row while the grid scrolls — wide
|
|
2271
|
+
* month grids keep their row labels in view. */
|
|
2272
|
+
sticky?: boolean;
|
|
2273
|
+
/** Render zeroes as an em dash — de-noises mostly-empty month grids. */
|
|
2274
|
+
zero_dash?: boolean;
|
|
2275
|
+
/** Column show/hide toggle pills above the table (EFP Actuals / Forecasts /
|
|
2276
|
+
* Calendar Year). A toggle turned OFF hides columns matched by exact
|
|
2277
|
+
* `fields` or a field-name `suffix` — unless `hide_when_on` inverts it
|
|
2278
|
+
* (Calendar Year ON hides the Prior/Carryover columns). */
|
|
2279
|
+
toggles?: Array<{
|
|
2280
|
+
label: string;
|
|
2281
|
+
fields?: string[];
|
|
2282
|
+
suffix?: string;
|
|
2283
|
+
default_on?: boolean;
|
|
2284
|
+
hide_when_on?: boolean;
|
|
2285
|
+
}>;
|
|
2286
|
+
/** Tint every column of this group (header + cells + totals). The sentinel
|
|
2287
|
+
* '$current_month' resolves to the current month's short label (Jan…Dec).
|
|
2288
|
+
* Pair with highlight_year_param so it only applies on the current year. */
|
|
2289
|
+
highlight_group?: string;
|
|
2290
|
+
/** Widget-layer guard: name of the effective param holding the selected
|
|
2291
|
+
* year — highlight_group is dropped unless it equals the current year. */
|
|
2292
|
+
highlight_year_param?: string;
|
|
2293
|
+
/** Tiny colored line-name legend under stacked-column headers, e.g.
|
|
2294
|
+
* ['Fcst', 'Act'] (EFP listHeaderSubLabel). */
|
|
2295
|
+
stack_legend?: [string, string];
|
|
2296
|
+
/** Pivot long rows into month columns BEFORE rendering. Rows sharing the
|
|
2297
|
+
* same key fields merge into one row with Jan…Dec (+ optional
|
|
2298
|
+
* prior/later-year buckets and a total) from `value_field`, driven by a
|
|
2299
|
+
* 'yyyy-MM' `date_field` and the `year` param/prop. */
|
|
2300
|
+
pivot?: {
|
|
2301
|
+
date_field: string;
|
|
2302
|
+
value_field: string;
|
|
2303
|
+
/** Fields that identify a row (everything else is dropped). */
|
|
2304
|
+
key_fields: string[];
|
|
2305
|
+
/** Which year's months to expand; other years fold into per-year columns.
|
|
2306
|
+
* Resolved from the widget's effective params when `year_param` set. */
|
|
2307
|
+
year?: number;
|
|
2308
|
+
year_param?: string;
|
|
2309
|
+
/** Add a Total column summing every pivoted cell. */
|
|
2310
|
+
total?: boolean;
|
|
2311
|
+
/** Render a Months/Quarters toggle above the table (EFP quarterly view).
|
|
2312
|
+
* Quarter columns sum their three months — same drill/total math. */
|
|
2313
|
+
quarter_toggle?: boolean;
|
|
2314
|
+
};
|
|
2315
|
+
}
|
|
2316
|
+
|
|
1470
2317
|
export declare function QueryWidgetBody({ cfg, dateRange, entityFilters, refetchInterval, onStatus, onDrill }: {
|
|
1471
2318
|
cfg: ReportQueryWidgetConfig;
|
|
1472
2319
|
dateRange: ReportDateRange | null;
|
|
@@ -1483,6 +2330,42 @@ export declare function QueryWidgetBody({ cfg, dateRange, entityFilters, refetch
|
|
|
1483
2330
|
}) => void;
|
|
1484
2331
|
}): JSX.Element;
|
|
1485
2332
|
|
|
2333
|
+
declare interface QueryWidgetStat {
|
|
2334
|
+
label: string;
|
|
2335
|
+
/** Sum this field over the main query's rows. */
|
|
2336
|
+
field?: string;
|
|
2337
|
+
format?: 'currency' | 'number';
|
|
2338
|
+
/** Hover breakdown: each entry summed over the same rows. */
|
|
2339
|
+
details?: Array<{
|
|
2340
|
+
label: string;
|
|
2341
|
+
field: string;
|
|
2342
|
+
}>;
|
|
2343
|
+
/** Independent source: own custom query. Value = sum of value_field over its
|
|
2344
|
+
* rows; when label_field set, rows also list in the hover breakdown.
|
|
2345
|
+
* param_from copies values from the main widget's effective params
|
|
2346
|
+
* {statQueryParam: widgetParam}. */
|
|
2347
|
+
query?: {
|
|
2348
|
+
slug: string;
|
|
2349
|
+
params?: Record<string, unknown>;
|
|
2350
|
+
param_from?: Record<string, string>;
|
|
2351
|
+
value_field: string;
|
|
2352
|
+
label_field?: string;
|
|
2353
|
+
};
|
|
2354
|
+
/** Card tint (any CSS color, e.g. '#f9fbd1'). */
|
|
2355
|
+
bg?: string;
|
|
2356
|
+
/** Only sum rows matching these field values (equality AND) — EFP
|
|
2357
|
+
* forecasting stats scope to the Workflow Forecast section. */
|
|
2358
|
+
row_match?: Record<string, unknown>;
|
|
2359
|
+
/** Delta stat: value = sum(field) − sum(field_subtract); positive values
|
|
2360
|
+
* render with a leading '+'. */
|
|
2361
|
+
field_subtract?: string;
|
|
2362
|
+
/** EFP stat-card accent: colored top border + value (accent_dark in dark
|
|
2363
|
+
* mode; accent_negative when a delta goes negative). */
|
|
2364
|
+
accent?: string;
|
|
2365
|
+
accent_dark?: string;
|
|
2366
|
+
accent_negative?: string;
|
|
2367
|
+
}
|
|
2368
|
+
|
|
1486
2369
|
export declare function QueueBulkBar({ count, states, busy, claimsEnabled, onClaim, onRelease, onTransition, onClear }: {
|
|
1487
2370
|
count: number;
|
|
1488
2371
|
states: Array<{
|
|
@@ -1497,6 +2380,25 @@ export declare function QueueBulkBar({ count, states, busy, claimsEnabled, onCla
|
|
|
1497
2380
|
onClear: () => void;
|
|
1498
2381
|
}): JSX.Element | null;
|
|
1499
2382
|
|
|
2383
|
+
export declare interface QueueGroup<T extends QueueGroupingRow = QueueGroupingRow> {
|
|
2384
|
+
key: string;
|
|
2385
|
+
rows: T[];
|
|
2386
|
+
breached: number;
|
|
2387
|
+
atRisk: number;
|
|
2388
|
+
}
|
|
2389
|
+
|
|
2390
|
+
declare interface QueueGroupingRow {
|
|
2391
|
+
collection: string;
|
|
2392
|
+
state: string | null;
|
|
2393
|
+
sla_status: 'ok' | 'warning' | 'breached' | null;
|
|
2394
|
+
at_risk: boolean;
|
|
2395
|
+
owners: {
|
|
2396
|
+
name: string;
|
|
2397
|
+
}[];
|
|
2398
|
+
aging_hours: number | null;
|
|
2399
|
+
extra?: Record<string, unknown>;
|
|
2400
|
+
}
|
|
2401
|
+
|
|
1500
2402
|
declare interface QueueItemRow {
|
|
1501
2403
|
collection: string;
|
|
1502
2404
|
item_id: string;
|
|
@@ -1595,6 +2497,23 @@ declare interface QuickFilterDef {
|
|
|
1595
2497
|
sort?: string;
|
|
1596
2498
|
}
|
|
1597
2499
|
|
|
2500
|
+
/** The reaction palette — mirrored server-side; anything else is rejected. */
|
|
2501
|
+
export declare const REACTION_EMOJI: readonly ["👍", "✅", "👀", "🎉", "❤️", "😂"];
|
|
2502
|
+
|
|
2503
|
+
export declare interface ReadViewLayout {
|
|
2504
|
+
layout: {
|
|
2505
|
+
id: number;
|
|
2506
|
+
name: string;
|
|
2507
|
+
};
|
|
2508
|
+
groups: LayoutGroup[];
|
|
2509
|
+
assignments: LayoutAssignment[];
|
|
2510
|
+
}
|
|
2511
|
+
|
|
2512
|
+
export declare function RecordChatActions({ collection, itemDraft }: {
|
|
2513
|
+
collection: string;
|
|
2514
|
+
itemDraft: Record<string, unknown>;
|
|
2515
|
+
}): JSX.Element | null;
|
|
2516
|
+
|
|
1598
2517
|
export declare function RecordDrilldownSheet({ collection, itemId, layoutId, rootLayoutSlug, width, title, stack: controlledStack, onPush, onPop, onClose }: {
|
|
1599
2518
|
collection: string;
|
|
1600
2519
|
itemId: string;
|
|
@@ -1616,11 +2535,150 @@ export declare function RecordDrilldownSheet({ collection, itemId, layoutId, roo
|
|
|
1616
2535
|
onClose: () => void;
|
|
1617
2536
|
}): JSX.Element;
|
|
1618
2537
|
|
|
2538
|
+
export declare function RecordGridEditor({ config }: {
|
|
2539
|
+
config: RecordGridEditorConfig;
|
|
2540
|
+
}): JSX.Element;
|
|
2541
|
+
|
|
2542
|
+
declare interface RecordGridEditorConfig {
|
|
2543
|
+
collection: string;
|
|
2544
|
+
title?: string;
|
|
2545
|
+
/** Scope pickers: every field must be chosen before rows load; values filter
|
|
2546
|
+
* loaded rows and seed created rows. `filter` supports '$scope.<field>'
|
|
2547
|
+
* tokens off the other scope values. */
|
|
2548
|
+
scope?: Array<{
|
|
2549
|
+
field: string;
|
|
2550
|
+
collection: string;
|
|
2551
|
+
label?: string;
|
|
2552
|
+
filter?: Record<string, unknown>;
|
|
2553
|
+
}>;
|
|
2554
|
+
/** Free-form identity pickers on each row (year / division / …) — part of
|
|
2555
|
+
* what makes a row unique; rendered as comboboxes on NEW rows, read-only
|
|
2556
|
+
* labels on existing ones. */
|
|
2557
|
+
key_columns?: Array<{
|
|
2558
|
+
field: string;
|
|
2559
|
+
label?: string;
|
|
2560
|
+
collection: string;
|
|
2561
|
+
}>;
|
|
2562
|
+
/** One editable row per record of this collection; existing target rows are
|
|
2563
|
+
* matched via fk_field. `filter` supports '$scope.<field>' tokens. */
|
|
2564
|
+
row_source?: {
|
|
2565
|
+
collection: string;
|
|
2566
|
+
label_field: string;
|
|
2567
|
+
fk_field: string;
|
|
2568
|
+
filter?: Record<string, unknown>;
|
|
2569
|
+
sort?: string;
|
|
2570
|
+
};
|
|
2571
|
+
/** Plain editable numeric columns. */
|
|
2572
|
+
columns?: Array<{
|
|
2573
|
+
field: string;
|
|
2574
|
+
label?: string;
|
|
2575
|
+
readonly?: boolean;
|
|
2576
|
+
}>;
|
|
2577
|
+
/** Generates january…december editable columns per set (field =
|
|
2578
|
+
* '<month><suffix>'). */
|
|
2579
|
+
month_sets?: Array<{
|
|
2580
|
+
suffix: string;
|
|
2581
|
+
label: string;
|
|
2582
|
+
}>;
|
|
2583
|
+
allow_add?: boolean;
|
|
2584
|
+
allow_delete?: boolean;
|
|
2585
|
+
/** Written on save as the sum of the FIRST month set's values. */
|
|
2586
|
+
computed_total_field?: string;
|
|
2587
|
+
/** Custom query run after a successful save — params support '$scope.<f>'. */
|
|
2588
|
+
after_save?: {
|
|
2589
|
+
query_slug: string;
|
|
2590
|
+
params?: Record<string, unknown>;
|
|
2591
|
+
};
|
|
2592
|
+
/** Nested map editors opened from toolbar buttons (EFP Manage Cost Tables) —
|
|
2593
|
+
* receive the current scope; enabled once `require_scope` fields are set. */
|
|
2594
|
+
toolbar_editors?: Array<{
|
|
2595
|
+
button_label: string;
|
|
2596
|
+
sheet_width?: number | string;
|
|
2597
|
+
require_scope?: string[];
|
|
2598
|
+
json_map: JsonMapEditorConfig;
|
|
2599
|
+
}>;
|
|
2600
|
+
}
|
|
2601
|
+
|
|
2602
|
+
export declare function RecordReadView({ collection, itemId, layoutData }: {
|
|
2603
|
+
collection: string;
|
|
2604
|
+
itemId: string;
|
|
2605
|
+
layoutData: ReadViewLayout;
|
|
2606
|
+
}): JSX.Element;
|
|
2607
|
+
|
|
2608
|
+
/**
|
|
2609
|
+
* "Since you last looked" — opening a saved record touches the per-user view
|
|
2610
|
+
* watermark and, when other people changed the record in between, renders a
|
|
2611
|
+
* one-line recap above the form. The server owns the session semantics (a
|
|
2612
|
+
* refresh within 30 minutes keeps the same baseline), the strip just shows
|
|
2613
|
+
* whatever the touch returned. Dismiss is per-mount — the next genuine visit
|
|
2614
|
+
* recomputes against the new baseline anyway.
|
|
2615
|
+
*/
|
|
2616
|
+
export declare function RecordRecapStrip({ collection, itemId }: {
|
|
2617
|
+
collection: string;
|
|
2618
|
+
itemId: string;
|
|
2619
|
+
}): JSX.Element | null;
|
|
2620
|
+
|
|
2621
|
+
/**
|
|
2622
|
+
* Per-record notification subscription — a bell in the item header that lets
|
|
2623
|
+
* any user watch this specific record. Backed entirely by the existing
|
|
2624
|
+
* nivaro_notification_subscriptions engine:
|
|
2625
|
+
*
|
|
2626
|
+
* State changes only → one event_type='workflow_transition' row scoped to
|
|
2627
|
+
* the record via filters [{field:'id', op:'eq', value:<id>}] (filter_field
|
|
2628
|
+
* stays null — on transition subs it means "to_state").
|
|
2629
|
+
* All changes → that row PLUS an event_type='all' row scoped via
|
|
2630
|
+
* filter_field='id' / filter_value (the create/update/delete path reads
|
|
2631
|
+
* only the flat filter pair, never the filters JSON).
|
|
2632
|
+
*
|
|
2633
|
+
* Transitions never fire the items-service update hook (state mirrors are raw
|
|
2634
|
+
* writes), so the two rows can't double-notify.
|
|
2635
|
+
*/
|
|
2636
|
+
export declare function RecordSubscribeButton({ collection, itemId, recordLabel }: {
|
|
2637
|
+
collection: string;
|
|
2638
|
+
itemId: string;
|
|
2639
|
+
recordLabel?: string;
|
|
2640
|
+
}): JSX.Element;
|
|
2641
|
+
|
|
1619
2642
|
/** Register the host's DM opener. Returns an unregister function. */
|
|
1620
2643
|
export declare function registerDmOpener(fn: DmOpener): () => void;
|
|
1621
2644
|
|
|
1622
2645
|
export declare function registerRoomOpener(fn: RoomOpener): () => void;
|
|
1623
2646
|
|
|
2647
|
+
export declare function RelatedRecordsPanel({ collection, itemId, defaultExpanded }: {
|
|
2648
|
+
collection: string;
|
|
2649
|
+
itemId: string;
|
|
2650
|
+
defaultExpanded?: boolean;
|
|
2651
|
+
}): JSX.Element;
|
|
2652
|
+
|
|
2653
|
+
export declare function RelationCombobox({ collection, value, onChange, disabled, placeholder, extraFilter, autoSelectSingle, optionSort, requiredParent, facets, fieldKey }: {
|
|
2654
|
+
collection: string;
|
|
2655
|
+
value: unknown;
|
|
2656
|
+
onChange: (v: unknown) => void;
|
|
2657
|
+
disabled?: boolean;
|
|
2658
|
+
placeholder?: string;
|
|
2659
|
+
extraFilter?: Record<string, unknown>;
|
|
2660
|
+
/** When the filtered option set has EXACTLY one option and the field is
|
|
2661
|
+
* empty, pick it automatically (options.auto_select_single). Two or more
|
|
2662
|
+
* options — or zero — leave the field blank; an existing value is never
|
|
2663
|
+
* overridden. Re-evaluates when the effective filter changes (e.g. a
|
|
2664
|
+
* cascade parent narrowing the list). */
|
|
2665
|
+
autoSelectSingle?: boolean;
|
|
2666
|
+
/** Option ordering: 'column' | '-column' (server sort) | 'label' | '-label' (display-label sort). Default: label ascending. */
|
|
2667
|
+
optionSort?: string;
|
|
2668
|
+
requiredParent?: string;
|
|
2669
|
+
/** Field name, so staleness can be reported to the form by name. */
|
|
2670
|
+
fieldKey?: string;
|
|
2671
|
+
/** In-picker filter facets: M2O fields ON THE TARGET COLLECTION rendered as
|
|
2672
|
+
* small pickers inside the dropdown. Ephemeral — they only narrow the
|
|
2673
|
+
* option list, nothing is written to the form. */
|
|
2674
|
+
facets?: Array<{
|
|
2675
|
+
field: string;
|
|
2676
|
+
label?: string;
|
|
2677
|
+
sort?: string;
|
|
2678
|
+
filter?: Record<string, unknown>;
|
|
2679
|
+
}>;
|
|
2680
|
+
}): JSX.Element;
|
|
2681
|
+
|
|
1624
2682
|
/**
|
|
1625
2683
|
* Unstyled relation picker.
|
|
1626
2684
|
* - m2o: single <select> of related items
|
|
@@ -1641,7 +2699,7 @@ export declare type RelationOption = {
|
|
|
1641
2699
|
raw: Record<string, unknown>;
|
|
1642
2700
|
};
|
|
1643
2701
|
|
|
1644
|
-
declare type RenderFieldProps = {
|
|
2702
|
+
export declare type RenderFieldProps = {
|
|
1645
2703
|
field: any;
|
|
1646
2704
|
value: unknown;
|
|
1647
2705
|
onChange: (v: unknown) => void;
|
|
@@ -1684,56 +2742,9 @@ export declare interface ReportViewProps {
|
|
|
1684
2742
|
emptyState?: React.ReactNode;
|
|
1685
2743
|
}
|
|
1686
2744
|
|
|
1687
|
-
export declare function
|
|
1688
|
-
|
|
1689
|
-
item: string | null | undefined,
|
|
1690
|
-
routes: NotificationRouteMap
|
|
1691
|
-
): NotificationTarget {
|
|
1692
|
-
const c = collection?.trim()
|
|
1693
|
-
if (!c) return null
|
|
1694
|
-
const i = item != null && String(item).trim() !== '' ? String(item) : null
|
|
1695
|
-
|
|
1696
|
-
if (c === '__chat__') {
|
|
1697
|
-
// Opening a room needs a registered chat dock — without one there is no
|
|
1698
|
-
// chat surface to open, so the row stays plain.
|
|
1699
|
-
return i && canOpenChatRoom() ? { type: 'chat', room: i } : null
|
|
1700
|
-
}
|
|
1701
|
-
|
|
1702
|
-
if (c === 'nivaro_report_defs') {
|
|
1703
|
-
const p = i ? routes.report?.(i) : null
|
|
1704
|
-
return p ? { type: 'path', path: p } : null
|
|
1705
|
-
}
|
|
1706
|
-
if (c === 'nivaro_queues') {
|
|
1707
|
-
const p = i ? routes.queue?.(i) : null
|
|
1708
|
-
return p ? { type: 'path', path: p } : null
|
|
1709
|
-
}
|
|
1710
|
-
if (c === 'nivaro_dashboards') {
|
|
1711
|
-
const p = i ? routes.dashboard?.(i) : null
|
|
1712
|
-
return p ? { type: 'path', path: p } : null
|
|
1713
|
-
}
|
|
1714
|
-
if (ALERT_COLLECTIONS.has(c)) {
|
|
1715
|
-
const p = routes.alerts?.()
|
|
1716
|
-
return p ? { type: 'path', path: p } : null
|
|
1717
|
-
}
|
|
1718
|
-
if (IMPORT_COLLECTIONS.has(c)) {
|
|
1719
|
-
const p = routes.imports?.()
|
|
1720
|
-
return p ? { type: 'path', path: p } : null
|
|
1721
|
-
}
|
|
1722
|
-
if (c === 'nivaro_issues') {
|
|
1723
|
-
const p = routes.issues?.()
|
|
1724
|
-
return p ? { type: 'path', path: p } : null
|
|
1725
|
-
}
|
|
1726
|
-
// Any other system collection has no user-facing page — plain row, never a
|
|
1727
|
-
// /collections/nivaro_* route that would 404 or 403.
|
|
1728
|
-
if (/^nivaro_/i.test(c) || /^directus_/i.test(c)) return null
|
|
1729
|
-
|
|
1730
|
-
if (i) {
|
|
1731
|
-
const p = routes.record(c, i)
|
|
1732
|
-
return p ? { type: 'path', path: p } : null
|
|
1733
|
-
}
|
|
1734
|
-
const p = routes.list?.(c)
|
|
1735
|
-
return p ? { type: 'path', path: p } : null
|
|
1736
|
-
}
|
|
2745
|
+
export declare function resolveCollectionIcon(iconName: string | null | undefined): React.ElementType | null;
|
|
2746
|
+
|
|
2747
|
+
export declare function resolveNotificationTarget(collection: string | null | undefined, item: string | null | undefined, routes: NotificationRouteMap): NotificationTarget;
|
|
1737
2748
|
|
|
1738
2749
|
export declare function RevisionsPanel({ collection, item, onRollback, triggerClassName, inlineTableFields, open, onOpenChange }: {
|
|
1739
2750
|
collection: string;
|
|
@@ -1767,20 +2778,67 @@ export declare interface RoomInfo {
|
|
|
1767
2778
|
*/
|
|
1768
2779
|
declare type RoomOpener = (room: string, label?: string) => void;
|
|
1769
2780
|
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
2781
|
+
export declare const ROW_HIGHLIGHT_TINTS: Record<string, {
|
|
2782
|
+
row: string;
|
|
2783
|
+
text: string;
|
|
2784
|
+
}>;
|
|
2785
|
+
|
|
2786
|
+
/**
|
|
2787
|
+
* A one-click rewrite of every row in the grid, driven by an aggregate of a
|
|
2788
|
+
* related collection.
|
|
2789
|
+
*
|
|
2790
|
+
* EFP's "Close Out Lines" is one instance of this shape: for each REQ line,
|
|
2791
|
+
* sum `open_unbilled_amount` across the PO lines pointing at it and, where the
|
|
2792
|
+
* line covers that remainder, subtract it. Expressed as config rather than
|
|
2793
|
+
* EFP code so any collection can do the same:
|
|
2794
|
+
*
|
|
2795
|
+
* {label:'Close Out Lines', relation:'po_line_items',
|
|
2796
|
+
* aggregate:{field:'open_unbilled_amount', op:'sum'},
|
|
2797
|
+
* guard:'{{amount}} >= {{__agg__}}',
|
|
2798
|
+
* set:{amount:'{{amount}} - {{__agg__}}'}}
|
|
2799
|
+
*
|
|
2800
|
+
* `{{__agg__}}` is the aggregate for that row (same token match-agg-column
|
|
2801
|
+
* uses); every other `{{field}}` reads the row's current value. Rows failing
|
|
2802
|
+
* the guard are left exactly as they are.
|
|
2803
|
+
*
|
|
2804
|
+
* Writes go through the SAME paths a manual cell edit uses, so a staged grid
|
|
2805
|
+
* (new record, addendum, save_mode 'pending') stages the change and an
|
|
2806
|
+
* immediate grid PATCHes it — the action never invents its own persistence.
|
|
2807
|
+
*/
|
|
2808
|
+
declare interface RowBulkActionConfig {
|
|
2809
|
+
label: string;
|
|
2810
|
+
/** O2M alias on the ROW's collection pointing at the rows to aggregate. */
|
|
2811
|
+
relation: string;
|
|
2812
|
+
aggregate: {
|
|
2813
|
+
field: string;
|
|
2814
|
+
op?: 'sum' | 'count' | 'min' | 'max';
|
|
2815
|
+
};
|
|
2816
|
+
/** Optional per-row condition; rows that fail are skipped untouched. */
|
|
2817
|
+
guard?: string;
|
|
2818
|
+
/** field → formula. */
|
|
2819
|
+
set: Record<string, string>;
|
|
2820
|
+
confirm?: string;
|
|
2821
|
+
variant?: 'default' | 'danger';
|
|
2822
|
+
}
|
|
2823
|
+
|
|
2824
|
+
export declare function rowHighlightClass(color?: string | null): string | undefined;
|
|
2825
|
+
|
|
2826
|
+
export declare function rowHighlightTextClass(color?: string | null): string;
|
|
2827
|
+
|
|
2828
|
+
declare interface RowRule {
|
|
2829
|
+
trigger_field?: string | null;
|
|
2830
|
+
trigger_op?: string;
|
|
2831
|
+
trigger_value?: string | null;
|
|
2832
|
+
target_field: string;
|
|
2833
|
+
target_type: 'set' | 'clear' | 'relation_field';
|
|
2834
|
+
target_value?: string | null;
|
|
2835
|
+
only_if_empty?: boolean;
|
|
2836
|
+
sort?: number;
|
|
1782
2837
|
}
|
|
1783
2838
|
|
|
2839
|
+
/** Convenience: run a resolved target (navigate or open the chat room). */
|
|
2840
|
+
export declare function runNotificationTarget(target: NotificationTarget, navigate: (path: string) => void): boolean;
|
|
2841
|
+
|
|
1784
2842
|
export declare type SectionState = {
|
|
1785
2843
|
isCollapsed: (key: string) => boolean;
|
|
1786
2844
|
toggle: (key: string) => void;
|
|
@@ -1791,20 +2849,27 @@ export declare type SectionState = {
|
|
|
1791
2849
|
export declare function SelectField({ field, value, onChange, error, disabled, readOnly, inputId, errorId }: FieldComponentProps): JSX.Element;
|
|
1792
2850
|
|
|
1793
2851
|
/**
|
|
1794
|
-
* rrweb session recorder for headless frontends
|
|
2852
|
+
* rrweb session recorder for headless frontends — two modes, one hook
|
|
2853
|
+
* (the exact model the admin app runs; see admin/src/lib/use-session-recorder.ts).
|
|
2854
|
+
*
|
|
2855
|
+
* FULL mode (`session_recording_enabled` on the instance): events stream to
|
|
2856
|
+
* the server continuously.
|
|
2857
|
+
*
|
|
2858
|
+
* ERROR-CLIP mode (`error_replay_enabled`, when full recording is off):
|
|
2859
|
+
* rrweb records into a rolling IN-MEMORY buffer — two 30s checkout windows,
|
|
2860
|
+
* so 30–60s of history — and uploads NOTHING. When the host reports an error,
|
|
2861
|
+
* `captureErrorClip()` flushes the buffer as a short recording labelled
|
|
2862
|
+
* app='error-clip'; attach the returned `recording_id`/`offset_ms` to your
|
|
2863
|
+
* `POST /issues/client` body and the issue links straight to the replay.
|
|
1795
2864
|
*
|
|
1796
2865
|
* Drop `useSessionRecorder({ app: 'customer-portal' })` anywhere inside a
|
|
1797
|
-
* NivaroProvider (or pass a client explicitly)
|
|
1798
|
-
*
|
|
1799
|
-
*
|
|
1800
|
-
*
|
|
2866
|
+
* NivaroProvider (or pass a client explicitly). Needs `rrweb` installed in
|
|
2867
|
+
* the host (optional peer dependency; without it the hook warns once and
|
|
2868
|
+
* no-ops). Privacy in both modes: every input masked, `nvr-no-record`
|
|
2869
|
+
* class blocked; in clip mode events never leave the browser except on error.
|
|
1801
2870
|
*
|
|
1802
|
-
*
|
|
1803
|
-
*
|
|
1804
|
-
* Events flush every 10s (or 150 events); the server enforces size caps and
|
|
1805
|
-
* a 7-day retention. Recordings attribute to the authenticated SDK identity
|
|
1806
|
-
* (usually your service token's user) with the `app` label telling replays
|
|
1807
|
-
* apart per frontend.
|
|
2871
|
+
* `captureErrorClip` is a module singleton so an error boundary — a class
|
|
2872
|
+
* component far from this hook — can call it without plumbing.
|
|
1808
2873
|
*/
|
|
1809
2874
|
export declare interface SessionRecorderOptions {
|
|
1810
2875
|
/** Label shown in the admin replay list — which frontend this is. */
|
|
@@ -1870,7 +2935,9 @@ export declare function TextField({ field, value, onChange, error, disabled, rea
|
|
|
1870
2935
|
|
|
1871
2936
|
export declare function TipLayer(): ReactPortal | null;
|
|
1872
2937
|
|
|
1873
|
-
declare
|
|
2938
|
+
export declare function titleCase(str: string): string;
|
|
2939
|
+
|
|
2940
|
+
export declare type TokenResolver = (path: string) => unknown;
|
|
1874
2941
|
|
|
1875
2942
|
/** Install the listeners. Safe to call more than once. */
|
|
1876
2943
|
export declare function trackActivity(): void;
|
|
@@ -1886,8 +2953,45 @@ export declare function translateScopeValues(client: {
|
|
|
1886
2953
|
target_collection: string;
|
|
1887
2954
|
}, ids: Array<string | number>, valueField?: string): Promise<Array<string | number>>;
|
|
1888
2955
|
|
|
2956
|
+
/**
|
|
2957
|
+
* Base URL + auth for the few raw `fetch` calls (widgets, PDF blobs) that
|
|
2958
|
+
* can't go through `client.request`. Derives everything from the ambient
|
|
2959
|
+
* Nivaro client so external hosts (different origin, token auth) work the
|
|
2960
|
+
* same as the same-origin admin; falls back to relative '/api' + cookies
|
|
2961
|
+
* when no provider is mounted.
|
|
2962
|
+
*/
|
|
2963
|
+
export declare function useApiFetchConfig(): {
|
|
2964
|
+
apiBase: string;
|
|
2965
|
+
authHeaders: Record<string, string>;
|
|
2966
|
+
credentials: RequestCredentials;
|
|
2967
|
+
};
|
|
2968
|
+
|
|
1889
2969
|
export declare function useApiUpdate(): ApiVersionInfo | null;
|
|
1890
2970
|
|
|
2971
|
+
export declare function useChannelAdmin(channelId: number | null): {
|
|
2972
|
+
update: UseMutationResult<unknown, Error, {
|
|
2973
|
+
name?: string;
|
|
2974
|
+
topic?: string | null;
|
|
2975
|
+
visibility?: "open" | "role" | "private";
|
|
2976
|
+
role?: string | null;
|
|
2977
|
+
is_archived?: boolean;
|
|
2978
|
+
}, unknown>;
|
|
2979
|
+
addMember: UseMutationResult<unknown, Error, string, unknown>;
|
|
2980
|
+
removeMember: UseMutationResult<unknown, Error, string, unknown>;
|
|
2981
|
+
};
|
|
2982
|
+
|
|
2983
|
+
/** Browsable channels — what keeps the sidebar to joined rooms only. */
|
|
2984
|
+
export declare function useChannelDirectory(search: string): {
|
|
2985
|
+
channels: NoInfer<DirectoryChannel[]>;
|
|
2986
|
+
loading: boolean;
|
|
2987
|
+
};
|
|
2988
|
+
|
|
2989
|
+
/** Members of a channel — the owner-facing list for private channels. */
|
|
2990
|
+
export declare function useChannelMembers(channelId: number | null): {
|
|
2991
|
+
members: NoInfer<ChannelMember[]>;
|
|
2992
|
+
loading: boolean;
|
|
2993
|
+
};
|
|
2994
|
+
|
|
1891
2995
|
export declare function useChatConfig(): ChatConfig;
|
|
1892
2996
|
|
|
1893
2997
|
export declare function useChatMessages(room: string | null): {
|
|
@@ -1895,6 +2999,13 @@ export declare function useChatMessages(room: string | null): {
|
|
|
1895
2999
|
loading: boolean;
|
|
1896
3000
|
};
|
|
1897
3001
|
|
|
3002
|
+
/** Id + name only — /api/roles is admin-gated, so the channel picker reads the
|
|
3003
|
+
* chat route's own lightweight list. */
|
|
3004
|
+
export declare function useChatRoles(): NoInfer<{
|
|
3005
|
+
id: string;
|
|
3006
|
+
name: string;
|
|
3007
|
+
}[]>;
|
|
3008
|
+
|
|
1898
3009
|
/**
|
|
1899
3010
|
* The sidebar. The server decides WHICH rooms (visibility) and computes unread
|
|
1900
3011
|
* in SQL against the watermark; the client only labels them. The old version
|
|
@@ -1908,8 +3019,48 @@ export declare function useChatRooms(): {
|
|
|
1908
3019
|
loading: boolean;
|
|
1909
3020
|
};
|
|
1910
3021
|
|
|
3022
|
+
/** Search every room in MY sidebar (server enforces visibility by
|
|
3023
|
+
* construction — the room set is the user's own). */
|
|
3024
|
+
export declare function useChatSearch(q: string): {
|
|
3025
|
+
hits: NoInfer<ChatSearchHit[]>;
|
|
3026
|
+
loading: boolean;
|
|
3027
|
+
};
|
|
3028
|
+
|
|
3029
|
+
export declare function useCreateChannel(): UseMutationResult<unknown, Error, {
|
|
3030
|
+
name: string;
|
|
3031
|
+
key?: string;
|
|
3032
|
+
topic?: string;
|
|
3033
|
+
visibility?: "open" | "role" | "private";
|
|
3034
|
+
role?: string | null;
|
|
3035
|
+
}, unknown>;
|
|
3036
|
+
|
|
3037
|
+
export declare function useCreateGroupDm(): UseMutationResult< {
|
|
3038
|
+
room: string;
|
|
3039
|
+
name: string;
|
|
3040
|
+
}, Error, {
|
|
3041
|
+
user_ids: string[];
|
|
3042
|
+
name?: string;
|
|
3043
|
+
}, unknown>;
|
|
3044
|
+
|
|
3045
|
+
export declare function useDeleteMessage(room: string): UseMutationResult<unknown, Error, number, unknown>;
|
|
3046
|
+
|
|
1911
3047
|
export declare function useDrilldown(): DrilldownContextValue | null;
|
|
1912
3048
|
|
|
3049
|
+
export declare function useEditMessage(room: string): UseMutationResult<unknown, Error, {
|
|
3050
|
+
messageId: number;
|
|
3051
|
+
text: string;
|
|
3052
|
+
}, unknown>;
|
|
3053
|
+
|
|
3054
|
+
/**
|
|
3055
|
+
* Resolves an entity room ('wf:CR26-76773') to the record's URL, host-routed
|
|
3056
|
+
* via cfg.recordUrl. The room-type registry maps the prefix to a collection +
|
|
3057
|
+
* match field; when the match field isn't the PK the record is looked up by
|
|
3058
|
+
* it (readable by construction — room visibility already required record
|
|
3059
|
+
* read). Null for non-entity rooms, unregistered prefixes, or when the record
|
|
3060
|
+
* doesn't resolve.
|
|
3061
|
+
*/
|
|
3062
|
+
export declare function useEntityRoomLink(room: string | null): string | null;
|
|
3063
|
+
|
|
1913
3064
|
export declare function useFieldArray(form: UseNivaroFormReturn, field: string): FieldArrayReturn;
|
|
1914
3065
|
|
|
1915
3066
|
export declare function useFieldState(form: UseNivaroFormReturn, field: string): FieldState;
|
|
@@ -2033,6 +3184,8 @@ export declare type UseNivaroFormReturn = {
|
|
|
2033
3184
|
gridFlushersRef: default_2.MutableRefObject<Map<string, () => Promise<void>>>;
|
|
2034
3185
|
};
|
|
2035
3186
|
|
|
3187
|
+
export declare function useOptionalNivaroClient(): NivaroClient | null;
|
|
3188
|
+
|
|
2036
3189
|
export declare function useOrderedLayout(form: UseNivaroFormReturn): {
|
|
2037
3190
|
items: LayoutItem[];
|
|
2038
3191
|
hasTabs: boolean;
|
|
@@ -2099,6 +3252,21 @@ export declare function useRelationOptions(client: NivaroClient | null, relatedC
|
|
|
2099
3252
|
error: Error | null;
|
|
2100
3253
|
};
|
|
2101
3254
|
|
|
3255
|
+
export declare function useRoomMembership(): {
|
|
3256
|
+
join: UseMutationResult<unknown, Error, string, unknown>;
|
|
3257
|
+
leave: UseMutationResult<unknown, Error, string, unknown>;
|
|
3258
|
+
setMuted: UseMutationResult<unknown, Error, {
|
|
3259
|
+
room: string;
|
|
3260
|
+
muted: boolean;
|
|
3261
|
+
}, unknown>;
|
|
3262
|
+
setNotifyMode: UseMutationResult<unknown, Error, {
|
|
3263
|
+
room: string;
|
|
3264
|
+
mode: "all" | "mentions";
|
|
3265
|
+
}, unknown>;
|
|
3266
|
+
};
|
|
3267
|
+
|
|
3268
|
+
export declare function useRoomPins(room: string | null): NoInfer<PinnedMessage[]>;
|
|
3269
|
+
|
|
2102
3270
|
/** Stacked avatar cluster (+N) with a hover/pinnable portal roster whose rows
|
|
2103
3271
|
* are UserChips — the single user-display primitive for owners/user lists.
|
|
2104
3272
|
* Reused by the item-header Owners chip and the collection browser. */
|
|
@@ -2122,6 +3290,13 @@ export declare function useSessionRecorder(options?: SessionRecorderOptions): vo
|
|
|
2122
3290
|
|
|
2123
3291
|
export declare function useTabState(form: UseNivaroFormReturn): TabState;
|
|
2124
3292
|
|
|
3293
|
+
export declare function useTogglePin(room: string): UseMutationResult<unknown, Error, number, unknown>;
|
|
3294
|
+
|
|
3295
|
+
export declare function useToggleReaction(room: string): UseMutationResult<unknown, Error, {
|
|
3296
|
+
messageId: number;
|
|
3297
|
+
emoji: string;
|
|
3298
|
+
}, unknown>;
|
|
3299
|
+
|
|
2125
3300
|
export declare function useTypingIndicator(room: string | null): {
|
|
2126
3301
|
onType: () => void;
|
|
2127
3302
|
clearTyping: () => void;
|
|
@@ -2130,6 +3305,17 @@ export declare function useTypingIndicator(room: string | null): {
|
|
|
2130
3305
|
|
|
2131
3306
|
export declare function useUnreadChirp(totalUnread: number, rooms?: RoomInfo[]): void;
|
|
2132
3307
|
|
|
3308
|
+
/** Directory of users to add to a private channel. */
|
|
3309
|
+
export declare function useUserSearch(search: string, enabled: boolean): {
|
|
3310
|
+
users: NoInfer<{
|
|
3311
|
+
id: string;
|
|
3312
|
+
first_name: string | null;
|
|
3313
|
+
last_name: string | null;
|
|
3314
|
+
email: string | null;
|
|
3315
|
+
}[]>;
|
|
3316
|
+
loading: boolean;
|
|
3317
|
+
};
|
|
3318
|
+
|
|
2133
3319
|
export declare function useWatchFields(form: UseNivaroFormReturn, fields: string[]): Record<string, unknown>;
|
|
2134
3320
|
|
|
2135
3321
|
/**
|
|
@@ -2149,6 +3335,32 @@ declare interface ValidationResult {
|
|
|
2149
3335
|
unknownTokens: string[];
|
|
2150
3336
|
}
|
|
2151
3337
|
|
|
3338
|
+
export declare function WidgetSlot({ widgetId, inputBindings, itemDraft, itemCollection, ready, label, defaultExpanded, frameless, apiBase: apiBaseProp, compact, strip, onClientAction, onWidgetType, onContentChange }: WidgetSlotProps): JSX.Element | null;
|
|
3339
|
+
|
|
3340
|
+
declare interface WidgetSlotProps {
|
|
3341
|
+
widgetId: number;
|
|
3342
|
+
inputBindings?: InputBinding[];
|
|
3343
|
+
itemDraft?: Record<string, unknown>;
|
|
3344
|
+
itemCollection?: string;
|
|
3345
|
+
ready?: boolean;
|
|
3346
|
+
label?: string;
|
|
3347
|
+
defaultExpanded?: boolean;
|
|
3348
|
+
/** Render body only — no card border/header/collapse (host provides chrome). */
|
|
3349
|
+
frameless?: boolean;
|
|
3350
|
+
apiBase?: string;
|
|
3351
|
+
compact?: boolean;
|
|
3352
|
+
strip?: boolean;
|
|
3353
|
+
onClientAction?: (action: ClientAction) => void;
|
|
3354
|
+
onWidgetType?: (type: string) => void;
|
|
3355
|
+
/**
|
|
3356
|
+
* Reports whether the widget has anything to show (review_list: any rows;
|
|
3357
|
+
* other types: any successful render; errors count as content so failures
|
|
3358
|
+
* stay visible). Lets a host section's hide_when_empty consider widget
|
|
3359
|
+
* content, not just field values.
|
|
3360
|
+
*/
|
|
3361
|
+
onContentChange?: (hasContent: boolean) => void;
|
|
3362
|
+
}
|
|
3363
|
+
|
|
2152
3364
|
export declare function WorkflowPanel({ collection, item }: {
|
|
2153
3365
|
collection: string;
|
|
2154
3366
|
item: string;
|