@evotecit/canopyx 0.3.15 → 0.3.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/CanopyX.Html/Assets/canopyx-board.css +50 -0
  2. package/CanopyX.Html/Assets/canopyx-board.js +39 -0
  3. package/CanopyX.Html/Assets/canopyx-buckets.js +15 -0
  4. package/CanopyX.Html/Assets/canopyx-calculations.css +7 -0
  5. package/CanopyX.Html/Assets/canopyx-calculations.js +52 -0
  6. package/CanopyX.Html/Assets/canopyx-calendar-edit.js +3 -3
  7. package/CanopyX.Html/Assets/canopyx-calendar.css +5 -24
  8. package/CanopyX.Html/Assets/canopyx-calendar.js +14 -19
  9. package/CanopyX.Html/Assets/canopyx-cell-range.js +16 -14
  10. package/CanopyX.Html/Assets/canopyx-changes.css +6 -24
  11. package/CanopyX.Html/Assets/canopyx-changes.js +18 -15
  12. package/CanopyX.Html/Assets/canopyx-compare.css +37 -0
  13. package/CanopyX.Html/Assets/canopyx-compare.js +12 -0
  14. package/CanopyX.Html/Assets/canopyx-data.js +3 -3
  15. package/CanopyX.Html/Assets/canopyx-editing.css +2 -2
  16. package/CanopyX.Html/Assets/canopyx-editing.js +2 -2
  17. package/CanopyX.Html/Assets/canopyx-enhance.js +4 -4
  18. package/CanopyX.Html/Assets/canopyx-export.js +54 -13
  19. package/CanopyX.Html/Assets/canopyx-facets.css +14 -5
  20. package/CanopyX.Html/Assets/canopyx-facets.js +19 -15
  21. package/CanopyX.Html/Assets/canopyx-filter-editor.css +71 -85
  22. package/CanopyX.Html/Assets/canopyx-filter-editor.js +20 -16
  23. package/CanopyX.Html/Assets/canopyx-flow-checks.css +2 -0
  24. package/CanopyX.Html/Assets/canopyx-flow-checks.js +5 -4
  25. package/CanopyX.Html/Assets/canopyx-flow-dialog.css +2 -0
  26. package/CanopyX.Html/Assets/canopyx-flow-dialog.js +1 -1
  27. package/CanopyX.Html/Assets/canopyx-flow-entry.css +136 -12
  28. package/CanopyX.Html/Assets/canopyx-flow-entry.js +5 -5
  29. package/CanopyX.Html/Assets/canopyx-flow-facts.js +2 -0
  30. package/CanopyX.Html/Assets/canopyx-flow-module.mjs +5 -5
  31. package/CanopyX.Html/Assets/canopyx-flow.js +8 -7
  32. package/CanopyX.Html/Assets/canopyx-format-editor.js +2 -2
  33. package/CanopyX.Html/Assets/canopyx-formatting.js +10 -9
  34. package/CanopyX.Html/Assets/canopyx-grid-module.mjs +185 -131
  35. package/CanopyX.Html/Assets/canopyx-grid.css +228 -96
  36. package/CanopyX.Html/Assets/canopyx-grid.js +185 -131
  37. package/CanopyX.Html/Assets/canopyx-grouping.css +22 -15
  38. package/CanopyX.Html/Assets/canopyx-grouping.js +24 -17
  39. package/CanopyX.Html/Assets/canopyx-interactive.css +197 -74
  40. package/CanopyX.Html/Assets/canopyx-interactive.js +38 -45
  41. package/CanopyX.Html/Assets/canopyx-labels-de.js +177 -9
  42. package/CanopyX.Html/Assets/canopyx-labels-es.js +177 -9
  43. package/CanopyX.Html/Assets/canopyx-labels-fr.js +176 -8
  44. package/CanopyX.Html/Assets/canopyx-labels-it.js +176 -8
  45. package/CanopyX.Html/Assets/canopyx-labels-pl.js +176 -8
  46. package/CanopyX.Html/Assets/canopyx-layouts.css +48 -20
  47. package/CanopyX.Html/Assets/canopyx-layouts.js +36 -14
  48. package/CanopyX.Html/Assets/canopyx-link.js +2 -2
  49. package/CanopyX.Html/Assets/canopyx-live.css +1 -3
  50. package/CanopyX.Html/Assets/canopyx-live.js +20 -15
  51. package/CanopyX.Html/Assets/canopyx-matrix.css +1 -8
  52. package/CanopyX.Html/Assets/canopyx-matrix.js +11 -11
  53. package/CanopyX.Html/Assets/canopyx-module.mjs +38 -45
  54. package/CanopyX.Html/Assets/canopyx-office-export.js +2936 -0
  55. package/CanopyX.Html/Assets/canopyx-path.css +45 -0
  56. package/CanopyX.Html/Assets/canopyx-path.js +28 -0
  57. package/CanopyX.Html/Assets/canopyx-pivot.css +75 -0
  58. package/CanopyX.Html/Assets/canopyx-pivot.js +72 -0
  59. package/CanopyX.Html/Assets/canopyx-plan.css +56 -0
  60. package/CanopyX.Html/Assets/canopyx-plan.js +67 -0
  61. package/CanopyX.Html/Assets/canopyx-presenters.js +2 -2
  62. package/CanopyX.Html/Assets/canopyx-record-panel.css +11 -2
  63. package/CanopyX.Html/Assets/canopyx-record-panel.js +18 -12
  64. package/CanopyX.Html/Assets/canopyx-reporting-module.mjs +225 -164
  65. package/CanopyX.Html/Assets/canopyx-reporting.css +240 -107
  66. package/CanopyX.Html/Assets/canopyx-reporting.js +225 -164
  67. package/CanopyX.Html/Assets/canopyx-stack.css +35 -0
  68. package/CanopyX.Html/Assets/canopyx-stack.js +24 -0
  69. package/CanopyX.Html/Assets/canopyx-time-slider.css +18 -0
  70. package/CanopyX.Html/Assets/canopyx-time-slider.js +27 -0
  71. package/CanopyX.Html/Assets/canopyx-timeline.js +6 -5
  72. package/CanopyX.Html/Assets/canopyx-tree-tools.css +36 -35
  73. package/CanopyX.Html/Assets/canopyx-tree-tools.js +15 -12
  74. package/CanopyX.Html/Assets/canopyx-ui-menu.css +41 -0
  75. package/CanopyX.Html/Assets/canopyx-ui-menu.js +64 -0
  76. package/CanopyX.Html/Assets/canopyx-ui-navigation.css +73 -0
  77. package/CanopyX.Html/Assets/canopyx-ui-navigation.js +39 -0
  78. package/CanopyX.Html/Assets/canopyx-ui-overlays.css +79 -0
  79. package/CanopyX.Html/Assets/canopyx-ui-overlays.js +42 -0
  80. package/CanopyX.Html/Assets/canopyx-ui-picker.css +12 -0
  81. package/CanopyX.Html/Assets/canopyx-ui-picker.js +6 -0
  82. package/CanopyX.Html/Assets/canopyx-ui-stepper.css +174 -0
  83. package/CanopyX.Html/Assets/canopyx-ui-stepper.js +48 -0
  84. package/CanopyX.Html/Assets/canopyx-ui-tabs.css +153 -0
  85. package/CanopyX.Html/Assets/canopyx-ui-tabs.js +47 -0
  86. package/CanopyX.Html/Assets/canopyx-values.css +5 -0
  87. package/CanopyX.Html/Assets/canopyx-values.js +13 -0
  88. package/CanopyX.Html/Assets/canopyx-view-intents.css +12 -0
  89. package/CanopyX.Html/Assets/canopyx-view-intents.js +56 -0
  90. package/CanopyX.Html/Assets/canopyx.css +197 -71
  91. package/CanopyX.Html/Assets/canopyx.js +29 -19
  92. package/JavaScript/board.d.ts +30 -0
  93. package/JavaScript/changes.d.ts +4 -1
  94. package/JavaScript/facets.d.ts +5 -3
  95. package/JavaScript/flow.d.ts +6 -0
  96. package/JavaScript/grid.d.ts +153 -17
  97. package/JavaScript/hosts.d.ts +14 -1
  98. package/JavaScript/index.d.ts +4 -2
  99. package/JavaScript/live.d.ts +2 -0
  100. package/JavaScript/locales/de.mjs +177 -9
  101. package/JavaScript/locales/es.mjs +177 -9
  102. package/JavaScript/locales/fr.mjs +176 -8
  103. package/JavaScript/locales/it.mjs +176 -8
  104. package/JavaScript/locales/pl.mjs +176 -8
  105. package/JavaScript/matrix.d.ts +4 -1
  106. package/JavaScript/path.d.ts +33 -0
  107. package/JavaScript/pivot.d.ts +135 -0
  108. package/JavaScript/plan.d.ts +23 -0
  109. package/JavaScript/protocol.d.ts +16 -3
  110. package/JavaScript/records.d.ts +20 -4
  111. package/JavaScript/stack.d.ts +28 -0
  112. package/JavaScript/time-slider.d.ts +58 -0
  113. package/JavaScript/ui.d.ts +261 -0
  114. package/JavaScript/view-intents.d.ts +45 -0
  115. package/README.md +22 -3
  116. package/ThirdParty/OfficeIMO/LICENSE +21 -0
  117. package/ThirdParty/OfficeIMO/README.md +13 -0
  118. package/package.json +76 -3
