@zestl/zvolv-widgets 0.0.0-stage → 0.0.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,3070 @@
1
+ import React from 'react';
2
+ import dayjs from 'dayjs';
3
+
4
+ interface ZvolvRuntime {
5
+ client: any;
6
+ resolveQueryUser?: () => Promise<any>;
7
+ resolveUserLabels?: (ids: any[], kind: string) => Promise<Record<string, string>>;
8
+ prefetchQueryMappings?: (formId: any) => Promise<any>;
9
+ generateQuery?: (...args: any[]) => any;
10
+ formatDashboardFilters?: (cfg: any, dataSource: any, filters: any) => any;
11
+ getUserFieldKind?: (type: any) => string | null;
12
+ /**
13
+ * Optional. Host's column-filter formatter (user name → id, workflow title →
14
+ * id, durations). When absent, a built-in plain-value IN filter is used.
15
+ */
16
+ formatHeaderFilters?: (dataSource: any, columnFilters: Record<string, any[]>) => any[];
17
+ }
18
+ interface ZvolvProviderProps {
19
+ runtime: ZvolvRuntime;
20
+ children: React.ReactNode;
21
+ }
22
+ declare const ZvolvProvider: React.FC<ZvolvProviderProps>;
23
+ declare function useZvolvRuntime(): ZvolvRuntime;
24
+ declare function useZvolvClient(): any;
25
+
26
+ /** Forget the cached user — call on login / logout. */
27
+ declare const resetQueryUser: () => void;
28
+
29
+ /**
30
+ * The real-data runtime, built in. Pass an initialised, logged-in
31
+ * @zestl/zvolv-js-sdk client and every widget queries live Zvolv data — no host
32
+ * utilities required. The query path is ported verbatim from ZAI-Dashboard.
33
+ */
34
+
35
+ interface CreateZvolvRuntimeOptions {
36
+ /** A ZvolvClient after `workspace.init(domain)` and login. A getter works too. */
37
+ client: any | (() => any);
38
+ /** Returns the logged-in user (decrypted). Default: `client.auth.userInstance`. */
39
+ readUser?: () => any;
40
+ }
41
+ declare function createZvolvRuntime({ client, readUser }: CreateZvolvRuntimeOptions): ZvolvRuntime;
42
+
43
+ /**
44
+ * A fake runtime for local development and design work.
45
+ *
46
+ * Use this to build and preview dashboards without a backend or login. Swap in
47
+ * the real adapter when you want live data — the widget code does not change.
48
+ *
49
+ * The mock honours the filter clauses and sort a real query would carry
50
+ * (dashboard filters, widget filters, column filters, search, sort), applied to
51
+ * its in-memory rows, so interactive controls visibly work in previews.
52
+ * It does NOT aggregate pivots: every widget receives the raw rows.
53
+ */
54
+
55
+ interface MockRuntimeOptions {
56
+ /** Rows every widget receives. Default: a small generic sample. */
57
+ rows?: any[];
58
+ /** Artificial latency in ms, to exercise loading states. */
59
+ delay?: number;
60
+ /** Called with every generated mock query — handy for asserting what was sent. */
61
+ onQuery?: (query: MockQuery) => void;
62
+ }
63
+ /** What the mock's generateQuery produces and its elasticSearch consumes. */
64
+ interface MockQuery {
65
+ filters: any[];
66
+ dashboardSort: Record<string, string> | null;
67
+ columns: any[];
68
+ limit: number | null;
69
+ }
70
+ declare const SAMPLE_ROWS: ({
71
+ id: number;
72
+ region: string;
73
+ owner: string;
74
+ revenue: number;
75
+ target: number;
76
+ orders: number;
77
+ status: string;
78
+ startDate: string;
79
+ endDate: string;
80
+ latitude: number;
81
+ longitude: number;
82
+ parentId: null;
83
+ } | {
84
+ id: number;
85
+ region: string;
86
+ owner: string;
87
+ revenue: number;
88
+ target: number;
89
+ orders: number;
90
+ status: string;
91
+ startDate: string;
92
+ endDate: string;
93
+ latitude: number;
94
+ longitude: number;
95
+ parentId: number;
96
+ })[];
97
+ declare function createMockRuntime(options?: MockRuntimeOptions): ZvolvRuntime;
98
+
99
+ /**
100
+ * Design tokens. This is the contract Claude's design pass writes to.
101
+ * Every visual decision a widget makes resolves through these values —
102
+ * no colour, font or spacing literal should appear in a template.
103
+ */
104
+ interface WidgetChrome {
105
+ appearance: "shadow" | "border" | "flat";
106
+ padding: string;
107
+ borderRadius: string;
108
+ borderWidth: string;
109
+ borderColor: string;
110
+ backgroundColor: string;
111
+ shadow: string;
112
+ hoverLift: boolean;
113
+ gap: string;
114
+ }
115
+ interface ZvolvTokens {
116
+ fontFamily: string;
117
+ monoFontFamily: string;
118
+ colors: {
119
+ background: string;
120
+ surface: string;
121
+ cardBackground: string;
122
+ textPrimary: string;
123
+ textSecondary: string;
124
+ textTertiary: string;
125
+ primary: string;
126
+ primaryLight: string;
127
+ border: string;
128
+ success: string;
129
+ error: string;
130
+ warning: string;
131
+ info: string;
132
+ onAccent: string;
133
+ charts: {
134
+ palette: string[];
135
+ grid: string;
136
+ axis: string;
137
+ neutral: string;
138
+ };
139
+ };
140
+ typography: {
141
+ title: {
142
+ fontSize: string;
143
+ fontWeight: number;
144
+ letterSpacing: string;
145
+ color?: string;
146
+ };
147
+ description: {
148
+ fontSize: string;
149
+ color?: string;
150
+ };
151
+ kpiValue: {
152
+ fontSize: string;
153
+ fontWeight: number;
154
+ letterSpacing: string;
155
+ };
156
+ kpiLabel: {
157
+ fontSize: string;
158
+ fontWeight: number;
159
+ textTransform: string;
160
+ letterSpacing: string;
161
+ };
162
+ body: {
163
+ fontSize: string;
164
+ lineHeight: string;
165
+ };
166
+ caption: {
167
+ fontSize: string;
168
+ };
169
+ };
170
+ /** Shared visual language for data-dense widgets. */
171
+ surfaces: {
172
+ /** Zebra / header / hover bands for tables, pivots and grids. */
173
+ table: {
174
+ headerBg: string;
175
+ rowBg: string;
176
+ altRowBg: string;
177
+ hoverBg: string;
178
+ borderColor: string;
179
+ };
180
+ /** Pills, chips and status badges. */
181
+ badge: {
182
+ radius: string;
183
+ paddingX: string;
184
+ paddingY: string;
185
+ fontSize: string;
186
+ fontWeight: number;
187
+ };
188
+ /** Card-like children inside a widget (list items, gallery tiles, steps). */
189
+ tile: {
190
+ bg: string;
191
+ radius: string;
192
+ padding: string;
193
+ borderColor: string;
194
+ gap: string;
195
+ };
196
+ /** Calendar / scheduler / gantt canvases. */
197
+ canvas: {
198
+ bg: string;
199
+ gridLine: string;
200
+ todayBg: string;
201
+ nowLine: string;
202
+ eventRadius: string;
203
+ };
204
+ };
205
+ widget: WidgetChrome;
206
+ /** Per-widget-type chrome overrides, keyed by widget type (case-insensitive). */
207
+ overrides?: Record<string, Partial<WidgetChrome>>;
208
+ /**
209
+ * Theme-level default `template` and config per widget type. Layered UNDER a
210
+ * widget's own config, so existing dashboards are never overridden.
211
+ */
212
+ widgetDefaults?: Record<string, {
213
+ template?: string;
214
+ [k: string]: any;
215
+ }>;
216
+ }
217
+ declare const defaultTokens: ZvolvTokens;
218
+ /** Deep-merges a partial design spec onto the defaults. Arrays replace wholesale. */
219
+ declare function mergeTokens(base: ZvolvTokens, patch?: DeepPartial<ZvolvTokens>): ZvolvTokens;
220
+ type DeepPartial<T> = {
221
+ [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
222
+ };
223
+ /** Resolves final chrome for a widget: base ← type override ← per-widget config.style. */
224
+ declare function resolveChrome(tokens: ZvolvTokens, widgetType?: string, perWidget?: Partial<WidgetChrome> | null): WidgetChrome;
225
+ /** Theme-level default config for a widget type, layered UNDER the widget's own config. */
226
+ declare function resolveWidgetDefaults(tokens: ZvolvTokens, widgetType: string | undefined, config: any): any;
227
+
228
+ interface ZvolvThemeProviderProps {
229
+ /** A partial design spec — deep-merged onto the defaults. This is Claude's design output. */
230
+ tokens?: DeepPartial<ZvolvTokens>;
231
+ children: React.ReactNode;
232
+ }
233
+ declare const ZvolvThemeProvider: React.FC<ZvolvThemeProviderProps>;
234
+ declare function useTokens(): ZvolvTokens;
235
+
236
+ type KpiTemplateId = "standard" | "trend" | "comparison" | "progress" | "financial" | "status" | "chart" | "hero_chart" | "icon";
237
+ type BadgeTone = "success" | "warning" | "error" | "info" | "neutral";
238
+ /**
239
+ * View-model for a single resolved KPI item.
240
+ *
241
+ * Templates are PURELY PRESENTATIONAL and must never re-derive values from `raw`.
242
+ * Everything a template needs to render is already resolved here.
243
+ */
244
+ interface KpiContentVM {
245
+ template: KpiTemplateId;
246
+ title: string;
247
+ subtitle: string;
248
+ value: string | number;
249
+ rawValue: number | null;
250
+ prefix: string;
251
+ suffix: string;
252
+ target: string | number;
253
+ rawTarget: number | null;
254
+ valueColor?: string;
255
+ icon: string | null;
256
+ iconColor: string;
257
+ iconSize: string;
258
+ textAlign: string;
259
+ iconAlign: string;
260
+ isLast: boolean;
261
+ delta?: {
262
+ value: number;
263
+ mode: "percent" | "absolute";
264
+ isPositive: boolean;
265
+ };
266
+ progress?: {
267
+ ratio: number;
268
+ max: number;
269
+ };
270
+ status?: {
271
+ label: string;
272
+ tone: BadgeTone;
273
+ description?: string;
274
+ };
275
+ series?: number[];
276
+ raw: any;
277
+ config: any;
278
+ }
279
+ /** Props every KPI template component receives. */
280
+ interface KpiTemplateProps {
281
+ vm: KpiContentVM;
282
+ index: number;
283
+ }
284
+
285
+ /** Anything Claude can override, keyed by "WIDGET_TYPE:templateId". */
286
+ type TemplateComponent = React.FC<any>;
287
+ type TemplateMap = Record<string, TemplateComponent>;
288
+ interface TemplateProviderProps {
289
+ /**
290
+ * Claude's UI layer. Keys are "WIDGET_TYPE:templateId", e.g.
291
+ * { "KPI_CARD:standard": MyKpiCard, "BAR_CHART:standard": MyBars }
292
+ * Any key not supplied falls back to the package's built-in template.
293
+ */
294
+ templates?: TemplateMap;
295
+ children: React.ReactNode;
296
+ }
297
+ declare const TemplateProvider: React.FC<TemplateProviderProps>;
298
+ declare function useTemplateOverride(widgetType: string, templateId: string): TemplateComponent | null;
299
+
300
+ declare const Label: React.FC<{
301
+ children: React.ReactNode;
302
+ }>;
303
+ declare const Value: React.FC<{
304
+ vm: KpiTemplateProps["vm"];
305
+ mono?: boolean;
306
+ }>;
307
+ declare const Delta: React.FC<{
308
+ vm: KpiTemplateProps["vm"];
309
+ }>;
310
+ declare const Sparkline: React.FC<{
311
+ series: number[];
312
+ color: string;
313
+ height?: number;
314
+ }>;
315
+ declare const KPI_DEFAULT_TEMPLATES: {
316
+ standard: React.FC<KpiTemplateProps>;
317
+ trend: React.FC<KpiTemplateProps>;
318
+ comparison: React.FC<KpiTemplateProps>;
319
+ progress: React.FC<KpiTemplateProps>;
320
+ financial: React.FC<KpiTemplateProps>;
321
+ status: React.FC<KpiTemplateProps>;
322
+ chart: React.FC<KpiTemplateProps>;
323
+ hero_chart: React.FC<KpiTemplateProps>;
324
+ icon: React.FC<KpiTemplateProps>;
325
+ };
326
+
327
+ type WidgetTypeId = "KPI_CARD" | "BAR_CHART" | "LINE_CHART" | "PIE_CHART" | "TABLE";
328
+ interface ZvolvDataSource {
329
+ formId?: string | number;
330
+ isTask?: boolean;
331
+ newFormFramework?: boolean;
332
+ fields?: any[];
333
+ pivot?: {
334
+ rows?: any[];
335
+ summary?: any[];
336
+ postOperations?: any[];
337
+ [k: string]: any;
338
+ };
339
+ automation?: {
340
+ automationId?: string | number;
341
+ enabled?: boolean;
342
+ [k: string]: any;
343
+ };
344
+ [k: string]: any;
345
+ }
346
+ interface SeriesConfig {
347
+ name?: string;
348
+ valueField: string;
349
+ argumentField: string;
350
+ color?: string;
351
+ formatting?: any[];
352
+ [k: string]: any;
353
+ }
354
+ interface WidgetConfigurations {
355
+ template?: string;
356
+ description?: string;
357
+ series?: SeriesConfig[];
358
+ legends?: {
359
+ showLabels?: boolean;
360
+ position?: string;
361
+ [k: string]: any;
362
+ };
363
+ axis?: {
364
+ argumentAxis?: any;
365
+ valueAxis?: any;
366
+ [k: string]: any;
367
+ };
368
+ sortOrder?: "none" | "asc" | "desc";
369
+ stackOrder?: "none" | "asc" | "desc";
370
+ contents?: any[];
371
+ style?: WidgetStyleOverrides | null;
372
+ [k: string]: any;
373
+ }
374
+ interface WidgetStyleOverrides {
375
+ appearance?: "shadow" | "border" | "flat";
376
+ padding?: string;
377
+ borderRadius?: string;
378
+ borderWidth?: string;
379
+ borderColor?: string;
380
+ borderTopWidth?: string;
381
+ borderTopColor?: string;
382
+ backgroundColor?: string;
383
+ hideScrollbar?: boolean;
384
+ hoverLift?: boolean;
385
+ titleFontSize?: string;
386
+ titleFontWeight?: number;
387
+ titleColor?: string;
388
+ }
389
+ type WidgetState = "loading" | "ready" | "empty" | "unconfigured" | "error";
390
+ interface WidgetDataResult<TRow = any> {
391
+ /** Rows to render — after local search / column filters / sort / widget filters. */
392
+ rows: TRow[];
393
+ /** Rows as fetched, before local interactions. Use for column-filter options. */
394
+ sourceRows: TRow[];
395
+ state: WidgetState;
396
+ loading: boolean;
397
+ initialLoading: boolean;
398
+ error: Error | null;
399
+ refresh: () => void;
400
+ meta: {
401
+ xKey: string;
402
+ series: SeriesConfig[];
403
+ template: string;
404
+ userLabels: Record<string, string>;
405
+ toLabel: (value: any) => any;
406
+ /** Where search / column filters / sort run for this widget. */
407
+ tableMode: "remote" | "local";
408
+ /** Where widget-level filters run for this widget. */
409
+ filterMode: "remote" | "local";
410
+ /** True when any search / filter is applied (drives the "no matches" message). */
411
+ filtered: boolean;
412
+ };
413
+ }
414
+
415
+ interface WidgetShellProps {
416
+ widgetType?: string;
417
+ title?: string;
418
+ description?: string;
419
+ state: WidgetState;
420
+ error?: Error | null;
421
+ /** Message shown when the widget has no data source configured. */
422
+ unconfiguredMessage?: string;
423
+ /** Message shown when the widget IS wired but returned zero rows. */
424
+ emptyMessage?: string;
425
+ /** Header controls (search, filters, buttons), right-aligned next to the title. */
426
+ actions?: React.ReactNode;
427
+ /** A refetch is in flight while rows stay on screen; the body dims slightly. */
428
+ busy?: boolean;
429
+ /** A search / filter is applied — an empty result then reads "no matches". */
430
+ filtered?: boolean;
431
+ style?: React.CSSProperties;
432
+ className?: string;
433
+ children: React.ReactNode;
434
+ }
435
+ /** What a host needs to draw a non-ready widget state in its own style. */
436
+ interface WidgetStateRenderArgs {
437
+ state: Exclude<WidgetState, "ready">;
438
+ widgetType?: string;
439
+ /** The message the library would show (defaults or the widget's overrides). */
440
+ message: string;
441
+ error?: Error | null;
442
+ filtered: boolean;
443
+ }
444
+ /**
445
+ * Supply one renderer for loading / unconfigured / empty / error across every
446
+ * widget: `<WidgetStateSlot.Provider value={(a) => <MyState {...a} />}>`.
447
+ * Return `undefined` to fall back to the built-in text.
448
+ */
449
+ declare const WidgetStateSlot: React.Context<((args: WidgetStateRenderArgs) => React.ReactNode) | null>;
450
+ /**
451
+ * Chrome + state handling shared by every widget: card frame, header, and the
452
+ * loading / unconfigured / empty / error states.
453
+ *
454
+ * `unconfigured` (no data source wired) and `empty` (wired, zero rows) are
455
+ * deliberately distinct — collapsing them hides real configuration mistakes.
456
+ */
457
+ declare const WidgetShell: React.FC<WidgetShellProps>;
458
+
459
+ /** Heuristic: a plain number in the ~2000–2100 ms-epoch band is a timestamp, not a value. */
460
+ declare function isLikelyTimestamp(v: any): boolean;
461
+ type DateGapUnit = "day" | "week" | "month";
462
+ interface FillDateGapsArgs {
463
+ rows: any[];
464
+ xKey: string;
465
+ series: {
466
+ valueField: string;
467
+ }[];
468
+ unit: DateGapUnit;
469
+ range: {
470
+ start: dayjs.Dayjs;
471
+ end: dayjs.Dayjs;
472
+ } | null;
473
+ }
474
+ /**
475
+ * Inserts zero rows for periods with no data so a time axis reads continuously.
476
+ *
477
+ * Keying by each period's start date (rather than a week/month number) avoids
478
+ * needing dayjs's weekOfYear plugin and stays unambiguous across year boundaries.
479
+ */
480
+ declare function fillDateGaps({ rows, xKey, series, unit, range }: FillDateGapsArgs): any[];
481
+ declare function coerceSeriesNumbers(rows: any[], series: {
482
+ valueField: string;
483
+ }[]): any[];
484
+
485
+ /**
486
+ * DataSource authoring — how a widget says WHERE its data comes from.
487
+ *
488
+ * `configurations` describes how a widget LOOKS and which fields it plots.
489
+ * `dataSource` describes WHAT is queried: the form, its fields, and any pivot
490
+ * (group-by + aggregate). The query generator reads `dataSource`, not `configurations`.
491
+ *
492
+ * Every builder here produces the exact object shape the server and the query
493
+ * generator expect. Prefer them over hand-writing the literals.
494
+ */
495
+ /** Zvolv form element types, as `masterFieldType`. */
496
+ type MasterFieldType = "INPUT_TEXT" | "INPUT_TEXTAREA" | "INPUT_NUMBER" | "INPUT_CURRENCY" | "INPUT_PERCENT" | "INPUT_FORMULA" | "INPUT_AUTONUMBER" | "INPUT_DATE" | "INPUT_DATE_RANGE" | "INPUT_TIME" | "INPUT_TIMER" | "CHECK_BOX" | "RADIO_BUTTON" | "DROP_DOWN" | "INPUT_TAG" | "FORM_SEARCH" | "INPUT_SEARCH" | "AUTO_COMPLETE" | "EXTERNAL_API" | "RATING_BAR" | "PROGRESS_BAR" | "UPLOAD_FILE_IMAGE" | "FILE_UPLOAD_V2" | "INPUT_SHEET";
497
+ /** Elasticsearch-side data type, derived from the element type. */
498
+ type MasterFieldDataType = "STRING" | "INT" | "FLOAT" | "BOOLEAN" | "ARRAY" | "OBJECT";
499
+ /**
500
+ * Mirrors the app's getDataType(): maps a form element type to its ES data type.
501
+ * Wrong values here produce empty aggregations, so always derive rather than guess.
502
+ */
503
+ declare function getDataType(elementType: string): MasterFieldDataType;
504
+ type FilterOperator = "EQUALS" | "NOT_IN" | "IN" | "IN_UG" | "CONTAINS" | "STARTS_WITH" | "GREATER_THAN" | "LESS_THAN" | "BETWEEN" | "EMPTY" | "NOT_EMPTY" | "DATE_IS" | "MULTIPLE" | "_ALL";
505
+ interface FieldFilter {
506
+ operator: FilterOperator;
507
+ /** Values. Date fields accept date-math tokens like `{@[TODAY]}`. */
508
+ operand: any[];
509
+ }
510
+ /**
511
+ * One queryable field. `header` is the name rows come back under — it is what a
512
+ * series' `valueField` / `argumentField` and a pivot's `title` must match.
513
+ */
514
+ interface DataSourceField {
515
+ /** Output name in the returned rows. Series and pivots reference THIS. */
516
+ header: string;
517
+ /** Server-side field name. For task fields, the camelCase form. */
518
+ masterfield?: string;
519
+ masterFieldType?: MasterFieldType | string;
520
+ masterFieldDataType?: MasterFieldDataType;
521
+ /** Form element id, when known. */
522
+ id?: string | number;
523
+ formID?: string | number;
524
+ /** True for built-in task fields (status, priority, assignee…). */
525
+ isTaskField?: boolean;
526
+ taskfield?: string;
527
+ sortOrder?: "asc" | "desc";
528
+ filter?: FieldFilter;
529
+ formula?: any[];
530
+ }
531
+ interface PivotRow {
532
+ /** Output column name. Must match the series `argumentField`. */
533
+ title: string;
534
+ masterField: string;
535
+ masterFieldType?: string;
536
+ masterFieldDataType?: MasterFieldDataType;
537
+ }
538
+ type AggregationType = "sum" | "avg" | "min" | "max" | "count" | "value_count" | "cardinality";
539
+ interface PivotSummary {
540
+ title: string;
541
+ masterField: string;
542
+ masterFieldType?: string;
543
+ masterFieldDataType?: MasterFieldDataType;
544
+ /** Output name of the aggregated value. Must match the series `valueField`. */
545
+ value: string;
546
+ type: AggregationType;
547
+ }
548
+ interface PivotFilter {
549
+ field: string;
550
+ operand: string;
551
+ masterField: string;
552
+ masterFieldType?: string;
553
+ masterFieldDataType?: MasterFieldDataType;
554
+ operator: FilterOperator;
555
+ value: any[];
556
+ }
557
+ type PostOperator = "ADD" | "SUB" | "MUL" | "DIV" | "PERCENT";
558
+ interface PostOperation {
559
+ /** Output name of the derived value. A series may plot it. */
560
+ title: string;
561
+ operator: PostOperator;
562
+ /** Names of OTHER summary entries, by their `value`. Order matters for SUB/DIV. */
563
+ operands: string[];
564
+ }
565
+ interface PivotConfig {
566
+ rows?: PivotRow[];
567
+ columns?: PivotRow[];
568
+ summary?: PivotSummary[];
569
+ filters?: PivotFilter[];
570
+ postOperations?: PostOperation[];
571
+ }
572
+ interface DataSourceDefinition {
573
+ formId?: string | number;
574
+ /** Set for form-backed sources. Omit only for legacy widget-id sources. */
575
+ newFormFramework?: boolean;
576
+ /** True to query the tasks index instead of a form's submissions. */
577
+ isTask?: boolean;
578
+ fields?: DataSourceField[];
579
+ pivot?: PivotConfig;
580
+ /** Max rows for pivot aggregations. */
581
+ displayRowLimit?: number | string;
582
+ automation?: {
583
+ automationId: string | number;
584
+ enabled?: boolean;
585
+ };
586
+ [k: string]: any;
587
+ }
588
+ /**
589
+ * Declares a queryable field. `masterFieldDataType` is derived from the element
590
+ * type when not given, which is what aggregations and filters key off.
591
+ */
592
+ declare function field(header: string, masterFieldType: MasterFieldType | string, options?: Partial<DataSourceField>): DataSourceField;
593
+ /**
594
+ * A built-in task field. The server expects these camelCased, so `header`
595
+ * "Status" becomes masterfield "status" automatically.
596
+ */
597
+ declare function taskField(header: string, masterFieldType?: MasterFieldType | string, options?: Partial<DataSourceField>): DataSourceField;
598
+ /** A group-by dimension. `title` is what a series' `argumentField` must match. */
599
+ declare function groupBy(f: DataSourceField, title?: string): PivotRow;
600
+ /**
601
+ * An aggregated metric. `outputName` is what a series' `valueField` must match,
602
+ * and what a postOperation references as an operand.
603
+ */
604
+ declare function aggregate(f: DataSourceField, type?: AggregationType, outputName?: string): PivotSummary;
605
+ /**
606
+ * A value derived from other aggregates, computed after the query returns.
607
+ *
608
+ * Operands name OTHER summaries by their `value`. Operand order matters:
609
+ * SUB is left-to-right, and PERCENT is operands[0] / operands[1] * 100.
610
+ */
611
+ declare function derive(title: string, operator: PostOperator, operands: string[]): PostOperation;
612
+ /** A filter applied to a field at query time. */
613
+ declare function where(operator: FilterOperator, ...operand: any[]): FieldFilter;
614
+ /**
615
+ * Builds a form-backed data source.
616
+ *
617
+ * Every field a widget plots, groups by, or filters on must be listed in
618
+ * `fields` — the query generator builds its field map from this list, so an
619
+ * omitted field silently returns nothing.
620
+ */
621
+ declare function formSource(formId: string | number, fields: DataSourceField[], options?: {
622
+ pivot?: PivotConfig;
623
+ displayRowLimit?: number;
624
+ }): DataSourceDefinition;
625
+ /**
626
+ * Builds a task-backed data source.
627
+ *
628
+ * Task sources query the tasks index and must NOT carry a formId — passing one
629
+ * makes the generator query submissions instead, returning the wrong rows.
630
+ */
631
+ declare function taskSource(fields: DataSourceField[], options?: {
632
+ pivot?: PivotConfig;
633
+ displayRowLimit?: number;
634
+ }): DataSourceDefinition;
635
+ /** Builds a data source whose rows come from an automation rather than a query. */
636
+ declare function automationSource(automationId: string | number, fields?: DataSourceField[]): DataSourceDefinition;
637
+ /** Assembles a pivot. Omit `rows` for a single-number (summary-only) result. */
638
+ declare function pivot(config: PivotConfig): PivotConfig;
639
+
640
+ /**
641
+ * Viewer interactions — search, column filters, sort and widget-level filters.
642
+ *
643
+ * These are the runtime choices a person makes while LOOKING at a widget, as
644
+ * opposed to `dataSource` filters an author bakes in. The UI for each one is
645
+ * supplied by the caller (render slots); this module owns what an applied
646
+ * interaction MEANS for the data:
647
+ *
648
+ * remote — translated into query clauses and sent through generateQuery, so
649
+ * the server filters/sorts the full dataset (form-framework sources).
650
+ * local — applied to the rows already loaded (pivot tables, legacy widget-id
651
+ * sources, automation rows), where the server cannot do it.
652
+ *
653
+ * Mirrors ZAI-Dashboard's DashboardTable (search `_ALL`, header filters,
654
+ * `dashboardSort`) and ZFilters (widget filters) so results match production.
655
+ */
656
+
657
+ type SortDirection = "asc" | "desc";
658
+ /** One active sort. `key` is the column key (the row field name). */
659
+ interface SortState {
660
+ key: string;
661
+ direction: SortDirection;
662
+ }
663
+ /**
664
+ * Column (header) filters: column key → the values the viewer ticked.
665
+ * Include `COLUMN_FILTER_BLANK` ("") to match empty cells.
666
+ */
667
+ type ColumnFilters = Record<string, any[]>;
668
+ /** Value that selects empty cells in a column filter. */
669
+ declare const COLUMN_FILTER_BLANK = "";
670
+ /** Relative-date tokens accepted by the `DATE_IS` operator. */
671
+ type DateToken = "TODAY" | "YESTERDAY" | "LAST_SEVEN_DAYS" | "LAST_THIRTY_DAYS" | "THIS_WEEK" | "THIS_MONTH" | "THIS_YEAR";
672
+ /**
673
+ * One widget-level filter, as the viewer applies it from the widget header.
674
+ *
675
+ * `field` is the field's `header` in `dataSource.fields` (the name rows come
676
+ * back under). Several filters are combined with AND.
677
+ */
678
+ interface WidgetFilter {
679
+ field: string;
680
+ operator: FilterOperator | "DATE_IS";
681
+ /**
682
+ * Scalar or array. `IN`/`NOT_IN` take a list, `BETWEEN` takes `[from, to]`,
683
+ * `DATE_IS` takes a DateToken, `EMPTY`/`NOT_EMPTY` take nothing.
684
+ * User fields (AUTO_COMPLETE, assignees) take user ids, not names.
685
+ */
686
+ value?: any;
687
+ }
688
+ /** Everything a viewer can apply to one widget. */
689
+ interface WidgetInteractionState {
690
+ search: string;
691
+ columnFilters: ColumnFilters;
692
+ sort: SortState | null;
693
+ widgetFilters: WidgetFilter[];
694
+ }
695
+ declare const EMPTY_INTERACTIONS: WidgetInteractionState;
696
+ type InteractionMode = "remote" | "local";
697
+ /**
698
+ * Where search / column filters / sort run.
699
+ *
700
+ * Remote only for form-framework sources WITHOUT pivot rows: a pivot returns
701
+ * aggregated buckets, so searching or sorting the underlying documents would
702
+ * not change what is shown. Same rule as ZAI-Dashboard's `isRemoteSort`.
703
+ */
704
+ declare function resolveTableMode(dataSource: any, widgetType?: string, hasAutomationRows?: boolean): InteractionMode;
705
+ /**
706
+ * Where widget-level filters run. They are query filters, so any form-framework
707
+ * source (pivot or not) filters server-side; only automation rows and legacy
708
+ * widget-id sources fall back to filtering loaded rows.
709
+ */
710
+ declare function resolveFilterMode(dataSource: any, hasAutomationRows?: boolean): InteractionMode;
711
+ declare function hasActiveInteractions(s: Partial<WidgetInteractionState>): boolean;
712
+ /** `[from, to]` (YYYY-MM-DD) for a relative-date token. Mirrors host getDateRange. */
713
+ declare function resolveDateToken(token: string, now?: dayjs.Dayjs): [string, string] | null;
714
+ /** Search → the `_ALL` (or `MULTIPLE` for a date) clause DashboardTable sends. */
715
+ declare function buildSearchClause(search: string): any | null;
716
+ /**
717
+ * Widget filters → generateQuery filter clauses.
718
+ * Unknown fields are skipped with a console warning rather than silently.
719
+ */
720
+ declare function buildWidgetFilterClauses(dataSource: any, filters?: WidgetFilter[]): any[];
721
+ /**
722
+ * Column filters → IN clauses (EMPTY when only blanks are ticked).
723
+ *
724
+ * The host's `formatHeaderFilters` also maps user names → ids, workflow titles →
725
+ * ids and humanized durations. Supply it as `runtime.formatHeaderFilters` for
726
+ * full parity; this built-in covers plain values.
727
+ */
728
+ declare function buildColumnFilterClauses(dataSource: any, columnFilters?: ColumnFilters): any[];
729
+ /**
730
+ * Sort → generateQuery's `dashboardSort` + the `configuration.columns` it needs.
731
+ *
732
+ * generateQuery matches `configuration.columns[].dataPoint` to a field's header
733
+ * and then reads `dashboardSort[column.label]`; with no `columns` it throws.
734
+ * So columns are synthesized from `dataSource.fields` when the config has none.
735
+ */
736
+ declare function buildRemoteSort(config: any, dataSource: any, sort: SortState | null): {
737
+ dashboardSort: Record<string, "ASC" | "DESC"> | null;
738
+ config: any;
739
+ };
740
+ /** Case-insensitive substring search across every cell (and its label). */
741
+ declare function applyLocalSearch(rows: any[], search: string, toLabel?: (v: any) => any): any[];
742
+ /** Keeps rows whose cell matches any ticked value, per column (AND across columns). */
743
+ declare function applyLocalColumnFilters(rows: any[], columnFilters?: ColumnFilters): any[];
744
+ /** Applies widget filters to loaded rows (AND). */
745
+ declare function applyLocalWidgetFilters(rows: any[], filters?: WidgetFilter[]): any[];
746
+ /** Numeric-aware, blanks-last sort. Returns a new array. */
747
+ declare function applyLocalSort(rows: any[], sort: SortState | null): any[];
748
+ /** Distinct values of a column, with counts, for a column-filter dropdown. */
749
+ declare function distinctColumnValues(rows: any[], key: string, toLabel?: (v: any) => any): {
750
+ value: any;
751
+ label: string;
752
+ count: number;
753
+ }[];
754
+
755
+ interface UseWidgetDataArgs {
756
+ widgetId?: string | number;
757
+ widgetType?: string;
758
+ workflowTypeId?: string | number;
759
+ title?: string;
760
+ dataSource?: ZvolvDataSource;
761
+ configurations?: any;
762
+ /** Dashboard-level filter state (URL params / ZFilters payload). */
763
+ dashFilters?: any;
764
+ /** Dashboard date filters (`cdate`). */
765
+ cdateFilters?: any[];
766
+ /**
767
+ * Raw host-format widget filter state (`{ filter, filter_cond }` from ZFilters).
768
+ * Prefer `widgetFilters`; this exists for migrated host code.
769
+ */
770
+ localFilters?: any;
771
+ rowLimit?: number;
772
+ dateGap?: {
773
+ unit: DateGapUnit;
774
+ start?: string;
775
+ end?: string;
776
+ } | null;
777
+ /** Rows supplied by an automation binding; when provided, no query is issued. */
778
+ automationRows?: any[] | null;
779
+ automationLoading?: boolean;
780
+ /** Free-text search across all columns. */
781
+ search?: string;
782
+ /** Column key → ticked values. */
783
+ columnFilters?: ColumnFilters;
784
+ /** Active sort, or null. */
785
+ sort?: SortState | null;
786
+ /** Widget-level filters, AND-ed. */
787
+ widgetFilters?: WidgetFilter[];
788
+ /** Debounce for remote search, ms. Default 400. */
789
+ searchDebounceMs?: number;
790
+ }
791
+ /**
792
+ * Fetches, normalizes and shapes a widget's rows.
793
+ *
794
+ * This owns the whole Zvolv data path — query generation, Elasticsearch, pivot
795
+ * postOperations, summary/series alignment, user-label resolution, date-gap
796
+ * filling, and viewer interactions (search / column filters / sort / widget
797
+ * filters, sent to the server or applied locally per `meta.tableMode` /
798
+ * `meta.filterMode`). It renders nothing: the caller owns the UI.
799
+ */
800
+ declare function useWidgetData(args: UseWidgetDataArgs): WidgetDataResult;
801
+
802
+ /**
803
+ * Value + change props for each viewer interaction.
804
+ *
805
+ * Every interaction works both ways:
806
+ * - uncontrolled — omit the value; pass `default*` to seed it. The widget owns it.
807
+ * - controlled — pass the value AND its `on*Change`. You own it (URL, store…).
808
+ */
809
+ interface InteractionStateProps {
810
+ search?: string;
811
+ defaultSearch?: string;
812
+ onSearchChange?: (search: string) => void;
813
+ columnFilters?: ColumnFilters;
814
+ defaultColumnFilters?: ColumnFilters;
815
+ onColumnFiltersChange?: (columnFilters: ColumnFilters) => void;
816
+ sort?: SortState | null;
817
+ defaultSort?: SortState | null;
818
+ onSortChange?: (sort: SortState | null) => void;
819
+ widgetFilters?: WidgetFilter[];
820
+ defaultWidgetFilters?: WidgetFilter[];
821
+ onWidgetFiltersChange?: (widgetFilters: WidgetFilter[]) => void;
822
+ /** Fires after any interaction changes, with the full next state. */
823
+ onInteractionsChange?: (state: WidgetInteractionState) => void;
824
+ }
825
+ /** The live interaction state plus every setter a UI slot needs. */
826
+ interface WidgetInteractions extends WidgetInteractionState {
827
+ setSearch: (search: string) => void;
828
+ setColumnFilters: (columnFilters: ColumnFilters) => void;
829
+ /** Sets one column's ticked values; an empty array clears that column. */
830
+ setColumnFilter: (key: string, values: any[]) => void;
831
+ setSort: (sort: SortState | null) => void;
832
+ /** Cycles a column: none → asc → desc → none. */
833
+ toggleSort: (key: string) => void;
834
+ sortDirectionFor: (key: string) => SortDirection | null;
835
+ setWidgetFilters: (filters: WidgetFilter[]) => void;
836
+ addWidgetFilter: (filter: WidgetFilter) => void;
837
+ removeWidgetFilter: (index: number) => void;
838
+ /** Clears search, column filters, sort and widget filters. */
839
+ clearAll: () => void;
840
+ /** True when anything is applied. */
841
+ active: boolean;
842
+ }
843
+ /**
844
+ * Headless state for search, column filters, sort and widget filters.
845
+ *
846
+ * Feed the returned values to `useWidgetData` (they are the same prop names)
847
+ * and hand the setters to your own controls. Widgets call this internally;
848
+ * use it directly only when building a widget from `useWidgetData`.
849
+ */
850
+ declare function useWidgetInteractions(props?: InteractionStateProps): WidgetInteractions;
851
+
852
+ /**
853
+ * Interactive widget layer — wires viewer controls (search, widget filters,
854
+ * column filters, sort) to the data path, with the UI supplied by the caller.
855
+ *
856
+ * Each control has a render slot. Pass your own component and the widget hands
857
+ * it the current value and setters; applying a value re-queries (remote) or
858
+ * re-filters loaded rows (local) automatically. Omit a slot and a minimal,
859
+ * token-styled default is used when that control is enabled.
860
+ */
861
+
862
+ /** A field the viewer may filter on, derived from `dataSource.fields`. */
863
+ interface FilterableField {
864
+ /** Pass this as `WidgetFilter.field`. */
865
+ field: string;
866
+ label: string;
867
+ masterFieldType?: string;
868
+ kind: "text" | "number" | "date" | "boolean";
869
+ /** Operators that make sense for this field's type, most useful first. */
870
+ operators: string[];
871
+ }
872
+ interface SearchSlotArgs {
873
+ value: string;
874
+ setValue: (value: string) => void;
875
+ clear: () => void;
876
+ placeholder: string;
877
+ /** "remote" = server-side search (debounced); "local" = filters loaded rows. */
878
+ mode: "remote" | "local";
879
+ loading: boolean;
880
+ tokens: ZvolvTokens;
881
+ }
882
+ interface WidgetFilterSlotArgs {
883
+ filters: WidgetFilter[];
884
+ setFilters: (filters: WidgetFilter[]) => void;
885
+ addFilter: (filter: WidgetFilter) => void;
886
+ removeFilter: (index: number) => void;
887
+ clear: () => void;
888
+ /** Fields that can be filtered, with valid operators per field. */
889
+ fields: FilterableField[];
890
+ /** The host's declared filter list (`config.filters`), when present. */
891
+ declared: any[];
892
+ mode: "remote" | "local";
893
+ tokens: ZvolvTokens;
894
+ }
895
+ interface ColumnFilterSlotArgs {
896
+ column: {
897
+ key: string;
898
+ header: string;
899
+ kind?: string;
900
+ };
901
+ selected: any[];
902
+ setSelected: (values: any[]) => void;
903
+ clear: () => void;
904
+ /** Distinct values seen in this column. `value` is what goes in `selected`. */
905
+ options: {
906
+ value: any;
907
+ label: string;
908
+ count: number;
909
+ }[];
910
+ mode: "remote" | "local";
911
+ tokens: ZvolvTokens;
912
+ }
913
+ interface SortSlotArgs {
914
+ column: {
915
+ key: string;
916
+ header: string;
917
+ kind?: string;
918
+ };
919
+ direction: SortDirection | null;
920
+ /** none → asc → desc → none */
921
+ toggle: () => void;
922
+ setDirection: (direction: SortDirection | null) => void;
923
+ tokens: ZvolvTokens;
924
+ }
925
+ interface ToolbarSlotArgs {
926
+ /** The resolved search control (slot or default), or null when disabled. */
927
+ search: React.ReactNode;
928
+ /** The resolved widget-filter control (slot or default), or null when disabled. */
929
+ widgetFilter: React.ReactNode;
930
+ interactions: WidgetInteractions;
931
+ tokens: ZvolvTokens;
932
+ }
933
+ /** UI props shared by every data widget. */
934
+ interface InteractionUiProps {
935
+ /** Show the search box. Default: `config.showSearchbar` / `config.styling.showSearchbar`. */
936
+ showSearch?: boolean;
937
+ /** Show the widget-level filter control. Default: `config.showWidgetFilter`, or on when a slot is passed. */
938
+ showWidgetFilter?: boolean;
939
+ /** Tables only. Show per-column filters. Default: `config.showColumnFilter` / `config.styling.showColumnFilter`. */
940
+ showColumnFilter?: boolean;
941
+ /** Tables only. Click a header to sort. Default: true (`config.enableSort === false` turns it off). */
942
+ enableSort?: boolean;
943
+ searchPlaceholder?: string;
944
+ renderSearch?: (args: SearchSlotArgs) => React.ReactNode;
945
+ renderWidgetFilter?: (args: WidgetFilterSlotArgs) => React.ReactNode;
946
+ /** Tables only. Rendered in each filterable header cell. */
947
+ renderColumnFilter?: (args: ColumnFilterSlotArgs) => React.ReactNode;
948
+ /** Tables only. Rendered in each sortable header cell. */
949
+ renderSortIndicator?: (args: SortSlotArgs) => React.ReactNode;
950
+ /** Replaces the whole header toolbar; receives the resolved controls to place. */
951
+ renderToolbar?: (args: ToolbarSlotArgs) => React.ReactNode;
952
+ }
953
+ type InteractionProps = InteractionStateProps & InteractionUiProps;
954
+ /** Props every data widget accepts: data args + interaction state + UI slots. */
955
+ type InteractiveWidgetProps = UseWidgetDataArgs & InteractionProps;
956
+ declare function fieldKind(masterFieldType?: string, dataType?: string): FilterableField["kind"];
957
+ declare function operatorsForKind(kind: FilterableField["kind"]): string[];
958
+ /** Every field in `dataSource.fields` as a filterable field. */
959
+ declare function filterableFields(dataSource: any): FilterableField[];
960
+ declare function describeWidgetFilter(f: WidgetFilter): string;
961
+ interface InteractiveWidgetData {
962
+ data: WidgetDataResult;
963
+ interactions: WidgetInteractions;
964
+ config: any;
965
+ tokens: ZvolvTokens;
966
+ /** Header toolbar node — pass to `<WidgetShell actions={toolbar}>`. */
967
+ toolbar: React.ReactNode;
968
+ /** Extra WidgetShell props (busy / filtered). Spread onto the shell. */
969
+ shell: {
970
+ busy: boolean;
971
+ filtered: boolean;
972
+ };
973
+ flags: {
974
+ showSearch: boolean;
975
+ showWidgetFilter: boolean;
976
+ showColumnFilter: boolean;
977
+ enableSort: boolean;
978
+ };
979
+ /** Column-filter options: values seen so far plus currently ticked ones. */
980
+ getColumnOptions: (key: string) => {
981
+ value: any;
982
+ label: string;
983
+ count: number;
984
+ }[];
985
+ /** Header controls (sort indicator + column filter) for one column. Tables use this. */
986
+ headerControls: (column: {
987
+ key: string;
988
+ header: string;
989
+ kind?: string;
990
+ }) => React.ReactNode;
991
+ ui: InteractionUiProps;
992
+ }
993
+ /**
994
+ * Resolves data + interactions + toolbar for one widget. Widgets call this in
995
+ * place of `useWidgetData`; custom widgets may too.
996
+ */
997
+ declare function useInteractiveWidgetData(props: InteractiveWidgetProps & {
998
+ widgetType: string;
999
+ }, options?: {
1000
+ table?: boolean;
1001
+ }): InteractiveWidgetData;
1002
+
1003
+ interface KpiWidgetProps extends Omit<InteractiveWidgetProps, "widgetType"> {
1004
+ title?: string;
1005
+ description?: string;
1006
+ emptyMessage?: string;
1007
+ unconfiguredMessage?: string;
1008
+ className?: string;
1009
+ style?: React.CSSProperties;
1010
+ onItemClick?: (vm: any, index: number) => void;
1011
+ }
1012
+ declare const KpiWidget: React.FC<KpiWidgetProps>;
1013
+
1014
+ interface ChartRenderArgs {
1015
+ rows: any[];
1016
+ xKey: string;
1017
+ series: SeriesConfig[];
1018
+ /** Palette colour for series index i, honouring an explicit series.color. */
1019
+ colorFor: (index: number, series?: SeriesConfig) => string;
1020
+ /** Maps an axis value through resolved user labels. */
1021
+ toLabel: (value: any) => any;
1022
+ template: string;
1023
+ config: any;
1024
+ tokens: ReturnType<typeof useTokens>;
1025
+ meta: WidgetDataResult["meta"];
1026
+ }
1027
+ interface ChartWidgetProps extends Omit<InteractiveWidgetProps, "widgetType"> {
1028
+ widgetType: string;
1029
+ title?: string;
1030
+ description?: string;
1031
+ emptyMessage?: string;
1032
+ unconfiguredMessage?: string;
1033
+ className?: string;
1034
+ style?: React.CSSProperties;
1035
+ /**
1036
+ * Claude's UI. Receives fully-resolved rows + axis keys + palette and returns
1037
+ * the chart. When omitted, a registered template override is used; if there is
1038
+ * none either, the widget renders a minimal built-in fallback.
1039
+ */
1040
+ render?: (args: ChartRenderArgs) => React.ReactNode;
1041
+ children?: (args: ChartRenderArgs) => React.ReactNode;
1042
+ }
1043
+ /**
1044
+ * Data-complete chart container. It resolves the Zvolv query, rows, series,
1045
+ * axis key, palette and user labels, then hands them to a renderer. It draws
1046
+ * no marks itself — the visual layer is entirely the caller's.
1047
+ */
1048
+ declare const ChartWidget: React.FC<ChartWidgetProps>;
1049
+
1050
+ type ChartProps = Omit<ChartWidgetProps, "widgetType">;
1051
+ /**
1052
+ * Cartesian + categorical charts. Each is ChartWidget with its type bound, so a
1053
+ * `render` prop or a registered template override supplies all the marks.
1054
+ */
1055
+ declare const BarChartWidget: React.FC<ChartProps>;
1056
+ declare const LineChartWidget: React.FC<ChartProps>;
1057
+ declare const AreaChartWidget: React.FC<ChartProps>;
1058
+ declare const PieChartWidget: React.FC<ChartProps>;
1059
+ declare const DoughnutChartWidget: React.FC<ChartProps>;
1060
+ declare const ScatterChartWidget: React.FC<ChartProps>;
1061
+ interface RankingRow {
1062
+ rank: number;
1063
+ label: any;
1064
+ value: number;
1065
+ /** value / max, clamped 0..1 — for bar widths. */
1066
+ ratio: number;
1067
+ raw: any;
1068
+ }
1069
+ interface RankingRenderArgs extends Omit<ChartRenderArgs, "rows"> {
1070
+ rows: RankingRow[];
1071
+ max: number;
1072
+ }
1073
+ interface RankingBarWidgetProps extends Omit<InteractiveWidgetProps, "widgetType"> {
1074
+ title?: string;
1075
+ description?: string;
1076
+ emptyMessage?: string;
1077
+ unconfiguredMessage?: string;
1078
+ className?: string;
1079
+ style?: React.CSSProperties;
1080
+ render?: (args: RankingRenderArgs) => React.ReactNode;
1081
+ }
1082
+ /**
1083
+ * Ranked list of categories. Sorting, ranking and ratio math happen here; the
1084
+ * caller renders. `config.ranking` supplies { limit, order, labelField, valueField }.
1085
+ */
1086
+ declare const RankingBarWidget: React.FC<RankingBarWidgetProps>;
1087
+ interface GaugeRenderArgs {
1088
+ value: number;
1089
+ min: number;
1090
+ max: number;
1091
+ /** (value - min) / (max - min), clamped 0..1. */
1092
+ ratio: number;
1093
+ /** Themed colour for the band the value falls in. */
1094
+ color: string;
1095
+ band: "low" | "medium" | "high";
1096
+ thresholds: {
1097
+ low: number;
1098
+ medium: number;
1099
+ high: number;
1100
+ };
1101
+ config: any;
1102
+ tokens: ReturnType<typeof useTokens>;
1103
+ rows: any[];
1104
+ }
1105
+ interface GaugeMeterWidgetProps extends Omit<InteractiveWidgetProps, "widgetType"> {
1106
+ title?: string;
1107
+ description?: string;
1108
+ emptyMessage?: string;
1109
+ unconfiguredMessage?: string;
1110
+ className?: string;
1111
+ style?: React.CSSProperties;
1112
+ render?: (args: GaugeRenderArgs) => React.ReactNode;
1113
+ }
1114
+ /** Single-value gauge. Band resolution is data logic; the dial is yours. */
1115
+ declare const GaugeMeterWidget: React.FC<GaugeMeterWidgetProps>;
1116
+ interface HeatCell {
1117
+ zone: any;
1118
+ count: number;
1119
+ /** Themed colour for the cell's threshold band. */
1120
+ color: string;
1121
+ band: "low" | "medium" | "high";
1122
+ breakdown: Record<string, any>;
1123
+ raw: any;
1124
+ }
1125
+ interface HeatMapRenderArgs {
1126
+ cells: HeatCell[];
1127
+ grid: {
1128
+ rows: number;
1129
+ cols: number;
1130
+ };
1131
+ config: any;
1132
+ tokens: ReturnType<typeof useTokens>;
1133
+ }
1134
+ interface HeatMapWidgetProps extends Omit<InteractiveWidgetProps, "widgetType"> {
1135
+ title?: string;
1136
+ description?: string;
1137
+ emptyMessage?: string;
1138
+ unconfiguredMessage?: string;
1139
+ className?: string;
1140
+ style?: React.CSSProperties;
1141
+ render?: (args: HeatMapRenderArgs) => React.ReactNode;
1142
+ }
1143
+ /**
1144
+ * Zone/count heat grid. Threshold banding is data logic; cell shape is yours.
1145
+ * `config.heatMap` supplies { grid, thresholds, dataMapping }.
1146
+ */
1147
+ declare const HeatMapWidget: React.FC<HeatMapWidgetProps>;
1148
+
1149
+ type Tone = "success" | "warning" | "error" | "info" | "neutral" | "primary";
1150
+ /** Resolves a semantic tone to its themed colour. Never hardcode a status colour. */
1151
+ declare function toneColor(tokens: ZvolvTokens, tone?: Tone): string;
1152
+ /** A soft background derived from a tone, for pills and highlight bands. */
1153
+ declare function toneSurface(tokens: ZvolvTokens, tone?: Tone, pct?: number): string;
1154
+ /**
1155
+ * Maps a free-text status string onto a tone. Zvolv status vocabularies vary by
1156
+ * workspace, so unknown values fall back to neutral rather than guessing.
1157
+ */
1158
+ declare function statusTone(status: any): Tone;
1159
+
1160
+ /**
1161
+ * One item in a collection widget, with the configured field mapping already
1162
+ * applied. Renderers read these named slots instead of guessing field names.
1163
+ */
1164
+ interface CollectionItem {
1165
+ id: string | number;
1166
+ title: any;
1167
+ subtitle?: any;
1168
+ description?: any;
1169
+ value?: any;
1170
+ image?: string;
1171
+ status?: {
1172
+ label: any;
1173
+ tone: ReturnType<typeof statusTone>;
1174
+ };
1175
+ timestamp?: any;
1176
+ /** Extra configured fields, in config order, for detail rows. */
1177
+ fields: {
1178
+ label: string;
1179
+ value: any;
1180
+ }[];
1181
+ raw: any;
1182
+ }
1183
+ interface CollectionRenderArgs {
1184
+ items: CollectionItem[];
1185
+ template: string;
1186
+ config: any;
1187
+ tokens: ZvolvTokens;
1188
+ toLabel: (v: any) => any;
1189
+ onItemClick?: (item: CollectionItem, index: number) => void;
1190
+ }
1191
+ interface CollectionWidgetProps extends Omit<InteractiveWidgetProps, "widgetType"> {
1192
+ widgetType: string;
1193
+ title?: string;
1194
+ description?: string;
1195
+ emptyMessage?: string;
1196
+ unconfiguredMessage?: string;
1197
+ className?: string;
1198
+ style?: React.CSSProperties;
1199
+ onItemClick?: (item: CollectionItem, index: number) => void;
1200
+ render?: (args: CollectionRenderArgs) => React.ReactNode;
1201
+ }
1202
+ /**
1203
+ * The item mapping for a collection widget, from whichever block its platform
1204
+ * config uses: CARDLIST `<template>Configuration`, `activityfeed`, `banner`,
1205
+ * or a gallery/carousel bound through `series[0]` (image = valueField).
1206
+ */
1207
+ declare function resolveCollectionMapping(config: any, series?: any[]): any;
1208
+ /**
1209
+ * Maps rows to CollectionItems using a config block. Field mapping lives here so
1210
+ * every collection widget resolves the same way and renderers stay presentational.
1211
+ */
1212
+ declare function useCollectionItems(rows: any[], mapping: any): CollectionItem[];
1213
+ /**
1214
+ * Shared container for every list/card/gallery widget. Resolves rows into named
1215
+ * item slots; the visual arrangement is entirely the renderer's.
1216
+ */
1217
+ declare const CollectionWidget: React.FC<CollectionWidgetProps>;
1218
+ type Bound = Omit<CollectionWidgetProps, "widgetType">;
1219
+ declare const CardListWidget: React.FC<Bound>;
1220
+ declare const ActivityFeedWidget: React.FC<Bound>;
1221
+ declare const EntityGalleryWidget: React.FC<Bound>;
1222
+ declare const GridCardWidget: React.FC<Bound>;
1223
+ declare const CarouselWidget: React.FC<Bound>;
1224
+ declare const BannerWidget: React.FC<Bound>;
1225
+
1226
+ interface TableColumn {
1227
+ key: string;
1228
+ header: string;
1229
+ align?: "left" | "right" | "center";
1230
+ width?: number | string;
1231
+ /** Hint for default cell treatment; a custom renderer may ignore it. */
1232
+ kind?: "text" | "number" | "date" | "status" | "user" | "html";
1233
+ }
1234
+ interface CellArgs {
1235
+ value: any;
1236
+ row: any;
1237
+ column: TableColumn;
1238
+ rowIndex: number;
1239
+ tokens: ZvolvTokens;
1240
+ toLabel: (v: any) => any;
1241
+ }
1242
+ interface TableRenderArgs {
1243
+ rows: any[];
1244
+ columns: TableColumn[];
1245
+ toLabel: (v: any) => any;
1246
+ tokens: ZvolvTokens;
1247
+ config: any;
1248
+ /** Default cell content for a column, so a custom renderer can reuse it. */
1249
+ renderCell: (args: CellArgs) => React.ReactNode;
1250
+ onRowClick?: (row: any, index: number) => void;
1251
+ /** Live search / column filter / sort / widget filter state and setters. */
1252
+ interactions: WidgetInteractions;
1253
+ /** Sort indicator + column filter for a header cell (slots or defaults). */
1254
+ headerControls: (column: TableColumn) => React.ReactNode;
1255
+ /** Distinct values for a column-filter dropdown. */
1256
+ getColumnOptions: (key: string) => {
1257
+ value: any;
1258
+ label: string;
1259
+ count: number;
1260
+ }[];
1261
+ /** Whether header sort / column filters are enabled for this table. */
1262
+ enableSort: boolean;
1263
+ showColumnFilter: boolean;
1264
+ /** "remote" = server sorts/filters the full dataset; "local" = loaded rows only. */
1265
+ mode: "remote" | "local";
1266
+ }
1267
+ interface TableWidgetProps extends Omit<InteractiveWidgetProps, "widgetType"> {
1268
+ widgetType?: string;
1269
+ title?: string;
1270
+ description?: string;
1271
+ columns?: TableColumn[];
1272
+ emptyMessage?: string;
1273
+ unconfiguredMessage?: string;
1274
+ className?: string;
1275
+ style?: React.CSSProperties;
1276
+ onRowClick?: (row: any, index: number) => void;
1277
+ /** Replace a single cell's content, keeping the default table chrome. */
1278
+ cell?: (args: CellArgs) => React.ReactNode;
1279
+ /** Replace the entire table body. */
1280
+ render?: (args: TableRenderArgs) => React.ReactNode;
1281
+ }
1282
+ /** Derives columns from explicit props, then config, then the first row's shape. */
1283
+ declare function useTableColumns(explicit: TableColumn[] | undefined, config: any, rows: any[]): TableColumn[];
1284
+ /**
1285
+ * Tabular widgets. Column resolution, field-type mapping and user-label lookup
1286
+ * are data logic; the markup is fully replaceable via `cell` or `render`.
1287
+ */
1288
+ declare const TableWidget: React.FC<TableWidgetProps>;
1289
+ type BoundTable = Omit<TableWidgetProps, "widgetType">;
1290
+ declare const DashboardTableWidget: React.FC<BoundTable>;
1291
+ declare const DatabaseTableWidget: React.FC<BoundTable>;
1292
+ declare const TaskTrackerTableWidget: React.FC<BoundTable>;
1293
+ /**
1294
+ * Child table. The host is responsible for clamping this to the parent body's
1295
+ * visible width — an unclamped child steals the parent's horizontal scroll.
1296
+ */
1297
+ declare const ChildTableWidget: React.FC<BoundTable>;
1298
+ interface PivotRenderArgs extends TableRenderArgs {
1299
+ rowFields: string[];
1300
+ columnFields: string[];
1301
+ valueFields: string[];
1302
+ }
1303
+ interface PivotGridWidgetProps extends Omit<BoundTable, "render"> {
1304
+ render?: (args: PivotRenderArgs) => React.ReactNode;
1305
+ }
1306
+ /**
1307
+ * Pivot grid. The server returns already-pivoted rows, so this resolves the
1308
+ * row/column/value field names and renders them as a table.
1309
+ */
1310
+ declare const PivotGridWidget: React.FC<PivotGridWidgetProps>;
1311
+
1312
+ /** A scheduled item, normalized from whatever field names the config maps. */
1313
+ interface TemporalEvent {
1314
+ id: string | number;
1315
+ title: any;
1316
+ group?: any;
1317
+ start: Date | null;
1318
+ end: Date | null;
1319
+ allDay: boolean;
1320
+ status?: {
1321
+ label: any;
1322
+ tone: Tone;
1323
+ };
1324
+ /** 0..1 progress, when the config maps a progress/percent field. */
1325
+ progress?: number;
1326
+ color?: string;
1327
+ raw: any;
1328
+ }
1329
+ interface TemporalRenderArgs {
1330
+ events: TemporalEvent[];
1331
+ /** Overall [min, max] span of the events, for laying out a track. */
1332
+ range: {
1333
+ start: Date;
1334
+ end: Date;
1335
+ } | null;
1336
+ /** Events grouped by their `group` value, preserving first-seen order. */
1337
+ lanes: {
1338
+ key: string;
1339
+ label: any;
1340
+ events: TemporalEvent[];
1341
+ }[];
1342
+ template: string;
1343
+ config: any;
1344
+ tokens: ZvolvTokens;
1345
+ toLabel: (v: any) => any;
1346
+ onEventClick?: (event: TemporalEvent, index: number) => void;
1347
+ }
1348
+ interface TemporalWidgetProps extends Omit<InteractiveWidgetProps, "widgetType"> {
1349
+ widgetType: string;
1350
+ title?: string;
1351
+ description?: string;
1352
+ emptyMessage?: string;
1353
+ unconfiguredMessage?: string;
1354
+ className?: string;
1355
+ style?: React.CSSProperties;
1356
+ onEventClick?: (event: TemporalEvent, index: number) => void;
1357
+ render?: (args: TemporalRenderArgs) => React.ReactNode;
1358
+ }
1359
+ /**
1360
+ * Normalizes rows into events. Field names come from the config and keep the
1361
+ * zvolv-web spellings (projectTitle/taskTitle/taskStatus/startDate/endDate) so
1362
+ * migrated dashboards map without edits.
1363
+ */
1364
+ declare function useTemporalEvents(rows: any[], mapping: any): TemporalEvent[];
1365
+ /**
1366
+ * Shared container for timeline / gantt / calendar / scheduler widgets. Event
1367
+ * normalization, range and lane grouping are data logic; the canvas is yours.
1368
+ */
1369
+ declare const TemporalWidget: React.FC<TemporalWidgetProps>;
1370
+ type BoundTemporal = Omit<TemporalWidgetProps, "widgetType">;
1371
+ declare const TimelineWidget: React.FC<BoundTemporal>;
1372
+ declare const GanttChartWidget: React.FC<BoundTemporal>;
1373
+ declare const CalendarWidget: React.FC<BoundTemporal>;
1374
+ declare const MeetingSchedulerWidget: React.FC<BoundTemporal>;
1375
+ interface StepItem {
1376
+ index: number;
1377
+ label: any;
1378
+ description?: any;
1379
+ state: "complete" | "current" | "upcoming";
1380
+ status?: {
1381
+ label: any;
1382
+ tone: Tone;
1383
+ };
1384
+ raw: any;
1385
+ }
1386
+ interface StepperRenderArgs {
1387
+ steps: StepItem[];
1388
+ currentIndex: number;
1389
+ template: string;
1390
+ config: any;
1391
+ tokens: ZvolvTokens;
1392
+ onStepClick?: (step: StepItem) => void;
1393
+ }
1394
+ interface StepperWidgetProps extends Omit<InteractiveWidgetProps, "widgetType"> {
1395
+ title?: string;
1396
+ description?: string;
1397
+ emptyMessage?: string;
1398
+ unconfiguredMessage?: string;
1399
+ className?: string;
1400
+ style?: React.CSSProperties;
1401
+ onStepClick?: (step: StepItem) => void;
1402
+ render?: (args: StepperRenderArgs) => React.ReactNode;
1403
+ }
1404
+ /** Process stepper. Config lives under `config.stepper.*`. */
1405
+ declare const StepperWidget: React.FC<StepperWidgetProps>;
1406
+
1407
+ /**
1408
+ * The chrome envelope every Zvolv widget config carries, independent of type.
1409
+ * Mirrors the keys the ZAI-Dashboard widgets read off `parsedConfig`.
1410
+ */
1411
+ interface WidgetChromeConfig {
1412
+ title?: string;
1413
+ description?: string;
1414
+ hideHeader?: boolean;
1415
+ hideTitle?: boolean;
1416
+ showTitle?: boolean;
1417
+ headerIcon?: string;
1418
+ bgColor?: string;
1419
+ color?: string;
1420
+ outlineColor?: string;
1421
+ outlineWidth?: string;
1422
+ showHighlight?: boolean;
1423
+ /** Text shown when the widget is wired but returned no rows. */
1424
+ customMessage?: string;
1425
+ enableFullScreen?: boolean;
1426
+ enableRefreshButtons?: boolean;
1427
+ disableExport?: boolean;
1428
+ style?: WidgetStyleOverrides | null;
1429
+ template?: string;
1430
+ drillDown?: any;
1431
+ drilldown?: any;
1432
+ /** Show the header search box. */
1433
+ showSearchbar?: boolean;
1434
+ /** Show the widget-level filter control. */
1435
+ showWidgetFilter?: boolean;
1436
+ searchPlaceholder?: string;
1437
+ /** Older dashboards nest the toggles here; top-level keys win. */
1438
+ styling?: {
1439
+ showSearchbar?: boolean;
1440
+ showWidgetFilter?: boolean;
1441
+ showColumnFilter?: boolean;
1442
+ [k: string]: any;
1443
+ };
1444
+ }
1445
+ interface ResolvedChromeConfig {
1446
+ title?: string;
1447
+ description?: string;
1448
+ showHeader: boolean;
1449
+ headerIcon?: string;
1450
+ emptyMessage?: string;
1451
+ showFullScreen: boolean;
1452
+ showRefresh: boolean;
1453
+ showExport: boolean;
1454
+ bgColor?: string;
1455
+ accentColor?: string;
1456
+ outlineColor?: string;
1457
+ outlineWidth?: string;
1458
+ showHighlight: boolean;
1459
+ }
1460
+ /**
1461
+ * Normalizes the chrome envelope. `hideHeader`/`hideTitle`/`showTitle` are three
1462
+ * spellings of the same idea across different widget generations — an explicit
1463
+ * hide always wins, and `showTitle === false` also suppresses the header.
1464
+ */
1465
+ declare function resolveChromeConfig(config?: WidgetChromeConfig): ResolvedChromeConfig;
1466
+ /** Drill-down target, however the config spells it. */
1467
+ declare function resolveDrillDown(config?: WidgetChromeConfig): any;
1468
+
1469
+ interface HtmlRenderArgs {
1470
+ /** Template with {{field}} placeholders already substituted from row 0. */
1471
+ html: string;
1472
+ rows: any[];
1473
+ config: any;
1474
+ tokens: ZvolvTokens;
1475
+ }
1476
+ interface HtmlWidgetProps extends Omit<InteractiveWidgetProps, "widgetType"> {
1477
+ widgetType?: string;
1478
+ title?: string;
1479
+ description?: string;
1480
+ emptyMessage?: string;
1481
+ unconfiguredMessage?: string;
1482
+ className?: string;
1483
+ style?: React.CSSProperties;
1484
+ /**
1485
+ * REQUIRED to render markup. The package never calls dangerouslySetInnerHTML —
1486
+ * the host owns sanitization (DOMPurify or equivalent). Without this, the raw
1487
+ * template is shown as text.
1488
+ */
1489
+ render?: (args: HtmlRenderArgs) => React.ReactNode;
1490
+ }
1491
+ /** Substitutes {{field}} / {field} placeholders from a row. */
1492
+ declare function interpolate(template: string, row: any): string;
1493
+ /**
1494
+ * `{{label}}` substitution driven by `config.variables` — ported from the host
1495
+ * HTMLWidget.getViewText (Angular raw-html parity). A variable reads
1496
+ * rows[0][dataPoint]; a falsy value (0, "", null) falls back to defaultValue.
1497
+ */
1498
+ declare function renderHtmlVariables(template: string, rows: any[], variables: any[]): string;
1499
+ declare const HtmlWidget: React.FC<HtmlWidgetProps>;
1500
+ declare const RawHtmlWidget: React.FC<Omit<HtmlWidgetProps, "widgetType">>;
1501
+ interface IframeWidgetProps extends Omit<InteractiveWidgetProps, "widgetType"> {
1502
+ title?: string;
1503
+ description?: string;
1504
+ emptyMessage?: string;
1505
+ unconfiguredMessage?: string;
1506
+ className?: string;
1507
+ style?: React.CSSProperties;
1508
+ render?: (args: {
1509
+ url: string;
1510
+ config: any;
1511
+ tokens: ZvolvTokens;
1512
+ }) => React.ReactNode;
1513
+ }
1514
+ declare const IframeWidget: React.FC<IframeWidgetProps>;
1515
+ interface MapMarker {
1516
+ id: string | number;
1517
+ lat: number;
1518
+ lng: number;
1519
+ label?: any;
1520
+ raw: any;
1521
+ }
1522
+ interface MapRenderArgs {
1523
+ markers: MapMarker[];
1524
+ center: {
1525
+ lat: number;
1526
+ lng: number;
1527
+ } | null;
1528
+ zoom: number;
1529
+ config: any;
1530
+ tokens: ZvolvTokens;
1531
+ }
1532
+ interface MapWidgetProps extends Omit<InteractiveWidgetProps, "widgetType"> {
1533
+ title?: string;
1534
+ description?: string;
1535
+ emptyMessage?: string;
1536
+ unconfiguredMessage?: string;
1537
+ className?: string;
1538
+ style?: React.CSSProperties;
1539
+ /** Required to draw a map — the package does not bundle a maps SDK. */
1540
+ render?: (args: MapRenderArgs) => React.ReactNode;
1541
+ }
1542
+ /** Resolves lat/lng markers from rows. Rendering needs a maps SDK you supply. */
1543
+ declare const GoogleMapWidget: React.FC<MapWidgetProps>;
1544
+ interface ActionItem {
1545
+ id: string | number;
1546
+ label: any;
1547
+ icon?: string;
1548
+ actionType?: string;
1549
+ disabled?: boolean;
1550
+ raw: any;
1551
+ }
1552
+ interface ActionRenderArgs {
1553
+ actions: ActionItem[];
1554
+ config: any;
1555
+ tokens: ZvolvTokens;
1556
+ onAction?: (action: ActionItem) => void;
1557
+ }
1558
+ interface ActionCardWidgetProps extends Omit<InteractiveWidgetProps, "widgetType"> {
1559
+ title?: string;
1560
+ description?: string;
1561
+ emptyMessage?: string;
1562
+ unconfiguredMessage?: string;
1563
+ className?: string;
1564
+ style?: React.CSSProperties;
1565
+ /** The host performs the action (new submission, popup, external link…). */
1566
+ onAction?: (action: ActionItem) => void;
1567
+ render?: (args: ActionRenderArgs) => React.ReactNode;
1568
+ }
1569
+ declare const ActionCardWidget: React.FC<ActionCardWidgetProps>;
1570
+ interface TreeNode {
1571
+ key: string;
1572
+ label: any;
1573
+ children: TreeNode[];
1574
+ depth: number;
1575
+ raw: any;
1576
+ }
1577
+ interface TreeRenderArgs {
1578
+ nodes: TreeNode[];
1579
+ config: any;
1580
+ tokens: ZvolvTokens;
1581
+ onNodeClick?: (node: TreeNode) => void;
1582
+ }
1583
+ interface TreeWidgetProps extends Omit<InteractiveWidgetProps, "widgetType"> {
1584
+ title?: string;
1585
+ description?: string;
1586
+ emptyMessage?: string;
1587
+ unconfiguredMessage?: string;
1588
+ className?: string;
1589
+ style?: React.CSSProperties;
1590
+ onNodeClick?: (node: TreeNode) => void;
1591
+ render?: (args: TreeRenderArgs) => React.ReactNode;
1592
+ }
1593
+ /** Builds a tree from flat parent-keyed rows. Orphans are promoted to roots. */
1594
+ declare function buildTree(rows: any[], idField: string, parentField: string, labelField: string): TreeNode[];
1595
+ declare const TreeWidget: React.FC<TreeWidgetProps>;
1596
+
1597
+ /**
1598
+ * Form schema types — the platform's form definition after normalisation.
1599
+ * Ported from ZAI-Dashboard `src/forms/types.ts` (itself a port of Angular
1600
+ * z-form). Both the v2 camelCase schema and the legacy PascalCase schema
1601
+ * normalise to this one shape.
1602
+ */
1603
+ type FormMode = "NEW" | "EDIT" | "DISABLED" | "NEW_DO_NOT_SUBMIT";
1604
+ interface FormElement {
1605
+ elementId: string;
1606
+ /** Legacy numeric id (FormElementID) — the key legacy submissions use. */
1607
+ id?: string;
1608
+ label: string;
1609
+ /** The stored type. Use `resolveFieldType` for routing (applies subType). */
1610
+ type: string;
1611
+ defaultValue?: any;
1612
+ required: boolean;
1613
+ disabled: boolean;
1614
+ hidden: boolean;
1615
+ unique?: boolean;
1616
+ /** Grid span out of 24 (a stored Width of 50% → 12). */
1617
+ width: number;
1618
+ widthSpecified: boolean;
1619
+ hideLabel: boolean;
1620
+ dataType?: string;
1621
+ properties: Record<string, any>;
1622
+ attributes: Record<string, any>;
1623
+ validations?: any[];
1624
+ dependencies?: any;
1625
+ }
1626
+ interface FormDefinition {
1627
+ /** The id submissions are posted against (24-hex v2 id, or legacy numeric id). */
1628
+ uuid: string;
1629
+ title: string;
1630
+ description?: string;
1631
+ type: string;
1632
+ elements: FormElement[];
1633
+ allowDraft: boolean;
1634
+ configurations: Record<string, any>;
1635
+ hideSubmit: boolean;
1636
+ hideFormTitle: boolean;
1637
+ successMsg: string | null;
1638
+ warningMsg: string | null;
1639
+ }
1640
+ type FormValues = Record<string, any>;
1641
+ type FormErrors = Record<string, string | undefined>;
1642
+ interface FieldOption {
1643
+ label: string;
1644
+ value: any;
1645
+ /** Extra columns pulled from a lookup row (ExtraLabels). */
1646
+ extra?: string[];
1647
+ color?: string;
1648
+ /** The stored shape for relational fields: { view, select, extraLabels }. */
1649
+ raw?: any;
1650
+ }
1651
+ /**
1652
+ * The UI family a field belongs to. A host draws one control per kind; the
1653
+ * library owns everything behind it (value shape, validation, submit format).
1654
+ */
1655
+ type FieldKind = "text" | "textarea" | "email" | "phone" | "url" | "number" | "currency" | "percent" | "select" | "radio" | "checkbox" | "lookup" | "user" | "date" | "time" | "datetime" | "daterange" | "rating" | "slider" | "file" | "signature" | "richtext" | "scan" | "timer" | "location" | "formula" | "display" | "autonumber" | "section" | "container" | "tabs" | "steps" | "matrix" | "table" | "sheet" | "comments" | "action" | "onbehalf" | "trials" | "system" | "unknown";
1656
+
1657
+ /** Types never sent in a submission body. */
1658
+ declare const SUBMISSION_SKIP_TYPES: Set<string>;
1659
+ declare function getEmptyValue(type: string): any;
1660
+ /** `'a|||b'`, scalars and option objects → the {view, select, extraLabels} shape. */
1661
+ declare function toRelational(el: FormElement, raw: any): any;
1662
+ /**
1663
+ * Initial values: explicit defaults win, then a loaded submission value, then
1664
+ * the element's defaultValue / dynamicDefault, then the type's empty value.
1665
+ */
1666
+ declare function buildInitialValues(elements: FormElement[], opts?: {
1667
+ defaults?: FormValues;
1668
+ submission?: FormValues;
1669
+ user?: any;
1670
+ }): FormValues;
1671
+ /** One element's value in the POST/PUT /api/v1/submissions body. */
1672
+ declare function serializeElementValue(el: FormElement, value: any): any;
1673
+ /** Sheet rows → their child submission ids. */
1674
+ declare function rowSubmissionIds(raw: any): string[];
1675
+ /** `elements[]` for POST/PUT /api/v1/submissions. */
1676
+ declare function buildSubmissionElements(elements: FormElement[], values: FormValues): any[];
1677
+ /**
1678
+ * Flat `{ formID, formSubmissionId, <elementId>: value }` body for automation
1679
+ * triggers — intentionally looser than the submission format (Angular parity).
1680
+ */
1681
+ declare function buildTriggerBody(elements: FormElement[], values: FormValues, opts?: {
1682
+ formId?: string;
1683
+ submissionId?: string | null;
1684
+ byLabel?: boolean;
1685
+ }): Record<string, any>;
1686
+ /** Human-readable value, for read-only views and summaries. */
1687
+ declare function formatFieldValue(el: FormElement, value: any): string;
1688
+
1689
+ /**
1690
+ * Form transport — every network call the form engine makes, against the
1691
+ * logged-in @zestl/zvolv-js-sdk client. Endpoints and bodies are ported from
1692
+ * ZAI-Dashboard `formApi.ts` / `FormSearchField.tsx` / `FileUploadField.tsx`.
1693
+ */
1694
+
1695
+ declare const isLegacyId: (id: any) => boolean;
1696
+ declare function fetchForm(client: any, formId: string): Promise<FormDefinition>;
1697
+ /** EDIT / DISABLED: the submission carries its own element list plus values. */
1698
+ declare function fetchSubmission(client: any, submissionId: string): Promise<{
1699
+ form: FormDefinition | null;
1700
+ values: FormValues;
1701
+ }>;
1702
+ interface SubmitOptions {
1703
+ skipAutomation?: boolean;
1704
+ skipValidations?: boolean;
1705
+ parentSubmissionId?: string;
1706
+ }
1707
+ /** Pulls the created submission id out of either API generation's response. */
1708
+ declare function submissionIdOf(res: any): string | null;
1709
+ declare function createSubmission(client: any, form: FormDefinition, elements: FormElement[], values: FormValues, opts?: SubmitOptions): Promise<any>;
1710
+ declare function updateSubmission(client: any, form: FormDefinition, submissionId: string, elements: FormElement[], values: FormValues, opts?: SubmitOptions): Promise<any>;
1711
+ declare function invokeTrigger(client: any, triggerId: string | number, body: Record<string, any>): Promise<any>;
1712
+ /** TRIGGER_AUTOMATION with properties.automationType "ZENO" (zvolv-web onTriggerZeno → invokeNuclioAutomation). */
1713
+ declare function invokeZeno(client: any, automationUuid: string, body: Record<string, any>): Promise<any>;
1714
+ /**
1715
+ * INVOKE_AGENT.
1716
+ * 1. With properties.flowId: POST /api/v1/zwall/agent/invoke/{flowId}/{agentId} — the
1717
+ * zvolv-web / ZAI-Dashboard call (legacy agent flows).
1718
+ * 2. Without a flowId, or when that server has no such flow (it answers
1719
+ * `{ error: true, reply: "Error: '<flowId>'" }`): POST
1720
+ * /api/v1/zwall/v3/agent_manager/agent_flow/{agentId} — how the platform calls
1721
+ * current ZAI agents (zvolv-mcp zagent.call_agent).
1722
+ * Called directly, not through the SDK's workflow.invokeAgent, whose handleRequest
1723
+ * rejects any reply without `error: false` ("Error fetching data").
1724
+ */
1725
+ declare function invokeAgent(client: any, body: any, flowId?: string, agentId?: string): Promise<any>;
1726
+ /** Field map from an agent reply: `{formData}` or wrapped in `response`, possibly JSON-encoded (ZAI extractAgentFormData). */
1727
+ declare function extractAgentFormData(reply: any): Record<string, any> | null;
1728
+ interface UploadedFile {
1729
+ media_name: string;
1730
+ media_type: string;
1731
+ media: string;
1732
+ media_size: number;
1733
+ mediaKey?: string;
1734
+ [k: string]: any;
1735
+ }
1736
+ /** UPLOAD_FILE_IMAGE with a cardID → dbFileUpload; otherwise the SDK's mediaUpload. */
1737
+ declare function uploadFile(client: any, el: FormElement, file: File, zappId?: string): Promise<UploadedFile>;
1738
+ interface LookupConfig {
1739
+ formId: string;
1740
+ viewLabel?: string;
1741
+ selectLabel?: string;
1742
+ searchLabel?: string;
1743
+ extraLabels: string[];
1744
+ staticFilters: any[];
1745
+ dynamicFilters: any[];
1746
+ maxResults: number;
1747
+ operator: "$and" | "$or";
1748
+ loadOnDependency: boolean;
1749
+ colorLabel?: string;
1750
+ }
1751
+ declare function lookupConfigOf(el: FormElement): LookupConfig | null;
1752
+ interface LookupFilter {
1753
+ label: string;
1754
+ value: any;
1755
+ arr_value: any[];
1756
+ operator: "eq" | "in" | "regex";
1757
+ mode?: string;
1758
+ }
1759
+ /** Options from the source form (getSubmissionAll) — eq/in filters re-applied client-side. */
1760
+ declare function fetchLookupOptions(client: any, cfg: LookupConfig, dependency: LookupFilter[], search?: string, maxAgeMs?: number): Promise<FieldOption[]>;
1761
+ declare function clearLookupCache(): void;
1762
+ declare function searchPeople(client: any, el: FormElement, query: string): Promise<FieldOption[]>;
1763
+
1764
+ /**
1765
+ * useZvolvForm — the headless form engine. Zvolv owns loading, values,
1766
+ * show/hide/mandatory rules, formulas, validation, field automations, action
1767
+ * buttons, child sheets and the submit wire format; the host draws every
1768
+ * control from the `FormField` descriptors it returns.
1769
+ */
1770
+
1771
+ interface FormField {
1772
+ id: string;
1773
+ /** Routing type (subType applied), e.g. "INPUT_CURRENCY". */
1774
+ type: string;
1775
+ kind: FieldKind;
1776
+ label: string;
1777
+ hideLabel: boolean;
1778
+ placeholder?: string;
1779
+ /** Help text under the field (attributes.helpMsg / infoMsg). */
1780
+ help?: string;
1781
+ required: boolean;
1782
+ disabled: boolean;
1783
+ hidden: boolean;
1784
+ /** Grid span out of 24. */
1785
+ span: number;
1786
+ value: any;
1787
+ /** Set from the last submit / validate(); cleared when this field's value changes. */
1788
+ error?: string;
1789
+ touched: boolean;
1790
+ /** Static options (SPINNER / RADIO_GROUP / static AUTO_COMPLETE). Lookups use useFieldOptions. */
1791
+ options: FieldOption[];
1792
+ multiple: boolean;
1793
+ allowAddOptions: boolean;
1794
+ min?: number;
1795
+ max?: number;
1796
+ step?: number;
1797
+ precision?: number;
1798
+ prefix?: string;
1799
+ suffix?: string;
1800
+ /** For file fields: accept string, max size (KB) and max count. */
1801
+ accept?: string;
1802
+ maxSizeKB?: number;
1803
+ maxCount?: number;
1804
+ /** Ids of fields a container holds, in order. */
1805
+ childIds: string[];
1806
+ /** STEPPER / TAB pages. */
1807
+ pages?: {
1808
+ title: string;
1809
+ description?: string;
1810
+ fieldIds: string[];
1811
+ }[];
1812
+ /** TEXT_VIEW / HTML_TEXT content (HTML). */
1813
+ html?: string;
1814
+ /**
1815
+ * Visual intent: action buttons (primary / outline); checkbox "switch" when
1816
+ * attributes.showAsSwitch is set (ZAI CheckboxField / zvolv-web nz-switch).
1817
+ */
1818
+ variant?: "primary" | "outline" | "switch" | "dropdown";
1819
+ /** Read-only text to show (ON_BEHALF_OF: the user's name rather than their id). */
1820
+ displayText?: string;
1821
+ /** DATE_PICKER display format from properties.format (dayjs tokens), default DD/MM/YYYY. */
1822
+ dateFormat?: string;
1823
+ /** Character limit (properties.maxLength / max, or attributes.charactersCount for rich text). */
1824
+ maxLength?: number;
1825
+ element: FormElement;
1826
+ setValue: (value: any) => void;
1827
+ onBlur: () => void;
1828
+ }
1829
+ type FormStatus = "loading" | "ready" | "error" | "submitted";
1830
+ interface ActionOutcome {
1831
+ ok: boolean;
1832
+ message?: string;
1833
+ }
1834
+ interface UseZvolvFormArgs {
1835
+ formId?: string;
1836
+ mode?: FormMode;
1837
+ submissionId?: string | null;
1838
+ /** Supply the schema yourself (raw platform JSON or a FormDefinition) to skip the fetch. */
1839
+ definition?: any;
1840
+ /** Initial values keyed by elementId or label. */
1841
+ defaultValues?: FormValues;
1842
+ /** Field ids (or labels) never shown. */
1843
+ hiddenFields?: string[];
1844
+ /** Element types never shown, e.g. ["COMMENTS"]. */
1845
+ skipTypes?: string[];
1846
+ skipAutomation?: boolean;
1847
+ skipValidations?: boolean;
1848
+ zappId?: string;
1849
+ onSubmitted?: (result: {
1850
+ submissionId: string | null;
1851
+ response: any;
1852
+ values: FormValues;
1853
+ }) => void;
1854
+ /**
1855
+ * Action buttons whose effect belongs to the host (open another form, a task,
1856
+ * a print preview …). Return an outcome, or undefined when not handled.
1857
+ */
1858
+ onAction?: (field: FormField, form: ZvolvFormApi) => Promise<ActionOutcome | void> | ActionOutcome | void;
1859
+ }
1860
+ interface ZvolvFormApi {
1861
+ status: FormStatus;
1862
+ error: Error | null;
1863
+ definition: FormDefinition | null;
1864
+ mode: FormMode;
1865
+ readOnly: boolean;
1866
+ values: FormValues;
1867
+ errors: FormErrors;
1868
+ /** Every field, resolved. */
1869
+ fields: FormField[];
1870
+ /** Visible top-level fields in order (containers hold the rest). */
1871
+ rootFields: FormField[];
1872
+ field: (id: string) => FormField | undefined;
1873
+ childrenOf: (field: FormField | string, visibleOnly?: boolean) => FormField[];
1874
+ setValue: (id: string, value: any) => void;
1875
+ /** Writes a map keyed by elementId, label or legacy id (automation formData). */
1876
+ applyValues: (data: Record<string, any>) => void;
1877
+ dirty: boolean;
1878
+ submitting: boolean;
1879
+ submitAttempted: boolean;
1880
+ submitError: string | null;
1881
+ submittedId: string | null;
1882
+ validate: (ids?: string[]) => boolean;
1883
+ submit: () => Promise<{
1884
+ submissionId: string | null;
1885
+ response: any;
1886
+ } | null>;
1887
+ reset: () => void;
1888
+ /**
1889
+ * Run an action button. For ACTION_DROPDOWN pass the picked option's label
1890
+ * (field.options) — only that action (or its cascade) runs, as in zvolv-web.
1891
+ */
1892
+ runAction: (field: FormField, choice?: string) => Promise<ActionOutcome>;
1893
+ /** Re-fetch the form (and the saved submission). Used by properties.refreshForm. */
1894
+ reload: () => void;
1895
+ /** Field ids with an action / automation in flight. */
1896
+ busy: Set<string>;
1897
+ client: any;
1898
+ /** Sheet child definitions register here so submit can post their rows. */
1899
+ registerSheet: (fieldId: string, def: FormDefinition) => void;
1900
+ /** A registered sheet's child form (after useSheetField loaded it). */
1901
+ sheetDefinition: (fieldId: string) => FormDefinition | undefined;
1902
+ /** Bumps whenever a sheet definition registers — memo key for inspectors. */
1903
+ sheetVersion: number;
1904
+ }
1905
+ /** Elements that go into the POST/PUT /api/v1/submissions body. */
1906
+ declare function submitElementsOf(elements: FormElement[]): FormElement[];
1907
+ declare const FormApiContext: React.Context<ZvolvFormApi | null>;
1908
+ /** The nearest form's api, for field components rendered inside <ZvolvForm>. */
1909
+ declare function useFormApi(): ZvolvFormApi;
1910
+ declare function useZvolvForm(args: UseZvolvFormArgs): ZvolvFormApi;
1911
+
1912
+ /**
1913
+ * What an "open another screen" action button wants, for the host's onAction —
1914
+ * mirrors ZAI-Dashboard ActionButtonField:
1915
+ * CREATE_SUBMISSION → NEW on properties.formId
1916
+ * EDIT_SUBMISSION / OPEN_TASK → EDIT on the button's value (a submission / task id)
1917
+ * SAVE_SUBMISSION → properties.formId, EDIT when the button holds an id, else NEW,
1918
+ * prefilled through properties.inputMap (source → destination elementId)
1919
+ * OPEN_PROJECT → the button's value is a project WID
1920
+ * After the host saves, write the new id back with form.setValue(field.id, id).
1921
+ */
1922
+ interface OpenFormRequest {
1923
+ actionType: string;
1924
+ formId?: string;
1925
+ submissionId?: string;
1926
+ projectId?: string;
1927
+ mode: "NEW" | "EDIT";
1928
+ defaultValues?: Record<string, any>;
1929
+ }
1930
+ declare function openFormRequest(field: FormField, form: Pick<ZvolvFormApi, "values">): OpenFormRequest | null;
1931
+
1932
+ /**
1933
+ * <ZvolvForm> — renders a Zvolv form with whatever field kit the host
1934
+ * supplies. Behaviour comes from useZvolvForm; appearance comes from
1935
+ * `FormKitSlot` (or the `kit` prop). The built-in kit is deliberately plain
1936
+ * native HTML so a form still works when no kit is provided.
1937
+ */
1938
+
1939
+ interface FormKit {
1940
+ /** Draw one field (any kind, containers included). Return undefined to use the built-in control. */
1941
+ field?: (field: FormField, form: ZvolvFormApi) => React.ReactNode | undefined;
1942
+ /** Draw the whole form: header, body and footer. Default: <FormFields> + submit bar. */
1943
+ form?: (form: ZvolvFormApi, parts: {
1944
+ body: React.ReactNode;
1945
+ title?: string;
1946
+ submitLabel: string;
1947
+ }) => React.ReactNode;
1948
+ /** Loading / error / submitted screens. Return undefined for the default. */
1949
+ status?: (args: {
1950
+ status: "loading" | "error" | "submitted";
1951
+ form: ZvolvFormApi;
1952
+ }) => React.ReactNode | undefined;
1953
+ /** Grid wrapper for a list of fields (24-column spans). */
1954
+ grid?: (children: React.ReactNode, fields: FormField[]) => React.ReactNode;
1955
+ }
1956
+ declare const FormKitSlot: React.Context<FormKit | null>;
1957
+ /** Renders fields in a 24-column grid with the active kit. Use it inside section / tab renderers. */
1958
+ declare const FormFields: React.FC<{
1959
+ form: ZvolvFormApi;
1960
+ fields: FormField[];
1961
+ kit?: FormKit;
1962
+ }>;
1963
+ interface ZvolvFormProps extends UseZvolvFormArgs {
1964
+ /** Heading above the form; defaults to the form's own title unless hidden in its config. */
1965
+ title?: string | false;
1966
+ submitLabel?: string;
1967
+ kit?: FormKit;
1968
+ className?: string;
1969
+ style?: React.CSSProperties;
1970
+ /** Receive the api (e.g. to put a submit button elsewhere). */
1971
+ formRef?: React.MutableRefObject<ZvolvFormApi | null>;
1972
+ }
1973
+ declare const ZvolvForm: React.FC<ZvolvFormProps>;
1974
+ declare const DefaultField: React.FC<{
1975
+ field: FormField;
1976
+ form: ZvolvFormApi;
1977
+ }>;
1978
+
1979
+ interface TabItem {
1980
+ key: string;
1981
+ label: any;
1982
+ /** The child widget definition this tab hosts, rendered by the host app. */
1983
+ widget: any;
1984
+ }
1985
+ interface TabRenderArgs {
1986
+ tabs: TabItem[];
1987
+ activeKey: string;
1988
+ setActiveKey: (key: string) => void;
1989
+ tokens: ZvolvTokens;
1990
+ config: any;
1991
+ }
1992
+ interface TabWidgetProps {
1993
+ title?: string;
1994
+ description?: string;
1995
+ configurations?: any;
1996
+ className?: string;
1997
+ style?: React.CSSProperties;
1998
+ /** Renders one tab's child widget. The host owns widget dispatch. */
1999
+ renderChild?: (widget: any, tab: TabItem) => React.ReactNode;
2000
+ render?: (args: TabRenderArgs) => React.ReactNode;
2001
+ }
2002
+ /**
2003
+ * Tab container. It holds no data of its own — it arranges child widget
2004
+ * definitions, which the host renders via `renderChild`.
2005
+ */
2006
+ declare const TabWidget: React.FC<TabWidgetProps>;
2007
+ interface FormWidgetProps {
2008
+ title?: string;
2009
+ description?: string;
2010
+ configurations?: any;
2011
+ dataSource?: any;
2012
+ className?: string;
2013
+ style?: React.CSSProperties;
2014
+ /** Extra <ZvolvForm> props (kit, onSubmitted, onAction, defaultValues …). */
2015
+ form?: Partial<ZvolvFormProps>;
2016
+ onSubmitted?: ZvolvFormProps["onSubmitted"];
2017
+ /**
2018
+ * Replace the form body entirely. Without it the widget renders <ZvolvForm>,
2019
+ * styled by the nearest FormKitSlot.
2020
+ */
2021
+ render?: (args: {
2022
+ formId: any;
2023
+ submissionId: any;
2024
+ mode: "NEW" | "EDIT" | "DISABLED";
2025
+ config: any;
2026
+ tokens: ZvolvTokens;
2027
+ }) => React.ReactNode;
2028
+ }
2029
+ /** Resolves the form a FORM / FORM_WIDGET config points at. */
2030
+ declare function resolveFormWidget(config: any, dataSource?: any): {
2031
+ formId: string | null;
2032
+ submissionId: any;
2033
+ mode: "NEW" | "EDIT" | "DISABLED";
2034
+ };
2035
+ /** Form widget: the headless form engine inside widget chrome. */
2036
+ declare const FormWidget: React.FC<FormWidgetProps>;
2037
+ interface FilterControl {
2038
+ key: string;
2039
+ label: any;
2040
+ type: "text" | "select" | "multiselect" | "date" | "daterange" | "number";
2041
+ options?: {
2042
+ label: any;
2043
+ value: any;
2044
+ }[];
2045
+ value?: any;
2046
+ }
2047
+ interface FilterPanelRenderArgs {
2048
+ controls: FilterControl[];
2049
+ values: Record<string, any>;
2050
+ setValue: (key: string, value: any) => void;
2051
+ apply: () => void;
2052
+ reset: () => void;
2053
+ tokens: ZvolvTokens;
2054
+ config: any;
2055
+ }
2056
+ interface FilterPanelWidgetProps {
2057
+ title?: string;
2058
+ configurations?: any;
2059
+ className?: string;
2060
+ style?: React.CSSProperties;
2061
+ /** Current filter values, owned by the dashboard (URL params). */
2062
+ value?: Record<string, any>;
2063
+ onChange?: (values: Record<string, any>) => void;
2064
+ render?: (args: FilterPanelRenderArgs) => React.ReactNode;
2065
+ }
2066
+ /**
2067
+ * In-grid filter panel. Dashboard filters are URL-param driven and owned by the
2068
+ * host, so this is a controlled component: it renders controls and reports
2069
+ * changes, and never issues queries itself.
2070
+ */
2071
+ declare const FilterPanelWidget: React.FC<FilterPanelWidgetProps>;
2072
+ interface ZaiChatWidgetProps {
2073
+ title?: string;
2074
+ configurations?: any;
2075
+ className?: string;
2076
+ style?: React.CSSProperties;
2077
+ /**
2078
+ * REQUIRED. The chat transport must stay byte-compatible with the existing
2079
+ * send body, so the host owns it; this only supplies chrome and tokens.
2080
+ */
2081
+ render?: (args: {
2082
+ config: any;
2083
+ tokens: ZvolvTokens;
2084
+ }) => React.ReactNode;
2085
+ }
2086
+ declare const ZaiChatWidget: React.FC<ZaiChatWidgetProps>;
2087
+
2088
+ /**
2089
+ * Every Zvolv widget type string → component. Aliases (BAR/BAR_CHART,
2090
+ * HTML/RAW_HTML/STATICHTML …) map to the same component, matching how the
2091
+ * dashboard config stores them across generations.
2092
+ */
2093
+ declare const WIDGET_REGISTRY: Record<string, React.FC<any>>;
2094
+ /** Types that never render as a grid widget (filters and data bindings). */
2095
+ declare const NON_RENDERING_TYPES: Set<string>;
2096
+ declare function resolveWidget(type?: string): React.FC<any> | null;
2097
+ interface ZvolvWidgetProps {
2098
+ type: string;
2099
+ [key: string]: any;
2100
+ }
2101
+ /** Renders any widget by its Zvolv type string. */
2102
+ declare const ZvolvWidget: React.FC<ZvolvWidgetProps>;
2103
+
2104
+ interface UseKpiContentsArgs {
2105
+ contents: any[];
2106
+ rows: any[];
2107
+ cardTemplate?: KpiTemplateId;
2108
+ /** Externally-fetched series keyed by content index (e.g. a history-form time series). */
2109
+ externalSeriesByIndex?: Record<number, number[]>;
2110
+ /** Fallback icon colour when a content item does not set one. */
2111
+ defaultIconColor?: string;
2112
+ dateFormatter?: (value: string, format: string) => string | null;
2113
+ }
2114
+ /**
2115
+ * Resolves raw KPI config + fetched rows into per-item view-models.
2116
+ *
2117
+ * The value/target/format resolution (the "00"→0 normalization, AMOUNT/DATE/precision
2118
+ * branches, target truthy resolution, prefix/suffix maps) is ported verbatim from the
2119
+ * ZAI-Dashboard KPI card so numbers match the Angular original exactly.
2120
+ */
2121
+ declare function useKpiContents({ contents, rows, cardTemplate, externalSeriesByIndex, defaultIconColor, dateFormatter, }: UseKpiContentsArgs): KpiContentVM[];
2122
+
2123
+ /**
2124
+ * Mirrors Angular getResult() for postOperations.
2125
+ * Ported verbatim from ZAI-Dashboard src/widgets/kpi/formatters.ts — do not
2126
+ * re-derive; the operand semantics here match the server's aggregation output.
2127
+ */
2128
+ declare function getPostOpResult(row: any, operator: string, operands: any[]): number;
2129
+ /**
2130
+ * Applies pivot `postOperations` to each fetched row, writing the derived value
2131
+ * onto `row[op.title]` so it's available for a series' valueField lookup.
2132
+ */
2133
+ declare function applyPostOperations(rows: any[], postOperations?: any[]): any[];
2134
+ /**
2135
+ * The set of every summary field referenced as a postOperation operand. Summary
2136
+ * entries in this set are intermediate feeds (e.g. "Total Status Count" deriving
2137
+ * "Incomplete = Total − Completed") and must keep their original agg output name —
2138
+ * renaming them to a series valueField breaks the operand lookup in getPostOpResult.
2139
+ */
2140
+ declare function getPostOpOperandSet(postOperations?: any[]): Set<string>;
2141
+ /**
2142
+ * Aligns each summary agg's output name with its series valueField so the SDK maps
2143
+ * the aggregated value onto the right key. Only `value` (the agg name) is touched —
2144
+ * title/masterFieldDataType/masterFieldType/type describe WHICH field is aggregated
2145
+ * and HOW, and must stay as the metric field (e.g. Population/FLOAT/sum). Overwriting
2146
+ * them turned a sum(Population) into a value_count(State.keyword).
2147
+ *
2148
+ * Summary entries referenced as postOperations operands are intermediate values with
2149
+ * no series of their own — renaming them positionally broke the operand lookup and
2150
+ * silently zeroed out the subtraction, so those are left untouched.
2151
+ */
2152
+ declare function alignSummaryToSeries(dataSource: any, series: any[]): any;
2153
+
2154
+ declare const PREFIX_UNITS: Record<string, string>;
2155
+ declare const SUFFIX_UNITS: Record<string, string>;
2156
+ /** Mirrors Angular formatAmountValue() from dashboards.utils */
2157
+ declare function formatAmountValue(value: number, suffix?: string, precision?: number): string;
2158
+ declare function toNum(v: any): number | null;
2159
+ /** Compact axis/label formatting: 1.2K, 3.4M, 1.1B. */
2160
+ declare function formatCompact(value: any): string;
2161
+
2162
+ /** Config may arrive as a JSON string from the server — parse defensively. */
2163
+ declare function parseConfig(configurations: any): WidgetConfigurations;
2164
+ /**
2165
+ * The configured series. Stored widgets spell it `series` (React dashboards) or
2166
+ * `serieses` (Angular-era dashboards) — both are read, `series` first.
2167
+ */
2168
+ declare function resolveSeries(config: WidgetConfigurations): SeriesConfig[];
2169
+ declare function resolveXKey(series: SeriesConfig[]): string;
2170
+ /**
2171
+ * A null/empty DataSource parses to {} — that is NOT "configured". Widgets must
2172
+ * show the unconfigured empty state rather than falling back to demo data.
2173
+ */
2174
+ declare function isDataSourceConfigured(dataSource: any): boolean;
2175
+ declare function usesFormFramework(dataSource: ZvolvDataSource): boolean;
2176
+
2177
+ /**
2178
+ * Typed config schemas — the authoring surface for writing widget configs in code.
2179
+ *
2180
+ * These describe the server's shape. Every field is optional because real configs
2181
+ * are sparse, and unknown keys are preserved: widen, never narrow, a config you
2182
+ * did not author.
2183
+ */
2184
+
2185
+ interface AxisConfig {
2186
+ title?: string;
2187
+ valueFormat?: string;
2188
+ /** Rotate/hide long category labels. */
2189
+ labelRotation?: number;
2190
+ showLabels?: boolean;
2191
+ min?: number;
2192
+ max?: number;
2193
+ }
2194
+ interface LegendConfig {
2195
+ show?: boolean;
2196
+ position?: "top" | "bottom" | "left" | "right";
2197
+ showLabels?: boolean;
2198
+ }
2199
+ interface ChartConfig extends WidgetChromeConfig {
2200
+ template?: string;
2201
+ series?: SeriesConfig[];
2202
+ axis?: {
2203
+ argumentAxis?: AxisConfig;
2204
+ valueAxis?: AxisConfig;
2205
+ };
2206
+ legends?: LegendConfig;
2207
+ sortOrder?: "none" | "asc" | "desc";
2208
+ stackOrder?: "none" | "asc" | "desc";
2209
+ /** Insert zero rows for empty periods so a time axis reads continuously. */
2210
+ fillDateGaps?: boolean;
2211
+ dateGapUnit?: "day" | "week" | "month";
2212
+ }
2213
+ interface KpiContentConfig {
2214
+ title?: string;
2215
+ subtitle?: string;
2216
+ /** Field whose value this item displays. */
2217
+ dataPoint?: string;
2218
+ targetPoint?: string;
2219
+ defaultVale?: any;
2220
+ template?: KpiTemplateId;
2221
+ dataFormat?: "AMOUNT" | "DATE" | "NUMBER";
2222
+ amountSuffix?: "Rupees" | "Lakhs" | "Crores" | "Millions";
2223
+ dateFormat?: string;
2224
+ precision?: number;
2225
+ unit?: string;
2226
+ icon?: string;
2227
+ iconColor?: string;
2228
+ valueColor?: string;
2229
+ deltaSource?: "target" | "datapoint";
2230
+ deltaPoint?: string;
2231
+ deltaMode?: "percent" | "absolute";
2232
+ invertColors?: boolean;
2233
+ maxSource?: "value" | "datapoint";
2234
+ maxPoint?: string;
2235
+ progressMax?: number;
2236
+ statusMap?: Record<string, {
2237
+ label?: string;
2238
+ tone?: string;
2239
+ description?: string;
2240
+ }>;
2241
+ statusFallbackTone?: string;
2242
+ seriesPoints?: string[];
2243
+ seriesPoint?: string;
2244
+ seriesSource?: {
2245
+ mode?: "timeseries" | "fields";
2246
+ [k: string]: any;
2247
+ };
2248
+ }
2249
+ interface KpiConfig extends WidgetChromeConfig {
2250
+ template?: KpiTemplateId;
2251
+ contents?: KpiContentConfig[];
2252
+ }
2253
+ interface TableColumnConfig {
2254
+ key?: string;
2255
+ masterfield?: string;
2256
+ field?: string;
2257
+ header?: string;
2258
+ title?: string;
2259
+ align?: "left" | "right" | "center";
2260
+ width?: number | string;
2261
+ hidden?: boolean;
2262
+ masterFieldType?: string;
2263
+ kind?: "text" | "number" | "date" | "status" | "user" | "html";
2264
+ }
2265
+ interface TableConfig extends WidgetChromeConfig {
2266
+ columns?: TableColumnConfig[];
2267
+ pageSize?: number;
2268
+ /** Per-column value filters in the header. */
2269
+ showColumnFilter?: boolean;
2270
+ /** Click-to-sort headers. Default true. */
2271
+ enableSort?: boolean;
2272
+ }
2273
+ interface CollectionMappingConfig {
2274
+ titleField?: string;
2275
+ subtitleField?: string;
2276
+ descriptionField?: string;
2277
+ valueField?: string;
2278
+ imageField?: string;
2279
+ statusField?: string;
2280
+ dateField?: string;
2281
+ fields?: {
2282
+ field?: string;
2283
+ label?: string;
2284
+ }[];
2285
+ }
2286
+ interface CollectionConfig extends WidgetChromeConfig {
2287
+ template?: string;
2288
+ cardConfiguration?: CollectionMappingConfig;
2289
+ mapping?: CollectionMappingConfig;
2290
+ }
2291
+ interface TemporalMappingConfig {
2292
+ /** zvolv-web spellings are preserved so migrated dashboards map unchanged. */
2293
+ taskTitle?: string;
2294
+ projectTitle?: string;
2295
+ taskStatus?: string;
2296
+ startDate?: string;
2297
+ endDate?: string;
2298
+ titleField?: string;
2299
+ groupField?: string;
2300
+ statusField?: string;
2301
+ progressField?: string;
2302
+ colorField?: string;
2303
+ }
2304
+ interface TemporalConfig extends WidgetChromeConfig {
2305
+ template?: string;
2306
+ timeline?: TemporalMappingConfig;
2307
+ gantt?: TemporalMappingConfig;
2308
+ calendar?: TemporalMappingConfig;
2309
+ scheduler?: TemporalMappingConfig;
2310
+ }
2311
+ interface StepperConfig extends WidgetChromeConfig {
2312
+ template?: string;
2313
+ stepper?: {
2314
+ steps?: any[];
2315
+ labelField?: string;
2316
+ descriptionField?: string;
2317
+ statusField?: string;
2318
+ currentIndex?: number;
2319
+ };
2320
+ }
2321
+ interface GaugeConfig extends WidgetChromeConfig {
2322
+ gauge?: {
2323
+ valueField?: string;
2324
+ min?: number;
2325
+ max?: number;
2326
+ thresholds?: {
2327
+ low?: number;
2328
+ medium?: number;
2329
+ high?: number;
2330
+ };
2331
+ };
2332
+ }
2333
+ interface HeatMapConfig extends WidgetChromeConfig {
2334
+ heatMap?: {
2335
+ grid?: {
2336
+ rows?: number;
2337
+ cols?: number;
2338
+ };
2339
+ thresholds?: {
2340
+ low?: {
2341
+ value?: number;
2342
+ color?: string;
2343
+ };
2344
+ medium?: {
2345
+ value?: number;
2346
+ color?: string;
2347
+ };
2348
+ high?: {
2349
+ value?: number;
2350
+ color?: string;
2351
+ };
2352
+ };
2353
+ dataMapping?: {
2354
+ zoneField?: string;
2355
+ countField?: string;
2356
+ breakdownFields?: string[];
2357
+ };
2358
+ };
2359
+ }
2360
+ interface RankingConfig extends WidgetChromeConfig {
2361
+ ranking?: {
2362
+ labelField?: string;
2363
+ valueField?: string;
2364
+ order?: "asc" | "desc";
2365
+ limit?: number;
2366
+ };
2367
+ }
2368
+ interface TreeConfig extends WidgetChromeConfig {
2369
+ tree?: {
2370
+ idField?: string;
2371
+ parentField?: string;
2372
+ labelField?: string;
2373
+ };
2374
+ }
2375
+ interface MapConfig extends WidgetChromeConfig {
2376
+ map?: {
2377
+ latField?: string;
2378
+ lngField?: string;
2379
+ labelField?: string;
2380
+ centerLat?: number;
2381
+ centerLng?: number;
2382
+ zoom?: number;
2383
+ };
2384
+ }
2385
+ interface HtmlConfig extends WidgetChromeConfig {
2386
+ /** Supports {{field}} placeholders, substituted from the first row. */
2387
+ html?: string;
2388
+ content?: string;
2389
+ }
2390
+ interface IframeConfig extends WidgetChromeConfig {
2391
+ url?: string;
2392
+ sandbox?: string;
2393
+ }
2394
+ interface ActionConfig extends WidgetChromeConfig {
2395
+ actions?: {
2396
+ id?: string | number;
2397
+ label?: string;
2398
+ icon?: string;
2399
+ actionType?: string;
2400
+ disabled?: boolean;
2401
+ [k: string]: any;
2402
+ }[];
2403
+ }
2404
+ interface TabConfig extends WidgetChromeConfig {
2405
+ tabs?: {
2406
+ key?: string;
2407
+ label?: string;
2408
+ widget?: any;
2409
+ }[];
2410
+ }
2411
+ interface FormConfig extends WidgetChromeConfig {
2412
+ formId?: string | number;
2413
+ submissionId?: string | number | null;
2414
+ mode?: "NEW" | "EDIT" | "DISABLED";
2415
+ }
2416
+ interface FilterPanelConfig extends WidgetChromeConfig {
2417
+ filters?: {
2418
+ key?: string;
2419
+ field?: string;
2420
+ label?: string;
2421
+ type?: "text" | "select" | "multiselect" | "date" | "daterange" | "number";
2422
+ options?: {
2423
+ label: any;
2424
+ value: any;
2425
+ }[];
2426
+ }[];
2427
+ }
2428
+ /** A complete widget definition as a dashboard stores it. */
2429
+ interface WidgetDefinition<TConfig = any> {
2430
+ WidgetID?: string | number;
2431
+ Type: string;
2432
+ Title?: string;
2433
+ DataSource?: ZvolvDataSource | string | null;
2434
+ Configurations?: TConfig | string | null;
2435
+ WorkflowTypeID?: string | number;
2436
+ }
2437
+ /** Identity helper: gives a config literal its type without widening. */
2438
+ declare function defineConfig<T>(config: T): T;
2439
+
2440
+ /** JSON-parses until the value is no longer a string (handles double encoding). */
2441
+ declare function parseDeep(raw: any): any;
2442
+ interface NormalizedWidget {
2443
+ id: string;
2444
+ type: string;
2445
+ title?: string;
2446
+ description?: string;
2447
+ configurations: any;
2448
+ dataSource: any;
2449
+ workflowTypeId?: string | number;
2450
+ raw: any;
2451
+ }
2452
+ /** A stored widget → the props every @zestl/zvolv-widgets component takes. */
2453
+ declare function normalizeWidget(widget: any): NormalizedWidget;
2454
+ /**
2455
+ * Widgets that render as grid tiles: drops filter/automation types and
2456
+ * widgets nested inside a TAB's `childWidget` (the tab renders those).
2457
+ */
2458
+ declare function gridWidgets(widgets: any[]): any[];
2459
+ declare const GRID: {
2460
+ readonly COLS: 60;
2461
+ /** Row unit in px. A tile's height = h * ROW_HEIGHT + (h - 1) * GAP. */
2462
+ readonly ROW_HEIGHT: 5;
2463
+ readonly GAP: 16;
2464
+ /** Layouts saved before grid v2 used 12 columns. */
2465
+ readonly VERSION: 2;
2466
+ readonly LEGACY_SCALE: 5;
2467
+ };
2468
+ interface GridItem {
2469
+ id: string;
2470
+ x: number;
2471
+ y: number;
2472
+ w: number;
2473
+ h: number;
2474
+ }
2475
+ /**
2476
+ * Grid positions from each widget's `Configuration.additionalProperties`, with
2477
+ * legacy 12-col layouts scaled up and unset positions packed row by row, then
2478
+ * compacted vertically like react-grid-layout (`compactType="vertical"`).
2479
+ */
2480
+ declare function resolveDashboardLayout(widgets: any[]): GridItem[];
2481
+ /** Pixel height of a tile `h` rows tall. */
2482
+ declare function gridHeight(h: number): number;
2483
+ /** One control in the dashboard filter bar (from the FILTER widget's config). */
2484
+ interface DashboardFilterDef {
2485
+ label: string;
2486
+ formId?: any;
2487
+ formTitle: string;
2488
+ fieldLabel: string;
2489
+ fieldType?: string;
2490
+ }
2491
+ /** The dashboard's FILTER widget's declared filters, if it has one. */
2492
+ declare function dashboardFilterDefs(widgets: any[]): DashboardFilterDef[];
2493
+ interface DashboardFilterValue {
2494
+ formTitle: string;
2495
+ fieldLabel: string;
2496
+ operator: string;
2497
+ values: any[];
2498
+ }
2499
+ interface DateRange {
2500
+ start: string;
2501
+ end: string;
2502
+ }
2503
+ /**
2504
+ * Builds the `dashFilters` object every widget takes — the same shape the host
2505
+ * derives from its `filters` / `operator` / `cdate` URL params.
2506
+ */
2507
+ declare function buildDashFilters(values?: DashboardFilterValue[], dateRange?: DateRange | null, operator?: "AND" | "OR"): any;
2508
+ type DateRangeToken = "TODAY" | "LAST_7_DAYS" | "LAST_30_DAYS" | "THIS_MONTH" | "LAST_MONTH" | "THIS_YEAR";
2509
+ declare function dateRangeFor(token: DateRangeToken | string): DateRange;
2510
+ /** The DATE_FILTER widget's default range token, if the dashboard has one. */
2511
+ declare function dashboardDefaultDateToken(widgets: any[]): string | null;
2512
+ /**
2513
+ * The per-widget `cdateFilters` — which of its fields a dashboard date range
2514
+ * lands on. Explicit DATE_FILTER mappings win; otherwise the widget's own date
2515
+ * field is picked (task sources by column name).
2516
+ */
2517
+ declare function cdateFiltersFor(widget: any, allWidgets: any[]): any[];
2518
+ interface DashboardNode {
2519
+ id: string;
2520
+ title: string;
2521
+ raw: any;
2522
+ children: DashboardNode[];
2523
+ }
2524
+ /** Strips the `<i class="…"></i>` icon tag some dashboard titles carry. */
2525
+ declare function cleanTitle(title: any): string;
2526
+ /**
2527
+ * `getDashboards()` elements → a sorted tree (ChildReportIDs nest), hiding
2528
+ * MobileOnly / HideInMobileApp dashboards from non-admins.
2529
+ */
2530
+ declare function buildDashboardTree(elements: any[], isAdmin?: boolean): DashboardNode[];
2531
+
2532
+ interface FieldOptionsState {
2533
+ options: FieldOption[];
2534
+ loading: boolean;
2535
+ error: string | null;
2536
+ search: string;
2537
+ setSearch: (q: string) => void;
2538
+ /** Set when a dependency must be filled first, e.g. "Select Region first". */
2539
+ waitingFor: string | null;
2540
+ /** The field's current selection as options (resolves stored ids to labels). */
2541
+ selected: FieldOption[];
2542
+ /** Commit a pick: stores the right shape for the field type. */
2543
+ select: (option: FieldOption | FieldOption[] | null) => void;
2544
+ /** Toggle one option in a multi-select (refused once `maxCount` is reached). */
2545
+ toggle: (option: FieldOption) => void;
2546
+ isSelected: (option: FieldOption) => boolean;
2547
+ /**
2548
+ * Call when the control gets focus / opens. Remote options (lookups, people
2549
+ * search) load on first focus, as in zvolv-web (nzFocus → onFocus) and
2550
+ * ZAI-Dashboard (handleFocus). Lookups reload on later focuses (throttled
2551
+ * 2 s); people search loads only when it has nothing yet.
2552
+ */
2553
+ onFocus: () => void;
2554
+ /** Force a reload of remote options. */
2555
+ refresh: () => void;
2556
+ /** Most selections allowed (properties.maxResults). 1 = single select. */
2557
+ maxCount: number;
2558
+ /** A multi-select already holds `maxCount` items. */
2559
+ atLimit: boolean;
2560
+ /** INPUT_TAG: add a tag that isn't in the list (ZAI FormSearchField free-text tag). */
2561
+ addFreeTag: (text: string) => void;
2562
+ }
2563
+ interface FieldOptionsOptions {
2564
+ debounceMs?: number;
2565
+ /**
2566
+ * When remote options load. "focus" (default) = on first onFocus(), like
2567
+ * zvolv-web and ZAI-Dashboard; "mount" = as soon as the control renders.
2568
+ * Dependency-filtered lookups always load when their source changes.
2569
+ */
2570
+ loadOn?: "focus" | "mount";
2571
+ /**
2572
+ * Copy a picked row's ExtraLabels into same-labelled fields on this form.
2573
+ * Off by default: neither zvolv-web nor ZAI-Dashboard does this — use a
2574
+ * FETCH_OPTIONS_FILTERS dependent lookup instead.
2575
+ */
2576
+ autofillExtraLabels?: boolean;
2577
+ }
2578
+ declare function useFieldOptions(form: ZvolvFormApi, field: FormField, opts?: FieldOptionsOptions): FieldOptionsState;
2579
+ /** Extensions the platform refuses (ZAI-Dashboard utils/constant BLOCKED_FILE_EXTENSIONS). */
2580
+ declare const BLOCKED_FILE_EXTENSIONS: Set<string>;
2581
+ interface FileItem {
2582
+ key: string;
2583
+ name: string;
2584
+ size: number;
2585
+ type: string;
2586
+ url?: string;
2587
+ uploading: boolean;
2588
+ error?: string;
2589
+ record?: UploadedFile;
2590
+ }
2591
+ interface FileFieldState {
2592
+ items: FileItem[];
2593
+ uploading: boolean;
2594
+ /** Validates size / count / type, then uploads immediately. */
2595
+ add: (files: FileList | File[]) => void;
2596
+ remove: (key: string) => void;
2597
+ canAdd: boolean;
2598
+ rejectReason: string | null;
2599
+ }
2600
+ declare function useFileField(form: ZvolvFormApi, field: FormField, opts?: {
2601
+ zappId?: string;
2602
+ }): FileFieldState;
2603
+ interface SheetColumn {
2604
+ id: string;
2605
+ label: string;
2606
+ type: string;
2607
+ required: boolean;
2608
+ options: FieldOption[];
2609
+ element: any;
2610
+ }
2611
+ interface SheetFieldState {
2612
+ loading: boolean;
2613
+ error: string | null;
2614
+ columns: SheetColumn[];
2615
+ rows: Record<string, any>[];
2616
+ addRow: (values?: Record<string, any>) => void;
2617
+ updateRow: (index: number, columnId: string, value: any) => void;
2618
+ removeRow: (index: number) => void;
2619
+ /** Row-level validation errors, keyed `${index}:${columnId}`. */
2620
+ rowErrors: Record<string, string>;
2621
+ display: (column: SheetColumn, value: any) => string;
2622
+ childForm: FormDefinition | null;
2623
+ /** properties.allowedAddActions / allowedActions include "ADD" (or neither is set), and the row cap isn't reached. */
2624
+ canAdd: boolean;
2625
+ /** properties.allowedDeleteActions / allowedActions include "DELETE" (or neither is set). */
2626
+ canDelete: boolean;
2627
+ /** properties.maxRows, when set. */
2628
+ maxRows?: number;
2629
+ /** Set when addRow was refused (row cap). */
2630
+ limitMessage: string | null;
2631
+ }
2632
+ declare function useSheetField(form: ZvolvFormApi, field: FormField): SheetFieldState;
2633
+
2634
+ interface TrialButton {
2635
+ label: string;
2636
+ icon?: string;
2637
+ color?: string;
2638
+ hideLabel?: boolean;
2639
+ disabled?: boolean;
2640
+ /** Second-level buttons shown after this response is pressed. */
2641
+ prompts: {
2642
+ label: string;
2643
+ icon?: string;
2644
+ color?: string;
2645
+ hideLabel?: boolean;
2646
+ }[];
2647
+ }
2648
+ interface TrialLogEntry {
2649
+ label: string;
2650
+ correct: boolean;
2651
+ detail?: string;
2652
+ }
2653
+ interface TrialFieldState {
2654
+ type: "percent" | "time" | "task";
2655
+ /** Response buttons for the current trial (task analysis: for the current step). */
2656
+ buttons: TrialButton[];
2657
+ /** Set after a response with prompt buttons is pressed; pick one with prompt(). */
2658
+ activeResponse?: string;
2659
+ prompts: TrialButton["prompts"];
2660
+ respond: (label: string) => void;
2661
+ prompt: (label: string) => void;
2662
+ cancelPrompt: () => void;
2663
+ /** Percent correct / task analysis: undo the last trial. */
2664
+ prev: () => void;
2665
+ currentTrial: number;
2666
+ maxTrials: number;
2667
+ complete: boolean;
2668
+ /** Share of responses labelled IND / NR / CHECK (ZAI's "correct" set), 0–100. */
2669
+ percentCorrect: number;
2670
+ log: TrialLogEntry[];
2671
+ disabled: boolean;
2672
+ timer: number;
2673
+ formattedTimer: string;
2674
+ running: boolean;
2675
+ start: () => void;
2676
+ pause: () => void;
2677
+ reset: () => void;
2678
+ interval: number;
2679
+ intervalCount: number;
2680
+ timeLimit: number;
2681
+ steps: string[];
2682
+ currentStep: number;
2683
+ stepName: string;
2684
+ chain: "forward" | "backward" | "whole";
2685
+ }
2686
+ declare function useTrialField(form: ZvolvFormApi, field: FormField): TrialFieldState;
2687
+
2688
+ /**
2689
+ * Form definition + submission normalisation. Ported from ZAI-Dashboard
2690
+ * `formApi.ts` (normaliseForm / normaliseElement / flattenElements /
2691
+ * submissionToValues) so both schema generations land in one shape.
2692
+ */
2693
+
2694
+ declare function normaliseElement(el: any): FormElement;
2695
+ /** Accepts getSingleForm output, the legacy `{value:{<id>:{…}}}` envelope, or an array. */
2696
+ declare function normaliseForm(raw: any, formId?: string): FormDefinition;
2697
+ /** Values keyed by elementId from a getSingleSubmission response. */
2698
+ declare function submissionToValues(sub: any): FormValues;
2699
+ /** The effective type: attributes.subType overrides the stored type for routing. */
2700
+ declare function resolveFieldType(el: FormElement): string;
2701
+ declare function fieldKindOf(el: FormElement): FieldKind;
2702
+ /** Kinds that hold other fields (their children are not rendered at the root). */
2703
+ declare const CONTAINER_KINDS: Set<FieldKind>;
2704
+ /** Child element ids declared by a container, in order. */
2705
+ declare function childIdsOf(el: FormElement): string[];
2706
+
2707
+ /**
2708
+ * Field validation. Ported from ZAI-Dashboard `formUtils.ts` (validateField /
2709
+ * validateForm / runCustomValidators); expression validators run through the
2710
+ * formula parser instead of `new Function`.
2711
+ */
2712
+
2713
+ /** Types that are layout, display or actions — never validated. */
2714
+ declare const NON_INPUT_TYPES: Set<string>;
2715
+ declare function validateField(el: FormElement, value: any, required?: boolean): string | undefined;
2716
+ declare function validateForm(elements: FormElement[], values: FormValues, state?: (el: FormElement) => {
2717
+ hidden: boolean;
2718
+ required: boolean;
2719
+ }): FormErrors;
2720
+
2721
+ /**
2722
+ * Conditional logic: `dependencies[]` rules live on the DRIVING element and
2723
+ * target another field or container. Ported from ZAI-Dashboard
2724
+ * ZFormRenderer `applyDependencies` / `depMatches` / `evaluateCondition`.
2725
+ */
2726
+
2727
+ interface RuleOverride {
2728
+ isHidden?: boolean;
2729
+ isDisabled?: boolean;
2730
+ isRequired?: boolean;
2731
+ }
2732
+ /** Does `dep` (declared on `src`) match the current values? */
2733
+ declare function ruleMatches(src: FormElement, dep: any, values: FormValues): boolean;
2734
+ declare function rulesOf(el: FormElement): any[];
2735
+ /**
2736
+ * Hidden / disabled / required overrides per target elementId. A matching rule
2737
+ * for a target wins over a non-matching one on the same aspect (Angular's
2738
+ * "perfect match" semantics).
2739
+ */
2740
+ declare function applyRules(elements: FormElement[], values: FormValues): Map<string, RuleOverride>;
2741
+ /**
2742
+ * FETCH_OPTIONS_FILTERS rules that narrow `targetId`'s lookup options:
2743
+ * [{ elementId: <source field>, masterField: <label on the lookup's source form> }].
2744
+ *
2745
+ * Platform shape (zvolv-web ZFormService.listenDependencies, ZAI-Dashboard
2746
+ * FormSearchField.buildDependencyFilters): the rule sits ON THE LOOKUP being
2747
+ * filtered; `elementId` is the field whose value is the filter, `masterField`
2748
+ * the label matched on the lookup's source form.
2749
+ *
2750
+ * Legacy shape (this library's earlier `cascade()`): the rule sits on a
2751
+ * NON-lookup driver and `elementId` is the lookup to filter. The platform never
2752
+ * reads FETCH_OPTIONS_FILTERS on a non-lookup, so the two cannot be confused.
2753
+ */
2754
+ declare function optionFilterRules(elements: FormElement[], targetId: string): {
2755
+ elementId: string;
2756
+ masterField: string;
2757
+ }[];
2758
+
2759
+ /** Legacy formulas reference bare labels — wrap them in {…}, longest first. */
2760
+ declare function toBraceFormula(formula: string, labels: string[]): string;
2761
+ /**
2762
+ * Evaluate `formula` with `valueOf(label)` resolving field references.
2763
+ * Returns null when the formula is invalid or the result is not finite.
2764
+ */
2765
+ declare function evaluateFormula(formula: string, valueOf: (label: string) => any, labels?: string[]): any;
2766
+ /** Labels a formula depends on (for recompute triggers). */
2767
+ declare function formulaLabels(formula: string, labels?: string[]): string[];
2768
+ /**
2769
+ * True when the platform can evaluate `formula` itself. The submission API
2770
+ * re-evaluates INPUT_FORMULA fields and rejects a mismatch ("Evaluated value
2771
+ * \"0\" and existing value \"8000\" … do not match"); it only resolves
2772
+ * `{Label}` references — bare labels (`MUL(Qty, Price)`) evaluate to 0 there.
2773
+ */
2774
+ declare function isServerSafeFormula(formula: string, labels?: string[]): boolean;
2775
+ /**
2776
+ * Recompute every INPUT_FORMULA cell of one sheet row (references are the
2777
+ * child form's labels). Returns a new row; other cells are untouched.
2778
+ */
2779
+ declare function computeRowFormulas(elements: {
2780
+ elementId: string;
2781
+ label: string;
2782
+ type: string;
2783
+ attributes?: any;
2784
+ properties?: any;
2785
+ }[], row: Record<string, any>): Record<string, any>;
2786
+
2787
+ type RuleEffect = "show" | "hide" | "required" | "optional" | "editable" | "read-only";
2788
+ interface RuleInsight {
2789
+ sourceId: string;
2790
+ sourceLabel: string;
2791
+ sourceValue: string;
2792
+ action: string;
2793
+ effect: RuleEffect;
2794
+ targetId: string;
2795
+ targetLabel: string;
2796
+ /** What the rule waits for, in words. */
2797
+ expected: string;
2798
+ matched: boolean;
2799
+ /** "triage" (properties.triage) or "dependencies". */
2800
+ origin: "triage" | "dependencies";
2801
+ }
2802
+ interface FilterInsight {
2803
+ targetId: string;
2804
+ targetLabel: string;
2805
+ sourceForm: string;
2806
+ kind: "dependent" | "dynamic" | "static";
2807
+ /** Label on the source form the filter is applied to. */
2808
+ masterField: string;
2809
+ /** The local field whose value feeds the filter (dependent / dynamic). */
2810
+ sourceLabel?: string;
2811
+ sourceValue?: string;
2812
+ /** Static filters: the configured value. */
2813
+ value?: string;
2814
+ active: boolean;
2815
+ }
2816
+ interface ValidationInsight {
2817
+ id: string;
2818
+ label: string;
2819
+ type: string;
2820
+ /** e.g. Accessories · row 2 — for sheet cells. */
2821
+ scope?: string;
2822
+ required: boolean;
2823
+ hidden: boolean;
2824
+ checks: string[];
2825
+ value: string;
2826
+ /** What validateField says right now. */
2827
+ error?: string;
2828
+ /** What the user currently sees (set on submit, cleared on change). */
2829
+ shownError?: string;
2830
+ }
2831
+ interface FormulaInsight {
2832
+ fieldId: string;
2833
+ label: string;
2834
+ scope: "form" | "row";
2835
+ sheetLabel?: string;
2836
+ row?: number;
2837
+ formula: string;
2838
+ /** The same formula with {Label} references — what the platform understands. */
2839
+ serverFormula: string;
2840
+ serverSafe: boolean;
2841
+ inputs: {
2842
+ label: string;
2843
+ value: any;
2844
+ }[];
2845
+ /** The library's result for the current inputs. */
2846
+ expected: any;
2847
+ /** The value that will be submitted. */
2848
+ current: any;
2849
+ inSync: boolean;
2850
+ }
2851
+ interface DefaultInsight {
2852
+ id: string;
2853
+ label: string;
2854
+ source: string;
2855
+ value: string;
2856
+ }
2857
+ interface PayloadInsight {
2858
+ formId: string;
2859
+ elements: any[];
2860
+ sheets: {
2861
+ fieldId: string;
2862
+ label: string;
2863
+ formId: string;
2864
+ rows: any[][];
2865
+ }[];
2866
+ }
2867
+ interface FormInspection {
2868
+ rules: RuleInsight[];
2869
+ filters: FilterInsight[];
2870
+ validation: ValidationInsight[];
2871
+ formulas: FormulaInsight[];
2872
+ defaults: DefaultInsight[];
2873
+ payload: PayloadInsight | null;
2874
+ summary: {
2875
+ rules: number;
2876
+ matched: number;
2877
+ filters: number;
2878
+ activeFilters: number;
2879
+ errors: number;
2880
+ formulas: number;
2881
+ formulaIssues: number;
2882
+ };
2883
+ }
2884
+ declare function inspectForm(form: ZvolvFormApi): FormInspection;
2885
+ /** inspectForm, memoised on the form's values, definition and loaded sheets. */
2886
+ declare function useFormInspector(form: ZvolvFormApi): FormInspection;
2887
+
2888
+ /**
2889
+ * Authoring helpers: build a platform `create_form` payload and the FORM
2890
+ * widget that renders it on a dashboard. Encodes the rules the platform
2891
+ * validates silently (see the zvibe KB `form_payload_field_types.md`):
2892
+ * - `width` is a percentage (25/50/75/100) and must be at the element root
2893
+ * AND in attributes.Width;
2894
+ * - SPINNER / RADIO_GROUP options and FORM_SEARCH dataSource sit at the root;
2895
+ * - formulas use bare single-word labels with MUL / ADD / SUB / DIVI / IF —
2896
+ * AVG is listed by the KB but 502s every write on the live platform;
2897
+ * - show / hide / mandatory rules live on the DRIVING element.
2898
+ */
2899
+ type Width = 25 | 50 | 75 | 100;
2900
+ interface ElementSpec {
2901
+ label: string;
2902
+ type: string;
2903
+ width?: Width;
2904
+ required?: boolean;
2905
+ hidden?: boolean;
2906
+ disabled?: boolean;
2907
+ elementId?: string;
2908
+ [k: string]: any;
2909
+ }
2910
+ /** A stable elementId from a label, e.g. "Quantity (MT)" → "EID_quantity_mt". */
2911
+ declare const eid: (label: string) => string;
2912
+ type Opt = Partial<ElementSpec>;
2913
+ declare const el: {
2914
+ text: (label: string, o?: Opt) => ElementSpec;
2915
+ longText: (label: string, o?: Opt) => ElementSpec;
2916
+ richText: (label: string, o?: Opt) => ElementSpec;
2917
+ email: (label: string, o?: Opt) => ElementSpec;
2918
+ phone: (label: string, o?: Opt & {
2919
+ countryCode?: string;
2920
+ }) => ElementSpec;
2921
+ url: (label: string, o?: Opt) => ElementSpec;
2922
+ number: (label: string, o?: Opt & {
2923
+ minVal?: number;
2924
+ maxVal?: number;
2925
+ }) => ElementSpec;
2926
+ currency: (label: string, o?: Opt) => ElementSpec;
2927
+ percent: (label: string, o?: Opt) => ElementSpec;
2928
+ /** formula uses `{Label}` references: `MUL({Quantity}, {Rate})`. */
2929
+ formula: (label: string, formula: string, o?: Opt) => ElementSpec;
2930
+ date: (label: string, o?: Opt & {
2931
+ today?: boolean;
2932
+ }) => ElementSpec;
2933
+ time: (label: string, o?: Opt) => ElementSpec;
2934
+ dateTime: (label: string, o?: Opt) => ElementSpec;
2935
+ dateRange: (label: string, o?: Opt) => ElementSpec;
2936
+ dropdown: (label: string, options: string[], o?: Opt) => ElementSpec;
2937
+ radio: (label: string, options: string[], o?: Opt) => ElementSpec;
2938
+ checkbox: (label: string, o?: Opt) => ElementSpec;
2939
+ /** Look up rows of another form; `extra` columns autofill same-labelled fields. */
2940
+ lookup: (label: string, src: {
2941
+ formId: string;
2942
+ field: string;
2943
+ extra?: string[];
2944
+ multiple?: boolean;
2945
+ }, o?: Opt) => ElementSpec;
2946
+ rating: (label: string, o?: Opt & {
2947
+ maxVal?: number;
2948
+ }) => ElementSpec;
2949
+ progress: (label: string, o?: Opt & {
2950
+ minVal?: number;
2951
+ maxVal?: number;
2952
+ step?: number;
2953
+ suffix?: string;
2954
+ }) => ElementSpec;
2955
+ file: (label: string, o?: Opt) => ElementSpec;
2956
+ signature: (label: string, o?: Opt) => ElementSpec;
2957
+ section: (label: string, childIds: string[], o?: Opt) => ElementSpec;
2958
+ note: (label: string, html: string, o?: Opt) => ElementSpec;
2959
+ createdAt: (label?: string) => {
2960
+ label: string;
2961
+ type: string;
2962
+ width: Width;
2963
+ attributes: {
2964
+ Width: number;
2965
+ };
2966
+ };
2967
+ createdBy: (label?: string) => {
2968
+ label: string;
2969
+ type: string;
2970
+ width: Width;
2971
+ attributes: {
2972
+ Width: number;
2973
+ };
2974
+ };
2975
+ autoNumber: (label: string) => {
2976
+ label: string;
2977
+ type: string;
2978
+ width: Width;
2979
+ attributes: {
2980
+ Width: number;
2981
+ };
2982
+ };
2983
+ };
2984
+ /** Rules go on the driving element: `when(severity, "Critical").show(rootCause)`. */
2985
+ declare function when(driver: ElementSpec, value: any): {
2986
+ show: (t: ElementSpec | string) => /*elided*/ any;
2987
+ hide: (t: ElementSpec | string) => /*elided*/ any;
2988
+ require: (t: ElementSpec | string) => /*elided*/ any;
2989
+ };
2990
+ /**
2991
+ * Filter `target`'s lookup options by `driver`'s value, matched against
2992
+ * `masterField` on the target's source form. Written in the platform shape —
2993
+ * the rule sits on the target lookup (zvolv-web / ZAI-Dashboard). When the
2994
+ * filter leaves exactly one row the target selects it automatically.
2995
+ */
2996
+ declare function cascade(driver: ElementSpec, target: ElementSpec, masterField: string): void;
2997
+ interface FormSpec {
2998
+ title: string;
2999
+ zappId: string | number;
3000
+ /** Zapp name, for the MASTER tag "<name> <id>". */
3001
+ zappName: string;
3002
+ type?: "MASTER" | "WORKFLOW" | "NESTED";
3003
+ description?: string;
3004
+ elements: ElementSpec[];
3005
+ successMsg?: string;
3006
+ }
3007
+ /** The `payload` for the MCP `create_form` tool. */
3008
+ declare function defineForm(spec: FormSpec): {
3009
+ elements: ElementSpec[];
3010
+ configurations?: {
3011
+ successMsg: string;
3012
+ } | undefined;
3013
+ title: string;
3014
+ type: "MASTER" | "WORKFLOW" | "NESTED";
3015
+ zappId: string[];
3016
+ tags: string[];
3017
+ description: string;
3018
+ };
3019
+ /**
3020
+ * A FORM widget payload for `create_widget`. The host app renders it with
3021
+ * <ZvolvForm>; `mode` NEW captures a submission, EDIT/DISABLED show one.
3022
+ */
3023
+ declare function formWidget(o: {
3024
+ formId: string;
3025
+ title: string;
3026
+ description?: string;
3027
+ mode?: "NEW" | "EDIT" | "DISABLED";
3028
+ submissionId?: string;
3029
+ submitLabel?: string;
3030
+ layout?: {
3031
+ x: number;
3032
+ y: number;
3033
+ w: number;
3034
+ h: number;
3035
+ };
3036
+ workflowTypeId?: number;
3037
+ }): {
3038
+ DataSource: {
3039
+ version: string;
3040
+ active: boolean;
3041
+ formId: string;
3042
+ fields: never[];
3043
+ };
3044
+ Configuration: {
3045
+ additionalProperties: {
3046
+ x: number;
3047
+ y: number;
3048
+ w: number;
3049
+ h: number;
3050
+ formId: string;
3051
+ };
3052
+ submitLabel?: string | undefined;
3053
+ submissionId?: string | undefined;
3054
+ version: string;
3055
+ formId: string;
3056
+ mode: "NEW" | "EDIT" | "DISABLED";
3057
+ };
3058
+ Layout: {
3059
+ x: number;
3060
+ y: number;
3061
+ cols: number;
3062
+ rows: number;
3063
+ };
3064
+ WorkflowTypeID?: number | undefined;
3065
+ Title: string;
3066
+ Type: string;
3067
+ Description: string;
3068
+ };
3069
+
3070
+ export { ActionCardWidget, type ActionCardWidgetProps, type ActionConfig, type ActionItem, type ActionOutcome, type ActionRenderArgs, ActivityFeedWidget, type AggregationType, AreaChartWidget, type AxisConfig, BLOCKED_FILE_EXTENSIONS, type BadgeTone, BannerWidget, BarChartWidget, COLUMN_FILTER_BLANK, CONTAINER_KINDS, CalendarWidget, CardListWidget, CarouselWidget, type CellArgs, type ChartConfig, type ChartRenderArgs, ChartWidget, type ChartWidgetProps, ChildTableWidget, type CollectionConfig, type CollectionItem, type CollectionMappingConfig, type CollectionRenderArgs, CollectionWidget, type CollectionWidgetProps, type ColumnFilterSlotArgs, type ColumnFilters, type CreateZvolvRuntimeOptions, type DashboardFilterDef, type DashboardFilterValue, type DashboardNode, DashboardTableWidget, type DataSourceDefinition, type DataSourceField, DatabaseTableWidget, type DateGapUnit, type DateRange, type DateRangeToken, type DateToken, type DeepPartial, DefaultField, type DefaultInsight, DoughnutChartWidget, EMPTY_INTERACTIONS, type ElementSpec, EntityGalleryWidget, type FieldFilter, type FieldKind, type FieldOption, type FieldOptionsState, type FileFieldState, type FileItem, type FilterControl, type FilterInsight, type FilterOperator, type FilterPanelConfig, type FilterPanelRenderArgs, FilterPanelWidget, type FilterPanelWidgetProps, type FilterableField, FormApiContext, type FormConfig, type FormDefinition, type FormElement, type FormErrors, type FormField, FormFields, type FormInspection, type FormKit, FormKitSlot, type FormMode, type FormSpec, type FormStatus, type FormValues, FormWidget, type FormWidgetProps, type FormulaInsight, GRID, GanttChartWidget, type GaugeConfig, GaugeMeterWidget, type GaugeMeterWidgetProps, type GaugeRenderArgs, GoogleMapWidget, GridCardWidget, type GridItem, type HeatCell, type HeatMapConfig, type HeatMapRenderArgs, HeatMapWidget, type HeatMapWidgetProps, type HtmlConfig, type HtmlRenderArgs, HtmlWidget, type HtmlWidgetProps, type IframeConfig, IframeWidget, type IframeWidgetProps, type InteractionMode, type InteractionProps, type InteractionStateProps, type InteractionUiProps, type InteractiveWidgetData, type InteractiveWidgetProps, KPI_DEFAULT_TEMPLATES, type KpiConfig, type KpiContentConfig, type KpiContentVM, Delta as KpiDelta, Label as KpiLabel, Sparkline as KpiSparkline, type KpiTemplateId, type KpiTemplateProps, Value as KpiValue, KpiWidget, type KpiWidgetProps, type LegendConfig, LineChartWidget, type LookupConfig, type MapConfig, type MapMarker, type MapRenderArgs, type MapWidgetProps, type MasterFieldDataType, type MasterFieldType, MeetingSchedulerWidget, type MockQuery, type MockRuntimeOptions, NON_INPUT_TYPES, NON_RENDERING_TYPES, type NormalizedWidget, type OpenFormRequest, PREFIX_UNITS, type PayloadInsight, PieChartWidget, type PivotConfig, type PivotFilter, PivotGridWidget, type PivotGridWidgetProps, type PivotRenderArgs, type PivotRow, type PivotSummary, type PostOperation, type PostOperator, RankingBarWidget, type RankingBarWidgetProps, type RankingConfig, type RankingRenderArgs, type RankingRow, RawHtmlWidget, type ResolvedChromeConfig, type RuleEffect, type RuleInsight, type RuleOverride, SAMPLE_ROWS, SUBMISSION_SKIP_TYPES, SUFFIX_UNITS, ScatterChartWidget, type SearchSlotArgs, type SeriesConfig, type SheetColumn, type SheetFieldState, type SortDirection, type SortSlotArgs, type SortState, type StepItem, type StepperConfig, type StepperRenderArgs, StepperWidget, type StepperWidgetProps, type SubmitOptions, type TabConfig, type TabItem, type TabRenderArgs, TabWidget, type TabWidgetProps, type TableColumn, type TableColumnConfig, type TableConfig, type TableRenderArgs, TableWidget, type TableWidgetProps, TaskTrackerTableWidget, type TemplateComponent, type TemplateMap, TemplateProvider, type TemporalConfig, type TemporalEvent, type TemporalMappingConfig, type TemporalRenderArgs, TemporalWidget, type TemporalWidgetProps, TimelineWidget, type Tone, type ToolbarSlotArgs, type TreeConfig, type TreeNode, type TreeRenderArgs, TreeWidget, type TreeWidgetProps, type TrialButton, type TrialFieldState, type TrialLogEntry, type UploadedFile, type UseKpiContentsArgs, type UseWidgetDataArgs, type UseZvolvFormArgs, type ValidationInsight, WIDGET_REGISTRY, type WidgetChrome, type WidgetChromeConfig, type WidgetConfigurations, type WidgetDataResult, type WidgetDefinition, type WidgetFilter, type WidgetFilterSlotArgs, type WidgetInteractionState, type WidgetInteractions, WidgetShell, type WidgetShellProps, type WidgetState, type WidgetStateRenderArgs, WidgetStateSlot, type WidgetStyleOverrides, type WidgetTypeId, ZaiChatWidget, type ZaiChatWidgetProps, type ZvolvDataSource, ZvolvForm, type ZvolvFormApi, type ZvolvFormProps, ZvolvProvider, type ZvolvProviderProps, type ZvolvRuntime, ZvolvThemeProvider, type ZvolvTokens, ZvolvWidget, type ZvolvWidgetProps, aggregate, alignSummaryToSeries, applyLocalColumnFilters, applyLocalSearch, applyLocalSort, applyLocalWidgetFilters, applyPostOperations, applyRules, automationSource, buildColumnFilterClauses, buildDashFilters, buildDashboardTree, buildInitialValues, buildRemoteSort, buildSearchClause, buildSubmissionElements, buildTree, buildTriggerBody, buildWidgetFilterClauses, cascade, cdateFiltersFor, childIdsOf, cleanTitle, clearLookupCache, coerceSeriesNumbers, computeRowFormulas, createMockRuntime, createSubmission, createZvolvRuntime, dashboardDefaultDateToken, dashboardFilterDefs, dateRangeFor, defaultTokens, defineConfig, defineForm, derive, describeWidgetFilter, distinctColumnValues, eid, el, evaluateFormula, extractAgentFormData, fetchForm, fetchLookupOptions, fetchSubmission, field, fieldKind, fieldKindOf, fillDateGaps, filterableFields, formSource, formWidget, formatAmountValue, formatCompact, formatFieldValue, formulaLabels, getDataType, getEmptyValue, getPostOpOperandSet, getPostOpResult, gridHeight, gridWidgets, groupBy, hasActiveInteractions, inspectForm, interpolate, invokeAgent, invokeTrigger, invokeZeno, isDataSourceConfigured, isLegacyId, isLikelyTimestamp, isServerSafeFormula, lookupConfigOf, mergeTokens, normaliseElement, normaliseForm, normalizeWidget, openFormRequest, operatorsForKind, optionFilterRules, parseConfig, parseDeep, pivot, renderHtmlVariables, resetQueryUser, resolveChrome, resolveChromeConfig, resolveCollectionMapping, resolveDashboardLayout, resolveDateToken, resolveDrillDown, resolveFieldType, resolveFilterMode, resolveFormWidget, resolveSeries, resolveTableMode, resolveWidget, resolveWidgetDefaults, resolveXKey, rowSubmissionIds, ruleMatches, rulesOf, searchPeople, serializeElementValue, statusTone, submissionIdOf, submissionToValues, submitElementsOf, taskField, taskSource, toBraceFormula, toNum, toRelational, toneColor, toneSurface, updateSubmission, uploadFile, useCollectionItems, useFieldOptions, useFileField, useFormApi, useFormInspector, useInteractiveWidgetData, useKpiContents, useSheetField, useTableColumns, useTemplateOverride, useTemporalEvents, useTokens, useTrialField, useWidgetData, useWidgetInteractions, useZvolvClient, useZvolvForm, useZvolvRuntime, usesFormFramework, validateField, validateForm, when, where };