@evotecit/canopyx 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CanopyX.Html/Assets/canopyx-filter-editor.css +135 -0
- package/CanopyX.Html/Assets/canopyx-filter-editor.js +61 -0
- package/CanopyX.Html/Assets/canopyx-grid-module.mjs +1035 -0
- package/CanopyX.Html/Assets/canopyx-grid.css +554 -0
- package/CanopyX.Html/Assets/canopyx-grid.js +1033 -0
- package/CanopyX.Html/Assets/canopyx-interactive.css +351 -0
- package/CanopyX.Html/Assets/canopyx-interactive.js +664 -0
- package/CanopyX.Html/Assets/canopyx-labels-de.js +225 -0
- package/CanopyX.Html/Assets/canopyx-labels-es.js +225 -0
- package/CanopyX.Html/Assets/canopyx-labels-pl.js +225 -0
- package/CanopyX.Html/Assets/canopyx-module.mjs +665 -0
- package/CanopyX.Html/Assets/canopyx-reporting-module.mjs +1278 -0
- package/CanopyX.Html/Assets/canopyx-reporting.css +604 -0
- package/CanopyX.Html/Assets/canopyx-reporting.js +1276 -0
- package/CanopyX.Html/Assets/canopyx.css +325 -0
- package/CanopyX.Html/Assets/canopyx.js +534 -0
- package/JavaScript/grid.d.ts +591 -0
- package/JavaScript/hosts.d.ts +109 -0
- package/JavaScript/index.d.ts +85 -0
- package/JavaScript/locales/de.d.ts +6 -0
- package/JavaScript/locales/de.mjs +223 -0
- package/JavaScript/locales/es.d.ts +6 -0
- package/JavaScript/locales/es.mjs +223 -0
- package/JavaScript/locales/pl.d.ts +6 -0
- package/JavaScript/locales/pl.mjs +223 -0
- package/JavaScript/protocol.d.ts +229 -0
- package/LICENSE +21 -0
- package/README.md +476 -2
- package/README.nuget.md +75 -0
- package/package.json +61 -4
|
@@ -0,0 +1,591 @@
|
|
|
1
|
+
import CanopyX from "./index.js";
|
|
2
|
+
import type { TreeGrid } from "./index.js";
|
|
3
|
+
import type { CanopyColumn, CanopyLabels, Cell, CellValue, SortDirection, TimeZone } from "./protocol.js";
|
|
4
|
+
import type { HostOptions } from "./hosts.js";
|
|
5
|
+
export * from "./index.js";
|
|
6
|
+
|
|
7
|
+
/** A stable record identity and typed cells. Flat records have no tree fields. */
|
|
8
|
+
export interface GridRow { id: string; cells: Record<string, Cell>; tone?: string; className?: string; }
|
|
9
|
+
/** First match wins separately for the row and each condition-column cell; raw filter semantics apply. */
|
|
10
|
+
export type GridHighlightRule = GridFilter & { target?: "row" | "cell" } &
|
|
11
|
+
({ tone: string; className?: string } | { tone?: string; className: string });
|
|
12
|
+
/** Portable cell semantics, independent of DOM renderers and stylesheet rules. Datetime values retain the original ISO string and its explicit time zone and precision. */
|
|
13
|
+
export interface GridExportCell {
|
|
14
|
+
readonly value: CellValue;
|
|
15
|
+
readonly text: string;
|
|
16
|
+
readonly tone?: string;
|
|
17
|
+
readonly link?: { readonly target: string; readonly tooltip?: string };
|
|
18
|
+
/** Unsupported presentation must be rejected by strict adapters or explicitly accepted as text-only. */
|
|
19
|
+
readonly diagnostics?: readonly string[];
|
|
20
|
+
}
|
|
21
|
+
/** An immutable record projected onto the declared export columns. Group headings and summaries are not records. */
|
|
22
|
+
export interface GridExportRow {
|
|
23
|
+
readonly id: string; readonly cells: Readonly<Record<string, GridExportCell>>;
|
|
24
|
+
readonly tone?: string; readonly diagnostics?: readonly string[];
|
|
25
|
+
}
|
|
26
|
+
/** Captured column intent. Hosts map semantic tones and CSS pixel widths into their output format. */
|
|
27
|
+
export interface GridExportColumn {
|
|
28
|
+
readonly id: string; readonly title: string; readonly kind: "text" | "number" | "datetime";
|
|
29
|
+
/** Reporting runtime only. */
|
|
30
|
+
readonly width?: { readonly unit: "css-px"; readonly preferred: number; readonly minimum: number; readonly maximum?: number };
|
|
31
|
+
readonly wrap?: boolean; readonly alignment?: "left" | "right";
|
|
32
|
+
readonly presenter?: GridPresenter;
|
|
33
|
+
readonly diagnostics?: readonly string[];
|
|
34
|
+
}
|
|
35
|
+
export type GridColumn = Omit<CanopyColumn, "editable" | "width"> & {
|
|
36
|
+
editable?: false; wrap?: boolean;
|
|
37
|
+
/** Declarative presentation; explicit host renderers take precedence. */
|
|
38
|
+
presenter?: GridPresenter;
|
|
39
|
+
/** Include selected numeric values in the optional status bar. */
|
|
40
|
+
aggregatable?: boolean;
|
|
41
|
+
/** Record drawer section label. */
|
|
42
|
+
section?: string;
|
|
43
|
+
/** Preferred width; the column grows to its header and loaded content. Omit to use the content width. Saved user widths take precedence. */
|
|
44
|
+
width?: number;
|
|
45
|
+
/** Wire documents retain a numeric width and set this flag for initial content fitting. */
|
|
46
|
+
autoWidth?: boolean;
|
|
47
|
+
/** The width is hard: it neither grows nor shrinks. Requires width. */
|
|
48
|
+
fixed?: boolean;
|
|
49
|
+
minWidth?: number;
|
|
50
|
+
/** Widest width and the content measuring cap (default cap 420). */
|
|
51
|
+
maxWidth?: number;
|
|
52
|
+
/** Share of spare width (0..100), given before the identity column. */
|
|
53
|
+
flex?: number;
|
|
54
|
+
autoSize?: "content" | "header" | "none";
|
|
55
|
+
/** How the column gives way when narrow. Integers follow DataTables responsivePriority: 0-1 essential, 10000+ optional. */
|
|
56
|
+
priority?: GridColumnPriority;
|
|
57
|
+
/** Requested edge; null unpins. Omitted: the identity column pins left. */
|
|
58
|
+
pinned?: "left" | "right" | null;
|
|
59
|
+
/** Marks the identity column; defaults to the first column. */
|
|
60
|
+
rowHeader?: boolean;
|
|
61
|
+
/** Retain this column during responsive fitting; explicit user hiding still applies. */
|
|
62
|
+
alwaysVisible?: boolean;
|
|
63
|
+
};
|
|
64
|
+
export type GridColumnPriority = "essential" | "normal" | "optional" | number;
|
|
65
|
+
export interface GridSort { readonly column: string; readonly direction: SortDirection; }
|
|
66
|
+
/** Code-unit collation; natural digit runs never convert to floating-point numbers. */
|
|
67
|
+
export interface GridOrdering {
|
|
68
|
+
readonly text: "ordinal" | "foldedOrdinal" | "natural" | "foldedNatural";
|
|
69
|
+
/** At most 512 distinct values after selected folding; remaining values follow declared categories. */
|
|
70
|
+
readonly categories?: readonly string[];
|
|
71
|
+
}
|
|
72
|
+
/** Safe DOM presentations; raw values retain their search, ordering and export meanings. */
|
|
73
|
+
export type GridPresenter =
|
|
74
|
+
| { readonly kind: "link"; readonly hrefColumn?: string; readonly newWindow?: boolean }
|
|
75
|
+
| { readonly kind: "icon"; readonly glyph: string }
|
|
76
|
+
| { readonly kind: "progress"; readonly maximum: number; readonly thresholds?: readonly GridThreshold[] }
|
|
77
|
+
| { readonly kind: "boolean"; readonly inverted?: boolean }
|
|
78
|
+
| { readonly kind: "list"; readonly separator: string; readonly limit: number }
|
|
79
|
+
| { readonly kind: "longText"; readonly mono?: boolean }
|
|
80
|
+
| { readonly kind: "enum" | "state"; readonly tones?: Readonly<Record<string,string>>; /** Tones shown as plain muted text. */ readonly quietTones?: readonly string[] }
|
|
81
|
+
| { readonly kind: "change"; readonly deltaColumn: string; readonly higherIsGood?: boolean }
|
|
82
|
+
| { readonly kind: "statusStrip" | "missing" }
|
|
83
|
+
| ({ readonly kind: "sparklineBars" | "sparklineLine" } & GridHistoryPresentation)
|
|
84
|
+
| { readonly kind: "identifier"; readonly secondaryColumn?: string; readonly mono?: boolean }
|
|
85
|
+
| { readonly kind: "tags"; readonly separator: string; readonly limit?: 3 };
|
|
86
|
+
/** Ascending inclusive upper bounds; unmatched values use cell tones. */
|
|
87
|
+
export interface GridThreshold { readonly upperBound: number; readonly tone: string; }
|
|
88
|
+
/** Both shared scale bounds must be supplied together; otherwise each cell scales independently. */
|
|
89
|
+
export interface GridHistoryPresentation {
|
|
90
|
+
readonly minimum?: number; readonly scaleMaximum?: number; readonly thresholds?: readonly GridThreshold[];
|
|
91
|
+
readonly higherIsGood?: boolean; readonly mark?: "worst" | "last";
|
|
92
|
+
}
|
|
93
|
+
/** Include the reporting entry point when this optional capability set is present. */
|
|
94
|
+
export interface GridReporting {
|
|
95
|
+
/** Fixed first ordering key. Group headings and collapse never change record paging/counts/exports. */
|
|
96
|
+
readonly grouping?: GridSort;
|
|
97
|
+
/** At most 32 generic aggregates over raw full-query and full-group values. */
|
|
98
|
+
readonly aggregates?: readonly GridAggregate[];
|
|
99
|
+
/** Adds row checkboxes and explicit page/all-matching selection controls. Requires an enabled selection mode. */
|
|
100
|
+
readonly selectionControls?: boolean;
|
|
101
|
+
/** Session preferences by default; local storage requires an explicit stateKey and retains sensitive query settings. */
|
|
102
|
+
readonly viewStorage?: "session" | "local";
|
|
103
|
+
readonly columnReorder?: boolean;
|
|
104
|
+
readonly responsive?: boolean;
|
|
105
|
+
/** Pins are temporarily suspended to leave this many CSS pixels for the center; default 128, range 40..4096. */
|
|
106
|
+
readonly minimumCenterWidth?: number;
|
|
107
|
+
readonly layout?: Readonly<Record<string, GridColumnLayout>>;
|
|
108
|
+
readonly ordering?: Readonly<Record<string, GridOrdering>>;
|
|
109
|
+
/** Accepted for existing hosts: column menus offer Filter…, and a filter button appears only on a filtered column. */
|
|
110
|
+
readonly headerFilters?: boolean;
|
|
111
|
+
/** Offer a bounded nested AND/OR editor over the accepted query's filterGroup. */
|
|
112
|
+
readonly filterGroups?: boolean;
|
|
113
|
+
/** Full accepted-query values/counts. Hosted grids require an explicit source facet capability. */
|
|
114
|
+
readonly facetColumns?: readonly string[];
|
|
115
|
+
/** Declared column identities; an explicit custom renderer takes precedence. */
|
|
116
|
+
readonly presenters?: Readonly<Record<string, GridPresenter>>;
|
|
117
|
+
}
|
|
118
|
+
/** CSS pixel bounds and a weight from zero to 100 for unused viewport space. Manual sizing disables flex until reset/state restoration. */
|
|
119
|
+
export type GridColumnPin = "none" | "left" | "right";
|
|
120
|
+
export interface GridColumnLayout {
|
|
121
|
+
readonly minimum: number; readonly maximum: number; readonly flex?: number;
|
|
122
|
+
readonly pin?: GridColumnPin;
|
|
123
|
+
/** Smaller values remain visible longer; equal priorities hide from the end of current order. */
|
|
124
|
+
readonly priority?: number;
|
|
125
|
+
/** Retain unless explicitly hidden by the user. */
|
|
126
|
+
readonly alwaysVisible?: boolean;
|
|
127
|
+
}
|
|
128
|
+
/** Effective layout is distinct from saved intent; responsive fields retain query and explicit export meanings. */
|
|
129
|
+
export interface GridColumnPlacement {
|
|
130
|
+
readonly id: string; readonly requestedPin: GridColumnPin; readonly pin: GridColumnPin;
|
|
131
|
+
/** False whenever the column is out of view; hiddenReason says why. */
|
|
132
|
+
readonly visible: boolean;
|
|
133
|
+
/** null when shown; "user" when hidden by the reader or host, "priority" when it gave way to the width or a responsive
|
|
134
|
+
* policy, "phone" when the phone layout (640 px and below) hid a normal column. */
|
|
135
|
+
readonly hiddenReason: GridColumnHiddenReason | null;
|
|
136
|
+
/** True only for the reporting.responsive policy; kept for existing hosts. */
|
|
137
|
+
readonly responsiveHidden: boolean; readonly width: number;
|
|
138
|
+
}
|
|
139
|
+
export type GridColumnHiddenReason = "user" | "priority" | "phone";
|
|
140
|
+
/** Per-control toolbar switches; an absent switch keeps its control, and a control switched off is not built. */
|
|
141
|
+
export interface GridToolbarControls {
|
|
142
|
+
/** Filters menu. */
|
|
143
|
+
filters?: boolean;
|
|
144
|
+
/** Columns menu. */
|
|
145
|
+
columns?: boolean;
|
|
146
|
+
/** Saved views menu with Reset view. */
|
|
147
|
+
views?: boolean;
|
|
148
|
+
/** Export menu. */
|
|
149
|
+
export?: boolean;
|
|
150
|
+
/** More menu: host actions, Record details and Print. */
|
|
151
|
+
more?: boolean;
|
|
152
|
+
/** Result count shown with the query chips. */
|
|
153
|
+
count?: boolean;
|
|
154
|
+
}
|
|
155
|
+
/** Runtime switches add the search box; documents keep it in the view's search property. */
|
|
156
|
+
export interface GridToolbarOptions extends GridToolbarControls {
|
|
157
|
+
search?: boolean;
|
|
158
|
+
}
|
|
159
|
+
/** The reporting runtime's host slots in toolbar order; afterSearch follows start directly when there is no search box, and
|
|
160
|
+
* end starts the right-hand group before Export and the more menu. */
|
|
161
|
+
export type GridToolbarSlot = "start" | "afterSearch" | "afterViews" | "end";
|
|
162
|
+
/** A more-menu entry: a handler, or (reporting runtime) host content disclosed inside the menu. */
|
|
163
|
+
export type GridAction<Q extends AcceptedGridQuery = GridQuery> =
|
|
164
|
+
| { label: string; run: (event: { query: Q | null; signal: AbortSignal }) => void | PromiseLike<void>; render?: never }
|
|
165
|
+
/** render fills container on the entry's first open (and again after a render that threw); close() closes the menu and
|
|
166
|
+
* focuses its button; signal aborts when the grid is destroyed. */
|
|
167
|
+
| { label: string; render: (container: HTMLElement, context: { close(): void; signal: AbortSignal }) => void; run?: never };
|
|
168
|
+
export type GridFilter = {
|
|
169
|
+
readonly column: string;
|
|
170
|
+
readonly operator: "eq" | "ne" | "contains" | "startsWith" | "in" | "gt" | "ge" | "lt" | "le";
|
|
171
|
+
readonly values: readonly Exclude<CellValue, null>[];
|
|
172
|
+
} | { readonly column: string; readonly operator: "isNull" | "isNotNull"; readonly values: readonly []; };
|
|
173
|
+
|
|
174
|
+
/** A nonempty nested expression: at most eight levels, 64 groups and 64 total predicates including flat filters. */
|
|
175
|
+
export interface GridFilterGroup {
|
|
176
|
+
readonly operator: "and" | "or";
|
|
177
|
+
readonly filters: readonly GridFilter[];
|
|
178
|
+
readonly groups: readonly GridFilterGroup[];
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/** A frozen accepted query. Sorting/filtering cover the entire source before the requested window. */
|
|
182
|
+
export interface GridQuery {
|
|
183
|
+
readonly protocol: "canopyx/2";
|
|
184
|
+
readonly type: "gridQuery";
|
|
185
|
+
readonly view: string;
|
|
186
|
+
readonly revision?: string;
|
|
187
|
+
readonly offset: number;
|
|
188
|
+
readonly limit: number;
|
|
189
|
+
readonly search: string;
|
|
190
|
+
/** Absent preserves substring matching; words matches all words/quoted phrases across searchable cells. */
|
|
191
|
+
readonly searchMode?: "substring" | "words";
|
|
192
|
+
readonly sort: readonly GridSort[];
|
|
193
|
+
readonly filters: readonly GridFilter[];
|
|
194
|
+
/** Combined with search and flat filters using AND. */
|
|
195
|
+
readonly filterGroup?: GridFilterGroup;
|
|
196
|
+
}
|
|
197
|
+
/** Sequential host query. Tokens require their issuing revision; there is no random-access offset. */
|
|
198
|
+
export interface GridCursorQuery extends Omit<GridQuery, "type" | "offset"> {
|
|
199
|
+
readonly type: "gridCursorQuery";
|
|
200
|
+
readonly cursor?: string;
|
|
201
|
+
}
|
|
202
|
+
export type AcceptedGridQuery = GridQuery | GridCursorQuery;
|
|
203
|
+
export type GridQueryInput<Q extends AcceptedGridQuery = GridQuery> = Partial<Q>;
|
|
204
|
+
type GridCount<Q extends AcceptedGridQuery> = Q extends GridCursorQuery ? number | null : number;
|
|
205
|
+
|
|
206
|
+
interface GridDefinition<Q extends AcceptedGridQuery = GridQuery> {
|
|
207
|
+
protocol: "canopyx/2";
|
|
208
|
+
type: "grid";
|
|
209
|
+
id: string;
|
|
210
|
+
label: string;
|
|
211
|
+
columns: GridColumn[];
|
|
212
|
+
/** Fixed CSS pixel height (20..64), or content measurement. Fixed is the default writer behavior. */
|
|
213
|
+
rowHeight?: number | "auto";
|
|
214
|
+
/** Graphite spacing; an explicit rowHeight remains authoritative. */
|
|
215
|
+
density?: "compact" | "default" | "comfortable";
|
|
216
|
+
/** Subtle alternate-row backgrounds. Off by default. */
|
|
217
|
+
zebra?: boolean;
|
|
218
|
+
/** Host-owned plural noun, such as "servers". */
|
|
219
|
+
noun?: string;
|
|
220
|
+
/** Host-owned explanation for an empty source. */
|
|
221
|
+
emptyReason?: string;
|
|
222
|
+
/** Optional result and selected-record counts. */
|
|
223
|
+
statusBar?: boolean;
|
|
224
|
+
/** Per-control toolbar switches (the search box is the search property). */
|
|
225
|
+
toolbar?: GridToolbarControls;
|
|
226
|
+
/** A grid whose rows fit is as tall as its rows (default true). */
|
|
227
|
+
autoHeight?: boolean;
|
|
228
|
+
/** What a plain row click does; it never selects (default "none"). */
|
|
229
|
+
rowAction?: "none" | "details" | "link";
|
|
230
|
+
/** Draw a row tone as a bar at the row start (default false). */
|
|
231
|
+
rowAccents?: boolean;
|
|
232
|
+
/** Wire documents retain numeric rowHeight and enable measurement with this optional flag. */
|
|
233
|
+
autoRowHeight?: boolean;
|
|
234
|
+
/** Minimum and estimate for the rowHeight: "auto" API shorthand (20..64, default 28). */
|
|
235
|
+
estimatedRowHeight?: number;
|
|
236
|
+
/** At most 64 ordered rules; a tone or className is required on each rule. */
|
|
237
|
+
highlightRules?: readonly GridHighlightRule[];
|
|
238
|
+
pageSize: number;
|
|
239
|
+
/** Presentation only; pageSize remains the source fetch size. */
|
|
240
|
+
presentation?: "continuous" | "paged";
|
|
241
|
+
pageLength?: number;
|
|
242
|
+
selection: "none" | "single" | "multiple";
|
|
243
|
+
search: boolean;
|
|
244
|
+
/** Search-input debounce (0..5000). Absent uses 0 for inline and 300 for host sources. */
|
|
245
|
+
searchDelayMs?: number;
|
|
246
|
+
/** Unique declared IDs; absent searches every column, including hidden columns. */
|
|
247
|
+
searchColumns?: string[];
|
|
248
|
+
reporting?: GridReporting;
|
|
249
|
+
stateKey?: string;
|
|
250
|
+
timeZone?: TimeZone;
|
|
251
|
+
labels?: Partial<CanopyLabels>;
|
|
252
|
+
query?: Q;
|
|
253
|
+
}
|
|
254
|
+
export interface InlineGridView extends GridDefinition { source: { kind: "inline"; navigation?: "offset" }; rows: GridRow[]; }
|
|
255
|
+
export interface HostGridView extends GridDefinition { source: { kind: "host"; navigation?: "offset" }; rows?: never; }
|
|
256
|
+
export interface CursorGridView extends GridDefinition<GridCursorQuery> {
|
|
257
|
+
source: { kind: "host"; navigation: "cursor" };
|
|
258
|
+
presentation: "paged";
|
|
259
|
+
rows?: never;
|
|
260
|
+
}
|
|
261
|
+
export type GridView = InlineGridView | HostGridView | CursorGridView;
|
|
262
|
+
|
|
263
|
+
/** A complete requested window from one dataset revision, with full and matching counts. */
|
|
264
|
+
export interface GridPage {
|
|
265
|
+
protocol: "canopyx/2";
|
|
266
|
+
type: "gridPage";
|
|
267
|
+
view: string;
|
|
268
|
+
revision: string;
|
|
269
|
+
offset: number;
|
|
270
|
+
total: number;
|
|
271
|
+
matched: number;
|
|
272
|
+
items: GridRow[];
|
|
273
|
+
}
|
|
274
|
+
/** Hosts own data access, authorization and query execution; cancellation does not grant write authority. */
|
|
275
|
+
export interface GridFacetOptions { readonly search?: string; readonly limit?: number; readonly includeCurrentFilter?: boolean; readonly signal?: AbortSignal; }
|
|
276
|
+
/** Facet values/counts ignore the query window and sort; excluding the current column replaces its predicates by true. */
|
|
277
|
+
export interface GridFacetQuery<Q extends AcceptedGridQuery = AcceptedGridQuery> {
|
|
278
|
+
readonly protocol: "canopyx/2"; readonly type: "gridFacetQuery"; readonly query: Q & { readonly revision: string };
|
|
279
|
+
readonly column: string; readonly search: string; readonly limit: number; readonly includeCurrentFilter: boolean;
|
|
280
|
+
}
|
|
281
|
+
export interface GridFacetPage {
|
|
282
|
+
readonly protocol: "canopyx/2"; readonly type: "gridFacetPage"; readonly view: string; readonly revision: string;
|
|
283
|
+
readonly column: string; readonly search: string; readonly includeCurrentFilter: boolean;
|
|
284
|
+
readonly matched: number; readonly totalValues: number; readonly truncated: boolean;
|
|
285
|
+
readonly items: readonly { readonly value: CellValue; readonly count: number }[];
|
|
286
|
+
}
|
|
287
|
+
export interface GridFacetSource<Q extends AcceptedGridQuery = AcceptedGridQuery> {
|
|
288
|
+
facet?(request: GridFacetQuery<Q>, options: { signal: AbortSignal }): GridFacetPage | PromiseLike<GridFacetPage>;
|
|
289
|
+
}
|
|
290
|
+
export interface GridSource extends GridFacetSource<GridQuery> {
|
|
291
|
+
readonly navigation?: "offset";
|
|
292
|
+
query(query: GridQuery, options: { signal: AbortSignal }): GridPage | PromiseLike<GridPage>;
|
|
293
|
+
/** Complete-query metadata, echoing the normalized accepted request, revision and matched count. */
|
|
294
|
+
summary?(query: GridQuery & { readonly revision: string }, options: { signal: AbortSignal }): GridSummary | PromiseLike<GridSummary>;
|
|
295
|
+
}
|
|
296
|
+
export interface GridAggregate {
|
|
297
|
+
readonly id: string; readonly column: string; readonly label: string;
|
|
298
|
+
readonly operation: "count" | "sum" | "average" | "minimum" | "maximum";
|
|
299
|
+
}
|
|
300
|
+
export interface GridGroup {
|
|
301
|
+
readonly key: string; readonly value: CellValue; readonly offset: number; readonly count: number;
|
|
302
|
+
readonly aggregates: Readonly<Record<string, number | null>>;
|
|
303
|
+
/** Host-owned complete-group display values; rendered with column presenters, excluded from record queries and exports. */
|
|
304
|
+
readonly cells?: Readonly<Record<string, Cell>>;
|
|
305
|
+
}
|
|
306
|
+
export interface GridSummary {
|
|
307
|
+
readonly protocol: "canopyx/2"; readonly type: "gridSummary"; readonly view: string; readonly revision: string;
|
|
308
|
+
readonly query: GridQuery & { readonly revision: string }; readonly matched: number;
|
|
309
|
+
readonly groups: readonly GridGroup[]; readonly aggregates: Readonly<Record<string, number | null>>;
|
|
310
|
+
}
|
|
311
|
+
/** One complete visible page. Null counts remain unknown; ordinal positions do not grant random access. */
|
|
312
|
+
export interface GridCursorPage extends Omit<GridPage, "type" | "total" | "matched"> {
|
|
313
|
+
type: "gridCursorPage";
|
|
314
|
+
total: number | null;
|
|
315
|
+
matched: number | null;
|
|
316
|
+
nextCursor?: string;
|
|
317
|
+
previousCursor?: string;
|
|
318
|
+
}
|
|
319
|
+
export interface GridCursorSource extends GridFacetSource<GridCursorQuery> {
|
|
320
|
+
readonly navigation: "cursor";
|
|
321
|
+
query(query: GridCursorQuery, options: { signal: AbortSignal }): GridCursorPage | PromiseLike<GridCursorPage>;
|
|
322
|
+
}
|
|
323
|
+
/** Accepted presentation; indices are zero based, while the visible range is one based (0–0 when empty). */
|
|
324
|
+
export interface GridPaging<Q extends AcceptedGridQuery = GridQuery> {
|
|
325
|
+
readonly presentation: "continuous" | "paged";
|
|
326
|
+
readonly pageLength: number;
|
|
327
|
+
readonly navigation?: Q extends GridCursorQuery ? "cursor" : "offset";
|
|
328
|
+
readonly pageIndex: Q extends GridCursorQuery ? null : number;
|
|
329
|
+
readonly pageCount: Q extends GridCursorQuery ? null : number;
|
|
330
|
+
readonly first: number;
|
|
331
|
+
readonly last: number;
|
|
332
|
+
readonly matched: GridCount<Q>;
|
|
333
|
+
readonly total: GridCount<Q>;
|
|
334
|
+
readonly hasNext?: boolean;
|
|
335
|
+
readonly hasPrevious?: boolean;
|
|
336
|
+
}
|
|
337
|
+
export interface GridQueryEvent<Q extends AcceptedGridQuery = GridQuery> { query: Q; revision: string; total: GridCount<Q>; matched: GridCount<Q>; }
|
|
338
|
+
/** A bounded selection of stable IDs, or an ephemeral complete accepted query with explicit exclusions. */
|
|
339
|
+
export type GridSelection<Q extends AcceptedGridQuery = GridQuery> =
|
|
340
|
+
| { readonly kind: "ids"; readonly revision: string | null; readonly ids: readonly string[] }
|
|
341
|
+
| GridQuerySelection<Q>;
|
|
342
|
+
export interface GridQuerySelection<Q extends AcceptedGridQuery = GridQuery> {
|
|
343
|
+
readonly kind: "query";
|
|
344
|
+
readonly query: Q;
|
|
345
|
+
readonly revision: string;
|
|
346
|
+
readonly matched: GridCount<Q>;
|
|
347
|
+
readonly excludedIds: readonly string[];
|
|
348
|
+
}
|
|
349
|
+
/** Exports retain the accepted revision, query ordering, columns and selected IDs at invocation. */
|
|
350
|
+
export interface GridExportRequest<Q extends AcceptedGridQuery = GridQuery> {
|
|
351
|
+
/** Ordinary grids capture text only; the reporting runtime resolves semantic presentation and diagnostics. */
|
|
352
|
+
readonly presentation: "text" | "semantic";
|
|
353
|
+
readonly scope: "filtered" | "selected" | "all";
|
|
354
|
+
readonly query: Q;
|
|
355
|
+
readonly revision: string;
|
|
356
|
+
readonly total: GridCount<Q>;
|
|
357
|
+
readonly matched: GridCount<Q>;
|
|
358
|
+
readonly selection: readonly string[];
|
|
359
|
+
/** Exact captured export count, including selected-query exclusions; null means unknown. */
|
|
360
|
+
readonly recordCount: number | null;
|
|
361
|
+
/** All-matching selected exports keep these accepted criteria. Hosts validate them rather than treating an empty ID list as empty selection. */
|
|
362
|
+
readonly querySelection?: GridQuerySelection<Q>;
|
|
363
|
+
readonly columns: readonly GridExportColumn[];
|
|
364
|
+
readonly values: "raw" | "display";
|
|
365
|
+
readonly timeZone: TimeZone;
|
|
366
|
+
/** Reporting delivery captures the canonical locale and a safe suggested basename without a format extension. */
|
|
367
|
+
readonly locale?: string;
|
|
368
|
+
readonly fileName?: string;
|
|
369
|
+
}
|
|
370
|
+
/** Record counts refer to the complete captured export scope, including selected-query exclusions. */
|
|
371
|
+
export interface GridExportProgress {
|
|
372
|
+
readonly phase: "reading" | "generating" | "ready";
|
|
373
|
+
readonly completed: number;
|
|
374
|
+
readonly total: number | null;
|
|
375
|
+
}
|
|
376
|
+
export interface GridExportOptions {
|
|
377
|
+
scope: GridExportRequest["scope"];
|
|
378
|
+
/** Defaults to visible columns in their current order. */
|
|
379
|
+
columns?: string[];
|
|
380
|
+
values?: GridExportRequest["values"];
|
|
381
|
+
signal?: AbortSignal;
|
|
382
|
+
/** Client CSV defaults to 50000; clipboard to 10000. Larger results use a host hook. */
|
|
383
|
+
maxRows?: number;
|
|
384
|
+
/** Reporting runtime only. A safe basename up to 100 UTF-16 units; hosts append their format extension. */
|
|
385
|
+
fileName?: string;
|
|
386
|
+
/** Reporting runtime only. A browser-supported locale; display formatting is captured at invocation. */
|
|
387
|
+
locale?: string;
|
|
388
|
+
/** Reporting runtime only. Overrides the captured display zone without changing the view. */
|
|
389
|
+
timeZone?: TimeZone;
|
|
390
|
+
/** Reporting runtime only. Observational synchronous progress; a throwing callback aborts the operation. */
|
|
391
|
+
onProgress?: (progress: GridExportProgress) => void;
|
|
392
|
+
}
|
|
393
|
+
/** A complete bounded snapshot for a host renderer: at most 10000 records and 4 Mi UTF-16 units. */
|
|
394
|
+
export interface GridExportSnapshot<Q extends AcceptedGridQuery = GridQuery> {
|
|
395
|
+
readonly request: GridExportRequest<Q>;
|
|
396
|
+
readonly rows: readonly GridExportRow[];
|
|
397
|
+
}
|
|
398
|
+
export interface GridExport<Q extends AcceptedGridQuery = GridQuery> {
|
|
399
|
+
readonly request: GridExportRequest<Q>;
|
|
400
|
+
/** Each enumeration requests fresh serial windows from the captured revision, independently of the viewport. */
|
|
401
|
+
rows(options?: { signal?: AbortSignal }): AsyncIterable<GridExportRow>;
|
|
402
|
+
}
|
|
403
|
+
export interface GridCellContext {
|
|
404
|
+
column: string; index: number;
|
|
405
|
+
/** Aborts before replacement, recycling, failed rendering or destruction. */
|
|
406
|
+
readonly signal: AbortSignal;
|
|
407
|
+
/** Registers cleanup for this cell paint. Called once in reverse registration order. */
|
|
408
|
+
onDispose(cleanup: () => void): void;
|
|
409
|
+
}
|
|
410
|
+
/** Versioned view settings. Queries omit dataset revisions; restoration revalidates against the current source. */
|
|
411
|
+
export interface GridState<Q extends AcceptedGridQuery = GridQuery> {
|
|
412
|
+
version: 1;
|
|
413
|
+
view: string;
|
|
414
|
+
columns: { id: string; width: number; hidden: boolean; flex?: boolean; pin?: GridColumnPin; sized?: boolean; priority?: GridColumnPriority }[];
|
|
415
|
+
query: Q;
|
|
416
|
+
timeZone: TimeZone;
|
|
417
|
+
selection: string[];
|
|
418
|
+
scrollTop: number;
|
|
419
|
+
/** Reporting grouping only. At most 10000 bounded stable keys; omitted from shareable state. */
|
|
420
|
+
collapsedGroups?: string[];
|
|
421
|
+
/** Optional for compatibility with existing continuous snapshots; restored offsets clamp to current results. */
|
|
422
|
+
paging?: { pageLength: number; offset: number; allRows?: boolean };
|
|
423
|
+
}
|
|
424
|
+
/** Versioned, bounded preference envelope. Revisions/cursors belong to data, never durable settings. */
|
|
425
|
+
export type GridPreferenceQuery<Q extends AcceptedGridQuery = GridQuery> = Readonly<Omit<Q, "revision" | "cursor">> & {
|
|
426
|
+
readonly revision?: never;
|
|
427
|
+
readonly cursor?: never;
|
|
428
|
+
};
|
|
429
|
+
export type GridPreferenceState<Q extends AcceptedGridQuery = GridQuery> = Readonly<Omit<GridState<Q>, "columns" | "selection" | "paging" | "query">> & {
|
|
430
|
+
readonly query: GridPreferenceQuery<Q>;
|
|
431
|
+
readonly columns: readonly Readonly<GridState<Q>["columns"][number]>[];
|
|
432
|
+
readonly selection: readonly string[];
|
|
433
|
+
readonly paging?: Readonly<{ pageLength: number; offset: number; allRows?: boolean }>;
|
|
434
|
+
};
|
|
435
|
+
export interface GridViewSettings<Q extends AcceptedGridQuery = GridQuery> {
|
|
436
|
+
readonly version: 1;
|
|
437
|
+
readonly view: string;
|
|
438
|
+
readonly current?: GridPreferenceState<Q>;
|
|
439
|
+
readonly views: readonly { readonly name: string; readonly state: GridPreferenceState<Q> }[];
|
|
440
|
+
readonly defaultView?: string;
|
|
441
|
+
}
|
|
442
|
+
/** Hosts authenticate preference access and honor cancellation. Saves are serial/coalesced per grid instance. */
|
|
443
|
+
export interface GridViewStore<Q extends AcceptedGridQuery = GridQuery> {
|
|
444
|
+
load(event: { key: string; view: string; signal: AbortSignal }): GridViewSettings<Q> | null | PromiseLike<GridViewSettings<Q> | null>;
|
|
445
|
+
save(event: { key: string; view: string; settings: GridViewSettings<Q>; signal: AbortSignal }): void | PromiseLike<void>;
|
|
446
|
+
}
|
|
447
|
+
interface GridHostBehavior<Q extends AcceptedGridQuery = GridQuery> {
|
|
448
|
+
/** False hides the whole toolbar so a host can compose controls around the same grid controller; an object switches
|
|
449
|
+
* single controls off (overriding the view's toolbar switches). Switched-off controls are not built. */
|
|
450
|
+
toolbar?: boolean | GridToolbarOptions;
|
|
451
|
+
/** Overrides the view's search-input debounce (0..5000); Enter always applies immediately. */
|
|
452
|
+
searchDelayMs?: number;
|
|
453
|
+
source?: Q extends GridCursorQuery ? GridCursorSource : GridSource;
|
|
454
|
+
labels?: Partial<CanopyLabels>;
|
|
455
|
+
renderers?: Record<string, (row: GridRow, element: HTMLElement, context: GridCellContext) => boolean | void>;
|
|
456
|
+
cachePageLimit?: number;
|
|
457
|
+
requestTimeoutMs?: number;
|
|
458
|
+
onQuery?: (event: GridQueryEvent<Q>) => void;
|
|
459
|
+
onSelect?: (event: { ids: string[]; selection?: GridSelection<Q> }) => void;
|
|
460
|
+
onError?: (event: { error: Error }) => void;
|
|
461
|
+
onColumnResize?: (event: { column: string; width: number }) => void;
|
|
462
|
+
onColumnPin?: (event: { column: string; pin: GridColumnPin }) => void;
|
|
463
|
+
onState?: (event: { query: Q | null; state: GridState<Q> }) => void;
|
|
464
|
+
/** Hosts govern Office generation, authorization and delivery. CanopyX performs no domain write. */
|
|
465
|
+
onExport?: (event: { format: string; request: GridExportRequest<Q>; capture: GridExport<Q>; signal: AbortSignal;
|
|
466
|
+
/** Reporting runtime only. Monotonic record counts and phases; late calls after cancellation are ignored. */
|
|
467
|
+
reportProgress?: (phase: GridExportProgress["phase"], completed: number) => void }) => void | PromiseLike<void>;
|
|
468
|
+
/** Reporting runtime only. Render the complete snapshot through a host-owned renderer; honor cancellation before delivery. */
|
|
469
|
+
onPrint?: (event: { snapshot: GridExportSnapshot<Q>; signal: AbortSignal }) => void | PromiseLike<void>;
|
|
470
|
+
/** Hosts compose a drawer or details view and restore returnFocus when it closes. */
|
|
471
|
+
onDetails?: (event: { row: Readonly<GridRow>; query: Q; signal: AbortSignal; returnFocus: Element | null }) => void | PromiseLike<void>;
|
|
472
|
+
/** Adds Chart to the selection bar. The host owns chart generation. */
|
|
473
|
+
onChart?: (event: { query: Q | null; selection: GridSelection<Q>; signal: AbortSignal }) => void | PromiseLike<void>;
|
|
474
|
+
/** Host-owned secondary actions in the more menu. Content entries (render) need the reporting runtime: render fills the
|
|
475
|
+
* container on first open, focus moves to its first control, Escape folds it back, and close() closes the menu. */
|
|
476
|
+
actions?: readonly GridAction<Q>[];
|
|
477
|
+
/** Optional host-governed removal of the report's fixed grouping. */
|
|
478
|
+
onUngroup?: (event: { query: Q | null; signal: AbortSignal }) => void | PromiseLike<void>;
|
|
479
|
+
}
|
|
480
|
+
/** A host store binds to an explicit keyed reporting definition; ordinary grids have no store option. */
|
|
481
|
+
export type GridHostOptions<Q extends AcceptedGridQuery = GridQuery> = GridHostBehavior<Q> & (
|
|
482
|
+
{ viewStore?: never } | {
|
|
483
|
+
viewStore: GridViewStore<Q>;
|
|
484
|
+
view: (Q extends GridCursorQuery ? CursorGridView : InlineGridView | HostGridView) & { stateKey: string; reporting: GridReporting };
|
|
485
|
+
}
|
|
486
|
+
);
|
|
487
|
+
export type GridOptions = GridHostOptions & ({ view: InlineGridView } | { view: HostGridView; source: GridSource });
|
|
488
|
+
export type CursorGridOptions = GridHostOptions<GridCursorQuery> & { view: CursorGridView; source: GridCursorSource };
|
|
489
|
+
|
|
490
|
+
/** Presentation controller. Selection uses stable IDs independently of cached or visible rows. */
|
|
491
|
+
export interface DataGrid<Q extends AcceptedGridQuery = GridQuery> {
|
|
492
|
+
readonly element: HTMLElement;
|
|
493
|
+
readonly view: GridView;
|
|
494
|
+
readonly ready: Promise<Q>;
|
|
495
|
+
getQuery(): Q | null;
|
|
496
|
+
setQuery(query: GridQueryInput<Q>): Promise<Q>;
|
|
497
|
+
sort(sorts: readonly GridSort[]): Promise<Q>;
|
|
498
|
+
getPaging(): GridPaging<Q>;
|
|
499
|
+
/** Offset sources only. Cursor sources reject random page access. */
|
|
500
|
+
goToPage(index: number): Promise<Q>;
|
|
501
|
+
firstPage(): Promise<Q>;
|
|
502
|
+
previousPage(): Promise<Q>;
|
|
503
|
+
nextPage(): Promise<Q>;
|
|
504
|
+
setPageLength(length: number | "all"): Promise<Q>;
|
|
505
|
+
setColumnWidth(id: string, width: number): void;
|
|
506
|
+
/** Samples at most 200 cached accepted-query records and 512 display code units per value, capped at 420 CSS pixels or maxWidth, and sets a sticky user width. No fetching or viewport scraping. */
|
|
507
|
+
autoFitColumn(id: string): Readonly<{ width: number; sampled: number; scope: "loaded" }>;
|
|
508
|
+
/** Fits every declared column from the same bounded loaded sample, including hidden columns. */
|
|
509
|
+
autoFitColumns(): Readonly<Record<string, Readonly<{ width: number; sampled: number; scope: "loaded" }>>>;
|
|
510
|
+
setColumnPinned(id: string, pin: GridColumnPin): void;
|
|
511
|
+
/** Drops user widths so the columns return to automatic content sizing. */
|
|
512
|
+
autoSizeColumns(ids?: readonly string[]): void;
|
|
513
|
+
setColumnPriority(id: string, priority: GridColumnPriority): void;
|
|
514
|
+
/** Restores the declared order, visibility, widths and pins; keeps the query. */
|
|
515
|
+
resetColumns(): void;
|
|
516
|
+
/** Reporting runtime only: effective layout for every declared column, with the reason a column is out of view. */
|
|
517
|
+
getColumnLayout?(): readonly GridColumnPlacement[];
|
|
518
|
+
/** Reporting runtime only: the stable container of a toolbar slot for the grid's lifetime. Host children marked
|
|
519
|
+
* data-cx-slot move into their slot when the grid mounts and return to the host element on destroy. */
|
|
520
|
+
toolbarSlot?(name: GridToolbarSlot): HTMLElement;
|
|
521
|
+
/** Reporting runtime only: revisioned, bounded full-query aggregation. Never reads the viewport cache for counts. */
|
|
522
|
+
getFacets?(column: string, options?: GridFacetOptions): Promise<GridFacetPage>;
|
|
523
|
+
setColumnVisible(id: string, visible: boolean): void;
|
|
524
|
+
setColumnOrder(ids: string[]): void;
|
|
525
|
+
getState(): GridState<Q>;
|
|
526
|
+
setState(state: GridState<Q> | GridPreferenceState<Q>): Promise<Q>;
|
|
527
|
+
resetView(): Promise<Q>;
|
|
528
|
+
getSavedViews(): string[];
|
|
529
|
+
saveView(name: string): void;
|
|
530
|
+
applySavedView(name: string): Promise<Q>;
|
|
531
|
+
removeSavedView(name: string): void;
|
|
532
|
+
/** Reporting runtime only: bounded, versioned preferences including current and named view snapshots. */
|
|
533
|
+
getViewSettings?(): GridViewSettings<Q>;
|
|
534
|
+
getDefaultView?(): string | null;
|
|
535
|
+
setDefaultView?(name: string | null): void;
|
|
536
|
+
renameSavedView?(oldName: string, newName: string): void;
|
|
537
|
+
/** Reporting runtime only. Omits search, filters, selection, revision, cursor, page offset and scroll position. */
|
|
538
|
+
getShareState?(): GridPreferenceState<Q>;
|
|
539
|
+
/** Waits for serial/coalesced host saves; persistence failures leave the current grid usable and reject this call. */
|
|
540
|
+
flushViewSettings?(): Promise<void>;
|
|
541
|
+
/** Requires reporting selection controls: immutable IDs or accepted-query selection, never persisted in a saved view. */
|
|
542
|
+
getSelectionDescriptor?(): GridSelection<Q>;
|
|
543
|
+
/** Reporting summary capability only; null before acceptance. */
|
|
544
|
+
getSummary?(): GridSummary | null;
|
|
545
|
+
/** Flat grouping only. Collapse affects display; record query/selection/export scope remain intact. */
|
|
546
|
+
setGroupCollapsed?(key: string, collapsed: boolean): void;
|
|
547
|
+
getCollapsedGroups?(): string[];
|
|
548
|
+
/** Requires selection controls and multiple selection. Query/revision changes retire this scope; paging preserves it. */
|
|
549
|
+
selectAllMatching?(): void;
|
|
550
|
+
/** Selects/deselects the full accepted page, including records outside the mounted viewport. */
|
|
551
|
+
selectPage?(selected?: boolean, options?: { signal?: AbortSignal }): Promise<GridSelection<Q>>;
|
|
552
|
+
/** Selects/deselects a currently loaded accepted record. */
|
|
553
|
+
setRowSelected?(id: string, selected: boolean): void;
|
|
554
|
+
/** Offset positions span accepted pages; cursor positions stay on the accepted page. At most 10000 records/IDs/exclusions. */
|
|
555
|
+
selectRange?(start: number, end: number, options?: { selected?: boolean; additive?: boolean; signal?: AbortSignal }): Promise<GridSelection<Q>>;
|
|
556
|
+
setTimeZone(zone: TimeZone): void;
|
|
557
|
+
getTimeZone(): TimeZone;
|
|
558
|
+
/** Explicit identities only. Throws in query-selection mode; use getSelectionDescriptor instead. */
|
|
559
|
+
getSelection(): string[];
|
|
560
|
+
setSelection(ids: string[]): void;
|
|
561
|
+
clearSelection(): void;
|
|
562
|
+
prepareExport(options: GridExportOptions): GridExport<Q>;
|
|
563
|
+
toCsv(options: GridExportOptions): Promise<string>;
|
|
564
|
+
copy(options: GridExportOptions): Promise<string>;
|
|
565
|
+
exportToHost(format: string, options: GridExportOptions): Promise<void>;
|
|
566
|
+
/** Reporting runtime only. Complete bounded record snapshot; default maxRows is 1000, never silently truncates. */
|
|
567
|
+
materializeExport?(options: GridExportOptions): Promise<GridExportSnapshot<Q>>;
|
|
568
|
+
/** Reporting runtime only. Passes the same bounded snapshot to onPrint; never prints viewport DOM. */
|
|
569
|
+
print?(options: GridExportOptions): Promise<void>;
|
|
570
|
+
/** Details are opened for loaded records, by toolbar, double click or Ctrl/Command+Enter. */
|
|
571
|
+
openDetails(id: string): Promise<void>;
|
|
572
|
+
focus(): void;
|
|
573
|
+
/** Reveals a zero-based position in the accepted result without taking DOM focus from a host drawer. */
|
|
574
|
+
scrollToRow(index: number): Promise<void>;
|
|
575
|
+
retry(): Promise<Q | void>;
|
|
576
|
+
/** Repaints the accepted data without querying the source. */
|
|
577
|
+
refresh(): void;
|
|
578
|
+
/** Requests a fresh source revision with accepted filters and ordering, or initial definition criteria before acceptance. Traversal restarts at the first page. */
|
|
579
|
+
reload(): Promise<Q>;
|
|
580
|
+
destroy(): void;
|
|
581
|
+
}
|
|
582
|
+
/** Requires a browser DOM. The grid runtime also hosts both existing tree variants. */
|
|
583
|
+
export function createDataGrid(host: HTMLElement, options: GridOptions): DataGrid;
|
|
584
|
+
export function createDataGrid(host: HTMLElement, options: CursorGridOptions): DataGrid<GridCursorQuery>;
|
|
585
|
+
/** Registers options before either a tree or flat-grid fragment mounts. */
|
|
586
|
+
export function configure(viewId: string, options: HostOptions | GridHostOptions | GridHostOptions<GridCursorQuery>): () => void;
|
|
587
|
+
/** Mounts tree and flat-grid fragments below root. Narrow a controller before using view-specific methods. */
|
|
588
|
+
export function mount(root?: ParentNode): Array<TreeGrid | DataGrid<AcceptedGridQuery>>;
|
|
589
|
+
|
|
590
|
+
declare const gridRuntime: Omit<typeof CanopyX, "configure" | "mount"> & { createDataGrid: typeof createDataGrid; configure: typeof configure; mount: typeof mount };
|
|
591
|
+
export default gridRuntime;
|