@@ -1,13 +1,25 @@
1
+ import type { GridPathDefinition } from "./path.js";
2
+ export * from "./path.js";
3
+ import type { GridStackDefinition } from "./stack.js";
4
+ export * from "./stack.js";
5
+ export * from "./time-slider.js";
1
6
  import CanopyX from "./index.js";
7
+ import type { GridBoardDefinition, GridBoardMove, GridBoardState } from "./board.js";
8
+ export * from "./board.js";
9
+ import type { GridPlanDefinition, GridPlanOptions, GridPlanChangeProposal } from "./plan.js";
10
+ export * from "./plan.js";
11
+ import type { GridViewIntentApi } from "./view-intents.js";
12
+ export type { GridViewIntent, GridViewIntentPreview, GridViewIntentApi } from "./view-intents.js";
2
13
  import type { TreeGrid } from "./index.js";
3
14
  import type { CanopyColumn, CanopyLabels, Cell, CellValue, SortDirection, TimeZone, SearchHighlightOptions, LayoutOptions, LayoutState, ViewModeMethods } from "./protocol.js";
4
15
  import type { HostOptions, ExportFormat, ExportFormatOptions, ExportFormatResult, ExportMenuOptions, LinkedView } from "./hosts.js";
5
16
  import type { CanopyPlugin } from "./plugins.js";
6
17
  import type { GridEditorDefinition, GridValidation, GridEditingSettings, GridEditingOptions, GridEditingApi, GridCellValueChange,
7
18
  GridRowCommit, GridCommitRowResult, GridCommitOutcome, GridCommit, GridCommitResult } from "./editing.js";
8
- import type { RecordPanelDefinition, RecordLoader, RecordSectionRenderer, RecordAction, RecordOpenAll, OpenRecordOptions } from "./records.js";
19
+ import type { RecordPanelDefinition, RecordPanelOptions, RecordLoader, RecordSectionRenderer, RecordAction, RecordOpenAll, OpenRecordOptions } from "./records.js";
9
20
  export * from "./records.js";
10
21
  export * from "./index.js";
22
+ export * from "./ui.js";
11
23
  export * from "./enhance.js";
12
24
  import type { enhance, grid } from "./enhance.js";
13
25
  export * from "./editing.js";
@@ -23,6 +35,8 @@ import type { GridCalendarDefinition, GridCalendarOptions, GridCalendarApi, Grid
23
35
  export * from "./facets.js";
24
36
  export * from "./calendar.js";
25
37
  export * from "./live.js";
38
+ import type { GridPivotApi, GridPivotDefinition, GridPivotState, GridPivotQuery, GridPivotAcceptedResult, GridPivotExportAxisPresentation, GridPivotExportDescriptor } from "./pivot.js";
39
+ export * from "./pivot.js";
26
40
 
27
41
  /** A stable record identity and typed cells. Flat records have no tree fields. */
28
42
  export interface GridRow { id: string; cells: Record<string, Cell>; tone?: string; className?: string;
@@ -44,6 +58,9 @@ export type GridHighlightRule = GridBuiltinFilter & { target?: "row" | "cell" }
44
58
  export interface GridExportCell {
45
59
  readonly value: CellValue;
46
60
  readonly text: string;
61
+ /** Pivot-table captures retain numeric display modes and native number formats. */
62
+ readonly mode?: GridShowAs;
63
+ readonly numberFormat?: string;
47
64
  readonly tone?: string;
48
65
  readonly link?: { readonly target: string; readonly tooltip?: string };
49
66
  /** The cell's conditional formatting, present when the grid has rules that format it. CSV reads only value and text. */
@@ -52,7 +69,7 @@ export interface GridExportCell {
52
69
  readonly diagnostics?: readonly string[];
53
70
  }
54
71
  /** An immutable record projected onto the declared export columns. Group headings and summaries are not records. */
55
- export interface GridExportRow {
72
+ export interface GridExportRow extends Partial<GridPivotExportAxisPresentation> {
56
73
  readonly id: string; readonly cells: Readonly<Record<string, GridExportCell>>;
57
74
  readonly tone?: string; readonly diagnostics?: readonly string[];
58
75
  /** The record's row formatting, present when a row rule matched it. */
@@ -61,11 +78,15 @@ export interface GridExportRow {
61
78
  readonly detail?: Extract<GridRowDetail, { type: "table" | "properties" | "html" }>;
62
79
  }
63
80
  /** Captured column intent. Hosts map semantic tones and CSS pixel widths into their output format. */
64
- export interface GridExportColumn {
81
+ export interface GridExportColumn extends Partial<GridPivotExportAxisPresentation> {
65
82
  readonly id: string; readonly title: string; readonly kind: "text" | "number" | "datetime";
83
+ /** Present on numeric pivot-table columns. */
84
+ readonly aggregate?: string;
66
85
  /** Reporting runtime only. */
67
86
  readonly width?: { readonly unit: "css-px"; readonly preferred: number; readonly minimum: number; readonly maximum?: number };
68
87
  readonly wrap?: boolean; readonly alignment?: "left" | "right";
88
+ /** The effective pin in the captured layout; null when the column is unpinned. */
89
+ readonly pinned?: "left" | "right" | null;
69
90
  readonly presenter?: GridPresenter;
70
91
  /** The column number format that produced the display text. */
71
92
  readonly format?: GridNumberFormat;
@@ -135,7 +156,19 @@ export type GridColumn<Row extends GridRow = GridRow> = Omit<CanopyColumn, "id"
135
156
  alwaysVisible?: boolean;
136
157
  /** Hover tooltip: "auto" shows a cell's full value while it is cut off; a declared column id shows that column's text. */
137
158
  tooltip?: string;
138
- };
159
+ } & (
160
+ | { readonly calculation?: never }
161
+ /** A bounded expression over raw row values. Calculated cells are read-only; hosted values come from the server. */
162
+ | { readonly calculation: string; editable?: false }
163
+ );
164
+ /** One reader-editable calculation definition; all authored calculation IDs must remain in the submitted set. */
165
+ export interface GridCalculatedColumnDefinition {
166
+ readonly id: string;
167
+ readonly title: string;
168
+ readonly kind: "text" | "number" | "datetime";
169
+ /** One to 2048 UTF-16 code units, parsed as the bounded calculation grammar. */
170
+ readonly expression: string;
171
+ }
139
172
  export type GridColumnPriority = "essential" | "normal" | "optional" | number;
140
173
  export interface GridSort { readonly column: string; readonly direction: SortDirection; }
141
174
  /** Code-unit collation; natural digit runs never convert to floating-point numbers. */
@@ -154,6 +187,7 @@ export type GridPresenter =
154
187
  | { readonly kind: "longText"; readonly mono?: boolean }
155
188
  | { readonly kind: "enum" | "state"; readonly tones?: Readonly<Record<string,string>>; /** Tones shown as plain text instead of a chip or dot. */ readonly quietTones?: readonly string[]; /** Quiet values muted (default) or in the normal text colour. */ readonly quietStyle?: "muted" | "plain" }
156
189
  | { readonly kind: "change"; readonly deltaColumn: string; readonly higherIsGood?: boolean }
190
+ | { readonly kind: "change"; readonly beforeAfter: true }
157
191
  | { readonly kind: "statusStrip" | "missing" }
158
192
  | ({ readonly kind: "sparklineBars" | "sparklineLine" } & GridHistoryPresentation)
159
193
  | { readonly kind: "identifier"; readonly secondaryColumn?: string; readonly mono?: boolean }
@@ -186,6 +220,10 @@ export interface GridPager {
186
220
  }
187
221
  /** Include the reporting entry point when this optional capability set is present. */
188
222
  export interface GridReporting {
223
+ /** Initial full-query pivot; requires offset navigation and declared aggregates. */
224
+ readonly pivot?: GridPivotDefinition;
225
+ /** Readers can configure pivots over declared sortable/filterable fields and aggregates. */
226
+ readonly pivotable?: boolean;
189
227
  /** Fixed first ordering key. Group headings and collapse never change record paging/counts/exports. */
190
228
  readonly grouping?: GridSort & { readonly headerTemplate?: string };
191
229
  /** Initial runtime grouping levels, outermost first (at most four). Not combined with grouping. */
@@ -271,14 +309,14 @@ export type GridAction<Q extends AcceptedGridQuery = GridQuery> =
271
309
  /** render fills container on the entry's first open (and again after a render that threw); close() closes the menu and
272
310
  * focuses its button; signal aborts when the grid is destroyed. */
273
311
  | { label: string; render: (container: HTMLElement, context: { close(): void; signal: AbortSignal }) => void; run?: never };
274
- export type GridBuiltinFilter = {
312
+ export type GridBuiltinFilter = ({
275
313
  readonly column: string;
276
314
  readonly operator: "eq" | "ne" | "contains" | "startsWith" | "in" | "gt" | "ge" | "lt" | "le";
277
315
  readonly values: readonly Exclude<CellValue, null>[];
278
- } | { readonly column: string; readonly operator: "isNull" | "isNotNull"; readonly values: readonly []; };
316
+ } | { readonly column: string; readonly operator: "isNull" | "isNotNull"; readonly values: readonly []; }) & { readonly bucket?: GridBucket };
279
317
 
280
318
  /** A registered custom operator uses one typed, non-null operand. */
281
- export type GridFilter = GridBuiltinFilter | { readonly column: string; readonly operator: string & {}; readonly values: readonly Exclude<CellValue, null>[] };
319
+ export type GridFilter = GridBuiltinFilter | { readonly column: string; readonly operator: string & {}; readonly values: readonly Exclude<CellValue, null>[]; readonly bucket?: never };
282
320
 
283
321
  /** A nonempty nested expression: at most eight levels, 64 groups and 64 total predicates including flat filters. */
284
322
  export interface GridFilterGroup {
@@ -287,6 +325,16 @@ export interface GridFilterGroup {
287
325
  readonly groups: readonly GridFilterGroup[];
288
326
  }
289
327
 
328
+ /** A raw or bucketed field in an exact correlated tuple. */
329
+ export interface GridTupleColumn { readonly column: string; readonly bucket?: GridBucket; }
330
+ /** One to six fields and one to 200 equally wide tuples. Strings are exact; null is an explicit missing value. */
331
+ export interface GridTupleFilter {
332
+ readonly columns: readonly GridTupleColumn[];
333
+ readonly values: readonly (readonly CellValue[])[];
334
+ /** Complements membership, including rows containing null. Defaults to false. */
335
+ readonly exclude?: boolean;
336
+ }
337
+
290
338
  /** A frozen accepted query. Sorting/filtering cover the entire source before the requested window. */
291
339
  export interface GridQuery {
292
340
  readonly protocol: "canopyx/2";
@@ -297,11 +345,13 @@ export interface GridQuery {
297
345
  readonly limit: number;
298
346
  readonly search: string;
299
347
  /** Absent preserves substring matching; words matches all words/quoted phrases across searchable cells. */
300
- readonly searchMode?: "substring" | "words";
348
+ readonly searchMode?: "substring" | "words" | "regex";
301
349
  readonly sort: readonly GridSort[];
302
350
  readonly filters: readonly GridFilter[];
303
351
  /** Combined with search and flat filters using AND. */
304
352
  readonly filterGroup?: GridFilterGroup;
353
+ /** At most eight atomic predicates, AND-combined with the other query criteria. Empty input is omitted. */
354
+ readonly tupleFilters?: readonly GridTupleFilter[];
305
355
  /** Runtime grouping levels (reporting groupBy/groupable definitions); omitted input uses the declared levels, [] ungroups. */
306
356
  readonly groupBy?: readonly GridGroupLevel[];
307
357
  }
@@ -314,7 +364,21 @@ export type AcceptedGridQuery = GridQuery | GridCursorQuery;
314
364
  export type GridQueryInput<Q extends AcceptedGridQuery = GridQuery> = Partial<Q>;
315
365
  type GridCount<Q extends AcceptedGridQuery> = Q extends GridCursorQuery ? number | null : number;
316
366
 
367
+ /** Complete summary counts remain stable when the displayed comparison is filtered. */
368
+ export interface DatasetCompare {
369
+ readonly statusColumn: string;
370
+ readonly counts: Readonly<{ added: number; removed: number; changed: number; unchanged: number }>;
371
+ /** Changed matched-cell counts by declared column, excluding added and removed rows. */
372
+ readonly columns: Readonly<Record<string, number>>;
373
+ readonly onlyChanges: boolean;
374
+ }
317
375
  interface GridDefinition<Q extends AcceptedGridQuery = GridQuery, Row extends GridRow = GridRow> {
376
+ /** Enables the calculated-column editor and saved definitions. Only built-in inline sources support it. */
377
+ calculatedColumnsEditable?: boolean;
378
+ /** Complete keyed comparison metadata; loads the optional comparison controls. */
379
+ compare?: DatasetCompare;
380
+ /** Carry the optional validated view-intent preview part. No model or transport is provided. */
381
+ viewIntents?: boolean;
318
382
  protocol: "canopyx/2";
319
383
  type: "grid";
320
384
  id: string;
@@ -352,6 +416,12 @@ interface GridDefinition<Q extends AcceptedGridQuery = GridQuery, Row extends Gr
352
416
  searchHighlight?: boolean | SearchHighlightOptions;
353
417
  /** The Layout menu: fit, scroll and cards, and the density (docs/layout-modes.md); layout.density starts the grid at that density. */
354
418
  layout?: LayoutOptions;
419
+ /** Literal templates keyed by card column slot. {columnId} inserts formatted text; markup is never parsed. */
420
+ cardTemplate?: Readonly<Record<string, string>>;
421
+ /** Follow page scrolling only when an auto-height grid fits all rows. Default false. */
422
+ stickyHeader?: boolean;
423
+ /** Permit searchMode: "regex" with the bounded condition grammar. Default false. */
424
+ allowRegexSearch?: boolean;
355
425
  /** Wire documents retain numeric rowHeight and enable measurement with this optional flag. */
356
426
  autoRowHeight?: boolean;
357
427
  /** Minimum and estimate for the rowHeight: "auto" API shorthand (20..64, default 28). */
@@ -391,6 +461,12 @@ interface GridDefinition<Q extends AcceptedGridQuery = GridQuery, Row extends Gr
391
461
  facets?: GridFacetPanelDefinition<Row>;
392
462
  /** Shows the records as a calendar: month, week, day, N days, agenda, year and the resource timeline (calendar.d.ts). */
393
463
  calendar?: GridCalendarDefinition<Row>;
464
+ /** Lane cards with the grid's search, facets, saved views and record panel; loaded as an optional part. */
465
+ path?: GridPathDefinition;
466
+ stack?: GridStackDefinition;
467
+ board?: GridBoardDefinition;
468
+ /** Dependencies, baseline and governed proposals on the calendar's resource timeline. */
469
+ plan?: GridPlanDefinition;
394
470
  /** Rows can be dragged out (or picked up with F2) onto a calendar that accepts drops. */
395
471
  dragRows?: boolean;
396
472
  stateKey?: string;
@@ -430,8 +506,9 @@ export interface GridRowData {
430
506
  }
431
507
  /** An inline grid whose rows the data part decodes from compact row data, chunk by chunk, after the first paint. */
432
508
  export interface CompactGridView<Row extends GridRow = GridRow> extends GridDefinition<GridQuery, Row> { source: { kind: "inline"; navigation?: "offset" }; rowData: GridRowData; rows?: never; }
433
- export interface HostGridView<Row extends GridRow = GridRow> extends GridDefinition<GridQuery, Row> { source: { kind: "host"; navigation?: "offset" }; rows?: never; }
509
+ export interface HostGridView<Row extends GridRow = GridRow> extends GridDefinition<GridQuery, Row> { calculatedColumnsEditable?: false; source: { kind: "host"; navigation?: "offset" }; rows?: never; }
434
510
  export interface CursorGridView<Row extends GridRow = GridRow> extends GridDefinition<GridCursorQuery, Row> {
511
+ calculatedColumnsEditable?: false;
435
512
  source: { kind: "host"; navigation: "cursor" };
436
513
  presentation: "paged";
437
514
  rows?: never;
@@ -452,13 +529,15 @@ export interface GridPage<Row extends GridRow = GridRow> {
452
529
  items: Row[];
453
530
  }
454
531
  /** Hosts own data access, authorization and query execution; cancellation does not grant write authority. */
455
- export interface GridFacetOptions { readonly search?: string; readonly limit?: number; readonly includeCurrentFilter?: boolean; readonly signal?: AbortSignal; }
532
+ export interface GridFacetOptions { readonly search?: string; readonly limit?: number; readonly includeCurrentFilter?: boolean; readonly signal?: AbortSignal; readonly bucket?: GridBucket; }
456
533
  /** Facet values/counts ignore the query window and sort; excluding the current column replaces its predicates by true. */
457
534
  export interface GridFacetQuery<Q extends AcceptedGridQuery = AcceptedGridQuery> {
535
+ readonly bucket?: GridBucket;
458
536
  readonly protocol: "canopyx/2"; readonly type: "gridFacetQuery"; readonly query: Q & { readonly revision: string };
459
537
  readonly column: string; readonly search: string; readonly limit: number; readonly includeCurrentFilter: boolean;
460
538
  }
461
539
  export interface GridFacetPage {
540
+ readonly bucket?: GridBucket;
462
541
  readonly protocol: "canopyx/2"; readonly type: "gridFacetPage"; readonly view: string; readonly revision: string;
463
542
  readonly column: string; readonly search: string; readonly includeCurrentFilter: boolean;
464
543
  readonly matched: number; readonly totalValues: number; readonly truncated: boolean;
@@ -472,6 +551,8 @@ export interface GridSource<Row extends GridRow = GridRow> extends GridFacetSour
472
551
  query(query: GridQuery, options: { signal: AbortSignal }): GridPage<Row> | PromiseLike<GridPage<Row>>;
473
552
  /** Complete-query metadata, echoing the normalized accepted request, revision and matched count. */
474
553
  summary?(query: GridQuery & { readonly revision: string }, options: { signal: AbortSignal }): GridSummary | PromiseLike<GridSummary>;
554
+ /** Computes the full accepted query, echoing its query/revision; requires an explicit endpoint capability. */
555
+ pivot?(request: GridPivotQuery, options: { signal: AbortSignal }): GridPivotAcceptedResult | PromiseLike<GridPivotAcceptedResult>;
475
556
  /** Saves changed rows (a remote source posts the gridCommit document to its commit endpoint) and answers per row. */
476
557
  commit?(batch: GridCommit, options: { signal: AbortSignal }): GridCommitResult | PromiseLike<GridCommitResult>;
477
558
  /** A record's details when its drawer opens (a gridRecordQuery answered with a gridRecord), as a remote protocol client sends it. */
@@ -488,6 +569,8 @@ export interface GridFooter {
488
569
  readonly aggregates: readonly GridAggregate[];
489
570
  }
490
571
  export interface GridAggregate {
572
+ /** A display transformation; raw aggregates remain unchanged. */
573
+ readonly showAs?: GridShowAs;
491
574
  /** The label is shown beside the value in group headings and the query totals row. */
492
575
  readonly id: string; readonly column: string; readonly label: string;
493
576
  readonly operation: GridAggregateOperation;
@@ -495,7 +578,14 @@ export interface GridAggregate {
495
578
  readonly format?: GridNumberFormat;
496
579
  }
497
580
  /** One runtime grouping level: groups order by value, or by a declared aggregate (nulls last, ties by value). */
581
+ /** Numeric keys partition calendar instants or half-open numeric intervals. Monday and UTC are the calendar defaults. */
582
+ export type GridBucket =
583
+ | { readonly kind: "day" | "week" | "month" | "quarter" | "year" | "hour" | "weekday"; readonly timeZone?: string; readonly firstWeekday?: 0 | 1 | 2 | 3 | 4 | 5 | 6 }
584
+ | { readonly kind: "width"; readonly width: number; readonly origin?: number }
585
+ | { readonly kind: "edges"; readonly edges: readonly number[] };
586
+
498
587
  export interface GridGroupLevel {
588
+ readonly bucket?: GridBucket;
499
589
  readonly column: string; readonly direction: "asc" | "desc"; readonly aggregate?: string;
500
590
  }
501
591
  /** Declared detail rows: one content source (a page template, a plugin detail renderer or a nested view), else record payloads. */
@@ -546,6 +636,14 @@ export interface GridSummary {
546
636
  readonly query: GridQuery & { readonly revision: string }; readonly matched: number;
547
637
  readonly groups: readonly GridGroup[]; readonly aggregates: Readonly<Record<string, number | null>>;
548
638
  }
639
+
640
+ /** Percent modes return fractions; rank uses descending competition order. Null/zero denominators produce null. */
641
+ export type GridShowAs = "value" | "percentGrandTotal" | "percentParent" | "percentColumn" | "percentRow" | "runningTotal" | "rank" | "difference" | "percentChange";
642
+ export interface GridAggregateDisplayValue { readonly value: number | null; readonly mode: GridShowAs; readonly numberFormat: string; }
643
+ export interface GridSummaryDisplay {
644
+ readonly totals: Readonly<Record<string, GridAggregateDisplayValue>>;
645
+ readonly groups: Readonly<Record<string, Readonly<Record<string, GridAggregateDisplayValue>>>>;
646
+ }
549
647
  /** One complete visible page. Null counts remain unknown; ordinal positions do not grant random access. */
550
648
  export interface GridCursorPage<Row extends GridRow = GridRow> extends Omit<GridPage<Row>, "type" | "total" | "matched"> {
551
649
  type: "gridCursorPage";
@@ -586,6 +684,10 @@ export interface GridQuerySelection<Q extends AcceptedGridQuery = GridQuery> {
586
684
  }
587
685
  /** Exports retain the accepted revision, query ordering, columns and selected IDs at invocation. */
588
686
  export interface GridExportRequest<Q extends AcceptedGridQuery = GridQuery> {
687
+ /** Reporting captures preserve the declared native rules for document writers; resolved cell formats stay on rows. */
688
+ readonly formatRules?: readonly GridFormatRule[];
689
+ /** UTC instant captured at invocation, for export metadata. */
690
+ readonly generatedAt?: string;
589
691
  /** Ordinary grids capture text only; the reporting runtime resolves semantic presentation and diagnostics. */
590
692
  readonly presentation: "text" | "semantic";
591
693
  readonly scope: "filtered" | "selected" | "all";
@@ -609,6 +711,8 @@ export interface GridExportRequest<Q extends AcceptedGridQuery = GridQuery> {
609
711
  readonly totals: Readonly<Record<string, number | null>>; readonly groups: readonly (GridGroup & { readonly text: string })[] };
610
712
  /** Records carry their detail payloads. */
611
713
  readonly details?: true;
714
+ /** Explicit full-query pivot table. Rows are enumerated once through the ordinary capture; they are not duplicated here. */
715
+ readonly pivot?: GridPivotExportDescriptor;
612
716
  }
613
717
  /** Record counts refer to the complete captured export scope, including selected-query exclusions. */
614
718
  export interface GridExportProgress {
@@ -636,11 +740,16 @@ export interface GridRowActivation<Row extends GridRow = GridRow> {
636
740
  }
637
741
  export interface GridExportOptions {
638
742
  scope: GridExportRequest["scope"];
743
+ /** Include declared detail payloads; false omits them. Defaults to the detail definition's print policy. */
744
+ includeDetails?: boolean;
745
+ /** Reporting bridge only: capture the active complete pivot table. Requires filtered scope; defaults to record capture.
746
+ * Available for capture, print and host delivery; pivot XLSX/PDF exportAs is not supported yet. */
747
+ pivot?: boolean;
639
748
  /** Defaults to visible exportable columns in their current order. Explicit non-exportable columns are rejected. */
640
749
  columns?: string[];
641
750
  values?: GridExportRequest["values"];
642
751
  signal?: AbortSignal;
643
- /** Client CSV defaults to 50000; clipboard to 10000. Larger results use a host hook. */
752
+ /** Client CSV defaults to 50000; clipboard to 10000; print to 1000 (maximum 10000). Larger results use a host hook. */
644
753
  maxRows?: number;
645
754
  /** Reporting runtime only. A safe basename up to 100 UTF-16 units; hosts append their format extension. */
646
755
  fileName?: string;
@@ -648,7 +757,7 @@ export interface GridExportOptions {
648
757
  locale?: string;
649
758
  /** Reporting runtime only. Overrides the captured display zone without changing the view. */
650
759
  timeZone?: TimeZone;
651
- /** Reporting runtime only. Observational synchronous progress; a throwing callback aborts the operation. */
760
+ /** Observational synchronous progress for print and reporting exports; a throwing callback aborts the operation. */
652
761
  onProgress?: (progress: GridExportProgress) => void;
653
762
  }
654
763
  /** A complete bounded snapshot for a host renderer: at most 10000 records and 4 Mi UTF-16 units. */
@@ -679,6 +788,7 @@ export interface GridState<Q extends AcceptedGridQuery = GridQuery> {
679
788
  scrollTop: number;
680
789
  /** Reporting grouping only. At most 10000 bounded stable keys; omitted from shareable state. */
681
790
  collapsedGroups?: string[];
791
+ aggregateShowAs?: Record<string, GridShowAs>;
682
792
  /** Optional for compatibility with existing continuous snapshots; restored offsets clamp to current results. */
683
793
  paging?: { pageLength: number; offset: number; allRows?: boolean };
684
794
  /** Formatting rules edited at run time, when they differ from the view's; restored with the view. */
@@ -691,6 +801,12 @@ export interface GridState<Q extends AcceptedGridQuery = GridQuery> {
691
801
  facets?: { open: boolean };
692
802
  /** The calendar's view, date, zoom and collapsed resources, in a grid with a calendar. */
693
803
  calendar?: GridCalendarSavedState;
804
+ /** Selected phone lane of an optional board. */
805
+ board?: GridBoardState;
806
+ /** Pivot definition, active mode, collapsed prefixes and compact-screen column choice. */
807
+ pivot?: GridPivotState;
808
+ /** Up to 32 definitions, allowed only when the current view enables calculatedColumnsEditable. */
809
+ calculatedColumns?: readonly GridCalculatedColumnDefinition[];
694
810
  }
695
811
  /** Versioned, bounded preference envelope. Revisions/cursors belong to data, never durable settings. */
696
812
  export type GridPreferenceQuery<Q extends AcceptedGridQuery = GridQuery> = Readonly<Omit<Q, "revision" | "cursor">> & {
@@ -746,12 +862,11 @@ interface GridHostBehavior<Q extends AcceptedGridQuery = GridQuery, Row extends
746
862
  onExport?: (event: { format: string; request: GridExportRequest<Q>; capture: GridExport<Q>; signal: AbortSignal;
747
863
  /** Reporting runtime only. Monotonic record counts and phases; late calls after cancellation are ignored. */
748
864
  reportProgress?: (phase: GridExportProgress["phase"], completed: number) => void }) => void | PromiseLike<void>;
749
- /** Reporting runtime only. Render the complete snapshot through a host-owned renderer; honor cancellation before delivery. */
750
865
  /** After a layout or density switch; the canopyx:layout event carries the same detail. */
751
866
  onLayout?: (detail: LayoutState) => void | boolean;
752
867
  /** After each finished match count and each move between matches; the canopyx:matches event carries the same detail. */
753
868
  onMatches?: (detail: { total: number; current: number; complete: boolean }) => void | boolean;
754
- /** layout asks for stacked records from a grid in the card layout and a table otherwise; print never scrolls. */
869
+ /** Overrides the script-free print renderer. layout is stacked for cards and table otherwise; honor cancellation before delivery. */
755
870
  onPrint?: (event: { snapshot: GridExportSnapshot<Q>; signal: AbortSignal; layout: "table" | "stacked" }) => void | PromiseLike<void>;
756
871
  /** Hosts compose a drawer or details view and restore returnFocus when it closes. */
757
872
  onDetails?: (event: { row: Readonly<Row>; query: Q; signal: AbortSignal; returnFocus: Element | null }) => void | PromiseLike<void>;
@@ -761,6 +876,8 @@ interface GridHostBehavior<Q extends AcceptedGridQuery = GridQuery, Row extends
761
876
  recordSections?: Readonly<Record<string, RecordSectionRenderer>>;
762
877
  /** Actions of the record actions menu, after the built-in ones. */
763
878
  recordActions?: readonly RecordAction[];
879
+ /** Projects a bounded plain-text record title and optional subtitle, without changing record identity. */
880
+ recordHeading?: RecordPanelOptions["recordHeading"];
764
881
  /** Open all in grid of a collection; return false (or cancel canopyx:openAll) to filter the target yourself. */
765
882
  onOpenAll?: (event: RecordOpenAll) => boolean | void;
766
883
  /** Print one record; return false (or cancel canopyx:recordPrint) to print the sheet yourself. */
@@ -787,6 +904,11 @@ interface GridHostBehavior<Q extends AcceptedGridQuery = GridQuery, Row extends
787
904
  editing?: GridEditingOptions<Q>;
788
905
  /** Before a value changes; returning false (or cancelling canopyx:cellValueChanging) keeps the old value. */
789
906
  onCellValueChanging?: (event: GridCellValueChange) => boolean | void;
907
+ /** Accept a board lane proposal with true, reject with false, or let the configured editing writer decide. */
908
+ onBoardMove?: (event: GridBoardMove) => boolean | void | PromiseLike<boolean>;
909
+ plan?: GridPlanOptions;
910
+ /** Cancel a plan proposal before the host callback runs; event return values never change actual dates. */
911
+ onPlanChangeProposal?: (event: GridPlanChangeProposal) => boolean | void;
790
912
  /** After a value changed. */
791
913
  onCellValueChanged?: (event: GridCellValueChange) => void;
792
914
  /** A row whose edits are complete and valid. Return a result (or true, or a promise) to save it, false to keep editing, nothing to leave it in the batch. */
@@ -835,12 +957,22 @@ export type GridOptions<Row extends GridRow = GridRow> = GridHostOptions<GridQue
835
957
  export type CursorGridOptions<Row extends GridRow = GridRow> = GridHostOptions<GridCursorQuery, Row> & { view: CursorGridView<Row>; source: GridCursorSource<Row> };
836
958
 
837
959
  /** Presentation controller. Selection uses stable IDs independently of cached or visible rows. Row (default GridRow) types its view, column methods and live API. */
838
- export interface DataGrid<Q extends AcceptedGridQuery = GridQuery, Row extends GridRow = GridRow> extends GridEditingApi, LinkedView, ViewModeMethods, GridColumnGroupApi, GridCellRangeApi, GridLiveApi<Row, Q>, GridFacetPanelApi, GridCalendarApi {
960
+ export interface DataGrid<Q extends AcceptedGridQuery = GridQuery, Row extends GridRow = GridRow> extends GridPivotApi, GridEditingApi, LinkedView, ViewModeMethods, GridColumnGroupApi, GridCellRangeApi, GridLiveApi<Row, Q>, GridFacetPanelApi, GridCalendarApi, GridViewIntentApi<Q> {
839
961
  readonly element: HTMLElement;
840
962
  readonly view: GridView<Row>;
841
963
  readonly ready: Promise<Q>;
842
964
  getQuery(): Q | null;
965
+ /** Whether the comparison's unchanged rows are excluded by the accepted query. */
966
+ getOnlyChanges(): boolean;
967
+ /** Change the comparison scope through its ordinary status-column filter. */
968
+ setOnlyChanges(enabled: boolean): Promise<Q>;
843
969
  setQuery(query: GridQueryInput<Q>): Promise<Q>;
970
+ /** Immutable definitions of the declared calculated columns; [] when none are configured. */
971
+ getCalculatedColumns(): readonly GridCalculatedColumnDefinition[];
972
+ /** Replaces the complete definition set after validation. Requires calculatedColumnsEditable and built-in inline data. */
973
+ setCalculatedColumns(definitions: readonly GridCalculatedColumnDefinition[]): Promise<readonly GridCalculatedColumnDefinition[]>;
974
+ /** Opens the inline calculated-column editor, optionally anchored to a host element. */
975
+ openCalculatedColumn(anchor?: HTMLElement): Promise<void>;
844
976
  sort(sorts: readonly GridSort[]): Promise<Q>;
845
977
  getPaging(): GridPaging<Q>;
846
978
  /** Offset sources only. Cursor sources reject random page access. */
@@ -889,6 +1021,10 @@ export interface DataGrid<Q extends AcceptedGridQuery = GridQuery, Row extends G
889
1021
  getSelectionDescriptor?(): GridSelection<Q>;
890
1022
  /** Reporting summary capability only; null before acceptance. */
891
1023
  getSummary?(): GridSummary | null;
1024
+ /** Changes only presentation, then updates saved/share state. */
1025
+ setAggregateShowAs?(aggregate: string, mode: GridShowAs): Promise<void>;
1026
+ /** Loads the optional values part and returns numeric values paired with export number formats. */
1027
+ getDisplaySummary?(): Promise<GridSummaryDisplay | null>;
892
1028
  /** Grouped reporting grids (fixed or runtime). Keys name groups of any level. Collapse affects display; record query/selection/export scope remain intact. */
893
1029
  setGroupCollapsed?(key: string, collapsed: boolean): void;
894
1030
  getCollapsedGroups?(): string[];
@@ -929,8 +1065,8 @@ export interface DataGrid<Q extends AcceptedGridQuery = GridQuery, Row extends G
929
1065
  exportAs(format: string, options: Omit<GridExportOptions, "onProgress" | "maxRows"> & ExportFormatOptions): Promise<ExportFormatResult>;
930
1066
  /** Reporting runtime only. Complete bounded record snapshot; default maxRows is 1000, never silently truncates. */
931
1067
  materializeExport?(options: GridExportOptions): Promise<GridExportSnapshot<Q>>;
932
- /** Reporting runtime only. Passes the same bounded snapshot to onPrint; never prints viewport DOM. */
933
- print?(options: GridExportOptions): Promise<void>;
1068
+ /** Prints a bounded complete static snapshot, or passes it to onPrint. Default maxRows is 1000; never prints viewport DOM. */
1069
+ print(options: GridExportOptions): Promise<void>;
934
1070
  /** Details are opened for loaded records, by toolbar, double click or Ctrl/Command+Enter. */
935
1071
  openDetails(id: string): Promise<void>;
936
1072
  /** The current formatting rules: the view's, or the ones set since. */
@@ -13,6 +13,8 @@ export interface ExportMenuOptions {
13
13
  csv?: boolean;
14
14
  /** Offers the clipboard action. Defaults to true. */
15
15
  copy?: boolean;
16
+ /** Offers a grid's default static print action. Defaults to true for declared XLSX/PDF formats; hosts can override printing. */
17
+ print?: boolean;
16
18
  /** Values captured by native menu actions. Defaults to display. */
17
19
  values?: "raw" | "display";
18
20
  }
@@ -98,6 +100,10 @@ export interface ExportFormatContext {
98
100
  readonly fileName: string;
99
101
  /** The format's id. */
100
102
  readonly format: string;
103
+ /** True requests a captured metadata section when the writer supports it. Default false. */
104
+ readonly includeMetadata: boolean;
105
+ /** Reports a bounded, structured limitation without changing captured values. */
106
+ diagnostic(value: ExportDiagnostic): void;
101
107
  /** Reports written records (a nonnegative integer; other values are ignored); the Export menu shows them as progress. */
102
108
  progress(completed: number): void;
103
109
  }
@@ -113,19 +119,26 @@ export interface ExportFormat<C extends ExportCapture = ExportCapture> {
113
119
  readonly mime?: string;
114
120
  /** False omits this writer from the Export menu; exportAs still runs it. Default true. */
115
121
  readonly showInMenu?: boolean;
122
+ /** Default capture values for this format, used only when the caller does not choose raw/display explicitly. */
123
+ readonly values?: "raw" | "display";
116
124
  /** Returns the file: a Blob (a File names the download itself), or bytes typed with mime. */
117
125
  write(capture: C, context: ExportFormatContext): Blob | ArrayBuffer | ArrayBufferView | PromiseLike<Blob | ArrayBuffer | ArrayBufferView>;
118
126
  }
119
127
  export interface ExportProgress { readonly phase: "reading" | "generating" | "ready"; readonly completed: number; readonly total: number | null; }
128
+ /** A document writer's limitation, with optional stable source identities. */
129
+ export interface ExportDiagnostic { readonly code: string; readonly columnId?: string; readonly rowId?: string; }
120
130
  export interface ExportFormatOptions {
121
131
  signal?: AbortSignal;
122
132
  onProgress?: (progress: ExportProgress) => void;
133
+ onDiagnostic?: (diagnostic: ExportDiagnostic) => void;
134
+ /** Requests captured metadata; the built-in XLSX writer adds an About worksheet. Default false. */
135
+ includeMetadata?: boolean;
123
136
  /** Safety timeout for the writer, 1..2147483647 ms; overrides the grid's exportTimeoutMs (default 600000). */
124
137
  timeoutMs?: number;
125
138
  /** False returns the file without starting a browser download. Default true. */
126
139
  download?: boolean;
127
140
  }
128
- export interface ExportFormatResult { readonly blob: Blob; readonly fileName: string; readonly format: string; }
141
+ export interface ExportFormatResult { readonly blob: Blob; readonly fileName: string; readonly format: string; readonly diagnostics: readonly ExportDiagnostic[]; }
129
142
  export interface TreeExportOptions {
130
143
  /** "visible" (default): the rows the reader can see, in order. "selected": the loaded selected nodes in tree order, including collapsed ones.
131
144
  * "all": every node in the current sort order, the whole tree of an inline source and the loaded nodes of a lazy one. */
@@ -4,9 +4,11 @@ import type {
4
4
  } from "./protocol.js";
5
5
  import type {
6
6
  TreeGridOptions, HostOptions, Sources, ExpandPathOptions, NodeFilter, FilterOptions,
7
- InteractionOptions, DropPlacement, ExportFormat, ExportFormatOptions, ExportFormatResult, TreeExport, TreeExportOptions, LinkedView
7
+ InteractionOptions, DropPlacement, ExportFormat, ExportFormatContext, ExportDiagnostic, ExportFormatOptions, ExportFormatResult, TreeExport, TreeExportOptions, LinkedView
8
8
  } from "./hosts.js";
9
9
  import type { CanopyPlugin, CanopyPartDefinition } from "./plugins.js";
10
+ import type { UiApi } from "./ui.js";
11
+ export * from "./ui.js";
10
12
  export * from "./protocol.js";
11
13
  export * from "./hosts.js";
12
14
  export * from "./plugins.js";
@@ -117,7 +119,7 @@ export function registerPart(name: string, part: CanopyPartDefinition): void;
117
119
  */
118
120
  export function setNonce(nonce: string): void;
119
121
 
120
- declare const CanopyX: Readonly<{
122
+ declare const CanopyX: Readonly<UiApi & {
121
123
  protocol: typeof protocol;
122
124
  createTreeGrid: typeof createTreeGrid;
123
125
  configure: typeof configure;
@@ -75,6 +75,8 @@ export interface GridLiveState {
75
75
  }
76
76
 
77
77
  export interface GridPollOptions<Row extends GridRow = GridRow, Q extends AcceptedGridQuery = GridQuery> {
78
+ /** After a successful native refresh, including unchanged rows. Not called for cancelled or failed loads; useful for snapshot provenance beside the grid. */
79
+ onRefresh?: (result: GridLiveResult) => void;
78
80
  /** 250..86400000; defaults to the live pollMs. */
79
81
  intervalMs?: number;
80
82
  /** Poll at once instead of after the first interval. */